[tor-commits] [tor/master] Enable the ntor handshake on the client side.

nickm at torproject.org nickm at torproject.org
Thu Jan 3 16:52:58 UTC 2013


commit b2863739083125d332cf1166ae6b095df7d0f155
Author: Nick Mathewson <nickm at torproject.org>
Date:   Thu Dec 6 01:53:29 2012 -0500

    Enable the ntor handshake on the client side.
    
    "works for me"
---
 src/or/channeltls.c   |    2 +
 src/or/circuitbuild.c |  103 ++++++++++++++++++++++++++++++++++++++++++++----
 src/or/circuitbuild.h |    5 +-
 src/or/circuituse.c   |    4 +-
 src/or/config.c       |    1 +
 src/or/entrynodes.c   |    2 +-
 src/or/nodelist.c     |   12 ++++++
 src/or/nodelist.h     |    1 +
 src/or/or.h           |    5 ++
 src/or/relay.c        |    4 +-
 src/or/router.c       |    3 +-
 src/or/routerparse.c  |    2 +
 12 files changed, 128 insertions(+), 16 deletions(-)

diff --git a/src/or/channeltls.c b/src/or/channeltls.c
index ede2458..f6069e0 100644
--- a/src/or/channeltls.c
+++ b/src/or/channeltls.c
@@ -914,6 +914,8 @@ channel_tls_handle_cell(cell_t *cell, or_connection_t *conn)
     case CELL_RELAY:
     case CELL_RELAY_EARLY:
     case CELL_DESTROY:
+    case CELL_CREATE2:
+    case CELL_CREATED2:
       /*
        * These are all transport independent and we pass them up through the
        * channel_t mechanism.  They are ultimately handled in command.c.
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index b7ab47f..9300b04 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -604,6 +604,73 @@ circuit_timeout_want_to_count_circ(origin_circuit_t *circ)
           && circ->build_state->desired_path_len == DEFAULT_ROUTE_LEN;
 }
 
+#ifdef CURVE25519_ENABLED
+/** Return true if the ntor handshake is enabled in the configuration, or if
+ * it's been set to "auto" in the configuration and it's enabled in the
+ * consensus. */
+static int
+circuits_can_use_ntor(void)
+{
+  const or_options_t *options = get_options();
+  if (options->UseNTorHandshake != -1)
+    return options->UseNTorHandshake;
+  return networkstatus_get_param(NULL, "UseNTorHandshake", 0, 0, 1);
+}
+#endif
+
+/** Decide whether to use a TAP or ntor handshake for connecting to <b>ei</b>
+ * directly, and set *<b>cell_type_out</b> and *<b>handshake_type_out</b>
+ * accordingly. */
+static void
+circuit_pick_create_handshake(uint8_t *cell_type_out,
+                              uint16_t *handshake_type_out,
+                              const extend_info_t *ei)
+{
+#ifdef CURVE25519_ENABLED
+  if (!tor_mem_is_zero((const char*)ei->curve25519_onion_key.public_key,
+                       CURVE25519_PUBKEY_LEN) &&
+      circuits_can_use_ntor()) {
+    *cell_type_out = CELL_CREATE2;
+    *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR;
+    return;
+  }
+#else
+  (void) ei;
+#endif
+
+  *cell_type_out = CELL_CREATE;
+  *handshake_type_out = ONION_HANDSHAKE_TYPE_TAP;
+}
+
+/** Decide whether to use a TAP or ntor handshake for connecting to <b>ei</b>
+ * directly, and set *<b>handshake_type_out</b> accordingly. Decide whether,
+ * in extending through <b>node</b> to do so, we should use an EXTEND2 or an
+ * EXTEND cell to do so, and set *<b>cell_type_out</b> and
+ * *<b>create_cell_type_out</b> accordingly. */
+static void
+circuit_pick_extend_handshake(uint8_t *cell_type_out,
+                              uint8_t *create_cell_type_out,
+                              uint16_t *handshake_type_out,
+                              const node_t *node_prev,
+                              const extend_info_t *ei)
+{
+  uint8_t t;
+  circuit_pick_create_handshake(&t, handshake_type_out, ei);
+  /* XXXX024 The check for whether the node has a curve25519 key is a bad
+   * proxy for whether it can do extend2 cells; once a version that
+   * handles extend2 cells is out, remove it. */
+  if (node_prev &&
+      *handshake_type_out != ONION_HANDSHAKE_TYPE_TAP &&
+      (node_has_curve25519_onion_key(node_prev) ||
+       (node_prev->rs && node_prev->rs->version_supports_extend2_cells))) {
+    *cell_type_out = RELAY_COMMAND_EXTEND2;
+    *create_cell_type_out = CELL_CREATE2;
+  } else {
+    *cell_type_out = RELAY_COMMAND_EXTEND;
+    *create_cell_type_out = CELL_CREATE;
+  }
+}
+
 /** This is the backbone function for building circuits.
  *
  * If circ's first hop is closed, then we need to build a create
@@ -638,10 +705,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
     fast = should_use_create_fast_for_circuit(circ);
     if (!fast) {
       /* We are an OR and we know the right onion key: we should
-       * send an old slow create cell.
+       * send a create cell.
        */
-      cc.cell_type = CELL_CREATE;
-      cc.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
+      circuit_pick_create_handshake(&cc.cell_type, &cc.handshake_type,
+                                    circ->cpath->extend_info);
       note_request("cell: create", 1);
     } else {
       /* We are not an OR, and we're building the first hop of a circuit to a
@@ -747,15 +814,21 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
       return - END_CIRC_REASON_INTERNAL;
     }
 
-    ec.cell_type = RELAY_COMMAND_EXTEND;
+    {
+      const node_t *prev_node;
+      prev_node = node_get_by_id(hop->prev->extend_info->identity_digest);
+      circuit_pick_extend_handshake(&ec.cell_type,
+                                    &ec.create_cell.cell_type,
+                                    &ec.create_cell.handshake_type,
+                                    prev_node,
+                                    hop->extend_info);
+    }
+
     tor_addr_copy(&ec.orport_ipv4.addr, &hop->extend_info->addr);
     ec.orport_ipv4.port = hop->extend_info->port;
     tor_addr_make_unspec(&ec.orport_ipv6.addr);
     memcpy(ec.node_id, hop->extend_info->identity_digest, DIGEST_LEN);
 
-    ec.create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
-    ec.create_cell.cell_type = CELL_CREATE;
-
     len = onion_skin_create(ec.create_cell.handshake_type,
                             hop->extend_info,
                             &hop->handshake_state,
@@ -903,6 +976,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
     circ->n_hop = extend_info_new(NULL /*nickname*/,
                                   (const char*)ec.node_id,
                                   NULL /*onion_key*/,
+                                  NULL /*curve25519_key*/,
                                   &ec.orport_ipv4.addr,
                                   ec.orport_ipv4.port);
 
@@ -938,6 +1012,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
 
   if (circuit_deliver_create_cell(circ, &ec.create_cell, 1) < 0)
     return -1;
+
   return 0;
 }
 
@@ -2310,8 +2385,9 @@ onion_append_hop(crypt_path_t **head_ptr, extend_info_t *choice)
 /** Allocate a new extend_info object based on the various arguments. */
 extend_info_t *
 extend_info_new(const char *nickname, const char *digest,
-                  crypto_pk_t *onion_key,
-                  const tor_addr_t *addr, uint16_t port)
+                crypto_pk_t *onion_key,
+                const curve25519_public_key_t *curve25519_key,
+                const tor_addr_t *addr, uint16_t port)
 {
   extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
   memcpy(info->identity_digest, digest, DIGEST_LEN);
@@ -2319,6 +2395,13 @@ extend_info_new(const char *nickname, const char *digest,
     strlcpy(info->nickname, nickname, sizeof(info->nickname));
   if (onion_key)
     info->onion_key = crypto_pk_dup_key(onion_key);
+#ifdef CURVE25519_ENABLED
+  if (curve25519_key)
+    memcpy(&info->curve25519_onion_key, curve25519_key,
+           sizeof(curve25519_public_key_t));
+#else
+  (void)curve25519_key;
+#endif
   tor_addr_copy(&info->addr, addr);
   info->port = port;
   return info;
@@ -2353,12 +2436,14 @@ extend_info_from_node(const node_t *node, int for_direct_connect)
     return extend_info_new(node->ri->nickname,
                              node->identity,
                              node->ri->onion_pkey,
+                             node->ri->onion_curve25519_pkey,
                              &ap.addr,
                              ap.port);
   else if (node->rs && node->md)
     return extend_info_new(node->rs->nickname,
                              node->identity,
                              node->md->onion_pkey,
+                             node->md->onion_curve25519_pkey,
                              &ap.addr,
                              ap.port);
   else
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 23213e8..d4f7926 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -46,8 +46,9 @@ int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info);
 int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info);
 void onion_append_to_cpath(crypt_path_t **head_ptr, crypt_path_t *new_hop);
 extend_info_t *extend_info_new(const char *nickname, const char *digest,
-                                 crypto_pk_t *onion_key,
-                                 const tor_addr_t *addr, uint16_t port);
+                               crypto_pk_t *onion_key,
+                               const curve25519_public_key_t *curve25519_key,
+                               const tor_addr_t *addr, uint16_t port);
 extend_info_t *extend_info_from_node(const node_t *r, int for_direct_connect);
 extend_info_t *extend_info_dup(extend_info_t *info);
 void extend_info_free(extend_info_t *info);
diff --git a/src/or/circuituse.c b/src/or/circuituse.c
index d3cde1d..6a733d6 100644
--- a/src/or/circuituse.c
+++ b/src/or/circuituse.c
@@ -1577,8 +1577,8 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn,
               return -1;
             }
             extend_info = extend_info_new(conn->chosen_exit_name+1,
-                                            digest, NULL, &addr,
-                                            conn->socks_request->port);
+                                          digest, NULL, NULL, &addr,
+                                          conn->socks_request->port);
           } else {
             /* We will need an onion key for the router, and we
              * don't have one. Refuse or relax requirements. */
diff --git a/src/or/config.c b/src/or/config.c
index 75f6193..979d09c 100644
--- a/src/or/config.c
+++ b/src/or/config.c
@@ -383,6 +383,7 @@ static config_var_t option_vars_[] = {
   V(UseBridges,                  BOOL,     "0"),
   V(UseEntryGuards,              BOOL,     "1"),
   V(UseMicrodescriptors,         AUTOBOOL, "auto"),
+  V(UseNTorHandshake,            AUTOBOOL, "auto"),
   V(User,                        STRING,   NULL),
   V(UserspaceIOCPBuffers,        BOOL,     "0"),
   VAR("V1AuthoritativeDirectory",BOOL, V1AuthoritativeDir,   "0"),
diff --git a/src/or/entrynodes.c b/src/or/entrynodes.c
index edb26dc..a4e18d0 100644
--- a/src/or/entrynodes.c
+++ b/src/or/entrynodes.c
@@ -1502,7 +1502,7 @@ routerset_contains_bridge(const routerset_t *routerset,
     return 0;
 
   extinfo = extend_info_new(
-         NULL, bridge->identity, NULL, &bridge->addr, bridge->port);
+         NULL, bridge->identity, NULL, NULL, &bridge->addr, bridge->port);
   result = routerset_contains_extendinfo(routerset, extinfo);
   extend_info_free(extinfo);
   return result;
diff --git a/src/or/nodelist.c b/src/or/nodelist.c
index 95345fb..fa3828f 100644
--- a/src/or/nodelist.c
+++ b/src/or/nodelist.c
@@ -916,6 +916,18 @@ node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out)
   }
 }
 
+/** Return true iff <b>node</b> has a curve25519 onion key. */
+int
+node_has_curve25519_onion_key(const node_t *node)
+{
+  if (node->ri)
+    return node->ri->onion_curve25519_pkey != NULL;
+  else if (node->md)
+    return node->md->onion_curve25519_pkey != NULL;
+  else
+    return 0;
+}
+
 /** Refresh the country code of <b>ri</b>.  This function MUST be called on
  * each router when the GeoIP database is reloaded, and on all new routers. */
 void
diff --git a/src/or/nodelist.h b/src/or/nodelist.h
index 13a3847..39f0948 100644
--- a/src/or/nodelist.h
+++ b/src/or/nodelist.h
@@ -54,6 +54,7 @@ int node_ipv6_preferred(const node_t *node);
 int node_get_prim_orport(const node_t *node, tor_addr_port_t *ap_out);
 void node_get_pref_orport(const node_t *node, tor_addr_port_t *ap_out);
 void node_get_pref_ipv6_orport(const node_t *node, tor_addr_port_t *ap_out);
+int node_has_curve25519_onion_key(const node_t *node);
 
 smartlist_t *nodelist_get_list(void);
 
diff --git a/src/or/or.h b/src/or/or.h
index 66e9054..b5718a8 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -2025,6 +2025,9 @@ typedef struct routerstatus_t {
   /** True iff this router is a version that allows DATA cells to arrive on
    * a stream before it has sent a CONNECTED cell. */
   unsigned int version_supports_optimistic_data:1;
+  /** True iff this router has a version that allows it to accept EXTEND2
+   * cells */
+  unsigned int version_supports_extend2_cells:1;
 
   unsigned int has_bandwidth:1; /**< The vote/consensus had bw info */
   unsigned int has_exitsummary:1; /**< The vote/consensus had exit summaries */
@@ -3799,6 +3802,8 @@ typedef struct {
 
   int IPv6Exit; /**< Do we support exiting to IPv6 addresses? */
 
+  /** Autobool: should we use the ntor handshake if we can? */
+  int UseNTorHandshake;
 } or_options_t;
 
 /** Persistent state for an onion router, as saved to disk. */
diff --git a/src/or/relay.c b/src/or/relay.c
index 5d87b27..ddeec4e 100644
--- a/src/or/relay.c
+++ b/src/or/relay.c
@@ -572,6 +572,7 @@ relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
     origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ);
     if (origin_circ->remaining_relay_early_cells > 0 &&
         (relay_command == RELAY_COMMAND_EXTEND ||
+         relay_command == RELAY_COMMAND_EXTEND2 ||
          cpath_layer != origin_circ->cpath)) {
       /* If we've got any relay_early cells left and (we're sending
        * an extend cell or we're not talking to the first hop), use
@@ -585,7 +586,8 @@ relay_send_command_from_edge(streamid_t stream_id, circuit_t *circ,
        * task 878. */
       origin_circ->relay_early_commands[
           origin_circ->relay_early_cells_sent++] = relay_command;
-    } else if (relay_command == RELAY_COMMAND_EXTEND) {
+    } else if (relay_command == RELAY_COMMAND_EXTEND ||
+               relay_command == RELAY_COMMAND_EXTEND2) {
       /* If no RELAY_EARLY cells can be sent over this circuit, log which
        * commands have been sent as RELAY_EARLY cells before; helps debug
        * task 878. */
diff --git a/src/or/router.c b/src/or/router.c
index 3733bec..a97db85 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1071,7 +1071,8 @@ extend_info_from_router(const routerinfo_t *r)
 
   router_get_prim_orport(r, &ap);
   return extend_info_new(r->nickname, r->cache_info.identity_digest,
-                           r->onion_pkey, &ap.addr, ap.port);
+                         r->onion_pkey, r->onion_curve25519_pkey,
+                         &ap.addr, ap.port);
 }
 
 /** Some time has passed, or we just got new directory information.
diff --git a/src/or/routerparse.c b/src/or/routerparse.c
index 17902d9..1be2374 100644
--- a/src/or/routerparse.c
+++ b/src/or/routerparse.c
@@ -2188,6 +2188,8 @@ routerstatus_parse_entry_from_string(memarea_t *area,
         tor_version_supports_microdescriptors(tok->args[0]);
       rs->version_supports_optimistic_data =
         tor_version_as_new_as(tok->args[0], "0.2.3.1-alpha");
+      rs->version_supports_extend2_cells =
+        tor_version_as_new_as(tok->args[0], "0.2.4.7-alpha");
     }
     if (vote_rs) {
       vote_rs->version = tor_strdup(tok->args[0]);





More information about the tor-commits mailing list