]> git.ipfire.org Git - thirdparty/tor.git/commitdiff
Merge remote-tracking branch 'public/feature17694_strongest_027'
authorNick Mathewson <nickm@torproject.org>
Thu, 10 Dec 2015 14:02:10 +0000 (09:02 -0500)
committerNick Mathewson <nickm@torproject.org>
Thu, 10 Dec 2015 14:02:10 +0000 (09:02 -0500)
1  2 
src/common/crypto.c
src/common/crypto.h

index 5569ec78b68099a7a0d37bff46f7cc6a505224b2,189794677aa946f44bba50aab80d67017b9ba19e..816423aa857ac60583e1c6ca542d0eb217d7cf44
@@@ -2476,55 -2337,46 +2476,92 @@@ crypto_strongest_rand_fallback(uint8_t 
  #endif
  }
  
- crypto_strongest_rand(uint8_t *out, size_t out_len)
 +/** Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
 + * storing it into <b>out</b>. Return 0 on success, -1 on failure.  A maximum
 + * request size of 256 bytes is imposed.
 + */
 +int
++crypto_strongest_rand_raw(uint8_t *out, size_t out_len)
 +{
 +  static const size_t sanity_min_size = 16;
 +  static const int max_attempts = 3;
 +  tor_assert(out_len <= MAX_STRONGEST_RAND_SIZE);
 +
 +  /* For buffers >= 16 bytes (128 bits), we sanity check the output by
 +   * zero filling the buffer and ensuring that it actually was at least
 +   * partially modified.
 +   *
 +   * Checking that any individual byte is non-zero seems like it would
 +   * fail too often (p = out_len * 1/256) for comfort, but this is an
 +   * "adjust according to taste" sort of check.
 +   */
 +  memwipe(out, 0, out_len);
 +  for (int i = 0; i < max_attempts; i++) {
 +    /* Try to use the syscall/OS favored mechanism to get strong entropy. */
 +    if (crypto_strongest_rand_syscall(out, out_len) != 0) {
 +      /* Try to use the less-favored mechanism to get strong entropy. */
 +      if (crypto_strongest_rand_fallback(out, out_len) != 0) {
 +        /* Welp, we tried.  Hopefully the calling code terminates the process
 +         * since we're basically boned without good entropy.
 +         */
 +        log_warn(LD_CRYPTO,
 +                 "Cannot get strong entropy: no entropy source found.");
 +        return -1;
 +      }
 +    }
 +
 +    if ((out_len < sanity_min_size) || !tor_mem_is_zero((char*)out, out_len))
 +      return 0;
 +  }
 +
 +  /* We tried max_attempts times to fill a buffer >= 128 bits long,
 +   * and each time it returned all '0's.  Either the system entropy
 +   * source is busted, or the user should go out and buy a ticket to
 +   * every lottery on the planet.
 +   */
 +  log_warn(LD_CRYPTO, "Strong OS entropy returned all zero buffer.");
 +  return -1;
 +}
 +
+ /** Try to get <b>out_len</b> bytes of the strongest entropy we can generate,
+  * storing it into <b>out</b>.
+  */
+ void
+ crypto_strongest_rand(uint8_t *out, size_t out_len)
+ {
+   const unsigned DLEN = SHA512_DIGEST_LENGTH;
+   /* We're going to hash DLEN bytes from the system RNG together with some
+    * bytes from the openssl PRNG, in order to yield DLEN bytes.
+    */
+   uint8_t inp[DLEN*2];
+   uint8_t tmp[DLEN];
+   tor_assert(out);
+   while (out_len) {
+     crypto_rand((char*) inp, DLEN);
+     if (crypto_strongest_rand_raw(inp+DLEN, DLEN) < 0) {
+       log_err(LD_CRYPTO, "Failed to load strong entropy when generating an "
+               "important key. Exiting.");
+       /* Die with an assertion so we get a stack trace. */
+       tor_assert(0);
+     }
+     if (out_len >= DLEN) {
+       SHA512(inp, sizeof(inp), out);
+       out += DLEN;
+       out_len -= DLEN;
+     } else {
+       SHA512(inp, sizeof(inp), tmp);
+       memcpy(out, tmp, out_len);
+       out += DLEN;
+       out_len -= DLEN;
+       break;
+     }
+   }
+   memwipe(tmp, 0, sizeof(tmp));
+   memwipe(inp, 0, sizeof(inp));
+ }
  /** Seed OpenSSL's random number generator with bytes from the operating
 - * system.  <b>startup</b> should be true iff we have just started Tor and
 - * have not yet allocated a bunch of fds.  Return 0 on success, -1 on failure.
 + * system.  Return 0 on success, -1 on failure.
   */
  int
  crypto_seed_rng(void)
Simple merge