Always hash crypto_strongest_rand() along with some prng

(before using it for anything besides feeding the PRNG)

Part of #17694
This commit is contained in:
Nick Mathewson 2015-12-08 10:54:42 -05:00
parent 943369f927
commit 2259de0de7
7 changed files with 58 additions and 20 deletions

View File

@ -0,0 +1,6 @@
o Minor features (security):
- Never use the system entropy output directly for anything besides
seeding the PRNG. When we want to generate important keys, instead
of using system entropy directly, hash it with the PRNG stream.
This may help resist certain attacks based on broken OS entropy
implementations. Closes part of ticket 17694.

View File

@ -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));
}

View File

@ -262,7 +262,7 @@ int crypto_expand_key_material_rfc5869_sha256(
int crypto_seed_rng(void) ATTR_WUR;
MOCK_DECL(void,crypto_rand,(char *to, size_t n));
void crypto_rand_unmocked(char *to, size_t n);
int crypto_strongest_rand(uint8_t *out, size_t out_len);
void crypto_strongest_rand(uint8_t *out, size_t out_len);
int crypto_rand_int(unsigned int max);
int crypto_rand_int_range(unsigned int min, unsigned int max);
uint64_t crypto_rand_uint64_range(uint64_t min, uint64_t max);

View File

@ -111,18 +111,11 @@ curve25519_public_key_is_ok(const curve25519_public_key_t *key)
int
curve25519_rand_seckey_bytes(uint8_t *out, int extra_strong)
{
uint8_t k_tmp[CURVE25519_SECKEY_LEN];
if (extra_strong)
crypto_strongest_rand(out, CURVE25519_SECKEY_LEN);
else
crypto_rand((char*)out, CURVE25519_SECKEY_LEN);
crypto_rand((char*)out, CURVE25519_SECKEY_LEN);
if (extra_strong && !crypto_strongest_rand(k_tmp, CURVE25519_SECKEY_LEN)) {
/* If they asked for extra-strong entropy and we have some, use it as an
* HMAC key to improve not-so-good entropy rather than using it directly,
* just in case the extra-strong entropy is less amazing than we hoped. */
crypto_hmac_sha256((char*) out,
(const char *)k_tmp, sizeof(k_tmp),
(const char *)out, CURVE25519_SECKEY_LEN);
}
memwipe(k_tmp, 0, sizeof(k_tmp));
return 0;
}

View File

@ -107,7 +107,9 @@ ed25519_secret_key_generate(ed25519_secret_key_t *seckey_out,
{
int r;
uint8_t seed[32];
if (! extra_strong || crypto_strongest_rand(seed, sizeof(seed)) < 0)
if (extra_strong)
crypto_strongest_rand(seed, sizeof(seed));
else
crypto_rand((char*)seed, sizeof(seed));
r = get_ed_impl()->seckey_expand(seckey_out->seckey, seed);

View File

@ -148,8 +148,7 @@ ed25519_donna_seckey(unsigned char *sk)
{
ed25519_secret_key seed;
if (crypto_strongest_rand(seed, 32))
return -1;
crypto_strongest_rand(seed, 32);
ed25519_extsk(sk, seed);

View File

@ -1,4 +1,4 @@
/* Added for Tor. */
#include "crypto.h"
#define randombytes(b, n) \
(crypto_strongest_rand((b), (n)))
(crypto_strongest_rand((b), (n)), 0)