[tor-commits] [tor/master] Make ECDHE group configurable: 224 for public, 256 for bridges (default)

nickm at torproject.org nickm at torproject.org
Wed Dec 26 03:13:09 UTC 2012


commit 25afecdbf999eb91ed9216be1f8b8cdf0f78135b
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue Dec 25 20:04:54 2012 -0500

    Make ECDHE group configurable: 224 for public, 256 for bridges (default)
---
 changes/tls_ecdhe   |   12 +++++++-----
 doc/tor.1.txt       |    6 ++++++
 src/common/tortls.c |   30 ++++++++++++++++++++++++------
 src/common/tortls.h |    7 ++++++-
 src/or/config.c     |   10 ++++++++++
 src/or/or.h         |    2 ++
 src/or/router.c     |   13 ++++++++++++-
 7 files changed, 67 insertions(+), 13 deletions(-)

diff --git a/changes/tls_ecdhe b/changes/tls_ecdhe
index 58a8f90..48c6384 100644
--- a/changes/tls_ecdhe
+++ b/changes/tls_ecdhe
@@ -1,10 +1,12 @@
   o Major features:
 
-    - Servers can now enable the ECDHE TLS ciphersuites when
-      available and appropriate. These ciphersuites, when used with
-      the P-256 elliptic curve, let us negotiate forward-secure TLS
-      secret keys more safely and more efficiently than with our
-      previous use of Diffie Hellman modulo a 1024-bit prime.
+    - Servers can now enable the ECDHE TLS ciphersuites when available
+      and appropriate. These ciphersuites let us negotiate forward-
+      secure TLS secret keys more safely and more efficiently than with
+      our previous use of Diffie Hellman modulo a 1024-bit prime.
+      By default, public servers prefer the (faster) P224 group, and
+      bridges prefer the (more common) P256 group; you can override this
+      with the TLSECGroup option.
 
       Enabling these ciphers was a little tricky, since for a long
       time, clients had been claiming to support them without
diff --git a/doc/tor.1.txt b/doc/tor.1.txt
index 85b7f4c..7d1742c 100644
--- a/doc/tor.1.txt
+++ b/doc/tor.1.txt
@@ -1527,6 +1527,12 @@ is non-zero):
 **GeoIPv6File** __filename__::
     A filename containing IPv6 GeoIP data, for use with by-country statistics.
 
+**TLSECGroup** **P224**|**P256**::
+    What EC group should we try to use for incoming TLS connections?
+    P224 is faster, but makes us stand out more. Has no effect if
+    we're a client, or if our OpenSSL version lacks support for ECDHE.
+    (Default: P224 for public servers; P256 for bridges.)
+
 **CellStatistics** **0**|**1**::
     When this option is enabled, Tor writes statistics on the mean time that
     cells spend in circuit queues to disk every 24 hours. (Default: 0)
diff --git a/src/common/tortls.c b/src/common/tortls.c
index 47b8f28..ce6c7d6 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -236,9 +236,11 @@ static X509* tor_tls_create_certificate(crypto_pk_t *rsa,
 static int tor_tls_context_init_one(tor_tls_context_t **ppcontext,
                                     crypto_pk_t *identity,
                                     unsigned int key_lifetime,
+                                    unsigned int flags,
                                     int is_client);
 static tor_tls_context_t *tor_tls_context_new(crypto_pk_t *identity,
                                               unsigned int key_lifetime,
+                                              unsigned int flags,
                                               int is_client);
 static int check_cert_lifetime_internal(int severity, const X509 *cert,
                                    int past_tolerance, int future_tolerance);
@@ -1098,17 +1100,20 @@ tor_tls_context_incref(tor_tls_context_t *ctx)
 /** Create new global client and server TLS contexts.
  *
  * If <b>server_identity</b> is NULL, this will not generate a server
- * TLS context. If <b>is_public_server</b> is non-zero, this will use
+ * TLS context. If TOR_TLS_CTX_IS_PUBLIC_SERVER is set in <b>flags</b>, use
  * the same TLS context for incoming and outgoing connections, and
- * ignore <b>client_identity</b>. */
+ * ignore <b>client_identity</b>. If one of TOR_TLS_CTX_USE_ECDHE_P{224,256}
+ * is set in <b>flags</b>, use that ECDHE group if possible; otherwise use
+ * the default ECDHE group. */
 int
-tor_tls_context_init(int is_public_server,
+tor_tls_context_init(unsigned flags,
                      crypto_pk_t *client_identity,
                      crypto_pk_t *server_identity,
                      unsigned int key_lifetime)
 {
   int rv1 = 0;
   int rv2 = 0;
+  const int is_public_server = flags & TOR_TLS_CTX_IS_PUBLIC_SERVER;
 
   if (is_public_server) {
     tor_tls_context_t *new_ctx;
@@ -1118,7 +1123,7 @@ tor_tls_context_init(int is_public_server,
 
     rv1 = tor_tls_context_init_one(&server_tls_context,
                                    server_identity,
-                                   key_lifetime, 0);
+                                   key_lifetime, flags, 0);
 
     if (rv1 >= 0) {
       new_ctx = server_tls_context;
@@ -1135,6 +1140,7 @@ tor_tls_context_init(int is_public_server,
       rv1 = tor_tls_context_init_one(&server_tls_context,
                                      server_identity,
                                      key_lifetime,
+                                     flags,
                                      0);
     } else {
       tor_tls_context_t *old_ctx = server_tls_context;
@@ -1148,6 +1154,7 @@ tor_tls_context_init(int is_public_server,
     rv2 = tor_tls_context_init_one(&client_tls_context,
                                    client_identity,
                                    key_lifetime,
+                                   flags,
                                    1);
   }
 
@@ -1164,10 +1171,12 @@ static int
 tor_tls_context_init_one(tor_tls_context_t **ppcontext,
                          crypto_pk_t *identity,
                          unsigned int key_lifetime,
+                         unsigned int flags,
                          int is_client)
 {
   tor_tls_context_t *new_ctx = tor_tls_context_new(identity,
                                                    key_lifetime,
+                                                   flags,
                                                    is_client);
   tor_tls_context_t *old_ctx = *ppcontext;
 
@@ -1191,7 +1200,7 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext,
  */
 static tor_tls_context_t *
 tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
-                    int is_client)
+                    unsigned flags, int is_client)
 {
   crypto_pk_t *rsa = NULL, *rsa_auth = NULL;
   EVP_PKEY *pkey = NULL;
@@ -1362,9 +1371,18 @@ tor_tls_context_new(crypto_pk_t *identity, unsigned int key_lifetime,
 #if (!defined(OPENSSL_NO_EC) &&                         \
      OPENSSL_VERSION_NUMBER >= OPENSSL_V_SERIES(1,0,0))
   if (! is_client) {
+    int nid;
     EC_KEY *ec_key;
+    if (flags & TOR_TLS_CTX_USE_ECDHE_P224)
+      nid = NID_secp224r1;
+    else if (flags & TOR_TLS_CTX_USE_ECDHE_P256)
+      nid = NID_X9_62_prime256v1;
+    else if (flags & TOR_TLS_CTX_IS_PUBLIC_SERVER)
+      nid = NID_X9_62_prime256v1;
+    else
+      nid = NID_secp224r1;
     /* Use P-256 for ECDHE. */
-    ec_key = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
+    ec_key = EC_KEY_new_by_curve_name(nid);
     if (ec_key != NULL) /*XXXX Handle errors? */
       SSL_CTX_set_tmp_ecdh(result->ctx, ec_key);
     EC_KEY_free(ec_key);
diff --git a/src/common/tortls.h b/src/common/tortls.h
index 8881827..df3ab87 100644
--- a/src/common/tortls.h
+++ b/src/common/tortls.h
@@ -54,7 +54,12 @@ const char *tor_tls_err_to_string(int err);
 void tor_tls_get_state_description(tor_tls_t *tls, char *buf, size_t sz);
 
 void tor_tls_free_all(void);
-int tor_tls_context_init(int is_public_server,
+
+#define TOR_TLS_CTX_IS_PUBLIC_SERVER (1u<<0)
+#define TOR_TLS_CTX_USE_ECDHE_P256   (1u<<1)
+#define TOR_TLS_CTX_USE_ECDHE_P224   (1u<<2)
+
+int tor_tls_context_init(unsigned flags,
                          crypto_pk_t *client_identity,
                          crypto_pk_t *server_identity,
                          unsigned int key_lifetime);
diff --git a/src/or/config.c b/src/or/config.c
index 1df10e1..b81edf7 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -372,6 +372,7 @@ static config_var_t option_vars_[] = {
   OBSOLETE("TestVia"),
   V(TokenBucketRefillInterval,   MSEC_INTERVAL, "100 msec"),
   V(Tor2webMode,                 BOOL,     "0"),
+  V(TLSECGroup,                  STRING,   NULL),
   V(TrackHostExits,              CSV,      NULL),
   V(TrackHostExitsExpire,        INTERVAL, "30 minutes"),
   OBSOLETE("TrafficShaping"),
@@ -1193,6 +1194,9 @@ options_transition_requires_fresh_tls_context(const or_options_t *old_options,
     return 1;
   }
 
+  if (!opt_streq(old_options->TLSECGroup, new_options->TLSECGroup))
+    return 1;
+
   return 0;
 }
 
@@ -2301,6 +2305,12 @@ options_validate(or_options_t *old_options, or_options_t *options,
     }
   }
 
+  if (options->TLSECGroup && (strcasecmp(options->TLSECGroup, "P256") &&
+                              strcasecmp(options->TLSECGroup, "P224"))) {
+    COMPLAIN("Unrecognized TLSECGroup: Falling back to the default.");
+    tor_free(options->TLSECGroup);
+  }
+
   if (options->ExcludeNodes && options->StrictNodes) {
     COMPLAIN("You have asked to exclude certain relays from all positions "
              "in your circuits. Expect hidden services and other Tor "
diff --git a/src/or/or.h b/src/or/or.h
index 3a8e50c..a65ca44 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -3854,6 +3854,8 @@ typedef struct {
 
   int IPv6Exit; /**< Do we support exiting to IPv6 addresses? */
 
+  char *TLSECGroup; /**< One of "P256", "P224", or nil for auto */
+
 } or_options_t;
 
 /** Persistent state for an onion router, as saved to disk. */
diff --git a/src/or/router.c b/src/or/router.c
index 5786103..c7380cb 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -491,7 +491,18 @@ v3_authority_check_key_expiry(void)
 int
 router_initialize_tls_context(void)
 {
-  return tor_tls_context_init(public_server_mode(get_options()),
+  unsigned int flags = 0;
+  const or_options_t *options = get_options();
+  if (public_server_mode(options))
+    flags |= TOR_TLS_CTX_IS_PUBLIC_SERVER;
+  if (options->TLSECGroup) {
+    if (!strcasecmp(options->TLSECGroup, "P256"))
+      flags |= TOR_TLS_CTX_USE_ECDHE_P256;
+    else if (!strcasecmp(options->TLSECGroup, "P224"))
+      flags |= TOR_TLS_CTX_USE_ECDHE_P224;
+  }
+
+  return tor_tls_context_init(flags,
                               get_tlsclient_identity_key(),
                               server_mode(get_options()) ?
                               get_server_identity_key() : NULL,





More information about the tor-commits mailing list