diff --git a/src/common/crypto.c b/src/common/crypto.c index bef62651fc..484366297d 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 b759459d40..5b753b83d6 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 a113f7b2da..78e91bbe11 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 0d2127d336..7008d388a1 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 414d346bfa..368ea1b741 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 f9d156cb09..41ff139936 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 b9f16d9929..974a58becf 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; }