123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109 |
- From a6d1adf3fed33218b5059d41128ab2b8b429d08c Mon Sep 17 00:00:00 2001
- From: Theodore Ts'o <tytso@mit.edu>
- Date: Wed, 4 May 2016 13:29:18 -0400
- Subject: [PATCH 21/32] random: add backtracking protection to the CRNG
- Signed-off-by: Theodore Ts'o <tytso@mit.edu>
- ---
- drivers/char/random.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-----
- 1 file changed, 49 insertions(+), 5 deletions(-)
- diff --git a/drivers/char/random.c b/drivers/char/random.c
- index 79b049e644f3..a1214c0fbaf3 100644
- --- a/drivers/char/random.c
- +++ b/drivers/char/random.c
- @@ -437,7 +437,8 @@ static int crng_init_cnt = 0;
- #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
- static void _extract_crng(struct crng_state *crng,
- __u8 out[CHACHA20_BLOCK_SIZE]);
- -static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]);
- +static void _crng_backtrack_protect(struct crng_state *crng,
- + __u8 tmp[CHACHA20_BLOCK_SIZE], int used);
- static void process_random_ready_list(void);
-
- /**********************************************************************
- @@ -828,8 +829,11 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
- num = extract_entropy(r, &buf, 32, 16, 0);
- if (num == 0)
- return;
- - } else
- + } else {
- _extract_crng(&primary_crng, buf.block);
- + _crng_backtrack_protect(&primary_crng, buf.block,
- + CHACHA20_KEY_SIZE);
- + }
- spin_lock_irqsave(&primary_crng.lock, flags);
- for (i = 0; i < 8; i++) {
- unsigned long rv;
- @@ -891,9 +895,46 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
- _extract_crng(crng, out);
- }
-
- +/*
- + * Use the leftover bytes from the CRNG block output (if there is
- + * enough) to mutate the CRNG key to provide backtracking protection.
- + */
- +static void _crng_backtrack_protect(struct crng_state *crng,
- + __u8 tmp[CHACHA20_BLOCK_SIZE], int used)
- +{
- + unsigned long flags;
- + __u32 *s, *d;
- + int i;
- +
- + used = round_up(used, sizeof(__u32));
- + if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE) {
- + extract_crng(tmp);
- + used = 0;
- + }
- + spin_lock_irqsave(&crng->lock, flags);
- + s = (__u32 *) &tmp[used];
- + d = &crng->state[4];
- + for (i=0; i < 8; i++)
- + *d++ ^= *s++;
- + spin_unlock_irqrestore(&crng->lock, flags);
- +}
- +
- +static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used)
- +{
- + struct crng_state *crng = NULL;
- +
- +#ifdef CONFIG_NUMA
- + if (crng_node_pool)
- + crng = crng_node_pool[numa_node_id()];
- + if (crng == NULL)
- +#endif
- + crng = &primary_crng;
- + _crng_backtrack_protect(crng, tmp, used);
- +}
- +
- static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
- {
- - ssize_t ret = 0, i;
- + ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE;
- __u8 tmp[CHACHA20_BLOCK_SIZE];
- int large_request = (nbytes > 256);
-
- @@ -918,6 +959,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
- buf += i;
- ret += i;
- }
- + crng_backtrack_protect(tmp, i);
-
- /* Wipe data just written to memory */
- memzero_explicit(tmp, sizeof(tmp));
- @@ -1479,8 +1521,10 @@ void get_random_bytes(void *buf, int nbytes)
- if (nbytes > 0) {
- extract_crng(tmp);
- memcpy(buf, tmp, nbytes);
- - memzero_explicit(tmp, nbytes);
- - }
- + crng_backtrack_protect(tmp, nbytes);
- + } else
- + crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE);
- + memzero_explicit(tmp, sizeof(tmp));
- }
- EXPORT_SYMBOL(get_random_bytes);
-
- --
- 2.16.4
|