aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJason A. Donenfeld <[email protected]>2022-02-08 12:18:33 +0100
committerJason A. Donenfeld <[email protected]>2022-02-21 16:48:06 +0100
commit28f425e573e906a4c15f8392cc2b1561ef448595 (patch)
treeac7278f90cfaf51412ac5639f09c57c77448ae72
parent7c2fe2b32bf76441ff5b7a425b384e5f75aa530a (diff)
random: use RDSEED instead of RDRAND in entropy extraction
When /dev/random was directly connected with entropy extraction, without any expansion stage, extract_buf() was called for every 10 bytes of data read from /dev/random. For that reason, RDRAND was used rather than RDSEED. At the same time, crng_reseed() was still only called every 5 minutes, so there RDSEED made sense. Those olden days were also a time when the entropy collector did not use a cryptographic hash function, which meant most bets were off in terms of real preimage resistance. For that reason too it didn't matter _that_ much whether RDSEED was mixed in before or after entropy extraction; both choices were sort of bad. But now we have a cryptographic hash function at work, and with that we get real preimage resistance. We also now only call extract_entropy() every 5 minutes, rather than every 10 bytes. This allows us to do two important things. First, we can switch to using RDSEED in extract_entropy(), as Dominik suggested. Second, we can ensure that RDSEED input always goes into the cryptographic hash function with other things before being used directly. This eliminates a category of attacks in which the CPU knows the current state of the crng and knows that we're going to xor RDSEED into it, and so it computes a malicious RDSEED. By going through our hash function, it would require the CPU to compute a preimage on the fly, which isn't going to happen. Cc: Theodore Ts'o <[email protected]> Reviewed-by: Eric Biggers <[email protected]> Reviewed-by: Dominik Brodowski <[email protected]> Suggested-by: Dominik Brodowski <[email protected]> Signed-off-by: Jason A. Donenfeld <[email protected]>
-rw-r--r--drivers/char/random.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 79cf577e5086..41f42d887513 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -727,13 +727,8 @@ static void crng_reseed(struct crng_state *crng)
CHACHA_KEY_SIZE);
}
spin_lock_irqsave(&crng->lock, flags);
- for (i = 0; i < 8; i++) {
- unsigned long rv;
- if (!arch_get_random_seed_long(&rv) &&
- !arch_get_random_long(&rv))
- rv = random_get_entropy();
- crng->state[i + 4] ^= buf.key[i] ^ rv;
- }
+ for (i = 0; i < 8; i++)
+ crng->state[i + 4] ^= buf.key[i];
memzero_explicit(&buf, sizeof(buf));
WRITE_ONCE(crng->init_time, jiffies);
spin_unlock_irqrestore(&crng->lock, flags);
@@ -1054,16 +1049,17 @@ static void extract_entropy(void *buf, size_t nbytes)
unsigned long flags;
u8 seed[BLAKE2S_HASH_SIZE], next_key[BLAKE2S_HASH_SIZE];
struct {
- unsigned long rdrand[32 / sizeof(long)];
+ unsigned long rdseed[32 / sizeof(long)];
size_t counter;
} block;
size_t i;
trace_extract_entropy(nbytes, input_pool.entropy_count);
- for (i = 0; i < ARRAY_SIZE(block.rdrand); ++i) {
- if (!arch_get_random_long(&block.rdrand[i]))
- block.rdrand[i] = random_get_entropy();
+ for (i = 0; i < ARRAY_SIZE(block.rdseed); ++i) {
+ if (!arch_get_random_seed_long(&block.rdseed[i]) &&
+ !arch_get_random_long(&block.rdseed[i]))
+ block.rdseed[i] = random_get_entropy();
}
spin_lock_irqsave(&input_pool.lock, flags);
@@ -1071,7 +1067,7 @@ static void extract_entropy(void *buf, size_t nbytes)
/* seed = HASHPRF(last_key, entropy_input) */
blake2s_final(&input_pool.hash, seed);
- /* next_key = HASHPRF(seed, RDRAND || 0) */
+ /* next_key = HASHPRF(seed, RDSEED || 0) */
block.counter = 0;
blake2s(next_key, (u8 *)&block, seed, sizeof(next_key), sizeof(block), sizeof(seed));
blake2s_init_key(&input_pool.hash, BLAKE2S_HASH_SIZE, next_key, sizeof(next_key));
@@ -1081,7 +1077,7 @@ static void extract_entropy(void *buf, size_t nbytes)
while (nbytes) {
i = min_t(size_t, nbytes, BLAKE2S_HASH_SIZE);
- /* output = HASHPRF(seed, RDRAND || ++counter) */
+ /* output = HASHPRF(seed, RDSEED || ++counter) */
++block.counter;
blake2s(buf, (u8 *)&block, seed, i, sizeof(block), sizeof(seed));
nbytes -= i;