diff --git a/src/common/crypto.c b/src/common/crypto.c index 9bdb1f41fa..13095ad79d 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -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? */ static int crypto_global_initialized_ = 0; @@ -242,15 +245,31 @@ crypto_openssl_get_header_version_str(void) 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 -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(); OpenSSL_add_all_algorithms(); - crypto_global_initialized_ = 1; + setup_openssl_threading(); 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_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) { #ifdef DISABLE_ENGINES (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."); } - 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()); + if (crypto_force_rand_ssleay()) { + if (crypto_seed_rng(1) < 0) + return -1; } evaluate_evp_for_aes(-1); evaluate_ctr_for_aes(); - return crypto_seed_rng(1); } return 0; } diff --git a/src/common/crypto.h b/src/common/crypto.h index 6ce3697c92..79a8a1bda4 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -110,6 +110,7 @@ typedef struct crypto_dh_t crypto_dh_t; /* global state */ const char * crypto_openssl_get_version_str(void); const char * crypto_openssl_get_header_version_str(void); +int crypto_early_init(void); int crypto_global_init(int hardwareAccel, const char *accelName, const char *accelPath); diff --git a/src/or/main.c b/src/or/main.c index a970e35801..526f000012 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2329,6 +2329,13 @@ tor_init(int argc, char *argv[]) /* Have the log set up with our application name. */ tor_snprintf(progname, sizeof(progname), "Tor %s", get_version()); 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. */ rep_hist_init(); /* Initialize the service cache. */