mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 15:43:32 +01:00
Remove DynamicDHGroups as obsoleted by PluggableTransports or P256.
Closes ticket 13736.
This commit is contained in:
parent
4247ce99e5
commit
511ca9b91c
5
changes/bug13736
Normal file
5
changes/bug13736
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
o Removed features:
|
||||||
|
- Remove the (seldom-used) DynamicDHGroups feature. For
|
||||||
|
anti-fingerprinting we now recommend pluggable transports; for
|
||||||
|
forward-secrecy in TLS, we now use the P-256 group.
|
||||||
|
Closes ticket 13736.
|
@ -1768,235 +1768,12 @@ static BIGNUM *dh_param_p_tls = NULL;
|
|||||||
/** Shared G parameter for our DH key exchanges. */
|
/** Shared G parameter for our DH key exchanges. */
|
||||||
static BIGNUM *dh_param_g = NULL;
|
static BIGNUM *dh_param_g = NULL;
|
||||||
|
|
||||||
/** Generate and return a reasonable and safe DH parameter p. */
|
/** Set the global TLS Diffie-Hellman modulus. Use the Apache mod_ssl DH
|
||||||
static BIGNUM *
|
|
||||||
crypto_generate_dynamic_dh_modulus(void)
|
|
||||||
{
|
|
||||||
BIGNUM *dynamic_dh_modulus;
|
|
||||||
DH *dh_parameters;
|
|
||||||
int r, dh_codes;
|
|
||||||
char *s;
|
|
||||||
|
|
||||||
dynamic_dh_modulus = BN_new();
|
|
||||||
tor_assert(dynamic_dh_modulus);
|
|
||||||
|
|
||||||
dh_parameters = DH_new();
|
|
||||||
tor_assert(dh_parameters);
|
|
||||||
|
|
||||||
r = DH_generate_parameters_ex(dh_parameters,
|
|
||||||
DH_BYTES*8, DH_GENERATOR, NULL);
|
|
||||||
tor_assert(r == 0);
|
|
||||||
|
|
||||||
r = DH_check(dh_parameters, &dh_codes);
|
|
||||||
tor_assert(r && !dh_codes);
|
|
||||||
|
|
||||||
BN_copy(dynamic_dh_modulus, dh_parameters->p);
|
|
||||||
tor_assert(dynamic_dh_modulus);
|
|
||||||
|
|
||||||
DH_free(dh_parameters);
|
|
||||||
|
|
||||||
{ /* log the dynamic DH modulus: */
|
|
||||||
s = BN_bn2hex(dynamic_dh_modulus);
|
|
||||||
tor_assert(s);
|
|
||||||
log_info(LD_OR, "Dynamic DH modulus generated: [%s]", s);
|
|
||||||
OPENSSL_free(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dynamic_dh_modulus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** 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)
|
|
||||||
{
|
|
||||||
int len, new_len;
|
|
||||||
DH *dh = NULL;
|
|
||||||
unsigned char *dh_string_repr = NULL;
|
|
||||||
char *base64_encoded_dh = NULL;
|
|
||||||
char *file_string = NULL;
|
|
||||||
int retval = -1;
|
|
||||||
static const char file_header[] = "# This file contains stored Diffie-"
|
|
||||||
"Hellman parameters for future use.\n# You *do not* need to edit this "
|
|
||||||
"file.\n\n";
|
|
||||||
|
|
||||||
tor_assert(fname);
|
|
||||||
|
|
||||||
if (!dh_param_p_tls) {
|
|
||||||
log_info(LD_CRYPTO, "Tried to store a DH modulus that does not exist.");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!(dh = DH_new()))
|
|
||||||
goto done;
|
|
||||||
if (!(dh->p = BN_dup(dh_param_p_tls)))
|
|
||||||
goto done;
|
|
||||||
if (!(dh->g = BN_new()))
|
|
||||||
goto done;
|
|
||||||
if (!BN_set_word(dh->g, DH_GENERATOR))
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
len = i2d_DHparams(dh, &dh_string_repr);
|
|
||||||
if ((len < 0) || (dh_string_repr == NULL)) {
|
|
||||||
log_warn(LD_CRYPTO, "Error occured while DER encoding DH modulus (2).");
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
base64_encoded_dh = tor_calloc(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;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* concatenate file header and the dh parameters blob */
|
|
||||||
new_len = tor_asprintf(&file_string, "%s%s", file_header, base64_encoded_dh);
|
|
||||||
|
|
||||||
/* write to file */
|
|
||||||
if (write_bytes_to_new_file(fname, file_string, new_len, 0) < 0) {
|
|
||||||
log_info(LD_CRYPTO, "'%s' was already occupied.", fname);
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = 0;
|
|
||||||
|
|
||||||
done:
|
|
||||||
if (dh)
|
|
||||||
DH_free(dh);
|
|
||||||
if (dh_string_repr)
|
|
||||||
OPENSSL_free(dh_string_repr);
|
|
||||||
tor_free(base64_encoded_dh);
|
|
||||||
tor_free(file_string);
|
|
||||||
|
|
||||||
return retval;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Return the dynamic DH modulus stored in <b>fname</b>. If there is no
|
|
||||||
dynamic DH modulus stored in <b>fname</b>, return NULL. */
|
|
||||||
static BIGNUM *
|
|
||||||
crypto_get_stored_dynamic_dh_modulus(const char *fname)
|
|
||||||
{
|
|
||||||
int retval;
|
|
||||||
char *contents = NULL;
|
|
||||||
const char *contents_tmp = NULL;
|
|
||||||
int dh_codes;
|
|
||||||
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);
|
|
||||||
|
|
||||||
contents = read_file_to_str(fname, RFTS_IGNORE_MISSING, NULL);
|
|
||||||
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.*/
|
|
||||||
}
|
|
||||||
|
|
||||||
/* skip the file header */
|
|
||||||
contents_tmp = eat_whitespace(contents);
|
|
||||||
if (!*contents_tmp) {
|
|
||||||
log_warn(LD_CRYPTO, "Stored dynamic DH modulus file "
|
|
||||||
"seems corrupted (eat_whitespace).");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* 'fname' contains the DH parameters stored in base64-ed DER
|
|
||||||
* format. We are only interested in the DH modulus.
|
|
||||||
* NOTE: We allocate more storage here than we need. Since we're already
|
|
||||||
* doing that, we can also add 1 byte extra to appease Coverity's
|
|
||||||
* scanner. */
|
|
||||||
|
|
||||||
cp = base64_decoded_dh = tor_malloc_zero(strlen(contents_tmp) + 1);
|
|
||||||
length = base64_decode((char *)base64_decoded_dh, strlen(contents_tmp),
|
|
||||||
contents_tmp, strlen(contents_tmp));
|
|
||||||
if (length < 0) {
|
|
||||||
log_warn(LD_CRYPTO, "Stored dynamic DH modulus seems corrupted (base64).");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
|
|
||||||
{ /* check the cryptographic qualities of the stored dynamic DH modulus: */
|
|
||||||
retval = DH_check(stored_dh, &dh_codes);
|
|
||||||
if (!retval || dh_codes) {
|
|
||||||
log_warn(LD_CRYPTO, "Stored dynamic DH modulus is not a safe prime.");
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
retval = DH_size(stored_dh);
|
|
||||||
if (retval < DH_BYTES) {
|
|
||||||
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(stored_dh->p);
|
|
||||||
tor_assert(s);
|
|
||||||
log_info(LD_OR, "Found stored dynamic DH modulus: [%s]", s);
|
|
||||||
OPENSSL_free(s);
|
|
||||||
}
|
|
||||||
|
|
||||||
goto done;
|
|
||||||
|
|
||||||
err:
|
|
||||||
|
|
||||||
{
|
|
||||||
/* move broken prime to $filename.broken */
|
|
||||||
char *fname_new=NULL;
|
|
||||||
tor_asprintf(&fname_new, "%s.broken", fname);
|
|
||||||
|
|
||||||
log_warn(LD_CRYPTO, "Moving broken dynamic DH prime to '%s'.", fname_new);
|
|
||||||
|
|
||||||
if (replace_file(fname, fname_new))
|
|
||||||
log_notice(LD_CRYPTO, "Error while moving '%s' to '%s'.",
|
|
||||||
fname, fname_new);
|
|
||||||
|
|
||||||
tor_free(fname_new);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (stored_dh) {
|
|
||||||
DH_free(stored_dh);
|
|
||||||
stored_dh = NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
done:
|
|
||||||
tor_free(contents);
|
|
||||||
tor_free(base64_decoded_dh);
|
|
||||||
|
|
||||||
if (stored_dh) {
|
|
||||||
dynamic_dh_modulus = BN_dup(stored_dh->p);
|
|
||||||
DH_free(stored_dh);
|
|
||||||
}
|
|
||||||
|
|
||||||
return dynamic_dh_modulus;
|
|
||||||
}
|
|
||||||
|
|
||||||
/** Set the global TLS Diffie-Hellman modulus.
|
|
||||||
* If <b>dynamic_dh_modulus_fname</b> 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 DH modulus.
|
|
||||||
* If <b>dynamic_dh_modulus_fname</b> is NULL, use the Apache mod_ssl DH
|
|
||||||
* modulus. */
|
* modulus. */
|
||||||
void
|
void
|
||||||
crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname)
|
crypto_set_tls_dh_prime(void)
|
||||||
{
|
{
|
||||||
BIGNUM *tls_prime = NULL;
|
BIGNUM *tls_prime = NULL;
|
||||||
int store_dh_prime_afterwards = 0;
|
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
/* If the space is occupied, free the previous TLS DH prime */
|
/* If the space is occupied, free the previous TLS DH prime */
|
||||||
@ -2005,18 +1782,7 @@ crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname)
|
|||||||
dh_param_p_tls = NULL;
|
dh_param_p_tls = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (dynamic_dh_modulus_fname) { /* use dynamic DH modulus: */
|
if (1) {
|
||||||
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 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();
|
tls_prime = BN_new();
|
||||||
tor_assert(tls_prime);
|
tor_assert(tls_prime);
|
||||||
|
|
||||||
@ -2036,13 +1802,6 @@ crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname)
|
|||||||
tor_assert(tls_prime);
|
tor_assert(tls_prime);
|
||||||
|
|
||||||
dh_param_p_tls = 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_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
|
/** Initialize dh_param_p and dh_param_g if they are not already
|
||||||
@ -2079,10 +1838,8 @@ init_dh_param(void)
|
|||||||
dh_param_p = circuit_dh_prime;
|
dh_param_p = circuit_dh_prime;
|
||||||
dh_param_g = generator;
|
dh_param_g = generator;
|
||||||
|
|
||||||
/* Ensure that we have TLS DH parameters set up, too, even if we're
|
|
||||||
going to change them soon. */
|
|
||||||
if (!dh_param_p_tls) {
|
if (!dh_param_p_tls) {
|
||||||
crypto_set_tls_dh_prime(NULL);
|
crypto_set_tls_dh_prime();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -122,8 +122,7 @@ int crypto_global_cleanup(void);
|
|||||||
crypto_pk_t *crypto_pk_new(void);
|
crypto_pk_t *crypto_pk_new(void);
|
||||||
void crypto_pk_free(crypto_pk_t *env);
|
void crypto_pk_free(crypto_pk_t *env);
|
||||||
|
|
||||||
void crypto_set_tls_dh_prime(const char *dynamic_dh_modulus_fname);
|
void crypto_set_tls_dh_prime(void);
|
||||||
|
|
||||||
crypto_cipher_t *crypto_cipher_new(const char *key);
|
crypto_cipher_t *crypto_cipher_new(const char *key);
|
||||||
crypto_cipher_t *crypto_cipher_new_with_iv(const char *key, const char *iv);
|
crypto_cipher_t *crypto_cipher_new_with_iv(const char *key, const char *iv);
|
||||||
void crypto_cipher_free(crypto_cipher_t *env);
|
void crypto_cipher_free(crypto_cipher_t *env);
|
||||||
@ -297,4 +296,3 @@ struct dh_st *crypto_dh_get_dh_(crypto_dh_t *dh);
|
|||||||
void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
|
void crypto_add_spaces_to_fp(char *out, size_t outlen, const char *in);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -225,7 +225,7 @@ static config_var_t option_vars_[] = {
|
|||||||
V(DisableDebuggerAttachment, BOOL, "1"),
|
V(DisableDebuggerAttachment, BOOL, "1"),
|
||||||
V(DisableIOCP, BOOL, "1"),
|
V(DisableIOCP, BOOL, "1"),
|
||||||
OBSOLETE("DisableV2DirectoryInfo_"),
|
OBSOLETE("DisableV2DirectoryInfo_"),
|
||||||
V(DynamicDHGroups, BOOL, "0"),
|
OBSOLETE("DynamicDHGroups"),
|
||||||
VPORT(DNSPort, LINELIST, NULL),
|
VPORT(DNSPort, LINELIST, NULL),
|
||||||
V(DNSListenAddress, LINELIST, NULL),
|
V(DNSListenAddress, LINELIST, NULL),
|
||||||
V(DownloadExtraInfo, BOOL, "0"),
|
V(DownloadExtraInfo, BOOL, "0"),
|
||||||
@ -1318,10 +1318,6 @@ options_transition_requires_fresh_tls_context(const or_options_t *old_options,
|
|||||||
if (!old_options)
|
if (!old_options)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if ((old_options->DynamicDHGroups != new_options->DynamicDHGroups)) {
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!opt_streq(old_options->TLSECGroup, new_options->TLSECGroup))
|
if (!opt_streq(old_options->TLSECGroup, new_options->TLSECGroup))
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
@ -1503,23 +1499,8 @@ options_act(const or_options_t *old_options)
|
|||||||
finish_daemon(options->DataDirectory);
|
finish_daemon(options->DataDirectory);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If needed, generate a new TLS DH prime according to the current torrc. */
|
/* Probably not needed any longer XXXX */
|
||||||
if (server_mode(options) && options->DynamicDHGroups) {
|
crypto_set_tls_dh_prime();
|
||||||
char *keydir = get_datadir_fname("keys");
|
|
||||||
if (check_private_dir(keydir, CPD_CREATE, options->User)) {
|
|
||||||
tor_free(keydir);
|
|
||||||
return -1;
|
|
||||||
}
|
|
||||||
tor_free(keydir);
|
|
||||||
|
|
||||||
if (!old_options || !old_options->DynamicDHGroups) {
|
|
||||||
char *fname = get_datadir_fname2("keys", "dynamic_dh_params");
|
|
||||||
crypto_set_tls_dh_prime(fname);
|
|
||||||
tor_free(fname);
|
|
||||||
}
|
|
||||||
} else { /* clients don't need a dynamic DH prime. */
|
|
||||||
crypto_set_tls_dh_prime(NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* We want to reinit keys as needed before we do much of anything else:
|
/* We want to reinit keys as needed before we do much of anything else:
|
||||||
keys are important, and other things can depend on them. */
|
keys are important, and other things can depend on them. */
|
||||||
|
@ -3384,8 +3384,6 @@ typedef struct {
|
|||||||
char *Address; /**< OR only: configured address for this onion router. */
|
char *Address; /**< OR only: configured address for this onion router. */
|
||||||
char *PidFile; /**< Where to store PID of Tor process. */
|
char *PidFile; /**< Where to store PID of Tor process. */
|
||||||
|
|
||||||
int DynamicDHGroups; /**< Dynamic generation of prime moduli for use in DH.*/
|
|
||||||
|
|
||||||
routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
|
routerset_t *ExitNodes; /**< Structure containing nicknames, digests,
|
||||||
* country codes and IP address patterns of ORs to
|
* country codes and IP address patterns of ORs to
|
||||||
* consider as exits. */
|
* consider as exits. */
|
||||||
|
@ -269,7 +269,7 @@ main(int c, const char **v)
|
|||||||
printf("Can't initialize crypto subsystem; exiting.\n");
|
printf("Can't initialize crypto subsystem; exiting.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
crypto_set_tls_dh_prime(NULL);
|
crypto_set_tls_dh_prime();
|
||||||
crypto_seed_rng(1);
|
crypto_seed_rng(1);
|
||||||
rep_hist_init();
|
rep_hist_init();
|
||||||
network_init();
|
network_init();
|
||||||
|
Loading…
Reference in New Issue
Block a user