commit 587a525cc5aedaee51fff33a78f004f103a4e0c4 Author: Nick Mathewson nickm@torproject.org Date: Mon Mar 18 12:03:48 2019 -0400
Add improved debugging support to crypto_rand_fast code. --- src/lib/crypt_ops/crypto_rand.h | 4 ++++ src/lib/crypt_ops/crypto_rand_fast.c | 46 +++++++++++++++++++++++++++++++++--- 2 files changed, 47 insertions(+), 3 deletions(-)
diff --git a/src/lib/crypt_ops/crypto_rand.h b/src/lib/crypt_ops/crypto_rand.h index c51d6a448..528f238fa 100644 --- a/src/lib/crypt_ops/crypto_rand.h +++ b/src/lib/crypt_ops/crypto_rand.h @@ -92,6 +92,10 @@ void crypto_rand_fast_shutdown(void); #if defined(TOR_UNIT_TESTS) /* Used for white-box testing */ size_t crypto_fast_rng_get_bytes_used_per_stream(void); +/* For deterministic prng implementations */ +void crypto_fast_rng_disable_reseed(crypto_fast_rng_t *rng); +/* To override the prng for testing. */ +crypto_fast_rng_t *crypto_replace_thread_fast_rng(crypto_fast_rng_t *rng); #endif
#ifdef CRYPTO_RAND_PRIVATE diff --git a/src/lib/crypt_ops/crypto_rand_fast.c b/src/lib/crypt_ops/crypto_rand_fast.c index dd9bf051c..b71ade81b 100644 --- a/src/lib/crypt_ops/crypto_rand_fast.c +++ b/src/lib/crypt_ops/crypto_rand_fast.c @@ -95,8 +95,13 @@ CTASSERT(KEY_BITS == 128 || KEY_BITS == 192 || KEY_BITS == 256);
struct crypto_fast_rng_t { /** How many more fills does this buffer have before we should mix - * in the output of crypto_rand()? */ - uint16_t n_till_reseed; + * in the output of crypto_strongest_rand()? + * + * This value may be negative if unit tests are enabled. If so, it + * indicates that we should never mix in extra data from + * crypto_strongest_rand(). + */ + int16_t n_till_reseed; /** How many bytes are remaining in cbuf.bytes? */ uint16_t bytes_left; #ifdef CHECK_PID @@ -181,6 +186,18 @@ crypto_fast_rng_new_from_seed(const uint8_t *seed) return result; }
+#ifdef TOR_UNIT_TESTS +/** + * Unit tests only: prevent a crypto_fast_rng_t from ever mixing in more + * entropy. + */ +void +crypto_fast_rng_disable_reseed(crypto_fast_rng_t *rng) +{ + rng->n_till_reseed = -1; +} +#endif + /** * Helper: create a crypto_cipher_t object from SEED_LEN bytes of * input. The first KEY_LEN bytes are used as the stream cipher's key, @@ -222,10 +239,19 @@ crypto_fast_rng_add_entopy(crypto_fast_rng_t *rng) static void crypto_fast_rng_refill(crypto_fast_rng_t *rng) { - if (rng->n_till_reseed-- == 0) { + rng->n_till_reseed--; + if (rng->n_till_reseed == 0) { /* It's time to reseed the RNG. */ crypto_fast_rng_add_entopy(rng); rng->n_till_reseed = RESEED_AFTER; + } else if (rng->n_till_reseed < 0) { +#ifdef TOR_UNIT_TESTS + /* Reseeding is disabled for testing; never do it on this prng. */ + rng->n_till_reseed = -1; +#else + /* If testing is disabled, this shouldn't be able to become negative. */ + tor_assert_unreached(); +#endif } /* Now fill rng->buf with output from our stream cipher, initialized from * that seed value. */ @@ -371,6 +397,20 @@ destroy_thread_fast_rng(void) tor_threadlocal_set(&thread_rng, NULL); }
+#ifdef TOR_UNIT_TESTS +/** + * Replace the current thread's rng with <b>rng</b>. For use by the + * unit tests only. Returns the previous thread rng. + **/ +crypto_fast_rng_t * +crypto_replace_thread_fast_rng(crypto_fast_rng_t *rng) +{ + crypto_fast_rng_t *old_rng = tor_threadlocal_get(&thread_rng); + tor_threadlocal_set(&thread_rng, rng); + return old_rng; +} +#endif + /** * Initialize the global thread-local key that will be used to keep track * of per-thread fast RNG instances. Called from the crypto subsystem's
tor-commits@lists.torproject.org