random.h 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436
  1. static TLS struct {
  2. _hydro_attr_aligned_(16) uint8_t state[gimli_BLOCKBYTES];
  3. uint64_t counter;
  4. uint8_t initialized;
  5. uint8_t available;
  6. } hydro_random_context;
  7. #if defined(AVR) && !defined(__unix__)
  8. #include <Arduino.h>
  9. static bool
  10. hydro_random_rbit(unsigned int x)
  11. {
  12. size_t i;
  13. bool res = 0;
  14. for (i = 0; i < sizeof x; i++) {
  15. res ^= ((x >> i) & 1);
  16. }
  17. return res;
  18. }
  19. static int
  20. hydro_random_init(void)
  21. {
  22. const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
  23. hydro_hash_state st;
  24. uint16_t ebits = 0;
  25. uint16_t tc;
  26. bool a, b;
  27. cli();
  28. MCUSR = 0;
  29. WDTCSR |= _BV(WDCE) | _BV(WDE);
  30. WDTCSR = _BV(WDIE);
  31. sei();
  32. hydro_hash_init(&st, ctx, NULL);
  33. while (ebits < 256) {
  34. delay(1);
  35. tc = TCNT1;
  36. hydro_hash_update(&st, (const uint8_t *) &tc, sizeof tc);
  37. a = hydro_random_rbit(tc);
  38. delay(1);
  39. tc = TCNT1;
  40. b = hydro_random_rbit(tc);
  41. hydro_hash_update(&st, (const uint8_t *) &tc, sizeof tc);
  42. if (a == b) {
  43. continue;
  44. }
  45. hydro_hash_update(&st, (const uint8_t *) &b, sizeof b);
  46. ebits++;
  47. }
  48. cli();
  49. MCUSR = 0;
  50. WDTCSR |= _BV(WDCE) | _BV(WDE);
  51. WDTCSR = 0;
  52. sei();
  53. hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
  54. hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
  55. return 0;
  56. }
  57. ISR(WDT_vect) {}
  58. #elif (defined(ESP32) || defined(ESP8266)) && !defined(__unix__)
  59. // Important: RF *must* be activated on ESP board
  60. // https://techtutorialsx.com/2017/12/22/esp32-arduino-random-number-generation/
  61. #include <esp_system.h>
  62. static int
  63. hydro_random_init(void)
  64. {
  65. const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
  66. hydro_hash_state st;
  67. uint16_t ebits = 0;
  68. hydro_hash_init(&st, ctx, NULL);
  69. while (ebits < 256) {
  70. uint32_t r = esp_random();
  71. delay(10);
  72. hydro_hash_update(&st, (const uint32_t *) &r, sizeof r);
  73. ebits += 32;
  74. }
  75. hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
  76. hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
  77. return 0;
  78. }
  79. #elif (defined(NRF52832_XXAA) || defined(NRF52832_XXAB)) && !defined(__unix__)
  80. // Important: The SoftDevice *must* be activated to enable reading from the RNG
  81. // http://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.nrf52832.ps.v1.1%2Frng.html
  82. #include <nrf_soc.h>
  83. static int
  84. hydro_random_init(void)
  85. {
  86. const char ctx[hydro_hash_CONTEXTBYTES] = { 'h', 'y', 'd', 'r', 'o', 'P', 'R', 'G' };
  87. hydro_hash_state st;
  88. const uint8_t total_bytes = 32;
  89. uint8_t remaining_bytes = total_bytes;
  90. uint8_t available_bytes;
  91. uint8_t rand_buffer[32];
  92. hydro_hash_init(&st, ctx, NULL);
  93. for (;;) {
  94. if (sd_rand_application_bytes_available_get(&available_bytes) != NRF_SUCCESS) {
  95. return -1;
  96. }
  97. if (available_bytes > 0) {
  98. if (available_bytes > remaining_bytes) {
  99. available_bytes = remaining_bytes;
  100. }
  101. if (sd_rand_application_vector_get(rand_buffer, available_bytes) != NRF_SUCCESS) {
  102. return -1;
  103. }
  104. hydro_hash_update(&st, rand_buffer, total_bytes);
  105. remaining_bytes -= available_bytes;
  106. }
  107. if (remaining_bytes <= 0) {
  108. break;
  109. }
  110. delay(10);
  111. }
  112. hydro_hash_final(&st, hydro_random_context.state, sizeof hydro_random_context.state);
  113. hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
  114. return 0;
  115. }
  116. #elif defined(_WIN32)
  117. #include <windows.h>
  118. #define RtlGenRandom SystemFunction036
  119. #if defined(__cplusplus)
  120. extern "C"
  121. #endif
  122. BOOLEAN NTAPI
  123. RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
  124. #pragma comment(lib, "advapi32.lib")
  125. static int
  126. hydro_random_init(void)
  127. {
  128. if (!RtlGenRandom((PVOID) hydro_random_context.state,
  129. (ULONG) sizeof hydro_random_context.state)) {
  130. return -1;
  131. }
  132. hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
  133. return 0;
  134. }
  135. #elif defined(__wasi__)
  136. #include <unistd.h>
  137. static int
  138. hydro_random_init(void)
  139. {
  140. if (getentropy(hydro_random_context.state,
  141. sizeof hydro_random_context.state) != 0) {
  142. return -1;
  143. }
  144. hydro_random_context.counter = ~LOAD64_LE(hydro_random_context.state);
  145. return 0;
  146. }
  147. #elif defined(__unix__)
  148. #include <errno.h>
  149. #include <fcntl.h>
  150. #ifdef __linux__
  151. # include <poll.h>
  152. #endif
  153. #include <sys/types.h>
  154. #include <unistd.h>
  155. #ifdef __linux__
  156. static int
  157. hydro_random_block_on_dev_random(void)
  158. {
  159. struct pollfd pfd;
  160. int fd;
  161. int pret;
  162. fd = open("/dev/random", O_RDONLY);
  163. if (fd == -1) {
  164. return 0;
  165. }
  166. pfd.fd = fd;
  167. pfd.events = POLLIN;
  168. pfd.revents = 0;
  169. do {
  170. pret = poll(&pfd, 1, -1);
  171. } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
  172. if (pret != 1) {
  173. (void) close(fd);
  174. errno = EIO;
  175. return -1;
  176. }
  177. return close(fd);
  178. }
  179. #endif
  180. static ssize_t
  181. hydro_random_safe_read(const int fd, void *const buf_, size_t len)
  182. {
  183. unsigned char *buf = (unsigned char *) buf_;
  184. ssize_t readnb;
  185. do {
  186. while ((readnb = read(fd, buf, len)) < (ssize_t) 0 && (errno == EINTR || errno == EAGAIN))
  187. ;
  188. if (readnb < (ssize_t) 0) {
  189. return readnb;
  190. }
  191. if (readnb == (ssize_t) 0) {
  192. break;
  193. }
  194. len -= (size_t) readnb;
  195. buf += readnb;
  196. } while (len > (ssize_t) 0);
  197. return (ssize_t)(buf - (unsigned char *) buf_);
  198. }
  199. static int
  200. hydro_random_init(void)
  201. {
  202. uint8_t tmp[gimli_BLOCKBYTES + 8];
  203. int fd;
  204. int ret = -1;
  205. #ifdef __linux__
  206. if (hydro_random_block_on_dev_random() != 0) {
  207. return -1;
  208. }
  209. #endif
  210. do {
  211. fd = open("/dev/urandom", O_RDONLY);
  212. if (fd == -1 && errno != EINTR) {
  213. return -1;
  214. }
  215. } while (fd == -1);
  216. if (hydro_random_safe_read(fd, tmp, sizeof tmp) == (ssize_t) sizeof tmp) {
  217. memcpy(hydro_random_context.state, tmp, gimli_BLOCKBYTES);
  218. memcpy(&hydro_random_context.counter, tmp + gimli_BLOCKBYTES, 8);
  219. hydro_memzero(tmp, sizeof tmp);
  220. ret = 0;
  221. }
  222. ret |= close(fd);
  223. return ret;
  224. }
  225. #elif defined(TARGET_LIKE_MBED)
  226. #include <mbedtls/ctr_drbg.h>
  227. #include <mbedtls/entropy.h>
  228. #if defined(MBEDTLS_ENTROPY_C)
  229. static int
  230. hydro_random_init(void)
  231. {
  232. mbedtls_entropy_context entropy;
  233. uint16_t pos = 0;
  234. mbedtls_entropy_init(&entropy);
  235. // Pull data directly out of the entropy pool for the state, as it's small enough.
  236. if (mbedtls_entropy_func(&entropy, (uint8_t *) &hydro_random_context.counter,
  237. sizeof hydro_random_context.counter) != 0) {
  238. return -1;
  239. }
  240. // mbedtls_entropy_func can't provide more than MBEDTLS_ENTROPY_BLOCK_SIZE in one go.
  241. // This constant depends of mbedTLS configuration (whether the PRNG is backed by SHA256/SHA512
  242. // at this time) Therefore, if necessary, we get entropy multiple times.
  243. do {
  244. const uint8_t dataLeftToConsume = gimli_BLOCKBYTES - pos;
  245. const uint8_t currentChunkSize = (dataLeftToConsume > MBEDTLS_ENTROPY_BLOCK_SIZE)
  246. ? MBEDTLS_ENTROPY_BLOCK_SIZE
  247. : dataLeftToConsume;
  248. // Forces mbedTLS to fetch fresh entropy, then get some to feed libhydrogen.
  249. if (mbedtls_entropy_gather(&entropy) != 0 ||
  250. mbedtls_entropy_func(&entropy, &hydro_random_context.state[pos], currentChunkSize) != 0) {
  251. return -1;
  252. }
  253. pos += MBEDTLS_ENTROPY_BLOCK_SIZE;
  254. } while (pos < gimli_BLOCKBYTES);
  255. mbedtls_entropy_free(&entropy);
  256. return 0;
  257. }
  258. #else
  259. # error Need an entropy source
  260. #endif
  261. #else
  262. # error Unsupported platform
  263. #endif
  264. static void
  265. hydro_random_check_initialized(void)
  266. {
  267. if (hydro_random_context.initialized == 0) {
  268. if (hydro_random_init() != 0) {
  269. abort();
  270. }
  271. gimli_core_u8(hydro_random_context.state, 0);
  272. hydro_random_ratchet();
  273. hydro_random_context.initialized = 1;
  274. }
  275. }
  276. void
  277. hydro_random_ratchet(void)
  278. {
  279. mem_zero(hydro_random_context.state, gimli_RATE);
  280. STORE64_LE(hydro_random_context.state, hydro_random_context.counter);
  281. hydro_random_context.counter++;
  282. gimli_core_u8(hydro_random_context.state, 0);
  283. hydro_random_context.available = gimli_RATE;
  284. }
  285. uint32_t
  286. hydro_random_u32(void)
  287. {
  288. uint32_t v;
  289. hydro_random_check_initialized();
  290. if (hydro_random_context.available < 4) {
  291. hydro_random_ratchet();
  292. }
  293. memcpy(&v, &hydro_random_context.state[gimli_RATE - hydro_random_context.available], 4);
  294. hydro_random_context.available -= 4;
  295. return v;
  296. }
  297. uint32_t
  298. hydro_random_uniform(const uint32_t upper_bound)
  299. {
  300. uint32_t min;
  301. uint32_t r;
  302. if (upper_bound < 2U) {
  303. return 0;
  304. }
  305. min = (1U + ~upper_bound) % upper_bound; /* = 2**32 mod upper_bound */
  306. do {
  307. r = hydro_random_u32();
  308. } while (r < min);
  309. /* r is now clamped to a set whose size mod upper_bound == 0
  310. * the worst case (2**31+1) requires 2 attempts on average */
  311. return r % upper_bound;
  312. }
  313. void
  314. hydro_random_buf(void *out, size_t out_len)
  315. {
  316. uint8_t *p = (uint8_t *) out;
  317. size_t i;
  318. size_t leftover;
  319. hydro_random_check_initialized();
  320. for (i = 0; i < out_len / gimli_RATE; i++) {
  321. gimli_core_u8(hydro_random_context.state, 0);
  322. memcpy(p + i * gimli_RATE, hydro_random_context.state, gimli_RATE);
  323. }
  324. leftover = out_len % gimli_RATE;
  325. if (leftover != 0) {
  326. gimli_core_u8(hydro_random_context.state, 0);
  327. mem_cpy(p + i * gimli_RATE, hydro_random_context.state, leftover);
  328. }
  329. hydro_random_ratchet();
  330. }
  331. void
  332. hydro_random_buf_deterministic(void *out, size_t out_len,
  333. const uint8_t seed[hydro_random_SEEDBYTES])
  334. {
  335. static const uint8_t prefix[] = { 7, 'd', 'r', 'b', 'g', '2', '5', '6' };
  336. _hydro_attr_aligned_(16) uint8_t state[gimli_BLOCKBYTES];
  337. uint8_t * p = (uint8_t *) out;
  338. size_t i;
  339. size_t leftover;
  340. mem_zero(state, gimli_BLOCKBYTES);
  341. COMPILER_ASSERT(sizeof prefix + 8 <= gimli_RATE);
  342. memcpy(state, prefix, sizeof prefix);
  343. STORE64_LE(state + sizeof prefix, (uint64_t) out_len);
  344. gimli_core_u8(state, 1);
  345. COMPILER_ASSERT(hydro_random_SEEDBYTES == gimli_RATE * 2);
  346. mem_xor(state, seed, gimli_RATE);
  347. gimli_core_u8(state, 2);
  348. mem_xor(state, seed + gimli_RATE, gimli_RATE);
  349. gimli_core_u8(state, 2);
  350. for (i = 0; i < out_len / gimli_RATE; i++) {
  351. gimli_core_u8(state, 0);
  352. memcpy(p + i * gimli_RATE, state, gimli_RATE);
  353. }
  354. leftover = out_len % gimli_RATE;
  355. if (leftover != 0) {
  356. gimli_core_u8(state, 0);
  357. mem_cpy(p + i * gimli_RATE, state, leftover);
  358. }
  359. hydro_random_ratchet();
  360. }
  361. void
  362. hydro_random_reseed(void)
  363. {
  364. hydro_random_context.initialized = 0;
  365. hydro_random_check_initialized();
  366. }