[tor-commits] [tor/release-0.2.1] Don't send a certificate chain on outgoing TLS connections from non-relays

arma at torproject.org arma at torproject.org
Thu Oct 27 23:51:30 UTC 2011


commit 638fdedcf16cf7d6f7c586d36f7ef335c1c9714f
Author: Nick Mathewson <nickm at torproject.org>
Date:   Sun Oct 23 16:06:06 2011 +0000

    Don't send a certificate chain on outgoing TLS connections from non-relays
---
 changes/issue-2011-10-19L |   12 ++++++
 src/common/tortls.c       |   93 ++++++++++++++++++++++++++-------------------
 2 files changed, 66 insertions(+), 39 deletions(-)

diff --git a/changes/issue-2011-10-19L b/changes/issue-2011-10-19L
new file mode 100644
index 0000000..972823e
--- /dev/null
+++ b/changes/issue-2011-10-19L
@@ -0,0 +1,12 @@
+  o Security fixes:
+
+    - Don't send TLS certificate chains on outgoing OR connections
+      from clients and bridges.  Previously, each client or bridge
+      would use a single cert chain for all outgoing OR connections
+      for up to 24 hours, which allowed any relay connected to by a
+      client or bridge to determine which entry guards it is using.
+      This is a potential user-tracing bug for *all* users; everyone
+      who uses Tor's client or hidden service functionality should
+      upgrade.  Fixes CVE-2011-2768.  Bugfix on FIXME; found by
+      frosty_un.
+
diff --git a/src/common/tortls.c b/src/common/tortls.c
index c78a9ec..cc805f8 100644
--- a/src/common/tortls.c
+++ b/src/common/tortls.c
@@ -186,9 +186,11 @@ static X509* tor_tls_create_certificate(crypto_pk_env_t *rsa,
 static void tor_tls_unblock_renegotiation(tor_tls_t *tls);
 static int tor_tls_context_init_one(tor_tls_context_t **ppcontext,
                                     crypto_pk_env_t *identity,
-                                    unsigned int key_lifetime);
+                                    unsigned int key_lifetime,
+                                    int is_client);
 static tor_tls_context_t *tor_tls_context_new(crypto_pk_env_t *identity,
-                                              unsigned int key_lifetime);
+                                              unsigned int key_lifetime,
+                                              int is_client);
 
 /** Global TLS contexts. We keep them here because nobody else needs
  * to touch them. */
@@ -624,7 +626,7 @@ tor_tls_context_init(int is_public_server,
 
     rv1 = tor_tls_context_init_one(&server_tls_context,
                                    server_identity,
-                                   key_lifetime);
+                                   key_lifetime, 0);
 
     if (rv1 >= 0) {
       new_ctx = server_tls_context;
@@ -640,7 +642,8 @@ tor_tls_context_init(int is_public_server,
     if (server_identity != NULL) {
       rv1 = tor_tls_context_init_one(&server_tls_context,
                                      server_identity,
-                                     key_lifetime);
+                                     key_lifetime,
+                                     0);
     } else {
       tor_tls_context_t *old_ctx = server_tls_context;
       server_tls_context = NULL;
@@ -652,7 +655,8 @@ tor_tls_context_init(int is_public_server,
 
     rv2 = tor_tls_context_init_one(&client_tls_context,
                                    client_identity,
-                                   key_lifetime);
+                                   key_lifetime,
+                                   1);
   }
 
   return rv1 < rv2 ? rv1 : rv2;
@@ -669,10 +673,12 @@ tor_tls_context_init(int is_public_server,
 static int
 tor_tls_context_init_one(tor_tls_context_t **ppcontext,
                          crypto_pk_env_t *identity,
-                         unsigned int key_lifetime)
+                         unsigned int key_lifetime,
+                         int is_client)
 {
   tor_tls_context_t *new_ctx = tor_tls_context_new(identity,
-                                                   key_lifetime);
+                                                   key_lifetime,
+                                                   is_client);
   tor_tls_context_t *old_ctx = *ppcontext;
 
   if (new_ctx != NULL) {
@@ -694,7 +700,8 @@ tor_tls_context_init_one(tor_tls_context_t **ppcontext,
  * certificate.
  */
 static tor_tls_context_t *
-tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
+tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime,
+                    int is_client)
 {
   crypto_pk_env_t *rsa = NULL;
   EVP_PKEY *pkey = NULL;
@@ -711,22 +718,26 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
     goto error;
   if (crypto_pk_generate_key(rsa)<0)
     goto error;
-  /* Create certificate signed by identity key. */
-  cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
-                                    key_lifetime);
-  /* Create self-signed certificate for identity key. */
-  idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
-                                      IDENTITY_CERT_LIFETIME);
-  if (!cert || !idcert) {
-    log(LOG_WARN, LD_CRYPTO, "Error creating certificate");
-    goto error;
+  if (!is_client) {
+    /* Create certificate signed by identity key. */
+    cert = tor_tls_create_certificate(rsa, identity, nickname, nn2,
+                                      key_lifetime);
+    /* Create self-signed certificate for identity key. */
+    idcert = tor_tls_create_certificate(identity, identity, nn2, nn2,
+                                        IDENTITY_CERT_LIFETIME);
+    if (!cert || !idcert) {
+      log(LOG_WARN, LD_CRYPTO, "Error creating certificate");
+      goto error;
+    }
   }
 
   result = tor_malloc_zero(sizeof(tor_tls_context_t));
   result->refcnt = 1;
-  result->my_cert = X509_dup(cert);
-  result->my_id_cert = X509_dup(idcert);
-  result->key = crypto_pk_dup_key(rsa);
+  if (!is_client) {
+    result->my_cert = X509_dup(cert);
+    result->my_id_cert = X509_dup(idcert);
+    result->key = crypto_pk_dup_key(rsa);
+  }
 
 #ifdef EVERYONE_HAS_AES
   /* Tell OpenSSL to only use TLS1 */
@@ -758,27 +769,31 @@ tor_tls_context_new(crypto_pk_env_t *identity, unsigned int key_lifetime)
 #ifdef SSL_MODE_RELEASE_BUFFERS
   SSL_CTX_set_mode(result->ctx, SSL_MODE_RELEASE_BUFFERS);
 #endif
-  if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
-    goto error;
-  X509_free(cert); /* We just added a reference to cert. */
-  cert=NULL;
-  if (idcert) {
-    X509_STORE *s = SSL_CTX_get_cert_store(result->ctx);
-    tor_assert(s);
-    X509_STORE_add_cert(s, idcert);
-    X509_free(idcert); /* The context now owns the reference to idcert */
-    idcert = NULL;
+  if (! is_client) {
+    if (cert && !SSL_CTX_use_certificate(result->ctx,cert))
+      goto error;
+    X509_free(cert); /* We just added a reference to cert. */
+    cert=NULL;
+    if (idcert) {
+      X509_STORE *s = SSL_CTX_get_cert_store(result->ctx);
+      tor_assert(s);
+      X509_STORE_add_cert(s, idcert);
+      X509_free(idcert); /* The context now owns the reference to idcert */
+      idcert = NULL;
+    }
   }
   SSL_CTX_set_session_cache_mode(result->ctx, SSL_SESS_CACHE_OFF);
-  tor_assert(rsa);
-  if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
-    goto error;
-  if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
-    goto error;
-  EVP_PKEY_free(pkey);
-  pkey = NULL;
-  if (!SSL_CTX_check_private_key(result->ctx))
-    goto error;
+  if (!is_client) {
+    tor_assert(rsa);
+    if (!(pkey = _crypto_pk_env_get_evp_pkey(rsa,1)))
+      goto error;
+    if (!SSL_CTX_use_PrivateKey(result->ctx, pkey))
+      goto error;
+    EVP_PKEY_free(pkey);
+    pkey = NULL;
+    if (!SSL_CTX_check_private_key(result->ctx))
+      goto error;
+  }
   {
     crypto_dh_env_t *dh = crypto_dh_new(DH_TYPE_TLS);
     SSL_CTX_set_tmp_dh(result->ctx, _crypto_dh_env_get_dh(dh));





More information about the tor-commits mailing list