0021-random-add-backtracking-protection-to-the-CRNG.patch 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. From a6d1adf3fed33218b5059d41128ab2b8b429d08c Mon Sep 17 00:00:00 2001
  2. From: Theodore Ts'o <tytso@mit.edu>
  3. Date: Wed, 4 May 2016 13:29:18 -0400
  4. Subject: [PATCH 21/32] random: add backtracking protection to the CRNG
  5. Signed-off-by: Theodore Ts'o <tytso@mit.edu>
  6. ---
  7. drivers/char/random.c | 54 ++++++++++++++++++++++++++++++++++++++++++++++-----
  8. 1 file changed, 49 insertions(+), 5 deletions(-)
  9. diff --git a/drivers/char/random.c b/drivers/char/random.c
  10. index 79b049e644f3..a1214c0fbaf3 100644
  11. --- a/drivers/char/random.c
  12. +++ b/drivers/char/random.c
  13. @@ -437,7 +437,8 @@ static int crng_init_cnt = 0;
  14. #define CRNG_INIT_CNT_THRESH (2*CHACHA20_KEY_SIZE)
  15. static void _extract_crng(struct crng_state *crng,
  16. __u8 out[CHACHA20_BLOCK_SIZE]);
  17. -static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE]);
  18. +static void _crng_backtrack_protect(struct crng_state *crng,
  19. + __u8 tmp[CHACHA20_BLOCK_SIZE], int used);
  20. static void process_random_ready_list(void);
  21. /**********************************************************************
  22. @@ -828,8 +829,11 @@ static void crng_reseed(struct crng_state *crng, struct entropy_store *r)
  23. num = extract_entropy(r, &buf, 32, 16, 0);
  24. if (num == 0)
  25. return;
  26. - } else
  27. + } else {
  28. _extract_crng(&primary_crng, buf.block);
  29. + _crng_backtrack_protect(&primary_crng, buf.block,
  30. + CHACHA20_KEY_SIZE);
  31. + }
  32. spin_lock_irqsave(&primary_crng.lock, flags);
  33. for (i = 0; i < 8; i++) {
  34. unsigned long rv;
  35. @@ -891,9 +895,46 @@ static void extract_crng(__u8 out[CHACHA20_BLOCK_SIZE])
  36. _extract_crng(crng, out);
  37. }
  38. +/*
  39. + * Use the leftover bytes from the CRNG block output (if there is
  40. + * enough) to mutate the CRNG key to provide backtracking protection.
  41. + */
  42. +static void _crng_backtrack_protect(struct crng_state *crng,
  43. + __u8 tmp[CHACHA20_BLOCK_SIZE], int used)
  44. +{
  45. + unsigned long flags;
  46. + __u32 *s, *d;
  47. + int i;
  48. +
  49. + used = round_up(used, sizeof(__u32));
  50. + if (used + CHACHA20_KEY_SIZE > CHACHA20_BLOCK_SIZE) {
  51. + extract_crng(tmp);
  52. + used = 0;
  53. + }
  54. + spin_lock_irqsave(&crng->lock, flags);
  55. + s = (__u32 *) &tmp[used];
  56. + d = &crng->state[4];
  57. + for (i=0; i < 8; i++)
  58. + *d++ ^= *s++;
  59. + spin_unlock_irqrestore(&crng->lock, flags);
  60. +}
  61. +
  62. +static void crng_backtrack_protect(__u8 tmp[CHACHA20_BLOCK_SIZE], int used)
  63. +{
  64. + struct crng_state *crng = NULL;
  65. +
  66. +#ifdef CONFIG_NUMA
  67. + if (crng_node_pool)
  68. + crng = crng_node_pool[numa_node_id()];
  69. + if (crng == NULL)
  70. +#endif
  71. + crng = &primary_crng;
  72. + _crng_backtrack_protect(crng, tmp, used);
  73. +}
  74. +
  75. static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
  76. {
  77. - ssize_t ret = 0, i;
  78. + ssize_t ret = 0, i = CHACHA20_BLOCK_SIZE;
  79. __u8 tmp[CHACHA20_BLOCK_SIZE];
  80. int large_request = (nbytes > 256);
  81. @@ -918,6 +959,7 @@ static ssize_t extract_crng_user(void __user *buf, size_t nbytes)
  82. buf += i;
  83. ret += i;
  84. }
  85. + crng_backtrack_protect(tmp, i);
  86. /* Wipe data just written to memory */
  87. memzero_explicit(tmp, sizeof(tmp));
  88. @@ -1479,8 +1521,10 @@ void get_random_bytes(void *buf, int nbytes)
  89. if (nbytes > 0) {
  90. extract_crng(tmp);
  91. memcpy(buf, tmp, nbytes);
  92. - memzero_explicit(tmp, nbytes);
  93. - }
  94. + crng_backtrack_protect(tmp, nbytes);
  95. + } else
  96. + crng_backtrack_protect(tmp, CHACHA20_BLOCK_SIZE);
  97. + memzero_explicit(tmp, sizeof(tmp));
  98. }
  99. EXPORT_SYMBOL(get_random_bytes);
  100. --
  101. 2.16.4