Merge remote-tracking branch 'public/feature17694_strongest_027'

This commit is contained in:
Nick Mathewson 2015-12-10 09:02:10 -05:00
commit 7186e2a943
7 changed files with 58 additions and 18 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

@ -2481,7 +2481,7 @@ crypto_strongest_rand_fallback(uint8_t *out, size_t out_len)
* request size of 256 bytes is imposed.
*/
int
crypto_strongest_rand(uint8_t *out, size_t out_len)
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;
@ -2523,6 +2523,43 @@ crypto_strongest_rand(uint8_t *out, size_t out_len)
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. Return 0 on success, -1 on failure.
*/
@ -2539,7 +2576,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));
}
@ -2580,6 +2617,9 @@ crypto_rand_unmocked(char *to, size_t n)
tor_assert(n < INT_MAX);
tor_assert(to);
r = RAND_bytes((unsigned char*)to, (int)n);
/* We consider a PRNG failure non-survivable. Let's assert so that we get a
* stack trace about where it happened.
*/
tor_assert(r >= 0);
}

View File

@ -273,7 +273,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)