From a53ecc94f9cda30d4c82b51c5d9ff32c879017ca Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Fri, 7 Oct 2005 19:03:09 +0000 Subject: [PATCH] Add half our entropy from RAND_poll in OpenSSL. These know how to use egd (if present) openbsd weirdness (if present), vms/os2 weirdness (if we ever port there), and more in the future. svn:r5215 --- src/common/crypto.c | 63 ++++++++++++++++++++++++++++++--------------- 1 file changed, 42 insertions(+), 21 deletions(-) diff --git a/src/common/crypto.c b/src/common/crypto.c index 2c5b96f371..8a9ba8324c 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1575,42 +1575,63 @@ crypto_dh_free(crypto_dh_env_t *dh) /* random numbers */ +/* This is how much entropy OpenSSL likes to add right now, so maybe it will + * work for us too. */ +#define ADD_ENTROPY 32 + +/* Use RAND_poll if openssl is 0.9.6 release or later. (The "f" means + "release".) */ +#define USE_RAND_POLL (OPENSSL_VERSION_NUMBER >= 0x0090600fl) + /** Seed OpenSSL's random number generator with bytes from the * operating system. Return 0 on success, -1 on failure. */ int crypto_seed_rng(void) { - char buf[64]; + char buf[ADD_ENTROPY]; + int rand_poll_status; + + /* local variables */ #ifdef MS_WINDOWS static int provider_set = 0; static HCRYPTPROV provider; - - if (!provider_set) { - if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { - if (GetLastError() != NTE_BAD_KEYSET) { - log_fn(LOG_ERR,"Can't get CryptoAPI provider [1]"); - return -1; - } - } - provider_set = 1; - } - if (!CryptGenRandom(provider, sizeof(buf), buf)) { - log_fn(LOG_ERR,"Can't get entropy from CryptoAPI."); - return -1; - } - RAND_seed(buf, sizeof(buf)); - /* And add the current screen state to the entropy pool for - * good measure. */ - RAND_screen(); - return 0; #else static const char *filenames[] = { "/dev/srandom", "/dev/urandom", "/dev/random", NULL }; int fd; int i, n; +#endif +#if USE_RAND_POLL + /* OpenSSL 0.9.6 adds a RAND_poll function that knows about more kinds of + * entropy than we do. We'll try calling that, *and* calling our own entropy + * functions. If one succeeds, we'll accept the RNG as seeded. */ + rand_poll_status = RAND_poll(); + if (rand_poll_status == 0) + log_fn(LOG_WARN, "RAND_poll() failed."); +#else + rand_poll_status = 0; +#endif + +#ifdef MS_WINDOWS + if (!provider_set) { + if (!CryptAcquireContext(&provider, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) { + if (GetLastError() != NTE_BAD_KEYSET) { + log_fn(LOG_ERR,"Can't get CryptoAPI provider [1]"); + return rand_poll_status ? 0 : -1; + } + } + provider_set = 1; + } + if (!CryptGenRandom(provider, sizeof(buf), buf)) { + log_fn(LOG_ERR,"Can't get entropy from CryptoAPI."); + return rand_poll_status ? 0 : -1; + } + RAND_seed(buf, sizeof(buf)); + return 0; +#else for (i = 0; filenames[i]; ++i) { fd = open(filenames[i], O_RDONLY, 0); if (fd<0) continue; @@ -1626,7 +1647,7 @@ crypto_seed_rng(void) } log_fn(LOG_WARN, "Cannot seed RNG -- no entropy source found."); - return -1; + return rand_poll_status ? 0 : -1; #endif }