random.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147
  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 "random/avr.h"
  9. #elif (defined(ESP32) || defined(ESP8266)) && !defined(__unix__)
  10. # include "random/esp32.h"
  11. #elif defined(PARTICLE) && defined(PLATFORM_ID) && PLATFORM_ID > 2 && !defined(__unix__)
  12. # include "random/particle.h"
  13. #elif (defined(NRF52832_XXAA) || defined(NRF52832_XXAB)) && !defined(__unix__)
  14. # include "random/nrf52832.h"
  15. #elif defined(_WIN32)
  16. # include "random/windows.h"
  17. #elif defined(__wasi__)
  18. # include "random/wasi.h"
  19. #elif defined(__unix__)
  20. # include "random/unix.h"
  21. #elif defined(TARGET_LIKE_MBED)
  22. # include "random/mbed.h"
  23. #elif defined(RIOT_VERSION)
  24. # include "random/riot.h"
  25. #elif defined(STM32F4)
  26. # include "random/stm32.h"
  27. #elif defined(__RTTHREAD__)
  28. # include "random/rtthread.h"
  29. #else
  30. # error Unsupported platform
  31. #endif
  32. static void
  33. hydro_random_ensure_initialized(void)
  34. {
  35. if (hydro_random_context.initialized == 0) {
  36. if (hydro_random_init() != 0) {
  37. abort();
  38. }
  39. gimli_core_u8(hydro_random_context.state, 0);
  40. hydro_random_ratchet();
  41. hydro_random_context.initialized = 1;
  42. }
  43. }
  44. void
  45. hydro_random_ratchet(void)
  46. {
  47. mem_zero(hydro_random_context.state, gimli_RATE);
  48. STORE64_LE(hydro_random_context.state, hydro_random_context.counter);
  49. hydro_random_context.counter++;
  50. gimli_core_u8(hydro_random_context.state, 0);
  51. hydro_random_context.available = gimli_RATE;
  52. }
  53. uint32_t
  54. hydro_random_u32(void)
  55. {
  56. uint32_t v;
  57. hydro_random_ensure_initialized();
  58. if (hydro_random_context.available < 4) {
  59. hydro_random_ratchet();
  60. }
  61. memcpy(&v, &hydro_random_context.state[gimli_RATE - hydro_random_context.available], 4);
  62. hydro_random_context.available -= 4;
  63. return v;
  64. }
  65. uint32_t
  66. hydro_random_uniform(const uint32_t upper_bound)
  67. {
  68. uint32_t min;
  69. uint32_t r;
  70. if (upper_bound < 2U) {
  71. return 0;
  72. }
  73. min = (1U + ~upper_bound) % upper_bound; /* = 2**32 mod upper_bound */
  74. do {
  75. r = hydro_random_u32();
  76. } while (r < min);
  77. /* r is now clamped to a set whose size mod upper_bound == 0
  78. * the worst case (2**31+1) requires 2 attempts on average */
  79. return r % upper_bound;
  80. }
  81. void
  82. hydro_random_buf(void *out, size_t out_len)
  83. {
  84. uint8_t *p = (uint8_t *) out;
  85. size_t i;
  86. size_t leftover;
  87. hydro_random_ensure_initialized();
  88. for (i = 0; i < out_len / gimli_RATE; i++) {
  89. gimli_core_u8(hydro_random_context.state, 0);
  90. memcpy(p + i * gimli_RATE, hydro_random_context.state, gimli_RATE);
  91. }
  92. leftover = out_len % gimli_RATE;
  93. if (leftover != 0) {
  94. gimli_core_u8(hydro_random_context.state, 0);
  95. mem_cpy(p + i * gimli_RATE, hydro_random_context.state, leftover);
  96. }
  97. hydro_random_ratchet();
  98. }
  99. void
  100. hydro_random_buf_deterministic(void *out, size_t out_len,
  101. const uint8_t seed[hydro_random_SEEDBYTES])
  102. {
  103. static const uint8_t prefix[] = { 7, 'd', 'r', 'b', 'g', '2', '5', '6' };
  104. _hydro_attr_aligned_(16) uint8_t state[gimli_BLOCKBYTES];
  105. uint8_t * p = (uint8_t *) out;
  106. size_t i;
  107. size_t leftover;
  108. mem_zero(state, gimli_BLOCKBYTES);
  109. COMPILER_ASSERT(sizeof prefix + 8 <= gimli_RATE);
  110. memcpy(state, prefix, sizeof prefix);
  111. STORE64_LE(state + sizeof prefix, (uint64_t) out_len);
  112. gimli_core_u8(state, 1);
  113. COMPILER_ASSERT(hydro_random_SEEDBYTES == gimli_RATE * 2);
  114. mem_xor(state, seed, gimli_RATE);
  115. gimli_core_u8(state, 2);
  116. mem_xor(state, seed + gimli_RATE, gimli_RATE);
  117. gimli_core_u8(state, 2);
  118. for (i = 0; i < out_len / gimli_RATE; i++) {
  119. gimli_core_u8(state, 0);
  120. memcpy(p + i * gimli_RATE, state, gimli_RATE);
  121. }
  122. leftover = out_len % gimli_RATE;
  123. if (leftover != 0) {
  124. gimli_core_u8(state, 0);
  125. mem_cpy(p + i * gimli_RATE, state, leftover);
  126. }
  127. }
  128. void
  129. hydro_random_reseed(void)
  130. {
  131. hydro_random_context.initialized = 0;
  132. hydro_random_ensure_initialized();
  133. }