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) ; }