[<prev] [next>] [<thread-prev] [day] [month] [year] [list]
Message-ID: <CACXcFmnFiH6zD=rQXjzyUOa8+DcnOoTETUxA=a=xB3A=MmGO0Q@mail.gmail.com>
Date: Thu, 7 Apr 2022 20:08:49 +0800
From: Sandy Harris <sandyinchina@...il.com>
To: "Jason A. Donenfeld" <Jason@...c4.com>
Cc: LKML <linux-kernel@...r.kernel.org>,
Linux Crypto Mailing List <linux-crypto@...r.kernel.org>,
Linus Torvalds <torvalds@...ux-foundation.org>,
"Theodore Ts'o" <tytso@....edu>,
Dominik Brodowski <linux@...inikbrodowski.net>
Subject: Re: [PATCH] random: opportunistically initialize on /dev/urandom reads
Does this help?
I have some code I'm not yet ready to submit as patches. Here's some
of it that could be used to initialise the pool (& I think also the
counter for chacha). The paper linked in the comments suggests that
adding a bit reversal would improve diffusion, but I have not done
that yet.
/**************************************************************************
* Load a 64-bit word with data from whatever source we have
*
* arch_get_random_long()
* hardware RNG
* emulated HWRNG in a VM
*
* When there are two sources, alternate.
*
* If you have no better source, or if one fails,
* or if the argument 'fast' is set, then fall back
* to random_get_entropy().
*
* Also use random_get_entropy() sometimes even
* if we have a good source, to avoid trusting
* the source completely
***************************************************************************/
static int load_count = 0;
static spinlock_t source_lock;
static unsigned long source_value __latent_entropy ;
#define rotl64(x,n) ((x>>(n)) | (x<<(n)))
static int get_hw_long(unsigned long *x)
{
int ret ;
unsigned s = sizeof(unsigned long) ;
ret = get_random_bytes_arch((u8 *) x, s) ;
return (ret == s) ? 1 : 0 ;
}
/* This should be a Mersenne number, (2^x)-1 */
#define MIX_MASK 15
#define GOT_A IS_ENABLED(CONFIG_ARCH_RANDOM)
#define GOT_H IS_ENABLED(CONFIG_HW_RANDOM)
static unsigned long get_64(int fast)
{
int ret = 0 ;
unsigned long x, flags ;
if (!fast && (GOT_A||GOT_H) && (load_count&MIX_MASK)) {
if (GOT_A && GOT_H) {
if (load_count & 1)
ret = arch_get_random_long(&x) ;
else ret = get_hw_long(&x) ;
/*
* if the chosen source failed
* then try the other
*/
if (!ret)
if (load_count & 1)
ret = get_hw_long(&x) ;
else ret = arch_get_random_long(&x) ;
}
if (GOT_A && !GOT_H)
ret = arch_get_random_long(&x) ;
if (GOT_H && !GOT_A)
ret = get_hw_long(&x) ;
}
/*
* fast is nonzero, so not trying expensive methods
*
* or no source configured, neither GOT_A nor GOT_H set
* or configured one(s) failed, ret is still zero
*
* or it is just time for a different source
* (load_count&MIX_MASK) == 0
*/
if (!ret)
x = random_get_entropy() ;
/*
* use 19-bit rotation, based on
* https://eprint.iacr.org/2021/523.pdf
*/
spin_lock_irqsave(&source_lock, flags);
source_value = rotl64(source_value, 19) ^ x ;
load_count++ ;
spin_unlock_irqrestore(&source_lock, flags);
memzero_explicit(x, sizeof(x)) ;
return(source_value) ;
}
Powered by blists - more mailing lists