commit 055d6c01fff3324dbb38c2d81ad49ccfdb5432c2 Author: George Kadianakis desnacked@gmail.com Date: Sat Nov 26 19:29:57 2011 +0100
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(-)
diff --git a/src/common/crypto.c b/src/common/crypto.c index 8cf6231..a38956d 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 <b>fname</b> for future use. */ +/** Store our dynamic DH modulus (and its group parameters) to + <b>fname</b> 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 9c65861..06914b6 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 67e98da..5d36939 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) {