[tor-commits] [tor/master] Downgrade 'invalid result from curve25519 handshake: 4' warning

nickm at torproject.org nickm at torproject.org
Mon Feb 2 21:31:42 UTC 2015


commit fb91d647acdf0560fc7479d72eeea52e4e6ff41d
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Oct 16 13:26:42 2014 -0400

    Downgrade 'invalid result from curve25519 handshake: 4' warning
    
    Also, refactor the way we handle failed handshakes so that this
    warning doesn't propagate itself to "onion_skin_client_handshake
    failed" and "circuit_finish_handshake failed" and
    "connection_edge_process_relay_cell (at origin) failed."
    
    Resolves warning from 9635.
---
 changes/bug9635         |    3 +++
 src/or/circuitbuild.c   |   12 +++++++++---
 src/or/command.c        |    1 -
 src/or/onion.c          |   24 +++++++++++++++---------
 src/or/onion.h          |    3 ++-
 src/or/onion_fast.c     |   10 ++++++----
 src/or/onion_fast.h     |    3 ++-
 src/or/onion_ntor.c     |   19 +++++++++++++++----
 src/or/onion_ntor.h     |    3 ++-
 src/or/onion_tap.c      |   10 ++++++----
 src/or/onion_tap.h      |    3 ++-
 src/or/relay.c          |    5 +++--
 src/test/bench.c        |    6 ++++--
 src/test/test.c         |   11 ++++++-----
 src/test/test_ntor_cl.c |    2 +-
 15 files changed, 76 insertions(+), 39 deletions(-)

diff --git a/changes/bug9635 b/changes/bug9635
new file mode 100644
index 0000000..17a2ea5
--- /dev/null
+++ b/changes/bug9635
@@ -0,0 +1,3 @@
+  o Downgraded warnings:
+    - Don't warn when we've attempted to contact a relay using the wrong
+      ntor onion key. Closes ticket 9635.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index 897f90f..873eba1 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -1256,8 +1256,10 @@ circuit_finish_handshake(origin_circuit_t *circ,
   crypt_path_t *hop;
   int rv;
 
-  if ((rv = pathbias_count_build_attempt(circ)) < 0)
+  if ((rv = pathbias_count_build_attempt(circ)) < 0) {
+    log_warn(LD_CIRC, "pathbias_count_build_attempt failed: %d", rv);
     return rv;
+  }
 
   if (circ->cpath->state == CPATH_STATE_AWAITING_KEYS) {
     hop = circ->cpath;
@@ -1271,12 +1273,15 @@ circuit_finish_handshake(origin_circuit_t *circ,
   tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS);
 
   {
+    const char *msg = NULL;
     if (onion_skin_client_handshake(hop->handshake_state.tag,
                                     &hop->handshake_state,
                                     reply->reply, reply->handshake_len,
                                     (uint8_t*)keys, sizeof(keys),
-                                    (uint8_t*)hop->rend_circ_nonce) < 0) {
-      log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
+                                    (uint8_t*)hop->rend_circ_nonce,
+                                    &msg) < 0) {
+      if (msg)
+        log_warn(LD_CIRC,"onion_skin_client_handshake failed: %s", msg);
       return -END_CIRC_REASON_TORPROTOCOL;
     }
   }
@@ -1284,6 +1289,7 @@ circuit_finish_handshake(origin_circuit_t *circ,
   onion_handshake_state_release(&hop->handshake_state);
 
   if (circuit_init_cpath_crypto(hop, keys, 0)<0) {
+    log_warn(LD_BUG, "Couldn't initialize cpath crypto");
     return -END_CIRC_REASON_TORPROTOCOL;
   }
 
diff --git a/src/or/command.c b/src/or/command.c
index 1f6f93a..1f8d0ba 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -398,7 +398,6 @@ command_process_created_cell(cell_t *cell, channel_t *chan)
     log_debug(LD_OR,"at OP. Finishing handshake.");
     if ((err_reason = circuit_finish_handshake(origin_circ,
                                         &extended_cell.created_cell)) < 0) {
-      log_warn(LD_OR,"circuit_finish_handshake failed.");
       circuit_mark_for_close(circ, -err_reason);
       return;
     }
diff --git a/src/or/onion.c b/src/or/onion.c
index ae39f45..b5e801d 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -541,13 +541,15 @@ onion_skin_server_handshake(int type,
  * bytes worth of key material in <b>keys_out_len</b>, set
  * <b>rend_authenticator_out</b> to the "KH" field that can be used to
  * establish introduction points at this hop, and return 0. On failure,
- * return -1. */
+ * return -1, and set *msg_out to an error message if this is worth
+ * complaining to the usre about. */
 int
 onion_skin_client_handshake(int type,
                       const onion_handshake_state_t *handshake_state,
                       const uint8_t *reply, size_t reply_len,
                       uint8_t *keys_out, size_t keys_out_len,
-                      uint8_t *rend_authenticator_out)
+                      uint8_t *rend_authenticator_out,
+                      const char **msg_out)
 {
   if (handshake_state->tag != type)
     return -1;
@@ -555,12 +557,14 @@ onion_skin_client_handshake(int type,
   switch (type) {
   case ONION_HANDSHAKE_TYPE_TAP:
     if (reply_len != TAP_ONIONSKIN_REPLY_LEN) {
-      log_warn(LD_CIRC, "TAP reply was not of the correct length.");
+      if (msg_out)
+        *msg_out = "TAP reply was not of the correct length.";
       return -1;
     }
     if (onion_skin_TAP_client_handshake(handshake_state->u.tap,
                                         (const char*)reply,
-                                        (char *)keys_out, keys_out_len) < 0)
+                                        (char *)keys_out, keys_out_len,
+                                        msg_out) < 0)
       return -1;
 
     memcpy(rend_authenticator_out, reply+DH_KEY_LEN, DIGEST_LEN);
@@ -568,11 +572,12 @@ onion_skin_client_handshake(int type,
     return 0;
   case ONION_HANDSHAKE_TYPE_FAST:
     if (reply_len != CREATED_FAST_LEN) {
-      log_warn(LD_CIRC, "CREATED_FAST reply was not of the correct length.");
+      if (msg_out)
+        *msg_out = "TAP reply was not of the correct length.";
       return -1;
     }
     if (fast_client_handshake(handshake_state->u.fast, reply,
-                              keys_out, keys_out_len) < 0)
+                              keys_out, keys_out_len, msg_out) < 0)
       return -1;
 
     memcpy(rend_authenticator_out, reply+DIGEST_LEN, DIGEST_LEN);
@@ -580,15 +585,16 @@ onion_skin_client_handshake(int type,
 #ifdef CURVE25519_ENABLED
   case ONION_HANDSHAKE_TYPE_NTOR:
     if (reply_len < NTOR_REPLY_LEN) {
-      log_warn(LD_CIRC, "ntor reply was not of the correct length.");
+      if (msg_out)
+        *msg_out = "ntor reply was not of the correct length.";
       return -1;
     }
     {
       size_t keys_tmp_len = keys_out_len + DIGEST_LEN;
       uint8_t *keys_tmp = tor_malloc(keys_tmp_len);
       if (onion_skin_ntor_client_handshake(handshake_state->u.ntor,
-                                           reply,
-                                           keys_tmp, keys_tmp_len) < 0) {
+                                        reply,
+                                        keys_tmp, keys_tmp_len, msg_out) < 0) {
         tor_free(keys_tmp);
         return -1;
       }
diff --git a/src/or/onion.h b/src/or/onion.h
index d62f032..1a53896 100644
--- a/src/or/onion.h
+++ b/src/or/onion.h
@@ -51,7 +51,8 @@ int onion_skin_client_handshake(int type,
                       const onion_handshake_state_t *handshake_state,
                       const uint8_t *reply, size_t reply_len,
                       uint8_t *keys_out, size_t key_out_len,
-                      uint8_t *rend_authenticator_out);
+                      uint8_t *rend_authenticator_out,
+                      const char **msg_out);
 
 /** A parsed CREATE, CREATE_FAST, or CREATE2 cell. */
 typedef struct create_cell_t {
diff --git a/src/or/onion_fast.c b/src/or/onion_fast.c
index 38b62de..30f60e8 100644
--- a/src/or/onion_fast.c
+++ b/src/or/onion_fast.c
@@ -92,7 +92,8 @@ int
 fast_client_handshake(const fast_handshake_state_t *handshake_state,
                       const uint8_t *handshake_reply_out,/*DIGEST_LEN*2 bytes*/
                       uint8_t *key_out,
-                      size_t key_out_len)
+                      size_t key_out_len,
+                      const char **msg_out)
 {
   uint8_t tmp[DIGEST_LEN+DIGEST_LEN];
   uint8_t *out;
@@ -104,13 +105,14 @@ fast_client_handshake(const fast_handshake_state_t *handshake_state,
   out_len = key_out_len+DIGEST_LEN;
   out = tor_malloc(out_len);
   if (crypto_expand_key_material_TAP(tmp, sizeof(tmp), out, out_len)) {
-    log_warn(LD_CIRC, "Failed to expand key material");
+    if (msg_out)
+      *msg_out = "Failed to expand key material";
     goto done;
   }
   if (tor_memneq(out, handshake_reply_out+DIGEST_LEN, DIGEST_LEN)) {
     /* H(K) does *not* match. Something fishy. */
-    log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on fast handshake. "
-             "Bug or attack.");
+    if (msg_out)
+      *msg_out = "Digest DOES NOT MATCH on fast handshake. Bug or attack.";
     goto done;
   }
   memcpy(key_out, out+DIGEST_LEN, key_out_len);
diff --git a/src/or/onion_fast.h b/src/or/onion_fast.h
index 8c07837..e6c213e 100644
--- a/src/or/onion_fast.h
+++ b/src/or/onion_fast.h
@@ -32,7 +32,8 @@ int fast_server_handshake(const uint8_t *message_in,
 int fast_client_handshake(const fast_handshake_state_t *handshake_state,
                           const uint8_t *handshake_reply_out,
                           uint8_t *key_out,
-                          size_t key_out_len);
+                          size_t key_out_len,
+                          const char **msg_out);
 
 #endif
 
diff --git a/src/or/onion_ntor.c b/src/or/onion_ntor.c
index ef501f6..32d5344 100644
--- a/src/or/onion_ntor.c
+++ b/src/or/onion_ntor.c
@@ -3,8 +3,8 @@
 
 #include "orconfig.h"
 
-#include "crypto.h"
 #define ONION_NTOR_PRIVATE
+#include "crypto.h"
 #include "onion_ntor.h"
 #include "torlog.h"
 #include "util.h"
@@ -226,7 +226,8 @@ onion_skin_ntor_client_handshake(
                              const ntor_handshake_state_t *handshake_state,
                              const uint8_t *handshake_reply,
                              uint8_t *key_out,
-                             size_t key_out_len)
+                             size_t key_out_len,
+                             const char **msg_out)
 {
   const tweakset_t *T = &proto1_tweaks;
   /* Sensitive stack-allocated material. Kept in an anonymous struct to make
@@ -291,8 +292,18 @@ onion_skin_ntor_client_handshake(
 
   memwipe(&s, 0, sizeof(s));
 
-  if (bad) {
-    log_warn(LD_PROTOCOL, "Invalid result from curve25519 handshake: %d", bad);
+  if (bad && msg_out) {
+    if (bad & 4) {
+      *msg_out = NULL; /* Don't report this one; we probably just had the
+                        * wrong onion key.*/
+      log_fn(LOG_INFO, LD_PROTOCOL,
+             "Invalid result from curve25519 handshake: %d", bad);
+    }
+    if (bad & 3) {
+      *msg_out = "Zero output from curve25519 handshake";
+      log_fn(LOG_WARN, LD_PROTOCOL,
+             "Invalid result from curve25519 handshake: %d", bad);
+    }
   }
 
   return bad ? -1 : 0;
diff --git a/src/or/onion_ntor.h b/src/or/onion_ntor.h
index c942e6e..3fd6c88 100644
--- a/src/or/onion_ntor.h
+++ b/src/or/onion_ntor.h
@@ -37,7 +37,8 @@ int onion_skin_ntor_client_handshake(
                              const ntor_handshake_state_t *handshake_state,
                              const uint8_t *handshake_reply,
                              uint8_t *key_out,
-                             size_t key_out_len);
+                             size_t key_out_len,
+                             const char **msg_out);
 
 #ifdef ONION_NTOR_PRIVATE
 
diff --git a/src/or/onion_tap.c b/src/or/onion_tap.c
index 65f8275..668c48c 100644
--- a/src/or/onion_tap.c
+++ b/src/or/onion_tap.c
@@ -183,7 +183,8 @@ int
 onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
             const char *handshake_reply, /* TAP_ONIONSKIN_REPLY_LEN bytes */
             char *key_out,
-            size_t key_out_len)
+            size_t key_out_len,
+            const char **msg_out)
 {
   ssize_t len;
   char *key_material=NULL;
@@ -196,14 +197,15 @@ onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
                                  handshake_reply, DH_KEY_LEN, key_material,
                                  key_material_len);
   if (len < 0) {
-    log_warn(LD_PROTOCOL,"DH computation failed.");
+    if (msg_out)
+      *msg_out = "DH computation failed.";
     goto err;
   }
 
   if (tor_memneq(key_material, handshake_reply+DH_KEY_LEN, DIGEST_LEN)) {
     /* H(K) does *not* match. Something fishy. */
-    log_warn(LD_PROTOCOL,"Digest DOES NOT MATCH on onion handshake. "
-             "Bug or attack.");
+    if (msg_out)
+      *msg_out = "Digest DOES NOT MATCH on onion handshake. Bug or attack.";
     goto err;
   }
 
diff --git a/src/or/onion_tap.h b/src/or/onion_tap.h
index b978b66..3b23d62 100644
--- a/src/or/onion_tap.h
+++ b/src/or/onion_tap.h
@@ -31,7 +31,8 @@ int onion_skin_TAP_server_handshake(const char *onion_skin,
 int onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
                                 const char *handshake_reply,
                                 char *key_out,
-                                size_t key_out_len);
+                                size_t key_out_len,
+                                const char **msg_out);
 
 #endif
 
diff --git a/src/or/relay.c b/src/or/relay.c
index 9407df0..73961de 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -1643,8 +1643,9 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ,
         }
         if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ),
                                          &extended_cell.created_cell)) < 0) {
-          log_warn(domain,"circuit_finish_handshake failed.");
-          return reason;
+          circuit_mark_for_close(circ, -reason);
+          return 0; /* We don't want to cause a warning, so we mark the circuit
+                     * here. */
         }
       }
       if ((reason=circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)))<0) {
diff --git a/src/test/bench.c b/src/test/bench.c
index f6c3362..fd374b5 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -162,7 +162,8 @@ bench_onion_TAP(void)
     char key_out[CPATH_KEY_MATERIAL_LEN];
     int s;
     dh = crypto_dh_dup(dh_out);
-    s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out));
+    s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out),
+                                        NULL);
     crypto_dh_free(dh);
     tor_assert(s == 0);
   }
@@ -222,7 +223,8 @@ bench_onion_ntor(void)
   for (i = 0; i < iters; ++i) {
     uint8_t key_out[CPATH_KEY_MATERIAL_LEN];
     int s;
-    s = onion_skin_ntor_client_handshake(state, or, key_out, sizeof(key_out));
+    s = onion_skin_ntor_client_handshake(state, or, key_out, sizeof(key_out),
+                                         NULL);
     tor_assert(s == 0);
   }
   end = perftime();
diff --git a/src/test/test.c b/src/test/test.c
index 8bce9c9..e6f79a6 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -264,7 +264,8 @@ test_onion_handshake(void)
 
     /* client handshake 2 */
     memset(c_keys, 0, 40);
-    test_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
+    test_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40,
+                                                  NULL));
 
     test_memeq(c_keys, s_keys, 40);
     memset(s_buf, 0, 40);
@@ -337,18 +338,18 @@ test_bad_onion_handshake(void *arg)
   /* Client: Case 1: The server sent back junk. */
   s_buf[64] ^= 33;
   tt_int_op(-1, ==,
-            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
+            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, NULL));
   s_buf[64] ^= 33;
 
   /* Let the client finish; make sure it can. */
   tt_int_op(0, ==,
-            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
+            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, NULL));
   test_memeq(s_keys, c_keys, 40);
 
   /* Client: Case 2: The server sent back a degenerate DH. */
   memset(s_buf, 0, sizeof(s_buf));
   tt_int_op(-1, ==,
-            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
+            onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, NULL));
 
  done:
   crypto_dh_free(c_dh);
@@ -398,7 +399,7 @@ test_ntor_handshake(void *arg)
   /* client handshake 2 */
   memset(c_keys, 0, 40);
   tt_int_op(0, ==, onion_skin_ntor_client_handshake(c_state, s_buf,
-                                                    c_keys, 400));
+                                                    c_keys, 400, NULL));
 
   test_memeq(c_keys, s_keys, 400);
   memset(s_buf, 0, 40);
diff --git a/src/test/test_ntor_cl.c b/src/test/test_ntor_cl.c
index f2b7a72..6103e80 100644
--- a/src/test/test_ntor_cl.c
+++ b/src/test/test_ntor_cl.c
@@ -130,7 +130,7 @@ client2(int argc, char **argv)
 
   keys = tor_malloc(keybytes);
   hexkeys = tor_malloc(keybytes*2+1);
-  if (onion_skin_ntor_client_handshake(&state, msg, keys, keybytes)<0) {
+  if (onion_skin_ntor_client_handshake(&state, msg, keys, keybytes, NULL)<0) {
     fprintf(stderr, "handshake failed");
     result = 2;
     goto done;





More information about the tor-commits mailing list