aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTheodore Ts'o <tytso@mit.edu>2016-05-04 13:29:18 -0400
committerTheodore Ts'o <tytso@mit.edu>2016-07-03 00:58:01 -0400
commitc92e040d575a7389d72e7e6f25e2033bfb867f8b (patch)
tree688c89943d4c14e46d678c6540fc0658debdbef2
parent1e7f583af67be4ff091d0aeb863c649efd7a9112 (diff)
random: add backtracking protection to the CRNG
Signed-off-by: Theodore Ts'o <tytso@mit.edu>
-rw-r--r--drivers/char/random.c54
1 files changed, 49 insertions, 5 deletions
diff --git a/drivers/char/random.c b/drivers/char/random.c
index 2a30d9718a1b..783dee11cdc9 100644
--- a/drivers/char/random.c
+++ b/drivers/char/random.c
@@ -438,7 +438,8 @@ static int crng_init_cnt = 0;
438#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE) 438#define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
439static void _extract_crng(struct crng_state *crng, 439static void _extract_crng(struct crng_state *crng,
440 __u8 out[CHACHA20_BLOCK_SIZE]); 440 __u8 out[CHACHA20_BLOCK_SIZE]);
441static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]); 441static void _crng_backtrack_protect(struct crng_state *crng,
442 __u8 tmp[CHACHA20_BLOCK_SIZE], int used);
442static void process_random_ready_list(void); 443static void process_random_ready_list(void);
443 444
444/********************************************************************** 445/**********************************************************************
@@ -826,8 +827,11 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
826 num = extract_entropy(r, &buf, 32, 16, 0); 827 num = extract_entropy(r, &buf, 32, 16, 0);
827 if (num == 0) 828 if (num == 0)
828 return; 829 return;
829 } else 830 } else {
830 _extract_crng(&primary_crng, buf.block); 831 _extract_crng(&primary_crng, buf.block);
832 _crng_backtrack_protect(&primary_crng, buf.block,
833 CHACHA20_KEY_SIZE);
834 }
831 spin_lock_irqsave(&primary_crng.lock, flags); 835 spin_lock_irqsave(&primary_crng.lock, flags);
832 for (i = 0; i < 8; i++) { 836 for (i = 0; i < 8; i++) {
833 unsigned long rv; 837 unsigned long rv;
@@ -889,9 +893,46 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
889 _extract_crng(crng, out); 893 _extract_crng(crng, out);
890} 894}
891 895
896/*
897 * Use the leftover bytes from the CRNG block output (if there is
898 * enough) to mutate the CRNG key to provide backtracking protection.
899 */
900static void _crng_backtrack_protect(struct crng_state *crng,
901 __u8 tmp[CHACHA20_BLOCK_SIZE], int used)
902{
903 unsigned long flags;
904 __u32 *s, *d;
905 int i;
906
907 used = round_up(used, sizeof(__u32));
908 if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE) {
909 extract_crng(tmp);
910 used = 0;
911 }
912 spin_lock_irqsave(&crng->lock, flags);
913 s = (__u32 *) &tmp[used];
914 d = &crng->state[4];
915 for (i=0; i < 8; i++)
916 *d++ ^= *s++;
917 spin_unlock_irqrestore(&crng->lock, flags);
918}
919
920static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used)
921{
922 struct crng_state *crng = NULL;
923
924#ifdef CONFIG_NUMA
925 if (crng_node_pool)
926 crng = crng_node_pool[numa_node_id()];
927 if (crng == NULL)
928#endif
929 crng = &primary_crng;
930 _crng_backtrack_protect(crng, tmp, used);
931}
932
892static ssize_t extract_crng_user(void __user *buf, size_t nbytes) 933static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
893{ 934{
894 ssize_t ret = 0, i; 935 ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE;
895 __u8 tmp[CHACHA20_BLOCK_SIZE]; 936 __u8 tmp[CHACHA20_BLOCK_SIZE];
896 int large_request = (nbytes > 256); 937 int large_request = (nbytes > 256);
897 938
@@ -916,6 +957,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
916 buf += i; 957 buf += i;
917 ret += i; 958 ret += i;
918 } 959 }
960 crng_backtrack_protect(tmp, i);
919 961
920 /* Wipe data just written to memory */ 962 /* Wipe data just written to memory */
921 memzero_explicit(tmp, sizeof(tmp)); 963 memzero_explicit(tmp, sizeof(tmp));
@@ -1473,8 +1515,10 @@ void get_random_bytes(void *buf, int nbytes)
1473 if (nbytes > 0) { 1515 if (nbytes > 0) {
1474 extract_crng(tmp); 1516 extract_crng(tmp);
1475 memcpy(buf, tmp, nbytes); 1517 memcpy(buf, tmp, nbytes);
1476 memzero_explicit(tmp, nbytes); 1518 crng_backtrack_protect(tmp, nbytes);
1477 } 1519 } else
1520 crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE);
1521 memzero_explicit(tmp, sizeof(tmp));
1478} 1522}
1479EXPORT_SYMBOL(get_random_bytes); 1523EXPORT_SYMBOL(get_random_bytes);
1480 1524