randombytes_internal_random.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637
  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. /* LCOV_EXCL_START */
  161. if (&getentropy == NULL) {
  162. errno = ENOSYS;
  163. return -1;
  164. }
  165. /* LCOV_EXCL_END */
  166. if (getentropy(buf, size) != 0) {
  167. return -1; /* LCOV_EXCL_LINE */
  168. }
  169. return 0;
  170. }
  171. static int
  172. randombytes_getentropy(void * const buf_, size_t size)
  173. {
  174. unsigned char *buf = (unsigned char *) buf_;
  175. size_t chunk_size = 256U;
  176. do {
  177. if (size < chunk_size) {
  178. chunk_size = size;
  179. assert(chunk_size > (size_t) 0U);
  180. }
  181. if (_randombytes_getentropy(buf, chunk_size) != 0) {
  182. return -1; /* LCOV_EXCL_LINE */
  183. }
  184. size -= chunk_size;
  185. buf += chunk_size;
  186. } while (size > (size_t) 0U);
  187. return 0;
  188. }
  189. # elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
  190. static int
  191. _randombytes_linux_getrandom(void * const buf, const size_t size)
  192. {
  193. int readnb;
  194. assert(size <= 256U);
  195. do {
  196. readnb = getrandom(buf, size, 0);
  197. } while (readnb < 0 && (errno == EINTR || errno == EAGAIN));
  198. return (readnb == (int) size) - 1;
  199. }
  200. static int
  201. randombytes_linux_getrandom(void * const buf_, size_t size)
  202. {
  203. unsigned char *buf = (unsigned char *) buf_;
  204. size_t chunk_size = 256U;
  205. do {
  206. if (size < chunk_size) {
  207. chunk_size = size;
  208. assert(chunk_size > (size_t) 0U);
  209. }
  210. if (_randombytes_linux_getrandom(buf, chunk_size) != 0) {
  211. return -1;
  212. }
  213. size -= chunk_size;
  214. buf += chunk_size;
  215. } while (size > (size_t) 0U);
  216. return 0;
  217. }
  218. # endif
  219. # ifndef NONEXISTENT_DEV_RANDOM
  220. # ifdef BLOCK_ON_DEV_RANDOM
  221. static int
  222. randombytes_block_on_dev_random(void)
  223. {
  224. struct pollfd pfd;
  225. int fd;
  226. int pret;
  227. fd = open("/dev/random", O_RDONLY);
  228. if (fd == -1) {
  229. return 0;
  230. }
  231. pfd.fd = fd;
  232. pfd.events = POLLIN;
  233. pfd.revents = 0;
  234. do {
  235. pret = poll(&pfd, 1, -1);
  236. } while (pret < 0 && (errno == EINTR || errno == EAGAIN));
  237. if (pret != 1) {
  238. (void) close(fd);
  239. errno = EIO;
  240. return -1;
  241. }
  242. return close(fd);
  243. }
  244. # endif
  245. /* LCOV_EXCL_START */
  246. static int
  247. randombytes_internal_random_random_dev_open(void)
  248. {
  249. struct stat st;
  250. static const char *devices[] = {
  251. # ifndef USE_BLOCKING_RANDOM
  252. "/dev/urandom",
  253. # endif
  254. "/dev/random", NULL
  255. };
  256. const char **device = devices;
  257. int fd;
  258. # ifdef BLOCK_ON_DEV_RANDOM
  259. if (randombytes_block_on_dev_random() != 0) {
  260. return -1;
  261. }
  262. # endif
  263. do {
  264. fd = open(*device, O_RDONLY);
  265. if (fd != -1) {
  266. if (fstat(fd, &st) == 0 && (S_ISNAM(st.st_mode) || S_ISCHR(st.st_mode))) {
  267. # if defined(F_SETFD) && defined(FD_CLOEXEC)
  268. (void) fcntl(fd, F_SETFD, fcntl(fd, F_GETFD) | FD_CLOEXEC);
  269. # endif
  270. return fd;
  271. }
  272. (void) close(fd);
  273. } else if (errno == EINTR) {
  274. continue;
  275. }
  276. device++;
  277. } while (*device != NULL);
  278. errno = EIO;
  279. return -1;
  280. }
  281. /* LCOV_EXCL_STOP */
  282. static ssize_t
  283. safe_read(const int fd, void * const buf_, size_t size)
  284. {
  285. unsigned char *buf = (unsigned char *) buf_;
  286. ssize_t readnb;
  287. assert(size > (size_t) 0U);
  288. assert(size <= SSIZE_MAX);
  289. do {
  290. while ((readnb = read(fd, buf, size)) < (ssize_t) 0 &&
  291. (errno == EINTR || errno == EAGAIN)); /* LCOV_EXCL_LINE */
  292. if (readnb < (ssize_t) 0) {
  293. return readnb; /* LCOV_EXCL_LINE */
  294. }
  295. if (readnb == (ssize_t) 0) {
  296. break; /* LCOV_EXCL_LINE */
  297. }
  298. size -= (size_t) readnb;
  299. buf += readnb;
  300. } while (size > (ssize_t) 0);
  301. return (ssize_t) (buf - (unsigned char *) buf_);
  302. }
  303. # endif /* !NONEXISTENT_DEV_RANDOM */
  304. static void
  305. randombytes_internal_random_init(void)
  306. {
  307. const int errno_save = errno;
  308. global.rdrand_available = sodium_runtime_has_rdrand();
  309. global.getentropy_available = 0;
  310. global.getrandom_available = 0;
  311. # ifdef HAVE_GETENTROPY
  312. {
  313. unsigned char fodder[16];
  314. if (randombytes_getentropy(fodder, sizeof fodder) == 0) {
  315. global.getentropy_available = 1;
  316. errno = errno_save;
  317. return;
  318. }
  319. }
  320. # elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
  321. {
  322. unsigned char fodder[16];
  323. if (randombytes_linux_getrandom(fodder, sizeof fodder) == 0) {
  324. global.getrandom_available = 1;
  325. errno = errno_save;
  326. return;
  327. }
  328. }
  329. # endif
  330. /* LCOV_EXCL_START */
  331. # if !defined(NONEXISTENT_DEV_RANDOM)
  332. assert((global.getentropy_available | global.getrandom_available) == 0);
  333. if ((global.random_data_source_fd =
  334. randombytes_internal_random_random_dev_open()) == -1) {
  335. sodium_misuse(); /* LCOV_EXCL_LINE */
  336. }
  337. errno = errno_save;
  338. return;
  339. # endif
  340. /* LCOV_EXCL_STOP */
  341. # ifndef HAVE_SAFE_ARC4RANDOM
  342. sodium_misuse();
  343. # endif
  344. }
  345. #endif /* _WIN32 */
  346. /*
  347. * (Re)seed the generator using the entropy source
  348. */
  349. static void
  350. randombytes_internal_random_stir(void)
  351. {
  352. stream.nonce = sodium_hrtime();
  353. assert(stream.nonce != (uint64_t) 0U);
  354. memset(stream.rnd32, 0, sizeof stream.rnd32);
  355. stream.rnd32_outleft = (size_t) 0U;
  356. if (global.initialized == 0) {
  357. randombytes_internal_random_init();
  358. global.initialized = 1;
  359. }
  360. #ifdef HAVE_GETPID
  361. global.pid = getpid();
  362. #endif
  363. #ifndef _WIN32
  364. # ifdef HAVE_GETENTROPY
  365. if (global.getentropy_available != 0) {
  366. if (randombytes_getentropy(stream.key, sizeof stream.key) != 0) {
  367. sodium_misuse(); /* LCOV_EXCL_LINE */
  368. }
  369. }
  370. # elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
  371. if (global.getrandom_available != 0) {
  372. if (randombytes_linux_getrandom(stream.key, sizeof stream.key) != 0) {
  373. sodium_misuse(); /* LCOV_EXCL_LINE */
  374. }
  375. }
  376. # elif defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM)
  377. arc4random_buf(stream.key, sizeof stream.key);
  378. # elif !defined(NONEXISTENT_DEV_RANDOM)
  379. if (global.random_data_source_fd == -1 ||
  380. safe_read(global.random_data_source_fd, stream.key,
  381. sizeof stream.key) != (ssize_t) sizeof stream.key) {
  382. sodium_misuse(); /* LCOV_EXCL_LINE */
  383. }
  384. # else
  385. sodium_misuse();
  386. # endif
  387. #else /* _WIN32 */
  388. if (! RtlGenRandom((PVOID) stream.key, (ULONG) sizeof stream.key)) {
  389. sodium_misuse(); /* LCOV_EXCL_LINE */
  390. }
  391. #endif
  392. stream.initialized = 1;
  393. }
  394. /*
  395. * Reseed the generator if it hasn't been initialized yet
  396. */
  397. static void
  398. randombytes_internal_random_stir_if_needed(void)
  399. {
  400. #ifdef HAVE_GETPID
  401. if (stream.initialized == 0) {
  402. randombytes_internal_random_stir();
  403. } else if (global.pid != getpid()) {
  404. sodium_misuse(); /* LCOV_EXCL_LINE */
  405. }
  406. #else
  407. if (stream.initialized == 0) {
  408. randombytes_internal_random_stir();
  409. }
  410. #endif
  411. }
  412. /*
  413. * Close the stream, free global resources
  414. */
  415. #ifdef _WIN32
  416. static int
  417. randombytes_internal_random_close(void)
  418. {
  419. int ret = -1;
  420. if (global.initialized != 0) {
  421. global.initialized = 0;
  422. ret = 0;
  423. }
  424. sodium_memzero(&stream, sizeof stream);
  425. return ret;
  426. }
  427. #else
  428. static int
  429. randombytes_internal_random_close(void)
  430. {
  431. int ret = -1;
  432. # ifdef HAVE_GETENTROPY
  433. if (global.getentropy_available != 0) {
  434. ret = 0;
  435. }
  436. # elif defined(HAVE_LINUX_COMPATIBLE_GETRANDOM)
  437. if (global.getrandom_available != 0) {
  438. ret = 0;
  439. }
  440. # elif !defined(NONEXISTENT_DEV_RANDOM) && defined(HAVE_SAFE_ARC4RANDOM)
  441. ret = 0;
  442. # else
  443. if (global.random_data_source_fd != -1 &&
  444. close(global.random_data_source_fd) == 0) {
  445. global.random_data_source_fd = -1;
  446. global.initialized = 0;
  447. # ifdef HAVE_GETPID
  448. global.pid = (pid_t) 0;
  449. # endif
  450. ret = 0;
  451. }
  452. # endif
  453. sodium_memzero(&stream, sizeof stream);
  454. return ret;
  455. }
  456. #endif
  457. /*
  458. * RDRAND is only used to mitigate prediction if a key is compromised
  459. */
  460. static void
  461. randombytes_internal_random_xorhwrand(void)
  462. {
  463. /* LCOV_EXCL_START */
  464. #ifdef HAVE_RDRAND
  465. unsigned int r;
  466. if (global.rdrand_available == 0) {
  467. return;
  468. }
  469. (void) _rdrand32_step(&r);
  470. * (uint32_t *) (void *)
  471. &stream.key[crypto_stream_chacha20_KEYBYTES - 4] ^= (uint32_t) r;
  472. #endif
  473. /* LCOV_EXCL_STOP */
  474. }
  475. /*
  476. * XOR the key with another same-length secret
  477. */
  478. static inline void
  479. randombytes_internal_random_xorkey(const unsigned char * const mix)
  480. {
  481. unsigned char *key = stream.key;
  482. size_t i;
  483. for (i = (size_t) 0U; i < sizeof stream.key; i++) {
  484. key[i] ^= mix[i];
  485. }
  486. }
  487. /*
  488. * Put `size` random bytes into `buf` and overwrite the key
  489. */
  490. static void
  491. randombytes_internal_random_buf(void * const buf, const size_t size)
  492. {
  493. size_t i;
  494. int ret;
  495. randombytes_internal_random_stir_if_needed();
  496. COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_chacha20_NONCEBYTES);
  497. #if defined(ULLONG_MAX) && defined(SIZE_MAX)
  498. # if SIZE_MAX > ULLONG_MAX
  499. /* coverity[result_independent_of_operands] */
  500. assert(size <= ULLONG_MAX);
  501. # endif
  502. #endif
  503. ret = crypto_stream_chacha20((unsigned char *) buf, (unsigned long long) size,
  504. (unsigned char *) &stream.nonce, stream.key);
  505. assert(ret == 0);
  506. for (i = 0U; i < sizeof size; i++) {
  507. stream.key[i] ^= ((const unsigned char *) (const void *) &size)[i];
  508. }
  509. randombytes_internal_random_xorhwrand();
  510. stream.nonce++;
  511. crypto_stream_chacha20_xor(stream.key, stream.key, sizeof stream.key,
  512. (unsigned char *) &stream.nonce, stream.key);
  513. }
  514. /*
  515. * Pop a 32-bit value from the random pool
  516. *
  517. * Overwrite the key after the pool gets refilled.
  518. */
  519. static uint32_t
  520. randombytes_internal_random(void)
  521. {
  522. uint32_t val;
  523. int ret;
  524. COMPILER_ASSERT(sizeof stream.rnd32 >= (sizeof stream.key) + (sizeof val));
  525. COMPILER_ASSERT(((sizeof stream.rnd32) - (sizeof stream.key))
  526. % sizeof val == (size_t) 0U);
  527. if (stream.rnd32_outleft <= (size_t) 0U) {
  528. randombytes_internal_random_stir_if_needed();
  529. COMPILER_ASSERT(sizeof stream.nonce == crypto_stream_chacha20_NONCEBYTES);
  530. ret = crypto_stream_chacha20((unsigned char *) stream.rnd32,
  531. (unsigned long long) sizeof stream.rnd32,
  532. (unsigned char *) &stream.nonce,
  533. stream.key);
  534. assert(ret == 0);
  535. stream.rnd32_outleft = (sizeof stream.rnd32) - (sizeof stream.key);
  536. randombytes_internal_random_xorhwrand();
  537. randombytes_internal_random_xorkey(&stream.rnd32[stream.rnd32_outleft]);
  538. memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof stream.key);
  539. stream.nonce++;
  540. }
  541. stream.rnd32_outleft -= sizeof val;
  542. memcpy(&val, &stream.rnd32[stream.rnd32_outleft], sizeof val);
  543. memset(&stream.rnd32[stream.rnd32_outleft], 0, sizeof val);
  544. return val;
  545. }
  546. static const char *
  547. randombytes_internal_implementation_name(void)
  548. {
  549. return "internal";
  550. }
  551. struct randombytes_implementation randombytes_internal_implementation = {
  552. SODIUM_C99(.implementation_name =) randombytes_internal_implementation_name,
  553. SODIUM_C99(.random =) randombytes_internal_random,
  554. SODIUM_C99(.stir =) randombytes_internal_random_stir,
  555. SODIUM_C99(.uniform =) NULL,
  556. SODIUM_C99(.buf =) randombytes_internal_random_buf,
  557. SODIUM_C99(.close =) randombytes_internal_random_close
  558. };