random.h 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241
  1. static uint8_t hydro_random_key[hydro_stream_chacha20_KEYBYTES];
  2. static uint8_t hydro_random_nonce[hydro_stream_chacha20_NONCEBYTES];
  3. static uint8_t hydro_random_initialized;
  4. #if defined(AVR) && !defined(__unix__)
  5. #include <Arduino.h>
  6. static bool hydro_random_rbit(unsigned int x)
  7. {
  8. size_t i;
  9. bool res = 0;
  10. for (i = 0; i < sizeof x; i++) {
  11. res ^= ((x >> i) & 1);
  12. }
  13. return res;
  14. }
  15. static int hydro_random_init(void)
  16. {
  17. const uint8_t hydrokey[hydro_hash128_KEYBYTES] = { 'h', 'y', 'd', 'r', 'o',
  18. 'g', 'e', 'n', ' ', 'k', 'e', 'y', 's', 'e', 'e', 'd' };
  19. hydro_hash128_state st;
  20. uint16_t ebits = 0;
  21. uint16_t tc;
  22. bool a, b;
  23. cli();
  24. MCUSR = 0;
  25. WDTCSR |= _BV(WDCE) | _BV(WDE);
  26. WDTCSR = _BV(WDIE);
  27. sei();
  28. COMPILER_ASSERT(hydro_hash128_KEYBYTES >= hydro_hash128_CONTEXTBYTES);
  29. hydro_hash128_init(&st, (const char *)hydrokey, hydrokey);
  30. while (ebits < 256) {
  31. delay(1);
  32. tc = TCNT1;
  33. hydro_hash128_update(&st, (const uint8_t *)&tc, sizeof tc);
  34. a = hydro_random_rbit(tc);
  35. delay(1);
  36. tc = TCNT1;
  37. b = hydro_random_rbit(tc);
  38. hydro_hash128_update(&st, (const uint8_t *)&tc, sizeof tc);
  39. if (a == b) {
  40. continue;
  41. }
  42. hydro_hash128_update(&st, (const uint8_t *)&b, sizeof b);
  43. ebits++;
  44. }
  45. cli();
  46. MCUSR = 0;
  47. WDTCSR |= _BV(WDCE) | _BV(WDE);
  48. WDTCSR = 0;
  49. sei();
  50. COMPILER_ASSERT(hydro_stream_chacha20_KEYBYTES == hydro_hash128_BYTES * 2);
  51. hydro_hash128_final(&st, hydro_random_key);
  52. memcpy(hydro_random_key + hydro_hash128_BYTES, hydro_random_key,
  53. hydro_hash128_BYTES);
  54. hydro_random_initialized = 1;
  55. return 0;
  56. }
  57. ISR(WDT_vect)
  58. {
  59. }
  60. #elif defined(_WIN32)
  61. #include <windows.h>
  62. #define RtlGenRandom SystemFunction036
  63. #if defined(__cplusplus)
  64. extern "C"
  65. #endif
  66. BOOLEAN NTAPI
  67. RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
  68. #pragma comment(lib, "advapi32.lib")
  69. static int hydro_random_init(void)
  70. {
  71. if (!RtlGenRandom(
  72. (PVOID)hydro_random_key, (ULONG)sizeof hydro_random_key)) {
  73. return -1;
  74. }
  75. hydro_random_initialized = 1;
  76. return 0;
  77. }
  78. #elif defined(__unix__)
  79. #include <errno.h>
  80. #include <fcntl.h>
  81. #ifdef __linux__
  82. #include <poll.h>
  83. #endif
  84. #include <sys/types.h>
  85. #include <unistd.h>
  86. #ifdef __linux__
  87. static int hydro_random_block_on_dev_random(void)
  88. {
  89. struct pollfd pfd;
  90. int fd;
  91. int pret;
  92. fd = open("/dev/random", O_RDONLY);
  93. if (fd == -1) {
  94. return 0;
  95. }
  96. pfd.fd = fd;
  97. pfd.events = POLLIN;
  98. pfd.revents = 0;
  99. do {
  100. pret = poll(&pfd, 1, -1);
  101. } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
  102. if (pret != 1) {
  103. (void)close(fd);
  104. errno = EIO;
  105. return -1;
  106. }
  107. return close(fd);
  108. }
  109. #endif
  110. static ssize_t hydro_random_safe_read(
  111. const int fd, void *const buf_, size_t len)
  112. {
  113. unsigned char *buf = (unsigned char *)buf_;
  114. ssize_t readnb;
  115. do {
  116. while ((readnb = read(fd, buf, len)) < (ssize_t)0 &&
  117. (errno == EINTR || errno == EAGAIN))
  118. ;
  119. if (readnb < (ssize_t)0) {
  120. return readnb;
  121. }
  122. if (readnb == (ssize_t)0) {
  123. break;
  124. }
  125. len -= (size_t)readnb;
  126. buf += readnb;
  127. } while (len > (ssize_t)0);
  128. return (ssize_t)(buf - (unsigned char *)buf_);
  129. }
  130. static int hydro_random_init(void)
  131. {
  132. int fd;
  133. int ret = -1;
  134. #ifdef __linux__
  135. if (hydro_random_block_on_dev_random() != 0) {
  136. return -1;
  137. }
  138. #endif
  139. do {
  140. fd = open("/dev/urandom", O_RDONLY);
  141. if (fd == -1 && errno != EINTR) {
  142. return -1;
  143. }
  144. } while (fd == -1);
  145. if (hydro_random_safe_read(fd, hydro_random_key, sizeof hydro_random_key) ==
  146. (ssize_t)sizeof hydro_random_key) {
  147. ret = 0;
  148. hydro_random_initialized = 1;
  149. }
  150. ret |= close(fd);
  151. return ret;
  152. }
  153. #else
  154. #error Unsupported platform
  155. #endif
  156. static void hydro_random_check_initialized(void)
  157. {
  158. if (hydro_random_initialized == 0 && hydro_random_init() != 0) {
  159. abort();
  160. }
  161. }
  162. uint32_t randombytes_random(void)
  163. {
  164. uint32_t v;
  165. hydro_random_check_initialized();
  166. if (hydro_random_nonce[0] == 0x0) {
  167. hydro_stream_chacha20_xor(hydro_random_key, hydro_random_key,
  168. sizeof hydro_random_key, hydro_random_nonce, hydro_random_key);
  169. }
  170. hydro_stream_chacha20(
  171. (uint8_t *)&v, sizeof v, hydro_random_nonce, hydro_random_key);
  172. hydro_increment(hydro_random_nonce, sizeof hydro_random_nonce);
  173. return v;
  174. }
  175. uint32_t randombytes_uniform(const uint32_t upper_bound)
  176. {
  177. uint32_t min;
  178. uint32_t r;
  179. if (upper_bound < 2U) {
  180. return 0;
  181. }
  182. min = (1U + ~upper_bound) % upper_bound;
  183. do {
  184. r = randombytes_random();
  185. } while (r < min);
  186. return r % upper_bound;
  187. }
  188. void randombytes_buf(void *buf, size_t len)
  189. {
  190. uint8_t *p = (uint8_t *)buf;
  191. size_t i;
  192. uint32_t v;
  193. for (i = (size_t)0U; i < len; i += sizeof v) {
  194. v = randombytes_random();
  195. memcpy(p + i, &v, sizeof v);
  196. }
  197. for (; i < len; i++) {
  198. p[i] = (uint8_t)randombytes_random();
  199. }
  200. }
  201. void randombytes_buf_deterministic(
  202. void *buf, size_t len, const uint8_t seed[randombytes_SEEDBYTES])
  203. {
  204. COMPILER_ASSERT(randombytes_SEEDBYTES == hydro_stream_chacha20_KEYBYTES);
  205. hydro_stream_chacha20((uint8_t *)buf, len, zero, seed);
  206. }