Преглед на файлове

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.
Nick Mathewson преди 11 години
родител
ревизия
d3fb846d8c
променени са 3 файла, в които са добавени 52 реда и са изтрити 10 реда
  1. 44 10
      src/common/crypto.c
  2. 1 0
      src/common/crypto.h
  3. 7 0
      src/or/main.c

+ 44 - 10
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;
 }

+ 1 - 0
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);

+ 7 - 0
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. */