summaryrefslogtreecommitdiff
path: root/src/lib/crypt_ops
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2019-03-18 12:03:48 -0400
committerDavid Goulet <dgoulet@torproject.org>2019-04-30 11:11:39 -0400
commit587a525cc5aedaee51fff33a78f004f103a4e0c4 (patch)
tree19b03466d047f23ab6696b8f66b494116d7b29b7 /src/lib/crypt_ops
parente66b5153bd5feeb16bb18b735745d37310ae63fa (diff)
downloadtor-587a525cc5aedaee51fff33a78f004f103a4e0c4.tar.gz
tor-587a525cc5aedaee51fff33a78f004f103a4e0c4.zip
Add improved debugging support to crypto_rand_fast code.
Diffstat (limited to 'src/lib/crypt_ops')
-rw-r--r--src/lib/crypt_ops/crypto_rand.h4
-rw-r--r--src/lib/crypt_ops/crypto_rand_fast.c46
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 c51d6a4480..528f238fa5 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 dd9bf051c8..b71ade81bd 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