lkml.org 
[lkml]   [2022]   [May]   [27]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 5.10 064/163] random: use RDSEED instead of RDRAND in entropy extraction
    Date
    From: "Jason A. Donenfeld" <Jason@zx2c4.com>

    commit 28f425e573e906a4c15f8392cc2b1561ef448595 upstream.

    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 <tytso@mit.edu>
    Reviewed-by: Eric Biggers <ebiggers@google.com>
    Reviewed-by: Dominik Brodowski <linux@dominikbrodowski.net>
    Suggested-by: Dominik Brodowski <linux@dominikbrodowski.net>
    Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
    Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
    ---
    drivers/char/random.c | 22 +++++++++-------------
    1 file changed, 9 insertions(+), 13 deletions(-)

    --- a/drivers/char/random.c
    +++ b/drivers/char/random.c
    @@ -727,13 +727,8 @@ static void crng_reseed(struct crng_stat
    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, s
    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, s
    /* 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, s

    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;

    \
     
     \ /
      Last update: 2022-05-27 14:02    [W:4.193 / U:0.336 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site