s2n_random.c 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683
  1. /*
  2. * Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License").
  5. * You may not use this file except in compliance with the License.
  6. * A copy of the License is located at
  7. *
  8. * http://aws.amazon.com/apache2.0
  9. *
  10. * or in the "license" file accompanying this file. This file is distributed
  11. * on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either
  12. * express or implied. See the License for the specific language governing
  13. * permissions and limitations under the License.
  14. */
  15. /*
  16. * _XOPEN_SOURCE is needed for resolving the constant O_CLOEXEC in some
  17. * environments. We use _XOPEN_SOURCE instead of _GNU_SOURCE because
  18. * _GNU_SOURCE is not portable and breaks when attempting to build rust
  19. * bindings on MacOS.
  20. *
  21. * https://man7.org/linux/man-pages/man2/open.2.html
  22. * The O_CLOEXEC, O_DIRECTORY, and O_NOFOLLOW flags are not
  23. * specified in POSIX.1-2001, but are specified in POSIX.1-2008.
  24. * Since glibc 2.12, one can obtain their definitions by defining
  25. * either _POSIX_C_SOURCE with a value greater than or equal to
  26. * 200809L or _XOPEN_SOURCE with a value greater than or equal to
  27. * 700. In glibc 2.11 and earlier, one obtains the definitions by
  28. * defining _GNU_SOURCE.
  29. *
  30. * We use two feature probes to detect the need to perform this workaround.
  31. * It is only applied if we can't get CLOEXEC without it and the build doesn't
  32. * fail with _XOPEN_SOURCE being defined.
  33. *
  34. * # Relevent Links
  35. *
  36. * - POSIX.1-2017: https://pubs.opengroup.org/onlinepubs/9699919799
  37. * - https://stackoverflow.com/a/5724485
  38. * - https://stackoverflow.com/a/5583764
  39. */
  40. #if !defined(S2N_CLOEXEC_SUPPORTED) && defined(S2N_CLOEXEC_XOPEN_SUPPORTED) && !defined(_XOPEN_SOURCE)
  41. #define _XOPEN_SOURCE 700
  42. #include <fcntl.h>
  43. #undef _XOPEN_SOURCE
  44. #else
  45. #include <fcntl.h>
  46. #endif
  47. #include <errno.h>
  48. #include <limits.h>
  49. #include <openssl/engine.h>
  50. #include <openssl/rand.h>
  51. #include <pthread.h>
  52. #include <stdint.h>
  53. #include <stdlib.h>
  54. #include <string.h>
  55. #include <sys/param.h>
  56. #include <sys/stat.h>
  57. #include <sys/types.h>
  58. #include <time.h>
  59. #include <unistd.h>
  60. #if defined(S2N_CPUID_AVAILABLE)
  61. #include <cpuid.h>
  62. #endif
  63. #include "api/s2n.h"
  64. #include "crypto/s2n_drbg.h"
  65. #include "crypto/s2n_fips.h"
  66. #include "error/s2n_errno.h"
  67. #include "stuffer/s2n_stuffer.h"
  68. #include "utils/s2n_fork_detection.h"
  69. #include "utils/s2n_init.h"
  70. #include "utils/s2n_mem.h"
  71. #include "utils/s2n_random.h"
  72. #include "utils/s2n_result.h"
  73. #include "utils/s2n_safety.h"
  74. #define ENTROPY_SOURCE "/dev/urandom"
  75. #if defined(O_CLOEXEC)
  76. #define ENTROPY_FLAGS O_RDONLY | O_CLOEXEC
  77. #else
  78. #define ENTROPY_FLAGS O_RDONLY
  79. #endif
  80. /* See https://en.wikipedia.org/wiki/CPUID */
  81. #define RDRAND_ECX_FLAG 0x40000000
  82. /* One second in nanoseconds */
  83. #define ONE_S INT64_C(1000000000)
  84. /* Placeholder value for an uninitialized entropy file descriptor */
  85. #define UNINITIALIZED_ENTROPY_FD -1
  86. static int entropy_fd = UNINITIALIZED_ENTROPY_FD;
  87. struct s2n_rand_state {
  88. uint64_t cached_fork_generation_number;
  89. struct s2n_drbg public_drbg;
  90. struct s2n_drbg private_drbg;
  91. bool drbgs_initialized;
  92. };
  93. /* Key which will control per-thread freeing of drbg memory */
  94. static pthread_key_t s2n_per_thread_rand_state_key;
  95. /* Needed to ensure key is initialized only once */
  96. static pthread_once_t s2n_per_thread_rand_state_key_once = PTHREAD_ONCE_INIT;
  97. /* Tracks if call to pthread_key_create failed */
  98. static int pthread_key_create_result;
  99. static __thread struct s2n_rand_state s2n_per_thread_rand_state = {
  100. .cached_fork_generation_number = 0,
  101. .public_drbg = { 0 },
  102. .private_drbg = { 0 },
  103. .drbgs_initialized = false
  104. };
  105. static int s2n_rand_init_impl(void);
  106. static int s2n_rand_cleanup_impl(void);
  107. static int s2n_rand_urandom_impl(void *ptr, uint32_t size);
  108. static int s2n_rand_rdrand_impl(void *ptr, uint32_t size);
  109. static s2n_rand_init_callback s2n_rand_init_cb = s2n_rand_init_impl;
  110. static s2n_rand_cleanup_callback s2n_rand_cleanup_cb = s2n_rand_cleanup_impl;
  111. static s2n_rand_seed_callback s2n_rand_seed_cb = s2n_rand_urandom_impl;
  112. static s2n_rand_mix_callback s2n_rand_mix_cb = s2n_rand_urandom_impl;
  113. /* non-static for SAW proof */
  114. bool s2n_cpu_supports_rdrand()
  115. {
  116. #if defined(S2N_CPUID_AVAILABLE)
  117. uint32_t eax, ebx, ecx, edx;
  118. if (!__get_cpuid(1, &eax, &ebx, &ecx, &edx)) {
  119. return false;
  120. }
  121. if (ecx & RDRAND_ECX_FLAG) {
  122. return true;
  123. }
  124. #endif
  125. return false;
  126. }
  127. int s2n_rand_set_callbacks(s2n_rand_init_callback rand_init_callback,
  128. s2n_rand_cleanup_callback rand_cleanup_callback,
  129. s2n_rand_seed_callback rand_seed_callback,
  130. s2n_rand_mix_callback rand_mix_callback)
  131. {
  132. POSIX_ENSURE_REF(rand_init_callback);
  133. POSIX_ENSURE_REF(rand_cleanup_callback);
  134. POSIX_ENSURE_REF(rand_seed_callback);
  135. POSIX_ENSURE_REF(rand_mix_callback);
  136. s2n_rand_init_cb = rand_init_callback;
  137. s2n_rand_cleanup_cb = rand_cleanup_callback;
  138. s2n_rand_seed_cb = rand_seed_callback;
  139. s2n_rand_mix_cb = rand_mix_callback;
  140. return S2N_SUCCESS;
  141. }
  142. S2N_RESULT s2n_get_seed_entropy(struct s2n_blob *blob)
  143. {
  144. RESULT_ENSURE_REF(blob);
  145. RESULT_ENSURE(s2n_rand_seed_cb(blob->data, blob->size) >= S2N_SUCCESS, S2N_ERR_CANCELLED);
  146. return S2N_RESULT_OK;
  147. }
  148. S2N_RESULT s2n_get_mix_entropy(struct s2n_blob *blob)
  149. {
  150. RESULT_ENSURE_REF(blob);
  151. RESULT_GUARD_POSIX(s2n_rand_mix_cb(blob->data, blob->size));
  152. return S2N_RESULT_OK;
  153. }
  154. /* Deletes pthread key at process-exit */
  155. static void __attribute__((destructor)) s2n_drbg_rand_state_key_cleanup(void)
  156. {
  157. if (s2n_is_initialized()) {
  158. pthread_key_delete(s2n_per_thread_rand_state_key);
  159. }
  160. }
  161. static void s2n_drbg_destructor(void *_unused_argument)
  162. {
  163. (void) _unused_argument;
  164. s2n_result_ignore(s2n_rand_cleanup_thread());
  165. }
  166. static void s2n_drbg_make_rand_state_key(void)
  167. {
  168. /* We can't return the output of pthread_key_create due to the parameter constraints of pthread_once.
  169. * Here we store the result in a global variable that will be error checked later. */
  170. pthread_key_create_result = pthread_key_create(&s2n_per_thread_rand_state_key, s2n_drbg_destructor);
  171. }
  172. static S2N_RESULT s2n_init_drbgs(void)
  173. {
  174. uint8_t s2n_public_drbg[] = "s2n public drbg";
  175. uint8_t s2n_private_drbg[] = "s2n private drbg";
  176. struct s2n_blob public = { 0 };
  177. RESULT_GUARD_POSIX(s2n_blob_init(&public, s2n_public_drbg, sizeof(s2n_public_drbg)));
  178. struct s2n_blob private = { 0 };
  179. RESULT_GUARD_POSIX(s2n_blob_init(&private, s2n_private_drbg, sizeof(s2n_private_drbg)));
  180. RESULT_ENSURE(pthread_once(&s2n_per_thread_rand_state_key_once, s2n_drbg_make_rand_state_key) == 0, S2N_ERR_DRBG);
  181. RESULT_ENSURE_EQ(pthread_key_create_result, 0);
  182. RESULT_GUARD(s2n_drbg_instantiate(&s2n_per_thread_rand_state.public_drbg, &public, S2N_AES_128_CTR_NO_DF_PR));
  183. RESULT_GUARD(s2n_drbg_instantiate(&s2n_per_thread_rand_state.private_drbg, &private, S2N_AES_256_CTR_NO_DF_PR));
  184. RESULT_ENSURE(pthread_setspecific(s2n_per_thread_rand_state_key, &s2n_per_thread_rand_state) == 0, S2N_ERR_DRBG);
  185. s2n_per_thread_rand_state.drbgs_initialized = true;
  186. return S2N_RESULT_OK;
  187. }
  188. static S2N_RESULT s2n_ensure_initialized_drbgs(void)
  189. {
  190. if (s2n_per_thread_rand_state.drbgs_initialized == false) {
  191. RESULT_GUARD(s2n_init_drbgs());
  192. /* Then cache the fork generation number. We just initialized the drbg
  193. * states with new entropy and forking is not an external event.
  194. */
  195. uint64_t returned_fork_generation_number = 0;
  196. RESULT_GUARD(s2n_get_fork_generation_number(&returned_fork_generation_number));
  197. s2n_per_thread_rand_state.cached_fork_generation_number = returned_fork_generation_number;
  198. }
  199. return S2N_RESULT_OK;
  200. }
  201. /* s2n_ensure_uniqueness() implements defenses against uniqueness
  202. * breaking events that might cause duplicated drbg states. Currently, only
  203. * implements fork detection.
  204. */
  205. static S2N_RESULT s2n_ensure_uniqueness(void)
  206. {
  207. uint64_t returned_fork_generation_number = 0;
  208. RESULT_GUARD(s2n_get_fork_generation_number(&returned_fork_generation_number));
  209. if (returned_fork_generation_number != s2n_per_thread_rand_state.cached_fork_generation_number) {
  210. /* This assumes that s2n_rand_cleanup_thread() doesn't mutate any other
  211. * state than the drbg states and it resets the drbg initialization
  212. * boolean to false. s2n_ensure_initialized_drbgs() will cache the new
  213. * fork generation number in the per thread state.
  214. */
  215. RESULT_GUARD(s2n_rand_cleanup_thread());
  216. RESULT_GUARD(s2n_ensure_initialized_drbgs());
  217. }
  218. return S2N_RESULT_OK;
  219. }
  220. static S2N_RESULT s2n_get_libcrypto_random_data(struct s2n_blob *out_blob)
  221. {
  222. RESULT_GUARD_PTR(out_blob);
  223. RESULT_GUARD_OSSL(RAND_bytes(out_blob->data, out_blob->size), S2N_ERR_DRBG);
  224. return S2N_RESULT_OK;
  225. }
  226. static S2N_RESULT s2n_get_custom_random_data(struct s2n_blob *out_blob, struct s2n_drbg *drbg_state)
  227. {
  228. RESULT_GUARD_PTR(out_blob);
  229. RESULT_GUARD_PTR(drbg_state);
  230. RESULT_ENSURE(!s2n_is_in_fips_mode(), S2N_ERR_DRBG);
  231. RESULT_GUARD(s2n_ensure_initialized_drbgs());
  232. RESULT_GUARD(s2n_ensure_uniqueness());
  233. uint32_t offset = 0;
  234. uint32_t remaining = out_blob->size;
  235. while (remaining) {
  236. struct s2n_blob slice = { 0 };
  237. RESULT_GUARD_POSIX(s2n_blob_slice(out_blob, &slice, offset, MIN(remaining, S2N_DRBG_GENERATE_LIMIT)));
  238. RESULT_GUARD(s2n_drbg_generate(drbg_state, &slice));
  239. remaining -= slice.size;
  240. offset += slice.size;
  241. }
  242. return S2N_RESULT_OK;
  243. }
  244. static S2N_RESULT s2n_get_random_data(struct s2n_blob *blob, struct s2n_drbg *drbg_state)
  245. {
  246. /* By default, s2n-tls uses a custom random implementation to generate random data for the TLS
  247. * handshake. When operating in FIPS mode, the FIPS-validated libcrypto implementation is used
  248. * instead.
  249. */
  250. if (s2n_is_in_fips_mode()) {
  251. RESULT_GUARD(s2n_get_libcrypto_random_data(blob));
  252. return S2N_RESULT_OK;
  253. }
  254. RESULT_GUARD(s2n_get_custom_random_data(blob, drbg_state));
  255. return S2N_RESULT_OK;
  256. }
  257. S2N_RESULT s2n_get_public_random_data(struct s2n_blob *blob)
  258. {
  259. RESULT_GUARD(s2n_get_random_data(blob, &s2n_per_thread_rand_state.public_drbg));
  260. return S2N_RESULT_OK;
  261. }
  262. S2N_RESULT s2n_get_private_random_data(struct s2n_blob *blob)
  263. {
  264. RESULT_GUARD(s2n_get_random_data(blob, &s2n_per_thread_rand_state.private_drbg));
  265. return S2N_RESULT_OK;
  266. }
  267. S2N_RESULT s2n_get_public_random_bytes_used(uint64_t *bytes_used)
  268. {
  269. RESULT_GUARD(s2n_drbg_bytes_used(&s2n_per_thread_rand_state.public_drbg, bytes_used));
  270. return S2N_RESULT_OK;
  271. }
  272. S2N_RESULT s2n_get_private_random_bytes_used(uint64_t *bytes_used)
  273. {
  274. RESULT_GUARD(s2n_drbg_bytes_used(&s2n_per_thread_rand_state.private_drbg, bytes_used));
  275. return S2N_RESULT_OK;
  276. }
  277. static int s2n_rand_urandom_impl(void *ptr, uint32_t size)
  278. {
  279. POSIX_ENSURE(entropy_fd != UNINITIALIZED_ENTROPY_FD, S2N_ERR_NOT_INITIALIZED);
  280. uint8_t *data = ptr;
  281. uint32_t n = size;
  282. struct timespec sleep_time = { .tv_sec = 0, .tv_nsec = 0 };
  283. long backoff = 1;
  284. while (n) {
  285. errno = 0;
  286. int r = read(entropy_fd, data, n);
  287. if (r <= 0) {
  288. /*
  289. * A non-blocking read() on /dev/urandom should "never" fail,
  290. * except for EINTR. If it does, briefly pause and use
  291. * exponential backoff to avoid creating a tight spinning loop.
  292. *
  293. * iteration delay
  294. * --------- -----------------
  295. * 1 10 nsec
  296. * 2 100 nsec
  297. * 3 1,000 nsec
  298. * 4 10,000 nsec
  299. * 5 100,000 nsec
  300. * 6 1,000,000 nsec
  301. * 7 10,000,000 nsec
  302. * 8 99,999,999 nsec
  303. * 9 99,999,999 nsec
  304. * ...
  305. */
  306. if (errno != EINTR) {
  307. backoff = MIN(backoff * 10, ONE_S - 1);
  308. sleep_time.tv_nsec = backoff;
  309. do {
  310. r = nanosleep(&sleep_time, &sleep_time);
  311. } while (r != 0);
  312. }
  313. continue;
  314. }
  315. data += r;
  316. n -= r;
  317. }
  318. return S2N_SUCCESS;
  319. }
  320. /*
  321. * Return a random number in the range [0, bound)
  322. */
  323. S2N_RESULT s2n_public_random(int64_t bound, uint64_t *output)
  324. {
  325. uint64_t r;
  326. RESULT_ENSURE_GT(bound, 0);
  327. while (1) {
  328. struct s2n_blob blob = { 0 };
  329. RESULT_GUARD_POSIX(s2n_blob_init(&blob, (void *) &r, sizeof(r)));
  330. RESULT_GUARD(s2n_get_public_random_data(&blob));
  331. /* Imagine an int was one byte and UINT_MAX was 256. If the
  332. * caller asked for s2n_random(129, ...) we'd end up in
  333. * trouble. Each number in the range 0...127 would be twice
  334. * as likely as 128. That's because r == 0 % 129 -> 0, and
  335. * r == 129 % 129 -> 0, but only r == 128 returns 128,
  336. * r == 257 is out of range.
  337. *
  338. * To de-bias the dice, we discard values of r that are higher
  339. * that the highest multiple of 'bound' an int can support. If
  340. * bound is a uint, then in the worst case we discard 50% - 1 r's.
  341. * But since 'bound' is an int and INT_MAX is <= UINT_MAX / 2,
  342. * in the worst case we discard 25% - 1 r's.
  343. */
  344. if (r < (UINT64_MAX - (UINT64_MAX % bound))) {
  345. *output = r % bound;
  346. return S2N_RESULT_OK;
  347. }
  348. }
  349. }
  350. #if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND
  351. #define S2N_RAND_ENGINE_ID "s2n_rand"
  352. int s2n_openssl_compat_rand(unsigned char *buf, int num)
  353. {
  354. struct s2n_blob out = { 0 };
  355. POSIX_GUARD(s2n_blob_init(&out, buf, num));
  356. if (s2n_result_is_error(s2n_get_private_random_data(&out))) {
  357. return 0;
  358. }
  359. return 1;
  360. }
  361. int s2n_openssl_compat_status(void)
  362. {
  363. return 1;
  364. }
  365. int s2n_openssl_compat_init(ENGINE *unused)
  366. {
  367. return 1;
  368. }
  369. RAND_METHOD s2n_openssl_rand_method = {
  370. .seed = NULL,
  371. .bytes = s2n_openssl_compat_rand,
  372. .cleanup = NULL,
  373. .add = NULL,
  374. .pseudorand = s2n_openssl_compat_rand,
  375. .status = s2n_openssl_compat_status
  376. };
  377. #endif
  378. static int s2n_rand_init_impl(void)
  379. {
  380. OPEN:
  381. entropy_fd = open(ENTROPY_SOURCE, ENTROPY_FLAGS);
  382. if (entropy_fd == -1) {
  383. if (errno == EINTR) {
  384. goto OPEN;
  385. }
  386. POSIX_BAIL(S2N_ERR_OPEN_RANDOM);
  387. }
  388. if (s2n_cpu_supports_rdrand()) {
  389. s2n_rand_mix_cb = s2n_rand_rdrand_impl;
  390. }
  391. return S2N_SUCCESS;
  392. }
  393. S2N_RESULT s2n_rand_init(void)
  394. {
  395. RESULT_ENSURE(s2n_rand_init_cb() >= S2N_SUCCESS, S2N_ERR_CANCELLED);
  396. RESULT_GUARD(s2n_ensure_initialized_drbgs());
  397. #if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND
  398. if (s2n_is_in_fips_mode()) {
  399. return S2N_RESULT_OK;
  400. }
  401. /* Create an engine */
  402. ENGINE *e = ENGINE_new();
  403. RESULT_ENSURE(e != NULL, S2N_ERR_OPEN_RANDOM);
  404. RESULT_GUARD_OSSL(ENGINE_set_id(e, S2N_RAND_ENGINE_ID), S2N_ERR_OPEN_RANDOM);
  405. RESULT_GUARD_OSSL(ENGINE_set_name(e, "s2n entropy generator"), S2N_ERR_OPEN_RANDOM);
  406. RESULT_GUARD_OSSL(ENGINE_set_flags(e, ENGINE_FLAGS_NO_REGISTER_ALL), S2N_ERR_OPEN_RANDOM);
  407. RESULT_GUARD_OSSL(ENGINE_set_init_function(e, s2n_openssl_compat_init), S2N_ERR_OPEN_RANDOM);
  408. RESULT_GUARD_OSSL(ENGINE_set_RAND(e, &s2n_openssl_rand_method), S2N_ERR_OPEN_RANDOM);
  409. RESULT_GUARD_OSSL(ENGINE_add(e), S2N_ERR_OPEN_RANDOM);
  410. RESULT_GUARD_OSSL(ENGINE_free(e), S2N_ERR_OPEN_RANDOM);
  411. /* Use that engine for rand() */
  412. e = ENGINE_by_id(S2N_RAND_ENGINE_ID);
  413. RESULT_ENSURE(e != NULL, S2N_ERR_OPEN_RANDOM);
  414. RESULT_GUARD_OSSL(ENGINE_init(e), S2N_ERR_OPEN_RANDOM);
  415. RESULT_GUARD_OSSL(ENGINE_set_default(e, ENGINE_METHOD_RAND), S2N_ERR_OPEN_RANDOM);
  416. RESULT_GUARD_OSSL(ENGINE_free(e), S2N_ERR_OPEN_RANDOM);
  417. #endif
  418. return S2N_RESULT_OK;
  419. }
  420. static int s2n_rand_cleanup_impl(void)
  421. {
  422. POSIX_ENSURE(entropy_fd != UNINITIALIZED_ENTROPY_FD, S2N_ERR_NOT_INITIALIZED);
  423. POSIX_GUARD(close(entropy_fd));
  424. entropy_fd = UNINITIALIZED_ENTROPY_FD;
  425. return S2N_SUCCESS;
  426. }
  427. S2N_RESULT s2n_rand_cleanup(void)
  428. {
  429. RESULT_ENSURE(s2n_rand_cleanup_cb() >= S2N_SUCCESS, S2N_ERR_CANCELLED);
  430. #if S2N_LIBCRYPTO_SUPPORTS_CUSTOM_RAND
  431. /* Cleanup our rand ENGINE in libcrypto */
  432. ENGINE *rand_engine = ENGINE_by_id(S2N_RAND_ENGINE_ID);
  433. if (rand_engine) {
  434. ENGINE_remove(rand_engine);
  435. ENGINE_finish(rand_engine);
  436. ENGINE_unregister_RAND(rand_engine);
  437. ENGINE_free(rand_engine);
  438. ENGINE_cleanup();
  439. RAND_set_rand_engine(NULL);
  440. RAND_set_rand_method(NULL);
  441. }
  442. #endif
  443. s2n_rand_init_cb = s2n_rand_init_impl;
  444. s2n_rand_cleanup_cb = s2n_rand_cleanup_impl;
  445. s2n_rand_seed_cb = s2n_rand_urandom_impl;
  446. s2n_rand_mix_cb = s2n_rand_urandom_impl;
  447. return S2N_RESULT_OK;
  448. }
  449. S2N_RESULT s2n_rand_cleanup_thread(void)
  450. {
  451. /* Currently, it is only safe for this function to mutate the drbg states
  452. * in the per thread rand state. See s2n_ensure_uniqueness().
  453. */
  454. RESULT_GUARD(s2n_drbg_wipe(&s2n_per_thread_rand_state.private_drbg));
  455. RESULT_GUARD(s2n_drbg_wipe(&s2n_per_thread_rand_state.public_drbg));
  456. s2n_per_thread_rand_state.drbgs_initialized = false;
  457. /* Unset the thread-local destructor */
  458. if (s2n_is_initialized()) {
  459. pthread_setspecific(s2n_per_thread_rand_state_key, NULL);
  460. }
  461. return S2N_RESULT_OK;
  462. }
  463. /* This must only be used for unit tests. Any real use is dangerous and will be
  464. * overwritten in s2n_ensure_uniqueness() if it is forked. This was added to
  465. * support known answer tests that use OpenSSL and s2n_get_private_random_data
  466. * directly.
  467. */
  468. S2N_RESULT s2n_set_private_drbg_for_test(struct s2n_drbg drbg)
  469. {
  470. RESULT_ENSURE(s2n_in_unit_test(), S2N_ERR_NOT_IN_UNIT_TEST);
  471. RESULT_GUARD(s2n_drbg_wipe(&s2n_per_thread_rand_state.private_drbg));
  472. s2n_per_thread_rand_state.private_drbg = drbg;
  473. return S2N_RESULT_OK;
  474. }
  475. /*
  476. * volatile is important to prevent the compiler from
  477. * re-ordering or optimizing the use of RDRAND.
  478. */
  479. static int s2n_rand_rdrand_impl(void *data, uint32_t size)
  480. {
  481. #if defined(__x86_64__) || defined(__i386__)
  482. struct s2n_blob out = { 0 };
  483. POSIX_GUARD(s2n_blob_init(&out, data, size));
  484. size_t space_remaining = 0;
  485. struct s2n_stuffer stuffer = { 0 };
  486. union {
  487. uint64_t u64;
  488. #if defined(__i386__)
  489. struct {
  490. /* since we check first that we're on intel, we can safely assume little endian. */
  491. uint32_t u_low;
  492. uint32_t u_high;
  493. } i386_fields;
  494. #endif /* defined(__i386__) */
  495. uint8_t u8[8];
  496. } output;
  497. POSIX_GUARD(s2n_stuffer_init(&stuffer, &out));
  498. while ((space_remaining = s2n_stuffer_space_remaining(&stuffer))) {
  499. unsigned char success = 0;
  500. output.u64 = 0;
  501. for (int tries = 0; tries < 10; tries++) {
  502. #if defined(__i386__)
  503. /* execute the rdrand instruction, store the result in a general purpose register (it's assigned to
  504. * output.i386_fields.u_low). Check the carry bit, which will be set on success. Then clober the register and reset
  505. * the carry bit. Due to needing to support an ancient assembler we use the opcode syntax.
  506. * the %b1 is to force compilers to use c1 instead of ecx.
  507. * Here's a description of how the opcode is encoded:
  508. * 0x0fc7 (rdrand)
  509. * 0xf0 (store the result in eax).
  510. */
  511. unsigned char success_high = 0, success_low = 0;
  512. __asm__ __volatile__(
  513. ".byte 0x0f, 0xc7, 0xf0;\n"
  514. "setc %b1;\n"
  515. : "=a"(output.i386_fields.u_low), "=qm"(success_low)
  516. :
  517. : "cc");
  518. __asm__ __volatile__(
  519. ".byte 0x0f, 0xc7, 0xf0;\n"
  520. "setc %b1;\n"
  521. : "=a"(output.i386_fields.u_high), "=qm"(success_high)
  522. :
  523. : "cc");
  524. /* cppcheck-suppress knownConditionTrueFalse */
  525. success = success_high & success_low;
  526. /* Treat either all 1 or all 0 bits in either the high or low order
  527. * bits as failure */
  528. if (output.i386_fields.u_low == 0 || output.i386_fields.u_low == UINT32_MAX
  529. || output.i386_fields.u_high == 0 || output.i386_fields.u_high == UINT32_MAX) {
  530. success = 0;
  531. }
  532. #else
  533. /* execute the rdrand instruction, store the result in a general purpose register (it's assigned to
  534. * output.u64). Check the carry bit, which will be set on success. Then clober the carry bit.
  535. * Due to needing to support an ancient assembler we use the opcode syntax.
  536. * the %b1 is to force compilers to use c1 instead of ecx.
  537. * Here's a description of how the opcode is encoded:
  538. * 0x48 (pick a 64-bit register it does more too, but that's all that matters there)
  539. * 0x0fc7 (rdrand)
  540. * 0xf0 (store the result in rax). */
  541. __asm__ __volatile__(
  542. ".byte 0x48, 0x0f, 0xc7, 0xf0;\n"
  543. "setc %b1;\n"
  544. : "=a"(output.u64), "=qm"(success)
  545. :
  546. : "cc");
  547. #endif /* defined(__i386__) */
  548. /* Some AMD CPUs will find that RDRAND "sticks" on all 1s but still reports success.
  549. * Some other very old CPUs use all 0s as an error condition while still reporting success.
  550. * If we encounter either of these suspicious values (a 1/2^63 chance) we'll treat them as
  551. * a failure and generate a new value.
  552. *
  553. * In the future we could add CPUID checks to detect processors with these known bugs,
  554. * however it does not appear worth it. The entropy loss is negligible and the
  555. * corresponding likelihood that a healthy CPU generates either of these values is also
  556. * negligible (1/2^63). Finally, adding processor specific logic would greatly
  557. * increase the complexity and would cause us to "miss" any unknown processors with
  558. * similar bugs. */
  559. if (output.u64 == UINT64_MAX || output.u64 == 0) {
  560. success = 0;
  561. }
  562. if (success) {
  563. break;
  564. }
  565. }
  566. POSIX_ENSURE(success, S2N_ERR_RDRAND_FAILED);
  567. size_t data_to_fill = MIN(sizeof(output), space_remaining);
  568. POSIX_GUARD(s2n_stuffer_write_bytes(&stuffer, output.u8, data_to_fill));
  569. }
  570. return S2N_SUCCESS;
  571. #else
  572. POSIX_BAIL(S2N_ERR_UNSUPPORTED_CPU);
  573. #endif
  574. }