randombytes_internal_random.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. #include <assert.h>
  2. #include <errno.h>
  3. #include <fcntl.h>
  4. #include <limits.h>
  5. #include <stdint.h>
  6. #include <stdlib.h>
  7. #include <stdlib.h>
  8. #include <string.h>
  9. #if !defined(_MSC_VER) && !defined(__BORLANDC__)
  10. # include <unistd.h>
  11. #endif
  12. #include <sys/types.h>
  13. #ifndef _WIN32
  14. # include <sys/stat.h>
  15. # include <sys/time.h>
  16. #endif
  17. #ifdef __linux__
  18. # define _LINUX_SOURCE
  19. #endif
  20. #ifdef HAVE_SYS_RANDOM_H
  21. # include <sys/random.h>
  22. #endif
  23. #ifdef __linux__
  24. # ifdef HAVE_GETRANDOM
  25. # define HAVE_LINUX_COMPATIBLE_GETRANDOM
  26. # else
  27. # include <sys/syscall.h>
  28. # if defined(SYS_getrandom) && defined(__NR_getrandom)
  29. # define getrandom(B, S, F) syscall(SYS_getrandom, (B), (int) (S), (F))
  30. # define HAVE_LINUX_COMPATIBLE_GETRANDOM
  31. # endif
  32. # endif
  33. #elif defined(__FreeBSD__)
  34. # include <sys/param.h>
  35. # if defined(__FreeBSD_version) && __FreeBSD_version >= 1200000
  36. # define HAVE_LINUX_COMPATIBLE_GETRANDOM
  37. # endif
  38. #endif
  39. #if !defined(NO_BLOCKING_RANDOM_POLL) && defined(__linux__)
  40. # define BLOCK_ON_DEV_RANDOM
  41. #endif
  42. #ifdef BLOCK_ON_DEV_RANDOM
  43. # include <poll.h>
  44. #endif
  45. #ifdef HAVE_RDRAND
  46. # pragma GCC target("rdrnd")
  47. # include <immintrin.h>
  48. #endif
  49. #include "core.h"
  50. #include "crypto_core_hchacha20.h"
  51. #include "crypto_stream_chacha20.h"
  52. #include "private/common.h"
  53. #include "randombytes.h"
  54. #include "randombytes_internal_random.h"
  55. #include "runtime.h"
  56. #include "utils.h"
  57. #ifdef _WIN32
  58. # include <windows.h>
  59. # include <sys/timeb.h>
  60. # define RtlGenRandom SystemFunction036
  61. # if defined(__cplusplus)
  62. extern "C"
  63. # endif
  64. BOOLEAN NTAPI RtlGenRandom(PVOID RandomBuffer, ULONG RandomBufferLength);
  65. # pragma comment(lib, "advapi32.lib")
  66. # ifdef __BORLANDC__
  67. # define _ftime ftime
  68. # define _timeb timeb
  69. # endif
  70. #endif
  71. #define INTERNAL_RANDOM_BLOCK_SIZE crypto_core_hchacha20_OUTPUTBYTES
  72. #if defined(__OpenBSD__) || defined(__CloudABI__) || defined(__wasi__)
  73. # define HAVE_SAFE_ARC4RANDOM 1
  74. #endif
  75. #if defined(__CloudABI__) || defined(__wasm__)
  76. # define NONEXISTENT_DEV_RANDOM 1
  77. #endif
  78. #ifndef SSIZE_MAX
  79. # define SSIZE_MAX (SIZE_MAX / 2 - 1)
  80. #endif
  81. #ifndef S_ISNAM
  82. # ifdef __COMPCERT__
  83. # define S_ISNAM(X) 1
  84. # else
  85. # define S_ISNAM(X) 0
  86. # endif
  87. #endif
  88. #ifndef TLS
  89. # ifdef _WIN32
  90. # define TLS __declspec(thread)
  91. # else
  92. # define TLS
  93. # endif
  94. #endif
  95. typedef struct InternalRandomGlobal_ {
  96. int initialized;
  97. int random_data_source_fd;
  98. int getentropy_available;
  99. int getrandom_available;
  100. int rdrand_available;
  101. #ifdef HAVE_GETPID
  102. pid_t pid;
  103. #endif
  104. } InternalRandomGlobal;
  105. typedef struct InternalRandom_ {
  106. int initialized;
  107. size_t rnd32_outleft;
  108. unsigned char key[crypto_stream_chacha20_KEYBYTES];
  109. unsigned char rnd32[16U * INTERNAL_RANDOM_BLOCK_SIZE];
  110. uint64_t nonce;
  111. } InternalRandom;
  112. static InternalRandomGlobal global = {
  113. SODIUM_C99(.initialized =) 0,
  114. SODIUM_C99(.random_data_source_fd =) -1
  115. };
  116. static TLS InternalRandom stream = {
  117. SODIUM_C99(.initialized =) 0,
  118. SODIUM_C99(.rnd32_outleft =) (size_t) 0U
  119. };
  120. /*
  121. * Get a high-resolution timestamp, as a uint64_t value
  122. */
  123. #ifdef _WIN32
  124. static uint64_t
  125. sodium_hrtime(void)
  126. {
  127. struct _timeb tb;
  128. # pragma warning(push)
  129. # pragma warning(disable: 4996)
  130. _ftime(&tb);
  131. # pragma warning(pop)
  132. return ((uint64_t) tb.time) * 1000000U + ((uint64_t) tb.millitm) * 1000U;
  133. }
  134. #else /* _WIN32 */
  135. static uint64_t
  136. sodium_hrtime(void)
  137. {
  138. struct timeval tv;
  139. if (gettimeofday(&tv, NULL) != 0) {
  140. sodium_misuse(); /* LCOV_EXCL_LINE */
  141. }
  142. return ((uint64_t) tv.tv_sec) * 1000000U + (uint64_t) tv.tv_usec;
  143. }
  144. #endif /* _WIN32 */
  145. /*
  146. * Initialize the entropy source
  147. */
  148. #ifdef _WIN32
  149. static void
  150. randombytes_internal_random_init(void)
  151. {
  152. global.rdrand_available = sodium_runtime_has_rdrand();
  153. }
  154. #else /* _WIN32 */
  155. # ifdef HAVE_GETENTROPY
  156. static int
  157. _randombytes_getentropy(void * const buf, const size_t size)
  158. {
  159. assert(size <= 256U);
  160. if (getentropy(buf, size) != 0) {
  161. return -1; /* LCOV_EXCL_LINE */
  162. }
  163. return 0;
  164. }
  165. static int
  166. randombytes_getentropy(void * const buf_, size_t size)
  167. {
  168. unsigned char *buf = (unsigned char *) buf_;
  169. size_t chunk_size = 256U;
  170. do {
  171. if (size < chunk_size) {
  172. chunk_size = size;
  173. assert(chunk_size > (size_t) 0U);
  174. }
  175. if (_randombytes_getentropy(buf, chunk_size) != 0) {
  176. return -1; /* LCOV_EXCL_LINE */
  177. }
  178. size -= chunk_size;
  179. buf += chunk_size;
  180. } while (size > (size_t) 0U);
  181. return 0;
  182. }
  183. # elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
  184. static int
  185. _randombytes_linux_getrandom(void * const buf, const size_t size)
  186. {
  187. int readnb;
  188. assert(size <= 256U);
  189. do {
  190. readnb = getrandom(buf, size, 0);
  191. } while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
  192. return (readnb == (int) size) - 1;
  193. }
  194. static int
  195. randombytes_linux_getrandom(void * const buf_, size_t size)
  196. {
  197. unsigned char *buf = (unsigned char *) buf_;
  198. size_t chunk_size = 256U;
  199. do {
  200. if (size < chunk_size) {
  201. chunk_size = size;
  202. assert(chunk_size > (size_t) 0U);
  203. }
  204. if (_randombytes_linux_getrandom(buf, chunk_size) != 0) {
  205. return -1;
  206. }
  207. size -= chunk_size;
  208. buf += chunk_size;
  209. } while (size > (size_t) 0U);
  210. return 0;
  211. }
  212. # endif
  213. # ifndef NONEXISTENT_DEV_RANDOM
  214. # ifdef BLOCK_ON_DEV_RANDOM
  215. static int
  216. randombytes_block_on_dev_random(void)
  217. {
  218. struct pollfd pfd;
  219. int fd;
  220. int pret;
  221. fd = open("/dev/random", O_RDONLY);
  222. if (fd == -1) {
  223. return 0;
  224. }
  225. pfd.fd = fd;
  226. pfd.events = POLLIN;
  227. pfd.revents = 0;
  228. do {
  229. pret = poll(&pfd, 1, -1);
  230. } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
  231. if (pret != 1) {
  232. (void) close(fd);
  233. errno = EIO;
  234. return -1;
  235. }
  236. return close(fd);
  237. }
  238. # endif
  239. /* LCOV_EXCL_START */
  240. static int
  241. randombytes_internal_random_random_dev_open(void)
  242. {
  243. struct stat st;
  244. static const char *devices[] = {
  245. # ifndef USE_BLOCKING_RANDOM
  246. "/dev/urandom",
  247. # endif
  248. "/dev/random", NULL
  249. };
  250. const char **device = devices;
  251. int fd;
  252. # ifdef BLOCK_ON_DEV_RANDOM
  253. if (randombytes_block_on_dev_random() != 0) {
  254. return -1;
  255. }
  256. # endif
  257. do {
  258. fd = open(*device, O_RDONLY);
  259. if (fd != -1) {
  260. if (fstat(fd, &st) == 0 && (S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))) {
  261. # if defined(F_SETFD) && defined(FD_CLOEXEC)
  262. (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
  263. # endif
  264. return fd;
  265. }
  266. (void) close(fd);
  267. } else if (errno == EINTR) {
  268. continue;
  269. }
  270. device++;
  271. } while (*device != NULL);
  272. errno = EIO;
  273. return -1;
  274. }
  275. /* LCOV_EXCL_STOP */
  276. static ssize_t
  277. safe_read(const int fd, void * const buf_, size_t size)
  278. {
  279. unsigned char *buf = (unsigned char *) buf_;
  280. ssize_t readnb;
  281. assert(size > (size_t) 0U);
  282. assert(size <= SSIZE_MAX);
  283. do {
  284. while ((readnb = read(fd, buf, size)) < (ssize_t) 0 &&
  285. (errno == EINTR || errno == EAGAIN)); /* LCOV_EXCL_LINE */
  286. if (readnb < (ssize_t) 0) {
  287. return readnb; /* LCOV_EXCL_LINE */
  288. }
  289. if (readnb == (ssize_t) 0) {
  290. break; /* LCOV_EXCL_LINE */
  291. }
  292. size -= (size_t) readnb;
  293. buf += readnb;
  294. } while (size > (ssize_t) 0);
  295. return (ssize_t) (buf - (unsigned char *) buf_);
  296. }
  297. # endif /* !NONEXISTENT_DEV_RANDOM */
  298. static void
  299. randombytes_internal_random_init(void)
  300. {
  301. const int errno_save = errno;
  302. global.rdrand_available = sodium_runtime_has_rdrand();
  303. global.getentropy_available = 0;
  304. global.getrandom_available = 0;
  305. # ifdef HAVE_GETENTROPY
  306. {
  307. unsigned char fodder[16];
  308. if (randombytes_getentropy(fodder, sizeof fodder) == 0) {
  309. global.getentropy_available = 1;
  310. errno = errno_save;
  311. return;
  312. }
  313. }
  314. # elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
  315. {
  316. unsigned char fodder[16];
  317. if (randombytes_linux_getrandom(fodder, sizeof fodder) == 0) {
  318. global.getrandom_available = 1;
  319. errno = errno_save;
  320. return;
  321. }
  322. }
  323. # endif
  324. /* LCOV_EXCL_START */
  325. # if !defined(NONEXISTENT_DEV_RANDOM)
  326. assert((global.getentropy_available | global.getrandom_available) == 0);
  327. if ((global.random_data_source_fd =
  328. randombytes_internal_random_random_dev_open()) == -1) {
  329. sodium_misuse(); /* LCOV_EXCL_LINE */
  330. }
  331. errno = errno_save;
  332. return;
  333. # endif
  334. /* LCOV_EXCL_STOP */
  335. # ifndef HAVE_SAFE_ARC4RANDOM
  336. sodium_misuse();
  337. # endif
  338. }
  339. #endif /* _WIN32 */
  340. /*
  341. * (Re)seed the generator using the entropy source
  342. */
  343. static void
  344. randombytes_internal_random_stir(void)
  345. {
  346. stream.nonce = sodium_hrtime();
  347. assert(stream.nonce != (uint64_t) 0U);
  348. memset(stream.rnd32, 0, sizeof stream.rnd32);
  349. stream.rnd32_outleft = (size_t) 0U;
  350. if (global.initialized == 0) {
  351. randombytes_internal_random_init();
  352. global.initialized = 1;
  353. }
  354. #ifdef HAVE_GETPID
  355. global.pid = getpid();
  356. #endif
  357. #ifndef _WIN32
  358. # ifdef HAVE_GETENTROPY
  359. if (global.getentropy_available != 0) {
  360. if (randombytes_getentropy(stream.key, sizeof stream.key) != 0) {
  361. sodium_misuse(); /* LCOV_EXCL_LINE */
  362. }
  363. }
  364. # elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
  365. if (global.getrandom_available != 0) {
  366. if (randombytes_linux_getrandom(stream.key, sizeof stream.key) != 0) {
  367. sodium_misuse(); /* LCOV_EXCL_LINE */
  368. }
  369. }
  370. # elif defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM)
  371. arc4random_buf(stream.key, sizeof stream.key);
  372. # elif !defined(NONEXISTENT_DEV_RANDOM)
  373. if (global.random_data_source_fd == -1 ||
  374. safe_read(global.random_data_source_fd, stream.key,
  375. sizeof stream.key) != (ssize_t) sizeof stream.key) {
  376. sodium_misuse(); /* LCOV_EXCL_LINE */
  377. }
  378. # else
  379. sodium_misuse();
  380. # endif
  381. #else /* _WIN32 */
  382. if (! RtlGenRandom((PVOID) stream.key, (ULONG) sizeof stream.key)) {
  383. sodium_misuse(); /* LCOV_EXCL_LINE */
  384. }
  385. #endif
  386. stream.initialized = 1;
  387. }
  388. /*
  389. * Reseed the generator if it hasn't been initialized yet
  390. */
  391. static void
  392. randombytes_internal_random_stir_if_needed(void)
  393. {
  394. #ifdef HAVE_GETPID
  395. if (stream.initialized == 0) {
  396. randombytes_internal_random_stir();
  397. } else if (global.pid != getpid()) {
  398. sodium_misuse(); /* LCOV_EXCL_LINE */
  399. }
  400. #else
  401. if (stream.initialized == 0) {
  402. randombytes_internal_random_stir();
  403. }
  404. #endif
  405. }
  406. /*
  407. * Close the stream, free global resources
  408. */
  409. #ifdef _WIN32
  410. static int
  411. randombytes_internal_random_close(void)
  412. {
  413. int ret = -1;
  414. if (global.initialized != 0) {
  415. global.initialized = 0;
  416. ret = 0;
  417. }
  418. sodium_memzero(&stream, sizeof stream);
  419. return ret;
  420. }
  421. #else
  422. static int
  423. randombytes_internal_random_close(void)
  424. {
  425. int ret = -1;
  426. # ifdef HAVE_GETENTROPY
  427. if (global.getentropy_available != 0) {
  428. ret = 0;
  429. }
  430. # elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
  431. if (global.getrandom_available != 0) {
  432. ret = 0;
  433. }
  434. # elif !defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM)
  435. ret = 0;
  436. # else
  437. if (global.random_data_source_fd != -1 &&
  438. close(global.random_data_source_fd) == 0) {
  439. global.random_data_source_fd = -1;
  440. global.initialized = 0;
  441. # ifdef HAVE_GETPID
  442. global.pid = (pid_t) 0;
  443. # endif
  444. ret = 0;
  445. }
  446. # endif
  447. sodium_memzero(&stream, sizeof stream);
  448. return ret;
  449. }
  450. #endif
  451. /*
  452. * RDRAND is only used to mitigate prediction if a key is compromised
  453. */
  454. static void
  455. randombytes_internal_random_xorhwrand(void)
  456. {
  457. /* LCOV_EXCL_START */
  458. #ifdef HAVE_RDRAND
  459. unsigned int r;
  460. if (global.rdrand_available == 0) {
  461. return;
  462. }
  463. (void) _rdrand32_step(&r);
  464. * (uint32_t *) (void *)
  465. &stream.key[crypto_stream_chacha20_KEYBYTES - 4] ^= (uint32_t) r;
  466. #endif
  467. /* LCOV_EXCL_STOP */
  468. }
  469. /*
  470. * XOR the key with another same-length secret
  471. */
  472. static inline void
  473. randombytes_internal_random_xorkey(const unsigned char * const mix)
  474. {
  475. unsigned char *key = stream.key;
  476. size_t i;
  477. for (i = (size_t) 0U; i < sizeof stream.key; i++) {
  478. key[i] ^= mix[i];
  479. }
  480. }
  481. /*
  482. * Put `size` random bytes into `buf` and overwrite the key
  483. */
  484. static void
  485. randombytes_internal_random_buf(void * const buf, const size_t size)
  486. {
  487. size_t i;
  488. int ret;
  489. randombytes_internal_random_stir_if_needed();
  490. COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_chacha20_NONCEBYTES);
  491. #if defined(ULLONG_MAX) && defined(SIZE_MAX)
  492. # if SIZE_MAX > ULLONG_MAX
  493. /* coverity[result_independent_of_operands] */
  494. assert(size <= ULLONG_MAX);
  495. # endif
  496. #endif
  497. ret = crypto_stream_chacha20((unsigned char *) buf, (unsigned long long) size,
  498. (unsigned char *) &stream.nonce, stream.key);
  499. assert(ret == 0);
  500. for (i = 0U; i < sizeof size; i++) {
  501. stream.key[i] ^= ((const unsigned char *) (const void *) &size)[i];
  502. }
  503. randombytes_internal_random_xorhwrand();
  504. stream.nonce++;
  505. crypto_stream_chacha20_xor(stream.key, stream.key, sizeof stream.key,
  506. (unsigned char *) &stream.nonce, stream.key);
  507. }
  508. /*
  509. * Pop a 32-bit value from the random pool
  510. *
  511. * Overwrite the key after the pool gets refilled.
  512. */
  513. static uint32_t
  514. randombytes_internal_random(void)
  515. {
  516. uint32_t val;
  517. int ret;
  518. COMPILER_ASSERT(sizeof stream.rnd32 >= (sizeof stream.key) + (sizeof val));
  519. COMPILER_ASSERT(((sizeof stream.rnd32) - (sizeof stream.key))
  520. % sizeof val == (size_t) 0U);
  521. if (stream.rnd32_outleft <= (size_t) 0U) {
  522. randombytes_internal_random_stir_if_needed();
  523. COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_chacha20_NONCEBYTES);
  524. ret = crypto_stream_chacha20((unsigned char *) stream.rnd32,
  525. (unsigned long long) sizeof stream.rnd32,
  526. (unsigned char *) &stream.nonce,
  527. stream.key);
  528. assert(ret == 0);
  529. stream.rnd32_outleft = (sizeof stream.rnd32) - (sizeof stream.key);
  530. randombytes_internal_random_xorhwrand();
  531. randombytes_internal_random_xorkey(&stream.rnd32[stream.rnd32_outleft]);
  532. memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof stream.key);
  533. stream.nonce++;
  534. }
  535. stream.rnd32_outleft -= sizeof val;
  536. memcpy(&val, &stream.rnd32[stream.rnd32_outleft], sizeof val);
  537. memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof val);
  538. return val;
  539. }
  540. static const char *
  541. randombytes_internal_implementation_name(void)
  542. {
  543. return "internal";
  544. }
  545. struct randombytes_implementation randombytes_internal_implementation = {
  546. SODIUM_C99(.implementation_name =) randombytes_internal_implementation_name,
  547. SODIUM_C99(.random =) randombytes_internal_random,
  548. SODIUM_C99(.stir =) randombytes_internal_random_stir,
  549. SODIUM_C99(.uniform =) NULL,
  550. SODIUM_C99(.buf =) randombytes_internal_random_buf,
  551. SODIUM_C99(.close =) randombytes_internal_random_close
  552. };