From 7703b887f5db0d8d62e9eb87305bb8e2113276f1 Mon Sep 17 00:00:00 2001 From: Martin Peck Date: Sat, 23 May 2009 16:42:44 -0700 Subject: [PATCH 1/4] Add support for dynamic OpenSSL hardware crypto acceleration engines. --- 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 bc7eb0c6ca..7b5743f64a 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include #include @@ -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 dd353ef030..fa6735d788 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 581b35848a..106a9d40ee 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 a4461a6fe7..0d176670e4 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 b151b1f666..456d9fab16 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 d5b36c85a6..77582309e9 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 da922b7508..7a567be30d 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 6ce0aaeb47..ef61e62ee1 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 b29b52d8db..6416dbfbb3 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 4971668c9f..d2ea4eb109 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; } From 58168322477a9f847c14ac6282218e9f56a37c28 Mon Sep 17 00:00:00 2001 From: Martin Peck Date: Sat, 30 May 2009 13:53:35 -0700 Subject: [PATCH 2/4] Add documentation for new AccelName and AccelDir dynamic hardware acceleration engine options. --- doc/tor.1.in | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/doc/tor.1.in b/doc/tor.1.in index 55f9a8e043..c9b344257d 100644 --- a/doc/tor.1.in +++ b/doc/tor.1.in @@ -354,6 +354,16 @@ If non-zero, try to use crypto hardware acceleration when available. This is untested and probably buggy. (Default: 0) .LP .TP +\fBAccelName \fR\fIEngineName\fP +When using OpenSSL hardware crypto acceleration attempt to load the dynamic +engine of this name. This must be used for any dynamic hardware engine. +.LP +.TP +\fBAccelDir \fR\fIPath\fP +Specify this option if using dynamic hardware acceleration and the engine +implementation library resides somewhere other than the OpenSSL default. +.LP +.TP \fBAvoidDiskWrites \fR\fB0\fR|\fB1\fP If non-zero, try to write to disk less frequently than we would otherwise. This is useful when running on flash memory or other media that support only From 65836d246dce0b5928bf6d9d580fce5786a23eb1 Mon Sep 17 00:00:00 2001 From: Martin Peck Date: Sat, 30 May 2009 15:15:43 -0700 Subject: [PATCH 3/4] Remove warning about untested HardwareAccel option and clarify usage. --- doc/tor.1.in | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/doc/tor.1.in b/doc/tor.1.in index c9b344257d..db0637a75f 100644 --- a/doc/tor.1.in +++ b/doc/tor.1.in @@ -350,16 +350,17 @@ On startup, setuid to this user and setgid to their primary group. .LP .TP \fBHardwareAccel \fR\fB0\fR|\fB1\fP -If non-zero, try to use crypto hardware acceleration when -available. This is untested and probably buggy. (Default: 0) +If non-zero, try to use built-in (static) crypto hardware acceleration when +available. (Default: 0) .LP .TP -\fBAccelName \fR\fIEngineName\fP +\fBAccelName \fR\fINAME\fP When using OpenSSL hardware crypto acceleration attempt to load the dynamic -engine of this name. This must be used for any dynamic hardware engine. +engine of this name. This must be used for any dynamic hardware engine. Names +can be verified with the openssl engine command. .LP .TP -\fBAccelDir \fR\fIPath\fP +\fBAccelDir \fR\fIDIR\fP Specify this option if using dynamic hardware acceleration and the engine implementation library resides somewhere other than the OpenSSL default. .LP From 3ca10bb62faaed6a5242ff760ed6c76330a750ef Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Sun, 31 May 2009 13:36:18 -0400 Subject: [PATCH 4/4] Fix-ups for dynamic OpenSSL engine patch. Include a changelog, and don't try to compare strings with !=. --- ChangeLog | 6 +++++- src/or/config.c | 4 ++-- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index ee9f814f5a..ff01403b78 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,9 @@ Changes in version 0.2.2.1-alpha - 2009-??-?? - o Minor features + o Major features: + - Add support for dynamic OpenSSL hardware crypto acceleration engines + via new AccelName and AccelDir options. + + o Minor features: - New --digests command-line switch to output the digests of the source files Tor was built with. - The "torify" script now uses torsocks where available. diff --git a/src/or/config.c b/src/or/config.c index 0d176670e4..dea76391d1 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -3671,8 +3671,8 @@ options_transition_allowed(or_options_t *old, or_options_t *new_val, } if ((old->HardwareAccel != new_val->HardwareAccel) - || (old->AccelName != new_val->AccelName) - || (old->AccelDir != new_val->AccelDir)) { + || !opt_streq(old->AccelName, new_val->AccelName) + || !opt_streq(old->AccelDir, new_val->AccelDir)) { *msg = tor_strdup("While Tor is running, changing OpenSSL hardware " "acceleration engine is not allowed."); return -1;