]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Add improved debugging support to crypto_rand_fast code.
authorNick Mathewson <nickm@torproject.org>
Mon, 18 Mar 2019 16:03:48 +0000 (12:03 -0400)
committerDavid Goulet <dgoulet@torproject.org>
Tue, 30 Apr 2019 15:11:39 +0000 (11:11 -0400)
src/lib/crypt_ops/crypto_rand.h
src/lib/crypt_ops/crypto_rand_fast.c

index c51d6a4480222d341949c9f5eb4569bfe239e429..528f238fa52467fcb1445f8f1c9bf0ea42b06f74 100644 (file)
@@ -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
index dd9bf051c81d35cc714343b964f9764758500512..b71ade81bdabc436747ab76f703f5f2f9869747e 100644 (file)
@@ -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