From edec9409e85ba4a8b5d0575b23046d83d7562b87 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 24 Nov 2011 22:06:50 +0100 Subject: Copy/Paste Jake's stuff. This commit copies parts of Jake's f3bb6846975193d9a6649c31f94bda47e4014070 commit verbatim to the current master. --- src/common/crypto.c | 60 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 57 insertions(+), 3 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index f2ef83352..aeaabafb0 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1816,23 +1816,71 @@ static BIGNUM *dh_param_p_tls = NULL; /** Shared G parameter for our DH key exchanges. */ static BIGNUM *dh_param_g = NULL; +/** Generate and return a reasonable and safe DH parameter p. */ +static BIGNUM *generate_rakshasa_prime(void) +{ + BIGNUM *rakshasa_prime, *misc; + DH *dh_parameters; + int r; + int dh_codes; + int rakshasa_bits = RAKSHASA_BITS; + int generator = DH_GENERATOR; + + dh_parameters = DH_new(); + rakshasa_prime = BN_new(); + misc = BN_new(); + + /** XXX - do we want to cache the result in a file? Or perhaps load from a file? */ + /* This implements the prime number strategy outlined in prop 179 */ + tor_assert(rakshasa_prime); + log_notice(LD_OR, "Generating Rakshasa prime; this will take a while..."); + dh_parameters = DH_generate_parameters(rakshasa_bits, generator, NULL, NULL); // XXX Do we want a pretty call back? + tor_assert(dh_parameters); + log_notice(LD_OR, "Rakshasa prime generated!"); + log_notice(LD_OR, "Testing our Rakshasa prime; this will take a while..."); + r = DH_check(dh_parameters, &dh_codes); + tor_assert(r); + log_notice(LD_OR, "Rakshasa prime seems probabilistically reasonable!"); + misc = BN_copy(rakshasa_prime, dh_parameters->p); + tor_assert(misc); + DH_free(dh_parameters); + + return rakshasa_prime; +} + /** Initialize dh_param_p and dh_param_g if they are not already * set. */ static void init_dh_param(void) { - BIGNUM *p, *p2, *g; + BIGNUM *rakshasa_prime, *p, *p2, *g; int r; if (dh_param_p && dh_param_g && dh_param_p_tls) return; + rakshasa_prime = BN_new(); p = BN_new(); p2 = BN_new(); g = BN_new(); + tor_assert(rakshasa_prime); tor_assert(p); tor_assert(p2); tor_assert(g); + /* Set our generator for all DH parameters */ + r = BN_set_word(g, generator); + tor_assert(r); + + /* Are we generating a random DH parameter?*/ + log_notice(LD_OR, "Do we want to generate a Rakshasa prime?"); + rakshasa = get_rakshasa(); + log_notice(LD_OR, "We think: %i?", rakshasa); + + /* This implements the prime number strategy outlined in prop 179 */ + if (rakshasa == 1) { + rakshasa_prime = generate_rakshasa_prime(); + } + /* This is from rfc2409, section 6.2. It's a safe prime, and supposedly it equals: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }. @@ -1845,7 +1893,9 @@ init_dh_param(void) "49286651ECE65381FFFFFFFFFFFFFFFF"); tor_assert(r); /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see - * modules/ssl/ssl_engine_dh.c */ + * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this + * prime. + */ r = BN_hex2bn(&p2, "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" @@ -1857,7 +1907,11 @@ init_dh_param(void) r = BN_set_word(g, 2); tor_assert(r); dh_param_p = p; - dh_param_p_tls = p2; + if (rakshasa) { + dh_param_p_tls = rakshasa_prime; + } else { + dh_param_p_tls = p2; + } dh_param_g = g; } -- cgit v1.2.3 From 659381e00dc09deb4fb342d9f45cfae0b65aa33f Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Tue, 22 Nov 2011 04:53:43 +0100 Subject: Introduce the DynamicPrimes configuration option. --- src/common/crypto.c | 13 ++++++------- src/common/crypto.h | 3 ++- src/or/config.c | 1 + src/or/main.c | 3 ++- src/or/or.h | 2 ++ src/or/router.c | 3 ++- src/test/test.c | 2 +- src/tools/tor-checkkey.c | 2 +- src/tools/tor-gencert.c | 2 +- 9 files changed, 18 insertions(+), 13 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index aeaabafb0..790ea1646 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -224,13 +224,15 @@ try_load_engine(const char *path, const char *engine) /** Initialize the crypto library. Return 0 on success, -1 on failure. */ int -crypto_global_init(int useAccel, const char *accelName, const char *accelDir) +crypto_global_init(int useAccel, const char *accelName, const char *accelDir, + int DynamicPrimes) { if (!_crypto_global_initialized) { ERR_load_crypto_strings(); OpenSSL_add_all_algorithms(); _crypto_global_initialized = 1; setup_openssl_threading(); + use_dynamic_primes = DynamicPrimes; if (useAccel > 0) { #ifdef DISABLE_ENGINES (void)accelName; @@ -1815,6 +1817,8 @@ static BIGNUM *dh_param_p = NULL; static BIGNUM *dh_param_p_tls = NULL; /** Shared G parameter for our DH key exchanges. */ static BIGNUM *dh_param_g = NULL; +/** True if we use dynamic primes. */ +static int use_dynamic_primes = 0; /** Generate and return a reasonable and safe DH parameter p. */ static BIGNUM *generate_rakshasa_prime(void) @@ -1871,13 +1875,8 @@ init_dh_param(void) r = BN_set_word(g, generator); tor_assert(r); - /* Are we generating a random DH parameter?*/ - log_notice(LD_OR, "Do we want to generate a Rakshasa prime?"); - rakshasa = get_rakshasa(); - log_notice(LD_OR, "We think: %i?", rakshasa); - /* This implements the prime number strategy outlined in prop 179 */ - if (rakshasa == 1) { + if (use_dynamic_primes) { rakshasa_prime = generate_rakshasa_prime(); } diff --git a/src/common/crypto.h b/src/common/crypto.h index 2929a2eff..99c52b1c4 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -87,7 +87,8 @@ typedef struct crypto_dh_env_t crypto_dh_env_t; /* global state */ int crypto_global_init(int hardwareAccel, const char *accelName, - const char *accelPath); + const char *accelPath, + int DynamicPrimes); void crypto_thread_cleanup(void); int crypto_global_cleanup(void); diff --git a/src/or/config.c b/src/or/config.c index 06d7d5c02..4766b2419 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -247,6 +247,7 @@ static config_var_t _option_vars[] = { VAR("DirServer", LINELIST, DirServers, NULL), V(DisableAllSwap, BOOL, "0"), V(DisableIOCP, BOOL, "1"), + V(DynamicPrimes, BOOL, "1"), V(DNSPort, LINELIST, NULL), V(DNSListenAddress, LINELIST, NULL), V(DownloadExtraInfo, BOOL, "0"), diff --git a/src/or/main.c b/src/or/main.c index 7008d388a..3c75e1c64 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2275,7 +2275,8 @@ tor_init(int argc, char *argv[]) if (crypto_global_init(get_options()->HardwareAccel, get_options()->AccelName, - get_options()->AccelDir)) { + get_options()->AccelDir, + get_options()->DynamicPrimes)) { log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } diff --git a/src/or/or.h b/src/or/or.h index 67ba62bdd..b2ea3bc7a 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2873,6 +2873,8 @@ typedef struct { char *Address; /**< OR only: configured address for this onion router. */ char *PidFile; /**< Where to store PID of Tor process. */ + int DynamicPrimes; /**< Enable dynamic generation of primes for use in DH. */ + routerset_t *ExitNodes; /**< Structure containing nicknames, digests, * country codes and IP address patterns of ORs to * consider as exits. */ diff --git a/src/or/router.c b/src/or/router.c index b6b96a5ff..414d346bf 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -514,7 +514,8 @@ init_keys(void) * openssl to initialize itself. */ if (crypto_global_init(get_options()->HardwareAccel, get_options()->AccelName, - get_options()->AccelDir)) { + get_options()->AccelDir, + get_options()->DynamicPrimes)) { log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } diff --git a/src/test/test.c b/src/test/test.c index d4edf1484..26a55d13f 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1903,7 +1903,7 @@ main(int c, const char **v) } options->command = CMD_RUN_UNITTESTS; - if (crypto_global_init(0, NULL, NULL)) { + if (crypto_global_init(0, NULL, NULL, 1)) { printf("Can't initialize crypto subsystem; exiting.\n"); return 1; } diff --git a/src/tools/tor-checkkey.c b/src/tools/tor-checkkey.c index 94c8cbd44..55480b488 100644 --- a/src/tools/tor-checkkey.c +++ b/src/tools/tor-checkkey.c @@ -31,7 +31,7 @@ main(int c, char **v) return 1; } - if (crypto_global_init(0, NULL, NULL)) { + if (crypto_global_init(0, NULL, NULL, 0)) { 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 974a58bec..b9f16d992 100644 --- a/src/tools/tor-gencert.c +++ b/src/tools/tor-gencert.c @@ -508,7 +508,7 @@ main(int argc, char **argv) init_logging(); /* Don't bother using acceleration. */ - if (crypto_global_init(0, NULL, NULL)) { + if (crypto_global_init(0, NULL, NULL, 0)) { fprintf(stderr, "Couldn't initialize crypto library.\n"); return 1; } -- cgit v1.2.3 From 375e55eaa2439e18f7a0c5a9f6bc6324cbca37a0 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Tue, 22 Nov 2011 05:08:26 +0100 Subject: Rename "Rakshasa" to "Dynamic Prime". --- src/common/crypto.c | 39 ++++++++++++++++++--------------------- src/common/crypto.h | 2 -- 2 files changed, 18 insertions(+), 23 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 790ea1646..a07cc9657 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1821,35 +1821,32 @@ static BIGNUM *dh_param_g = NULL; static int use_dynamic_primes = 0; /** Generate and return a reasonable and safe DH parameter p. */ -static BIGNUM *generate_rakshasa_prime(void) +static BIGNUM * +crypto_generate_dynamic_prime(void) { - BIGNUM *rakshasa_prime, *misc; + BIGNUM *dynamic_prime, *misc; DH *dh_parameters; int r; int dh_codes; - int rakshasa_bits = RAKSHASA_BITS; - int generator = DH_GENERATOR; dh_parameters = DH_new(); - rakshasa_prime = BN_new(); + dynamic_prime = BN_new(); misc = BN_new(); - /** XXX - do we want to cache the result in a file? Or perhaps load from a file? */ - /* This implements the prime number strategy outlined in prop 179 */ - tor_assert(rakshasa_prime); - log_notice(LD_OR, "Generating Rakshasa prime; this will take a while..."); - dh_parameters = DH_generate_parameters(rakshasa_bits, generator, NULL, NULL); // XXX Do we want a pretty call back? + tor_assert(dynamic_prime); + log_notice(LD_OR, "Generating Dynamic prime; this will take a while..."); + dh_parameters = DH_generate_parameters(DH_BYTES*8, DH_GENERATOR, NULL, NULL); // XXX Do we want a pretty call back? tor_assert(dh_parameters); - log_notice(LD_OR, "Rakshasa prime generated!"); - log_notice(LD_OR, "Testing our Rakshasa prime; this will take a while..."); + log_notice(LD_OR, "Dynamic prime generated!"); + log_notice(LD_OR, "Testing our Dynamic prime; this will take a while..."); r = DH_check(dh_parameters, &dh_codes); tor_assert(r); - log_notice(LD_OR, "Rakshasa prime seems probabilistically reasonable!"); - misc = BN_copy(rakshasa_prime, dh_parameters->p); + log_notice(LD_OR, "Dynamic prime seems probabilistically reasonable!"); + misc = BN_copy(dynamic_prime, dh_parameters->p); tor_assert(misc); DH_free(dh_parameters); - return rakshasa_prime; + return dynamic_prime; } /** Initialize dh_param_p and dh_param_g if they are not already @@ -1857,16 +1854,16 @@ static BIGNUM *generate_rakshasa_prime(void) static void init_dh_param(void) { - BIGNUM *rakshasa_prime, *p, *p2, *g; + BIGNUM *dynamic_prime, *p, *p2, *g; int r; if (dh_param_p && dh_param_g && dh_param_p_tls) return; - rakshasa_prime = BN_new(); + dynamic_prime = BN_new(); p = BN_new(); p2 = BN_new(); g = BN_new(); - tor_assert(rakshasa_prime); + tor_assert(dynamic_prime); tor_assert(p); tor_assert(p2); tor_assert(g); @@ -1877,7 +1874,7 @@ init_dh_param(void) /* This implements the prime number strategy outlined in prop 179 */ if (use_dynamic_primes) { - rakshasa_prime = generate_rakshasa_prime(); + dynamic_prime = crypto_generate_dynamic_prime(); } /* This is from rfc2409, section 6.2. It's a safe prime, and @@ -1906,8 +1903,8 @@ init_dh_param(void) r = BN_set_word(g, 2); tor_assert(r); dh_param_p = p; - if (rakshasa) { - dh_param_p_tls = rakshasa_prime; + if (use_dynamic_primes) { + dh_param_p_tls = dynamic_prime; } else { dh_param_p_tls = p2; } diff --git a/src/common/crypto.h b/src/common/crypto.h index 99c52b1c4..9e52bc417 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -31,8 +31,6 @@ #define DH_BYTES (1024/8) /** Our DH 'g' parameter */ #define DH_GENERATOR 2 -/** Length of our Rakshasa DH parameter prime 'p' */ -#define RAKSHASA_BITS 1024 /** Length of a sha1 message digest when encoded in base64 with trailing = * signs removed. */ -- cgit v1.2.3 From 1797e0a39e85f81e773304d7121e1f5f36fe9de9 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Tue, 22 Nov 2011 05:13:34 +0100 Subject: Make it compile. --- src/common/crypto.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index a07cc9657..647d634fa 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -105,6 +105,9 @@ static tor_mutex_t **_openssl_mutexes = NULL; static int _n_openssl_mutexes = 0; #endif +/** True if we use dynamic primes. */ +static int use_dynamic_primes = 0; + /** A public key, or a public/private key-pair. */ struct crypto_pk_env_t { @@ -1817,8 +1820,6 @@ static BIGNUM *dh_param_p = NULL; static BIGNUM *dh_param_p_tls = NULL; /** Shared G parameter for our DH key exchanges. */ static BIGNUM *dh_param_g = NULL; -/** True if we use dynamic primes. */ -static int use_dynamic_primes = 0; /** Generate and return a reasonable and safe DH parameter p. */ static BIGNUM * @@ -1869,7 +1870,7 @@ init_dh_param(void) tor_assert(g); /* Set our generator for all DH parameters */ - r = BN_set_word(g, generator); + r = BN_set_word(g, DH_GENERATOR); tor_assert(r); /* This implements the prime number strategy outlined in prop 179 */ -- cgit v1.2.3 From fb38e58d14e2557a07f0ea34568f8966946c4316 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Tue, 22 Nov 2011 13:55:07 +0100 Subject: Improve logging. --- src/common/crypto.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 647d634fa..81690b26d 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1829,24 +1829,27 @@ crypto_generate_dynamic_prime(void) DH *dh_parameters; int r; int dh_codes; + char *s; dh_parameters = DH_new(); dynamic_prime = BN_new(); misc = BN_new(); tor_assert(dynamic_prime); - log_notice(LD_OR, "Generating Dynamic prime; this will take a while..."); dh_parameters = DH_generate_parameters(DH_BYTES*8, DH_GENERATOR, NULL, NULL); // XXX Do we want a pretty call back? tor_assert(dh_parameters); - log_notice(LD_OR, "Dynamic prime generated!"); - log_notice(LD_OR, "Testing our Dynamic prime; this will take a while..."); r = DH_check(dh_parameters, &dh_codes); tor_assert(r); - log_notice(LD_OR, "Dynamic prime seems probabilistically reasonable!"); misc = BN_copy(dynamic_prime, dh_parameters->p); tor_assert(misc); DH_free(dh_parameters); + { + s = BN_bn2hex(dynamic_prime); + log_notice(LD_OR, "Dynamic prime generated: [%s]", s); + OPENSSL_free(s); + } + return dynamic_prime; } @@ -1875,6 +1878,7 @@ init_dh_param(void) /* This implements the prime number strategy outlined in prop 179 */ if (use_dynamic_primes) { + log_notice(LD_OR, "Generating fresh dynamic prime."); dynamic_prime = crypto_generate_dynamic_prime(); } -- cgit v1.2.3 From 0e71be5d943811eb4ee9cfee0f435a184c10beb1 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Tue, 22 Nov 2011 15:08:27 +0100 Subject: Improve code in the dynamic primes realm. --- src/common/crypto.c | 87 +++++++++++++++++++++++++---------------------------- 1 file changed, 41 insertions(+), 46 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 81690b26d..88cba033a 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1825,27 +1825,28 @@ static BIGNUM *dh_param_g = NULL; static BIGNUM * crypto_generate_dynamic_prime(void) { - BIGNUM *dynamic_prime, *misc; + BIGNUM *dynamic_prime; DH *dh_parameters; - int r; - int dh_codes; + int r, dh_codes; char *s; - dh_parameters = DH_new(); dynamic_prime = BN_new(); - misc = BN_new(); - tor_assert(dynamic_prime); - dh_parameters = DH_generate_parameters(DH_BYTES*8, DH_GENERATOR, NULL, NULL); // XXX Do we want a pretty call back? + + dh_parameters = DH_generate_parameters(DH_BYTES*8, DH_GENERATOR, NULL, NULL); tor_assert(dh_parameters); + r = DH_check(dh_parameters, &dh_codes); tor_assert(r); - misc = BN_copy(dynamic_prime, dh_parameters->p); - tor_assert(misc); + + BN_copy(dynamic_prime, dh_parameters->p); + tor_assert(dynamic_prime); + DH_free(dh_parameters); - { + { /* log the dynamic prime: */ s = BN_bn2hex(dynamic_prime); + tor_assert(s); log_notice(LD_OR, "Dynamic prime generated: [%s]", s); OPENSSL_free(s); } @@ -1858,62 +1859,56 @@ crypto_generate_dynamic_prime(void) static void init_dh_param(void) { - BIGNUM *dynamic_prime, *p, *p2, *g; + BIGNUM *circuit_dh_prime, *tls_prime, *generator; int r; if (dh_param_p && dh_param_g && dh_param_p_tls) return; - dynamic_prime = BN_new(); - p = BN_new(); - p2 = BN_new(); - g = BN_new(); - tor_assert(dynamic_prime); - tor_assert(p); - tor_assert(p2); - tor_assert(g); + circuit_dh_prime = BN_new(); + generator = BN_new(); + tor_assert(circuit_dh_prime && generator); /* Set our generator for all DH parameters */ - r = BN_set_word(g, DH_GENERATOR); + r = BN_set_word(generator, DH_GENERATOR); tor_assert(r); - /* This implements the prime number strategy outlined in prop 179 */ - if (use_dynamic_primes) { - log_notice(LD_OR, "Generating fresh dynamic prime."); - dynamic_prime = crypto_generate_dynamic_prime(); - } - /* This is from rfc2409, section 6.2. It's a safe prime, and supposedly it equals: 2^1024 - 2^960 - 1 + 2^64 * { [2^894 pi] + 129093 }. */ - r = BN_hex2bn(&p, + r = BN_hex2bn(&circuit_dh_prime, "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" "49286651ECE65381FFFFFFFFFFFFFFFF"); tor_assert(r); - /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see - * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this - * prime. - */ - r = BN_hex2bn(&p2, - "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" - "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" - "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" - "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" - "B0E7393E0F24218EB3"); - tor_assert(r); - r = BN_set_word(g, 2); - tor_assert(r); - dh_param_p = p; - if (use_dynamic_primes) { - dh_param_p_tls = dynamic_prime; - } else { - dh_param_p_tls = p2; + if (use_dynamic_primes) { /* use dynamic primes: */ + log_notice(LD_OR, "Generating fresh dynamic prime."); + tls_prime = crypto_generate_dynamic_prime(); + tor_assert(tls_prime); + } else { /* use the static DH prime modulus used by Apache in mod_ssl: */ + tls_prime = BN_new(); + tor_assert(tls_prime); + + /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see + * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this + * prime. + */ + r = BN_hex2bn(&tls_prime, + "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" + "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" + "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" + "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" + "B0E7393E0F24218EB3"); + tor_assert(r); } - dh_param_g = g; + + /* Set the new values as the global DH parameters. */ + dh_param_p = circuit_dh_prime; + dh_param_p_tls = tls_prime; + dh_param_g = generator; } /** Number of bits to use when choosing the x or y value in a Diffie-Hellman -- cgit v1.2.3 From 42bda231ee10db0136cf2ffb56a38ce290891794 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Wed, 23 Nov 2011 23:39:46 +0100 Subject: Make DynamicPrimes SIGHUP-able. Instead of passing the DynamicPrimes configuration option to crypto_global_init(), generate and set a new TLS DH prime when we read the torrc. --- src/common/crypto.c | 82 ++++++++++++++++++++++++++++++------------------ src/common/crypto.h | 3 +- src/or/config.c | 17 ++++++++++ src/or/main.c | 3 +- src/test/test.c | 2 +- src/tools/tor-checkkey.c | 2 +- 6 files changed, 73 insertions(+), 36 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 88cba033a..bef62651f 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -105,9 +105,6 @@ static tor_mutex_t **_openssl_mutexes = NULL; static int _n_openssl_mutexes = 0; #endif -/** True if we use dynamic primes. */ -static int use_dynamic_primes = 0; - /** A public key, or a public/private key-pair. */ struct crypto_pk_env_t { @@ -227,15 +224,13 @@ try_load_engine(const char *path, const char *engine) /** Initialize the crypto library. Return 0 on success, -1 on failure. */ int -crypto_global_init(int useAccel, const char *accelName, const char *accelDir, - int DynamicPrimes) +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(); - use_dynamic_primes = DynamicPrimes; if (useAccel > 0) { #ifdef DISABLE_ENGINES (void)accelName; @@ -1854,14 +1849,60 @@ crypto_generate_dynamic_prime(void) return dynamic_prime; } +/** Set the global TLS Diffie-Hellman modulus. + * If use_dynamic_primes is not set, use the prime + * modulus of mod_ssl. + * If use_dynamic_primes is set, use stored_dynamic_prime + * if it exists, otherwise generate and use a new prime modulus. */ +void +crypto_set_tls_dh_prime(int use_dynamic_primes, BIGNUM *stored_dynamic_prime) +{ + BIGNUM *tls_prime = NULL; + + /* If the space is occupied, free the previous TLS DH prime */ + if (dh_param_p_tls) { + BN_free(dh_param_p_tls); + dh_param_p_tls = NULL; + } + + if (use_dynamic_primes) { /* use dynamic primes: */ + if (stored_dynamic_prime) { + log_notice(LD_OR, "Using stored dynamic prime."); + tls_prime = stored_dynamic_prime; + } else { + log_notice(LD_OR, "Generating fresh dynamic prime."); + tls_prime = crypto_generate_dynamic_prime(); + } + } else { /* use the static DH prime modulus used by Apache in mod_ssl: */ + tls_prime = BN_new(); + tor_assert(tls_prime); + + /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see + * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this + * prime. + */ + r = BN_hex2bn(&tls_prime, + "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" + "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" + "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" + "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" + "B0E7393E0F24218EB3"); + tor_assert(r); + } + + tor_assert(tls_prime); + + dh_param_p_tls = tls_prime; +} + /** Initialize dh_param_p and dh_param_g if they are not already * set. */ static void init_dh_param(void) { - BIGNUM *circuit_dh_prime, *tls_prime, *generator; + BIGNUM *circuit_dh_prime, *generator; int r; - if (dh_param_p && dh_param_g && dh_param_p_tls) + if (dh_param_p && dh_param_g) return; circuit_dh_prime = BN_new(); @@ -1884,31 +1925,12 @@ init_dh_param(void) "49286651ECE65381FFFFFFFFFFFFFFFF"); tor_assert(r); - if (use_dynamic_primes) { /* use dynamic primes: */ - log_notice(LD_OR, "Generating fresh dynamic prime."); - tls_prime = crypto_generate_dynamic_prime(); - tor_assert(tls_prime); - } else { /* use the static DH prime modulus used by Apache in mod_ssl: */ - tls_prime = BN_new(); - tor_assert(tls_prime); - - /* This is the 1024-bit safe prime that Apache uses for its DH stuff; see - * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this - * prime. - */ - r = BN_hex2bn(&tls_prime, - "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" - "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" - "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" - "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" - "B0E7393E0F24218EB3"); - tor_assert(r); - } - /* Set the new values as the global DH parameters. */ dh_param_p = circuit_dh_prime; - dh_param_p_tls = tls_prime; dh_param_g = generator; + + /* Should be already set by config.c. */ + tor_assert(dh_param_p_tls); } /** Number of bits to use when choosing the x or y value in a Diffie-Hellman diff --git a/src/common/crypto.h b/src/common/crypto.h index 9e52bc417..b759459d4 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -85,8 +85,7 @@ typedef struct crypto_dh_env_t crypto_dh_env_t; /* global state */ int crypto_global_init(int hardwareAccel, const char *accelName, - const char *accelPath, - int DynamicPrimes); + const char *accelPath); void crypto_thread_cleanup(void); int crypto_global_cleanup(void); diff --git a/src/or/config.c b/src/or/config.c index 4766b2419..a113f7b2d 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1362,6 +1362,23 @@ options_act(const or_options_t *old_options) finish_daemon(options->DataDirectory); } + /* If needed, generate a new TLS DH prime according to the current torrc. */ + if (!old_options) { + if (options->DynamicPrimes) { + crypto_set_tls_dh_prime(1, router_get_stored_dynamic_prime()); + } else { + crypto_set_tls_dh_prime(0, NULL); + } + } else { + if (options->DynamicPrimes && !old_options->DynamicPrimes) { + crypto_set_tls_dh_prime(1, router_get_stored_dynamic_prime()); + } else if (!options->DynamicPrimes && old_options->DynamicPrimes) { + crypto_set_tlS_dh_prime(0, NULL); + } else { + tor_assert(crypto_get_tls_dh_prime); + } + } + /* We want to reinit keys as needed before we do much of anything else: keys are important, and other things can depend on them. */ if (transition_affects_workers || diff --git a/src/or/main.c b/src/or/main.c index 3c75e1c64..0d2127d33 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2275,8 +2275,7 @@ tor_init(int argc, char *argv[]) if (crypto_global_init(get_options()->HardwareAccel, get_options()->AccelName, - get_options()->AccelDir, - get_options()->DynamicPrimes)) { + get_options()->AccelDir) { log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } diff --git a/src/test/test.c b/src/test/test.c index 26a55d13f..d4edf1484 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -1903,7 +1903,7 @@ main(int c, const char **v) } options->command = CMD_RUN_UNITTESTS; - if (crypto_global_init(0, NULL, NULL, 1)) { + if (crypto_global_init(0, NULL, NULL)) { printf("Can't initialize crypto subsystem; exiting.\n"); return 1; } diff --git a/src/tools/tor-checkkey.c b/src/tools/tor-checkkey.c index 55480b488..94c8cbd44 100644 --- a/src/tools/tor-checkkey.c +++ b/src/tools/tor-checkkey.c @@ -31,7 +31,7 @@ main(int c, char **v) return 1; } - if (crypto_global_init(0, NULL, NULL, 0)) { + if (crypto_global_init(0, NULL, NULL)) { fprintf(stderr, "Couldn't initialize crypto library.\n"); return 1; } -- cgit v1.2.3 From 8a726dd0dd28c4550a7f6f7d9aa5f72507d4716b Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 24 Nov 2011 00:22:31 +0100 Subject: Implement dynamic prime reading and storing to disk. --- src/common/crypto.c | 9 ++++- src/common/crypto.h | 6 ++++ src/or/config.c | 5 +-- src/or/main.c | 2 +- src/or/router.c | 94 +++++++++++++++++++++++++++++++++++++++++++++++-- src/or/router.h | 4 +++ src/tools/tor-gencert.c | 2 +- 7 files changed, 115 insertions(+), 7 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index bef62651f..484366297 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1849,6 +1849,12 @@ crypto_generate_dynamic_prime(void) return dynamic_prime; } +BIGNUM * +crypto_get_tls_dh_prime(void) +{ + return dh_param_p_tls; +} + /** Set the global TLS Diffie-Hellman modulus. * If use_dynamic_primes is not set, use the prime * modulus of mod_ssl. @@ -1858,6 +1864,7 @@ void crypto_set_tls_dh_prime(int use_dynamic_primes, BIGNUM *stored_dynamic_prime) { BIGNUM *tls_prime = NULL; + int r; /* If the space is occupied, free the previous TLS DH prime */ if (dh_param_p_tls) { @@ -1867,7 +1874,7 @@ crypto_set_tls_dh_prime(int use_dynamic_primes, BIGNUM *stored_dynamic_prime) if (use_dynamic_primes) { /* use dynamic primes: */ if (stored_dynamic_prime) { - log_notice(LD_OR, "Using stored dynamic prime."); + log_warn(LD_OR, "Using stored dynamic prime."); tls_prime = stored_dynamic_prime; } else { log_notice(LD_OR, "Generating fresh dynamic prime."); diff --git a/src/common/crypto.h b/src/common/crypto.h index b759459d4..5b753b83d 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -16,6 +16,8 @@ #include #include "torint.h" +#include + /** Length of the output of our message digest. */ #define DIGEST_LEN 20 /** Length of the output of our second (improved) message digests. (For now @@ -93,6 +95,10 @@ int crypto_global_cleanup(void); crypto_pk_env_t *crypto_new_pk_env(void); void crypto_free_pk_env(crypto_pk_env_t *env); +void crypto_set_tls_dh_prime(int use_dynamic_primes, + BIGNUM *stored_dynamic_prime); +BIGNUM * crypto_get_tls_dh_prime(void); + /* convenience function: wraps crypto_create_crypto_env, set_key, and init. */ crypto_cipher_env_t *crypto_create_init_cipher(const char *key, int encrypt_mode); diff --git a/src/or/config.c b/src/or/config.c index a113f7b2d..78e91bbe1 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1373,9 +1373,9 @@ options_act(const or_options_t *old_options) if (options->DynamicPrimes && !old_options->DynamicPrimes) { crypto_set_tls_dh_prime(1, router_get_stored_dynamic_prime()); } else if (!options->DynamicPrimes && old_options->DynamicPrimes) { - crypto_set_tlS_dh_prime(0, NULL); + crypto_set_tls_dh_prime(0, NULL); } else { - tor_assert(crypto_get_tls_dh_prime); + tor_assert(crypto_get_tls_dh_prime()); } } @@ -4069,6 +4069,7 @@ options_transition_affects_workers(const or_options_t *old_options, { if (!opt_streq(old_options->DataDirectory, new_options->DataDirectory) || old_options->NumCPUs != new_options->NumCPUs || + old_options->DynamicPrimes != new_options->DynamicPrimes || old_options->ORPort != new_options->ORPort || old_options->ServerDNSSearchDomains != new_options->ServerDNSSearchDomains || diff --git a/src/or/main.c b/src/or/main.c index 0d2127d33..7008d388a 100644 --- a/src/or/main.c +++ b/src/or/main.c @@ -2275,7 +2275,7 @@ tor_init(int argc, char *argv[]) if (crypto_global_init(get_options()->HardwareAccel, get_options()->AccelName, - get_options()->AccelDir) { + get_options()->AccelDir)) { log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } diff --git a/src/or/router.c b/src/or/router.c index 414d346bf..368ea1b74 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -484,6 +484,86 @@ v3_authority_check_key_expiry(void) last_warned = now; } + +/** Store dynamic_prime to disk for future use. */ +int +router_store_dynamic_prime(const BIGNUM *dynamic_prime) +{ + FILE *fp = NULL; + char *fname = get_datadir_fname2("keys", "dynamic_prime"); + int retval = -1; + + if (file_status(fname) != FN_NOENT) { + log_warn(LD_GENERAL, "Dynamic prime already occupied."); + goto done; + } + + if (!(fp = fopen(fname, "w"))) { + log_warn(LD_GENERAL, "Error writing to certificate file"); + goto done; + } + + if (BN_print_fp(fp, dynamic_prime) == 0) { + log_warn(LD_GENERAL, "Error on bn_print_fp()"); + goto done; + } + + retval = 0; + + done: + if (fp) + fclose(fp); + tor_free(fname); + + return retval; +} + +/** Return the dynamic prime stored in the disk. If there is no + dynamic prime stored in the disk, return NULL. */ +BIGNUM * +router_get_stored_dynamic_prime(void) +{ + int retval; + char *contents = NULL; + char *fname = get_datadir_fname2("keys", "dynamic_prime"); + BIGNUM *dynamic_prime = BN_new(); + if (!dynamic_prime) + goto err; + + contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); + if (!contents) { + log_warn(LD_GENERAL, "Error reading dynamic prime from \"%s\"", fname); + goto err; + } + + retval = BN_hex2bn(&dynamic_prime, contents); + if (!retval) { + log_warn(LD_GENERAL, "C0rrupted dynamic prime?!?!"); + goto err; + } + + { /* log the dynamic prime: */ + char *s = BN_bn2hex(dynamic_prime); + tor_assert(s); + log_notice(LD_OR, "Found stored dynamic prime: [%s]", s); + OPENSSL_free(s); + } + + goto done; + + err: + if (dynamic_prime) { + BN_free(dynamic_prime); + dynamic_prime = NULL; + } + + done: + tor_free(fname); + tor_free(contents); + + return dynamic_prime; +} + /** Initialize all OR private keys, and the TLS context, as necessary. * On OPs, this only initializes the tls context. Return 0 on success, * or -1 if Tor should die. @@ -514,8 +594,7 @@ init_keys(void) * openssl to initialize itself. */ if (crypto_global_init(get_options()->HardwareAccel, get_options()->AccelName, - get_options()->AccelDir, - get_options()->DynamicPrimes)) { + get_options()->AccelDir)) { log_err(LD_BUG, "Unable to initialize OpenSSL. Exiting."); return -1; } @@ -634,6 +713,17 @@ init_keys(void) log_err(LD_GENERAL,"Error initializing TLS context"); return -1; } + + /** 3b. If we use a dynamic prime, store it to disk. */ + if (get_options()->DynamicPrimes) { + BIGNUM *dynamic_prime = crypto_get_tls_dh_prime(); + if (dynamic_prime) { + if (router_store_dynamic_prime(dynamic_prime) < 0) + log_warn(LD_GENERAL, "Failed while storing dynamic prime. " + "Make sure your data directory is sane."); + } + } + /* 4. Build our router descriptor. */ /* Must be called after keys are initialized. */ mydesc = router_get_my_descriptor(); diff --git a/src/or/router.h b/src/or/router.h index f9d156cb0..41ff13993 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -28,6 +28,10 @@ void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last); void rotate_onion_key(void); crypto_pk_env_t *init_key_from_file(const char *fname, int generate, int severity); + +BIGNUM *router_get_stored_dynamic_prime(void); +int router_store_dynamic_prime(const BIGNUM *dynamic_prime); + void v3_authority_check_key_expiry(void); int init_keys(void); diff --git a/src/tools/tor-gencert.c b/src/tools/tor-gencert.c index b9f16d992..974a58bec 100644 --- a/src/tools/tor-gencert.c +++ b/src/tools/tor-gencert.c @@ -508,7 +508,7 @@ main(int argc, char **argv) init_logging(); /* Don't bother using acceleration. */ - if (crypto_global_init(0, NULL, NULL, 0)) { + if (crypto_global_init(0, NULL, NULL)) { fprintf(stderr, "Couldn't initialize crypto library.\n"); return 1; } -- cgit v1.2.3 From cabb8e54c7240aeb20ccfa745d75c5ad4063edb3 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 24 Nov 2011 06:12:22 +0100 Subject: Tone down the logging. --- src/common/crypto.c | 6 +++--- src/or/router.c | 28 +++++++++++++++++----------- 2 files changed, 20 insertions(+), 14 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 484366297..72c3dd7c1 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1842,7 +1842,7 @@ crypto_generate_dynamic_prime(void) { /* log the dynamic prime: */ s = BN_bn2hex(dynamic_prime); tor_assert(s); - log_notice(LD_OR, "Dynamic prime generated: [%s]", s); + log_info(LD_OR, "Dynamic prime generated: [%s]", s); OPENSSL_free(s); } @@ -1874,10 +1874,10 @@ crypto_set_tls_dh_prime(int use_dynamic_primes, BIGNUM *stored_dynamic_prime) if (use_dynamic_primes) { /* use dynamic primes: */ if (stored_dynamic_prime) { - log_warn(LD_OR, "Using stored dynamic prime."); + log_info(LD_OR, "Using stored dynamic prime."); tls_prime = stored_dynamic_prime; } else { - log_notice(LD_OR, "Generating fresh dynamic prime."); + log_info(LD_OR, "Generating fresh dynamic prime."); tls_prime = crypto_generate_dynamic_prime(); } } else { /* use the static DH prime modulus used by Apache in mod_ssl: */ diff --git a/src/or/router.c b/src/or/router.c index 368ea1b74..6b38c793c 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -492,19 +492,26 @@ router_store_dynamic_prime(const BIGNUM *dynamic_prime) FILE *fp = NULL; char *fname = get_datadir_fname2("keys", "dynamic_prime"); int retval = -1; + file_status_t fname_status = file_status(fname); - if (file_status(fname) != FN_NOENT) { - log_warn(LD_GENERAL, "Dynamic prime already occupied."); + if (fname_status == FN_FILE) { + /* If the fname is a file, then the dynamic prime is already stored. */ + retval = 0; + goto done; + } else if (fname_status != FN_NOENT) { + log_info(LD_GENERAL, "Dynamic prime filename is occupied."); goto done; } + tor_assert(fname_status == FN_NOENT); + if (!(fp = fopen(fname, "w"))) { - log_warn(LD_GENERAL, "Error writing to certificate file"); + log_notice(LD_GENERAL, "Error while creating dynamic prime file."); goto done; } if (BN_print_fp(fp, dynamic_prime) == 0) { - log_warn(LD_GENERAL, "Error on bn_print_fp()"); + log_warn(LD_GENERAL, "Error while printing dynamic prime to file."); goto done; } @@ -531,21 +538,20 @@ router_get_stored_dynamic_prime(void) goto err; contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); - if (!contents) { - log_warn(LD_GENERAL, "Error reading dynamic prime from \"%s\"", fname); + if (!contents) goto err; - } retval = BN_hex2bn(&dynamic_prime, contents); if (!retval) { - log_warn(LD_GENERAL, "C0rrupted dynamic prime?!?!"); + log_notice(LD_GENERAL, "Could not understand the dynamic prime " + "format in '%s'", fname); goto err; } { /* log the dynamic prime: */ char *s = BN_bn2hex(dynamic_prime); tor_assert(s); - log_notice(LD_OR, "Found stored dynamic prime: [%s]", s); + log_info(LD_OR, "Found stored dynamic prime: [%s]", s); OPENSSL_free(s); } @@ -719,8 +725,8 @@ init_keys(void) BIGNUM *dynamic_prime = crypto_get_tls_dh_prime(); if (dynamic_prime) { if (router_store_dynamic_prime(dynamic_prime) < 0) - log_warn(LD_GENERAL, "Failed while storing dynamic prime. " - "Make sure your data directory is sane."); + log_notice(LD_GENERAL, "Failed while storing dynamic prime. " + "Make sure your data directory is sane."); } } -- cgit v1.2.3 From 2ef68980a778666bcc9b3b492c4acbd7af27fc28 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 24 Nov 2011 22:32:10 +0100 Subject: Move store_dynamic_prime() to crypto.c. --- src/common/crypto.c | 40 +++++++++++++++++++++++++++++++++++++--- src/common/crypto.h | 2 +- src/or/router.c | 52 ++++++---------------------------------------------- src/or/router.h | 1 - 4 files changed, 44 insertions(+), 51 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 72c3dd7c1..a3c292324 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1849,10 +1849,44 @@ crypto_generate_dynamic_prime(void) return dynamic_prime; } -BIGNUM * -crypto_get_tls_dh_prime(void) +/** Store our dynamic prime to fname for future use. */ +int +router_store_dynamic_prime(const char *fname) { - return dh_param_p_tls; + FILE *fp = NULL; + int retval = -1; + file_status_t fname_status = file_status(fname); + + tor_assert(fname); + + if (fname_status == FN_FILE) { + /* If the fname is a file, then the dynamic prime is already stored. */ + retval = 0; + goto done; + } else if (fname_status != FN_NOENT) { + log_info(LD_GENERAL, "Dynamic prime filename is occupied."); + goto done; + } + + tor_assert(fname_status == FN_NOENT); + + if (!(fp = fopen(fname, "w"))) { + log_notice(LD_GENERAL, "Error while creating dynamic prime file."); + goto done; + } + + if (BN_print_fp(fp, dh_param_p_tls) == 0) { + log_warn(LD_GENERAL, "Error while printing dynamic prime to file."); + goto done; + } + + retval = 0; + + done: + if (fp) + fclose(fp); + + return retval; } /** Set the global TLS Diffie-Hellman modulus. diff --git a/src/common/crypto.h b/src/common/crypto.h index 5b753b83d..8c99dd7a3 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -97,7 +97,7 @@ void crypto_free_pk_env(crypto_pk_env_t *env); void crypto_set_tls_dh_prime(int use_dynamic_primes, BIGNUM *stored_dynamic_prime); -BIGNUM * crypto_get_tls_dh_prime(void); +int router_store_dynamic_prime(const char *fname); /* convenience function: wraps crypto_create_crypto_env, set_key, and init. */ crypto_cipher_env_t *crypto_create_init_cipher(const char *key, diff --git a/src/or/router.c b/src/or/router.c index 6b38c793c..dd5b9fff5 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -485,46 +485,6 @@ v3_authority_check_key_expiry(void) } -/** Store dynamic_prime to disk for future use. */ -int -router_store_dynamic_prime(const BIGNUM *dynamic_prime) -{ - FILE *fp = NULL; - char *fname = get_datadir_fname2("keys", "dynamic_prime"); - int retval = -1; - file_status_t fname_status = file_status(fname); - - if (fname_status == FN_FILE) { - /* If the fname is a file, then the dynamic prime is already stored. */ - retval = 0; - goto done; - } else if (fname_status != FN_NOENT) { - log_info(LD_GENERAL, "Dynamic prime filename is occupied."); - goto done; - } - - tor_assert(fname_status == FN_NOENT); - - if (!(fp = fopen(fname, "w"))) { - log_notice(LD_GENERAL, "Error while creating dynamic prime file."); - goto done; - } - - if (BN_print_fp(fp, dynamic_prime) == 0) { - log_warn(LD_GENERAL, "Error while printing dynamic prime to file."); - goto done; - } - - retval = 0; - - done: - if (fp) - fclose(fp); - tor_free(fname); - - return retval; -} - /** Return the dynamic prime stored in the disk. If there is no dynamic prime stored in the disk, return NULL. */ BIGNUM * @@ -722,12 +682,12 @@ init_keys(void) /** 3b. If we use a dynamic prime, store it to disk. */ if (get_options()->DynamicPrimes) { - BIGNUM *dynamic_prime = crypto_get_tls_dh_prime(); - if (dynamic_prime) { - if (router_store_dynamic_prime(dynamic_prime) < 0) - log_notice(LD_GENERAL, "Failed while storing dynamic prime. " - "Make sure your data directory is sane."); - } + const char *fname = get_datadir_fname2("keys", "dynamic_prime"); + if (crypto_store_dynamic_prime(fname)) { + log_notice(LD_GENERAL, "Failed while storing dynamic prime. " + "Make sure your data directory is sane."); + } + tor_free(fname); } /* 4. Build our router descriptor. */ diff --git a/src/or/router.h b/src/or/router.h index 41ff13993..a998335aa 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -30,7 +30,6 @@ crypto_pk_env_t *init_key_from_file(const char *fname, int generate, int severity); BIGNUM *router_get_stored_dynamic_prime(void); -int router_store_dynamic_prime(const BIGNUM *dynamic_prime); void v3_authority_check_key_expiry(void); -- cgit v1.2.3 From 94076d9e3b74ad1f6aee8a96f51eb4af5f5bdb64 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Thu, 24 Nov 2011 22:59:01 +0100 Subject: Move crypto_get_stored_dynamic_prime() to crypto.c --- src/common/crypto.c | 70 ++++++++++++++++++++++++++++++++++++++++++++--------- src/common/crypto.h | 5 ++-- src/or/config.c | 14 ++++++----- src/or/router.c | 58 +++++--------------------------------------- src/or/router.h | 2 -- 5 files changed, 75 insertions(+), 74 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index a3c292324..c6285e5ce 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1851,7 +1851,7 @@ crypto_generate_dynamic_prime(void) /** Store our dynamic prime to fname for future use. */ int -router_store_dynamic_prime(const char *fname) +crypto_store_dynamic_prime(const char *fname) { FILE *fp = NULL; int retval = -1; @@ -1889,13 +1889,61 @@ router_store_dynamic_prime(const char *fname) return retval; } +/** Return the dynamic prime stored in fname. If there is no + dynamic prime stored in fname, return NULL. */ +static BIGNUM * +crypto_get_stored_dynamic_prime(const char *fname) +{ + int retval; + char *contents = NULL; + BIGNUM *dynamic_prime = BN_new(); + + tor_assert(fname); + + if (!dynamic_prime) + goto err; + + contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); + if (!contents) + goto err; + + retval = BN_hex2bn(&dynamic_prime, contents); + if (!retval) { + log_notice(LD_GENERAL, "Could not understand the dynamic prime " + "format in '%s'", fname); + goto err; + } + + { /* log the dynamic prime: */ + char *s = BN_bn2hex(dynamic_prime); + tor_assert(s); + log_info(LD_OR, "Found stored dynamic prime: [%s]", s); + OPENSSL_free(s); + } + + goto done; + + err: + if (dynamic_prime) { + BN_free(dynamic_prime); + dynamic_prime = NULL; + } + + done: + tor_free(contents); + + return dynamic_prime; +} + + /** Set the global TLS Diffie-Hellman modulus. - * If use_dynamic_primes is not set, use the prime - * modulus of mod_ssl. - * If use_dynamic_primes is set, use stored_dynamic_prime - * if it exists, otherwise generate and use a new prime modulus. */ + * If dynamic_prime_fname is set, try to read a dynamic prime + * off it and use it as the DH modulus. If that's not possible, + * generate a new dynamic prime. + * If dynamic_prime_fname is NULL, use the Apache mod_ssl DH + * modulus. */ void -crypto_set_tls_dh_prime(int use_dynamic_primes, BIGNUM *stored_dynamic_prime) +crypto_set_tls_dh_prime(const char *dynamic_prime_fname) { BIGNUM *tls_prime = NULL; int r; @@ -1906,11 +1954,11 @@ crypto_set_tls_dh_prime(int use_dynamic_primes, BIGNUM *stored_dynamic_prime) dh_param_p_tls = NULL; } - if (use_dynamic_primes) { /* use dynamic primes: */ - if (stored_dynamic_prime) { - log_info(LD_OR, "Using stored dynamic prime."); - tls_prime = stored_dynamic_prime; - } else { + if (dynamic_prime_fname) { /* use dynamic primes: */ + log_info(LD_OR, "Using stored dynamic prime."); + tls_prime = crypto_get_stored_dynamic_prime(dynamic_prime_fname); + + if (!tls_prime) { log_info(LD_OR, "Generating fresh dynamic prime."); tls_prime = crypto_generate_dynamic_prime(); } diff --git a/src/common/crypto.h b/src/common/crypto.h index 8c99dd7a3..20298b3c4 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -95,9 +95,8 @@ int crypto_global_cleanup(void); crypto_pk_env_t *crypto_new_pk_env(void); void crypto_free_pk_env(crypto_pk_env_t *env); -void crypto_set_tls_dh_prime(int use_dynamic_primes, - BIGNUM *stored_dynamic_prime); -int router_store_dynamic_prime(const char *fname); +void crypto_set_tls_dh_prime(const char *dynamic_prime_fname); +int crypto_store_dynamic_prime(const char *fname); /* convenience function: wraps crypto_create_crypto_env, set_key, and init. */ crypto_cipher_env_t *crypto_create_init_cipher(const char *key, diff --git a/src/or/config.c b/src/or/config.c index 78e91bbe1..e1e71b059 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1365,17 +1365,19 @@ options_act(const or_options_t *old_options) /* If needed, generate a new TLS DH prime according to the current torrc. */ if (!old_options) { if (options->DynamicPrimes) { - crypto_set_tls_dh_prime(1, router_get_stored_dynamic_prime()); + char *fname = get_datadir_fname2("keys", "dynamic_prime"); + crypto_set_tls_dh_prime(fname); + tor_free(fname); } else { - crypto_set_tls_dh_prime(0, NULL); + crypto_set_tls_dh_prime(NULL); } } else { if (options->DynamicPrimes && !old_options->DynamicPrimes) { - crypto_set_tls_dh_prime(1, router_get_stored_dynamic_prime()); + char *fname = get_datadir_fname2("keys", "dynamic_prime"); + crypto_set_tls_dh_prime(fname); + tor_free(fname); } else if (!options->DynamicPrimes && old_options->DynamicPrimes) { - crypto_set_tls_dh_prime(0, NULL); - } else { - tor_assert(crypto_get_tls_dh_prime()); + crypto_set_tls_dh_prime(NULL); } } diff --git a/src/or/router.c b/src/or/router.c index dd5b9fff5..c554d5b96 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -484,52 +484,6 @@ v3_authority_check_key_expiry(void) last_warned = now; } - -/** Return the dynamic prime stored in the disk. If there is no - dynamic prime stored in the disk, return NULL. */ -BIGNUM * -router_get_stored_dynamic_prime(void) -{ - int retval; - char *contents = NULL; - char *fname = get_datadir_fname2("keys", "dynamic_prime"); - BIGNUM *dynamic_prime = BN_new(); - if (!dynamic_prime) - goto err; - - contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); - if (!contents) - goto err; - - retval = BN_hex2bn(&dynamic_prime, contents); - if (!retval) { - log_notice(LD_GENERAL, "Could not understand the dynamic prime " - "format in '%s'", fname); - goto err; - } - - { /* log the dynamic prime: */ - char *s = BN_bn2hex(dynamic_prime); - tor_assert(s); - log_info(LD_OR, "Found stored dynamic prime: [%s]", s); - OPENSSL_free(s); - } - - goto done; - - err: - if (dynamic_prime) { - BN_free(dynamic_prime); - dynamic_prime = NULL; - } - - done: - tor_free(fname); - tor_free(contents); - - return dynamic_prime; -} - /** Initialize all OR private keys, and the TLS context, as necessary. * On OPs, this only initializes the tls context. Return 0 on success, * or -1 if Tor should die. @@ -682,12 +636,12 @@ init_keys(void) /** 3b. If we use a dynamic prime, store it to disk. */ if (get_options()->DynamicPrimes) { - const char *fname = get_datadir_fname2("keys", "dynamic_prime"); - if (crypto_store_dynamic_prime(fname)) { - log_notice(LD_GENERAL, "Failed while storing dynamic prime. " - "Make sure your data directory is sane."); - } - tor_free(fname); + char *fname = get_datadir_fname2("keys", "dynamic_prime"); + if (crypto_store_dynamic_prime(fname)) { + log_notice(LD_GENERAL, "Failed while storing dynamic prime. " + "Make sure your data directory is sane."); + } + tor_free(fname); } /* 4. Build our router descriptor. */ diff --git a/src/or/router.h b/src/or/router.h index a998335aa..b9e9f2a71 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -29,8 +29,6 @@ void rotate_onion_key(void); crypto_pk_env_t *init_key_from_file(const char *fname, int generate, int severity); -BIGNUM *router_get_stored_dynamic_prime(void); - void v3_authority_check_key_expiry(void); int init_keys(void); -- cgit v1.2.3 From 5f3f41c23412e149add77a30e82431eb018cd376 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 25 Nov 2011 00:33:40 +0100 Subject: Make sure that the stored DH prime is safe to use. --- src/common/crypto.c | 38 ++++++++++++++++++++++++++++++++++---- 1 file changed, 34 insertions(+), 4 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index c6285e5ce..83f56a5d8 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1832,7 +1832,7 @@ crypto_generate_dynamic_prime(void) tor_assert(dh_parameters); r = DH_check(dh_parameters, &dh_codes); - tor_assert(r); + tor_assert(r && !dh_codes); BN_copy(dynamic_prime, dh_parameters->p); tor_assert(dynamic_prime); @@ -1855,10 +1855,12 @@ crypto_store_dynamic_prime(const char *fname) { FILE *fp = NULL; int retval = -1; - file_status_t fname_status = file_status(fname); + file_status_t fname_status; tor_assert(fname); + fname_status = file_status(fname); + if (fname_status == FN_FILE) { /* If the fname is a file, then the dynamic prime is already stored. */ retval = 0; @@ -1896,6 +1898,8 @@ crypto_get_stored_dynamic_prime(const char *fname) { int retval; char *contents = NULL; + DH *dh = NULL; + int dh_codes; BIGNUM *dynamic_prime = BN_new(); tor_assert(fname); @@ -1909,11 +1913,35 @@ crypto_get_stored_dynamic_prime(const char *fname) retval = BN_hex2bn(&dynamic_prime, contents); if (!retval) { - log_notice(LD_GENERAL, "Could not understand the dynamic prime " - "format in '%s'", fname); + log_warn(LD_GENERAL, "Could not understand the dynamic prime " + "format in '%s'", fname); goto err; } + { /* validate the stored prime */ + dh = DH_new(); + if (!dh) + goto err; + + dh->p = BN_dup(dynamic_prime); + dh->g = BN_new(); + BN_set_word(dh->g, DH_GENERATOR); + + retval = DH_check(dh, &dh_codes); + if (!retval || dh_codes) { + log_warn(LD_GENERAL, "Stored dynamic DH prime is not a safe prime."); + goto err; + } + + retval = DH_size(dh); + if (retval < DH_BYTES) { + log_warn(LD_GENERAL, "Stored dynamic DH prime is smaller " + "than '%d' bits.", DH_BYTES*8); + goto err; + } + + } + { /* log the dynamic prime: */ char *s = BN_bn2hex(dynamic_prime); tor_assert(s); @@ -1931,6 +1959,8 @@ crypto_get_stored_dynamic_prime(const char *fname) done: tor_free(contents); + if (dh) + DH_free(dh); return dynamic_prime; } -- cgit v1.2.3 From bdeb797a130c0d11dd6c1d7375eba468a09c6245 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 25 Nov 2011 00:59:47 +0100 Subject: Notify the user that her computer is generating numbers. --- src/common/crypto.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 83f56a5d8..4e96fed90 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1989,7 +1989,8 @@ crypto_set_tls_dh_prime(const char *dynamic_prime_fname) tls_prime = crypto_get_stored_dynamic_prime(dynamic_prime_fname); if (!tls_prime) { - log_info(LD_OR, "Generating fresh dynamic prime."); + log_notice(LD_OR, "Generating fresh dynamic prime. " + "This might take a while..."); tls_prime = crypto_generate_dynamic_prime(); } } else { /* use the static DH prime modulus used by Apache in mod_ssl: */ -- cgit v1.2.3 From 7c37a664c17f4dd9748f096ea385c3627cc323fa Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 25 Nov 2011 01:00:58 +0100 Subject: Rename 'dynamic prime' to 'dynamic DH modulus'. --- src/common/crypto.c | 80 ++++++++++++++++++++++++++--------------------------- src/common/crypto.h | 4 +-- src/or/config.c | 4 +-- src/or/router.c | 4 +-- 4 files changed, 46 insertions(+), 46 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 4e96fed90..0f828db81 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1818,15 +1818,15 @@ static BIGNUM *dh_param_g = NULL; /** Generate and return a reasonable and safe DH parameter p. */ static BIGNUM * -crypto_generate_dynamic_prime(void) +crypto_generate_dynamic_dh_modulus(void) { - BIGNUM *dynamic_prime; + BIGNUM *dynamic_dh_modulus; DH *dh_parameters; int r, dh_codes; char *s; - dynamic_prime = BN_new(); - tor_assert(dynamic_prime); + dynamic_dh_modulus = BN_new(); + tor_assert(dynamic_dh_modulus); dh_parameters = DH_generate_parameters(DH_BYTES*8, DH_GENERATOR, NULL, NULL); tor_assert(dh_parameters); @@ -1834,24 +1834,24 @@ crypto_generate_dynamic_prime(void) r = DH_check(dh_parameters, &dh_codes); tor_assert(r && !dh_codes); - BN_copy(dynamic_prime, dh_parameters->p); - tor_assert(dynamic_prime); + BN_copy(dynamic_dh_modulus, dh_parameters->p); + tor_assert(dynamic_dh_modulus); DH_free(dh_parameters); - { /* log the dynamic prime: */ - s = BN_bn2hex(dynamic_prime); + { /* log the dynamic DH modulus: */ + s = BN_bn2hex(dynamic_dh_modulus); tor_assert(s); - log_info(LD_OR, "Dynamic prime generated: [%s]", s); + log_info(LD_OR, "Dynamic DH modulus generated: [%s]", s); OPENSSL_free(s); } - return dynamic_prime; + return dynamic_dh_modulus; } -/** Store our dynamic prime to fname for future use. */ +/** Store our dynamic DH modulus to fname for future use. */ int -crypto_store_dynamic_prime(const char *fname) +crypto_store_dynamic_dh_modulus(const char *fname) { FILE *fp = NULL; int retval = -1; @@ -1862,23 +1862,23 @@ crypto_store_dynamic_prime(const char *fname) fname_status = file_status(fname); if (fname_status == FN_FILE) { - /* If the fname is a file, then the dynamic prime is already stored. */ + /* If the fname is a file, then the dynamic DH modulus is already stored. */ retval = 0; goto done; } else if (fname_status != FN_NOENT) { - log_info(LD_GENERAL, "Dynamic prime filename is occupied."); + log_info(LD_GENERAL, "Dynamic DH modulus filename is occupied."); goto done; } tor_assert(fname_status == FN_NOENT); if (!(fp = fopen(fname, "w"))) { - log_notice(LD_GENERAL, "Error while creating dynamic prime file."); + log_notice(LD_GENERAL, "Error while creating dynamic DH modulus file."); goto done; } if (BN_print_fp(fp, dh_param_p_tls) == 0) { - log_warn(LD_GENERAL, "Error while printing dynamic prime to file."); + log_warn(LD_GENERAL, "Error while printing dynamic DH modulus to file."); goto done; } @@ -1891,29 +1891,29 @@ crypto_store_dynamic_prime(const char *fname) return retval; } -/** Return the dynamic prime stored in fname. If there is no - dynamic prime stored in fname, return NULL. */ +/** Return the dynamic DH modulus stored in fname. If there is no + dynamic DH modulus stored in fname, return NULL. */ static BIGNUM * -crypto_get_stored_dynamic_prime(const char *fname) +crypto_get_stored_dynamic_dh_modulus(const char *fname) { int retval; char *contents = NULL; DH *dh = NULL; int dh_codes; - BIGNUM *dynamic_prime = BN_new(); + BIGNUM *dynamic_dh_modulus = BN_new(); tor_assert(fname); - if (!dynamic_prime) + if (!dynamic_dh_modulus) goto err; contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); if (!contents) goto err; - retval = BN_hex2bn(&dynamic_prime, contents); + retval = BN_hex2bn(&dynamic_dh_modulus, contents); if (!retval) { - log_warn(LD_GENERAL, "Could not understand the dynamic prime " + log_warn(LD_GENERAL, "Could not understand the dynamic DH modulus " "format in '%s'", fname); goto err; } @@ -1923,7 +1923,7 @@ crypto_get_stored_dynamic_prime(const char *fname) if (!dh) goto err; - dh->p = BN_dup(dynamic_prime); + dh->p = BN_dup(dynamic_dh_modulus); dh->g = BN_new(); BN_set_word(dh->g, DH_GENERATOR); @@ -1942,19 +1942,19 @@ crypto_get_stored_dynamic_prime(const char *fname) } - { /* log the dynamic prime: */ - char *s = BN_bn2hex(dynamic_prime); + { /* log the dynamic DH modulus: */ + char *s = BN_bn2hex(dynamic_dh_modulus); tor_assert(s); - log_info(LD_OR, "Found stored dynamic prime: [%s]", s); + log_info(LD_OR, "Found stored dynamic DH modulus: [%s]", s); OPENSSL_free(s); } goto done; err: - if (dynamic_prime) { - BN_free(dynamic_prime); - dynamic_prime = NULL; + if (dynamic_dh_modulus) { + BN_free(dynamic_dh_modulus); + dynamic_dh_modulus = NULL; } done: @@ -1962,18 +1962,18 @@ crypto_get_stored_dynamic_prime(const char *fname) if (dh) DH_free(dh); - return dynamic_prime; + return dynamic_dh_modulus; } /** Set the global TLS Diffie-Hellman modulus. - * If dynamic_prime_fname is set, try to read a dynamic prime + * If dynamic_dh_modulus_fname is set, try to read a dynamic DH modulus * off it and use it as the DH modulus. If that's not possible, - * generate a new dynamic prime. - * If dynamic_prime_fname is NULL, use the Apache mod_ssl DH + * generate a new dynamic DH modulus. + * If dynamic_dh_modulus_fname is NULL, use the Apache mod_ssl DH * modulus. */ void -crypto_set_tls_dh_prime(const char *dynamic_prime_fname) +crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) { BIGNUM *tls_prime = NULL; int r; @@ -1984,14 +1984,14 @@ crypto_set_tls_dh_prime(const char *dynamic_prime_fname) dh_param_p_tls = NULL; } - if (dynamic_prime_fname) { /* use dynamic primes: */ - log_info(LD_OR, "Using stored dynamic prime."); - tls_prime = crypto_get_stored_dynamic_prime(dynamic_prime_fname); + if (dynamic_dh_modulus_fname) { /* use dynamic DH moduluss: */ + log_info(LD_OR, "Using stored dynamic DH modulus."); + tls_prime = crypto_get_stored_dynamic_dh_modulus(dynamic_dh_modulus_fname); if (!tls_prime) { - log_notice(LD_OR, "Generating fresh dynamic prime. " + log_notice(LD_OR, "Generating fresh dynamic DH modulus. " "This might take a while..."); - tls_prime = crypto_generate_dynamic_prime(); + tls_prime = crypto_generate_dynamic_dh_modulus(); } } else { /* use the static DH prime modulus used by Apache in mod_ssl: */ tls_prime = BN_new(); diff --git a/src/common/crypto.h b/src/common/crypto.h index 20298b3c4..504c59b1a 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -95,8 +95,8 @@ int crypto_global_cleanup(void); crypto_pk_env_t *crypto_new_pk_env(void); void crypto_free_pk_env(crypto_pk_env_t *env); -void crypto_set_tls_dh_prime(const char *dynamic_prime_fname); -int crypto_store_dynamic_prime(const char *fname); +void crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname); +int crypto_store_dynamic_dh_modulus(const char *fname); /* convenience function: wraps crypto_create_crypto_env, set_key, and init. */ crypto_cipher_env_t *crypto_create_init_cipher(const char *key, diff --git a/src/or/config.c b/src/or/config.c index fc3cc745f..d403decb1 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1365,7 +1365,7 @@ options_act(const or_options_t *old_options) /* If needed, generate a new TLS DH prime according to the current torrc. */ if (!old_options) { if (options->DynamicDHGroups) { - char *fname = get_datadir_fname2("keys", "dynamic_prime"); + char *fname = get_datadir_fname2("keys", "dynamic_dh_modulus"); crypto_set_tls_dh_prime(fname); tor_free(fname); } else { @@ -1373,7 +1373,7 @@ options_act(const or_options_t *old_options) } } else { if (options->DynamicDHGroups && !old_options->DynamicDHGroups) { - char *fname = get_datadir_fname2("keys", "dynamic_prime"); + char *fname = get_datadir_fname2("keys", "dynamic_dh_modulus"); crypto_set_tls_dh_prime(fname); tor_free(fname); } else if (!options->DynamicDHGroups && old_options->DynamicDHGroups) { diff --git a/src/or/router.c b/src/or/router.c index fa791fc85..963c78173 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -636,8 +636,8 @@ init_keys(void) /** 3b. If we use a dynamic prime, store it to disk. */ if (get_options()->DynamicDHGroups) { - char *fname = get_datadir_fname2("keys", "dynamic_prime"); - if (crypto_store_dynamic_prime(fname)) { + char *fname = get_datadir_fname2("keys", "dynamic_dh_modulus"); + if (crypto_store_dynamic_dh_modulus(fname)) { log_notice(LD_GENERAL, "Failed while storing dynamic prime. " "Make sure your data directory is sane."); } -- cgit v1.2.3 From 1d1d5ae7f8f91b62f0e86081ff1f7255c545383b Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 25 Nov 2011 01:08:31 +0100 Subject: Finishing touches. - Make check-spaces happy. - Remove a stray header from crypto.h --- src/common/crypto.c | 16 +++++++--------- src/common/crypto.h | 2 -- src/or/or.h | 2 +- src/or/router.h | 1 - 4 files changed, 8 insertions(+), 13 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 0f828db81..8b0f0ef9d 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1862,7 +1862,7 @@ crypto_store_dynamic_dh_modulus(const char *fname) fname_status = file_status(fname); if (fname_status == FN_FILE) { - /* If the fname is a file, then the dynamic DH modulus is already stored. */ + /* If the fname is a file, then the dynamic DH modulus is already stored.*/ retval = 0; goto done; } else if (fname_status != FN_NOENT) { @@ -1939,7 +1939,6 @@ crypto_get_stored_dynamic_dh_modulus(const char *fname) "than '%d' bits.", DH_BYTES*8); goto err; } - } { /* log the dynamic DH modulus: */ @@ -1965,7 +1964,6 @@ crypto_get_stored_dynamic_dh_modulus(const char *fname) return dynamic_dh_modulus; } - /** Set the global TLS Diffie-Hellman modulus. * If dynamic_dh_modulus_fname is set, try to read a dynamic DH modulus * off it and use it as the DH modulus. If that's not possible, @@ -2001,12 +1999,12 @@ crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) * modules/ssl/ssl_engine_dh.c; Apache also uses a generator of 2 with this * prime. */ - r = BN_hex2bn(&tls_prime, - "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" - "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" - "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" - "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" - "B0E7393E0F24218EB3"); + r =BN_hex2bn(&tls_prime, + "D67DE440CBBBDC1936D693D34AFD0AD50C84D239A45F520BB88174CB98" + "BCE951849F912E639C72FB13B4B4D7177E16D55AC179BA420B2A29FE324A" + "467A635E81FF5901377BEDDCFD33168A461AAD3B72DAE8860078045B07A7" + "DBCA7874087D1510EA9FCC9DDD330507DD62DB88AEAA747DE0F4D6E2BD68" + "B0E7393E0F24218EB3"); tor_assert(r); } diff --git a/src/common/crypto.h b/src/common/crypto.h index 504c59b1a..683c8ea38 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -16,8 +16,6 @@ #include #include "torint.h" -#include - /** Length of the output of our message digest. */ #define DIGEST_LEN 20 /** Length of the output of our second (improved) message digests. (For now diff --git a/src/or/or.h b/src/or/or.h index e3feeedc2..ec49014d9 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -2873,7 +2873,7 @@ typedef struct { char *Address; /**< OR only: configured address for this onion router. */ char *PidFile; /**< Where to store PID of Tor process. */ - int DynamicDHGroups; /**< Enable dynamic generation of primes for use in DH. */ + int DynamicDHGroups; /**< Dynamic generation of prime moduli for use in DH.*/ routerset_t *ExitNodes; /**< Structure containing nicknames, digests, * country codes and IP address patterns of ORs to diff --git a/src/or/router.h b/src/or/router.h index b9e9f2a71..f9d156cb0 100644 --- a/src/or/router.h +++ b/src/or/router.h @@ -28,7 +28,6 @@ void dup_onion_keys(crypto_pk_env_t **key, crypto_pk_env_t **last); void rotate_onion_key(void); crypto_pk_env_t *init_key_from_file(const char *fname, int generate, int severity); - void v3_authority_check_key_expiry(void); int init_keys(void); -- cgit v1.2.3 From 4938bcc06a41b95f47def181ce03a7ade805595b Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 25 Nov 2011 17:39:28 +0100 Subject: Do dynamic DH modulus storing in crypto.c. --- src/common/crypto.c | 15 +++++++++++++-- src/common/crypto.h | 1 - src/or/router.c | 10 ---------- 3 files changed, 13 insertions(+), 13 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 8b0f0ef9d..1974a3931 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1850,7 +1850,7 @@ crypto_generate_dynamic_dh_modulus(void) } /** Store our dynamic DH modulus to fname for future use. */ -int +static int crypto_store_dynamic_dh_modulus(const char *fname) { FILE *fp = NULL; @@ -1974,6 +1974,7 @@ void crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) { BIGNUM *tls_prime = NULL; + int store_dh_prime_afterwards = 0; int r; /* If the space is occupied, free the previous TLS DH prime */ @@ -1982,7 +1983,7 @@ crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) dh_param_p_tls = NULL; } - if (dynamic_dh_modulus_fname) { /* use dynamic DH moduluss: */ + if (dynamic_dh_modulus_fname) { /* use dynamic DH modulus: */ log_info(LD_OR, "Using stored dynamic DH modulus."); tls_prime = crypto_get_stored_dynamic_dh_modulus(dynamic_dh_modulus_fname); @@ -1990,6 +1991,8 @@ crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) log_notice(LD_OR, "Generating fresh dynamic DH modulus. " "This might take a while..."); tls_prime = crypto_generate_dynamic_dh_modulus(); + + store_dh_prime_afterwards++; } } else { /* use the static DH prime modulus used by Apache in mod_ssl: */ tls_prime = BN_new(); @@ -2011,6 +2014,14 @@ crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) tor_assert(tls_prime); dh_param_p_tls = tls_prime; + + if (store_dh_prime_afterwards) + /* save the new dynamic DH modulus to disk. */ + if (crypto_store_dynamic_dh_modulus(dynamic_dh_modulus_fname)) { + log_notice(LD_GENERAL, "Failed while storing dynamic DH modulus. " + "Make sure your data directory is sane."); + } + } /** Initialize dh_param_p and dh_param_g if they are not already diff --git a/src/common/crypto.h b/src/common/crypto.h index 683c8ea38..bac6db920 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -94,7 +94,6 @@ crypto_pk_env_t *crypto_new_pk_env(void); void crypto_free_pk_env(crypto_pk_env_t *env); void crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname); -int crypto_store_dynamic_dh_modulus(const char *fname); /* convenience function: wraps crypto_create_crypto_env, set_key, and init. */ crypto_cipher_env_t *crypto_create_init_cipher(const char *key, diff --git a/src/or/router.c b/src/or/router.c index 963c78173..fdc83f508 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -634,16 +634,6 @@ init_keys(void) return -1; } - /** 3b. If we use a dynamic prime, store it to disk. */ - if (get_options()->DynamicDHGroups) { - char *fname = get_datadir_fname2("keys", "dynamic_dh_modulus"); - if (crypto_store_dynamic_dh_modulus(fname)) { - log_notice(LD_GENERAL, "Failed while storing dynamic prime. " - "Make sure your data directory is sane."); - } - tor_free(fname); - } - /* 4. Build our router descriptor. */ /* Must be called after keys are initialized. */ mydesc = router_get_my_descriptor(); -- cgit v1.2.3 From 1df6b5a734acd381d49a57bb689c7dcd2cd66ad9 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 25 Nov 2011 17:39:45 +0100 Subject: Move broken primes to dynamic_dh_modulus.broken. --- src/common/crypto.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 1974a3931..da3b80bec 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1900,6 +1900,7 @@ crypto_get_stored_dynamic_dh_modulus(const char *fname) char *contents = NULL; DH *dh = NULL; int dh_codes; + char *fname_new = NULL; BIGNUM *dynamic_dh_modulus = BN_new(); tor_assert(fname); @@ -1951,6 +1952,24 @@ crypto_get_stored_dynamic_dh_modulus(const char *fname) goto done; err: + + { /* move broken prime to $filename.broken */ + + fname_new = tor_malloc(strlen(fname) + 8); + + /* no can do if these functions return error */ + strlcpy(fname_new, fname, strlen(fname) + 8); + strlcat(fname_new, ".broken", strlen(fname) + 8); + + log_warn(LD_GENERAL, "Moving broken dynamic DH prime to '%s'.", fname_new); + + if (replace_file(fname, fname_new)) + log_warn(LD_GENERAL, "Error while moving '%s' to '%s'.", fname, fname_new); + + tor_free(fname_new); + + } + if (dynamic_dh_modulus) { BN_free(dynamic_dh_modulus); dynamic_dh_modulus = NULL; -- cgit v1.2.3 From b31601975b0be372f6c041868a54024a8d89ad8c Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Fri, 25 Nov 2011 17:44:11 +0100 Subject: Move DH_GENERATOR to crypto.c. --- src/common/crypto.c | 3 +++ src/common/crypto.h | 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index da3b80bec..8cf623192 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1809,6 +1809,9 @@ crypto_hmac_sha256(char *hmac_out, /* DH */ +/** Our DH 'g' parameter */ +#define DH_GENERATOR 2 + /** Shared P parameter for our circuit-crypto DH key exchanges. */ static BIGNUM *dh_param_p = NULL; /** Shared P parameter for our TLS DH key exchanges. */ diff --git a/src/common/crypto.h b/src/common/crypto.h index bac6db920..771c49c2d 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -29,8 +29,6 @@ #define PK_BYTES (1024/8) /** Length of our DH keys. */ #define DH_BYTES (1024/8) -/** Our DH 'g' parameter */ -#define DH_GENERATOR 2 /** Length of a sha1 message digest when encoded in base64 with trailing = * signs removed. */ -- cgit v1.2.3 From 055d6c01fff3324dbb38c2d81ad49ccfdb5432c2 Mon Sep 17 00:00:00 2001 From: George Kadianakis Date: Sat, 26 Nov 2011 19:29:57 +0100 Subject: Write dynamic DH parameters to a file. Instead of only writing the dynamic DH prime modulus to a file, write the whole DH parameters set for forward compatibility. At the moment we only accept '2' as the group generator. The DH parameters gets stored in base64-ed DER format to the 'dynamic_dh_params' file. --- src/common/crypto.c | 136 ++++++++++++++++++++++++++++++++-------------------- src/or/config.c | 4 +- src/or/router.c | 1 - 3 files changed, 87 insertions(+), 54 deletions(-) (limited to 'src/common/crypto.c') diff --git a/src/common/crypto.c b/src/common/crypto.c index 8cf623192..a38956d3e 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1852,44 +1852,66 @@ crypto_generate_dynamic_dh_modulus(void) return dynamic_dh_modulus; } -/** Store our dynamic DH modulus to fname for future use. */ +/** Store our dynamic DH modulus (and its group parameters) to + fname for future use. */ static int crypto_store_dynamic_dh_modulus(const char *fname) { - FILE *fp = NULL; + int len, new_len; + DH *dh = NULL; + unsigned char *dh_string_repr = NULL, *cp = NULL; + char *base64_encoded_dh = NULL; int retval = -1; - file_status_t fname_status; tor_assert(fname); - fname_status = file_status(fname); + if (!dh_param_p_tls) { + log_info(LD_CRYPTO, "Tried to store a DH modulus that does not exist."); + goto done; + } - if (fname_status == FN_FILE) { - /* If the fname is a file, then the dynamic DH modulus is already stored.*/ - retval = 0; + if (!(dh = DH_new())) + goto done; + if (!(dh->p = BN_dup(dh_param_p_tls))) + goto done; + if (!(dh->g = BN_new())) goto done; - } else if (fname_status != FN_NOENT) { - log_info(LD_GENERAL, "Dynamic DH modulus filename is occupied."); + if (!BN_set_word(dh->g, DH_GENERATOR)) + goto done; + + len = i2d_DHparams(dh, NULL); + if (len < 0) { + log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (1)."); goto done; } - tor_assert(fname_status == FN_NOENT); + cp = dh_string_repr = tor_malloc_zero(len+1); + len = i2d_DHparams(dh, &cp); + if ((len < 0) || ((cp - dh_string_repr) != len)) { + log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (2)."); + goto done; + } - if (!(fp = fopen(fname, "w"))) { - log_notice(LD_GENERAL, "Error while creating dynamic DH modulus file."); + base64_encoded_dh = tor_malloc_zero(len * 2); /* should be enough */ + new_len = base64_encode(base64_encoded_dh, len * 2, + (char *)dh_string_repr, len); + if (new_len < 0) { + log_warn(LD_CRYPTO, "Error occured while base64-encoding DH modulus."); goto done; } - if (BN_print_fp(fp, dh_param_p_tls) == 0) { - log_warn(LD_GENERAL, "Error while printing dynamic DH modulus to file."); + if (write_bytes_to_new_file(fname, base64_encoded_dh, new_len, 0) < 0) { + log_info(LD_CRYPTO, "'%s' was already occupied.", fname); goto done; } retval = 0; done: - if (fp) - fclose(fp); + if (dh) + DH_free(dh); + tor_free(dh_string_repr); + tor_free(base64_encoded_dh); return retval; } @@ -1901,52 +1923,62 @@ crypto_get_stored_dynamic_dh_modulus(const char *fname) { int retval; char *contents = NULL; - DH *dh = NULL; int dh_codes; char *fname_new = NULL; - BIGNUM *dynamic_dh_modulus = BN_new(); + DH *stored_dh = NULL; + BIGNUM *dynamic_dh_modulus = NULL; + int length = 0; + unsigned char *base64_decoded_dh = NULL; + const unsigned char *cp = NULL; tor_assert(fname); - if (!dynamic_dh_modulus) - goto err; - contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL); - if (!contents) - goto err; + if (!contents) { + log_info(LD_CRYPTO, "Could not open file '%s'", fname); + goto done; /*usually means that ENOENT. don't try to move file to broken.*/ + } + + /* 'fname' contains the DH parameters stored in base64-ed DER + format. We are only interested in the DH modulus. */ - retval = BN_hex2bn(&dynamic_dh_modulus, contents); - if (!retval) { - log_warn(LD_GENERAL, "Could not understand the dynamic DH modulus " - "format in '%s'", fname); + cp = base64_decoded_dh = tor_malloc_zero(strlen(contents)); + length = base64_decode((char *)base64_decoded_dh, strlen(contents), + contents, strlen(contents)); + if (length < 0) { + log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (base64)."); goto err; } - { /* validate the stored prime */ - dh = DH_new(); - if (!dh) - goto err; - - dh->p = BN_dup(dynamic_dh_modulus); - dh->g = BN_new(); - BN_set_word(dh->g, DH_GENERATOR); + stored_dh = d2i_DHparams(NULL, &cp, length); + if ((!stored_dh) || (cp - base64_decoded_dh != length)) { + log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (d2i)."); + goto err; + } - retval = DH_check(dh, &dh_codes); + { /* check the cryptographic qualities of the stored dynamic DH modulus: */ + retval = DH_check(stored_dh, &dh_codes); if (!retval || dh_codes) { - log_warn(LD_GENERAL, "Stored dynamic DH prime is not a safe prime."); + log_warn(LD_CRYPTO, "Stored dynamic DH modulus is not a safe prime."); goto err; } - retval = DH_size(dh); + retval = DH_size(stored_dh); if (retval < DH_BYTES) { - log_warn(LD_GENERAL, "Stored dynamic DH prime is smaller " + log_warn(LD_CRYPTO, "Stored dynamic DH modulus is smaller " "than '%d' bits.", DH_BYTES*8); goto err; } + + if (!BN_is_word(stored_dh->g, 2)) { + log_warn(LD_CRYPTO, "Stored dynamic DH parameters do not use '2' " + "as the group generator."); + goto err; + } } { /* log the dynamic DH modulus: */ - char *s = BN_bn2hex(dynamic_dh_modulus); + char *s = BN_bn2hex(stored_dh->p); tor_assert(s); log_info(LD_OR, "Found stored dynamic DH modulus: [%s]", s); OPENSSL_free(s); @@ -1957,31 +1989,34 @@ crypto_get_stored_dynamic_dh_modulus(const char *fname) err: { /* move broken prime to $filename.broken */ - fname_new = tor_malloc(strlen(fname) + 8); /* no can do if these functions return error */ strlcpy(fname_new, fname, strlen(fname) + 8); strlcat(fname_new, ".broken", strlen(fname) + 8); - log_warn(LD_GENERAL, "Moving broken dynamic DH prime to '%s'.", fname_new); + log_warn(LD_CRYPTO, "Moving broken dynamic DH prime to '%s'.", fname_new); if (replace_file(fname, fname_new)) - log_warn(LD_GENERAL, "Error while moving '%s' to '%s'.", fname, fname_new); + log_notice(LD_CRYPTO, "Error while moving '%s' to '%s'.", + fname, fname_new); tor_free(fname_new); - } - if (dynamic_dh_modulus) { - BN_free(dynamic_dh_modulus); - dynamic_dh_modulus = NULL; + if (stored_dh) { + DH_free(stored_dh); + stored_dh = NULL; } done: tor_free(contents); - if (dh) - DH_free(dh); + tor_free(base64_decoded_dh); + + if (stored_dh) { + dynamic_dh_modulus = BN_dup(stored_dh->p); + DH_free(stored_dh); + } return dynamic_dh_modulus; } @@ -2040,10 +2075,9 @@ crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname) if (store_dh_prime_afterwards) /* save the new dynamic DH modulus to disk. */ if (crypto_store_dynamic_dh_modulus(dynamic_dh_modulus_fname)) { - log_notice(LD_GENERAL, "Failed while storing dynamic DH modulus. " + log_notice(LD_CRYPTO, "Failed while storing dynamic DH modulus. " "Make sure your data directory is sane."); } - } /** Initialize dh_param_p and dh_param_g if they are not already diff --git a/src/or/config.c b/src/or/config.c index 9c658614b..06914b62a 100644 --- a/src/or/config.c +++ b/src/or/config.c @@ -1384,7 +1384,7 @@ options_act(const or_options_t *old_options) if (server_mode(options)) { if (!old_options) { if (options->DynamicDHGroups) { - char *fname = get_datadir_fname2("keys", "dynamic_dh_modulus"); + char *fname = get_datadir_fname2("keys", "dynamic_dh_params"); crypto_set_tls_dh_prime(fname); tor_free(fname); } else { @@ -1392,7 +1392,7 @@ options_act(const or_options_t *old_options) } } else { if (options->DynamicDHGroups && !old_options->DynamicDHGroups) { - char *fname = get_datadir_fname2("keys", "dynamic_dh_modulus"); + char *fname = get_datadir_fname2("keys", "dynamic_dh_params"); crypto_set_tls_dh_prime(fname); tor_free(fname); } else if (!options->DynamicDHGroups && old_options->DynamicDHGroups) { diff --git a/src/or/router.c b/src/or/router.c index 67e98da23..5d36939a8 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -484,7 +484,6 @@ v3_authority_check_key_expiry(void) last_warned = now; } - int router_initialize_tls_context(void) { -- cgit v1.2.3