rng_test_helpers.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  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 "test/rng_test_helpers.h"
  18. #ifndef TOR_UNIT_TESTS
  19. #error "No. Never link this code into Tor proper."
  20. #endif
  21. /**
  22. * Mutex to protect deterministic prng.
  23. *
  24. * Note that if you actually _use_ the prng from two threads at the same time,
  25. * the results will probably be nondeterministic anyway.
  26. */
  27. static tor_mutex_t *rng_mutex = NULL;
  28. /* This is the seed of the deterministic randomness. */
  29. static uint8_t rng_seed[16];
  30. static crypto_xof_t *rng_xof = NULL;
  31. /**
  32. * Print the seed for our PRNG to stdout. We use this when we're
  33. **/
  34. void
  35. testing_dump_reproducible_rng_seed(void)
  36. {
  37. printf("\n"
  38. "Seed: %s\n",
  39. hex_str((const char*)rng_seed, sizeof(rng_seed)));
  40. }
  41. /** Produce deterministic randomness for the stochastic tests using the global
  42. * rng_xof output.
  43. *
  44. * This function produces deterministic data over multiple calls iff it's
  45. * called in the same call order with the same 'n' parameter.
  46. * If not, outputs will deviate. */
  47. static void
  48. crypto_rand_deterministic(char *out, size_t n)
  49. {
  50. tor_assert(rng_xof);
  51. tor_mutex_acquire(rng_mutex);
  52. crypto_xof_squeeze_bytes(rng_xof, (uint8_t*)out, n);
  53. tor_mutex_release(rng_mutex);
  54. }
  55. /**
  56. * Implementation helper: override our crypto_rand() PRNG with a given seed of
  57. * length <b>seed_len</b>. Overlong seeds are truncated; short ones are
  58. * padded.
  59. **/
  60. static void
  61. enable_deterministic_rng_impl(const uint8_t *seed, size_t seed_len)
  62. {
  63. memset(rng_seed, 0, sizeof(rng_seed));
  64. memcpy(rng_seed, seed, MIN(seed_len, sizeof(rng_seed)));
  65. rng_mutex = tor_mutex_new();
  66. crypto_xof_free(rng_xof);
  67. rng_xof = crypto_xof_new();
  68. crypto_xof_add_bytes(rng_xof, rng_seed, sizeof(rng_seed));
  69. MOCK(crypto_rand, crypto_rand_deterministic);
  70. }
  71. /**
  72. * Replace our crypto_rand() prng with a variant that generates all of its
  73. * output deterministically from a randomly chosen seed. In the event of an
  74. * error, you can log the seed later on with
  75. * testing_dump_reproducible_rng_seed.
  76. **/
  77. void
  78. testing_enable_reproducible_rng(void)
  79. {
  80. uint8_t seed[16];
  81. crypto_rand((char*)seed, sizeof(seed));
  82. enable_deterministic_rng_impl(seed, sizeof(seed));
  83. }
  84. /**
  85. * Replace our crypto_rand() prng with a variant that generates all of its
  86. * output deterministically from a fixed seed. This variant is mainly useful
  87. * for cases when we don't want coverage to change between runs.
  88. *
  89. * USAGE NOTE: Test correctness SHOULD NOT depend on the specific output of
  90. * this "rng". If you need a specific output, use
  91. * testing_enable_prefilled_rng() instead.
  92. **/
  93. void
  94. testing_enable_deterministic_rng(void)
  95. {
  96. static const uint8_t quotation[] =
  97. "What will it be? A tree? A weed? "
  98. "Each one is started from a seed."; // -- Mary Ann Hoberman
  99. enable_deterministic_rng_impl(quotation, sizeof(quotation));
  100. }
  101. static uint8_t *prefilled_rng_buffer = NULL;
  102. static size_t prefilled_rng_buflen;
  103. static size_t prefilled_rng_idx;
  104. /**
  105. * crypto_rand() replacement that returns canned data.
  106. **/
  107. static void
  108. crypto_rand_prefilled(char *out, size_t n)
  109. {
  110. tor_mutex_acquire(rng_mutex);
  111. while (n) {
  112. size_t n_to_copy = MIN(prefilled_rng_buflen - prefilled_rng_idx, n);
  113. memcpy(out, prefilled_rng_buffer + prefilled_rng_idx, n_to_copy);
  114. out += n_to_copy;
  115. n -= n_to_copy;
  116. prefilled_rng_idx += n_to_copy;
  117. if (prefilled_rng_idx == prefilled_rng_buflen) {
  118. prefilled_rng_idx = 0;
  119. }
  120. }
  121. tor_mutex_release(rng_mutex);
  122. }
  123. /**
  124. * Replace our crypto_rand() prng with a variant that yields output
  125. * from a buffer. If it reaches the end of the buffer, it starts over.
  126. **/
  127. void
  128. testing_enable_prefilled_rng(const void *buffer, size_t buflen)
  129. {
  130. tor_assert(buflen > 0);
  131. rng_mutex = tor_mutex_new();
  132. prefilled_rng_buffer = tor_memdup(buffer, buflen);
  133. prefilled_rng_buflen = buflen;
  134. prefilled_rng_idx = 0;
  135. MOCK(crypto_rand, crypto_rand_prefilled);
  136. }
  137. /**
  138. * Reset the position in the prefilled RNG buffer to the start.
  139. */
  140. void
  141. testing_prefilled_rng_reset(void)
  142. {
  143. tor_mutex_acquire(rng_mutex);
  144. prefilled_rng_idx = 0;
  145. tor_mutex_release(rng_mutex);
  146. }
  147. /**
  148. * Undo the overrides for our PRNG. To be used at the end of testing.
  149. **/
  150. void
  151. testing_disable_rng_override(void)
  152. {
  153. crypto_xof_free(rng_xof);
  154. tor_free(prefilled_rng_buffer);
  155. UNMOCK(crypto_rand);
  156. tor_mutex_free(rng_mutex);
  157. }