Commit 2259de0d authored by Nick Mathewson's avatar Nick Mathewson 🎡
Browse files

Always hash crypto_strongest_rand() along with some prng

(before using it for anything besides feeding the PRNG)

Part of #17694
parent 943369f9
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.
\ No newline at end of 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));
}
......
......@@ -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);
......
......@@ -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];
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));
if (extra_strong)
crypto_strongest_rand(out, CURVE25519_SECKEY_LEN);
else
crypto_rand((char*)out, CURVE25519_SECKEY_LEN);
return 0;
}
......
......@@ -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);
......
......@@ -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);
......
/* Added for Tor. */
#include "crypto.h"
#define randombytes(b, n) \
(crypto_strongest_rand((b), (n)))
(crypto_strongest_rand((b), (n)), 0)
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment