alt_arc4random.c 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240
  1. #include <config.h>
  2. #if !defined(__OpenBSD__) && !defined(__CloudABI__) && !defined(__wasi__)
  3. #include "crypto.h"
  4. #include "ftpd.h"
  5. #include "safe_rw.h"
  6. #include "alt_arc4random.h"
  7. #include "utils.h"
  8. #define RNG_RESERVE_LEN 512
  9. #define CHACHA20_KEYBYTES 32
  10. #define CHACHA20_BLOCKBYTES 64
  11. #define ROTL32(x, b) (uint32_t)(((x) << (b)) | ((x) >> (32 - (b))))
  12. #define CHACHA20_QUARTERROUND(A, B, C, D) \
  13. A += B; \
  14. D = ROTL32(D ^ A, 16); \
  15. C += D; \
  16. B = ROTL32(B ^ C, 12); \
  17. A += B; \
  18. D = ROTL32(D ^ A, 8); \
  19. C += D; \
  20. B = ROTL32(B ^ C, 7)
  21. static void CHACHA20_ROUNDS(uint32_t st[16])
  22. {
  23. int i;
  24. for (i = 0; i < 20; i += 2) {
  25. CHACHA20_QUARTERROUND(st[0], st[4], st[8], st[12]);
  26. CHACHA20_QUARTERROUND(st[1], st[5], st[9], st[13]);
  27. CHACHA20_QUARTERROUND(st[2], st[6], st[10], st[14]);
  28. CHACHA20_QUARTERROUND(st[3], st[7], st[11], st[15]);
  29. CHACHA20_QUARTERROUND(st[0], st[5], st[10], st[15]);
  30. CHACHA20_QUARTERROUND(st[1], st[6], st[11], st[12]);
  31. CHACHA20_QUARTERROUND(st[2], st[7], st[8], st[13]);
  32. CHACHA20_QUARTERROUND(st[3], st[4], st[9], st[14]);
  33. }
  34. }
  35. static void chacha20_update(uint8_t out[CHACHA20_BLOCKBYTES], uint32_t st[16])
  36. {
  37. uint32_t ks[16];
  38. int i;
  39. memcpy(ks, st, 4 * 16);
  40. CHACHA20_ROUNDS(st);
  41. for (i = 0; i < 16; i++) {
  42. ks[i] += st[i];
  43. }
  44. memcpy(out, ks, CHACHA20_BLOCKBYTES);
  45. st[12]++;
  46. }
  47. static void chacha20_init(uint32_t st[16], const uint8_t key[CHACHA20_KEYBYTES])
  48. {
  49. static const uint32_t constants[4] = {
  50. 0x61707865, 0x3320646e, 0x79622d32, 0x6b206574
  51. };
  52. memcpy(&st[0], constants, 4 * 4);
  53. memcpy(&st[4], key, CHACHA20_KEYBYTES);
  54. memset(&st[12], 0, 4 * 4);
  55. }
  56. static int chacha20_rng(uint8_t* out, size_t len, uint8_t key[CHACHA20_KEYBYTES])
  57. {
  58. uint32_t st[16];
  59. size_t off;
  60. chacha20_init(st, key);
  61. chacha20_update(&out[0], st);
  62. memcpy(key, out, CHACHA20_KEYBYTES);
  63. off = 0;
  64. while (len >= CHACHA20_BLOCKBYTES) {
  65. chacha20_update(&out[off], st);
  66. len -= CHACHA20_BLOCKBYTES;
  67. off += CHACHA20_BLOCKBYTES;
  68. }
  69. if (len > 0) {
  70. uint8_t tmp[CHACHA20_BLOCKBYTES];
  71. chacha20_update(tmp, st);
  72. memcpy(&out[off], tmp, len);
  73. }
  74. return 0;
  75. }
  76. struct rng_state {
  77. int initialized;
  78. int fd;
  79. size_t off;
  80. uint8_t key[CHACHA20_KEYBYTES];
  81. uint8_t reserve[RNG_RESERVE_LEN];
  82. };
  83. static struct rng_state rng_state;
  84. static int random_dev_open(void)
  85. {
  86. struct stat st;
  87. static const char *devices[] = {
  88. "/dev/urandom",
  89. "/dev/random", NULL
  90. };
  91. const char **device = devices;
  92. int fd;
  93. do {
  94. fd = open(*device, O_RDONLY);
  95. if (fd != -1) {
  96. if (fstat(fd, &st) == 0 &&
  97. #ifdef __COMPCERT__
  98. 1
  99. #elif defined(S_ISNAM)
  100. (S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))
  101. #else
  102. S_ISCHR(st.st_mode)
  103. #endif
  104. ) {
  105. #if defined(F_SETFD) && defined(FD_CLOEXEC)
  106. (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
  107. #endif
  108. return fd;
  109. }
  110. (void) close(fd);
  111. } else if (errno == EINTR) {
  112. continue;
  113. }
  114. device++;
  115. } while (*device != NULL);
  116. errno = EIO;
  117. return -1;
  118. }
  119. void alt_arc4random_stir(void)
  120. {
  121. if (rng_state.initialized == 0) {
  122. rng_state.fd = -1;
  123. }
  124. if (rng_state.fd == -1 &&
  125. (rng_state.fd = random_dev_open()) == -1) {
  126. abort();
  127. }
  128. if (safe_read(rng_state.fd,
  129. rng_state.key, sizeof rng_state.key) <= (ssize_t) 0) {
  130. abort();
  131. }
  132. rng_state.off = RNG_RESERVE_LEN;
  133. rng_state.initialized = 1;
  134. }
  135. void alt_arc4random_buf(void* buffer, size_t len)
  136. {
  137. unsigned char *buffer_ = (unsigned char*)buffer;
  138. size_t off;
  139. size_t remaining;
  140. size_t partial;
  141. int ret;
  142. if (!rng_state.initialized) {
  143. alt_arc4random_stir();
  144. }
  145. off = 0;
  146. remaining = len;
  147. while (remaining > 0) {
  148. if (rng_state.off == RNG_RESERVE_LEN) {
  149. while (remaining >= RNG_RESERVE_LEN) {
  150. chacha20_rng(&buffer_[off], RNG_RESERVE_LEN, rng_state.key);
  151. off += RNG_RESERVE_LEN;
  152. remaining -= RNG_RESERVE_LEN;
  153. }
  154. if (remaining == 0) {
  155. break;
  156. }
  157. chacha20_rng(&rng_state.reserve[0], RNG_RESERVE_LEN, rng_state.key);
  158. rng_state.off = 0;
  159. }
  160. partial = RNG_RESERVE_LEN - rng_state.off;
  161. if (remaining < partial) {
  162. partial = remaining;
  163. }
  164. memcpy(&buffer_[off], &rng_state.reserve[rng_state.off], partial);
  165. memset(&rng_state.reserve[rng_state.off], 0, partial);
  166. rng_state.off += partial;
  167. remaining -= partial;
  168. off += partial;
  169. }
  170. }
  171. uint32_t alt_arc4random(void)
  172. {
  173. uint32_t v;
  174. alt_arc4random_buf(&v, sizeof v);
  175. return v;
  176. }
  177. uint32_t alt_arc4random_uniform(const uint32_t upper_bound)
  178. {
  179. uint32_t min;
  180. uint32_t r;
  181. if (upper_bound < 2U) {
  182. return 0;
  183. }
  184. min = (1U + ~upper_bound) % upper_bound; /* = 2**32 mod upper_bound */
  185. do {
  186. r = alt_arc4random();
  187. } while (r < min);
  188. /* r is now clamped to a set whose size mod upper_bound == 0
  189. * the worst case (2**31+1) requires 2 attempts on average */
  190. return r % upper_bound;
  191. }
  192. int alt_arc4random_close(void)
  193. {
  194. rng_state.initialized = 0;
  195. pure_memzero(rng_state.key, sizeof rng_state.key);
  196. if (rng_state.fd != -1) {
  197. return close(rng_state.fd);
  198. }
  199. return 0;
  200. }
  201. #else
  202. #include "alt_arc4random.h"
  203. int
  204. alt_arc4random_close(void)
  205. {
  206. return 0;
  207. }
  208. #endif