Browse Source

Add support for dynamic OpenSSL hardware crypto acceleration engines.

Martin Peck 16 years ago
parent
commit
7703b887f5
10 changed files with 77 additions and 22 deletions
  1. 47 12
      src/common/crypto.c
  2. 3 1
      src/common/crypto.h
  3. 0 1
      src/common/tortls.c
  4. 16 3
      src/or/config.c
  5. 3 1
      src/or/main.c
  6. 2 0
      src/or/or.h
  7. 3 1
      src/or/router.c
  8. 1 1
      src/or/test.c
  9. 1 1
      src/tools/tor-checkkey.c
  10. 1 1
      src/tools/tor-gencert.c

+ 47 - 12
src/common/crypto.c

@@ -27,6 +27,7 @@
 #include <openssl/rsa.h>
 #include <openssl/pem.h>
 #include <openssl/evp.h>
+#include <openssl/engine.h>
 #include <openssl/rand.h>
 #include <openssl/opensslv.h>
 #include <openssl/bn.h>
@@ -166,36 +167,70 @@ log_engine(const char *fn, ENGINE *e)
   }
 }
 
+/** Try to load an engine in a shared library via fully qualified path.
+ */
+static ENGINE *
+try_load_engine(const char *path, const char *engine)
+{
+  ENGINE *e = ENGINE_by_id("dynamic");
+  if (e) {
+    if (!ENGINE_ctrl_cmd_string(e, "ID", engine, 0) ||
+        !ENGINE_ctrl_cmd_string(e, "DIR_LOAD", "2", 0) ||
+        !ENGINE_ctrl_cmd_string(e, "DIR_ADD", path, 0) ||
+        !ENGINE_ctrl_cmd_string(e, "LOAD", NULL, 0)) {
+      ENGINE_free(e);
+      e = NULL;
+    }
+  }
+  return e;
+}
+
 /** Initialize the crypto library.  Return 0 on success, -1 on failure.
  */
 int
-crypto_global_init(int useAccel)
+crypto_global_init(int useAccel, const char *accelName, const char *accelDir)
 {
   if (!_crypto_global_initialized) {
     ERR_load_crypto_strings();
     OpenSSL_add_all_algorithms();
     _crypto_global_initialized = 1;
     setup_openssl_threading();
-    /* XXX the below is a bug, since we can't know if we're supposed
-     * to be using hardware acceleration or not. we should arrange
-     * for this function to be called before init_keys. But make it
-     * not complain loudly, at least until we make acceleration work. */
-    if (useAccel < 0) {
-      log_info(LD_CRYPTO, "Initializing OpenSSL via tor_tls_init().");
-    }
     if (useAccel > 0) {
+      ENGINE *e = NULL;
       log_info(LD_CRYPTO, "Initializing OpenSSL engine support.");
       ENGINE_load_builtin_engines();
-      if (!ENGINE_register_all_complete())
-        return -1;
-
-      /* XXXX make sure this isn't leaking. */
+      ENGINE_register_all_complete();
+      if (accelName) {
+        if (accelDir) {
+          log_info(LD_CRYPTO, "Trying to load dynamic OpenSSL engine \"%s\""
+                   " via path \"%s\".", accelName, accelDir);
+          e = try_load_engine(accelName, accelDir);
+        } else {
+          log_info(LD_CRYPTO, "Initializing dynamic OpenSSL engine \"%s\""
+                   " acceleration support.", accelName);
+          e = ENGINE_by_id(accelName);
+        }
+        if (!e) {
+          log_warn(LD_CRYPTO, "Unable to load dynamic OpenSSL engine \"%s\".",
+                   accelName);
+        } else {
+          log_info(LD_CRYPTO, "Loaded dynamic OpenSSL engine \"%s\".",
+                   accelName);
+        }
+      }
+      if (e) {
+        log_info(LD_CRYPTO, "Loaded OpenSSL hardware acceleration engine,"
+                 " setting default ciphers.");
+        ENGINE_set_default(e, ENGINE_METHOD_ALL);
+      }
       log_engine("RSA", ENGINE_get_default_RSA());
       log_engine("DH", ENGINE_get_default_DH());
       log_engine("RAND", ENGINE_get_default_RAND());
       log_engine("SHA1", ENGINE_get_digest_engine(NID_sha1));
       log_engine("3DES", ENGINE_get_cipher_engine(NID_des_ede3_ecb));
       log_engine("AES", ENGINE_get_cipher_engine(NID_aes_128_ecb));
+    } else {
+      log_info(LD_CRYPTO, "NOT using OpenSSL engine support.");
     }
     return crypto_seed_rng(1);
   }

+ 3 - 1
src/common/crypto.h

@@ -55,7 +55,9 @@ typedef struct crypto_digest_env_t crypto_digest_env_t;
 typedef struct crypto_dh_env_t crypto_dh_env_t;
 
 /* global state */
-int crypto_global_init(int hardwareAccel);
+int crypto_global_init(int hardwareAccel,
+                       const char *accelName,
+                       const char *accelPath);
 void crypto_thread_cleanup(void);
 int crypto_global_cleanup(void);
 

+ 0 - 1
src/common/tortls.c

@@ -308,7 +308,6 @@ tor_tls_init(void)
   if (!tls_library_is_initialized) {
     SSL_library_init();
     SSL_load_error_strings();
-    crypto_global_init(-1);
     tls_library_is_initialized = 1;
   }
 }

+ 16 - 3
src/or/config.c

@@ -222,6 +222,8 @@ static config_var_t _option_vars[] = {
 #endif
   OBSOLETE("Group"),
   V(HardwareAccel,               BOOL,     "0"),
+  V(AccelName,                   STRING,   NULL),
+  V(AccelDir,                    FILENAME, NULL),
   V(HashedControlPassword,       LINELIST, NULL),
   V(HidServDirectoryV2,          BOOL,     "1"),
   VAR("HiddenServiceDir",    LINELIST_S, RendConfigLines,    NULL),
@@ -444,6 +446,10 @@ static config_var_description_t options_description[] = {
    * FetchUselessDescriptors */
   { "HardwareAccel", "If set, Tor tries to use hardware crypto accelerators "
     "when it can." },
+  { "AccelName", "If set, try to use hardware crypto accelerator with this "
+    "specific ID." },
+  { "AccelDir", "If set, look in this directory for the dynamic hardware "
+    "engine in addition to OpenSSL default path." },
   /* HashedControlPassword */
   { "HTTPProxy", "Force Tor to make all HTTP directory requests through this "
     "host:port (or host:80 if port is not set)." },
@@ -3602,6 +3608,11 @@ options_validate(or_options_t *old_options, or_options_t *options,
                         "testing Tor network!");
   }
 
+  if (options->AccelName && !options->HardwareAccel)
+    options->HardwareAccel = 1;
+  if (options->AccelDir && !options->AccelName)
+    REJECT("Can't use hardware crypto accelerator dir without engine name.");
+
   return 0;
 #undef REJECT
 #undef COMPLAIN
@@ -3659,9 +3670,11 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val,
     return -1;
   }
 
-  if (old->HardwareAccel != new_val->HardwareAccel) {
-    *msg = tor_strdup("While Tor is running, changing HardwareAccel is "
-                      "not allowed.");
+  if ((old->HardwareAccel != new_val->HardwareAccel)
+      || (old->AccelName != new_val->AccelName)
+      || (old->AccelDir != new_val->AccelDir)) {
+    *msg = tor_strdup("While Tor is running, changing OpenSSL hardware "
+                      "acceleration engine is not allowed.");
     return -1;
   }
 

+ 3 - 1
src/or/main.c

@@ -1818,7 +1818,9 @@ tor_init(int argc, char *argv[])
              "and you probably shouldn't.");
 #endif
 
-  if (crypto_global_init(get_options()->HardwareAccel)) {
+  if (crypto_global_init(get_options()->HardwareAccel,
+                         get_options()->AccelName,
+                         get_options()->AccelDir)) {
     log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
     return -1;
   }

+ 2 - 0
src/or/or.h

@@ -2422,6 +2422,8 @@ typedef struct {
                   * log whether it was DNS-leaking or not? */
   int HardwareAccel; /**< Boolean: Should we enable OpenSSL hardware
                       * acceleration where available? */
+  char *AccelName; /**< Optional hardware acceleration engine name. */
+  char *AccelDir; /**< Optional hardware acceleration engine search dir. */
   int UseEntryGuards; /**< Boolean: Do we try to enter from a smallish number
                        * of fixed nodes? */
   int NumEntryGuards; /**< How many entry guards do we try to establish? */

+ 3 - 1
src/or/router.c

@@ -442,7 +442,9 @@ init_keys(void)
     key_lock = tor_mutex_new();
 
   /* There are a couple of paths that put us here before */
-  if (crypto_global_init(get_options()->HardwareAccel)) {
+  if (crypto_global_init(get_options()->HardwareAccel,
+                         get_options()->AccelName,
+                         get_options()->AccelDir)) {
     log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting.");
     return -1;
   }

+ 1 - 1
src/or/test.c

@@ -4793,7 +4793,7 @@ main(int c, char**v)
   }
 
   options->command = CMD_RUN_UNITTESTS;
-  crypto_global_init(0);
+  crypto_global_init(0, NULL, NULL);
   rep_hist_init();
   network_init();
   setup_directory();

+ 1 - 1
src/tools/tor-checkkey.c

@@ -29,7 +29,7 @@ int main(int c, char **v)
     return 1;
   }
 
-  if (crypto_global_init(0)) {
+  if (crypto_global_init(0, NULL, NULL)) {
     fprintf(stderr, "Couldn't initialize crypto library.\n");
     return 1;
   }

+ 1 - 1
src/tools/tor-gencert.c

@@ -496,7 +496,7 @@ main(int argc, char **argv)
   init_logging();
 
   /* Don't bother using acceleration. */
-  if (crypto_global_init(0)) {
+  if (crypto_global_init(0, NULL, NULL)) {
     fprintf(stderr, "Couldn't initialize crypto library.\n");
     return 1;
   }