aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/crypto.c44
-rw-r--r--src/common/crypto.h2
-rw-r--r--src/common/crypto_curve25519.c17
-rw-r--r--src/common/crypto_ed25519.c4
-rw-r--r--src/ext/ed25519/donna/ed25519_tor.c3
-rw-r--r--src/ext/ed25519/ref10/randombytes.h2
6 files changed, 53 insertions, 19 deletions
diff --git a/src/common/crypto.c b/src/common/crypto.c
index 5569ec78b6..816423aa85 100644
--- a/src/common/crypto.c
+++ b/src/common/crypto.c
@@ -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);
}
diff --git a/src/common/crypto.h b/src/common/crypto.h
index 9b922ff818..0fba958f8d 100644
--- a/src/common/crypto.h
+++ b/src/common/crypto.h
@@ -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);
diff --git a/src/common/crypto_curve25519.c b/src/common/crypto_curve25519.c
index 00302a2ff0..2002483265 100644
--- a/src/common/crypto_curve25519.c
+++ b/src/common/crypto_curve25519.c
@@ -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;
}
diff --git a/src/common/crypto_ed25519.c b/src/common/crypto_ed25519.c
index 1749efc34c..41ec486f0a 100644
--- a/src/common/crypto_ed25519.c
+++ b/src/common/crypto_ed25519.c
@@ -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);
diff --git a/src/ext/ed25519/donna/ed25519_tor.c b/src/ext/ed25519/donna/ed25519_tor.c
index 12493f7d14..ac726ba045 100644
--- a/src/ext/ed25519/donna/ed25519_tor.c
+++ b/src/ext/ed25519/donna/ed25519_tor.c
@@ -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);
diff --git a/src/ext/ed25519/ref10/randombytes.h b/src/ext/ed25519/ref10/randombytes.h
index fc709fcefc..8bf31631f0 100644
--- a/src/ext/ed25519/ref10/randombytes.h
+++ b/src/ext/ed25519/ref10/randombytes.h
@@ -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)