havege.c 8.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. /**
  2. * \brief HAVEGE: HArdware Volatile Entropy Gathering and Expansion
  3. *
  4. * Copyright The Mbed TLS Contributors
  5. * SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later
  6. */
  7. /*
  8. * The HAVEGE RNG was designed by Andre Seznec in 2002.
  9. *
  10. * http://www.irisa.fr/caps/projects/hipsor/publi.php
  11. *
  12. * Contact: seznec(at)irisa_dot_fr - orocheco(at)irisa_dot_fr
  13. */
  14. #include "common.h"
  15. #if defined(MBEDTLS_HAVEGE_C)
  16. #include "mbedtls/havege.h"
  17. #include "mbedtls/timing.h"
  18. #include "mbedtls/platform_util.h"
  19. #include <stdint.h>
  20. #include <string.h>
  21. /* ------------------------------------------------------------------------
  22. * On average, one iteration accesses two 8-word blocks in the havege WALK
  23. * table, and generates 16 words in the RES array.
  24. *
  25. * The data read in the WALK table is updated and permuted after each use.
  26. * The result of the hardware clock counter read is used for this update.
  27. *
  28. * 25 conditional tests are present. The conditional tests are grouped in
  29. * two nested groups of 12 conditional tests and 1 test that controls the
  30. * permutation; on average, there should be 6 tests executed and 3 of them
  31. * should be mispredicted.
  32. * ------------------------------------------------------------------------
  33. */
  34. #define SWAP(X, Y) { uint32_t *T = (X); (X) = (Y); (Y) = T; }
  35. #define TST1_ENTER if (PTEST & 1) { PTEST ^= 3; PTEST >>= 1;
  36. #define TST2_ENTER if (PTEST & 1) { PTEST ^= 3; PTEST >>= 1;
  37. #define TST1_LEAVE U1++; }
  38. #define TST2_LEAVE U2++; }
  39. #define ONE_ITERATION \
  40. \
  41. PTEST = PT1 >> 20; \
  42. \
  43. TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
  44. TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
  45. TST1_ENTER TST1_ENTER TST1_ENTER TST1_ENTER \
  46. \
  47. TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
  48. TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
  49. TST1_LEAVE TST1_LEAVE TST1_LEAVE TST1_LEAVE \
  50. \
  51. PTX = (PT1 >> 18) & 7; \
  52. PT1 &= 0x1FFF; \
  53. PT2 &= 0x1FFF; \
  54. CLK = (uint32_t) mbedtls_timing_hardclock(); \
  55. \
  56. i = 0; \
  57. A = &WALK[PT1]; RES[i++] ^= *A; \
  58. B = &WALK[PT2]; RES[i++] ^= *B; \
  59. C = &WALK[PT1 ^ 1]; RES[i++] ^= *C; \
  60. D = &WALK[PT2 ^ 4]; RES[i++] ^= *D; \
  61. \
  62. IN = (*A >> (1)) ^ (*A << (31)) ^ CLK; \
  63. *A = (*B >> (2)) ^ (*B << (30)) ^ CLK; \
  64. *B = IN ^ U1; \
  65. *C = (*C >> (3)) ^ (*C << (29)) ^ CLK; \
  66. *D = (*D >> (4)) ^ (*D << (28)) ^ CLK; \
  67. \
  68. A = &WALK[PT1 ^ 2]; RES[i++] ^= *A; \
  69. B = &WALK[PT2 ^ 2]; RES[i++] ^= *B; \
  70. C = &WALK[PT1 ^ 3]; RES[i++] ^= *C; \
  71. D = &WALK[PT2 ^ 6]; RES[i++] ^= *D; \
  72. \
  73. if (PTEST & 1) SWAP(A, C); \
  74. \
  75. IN = (*A >> (5)) ^ (*A << (27)) ^ CLK; \
  76. *A = (*B >> (6)) ^ (*B << (26)) ^ CLK; \
  77. *B = IN; CLK = (uint32_t) mbedtls_timing_hardclock(); \
  78. *C = (*C >> (7)) ^ (*C << (25)) ^ CLK; \
  79. *D = (*D >> (8)) ^ (*D << (24)) ^ CLK; \
  80. \
  81. A = &WALK[PT1 ^ 4]; \
  82. B = &WALK[PT2 ^ 1]; \
  83. \
  84. PTEST = PT2 >> 1; \
  85. \
  86. PT2 = (RES[(i - 8) ^ PTY] ^ WALK[PT2 ^ PTY ^ 7]); \
  87. PT2 = ((PT2 & 0x1FFF) & (~8)) ^ ((PT1 ^ 8) & 0x8); \
  88. PTY = (PT2 >> 10) & 7; \
  89. \
  90. TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
  91. TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
  92. TST2_ENTER TST2_ENTER TST2_ENTER TST2_ENTER \
  93. \
  94. TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
  95. TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
  96. TST2_LEAVE TST2_LEAVE TST2_LEAVE TST2_LEAVE \
  97. \
  98. C = &WALK[PT1 ^ 5]; \
  99. D = &WALK[PT2 ^ 5]; \
  100. \
  101. RES[i++] ^= *A; \
  102. RES[i++] ^= *B; \
  103. RES[i++] ^= *C; \
  104. RES[i++] ^= *D; \
  105. \
  106. IN = (*A >> (9)) ^ (*A << (23)) ^ CLK; \
  107. *A = (*B >> (10)) ^ (*B << (22)) ^ CLK; \
  108. *B = IN ^ U2; \
  109. *C = (*C >> (11)) ^ (*C << (21)) ^ CLK; \
  110. *D = (*D >> (12)) ^ (*D << (20)) ^ CLK; \
  111. \
  112. A = &WALK[PT1 ^ 6]; RES[i++] ^= *A; \
  113. B = &WALK[PT2 ^ 3]; RES[i++] ^= *B; \
  114. C = &WALK[PT1 ^ 7]; RES[i++] ^= *C; \
  115. D = &WALK[PT2 ^ 7]; RES[i++] ^= *D; \
  116. \
  117. IN = (*A >> (13)) ^ (*A << (19)) ^ CLK; \
  118. *A = (*B >> (14)) ^ (*B << (18)) ^ CLK; \
  119. *B = IN; \
  120. *C = (*C >> (15)) ^ (*C << (17)) ^ CLK; \
  121. *D = (*D >> (16)) ^ (*D << (16)) ^ CLK; \
  122. \
  123. PT1 = (RES[(i - 8) ^ PTX] ^ \
  124. WALK[PT1 ^ PTX ^ 7]) & (~1); \
  125. PT1 ^= (PT2 ^ 0x10) & 0x10; \
  126. \
  127. for (n++, i = 0; i < 16; i++) \
  128. hs->pool[n % MBEDTLS_HAVEGE_COLLECT_SIZE] ^= RES[i];
  129. /*
  130. * Entropy gathering function
  131. */
  132. static void havege_fill(mbedtls_havege_state *hs)
  133. {
  134. size_t n = 0;
  135. size_t i;
  136. uint32_t U1, U2, *A, *B, *C, *D;
  137. uint32_t PT1, PT2, *WALK, RES[16];
  138. uint32_t PTX, PTY, CLK, PTEST, IN;
  139. WALK = hs->WALK;
  140. PT1 = hs->PT1;
  141. PT2 = hs->PT2;
  142. PTX = U1 = 0;
  143. PTY = U2 = 0;
  144. (void) PTX;
  145. memset(RES, 0, sizeof(RES));
  146. while (n < MBEDTLS_HAVEGE_COLLECT_SIZE * 4) {
  147. ONE_ITERATION
  148. ONE_ITERATION
  149. ONE_ITERATION
  150. ONE_ITERATION
  151. }
  152. hs->PT1 = PT1;
  153. hs->PT2 = PT2;
  154. hs->offset[0] = 0;
  155. hs->offset[1] = MBEDTLS_HAVEGE_COLLECT_SIZE / 2;
  156. }
  157. /*
  158. * HAVEGE initialization
  159. */
  160. void mbedtls_havege_init(mbedtls_havege_state *hs)
  161. {
  162. memset(hs, 0, sizeof(mbedtls_havege_state));
  163. havege_fill(hs);
  164. }
  165. void mbedtls_havege_free(mbedtls_havege_state *hs)
  166. {
  167. if (hs == NULL) {
  168. return;
  169. }
  170. mbedtls_platform_zeroize(hs, sizeof(mbedtls_havege_state));
  171. }
  172. /*
  173. * HAVEGE rand function
  174. */
  175. int mbedtls_havege_random(void *p_rng, unsigned char *buf, size_t len)
  176. {
  177. uint32_t val;
  178. size_t use_len;
  179. mbedtls_havege_state *hs = (mbedtls_havege_state *) p_rng;
  180. unsigned char *p = buf;
  181. while (len > 0) {
  182. use_len = len;
  183. if (use_len > sizeof(val)) {
  184. use_len = sizeof(val);
  185. }
  186. if (hs->offset[1] >= MBEDTLS_HAVEGE_COLLECT_SIZE) {
  187. havege_fill(hs);
  188. }
  189. val = hs->pool[hs->offset[0]++];
  190. val ^= hs->pool[hs->offset[1]++];
  191. memcpy(p, &val, use_len);
  192. len -= use_len;
  193. p += use_len;
  194. }
  195. return 0;
  196. }
  197. #endif /* MBEDTLS_HAVEGE_C */