diff options
author | Nick Mathewson <nickm@torproject.org> | 2015-12-08 10:54:42 -0500 |
---|---|---|
committer | Nick Mathewson <nickm@torproject.org> | 2015-12-08 10:54:42 -0500 |
commit | 2259de0de726f3f617b2451d64f72f0d4d6bc0ae (patch) | |
tree | 6aeca7dc70a1231f8fd413d9572adbdf0a5c228f /src/common/crypto.c | |
parent | 943369f927967268cacd2067ccae0bc5f1c5835e (diff) | |
download | tor-2259de0de726f3f617b2451d64f72f0d4d6bc0ae.tar.gz tor-2259de0de726f3f617b2451d64f72f0d4d6bc0ae.zip |
Always hash crypto_strongest_rand() along with some prng
(before using it for anything besides feeding the PRNG)
Part of #17694
Diffstat (limited to 'src/common/crypto.c')
-rw-r--r-- | src/common/crypto.c | 46 |
1 files changed, 42 insertions, 4 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c index 9669493a83..675fe7a8f0 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -2280,10 +2280,13 @@ crypto_seed_weak_rng(tor_weak_rng_t *rng) } /** Try to get <b>out_len</b> bytes of the strongest entropy we can generate, - * storing it into <b>out</b>. + * storing it into <b>out</b>. Return 0 on success, -1 on failure. + * + * (You should almost never call this directly unless you are seeding a PRNG; + * use crypto_strongest_rand() instead.) */ -int -crypto_strongest_rand(uint8_t *out, size_t out_len) +static int +crypto_strongest_rand_raw(uint8_t *out, size_t out_len) { #ifdef _WIN32 static int provider_set = 0; @@ -2334,6 +2337,41 @@ crypto_strongest_rand(uint8_t *out, size_t out_len) #endif } +/** 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; + uint8_t inp[DLEN*2]; + uint8_t tmp[DLEN]; + tor_assert(out); + while (out_len) { + crypto_rand((char*) inp+DLEN, DLEN); + if (crypto_strongest_rand_raw(inp, DLEN) < 0) { + log_err(LD_CRYPTO, "Failed to load strong entropy when generating an " + "important key. Exiting."); + 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. @@ -2351,7 +2389,7 @@ crypto_seed_rng(void) if (rand_poll_ok == 0) log_warn(LD_CRYPTO, "RAND_poll() failed."); - load_entropy_ok = !crypto_strongest_rand(buf, sizeof(buf)); + load_entropy_ok = !crypto_strongest_rand_raw(buf, sizeof(buf)); if (load_entropy_ok) { RAND_seed(buf, sizeof(buf)); } |