2022-04-01 07:43:28

by Jason A. Donenfeld

[permalink] [raw]
Subject: [PATCH v2] random: mix build-time latent entropy into pool at init

Prior, the "input_pool_data" array needed no real initialization, and so
it was easy to mark it with __latent_entropy to populate it during
compile-time. In switching to using a hash function, this required us to
specifically initialize it to some specific state, which means we
dropped the __latent_entropy attribute. An unfortunate side effect was
this meant the pool was no longer seeded using compile-time random data.
In order to bring this back, we declare an array in rand_initialize()
with __latent_entropy and call mix_pool_bytes() on that at init, which
accomplishes the same thing as before. We make this __initconst, so that
it doesn't take up space at runtime after init.

Fixes: 6e8ec2552c7d ("random: use computational hash for entropy extraction")
Cc: Dominik Brodowski <[email protected]>
Cc: Theodore Ts'o <[email protected]>
Signed-off-by: Jason A. Donenfeld <[email protected]>
---
Changes v1->v2:
- Use __initconst.

drivers/char/random.c | 5 +++++
1 file changed, 5 insertions(+)

diff --git a/drivers/char/random.c b/drivers/char/random.c
index 40107f8b9e9e..1d8242969751 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -975,6 +975,11 @@ int __init rand_initialize(void)
bool arch_init = true;
unsigned long rv;

+#if defined(LATENT_ENTROPY_PLUGIN)
+ static const u8 compiletime_seed[BLAKE2S_BLOCK_SIZE] __initconst __latent_entropy;
+ _mix_pool_bytes(compiletime_seed, sizeof(compiletime_seed));
+#endif
+
for (i = 0; i < BLAKE2S_BLOCK_SIZE; i += sizeof(rv)) {
if (!arch_get_random_seed_long_early(&rv) &&
!arch_get_random_long_early(&rv)) {
--
2.35.1


2022-04-02 15:11:12

by Sandy Harris

[permalink] [raw]
Subject: Re: [PATCH v2] random: mix build-time latent entropy into pool at init

On Fri, Apr 1, 2022 at 11:16 PM Jason A. Donenfeld <[email protected]> wrote:

> Prior, the "input_pool_data" array needed no real initialization, and so
> it was easy to mark it with __latent_entropy to populate it during
> compile-time.

As I see it, that was the correct approach.

> In switching to using a hash function, this required us to
> specifically initialize it to some specific state,

Hash functions do not require that. Any such function must
work correctly with a new input block and a more-or-less
random state from hashing previous blocks.

In general, except perhaps at boot time, I do not think
any of the hopefully-random data structures -- input
pool, hash context or chacha context -- should ever be
set to any specific state. Update them only with += or
^= and preferably not with constants.

What requires a fixed initialisation is your decision to
eliminate the input pool & just collect entropy in a hash
context. In effect you are reducing the driver to a
Yarrow-like design, which I think is an error.

Yarrow is a good design, but it has limitations; in particular
the Yarrow paper says the cryptographic strength is limited
to the size of the hash context, 160 bits for their SHA-1 &
512 for our Blake.

512 bits is more than enough for nearly all use cases, but
we may have some where it is not. How many random bits
are needed to generate a 4k-bit PGP key?

Will some users try to generate one-time pads from /dev/random?
The OTP security proof requires truly random data as long as the
message; with anything short of that the proof fails & you get
a stream cipher.

Patches will follow, but likely not soon; I'm busy with
other things.

2022-04-05 03:07:23

by Eric Biggers

[permalink] [raw]
Subject: Re: [PATCH v2] random: mix build-time latent entropy into pool at init

On Sat, Apr 02, 2022 at 12:44:42PM +0800, Sandy Harris wrote:
> Yarrow is a good design, but it has limitations; in particular
> the Yarrow paper says the cryptographic strength is limited
> to the size of the hash context, 160 bits for their SHA-1 &
> 512 for our Blake.
>
> 512 bits is more than enough for nearly all use cases, but
> we may have some where it is not. How many random bits
> are needed to generate a 4k-bit PGP key?
>
> Will some users try to generate one-time pads from /dev/random?
> The OTP security proof requires truly random data as long as the
> message; with anything short of that the proof fails & you get
> a stream cipher.

All the data from /dev/{u,}random is generated by ChaCha20, which is a 256-bit
stream cipher. We don't target, or need to target, more than 256-bit security.
So the entropy pool itself doesn't need to be more than 256 bits, provided that
it is implemented properly using a cryptographic hash function, which it now is.

- Eric