}
}
+/** 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;
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 &&
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;
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;
}
/* 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. */