[or-cvs] [tor/master] Add support for dynamic OpenSSL hardware crypto acceleration engines.

Nick Mathewson nickm at seul.org
Sun May 31 17:38:00 UTC 2009


Author: Martin Peck <coder at peertech.org>
Date: Sat, 23 May 2009 16:42:44 -0700
Subject: Add support for dynamic OpenSSL hardware crypto acceleration engines.
Commit: 7703b887f5db0d8d62e9eb87305bb8e2113276f1

---
 src/common/crypto.c      |   59 ++++++++++++++++++++++++++++++++++++---------
 src/common/crypto.h      |    4 ++-
 src/common/tortls.c      |    1 -
 src/or/config.c          |   19 ++++++++++++--
 src/or/main.c            |    4 ++-
 src/or/or.h              |    2 +
 src/or/router.c          |    4 ++-
 src/or/test.c            |    2 +-
 src/tools/tor-checkkey.c |    2 +-
 src/tools/tor-gencert.c  |    2 +-
 10 files changed, 77 insertions(+), 22 deletions(-)

diff --git a/src/common/crypto.c b/src/common/crypto.c
index bc7eb0c..7b5743f 100644
--- a/src/common/crypto.c
+++ b/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);
   }
diff --git a/src/common/crypto.h b/src/common/crypto.h
index dd353ef..fa6735d 100644
--- a/src/common/crypto.h
+++ b/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);
 
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 581b358..106a9d4 100644
--- a/src/common/tortls.c
+++ b/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;
   }
 }
diff --git a/src/or/config.c b/src/or/config.c
index a4461a6..0d17667 100644
--- a/src/or/config.c
+++ b/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;
   }
 
diff --git a/src/or/main.c b/src/or/main.c
index b151b1f..456d9fa 100644
--- a/src/or/main.c
+++ b/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;
   }
diff --git a/src/or/or.h b/src/or/or.h
index d5b36c8..7758230 100644
--- a/src/or/or.h
+++ b/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? */
diff --git a/src/or/router.c b/src/or/router.c
index da922b7..7a567be 100644
--- a/src/or/router.c
+++ b/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;
   }
diff --git a/src/or/test.c b/src/or/test.c
index 6ce0aae..ef61e62 100644
--- a/src/or/test.c
+++ b/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();
diff --git a/src/tools/tor-checkkey.c b/src/tools/tor-checkkey.c
index b29b52d..6416dbf 100644
--- a/src/tools/tor-checkkey.c
+++ b/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;
   }
diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c
index 4971668..d2ea4eb 100644
--- a/src/tools/tor-gencert.c
+++ b/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;
   }
-- 
1.5.6.5




More information about the tor-commits mailing list