Split crypto_global_init() into pre/post config

It's increasingly apparent that we want to make sure we initialize our
PRNG nice and early, or else OpenSSL will do it for us.  (OpenSSL
doesn't do _too_ bad a job, but it's nice to do it ourselves.)

We'll also need this for making sure we initialize the siphash key
before we do any hashes.
This commit is contained in:
Nick Mathewson 2014-02-12 11:56:29 -05:00
parent 0e97c8e23e
commit d3fb846d8c
3 changed files with 52 additions and 10 deletions

View File

@ -131,6 +131,9 @@ crypto_get_rsa_padding(int padding)
} }
} }
/** Boolean: has OpenSSL's crypto been initialized? */
static int crypto_early_initialized_ = 0;
/** Boolean: has OpenSSL's crypto been initialized? */ /** Boolean: has OpenSSL's crypto been initialized? */
static int crypto_global_initialized_ = 0; static int crypto_global_initialized_ = 0;
@ -242,15 +245,31 @@ crypto_openssl_get_header_version_str(void)
return crypto_openssl_header_version_str; return crypto_openssl_header_version_str;
} }
/** Initialize the crypto library. Return 0 on success, -1 on failure. /** Make sure that openssl is using its default PRNG. Return 1 if we had to
* adjust it; 0 otherwise. */
static int
crypto_force_rand_ssleay(void)
{
if (RAND_get_rand_method() != RAND_SSLeay()) {
log_notice(LD_CRYPTO, "It appears that one of our engines has provided "
"a replacement the OpenSSL RNG. Resetting it to the default "
"implementation.");
RAND_set_rand_method(RAND_SSLeay());
return 1;
}
return 0;
}
/** Initialize the parts of the crypto library that don't depend on
* settings or options. Return 0 on success, -1 on failure.
*/ */
int int
crypto_global_init(int useAccel, const char *accelName, const char *accelDir) crypto_early_init(void)
{ {
if (!crypto_global_initialized_) { if (!crypto_early_initialized_) {
ERR_load_crypto_strings(); ERR_load_crypto_strings();
OpenSSL_add_all_algorithms(); OpenSSL_add_all_algorithms();
crypto_global_initialized_ = 1;
setup_openssl_threading(); setup_openssl_threading();
if (SSLeay() == OPENSSL_VERSION_NUMBER && if (SSLeay() == OPENSSL_VERSION_NUMBER &&
@ -272,6 +291,24 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
crypto_openssl_get_version_str()); crypto_openssl_get_version_str());
} }
crypto_force_rand_ssleay();
if (crypto_seed_rng(1) < 0)
return -1;
}
return 0;
}
/** Initialize the crypto library. Return 0 on success, -1 on failure.
*/
int
crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
{
if (!crypto_global_initialized_) {
crypto_early_init();
crypto_global_initialized_ = 1;
if (useAccel > 0) { if (useAccel > 0) {
#ifdef DISABLE_ENGINES #ifdef DISABLE_ENGINES
(void)accelName; (void)accelName;
@ -335,17 +372,14 @@ crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
log_info(LD_CRYPTO, "NOT using OpenSSL engine support."); log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
} }
if (RAND_get_rand_method() != RAND_SSLeay()) { if (crypto_force_rand_ssleay()) {
log_notice(LD_CRYPTO, "It appears that one of our engines has provided " if (crypto_seed_rng(1) < 0)
"a replacement the OpenSSL RNG. Resetting it to the default " return -1;
"implementation.");
RAND_set_rand_method(RAND_SSLeay());
} }
evaluate_evp_for_aes(-1); evaluate_evp_for_aes(-1);
evaluate_ctr_for_aes(); evaluate_ctr_for_aes();
return crypto_seed_rng(1);
} }
return 0; return 0;
} }

View File

@ -110,6 +110,7 @@ typedef struct crypto_dh_t crypto_dh_t;
/* global state */ /* global state */
const char * crypto_openssl_get_version_str(void); const char * crypto_openssl_get_version_str(void);
const char * crypto_openssl_get_header_version_str(void); const char * crypto_openssl_get_header_version_str(void);
int crypto_early_init(void);
int crypto_global_init(int hardwareAccel, int crypto_global_init(int hardwareAccel,
const char *accelName, const char *accelName,
const char *accelPath); const char *accelPath);

View File

@ -2329,6 +2329,13 @@ tor_init(int argc, char *argv[])
/* Have the log set up with our application name. */ /* Have the log set up with our application name. */
tor_snprintf(progname, sizeof(progname), "Tor %s", get_version()); tor_snprintf(progname, sizeof(progname), "Tor %s", get_version());
log_set_application_name(progname); log_set_application_name(progname);
/* Set up the crypto nice and early */
if (crypto_early_init() < 0) {
log_err(LD_GENERAL, "Unable to initialize the crypto subsystem!");
return 1;
}
/* Initialize the history structures. */ /* Initialize the history structures. */
rep_hist_init(); rep_hist_init();
/* Initialize the service cache. */ /* Initialize the service cache. */