From 5ed73e3807d90dd0a3a2e5542f98a0a58374a066 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jan 2011 16:03:14 -0500 Subject: [PATCH] Make the DH parameter we use for TLS match the one from Apache's mod_ssl Our regular DH parameters that we use for circuit and rendezvous crypto are unchanged. This is yet another small step on the path of protocol fingerprinting resistance. --- changes/dhparam | 3 +++ src/common/crypto.c | 34 ++++++++++++++++++++++++++++------ src/common/crypto.h | 5 ++++- src/common/tortls.c | 2 +- src/or/onion.c | 4 ++-- src/or/rendclient.c | 2 +- src/or/rendservice.c | 2 +- src/test/test_crypto.c | 4 ++-- 8 files changed, 42 insertions(+), 14 deletions(-) create mode 100644 changes/dhparam diff --git a/changes/dhparam b/changes/dhparam new file mode 100644 index 0000000000..cb31243ba9 --- /dev/null +++ b/changes/dhparam @@ -0,0 +1,3 @@ + o Minor features + - Adjust our TLS Diffie-Hellman parameters to match those used by + Apache's mod_ssl. diff --git a/src/common/crypto.c b/src/common/crypto.c index e847d8c033..5264fd8085 100644 --- a/src/common/crypto.c +++ b/src/common/crypto.c @@ -1685,8 +1685,10 @@ crypto_hmac_sha1(char *hmac_out, /* DH */ -/** Shared P parameter for our DH key exchanged. */ +/** 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. */ +static BIGNUM *dh_param_p_tls = NULL; /** Shared G parameter for our DH key exchanges. */ static BIGNUM *dh_param_g = NULL; @@ -1695,14 +1697,16 @@ static BIGNUM *dh_param_g = NULL; static void init_dh_param(void) { - BIGNUM *p, *g; + BIGNUM *p, *p2, *g; int r; - if (dh_param_p && dh_param_g) + if (dh_param_p && dh_param_g && dh_param_p_tls) return; p = BN_new(); + p2 = BN_new(); g = BN_new(); tor_assert(p); + tor_assert(p2); tor_assert(g); /* This is from rfc2409, section 6.2. It's a safe prime, and @@ -1716,10 +1720,20 @@ init_dh_param(void) "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 */ + 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; + dh_param_p_tls = p2; dh_param_g = g; } @@ -1728,18 +1742,26 @@ init_dh_param(void) /** Allocate and return a new DH object for a key exchange. */ crypto_dh_env_t * -crypto_dh_new(void) +crypto_dh_new(int dh_type) { crypto_dh_env_t *res = tor_malloc_zero(sizeof(crypto_dh_env_t)); + tor_assert(dh_type == DH_TYPE_CIRCUIT || dh_type == DH_TYPE_TLS || + dh_type == DH_TYPE_REND); + if (!dh_param_p) init_dh_param(); if (!(res->dh = DH_new())) goto err; - if (!(res->dh->p = BN_dup(dh_param_p))) - goto err; + if (dh_type == DH_TYPE_TLS) { + if (!(res->dh->p = BN_dup(dh_param_p_tls))) + goto err; + } else { + if (!(res->dh->p = BN_dup(dh_param_p))) + goto err; + } if (!(res->dh->g = BN_dup(dh_param_g))) goto err; diff --git a/src/common/crypto.h b/src/common/crypto.h index c306bec276..7134956731 100644 --- a/src/common/crypto.h +++ b/src/common/crypto.h @@ -195,7 +195,10 @@ void crypto_hmac_sha1(char *hmac_out, const char *msg, size_t msg_len); /* Key negotiation */ -crypto_dh_env_t *crypto_dh_new(void); +#define DH_TYPE_CIRCUIT 1 +#define DH_TYPE_REND 2 +#define DH_TYPE_TLS 3 +crypto_dh_env_t *crypto_dh_new(int dh_type); int crypto_dh_get_bytes(crypto_dh_env_t *dh); int crypto_dh_generate_public(crypto_dh_env_t *dh); int crypto_dh_get_public(crypto_dh_env_t *dh, char *pubkey_out, diff --git a/src/common/tortls.c b/src/common/tortls.c index 9d22657f6d..8ad0f2f310 100644 --- a/src/common/tortls.c +++ b/src/common/tortls.c @@ -807,7 +807,7 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime) if (!SSL_CTX_check_private_key(result->ctx)) goto error; { - crypto_dh_env_t *dh = crypto_dh_new(); + crypto_dh_env_t *dh = crypto_dh_new(DH_TYPE_TLS); SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_env_get_dh(dh)); crypto_dh_free(dh); } diff --git a/src/or/onion.c b/src/or/onion.c index 323e0003e6..9aa16d2747 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -184,7 +184,7 @@ onion_skin_create(crypto_pk_env_t *dest_router_key, *handshake_state_out = NULL; memset(onion_skin_out, 0, ONIONSKIN_CHALLENGE_LEN); - if (!(dh = crypto_dh_new())) + if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT))) goto err; dhbytes = crypto_dh_get_bytes(dh); @@ -258,7 +258,7 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/ goto err; } - dh = crypto_dh_new(); + dh = crypto_dh_new(DH_TYPE_CIRCUIT); if (crypto_dh_get_public(dh, handshake_reply_out, DH_KEY_LEN)) { log_info(LD_GENERAL, "crypto_dh_get_public failed."); goto err; diff --git a/src/or/rendclient.c b/src/or/rendclient.c index 1306fe0710..ba5987c698 100644 --- a/src/or/rendclient.c +++ b/src/or/rendclient.c @@ -121,7 +121,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc, cpath = rendcirc->build_state->pending_final_cpath = tor_malloc_zero(sizeof(crypt_path_t)); cpath->magic = CRYPT_PATH_MAGIC; - if (!(cpath->dh_handshake_state = crypto_dh_new())) { + if (!(cpath->dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) { log_warn(LD_BUG, "Internal error: couldn't allocate DH."); goto err; } diff --git a/src/or/rendservice.c b/src/or/rendservice.c index f1480e0b7f..45039822f8 100644 --- a/src/or/rendservice.c +++ b/src/or/rendservice.c @@ -1100,7 +1100,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request, } /* Try DH handshake... */ - dh = crypto_dh_new(); + dh = crypto_dh_new(DH_TYPE_REND); if (!dh || crypto_dh_generate_public(dh)<0) { log_warn(LD_BUG,"Internal error: couldn't build DH state " "or generate public key."); diff --git a/src/test/test_crypto.c b/src/test/test_crypto.c index 8093c9c898..6ea7f295ed 100644 --- a/src/test/test_crypto.c +++ b/src/test/test_crypto.c @@ -12,8 +12,8 @@ static void test_crypto_dh(void) { - crypto_dh_env_t *dh1 = crypto_dh_new(); - crypto_dh_env_t *dh2 = crypto_dh_new(); + crypto_dh_env_t *dh1 = crypto_dh_new(DH_TYPE_CIRCUIT); + crypto_dh_env_t *dh2 = crypto_dh_new(DH_TYPE_CIRCUIT); char p1[DH_BYTES]; char p2[DH_BYTES]; char s1[DH_BYTES];