rng_test_helpers.c 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /* Copyright (c) 2018-2019, The Tor Project, Inc. */
  2. /* See LICENSE for licensing information */
  3. /**
  4. * \file rng_test_helpers.c
  5. * \brief Helpers for overriding PRNGs during unit tests.
  6. *
  7. * We define two PRNG overrides: a "reproducible PRNG" where the seed is
  8. * chosen randomly but the stream can be replayed later on in case a bug is
  9. * found, and a "deterministic PRNG" where the seed is fixed in the unit
  10. * tests.
  11. *
  12. * Obviously, this code is testing-only.
  13. */
  14. #include "orconfig.h"
  15. #include "core/or/or.h"
  16. #include "lib/crypt_ops/crypto_rand.h"
  17. #include "ext/tinytest.h"
  18. #include "test/rng_test_helpers.h"
  19. #ifndef TOR_UNIT_TESTS
  20. #error "No. Never link this code into Tor proper."
  21. #endif
  22. /**
  23. * True iff the RNG is currently replaced. Prevents double-replacement.
  24. **/
  25. static bool rng_is_replaced = false;
  26. /**
  27. * Mutex to protect deterministic prng.
  28. *
  29. * Note that if you actually _use_ the prng from two threads at the same time,
  30. * the results will probably be nondeterministic anyway.
  31. */
  32. static tor_mutex_t *rng_mutex = NULL;
  33. /**
  34. * Cached old value for the thread prng.
  35. **/
  36. static crypto_fast_rng_t *stored_fast_rng = NULL;
  37. /** replacement for crypto_strongest_rand that delegates to crypto_rand. */
  38. static void
  39. mock_crypto_strongest_rand(uint8_t *out, size_t len)
  40. {
  41. crypto_rand((char *)out, len);
  42. }
  43. /* This is the seed of the deterministic randomness. */
  44. static uint8_t rng_seed[16];
  45. static crypto_xof_t *rng_xof = NULL;
  46. /**
  47. * Print the seed for our PRNG to stdout. We use this when we're failed
  48. * test that had a reproducible RNG set.
  49. **/
  50. void
  51. testing_dump_reproducible_rng_seed(void)
  52. {
  53. printf("\n"
  54. "Seed: %s\n",
  55. hex_str((const char*)rng_seed, sizeof(rng_seed)));
  56. }
  57. /** Produce deterministic randomness for the stochastic tests using the global
  58. * rng_xof output.
  59. *
  60. * This function produces deterministic data over multiple calls iff it's
  61. * called in the same call order with the same 'n' parameter.
  62. * If not, outputs will deviate. */
  63. static void
  64. crypto_rand_deterministic(char *out, size_t n)
  65. {
  66. tor_assert(rng_xof);
  67. tor_mutex_acquire(rng_mutex);
  68. crypto_xof_squeeze_bytes(rng_xof, (uint8_t*)out, n);
  69. tor_mutex_release(rng_mutex);
  70. }
  71. /**
  72. * Implementation helper: override our crypto_rand() PRNG with a given seed of
  73. * length <b>seed_len</b>. Overlong seeds are truncated; short ones are
  74. * padded.
  75. **/
  76. static void
  77. enable_deterministic_rng_impl(const uint8_t *seed, size_t seed_len)
  78. {
  79. tor_assert(!rng_is_replaced);
  80. tor_assert(crypto_rand == crypto_rand__real);
  81. memset(rng_seed, 0, sizeof(rng_seed));
  82. memcpy(rng_seed, seed, MIN(seed_len, sizeof(rng_seed)));
  83. rng_mutex = tor_mutex_new();
  84. crypto_xof_free(rng_xof);
  85. rng_xof = crypto_xof_new();
  86. crypto_xof_add_bytes(rng_xof, rng_seed, sizeof(rng_seed));
  87. MOCK(crypto_rand, crypto_rand_deterministic);
  88. MOCK(crypto_strongest_rand_, mock_crypto_strongest_rand);
  89. uint8_t fast_rng_seed[CRYPTO_FAST_RNG_SEED_LEN];
  90. memset(fast_rng_seed, 0xff, sizeof(fast_rng_seed));
  91. memcpy(fast_rng_seed, rng_seed, MIN(sizeof(rng_seed),
  92. sizeof(fast_rng_seed)));
  93. crypto_fast_rng_t *fast_rng = crypto_fast_rng_new_from_seed(fast_rng_seed);
  94. crypto_fast_rng_disable_reseed(fast_rng);
  95. stored_fast_rng = crypto_replace_thread_fast_rng(fast_rng);
  96. rng_is_replaced = true;
  97. }
  98. /**
  99. * Replace our get_thread_fast_rng(), crypto_rand() and
  100. * crypto_strongest_rand() prngs with a variant that generates all of its
  101. * output deterministically from a randomly chosen seed. In the event of an
  102. * error, you can log the seed later on with
  103. * testing_dump_reproducible_rng_seed.
  104. **/
  105. void
  106. testing_enable_reproducible_rng(void)
  107. {
  108. const char *provided_seed = getenv("TOR_TEST_RNG_SEED");
  109. if (provided_seed) {
  110. size_t hexlen = strlen(provided_seed);
  111. size_t seedlen = hexlen / 2;
  112. uint8_t *seed = tor_malloc(hexlen / 2);
  113. if (base16_decode((char*)seed, seedlen, provided_seed, hexlen) < 0) {
  114. puts("Cannot decode value in TOR_TEST_RNG_SEED");
  115. exit(1);
  116. }
  117. enable_deterministic_rng_impl(seed, seedlen);
  118. tor_free(seed);
  119. } else {
  120. uint8_t seed[16];
  121. crypto_rand((char*)seed, sizeof(seed));
  122. enable_deterministic_rng_impl(seed, sizeof(seed));
  123. }
  124. }
  125. /**
  126. * Replace our get_thread_fast_rng(), crypto_rand() and
  127. * crypto_strongest_rand() prngs with a variant that generates all of its
  128. * output deterministically from a fixed seed. This variant is mainly useful
  129. * for cases when we don't want coverage to change between runs.
  130. *
  131. * USAGE NOTE: Test correctness SHOULD NOT depend on the specific output of
  132. * this "rng". If you need a specific output, use
  133. * testing_enable_prefilled_rng() instead.
  134. **/
  135. void
  136. testing_enable_deterministic_rng(void)
  137. {
  138. static const uint8_t quotation[] =
  139. "What will it be? A tree? A weed? "
  140. "Each one is started from a seed."; // -- Mary Ann Hoberman
  141. enable_deterministic_rng_impl(quotation, sizeof(quotation));
  142. }
  143. static uint8_t *prefilled_rng_buffer = NULL;
  144. static size_t prefilled_rng_buflen;
  145. static size_t prefilled_rng_idx;
  146. /**
  147. * crypto_rand() replacement that returns canned data.
  148. **/
  149. static void
  150. crypto_rand_prefilled(char *out, size_t n)
  151. {
  152. tor_mutex_acquire(rng_mutex);
  153. while (n) {
  154. size_t n_to_copy = MIN(prefilled_rng_buflen - prefilled_rng_idx, n);
  155. memcpy(out, prefilled_rng_buffer + prefilled_rng_idx, n_to_copy);
  156. out += n_to_copy;
  157. n -= n_to_copy;
  158. prefilled_rng_idx += n_to_copy;
  159. if (prefilled_rng_idx == prefilled_rng_buflen) {
  160. prefilled_rng_idx = 0;
  161. }
  162. }
  163. tor_mutex_release(rng_mutex);
  164. }
  165. /**
  166. * Replace our crypto_rand() and crypto_strongest_rand() prngs with a variant
  167. * that yields output from a buffer. If it reaches the end of the buffer, it
  168. * starts over.
  169. *
  170. * Note: the get_thread_fast_rng() prng is not replaced by this; we'll need
  171. * more code to support that.
  172. **/
  173. void
  174. testing_enable_prefilled_rng(const void *buffer, size_t buflen)
  175. {
  176. tor_assert(buflen > 0);
  177. tor_assert(!rng_mutex);
  178. rng_mutex = tor_mutex_new();
  179. tor_mutex_acquire(rng_mutex);
  180. prefilled_rng_buffer = tor_memdup(buffer, buflen);
  181. prefilled_rng_buflen = buflen;
  182. prefilled_rng_idx = 0;
  183. tor_mutex_release(rng_mutex);
  184. MOCK(crypto_rand, crypto_rand_prefilled);
  185. MOCK(crypto_strongest_rand_, mock_crypto_strongest_rand);
  186. }
  187. /**
  188. * Reset the position in the prefilled RNG buffer to the start.
  189. */
  190. void
  191. testing_prefilled_rng_reset(void)
  192. {
  193. tor_mutex_acquire(rng_mutex);
  194. prefilled_rng_idx = 0;
  195. tor_mutex_release(rng_mutex);
  196. }
  197. /**
  198. * Undo the overrides for our PRNG. To be used at the end of testing.
  199. *
  200. * Note that this function should be safe to call even if the rng has not
  201. * yet been replaced.
  202. **/
  203. void
  204. testing_disable_rng_override(void)
  205. {
  206. crypto_xof_free(rng_xof);
  207. tor_free(prefilled_rng_buffer);
  208. UNMOCK(crypto_rand);
  209. UNMOCK(crypto_strongest_rand_);
  210. tor_mutex_free(rng_mutex);
  211. crypto_fast_rng_t *rng = crypto_replace_thread_fast_rng(stored_fast_rng);
  212. crypto_fast_rng_free(rng);
  213. rng_is_replaced = false;
  214. }
  215. /**
  216. * As testing_disable_rng_override(), but dump the seed if the current
  217. * test has failed.
  218. */
  219. void
  220. testing_disable_reproducible_rng(void)
  221. {
  222. if (tinytest_cur_test_has_failed()) {
  223. testing_dump_reproducible_rng_seed();
  224. }
  225. testing_disable_rng_override();
  226. }