[tor-commits] [tor/master] Massive refactoring of the various handshake types

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


commit f58d4dfcd61aec7ea1900873ca08ecc31d7a7ef7
Author: Nick Mathewson <nickm at torproject.org>
Date:   Tue Dec 4 21:27:07 2012 -0500

    Massive refactoring of the various handshake types
    
    The three handshake types are now accessed from a unified interface;
    their state is abstracted from the rest of the cpath state, and so on.
---
 src/or/circuitbuild.c |  122 ++++++++++++++-----------
 src/or/circuitbuild.h |    3 +-
 src/or/circuitlist.c  |    7 +-
 src/or/command.c      |   10 +-
 src/or/cpuworker.c    |   40 ++++----
 src/or/onion.c        |  243 ++++++++++++++++++++++++++++++++++++++++++++++++-
 src/or/onion.h        |   33 +++++++
 src/or/onion_ntor.h   |    2 +
 src/or/onion_tap.c    |   26 +++--
 src/or/onion_tap.h    |   11 ++-
 src/or/or.h           |   40 ++++++---
 src/or/rendclient.c   |   14 ++--
 src/or/rendservice.c  |    8 +-
 src/or/router.c       |    7 ++
 src/or/router.h       |    1 +
 src/test/bench.c      |   16 ++--
 src/test/test.c       |   14 ++--
 17 files changed, 462 insertions(+), 135 deletions(-)

diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index b6cf125..8393ba1 100644
--- a/src/or/circuitbuild.c
+++ b/src/or/circuitbuild.c
@@ -27,6 +27,7 @@
 #include "main.h"
 #include "networkstatus.h"
 #include "nodelist.h"
+#include "onion.h"
 #include "onion_tap.h"
 #include "onion_fast.h"
 #include "policies.h"
@@ -54,7 +55,9 @@ static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
                                                uint16_t port,
                                                const char *id_digest);
 static int circuit_deliver_create_cell(circuit_t *circ,
-                                       uint8_t cell_type, const char *payload);
+                                       uint8_t cell_type,
+                                       const uint8_t *payload,
+                                       size_t payload_len);
 static int onion_pick_cpath_exit(origin_circuit_t *circ, extend_info_t *exit);
 static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
 static int onion_extend_cpath(origin_circuit_t *circ);
@@ -474,7 +477,8 @@ circuit_n_chan_done(channel_t *chan, int status)
         /* pull the create cell out of circ->onionskin, and send it */
         tor_assert(circ->n_chan_onionskin);
         if (circuit_deliver_create_cell(circ,CELL_CREATE,
-                                        circ->n_chan_onionskin)<0) {
+                                        (const uint8_t*)circ->n_chan_onionskin,
+                                        circ->n_chan_onionskin_len)<0) {
           circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
           continue;
         }
@@ -491,12 +495,12 @@ circuit_n_chan_done(channel_t *chan, int status)
  * for the outgoing
  * circuit <b>circ</b>, and deliver a cell of type <b>cell_type</b>
  * (either CELL_CREATE or CELL_CREATE_FAST) with payload <b>payload</b>
- * to this circuit.
+ * to this circuit. DOCDOC payload_len
  * Return -1 if we failed to find a suitable circid, else return 0.
  */
 static int
 circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
-                            const char *payload)
+                            const uint8_t *payload, size_t payload_len)
 {
   cell_t cell;
   circid_t id;
@@ -518,7 +522,7 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
   cell.command = cell_type;
   cell.circ_id = circ->n_circ_id;
 
-  memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN);
+  memcpy(cell.payload, payload, payload_len);
   append_cell_to_circuit_queue(circ, circ->n_chan, &cell,
                                CELL_DIRECTION_OUT, 0);
 
@@ -611,8 +615,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
 {
   crypt_path_t *hop;
   const node_t *node;
-  char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN];
-  char *onionskin;
+  uint8_t payload[2+4+DIGEST_LEN+MAX_ONIONSKIN_CHALLENGE_LEN];
+  uint8_t *onionskin;
+  uint16_t handshake_type;
+  int onionskin_len;
   size_t payload_len;
 
   tor_assert(circ);
@@ -633,30 +639,29 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
        * send an old slow create cell.
        */
       cell_type = CELL_CREATE;
-      if (onion_skin_create(circ->cpath->extend_info->onion_key,
-                            &(circ->cpath->dh_handshake_state),
-                            payload) < 0) {
-        log_warn(LD_CIRC,"onion_skin_create (first hop) failed.");
-        return - END_CIRC_REASON_INTERNAL;
-      }
+      handshake_type = ONION_HANDSHAKE_TYPE_TAP;
       note_request("cell: create", 1);
     } else {
       /* We are not an OR, and we're building the first hop of a circuit to a
        * new OR: we can be speedy and use CREATE_FAST to save an RSA operation
        * and a DH operation. */
       cell_type = CELL_CREATE_FAST;
-
-      memset(payload, 0, sizeof(payload));
-      if (fast_onionskin_create(&circ->cpath->fast_handshake_state,
-                                (uint8_t *)payload) < 0) {
-        log_warn(LD_CIRC,"onion_skin_create FAST (first hop) failed.");
-        return - END_CIRC_REASON_INTERNAL;
-      }
-
+      handshake_type = ONION_HANDSHAKE_TYPE_FAST;
       note_request("cell: create fast", 1);
     }
 
-    if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload) < 0)
+    memset(payload, 0, sizeof(payload));
+    onionskin_len = onion_skin_create(handshake_type,
+                                      circ->cpath->extend_info,
+                                      &circ->cpath->handshake_state,
+                                      payload);
+    if (onionskin_len < 0) {
+      log_warn(LD_CIRC,"onion_skin_create (first hop) failed.");
+      return - END_CIRC_REASON_INTERNAL;
+    }
+
+    if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload,
+                                    onionskin_len) < 0)
       return - END_CIRC_REASON_RESOURCELIMIT;
 
     circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
@@ -742,12 +747,16 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
     set_uint16(payload+4, htons(hop->extend_info->port));
 
     onionskin = payload+2+4;
-    memcpy(payload+2+4+ONIONSKIN_CHALLENGE_LEN,
+    memcpy(payload+2+4+TAP_ONIONSKIN_CHALLENGE_LEN,
            hop->extend_info->identity_digest, DIGEST_LEN);
-    payload_len = 2+4+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN;
+    payload_len = 2+4+TAP_ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN;
+
+    handshake_type = ONION_HANDSHAKE_TYPE_TAP;
 
-    if (onion_skin_create(hop->extend_info->onion_key,
-                          &(hop->dh_handshake_state), onionskin) < 0) {
+    if (onion_skin_create(handshake_type,
+                          hop->extend_info,
+                          &hop->handshake_state,
+                          onionskin) < 0) {
       log_warn(LD_CIRC,"onion_skin_create failed.");
       return - END_CIRC_REASON_INTERNAL;
     }
@@ -758,7 +767,8 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
      * it to a create cell and then send to hop */
     if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
                                      RELAY_COMMAND_EXTEND,
-                                     payload, payload_len, hop->prev) < 0)
+                                     (char*)payload, payload_len,
+                                     hop->prev) < 0)
       return 0; /* circuit is closed */
 
     hop->state = CPATH_STATE_AWAITING_KEYS;
@@ -826,7 +836,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
 
   relay_header_unpack(&rh, cell->payload);
 
-  if (rh.length < 4+2+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN) {
+  if (rh.length < 4+2+TAP_ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN) {
     log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
            "Wrong length %d on extend cell. Closing circuit.",
            rh.length);
@@ -837,7 +847,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
   n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4));
   onionskin = (char*) cell->payload+RELAY_HEADER_SIZE+4+2;
   id_digest = (char*) cell->payload+RELAY_HEADER_SIZE+4+2+
-    ONIONSKIN_CHALLENGE_LEN;
+    TAP_ONIONSKIN_CHALLENGE_LEN;
   tor_addr_from_ipv4h(&n_addr, n_addr32);
 
   if (!n_port || !n_addr32) {
@@ -890,8 +900,10 @@ circuit_extend(cell_t *cell, circuit_t *circ)
                                     NULL /*onion_key*/,
                                     &n_addr, n_port);
 
-    circ->n_chan_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
-    memcpy(circ->n_chan_onionskin, onionskin, ONIONSKIN_CHALLENGE_LEN);
+    circ->n_chan_onionskin = tor_malloc(TAP_ONIONSKIN_CHALLENGE_LEN);
+    memcpy(circ->n_chan_onionskin, onionskin, TAP_ONIONSKIN_CHALLENGE_LEN);
+    circ->n_chan_onionskin_len = TAP_ONIONSKIN_CHALLENGE_LEN;
+
     circuit_set_state(circ, CIRCUIT_STATE_CHAN_WAIT);
 
     if (should_launch) {
@@ -917,7 +929,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
             "n_chan is %s",
             channel_get_canonical_remote_descr(n_chan));
 
-  if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0)
+  if (circuit_deliver_create_cell(circ, CELL_CREATE, (uint8_t*)onionskin,
+                                  TAP_ONIONSKIN_CHALLENGE_LEN) < 0)
     return -1;
   return 0;
 }
@@ -1377,31 +1390,32 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type,
   }
   tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS);
 
-  if (reply_type == CELL_CREATED && hop->dh_handshake_state) {
-    if (onion_skin_client_handshake(hop->dh_handshake_state, (char*)reply,keys,
-                                    DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
-      log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
+  {
+    uint16_t handshake_type = 0xffff;
+    if (reply_type == CELL_CREATED)
+      handshake_type = ONION_HANDSHAKE_TYPE_TAP;
+    else if (reply_type == CELL_CREATED_FAST)
+      handshake_type = ONION_HANDSHAKE_TYPE_FAST;
+
+    if (handshake_type != hop->handshake_state.tag) {
+      log_warn(LD_PROTOCOL,"CREATED cell onionskin type (%u) did not "
+               "match CREATE cell onionskin type (%u).",
+               (unsigned)handshake_type,
+               (unsigned) hop->handshake_state.tag);
       return -END_CIRC_REASON_TORPROTOCOL;
     }
-    /* Remember hash of g^xy */
-    memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
-  } else if (reply_type == CELL_CREATED_FAST && !hop->dh_handshake_state) {
-    if (fast_client_handshake(hop->fast_handshake_state, reply,
-                              (uint8_t*)keys,
-                              DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
-      log_warn(LD_CIRC,"fast_client_handshake failed.");
+
+    if (onion_skin_client_handshake(handshake_type,
+                                    &hop->handshake_state,
+                                    reply,
+                                    (uint8_t*)keys, sizeof(keys),
+                                    (uint8_t*)hop->handshake_digest) < 0) {
+      log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
       return -END_CIRC_REASON_TORPROTOCOL;
     }
-    memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN);
-  } else {
-    log_warn(LD_PROTOCOL,"CREATED cell type did not match CREATE cell type.");
-    return -END_CIRC_REASON_TORPROTOCOL;
   }
 
-  crypto_dh_free(hop->dh_handshake_state); /* don't need it anymore */
-  hop->dh_handshake_state = NULL;
-
-  memset(hop->fast_handshake_state, 0, sizeof(hop->fast_handshake_state));
+  onion_handshake_state_release(&hop->handshake_state);
 
   if (circuit_init_cpath_crypto(hop, keys, 0)<0) {
     return -END_CIRC_REASON_TORPROTOCOL;
@@ -1470,7 +1484,7 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, int reason)
  */
 int
 onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
-                 const char *keys)
+                 size_t payload_len, const char *keys)
 {
   cell_t cell;
   crypt_path_t *tmp_cpath;
@@ -1484,8 +1498,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
 
   circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);
 
-  memcpy(cell.payload, payload,
-         cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2);
+  memcpy(cell.payload, payload, payload_len);
 
   log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.",
             (unsigned int)get_uint32(keys),
@@ -1502,6 +1515,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
   tmp_cpath->magic = 0;
   tor_free(tmp_cpath);
 
+  /* XXXX Move responsibility for extracting this. */
   if (cell_type == CELL_CREATED)
     memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN);
   else
diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h
index 78575af..f83cb55 100644
--- a/src/or/circuitbuild.h
+++ b/src/or/circuitbuild.h
@@ -35,7 +35,8 @@ int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type,
 int circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer,
                       int reason);
 int onionskin_answer(or_circuit_t *circ, uint8_t cell_type,
-                     const char *payload, const char *keys);
+                     const char *payload, size_t payload_len,
+                     const char *keys);
 int circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
                                         int *need_capacity);
 
diff --git a/src/or/circuitlist.c b/src/or/circuitlist.c
index 2c17fd2..2565470 100644
--- a/src/or/circuitlist.c
+++ b/src/or/circuitlist.c
@@ -744,8 +744,8 @@ circuit_free_cpath_node(crypt_path_t *victim)
   crypto_cipher_free(victim->b_crypto);
   crypto_digest_free(victim->f_digest);
   crypto_digest_free(victim->b_digest);
-  crypto_dh_free(victim->dh_handshake_state);
-  fast_handshake_state_free(victim->fast_handshake_state);
+  onion_handshake_state_release(&victim->handshake_state);
+  crypto_dh_free(victim->rend_dh_handshake_state);
   extend_info_free(victim->extend_info);
 
   memwipe(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
@@ -1494,7 +1494,8 @@ assert_cpath_layer_ok(const crypt_path_t *cp)
       tor_assert(cp->b_crypto);
       /* fall through */
     case CPATH_STATE_CLOSED:
-      tor_assert(!cp->dh_handshake_state);
+      /*XXXX Assert that there's no handshake_state either. */
+      tor_assert(!cp->rend_dh_handshake_state);
       break;
     case CPATH_STATE_AWAITING_KEYS:
       /* tor_assert(cp->dh_handshake_state); */
diff --git a/src/or/command.c b/src/or/command.c
index 2718ec9..a33a9b1 100644
--- a/src/or/command.c
+++ b/src/or/command.c
@@ -30,6 +30,7 @@
 #include "hibernate.h"
 #include "nodelist.h"
 //#include "onion.h"
+#include "onion_tap.h"
 #include "onion_fast.h"
 #include "relay.h"
 #include "router.h"
@@ -254,8 +255,8 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
   circ->base_.purpose = CIRCUIT_PURPOSE_OR;
   circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
   if (cell->command == CELL_CREATE) {
-    char *onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
-    memcpy(onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
+    char *onionskin = tor_malloc(TAP_ONIONSKIN_CHALLENGE_LEN);
+    memcpy(onionskin, cell->payload, TAP_ONIONSKIN_CHALLENGE_LEN);
 
     /* hand it off to the cpuworkers, and then return. */
     if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) {
@@ -282,7 +283,8 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
       circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
       return;
     }
-    if (onionskin_answer(circ, CELL_CREATED_FAST, reply, keys)<0) {
+    if (onionskin_answer(circ, CELL_CREATED_FAST, reply, sizeof(reply),
+                         keys)<0) {
       log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing.");
       circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
       return;
@@ -340,7 +342,7 @@ command_process_created_cell(cell_t *cell, channel_t *chan)
     log_debug(LD_OR,
               "Converting created cell to extended relay cell, sending.");
     relay_send_command_from_edge(0, circ, RELAY_COMMAND_EXTENDED,
-                                 (char*)cell->payload, ONIONSKIN_REPLY_LEN,
+                                 (char*)cell->payload, TAP_ONIONSKIN_REPLY_LEN,
                                  NULL);
   }
 }
diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c
index 3a3d687..e8087c2 100644
--- a/src/or/cpuworker.c
+++ b/src/or/cpuworker.c
@@ -35,7 +35,7 @@
 #define TAG_LEN 10
 /** How many bytes are sent from the cpuworker back to tor? */
 #define LEN_ONION_RESPONSE \
-  (1+TAG_LEN+ONIONSKIN_REPLY_LEN+CPATH_KEY_MATERIAL_LEN)
+  (1+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN+CPATH_KEY_MATERIAL_LEN)
 
 /** How many cpuworkers we have running right now. */
 static int num_cpuworkers=0;
@@ -185,7 +185,8 @@ connection_cpu_process_inbuf(connection_t *conn)
     }
     tor_assert(! CIRCUIT_IS_ORIGIN(circ));
     if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN,
-                         buf+TAG_LEN+ONIONSKIN_REPLY_LEN) < 0) {
+                         TAP_ONIONSKIN_REPLY_LEN,
+                         buf+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN) < 0) {
       log_warn(LD_OR,"onionskin_answer failed. Closing.");
       circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
       goto done_processing;
@@ -214,11 +215,11 @@ connection_cpu_process_inbuf(connection_t *conn)
  *   Request format:
  *          Task type           [1 byte, always CPUWORKER_TASK_ONION]
  *          Opaque tag          TAG_LEN
- *          Onionskin challenge ONIONSKIN_CHALLENGE_LEN
+ *          Onionskin challenge TAP_ONIONSKIN_CHALLENGE_LEN
  *   Response format:
  *          Success/failure     [1 byte, boolean.]
  *          Opaque tag          TAG_LEN
- *          Onionskin challenge ONIONSKIN_REPLY_LEN
+ *          Onionskin challenge TAP_ONIONSKIN_REPLY_LEN
  *          Negotiated keys     KEY_LEN*2+DIGEST_LEN*2
  *
  *  (Note: this _should_ be by addr/port, since we're concerned with specific
@@ -227,17 +228,17 @@ connection_cpu_process_inbuf(connection_t *conn)
 static void
 cpuworker_main(void *data)
 {
-  char question[ONIONSKIN_CHALLENGE_LEN];
+  char question[TAP_ONIONSKIN_CHALLENGE_LEN];
   uint8_t question_type;
   tor_socket_t *fdarray = data;
   tor_socket_t fd;
 
   /* variables for onion processing */
   char keys[CPATH_KEY_MATERIAL_LEN];
-  char reply_to_proxy[ONIONSKIN_REPLY_LEN];
+  char reply_to_proxy[MAX_ONIONSKIN_REPLY_LEN];
   char buf[LEN_ONION_RESPONSE];
   char tag[TAG_LEN];
-  crypto_pk_t *onion_key = NULL, *last_onion_key = NULL;
+  server_onion_keys_t onion_keys;
 
   fd = fdarray[1]; /* this side is ours */
 #ifndef TOR_IS_MULTITHREADED
@@ -248,7 +249,7 @@ cpuworker_main(void *data)
 #endif
   tor_free(data);
 
-  dup_onion_keys(&onion_key, &last_onion_key);
+  setup_server_onion_keys(&onion_keys);
 
   for (;;) {
     ssize_t r;
@@ -275,15 +276,18 @@ cpuworker_main(void *data)
       goto end;
     }
 
-    if (read_all(fd, question, ONIONSKIN_CHALLENGE_LEN, 1) !=
-        ONIONSKIN_CHALLENGE_LEN) {
+    if (read_all(fd, question, TAP_ONIONSKIN_CHALLENGE_LEN, 1) !=
+        TAP_ONIONSKIN_CHALLENGE_LEN) {
       log_err(LD_BUG,"read question failed. Exiting.");
       goto end;
     }
 
     if (question_type == CPUWORKER_TASK_ONION) {
-      if (onion_skin_server_handshake(question, onion_key, last_onion_key,
-          reply_to_proxy, keys, CPATH_KEY_MATERIAL_LEN) < 0) {
+      if (onion_skin_server_handshake(ONION_HANDSHAKE_TYPE_TAP,
+                         (const uint8_t*)question,
+                         &onion_keys,
+                         (uint8_t*)reply_to_proxy,
+                         (uint8_t*)keys, CPATH_KEY_MATERIAL_LEN) < 0) {
         /* failure */
         log_debug(LD_OR,"onion_skin_server_handshake failed.");
         *buf = 0; /* indicate failure in first byte */
@@ -295,8 +299,9 @@ cpuworker_main(void *data)
         log_debug(LD_OR,"onion_skin_server_handshake succeeded.");
         buf[0] = 1; /* 1 means success */
         memcpy(buf+1,tag,TAG_LEN);
-        memcpy(buf+1+TAG_LEN,reply_to_proxy,ONIONSKIN_REPLY_LEN);
-        memcpy(buf+1+TAG_LEN+ONIONSKIN_REPLY_LEN,keys,CPATH_KEY_MATERIAL_LEN);
+        memcpy(buf+1+TAG_LEN,reply_to_proxy,TAP_ONIONSKIN_REPLY_LEN);
+        memcpy(buf+1+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN,keys,
+               CPATH_KEY_MATERIAL_LEN);
       }
       if (write_all(fd, buf, LEN_ONION_RESPONSE, 1) != LEN_ONION_RESPONSE) {
         log_err(LD_BUG,"writing response buf failed. Exiting.");
@@ -306,10 +311,7 @@ cpuworker_main(void *data)
     }
   }
  end:
-  if (onion_key)
-    crypto_pk_free(onion_key);
-  if (last_onion_key)
-    crypto_pk_free(last_onion_key);
+  release_server_onion_keys(&onion_keys);
   tor_close_socket(fd);
   crypto_thread_cleanup();
   spawn_exit();
@@ -497,7 +499,7 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker,
     qbuf[0] = CPUWORKER_TASK_ONION;
     connection_write_to_buf(qbuf, 1, cpuworker);
     connection_write_to_buf(tag, sizeof(tag), cpuworker);
-    connection_write_to_buf(onionskin, ONIONSKIN_CHALLENGE_LEN, cpuworker);
+    connection_write_to_buf(onionskin, TAP_ONIONSKIN_CHALLENGE_LEN, cpuworker);
     tor_free(onionskin);
   }
   return 0;
diff --git a/src/or/onion.c b/src/or/onion.c
index f468ada..90fc830 100644
--- a/src/or/onion.c
+++ b/src/or/onion.c
@@ -6,15 +6,19 @@
 
 /**
  * \file onion.c
- * \brief Functions to queue create cells, and handle onionskin
- * parsing and creation.
+ * \brief Functions to queue create cells, handle onionskin
+ * parsing and creation, and wrap the various onionskin types.
  **/
 
 #include "or.h"
 #include "circuitlist.h"
 #include "config.h"
 #include "onion.h"
+#include "onion_fast.h"
+#include "onion_ntor.h"
+#include "onion_tap.h"
 #include "rephist.h"
+#include "router.h"
 
 /** Type for a linked list of circuits that are waiting for a free CPU worker
  * to process a waiting onion handshake. */
@@ -37,6 +41,8 @@ static onion_queue_t *ol_tail=NULL;
 /** Length of ol_list */
 static int ol_length=0;
 
+/* XXXX Check lengths vs MAX_ONIONSKIN_{CHALLENGE,REPLY}_LEN */
+
 /** Add <b>circ</b> to the end of ol_list and return 0, except
  * if ol_list is too long, in which case do nothing and return -1.
  */
@@ -171,3 +177,236 @@ clear_pending_onions(void)
   ol_length = 0;
 }
 
+/* ============================================================ */
+
+/** Fill in a server_onion_keys_t object at <b>keys</b> with all of the keys
+ * and other info we might need to do onion handshakes.  (We make a copy of
+ * our keys for each cpuworker to avoid race conditions with the main thread,
+ * and to avoid locking) */
+void
+setup_server_onion_keys(server_onion_keys_t *keys)
+{
+  memset(keys, 0, sizeof(server_onion_keys_t));
+  memcpy(keys->my_identity, router_get_my_id_digest(), DIGEST_LEN);
+  dup_onion_keys(&keys->onion_key, &keys->last_onion_key);
+#ifdef CURVE25519_ENABLED
+  keys->curve25519_key_map = construct_ntor_key_map();
+#endif
+}
+
+/** Release all storage held in <b>keys</b>, but do not free <b>keys</b>
+ * itself (as it's likely to be stack-allocated.) */
+void
+release_server_onion_keys(server_onion_keys_t *keys)
+{
+  if (! keys)
+    return;
+
+  crypto_pk_free(keys->onion_key);
+  crypto_pk_free(keys->last_onion_key);
+#ifdef CURVE25519_ENABLED
+  ntor_key_map_free(keys->curve25519_key_map);
+#endif
+  memset(keys, 0, sizeof(server_onion_keys_t));
+}
+
+/** Release whatever storage is held in <b>state</b>, depending on its
+ * type, and clear its pointer. */
+void
+onion_handshake_state_release(onion_handshake_state_t *state)
+{
+  switch (state->tag) {
+  case ONION_HANDSHAKE_TYPE_TAP:
+    crypto_dh_free(state->u.tap);
+    state->u.tap = NULL;
+    break;
+  case ONION_HANDSHAKE_TYPE_FAST:
+    fast_handshake_state_free(state->u.fast);
+    state->u.fast = NULL;
+    break;
+#ifdef CURVE25519_ENABLED
+  case ONION_HANDSHAKE_TYPE_NTOR:
+    ntor_handshake_state_free(state->u.ntor);
+    state->u.ntor = NULL;
+    break;
+#endif
+  default:
+    log_warn(LD_BUG, "called with unknown handshake state type %d",
+             (int)state->tag);
+    tor_fragile_assert();
+  }
+}
+
+/** Perform the first step of a circuit-creation handshake of type <b>type</b>
+ * (one of ONION_HANDSHAKE_TYPE_*): generate the initial "onion skin" in
+ * <b>onion_skin_out</b>, and store any state information in <b>state_out</b>.
+ * Return -1 on failure, and the length of the onionskin on acceptance.
+ */
+int
+onion_skin_create(int type,
+                  const extend_info_t *node,
+                  onion_handshake_state_t *state_out,
+                  uint8_t *onion_skin_out)
+{
+  int r = -1;
+
+  switch (type) {
+  case ONION_HANDSHAKE_TYPE_TAP:
+    if (!node->onion_key)
+      return -1;
+
+    if (onion_skin_TAP_create(node->onion_key,
+                              &state_out->u.tap,
+                              (char*)onion_skin_out) < 0)
+      return -1;
+
+    r = TAP_ONIONSKIN_CHALLENGE_LEN;
+    break;
+  case ONION_HANDSHAKE_TYPE_FAST:
+    if (fast_onionskin_create(&state_out->u.fast, onion_skin_out) < 0)
+      return -1;
+
+    r = CREATE_FAST_LEN;
+    break;
+  case ONION_HANDSHAKE_TYPE_NTOR:
+#ifdef CURVE25519_ENABLED
+    if (tor_mem_is_zero((const char*)node->curve25519_onion_key.public_key,
+                        CURVE25519_PUBKEY_LEN))
+      return -1;
+    if (onion_skin_ntor_create((const uint8_t*)node->identity_digest,
+                               &node->curve25519_onion_key,
+                               &state_out->u.ntor,
+                               onion_skin_out) < 0)
+      return -1;
+
+    r = NTOR_ONIONSKIN_LEN;
+#else
+    return -1;
+#endif
+    break;
+  default:
+    log_warn(LD_BUG, "called with unknown handshake state type %d", type);
+    tor_fragile_assert();
+    r = -1;
+  }
+
+  if (r > 0)
+    state_out->tag = (uint16_t) type;
+
+  return r;
+}
+
+/** Perform the second (server-side) step of a circuit-creation handshake of
+ * type <b>type</b>, responding to the client request in <b>onion_skin</b>
+ * using the keys in <b>keys</b>.  On success, write our response into
+ * <b>reply_out</b>, generate <b>keys_out_len</b> bytes worth of key material
+ * in <b>keys_out_len</b>, and return the length of the reply. On failure,
+ * return -1.  */
+int
+onion_skin_server_handshake(int type,
+                      const uint8_t *onion_skin,
+                      const server_onion_keys_t *keys,
+                      uint8_t *reply_out,
+                      uint8_t *keys_out, size_t keys_out_len)
+{
+  int r = -1;
+
+  switch (type) {
+  case ONION_HANDSHAKE_TYPE_TAP:
+    if (onion_skin_TAP_server_handshake((const char*)onion_skin,
+                                        keys->onion_key, keys->last_onion_key,
+                                        (char*)reply_out,
+                                        (char*)keys_out, keys_out_len)<0)
+      return -1;
+    r = TAP_ONIONSKIN_REPLY_LEN;
+    break;
+  case ONION_HANDSHAKE_TYPE_FAST:
+    if (fast_server_handshake(onion_skin, reply_out, keys_out, keys_out_len)<0)
+      return -1;
+    r = CREATED_FAST_LEN;
+    break;
+  case ONION_HANDSHAKE_TYPE_NTOR:
+#ifdef CURVE25519_ENABLED
+    if (onion_skin_ntor_server_handshake(onion_skin, keys->curve25519_key_map,
+                                         keys->my_identity,
+                                         reply_out, keys_out, keys_out_len)<0)
+      return -1;
+    r = NTOR_REPLY_LEN;
+#else
+    return -1;
+#endif
+    break;
+  default:
+    log_warn(LD_BUG, "called with unknown handshake state type %d", type);
+    tor_fragile_assert();
+    return -1;
+  }
+
+  /* XXXX we should generate the rendezvous nonce stuff too.  Some notes
+   * below */
+    // memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
+
+    //memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN);
+
+  return r;
+}
+
+/** Perform the final (client-side) step of a circuit-creation handshake of
+ * type <b>type</b>, using our state in <b>handshake_state</b> and the
+ * server's response in <b>reply</b> On success, generate <b>keys_out_len</b>
+ * 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. */
+int
+onion_skin_client_handshake(int type,
+                      const onion_handshake_state_t *handshake_state,
+                      const uint8_t *reply,
+                      uint8_t *keys_out, size_t keys_out_len,
+                      uint8_t *rend_authenticator_out)
+{
+  if (handshake_state->tag != type)
+    return -1;
+
+  switch (type) {
+  case ONION_HANDSHAKE_TYPE_TAP:
+    if (onion_skin_TAP_client_handshake(handshake_state->u.tap,
+                                        (const char*)reply,
+                                        (char *)keys_out, keys_out_len) < 0)
+      return -1;
+
+    memcpy(rend_authenticator_out, reply+DH_KEY_LEN, DIGEST_LEN);
+
+    return 0;
+  case ONION_HANDSHAKE_TYPE_FAST:
+    if (fast_client_handshake(handshake_state->u.fast, reply,
+                              keys_out, keys_out_len) < 0)
+      return -1;
+
+    memcpy(rend_authenticator_out, reply+DIGEST_LEN, DIGEST_LEN);
+    return 0;
+#ifdef CURVE25519_ENABLED
+  case ONION_HANDSHAKE_TYPE_NTOR:
+    {
+      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) {
+        tor_free(keys_tmp);
+        return -1;
+      }
+      memcpy(keys_out, keys_tmp, keys_out_len);
+      memcpy(rend_authenticator_out, keys_tmp + keys_out_len, DIGEST_LEN);
+      memwipe(keys_tmp, 0, keys_tmp_len);
+      tor_free(keys_tmp);
+    }
+    return 0;
+#endif
+  default:
+    log_warn(LD_BUG, "called with unknown handshake state type %d", type);
+    tor_fragile_assert();
+    return -1;
+  }
+}
+
diff --git a/src/or/onion.h b/src/or/onion.h
index 55ea3f9..3c12e1f 100644
--- a/src/or/onion.h
+++ b/src/or/onion.h
@@ -17,5 +17,38 @@ or_circuit_t *onion_next_task(char **onionskin_out);
 void onion_pending_remove(or_circuit_t *circ);
 void clear_pending_onions(void);
 
+typedef struct server_onion_keys_t {
+  uint8_t my_identity[DIGEST_LEN];
+  crypto_pk_t *onion_key;
+  crypto_pk_t *last_onion_key;
+#ifdef CURVE25519_ENABLED
+  di_digest256_map_t *curve25519_key_map;
+#endif
+} server_onion_keys_t;
+
+#define MAX_ONIONSKIN_CHALLENGE_LEN 255
+#define MAX_ONIONSKIN_REPLY_LEN 255
+
+void setup_server_onion_keys(server_onion_keys_t *keys);
+void release_server_onion_keys(server_onion_keys_t *keys);
+
+void onion_handshake_state_release(onion_handshake_state_t *state);
+
+int onion_skin_create(int type,
+                      const extend_info_t *node,
+                      onion_handshake_state_t *state_out,
+                      uint8_t *onion_skin_out);
+int onion_skin_server_handshake(int type,
+                      const uint8_t *onion_skin,
+                      const server_onion_keys_t *keys,
+                      uint8_t *reply_out,
+                      uint8_t *keys_out, size_t key_out_len);
+//                      uint8_t *rend_authenticator_out);
+int onion_skin_client_handshake(int type,
+                      const onion_handshake_state_t *handshake_state,
+                      const uint8_t *reply,
+                      uint8_t *keys_out, size_t key_out_len,
+                      uint8_t *rend_authenticator_out);
+
 #endif
 
diff --git a/src/or/onion_ntor.h b/src/or/onion_ntor.h
index 4f305a4..80015fd 100644
--- a/src/or/onion_ntor.h
+++ b/src/or/onion_ntor.h
@@ -17,6 +17,7 @@ typedef struct ntor_handshake_state_t ntor_handshake_state_t;
 /** Length of an ntor reply, as sent from server to client. */
 #define NTOR_REPLY_LEN 64
 
+#ifdef CURVE25519_ENABLED
 void ntor_handshake_state_free(ntor_handshake_state_t *state);
 
 int onion_skin_ntor_create(const uint8_t *router_id,
@@ -36,6 +37,7 @@ int onion_skin_ntor_client_handshake(
                              const uint8_t *handshake_reply,
                              uint8_t *key_out,
                              size_t key_out_len);
+#endif
 
 #endif
 
diff --git a/src/or/onion_tap.c b/src/or/onion_tap.c
index 464b845..0ec526c 100644
--- a/src/or/onion_tap.c
+++ b/src/or/onion_tap.c
@@ -35,9 +35,9 @@
  * The meeting point/cookies and auth are zeroed out for now.
  */
 int
-onion_skin_create(crypto_pk_t *dest_router_key,
+onion_skin_TAP_create(crypto_pk_t *dest_router_key,
                   crypto_dh_t **handshake_state_out,
-                  char *onion_skin_out) /* ONIONSKIN_CHALLENGE_LEN bytes */
+                  char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */
 {
   char challenge[DH_KEY_LEN];
   crypto_dh_t *dh = NULL;
@@ -47,7 +47,7 @@ onion_skin_create(crypto_pk_t *dest_router_key,
   tor_assert(handshake_state_out);
   tor_assert(onion_skin_out);
   *handshake_state_out = NULL;
-  memset(onion_skin_out, 0, ONIONSKIN_CHALLENGE_LEN);
+  memset(onion_skin_out, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
 
   if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT)))
     goto err;
@@ -64,7 +64,7 @@ onion_skin_create(crypto_pk_t *dest_router_key,
 
   /* set meeting point, meeting cookie, etc here. Leave zero for now. */
   if (crypto_pk_public_hybrid_encrypt(dest_router_key, onion_skin_out,
-                                      ONIONSKIN_CHALLENGE_LEN,
+                                      TAP_ONIONSKIN_CHALLENGE_LEN,
                                       challenge, DH_KEY_LEN,
                                       PK_PKCS1_OAEP_PADDING, 1)<0)
     goto err;
@@ -85,14 +85,17 @@ onion_skin_create(crypto_pk_t *dest_router_key,
  * next key_out_len bytes of key material in key_out.
  */
 int
-onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
+onion_skin_TAP_server_handshake(
+                            /*TAP_ONIONSKIN_CHALLENGE_LEN*/
+                            const char *onion_skin,
                             crypto_pk_t *private_key,
                             crypto_pk_t *prev_private_key,
-                            char *handshake_reply_out, /*ONIONSKIN_REPLY_LEN*/
+                            /*TAP_ONIONSKIN_REPLY_LEN*/
+                            char *handshake_reply_out,
                             char *key_out,
                             size_t key_out_len)
 {
-  char challenge[ONIONSKIN_CHALLENGE_LEN];
+  char challenge[TAP_ONIONSKIN_CHALLENGE_LEN];
   crypto_dh_t *dh = NULL;
   ssize_t len;
   char *key_material=NULL;
@@ -107,8 +110,9 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
       break;
     note_crypto_pk_op(DEC_ONIONSKIN);
     len = crypto_pk_private_hybrid_decrypt(k, challenge,
-                                           ONIONSKIN_CHALLENGE_LEN,
-                                           onion_skin, ONIONSKIN_CHALLENGE_LEN,
+                                           TAP_ONIONSKIN_CHALLENGE_LEN,
+                                           onion_skin,
+                                           TAP_ONIONSKIN_CHALLENGE_LEN,
                                            PK_PKCS1_OAEP_PADDING,0);
     if (len>0)
       break;
@@ -175,8 +179,8 @@ onion_skin_server_handshake(const char *onion_skin, /*ONIONSKIN_CHALLENGE_LEN*/
  * After the invocation, call crypto_dh_free on handshake_state.
  */
 int
-onion_skin_client_handshake(crypto_dh_t *handshake_state,
-            const char *handshake_reply, /* ONIONSKIN_REPLY_LEN bytes */
+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)
 {
diff --git a/src/or/onion_tap.h b/src/or/onion_tap.h
index 3bd90c9..deae1bf 100644
--- a/src/or/onion_tap.h
+++ b/src/or/onion_tap.h
@@ -12,18 +12,23 @@
 #ifndef TOR_ONION_TAP_H
 #define TOR_ONION_TAP_H
 
-int onion_skin_create(crypto_pk_t *router_key,
+#define TAP_ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
+                                 CIPHER_KEY_LEN+\
+                                 DH_KEY_LEN)
+#define TAP_ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN)
+
+int onion_skin_TAP_create(crypto_pk_t *router_key,
                       crypto_dh_t **handshake_state_out,
                       char *onion_skin_out);
 
-int onion_skin_server_handshake(const char *onion_skin,
+int onion_skin_TAP_server_handshake(const char *onion_skin,
                                 crypto_pk_t *private_key,
                                 crypto_pk_t *prev_private_key,
                                 char *handshake_reply_out,
                                 char *key_out,
                                 size_t key_out_len);
 
-int onion_skin_client_handshake(crypto_dh_t *handshake_state,
+int onion_skin_TAP_client_handshake(crypto_dh_t *handshake_state,
                                 const char *handshake_reply,
                                 char *key_out,
                                 size_t key_out_len);
diff --git a/src/or/or.h b/src/or/or.h
index 6fada77..f7407a8 100644
--- a/src/or/or.h
+++ b/src/or/or.h
@@ -1381,6 +1381,7 @@ typedef struct or_connection_t {
 
   or_handshake_state_t *handshake_state; /**< If we are setting this connection
                                           * up, state information to do so. */
+
   time_t timestamp_lastempty; /**< When was the outbuf last completely empty?*/
   time_t timestamp_last_added_nonpadding; /** When did we last add a
                                            * non-padding cell to the outbuf? */
@@ -2470,6 +2471,9 @@ typedef struct extend_info_t {
   uint16_t port; /**< OR port. */
   tor_addr_t addr; /**< IP address. */
   crypto_pk_t *onion_key; /**< Current onionskin key. */
+#ifdef CURVE25519_ENABLED
+  curve25519_public_key_t curve25519_onion_key;
+#endif
 } extend_info_t;
 
 /** Certificate for v3 directory protocol: binds long-term authority identity
@@ -2525,6 +2529,19 @@ typedef enum {
 #define CRYPT_PATH_MAGIC 0x70127012u
 
 struct fast_handshake_state_t;
+struct ntor_handshake_state_t;
+#define ONION_HANDSHAKE_TYPE_TAP 0x0000
+#define ONION_HANDSHAKE_TYPE_FAST 0x0001
+#define ONION_HANDSHAKE_TYPE_NTOR 0x0002
+typedef struct {
+  uint16_t tag;
+  union {
+    struct fast_handshake_state_t *fast;
+    crypto_dh_t *tap;
+    struct ntor_handshake_state_t *ntor;
+  } u;
+} onion_handshake_state_t;
+
 /** Holds accounting information for a single step in the layered encryption
  * performed by a circuit.  Used only at the client edge of a circuit. */
 typedef struct crypt_path_t {
@@ -2543,16 +2560,15 @@ typedef struct crypt_path_t {
   /** Digest state for cells heading away from the OR at this step. */
   crypto_digest_t *b_digest;
 
-  /** Current state of Diffie-Hellman key negotiation with the OR at this
+  /** Current state of the handshake as performed with the OR at this
    * step. */
-  crypto_dh_t *dh_handshake_state;
-  /** Current state of 'fast' (non-PK) key negotiation with the OR at this
-   * step. Used to save CPU when TLS is already providing all the
-   * authentication, secrecy, and integrity we need, and we're already
-   * distinguishable from an OR.
-   */
-  struct fast_handshake_state_t *fast_handshake_state;
+  onion_handshake_state_t handshake_state;
+  /** Diffie-hellman handshake state for performing an introduction
+   * operations */
+  crypto_dh_t *rend_dh_handshake_state;
+
   /** Negotiated key material shared with the OR at this step. */
+  /* XXXX RENAME */
   char handshake_digest[DIGEST_LEN];/* KH in tor-spec.txt */
 
   /** Information to extend to the OR at this step. */
@@ -2594,10 +2610,6 @@ typedef struct {
 #define CPATH_KEY_MATERIAL_LEN (20*2+16*2)
 
 #define DH_KEY_LEN DH_BYTES
-#define ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\
-                                 CIPHER_KEY_LEN+\
-                                 DH_KEY_LEN)
-#define ONIONSKIN_REPLY_LEN (DH_KEY_LEN+DIGEST_LEN)
 
 /** Information used to build a circuit. */
 typedef struct {
@@ -2703,9 +2715,10 @@ typedef struct circuit_t {
    * more. */
   int deliver_window;
 
+  uint8_t n_chan_onionskin_len; /* XXXX MAKE THIS GET USED. */
   /** For storage while n_chan is pending
     * (state CIRCUIT_STATE_CHAN_WAIT). When defined, it is always
-    * length ONIONSKIN_CHALLENGE_LEN. */
+    * length n_chan_onionskin_len */
   char *n_chan_onionskin;
 
   /** When was this circuit created?  We keep this timestamp with a higher
@@ -2965,6 +2978,7 @@ typedef struct or_circuit_t {
   char rend_token[REND_TOKEN_LEN];
 
   /* ???? move to a subtype or adjunct structure? Wastes 20 bytes -NM */
+  /* XXXX rename this. */
   char handshake_digest[DIGEST_LEN]; /**< Stores KH for the handshake. */
 
   /** How many more relay_early cells can we send on this circuit, according
diff --git a/src/or/rendclient.c b/src/or/rendclient.c
index 3fb4025..61fb3aa 100644
--- a/src/or/rendclient.c
+++ b/src/or/rendclient.c
@@ -206,12 +206,12 @@ 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(DH_TYPE_REND))) {
+    if (!(cpath->rend_dh_handshake_state = crypto_dh_new(DH_TYPE_REND))) {
       log_warn(LD_BUG, "Internal error: couldn't allocate DH.");
       status = -2;
       goto perm_err;
     }
-    if (crypto_dh_generate_public(cpath->dh_handshake_state)<0) {
+    if (crypto_dh_generate_public(cpath->rend_dh_handshake_state)<0) {
       log_warn(LD_BUG, "Internal error: couldn't generate g^x.");
       status = -2;
       goto perm_err;
@@ -261,7 +261,7 @@ rend_client_send_introduction(origin_circuit_t *introcirc,
     dh_offset = MAX_NICKNAME_LEN+1+REND_COOKIE_LEN;
   }
 
-  if (crypto_dh_get_public(cpath->dh_handshake_state, tmp+dh_offset,
+  if (crypto_dh_get_public(cpath->rend_dh_handshake_state, tmp+dh_offset,
                            DH_KEY_LEN)<0) {
     log_warn(LD_BUG, "Internal error: couldn't extract g^x.");
     status = -2;
@@ -896,9 +896,9 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
   tor_assert(circ->build_state);
   tor_assert(circ->build_state->pending_final_cpath);
   hop = circ->build_state->pending_final_cpath;
-  tor_assert(hop->dh_handshake_state);
+  tor_assert(hop->rend_dh_handshake_state);
   if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN,
-                               hop->dh_handshake_state, (char*)request,
+                               hop->rend_dh_handshake_state, (char*)request,
                                DH_KEY_LEN,
                                keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
     log_warn(LD_GENERAL, "Couldn't complete DH handshake.");
@@ -914,8 +914,8 @@ rend_client_receive_rendezvous(origin_circuit_t *circ, const uint8_t *request,
     goto err;
   }
 
-  crypto_dh_free(hop->dh_handshake_state);
-  hop->dh_handshake_state = NULL;
+  crypto_dh_free(hop->rend_dh_handshake_state);
+  hop->rend_dh_handshake_state = NULL;
 
   /* All is well. Extend the circuit. */
   circuit_change_purpose(TO_CIRCUIT(circ), CIRCUIT_PURPOSE_C_REND_JOINED);
diff --git a/src/or/rendservice.c b/src/or/rendservice.c
index 09792bd..08a7feb 100644
--- a/src/or/rendservice.c
+++ b/src/or/rendservice.c
@@ -1378,7 +1378,7 @@ rend_service_introduce(origin_circuit_t *circuit, const uint8_t *request,
   cpath->magic = CRYPT_PATH_MAGIC;
   launched->build_state->expiry_time = now + MAX_REND_TIMEOUT;
 
-  cpath->dh_handshake_state = dh;
+  cpath->rend_dh_handshake_state = dh;
   dh = NULL;
   if (circuit_init_cpath_crypto(cpath,keys+DIGEST_LEN,1)<0)
     goto err;
@@ -2624,7 +2624,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
 
   /* All we need to do is send a RELAY_RENDEZVOUS1 cell... */
   memcpy(buf, circuit->rend_data->rend_cookie, REND_COOKIE_LEN);
-  if (crypto_dh_get_public(hop->dh_handshake_state,
+  if (crypto_dh_get_public(hop->rend_dh_handshake_state,
                            buf+REND_COOKIE_LEN, DH_KEY_LEN)<0) {
     log_warn(LD_GENERAL,"Couldn't get DH public key.");
     reason = END_CIRC_REASON_INTERNAL;
@@ -2643,8 +2643,8 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
     goto err;
   }
 
-  crypto_dh_free(hop->dh_handshake_state);
-  hop->dh_handshake_state = NULL;
+  crypto_dh_free(hop->rend_dh_handshake_state);
+  hop->rend_dh_handshake_state = NULL;
 
   /* Append the cpath entry. */
   hop->state = CPATH_STATE_OPEN;
diff --git a/src/or/router.c b/src/or/router.c
index 954304d..3733bec 100644
--- a/src/or/router.c
+++ b/src/or/router.c
@@ -1598,6 +1598,13 @@ router_digest_is_me(const char *digest)
           tor_memeq(server_identitykey_digest, digest, DIGEST_LEN));
 }
 
+/** DOCDOC */
+const uint8_t *
+router_get_my_id_digest(void)
+{
+  return (const uint8_t *)server_identitykey_digest;
+}
+
 /** Return true iff I'm a server and <b>digest</b> is equal to
  * my identity digest. */
 int
diff --git a/src/or/router.h b/src/or/router.h
index 85c7d35..ea0b2ab 100644
--- a/src/or/router.h
+++ b/src/or/router.h
@@ -84,6 +84,7 @@ extrainfo_t *router_get_my_extrainfo(void);
 const char *router_get_my_descriptor(void);
 const char *router_get_descriptor_gen_reason(void);
 int router_digest_is_me(const char *digest);
+const uint8_t *router_get_my_id_digest(void);
 int router_extrainfo_digest_is_me(const char *digest);
 int router_is_me(const routerinfo_t *router);
 int router_fingerprint_is_me(const char *fp);
diff --git a/src/test/bench.c b/src/test/bench.c
index 567b1a4..23560cd 100644
--- a/src/test/bench.c
+++ b/src/test/bench.c
@@ -110,8 +110,8 @@ bench_onion_TAP(void)
   int i;
   crypto_pk_t *key, *key2;
   uint64_t start, end;
-  char os[ONIONSKIN_CHALLENGE_LEN];
-  char or[ONIONSKIN_REPLY_LEN];
+  char os[TAP_ONIONSKIN_CHALLENGE_LEN];
+  char or[TAP_ONIONSKIN_REPLY_LEN];
   crypto_dh_t *dh_out;
 
   key = crypto_pk_new();
@@ -122,17 +122,18 @@ bench_onion_TAP(void)
   reset_perftime();
   start = perftime();
   for (i = 0; i < iters; ++i) {
-    onion_skin_create(key, &dh_out, os);
+    onion_skin_TAP_create(key, &dh_out, os);
     crypto_dh_free(dh_out);
   }
   end = perftime();
   printf("Client-side, part 1: %f usec.\n", NANOCOUNT(start, end, iters)/1e3);
 
-  onion_skin_create(key, &dh_out, os);
+  onion_skin_TAP_create(key, &dh_out, os);
   start = perftime();
   for (i = 0; i < iters; ++i) {
     char key_out[CPATH_KEY_MATERIAL_LEN];
-    onion_skin_server_handshake(os, key, NULL, or, key_out, sizeof(key_out));
+    onion_skin_TAP_server_handshake(os, key, NULL, or,
+                                    key_out, sizeof(key_out));
   }
   end = perftime();
   printf("Server-side, key guessed right: %f usec\n",
@@ -141,7 +142,8 @@ bench_onion_TAP(void)
   start = perftime();
   for (i = 0; i < iters; ++i) {
     char key_out[CPATH_KEY_MATERIAL_LEN];
-    onion_skin_server_handshake(os, key2, key, or, key_out, sizeof(key_out));
+    onion_skin_TAP_server_handshake(os, key2, key, or,
+                                    key_out, sizeof(key_out));
   }
   end = perftime();
   printf("Server-side, key guessed wrong: %f usec.\n",
@@ -153,7 +155,7 @@ bench_onion_TAP(void)
     char key_out[CPATH_KEY_MATERIAL_LEN];
     int s;
     dh = crypto_dh_dup(dh_out);
-    s = onion_skin_client_handshake(dh, or, key_out, sizeof(key_out));
+    s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out));
     tor_assert(s == 0);
   }
   end = perftime();
diff --git a/src/test/test.c b/src/test/test.c
index cc2d481..daac67e 100644
--- a/src/test/test.c
+++ b/src/test/test.c
@@ -819,11 +819,11 @@ test_onion_handshake(void)
 {
   /* client-side */
   crypto_dh_t *c_dh = NULL;
-  char c_buf[ONIONSKIN_CHALLENGE_LEN];
+  char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN];
   char c_keys[40];
 
   /* server-side */
-  char s_buf[ONIONSKIN_REPLY_LEN];
+  char s_buf[TAP_ONIONSKIN_REPLY_LEN];
   char s_keys[40];
 
   /* shared */
@@ -832,18 +832,18 @@ test_onion_handshake(void)
   pk = pk_generate(0);
 
   /* client handshake 1. */
-  memset(c_buf, 0, ONIONSKIN_CHALLENGE_LEN);
-  test_assert(! onion_skin_create(pk, &c_dh, c_buf));
+  memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN);
+  test_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf));
 
   /* server handshake */
-  memset(s_buf, 0, ONIONSKIN_REPLY_LEN);
+  memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN);
   memset(s_keys, 0, 40);
-  test_assert(! onion_skin_server_handshake(c_buf, pk, NULL,
+  test_assert(! onion_skin_TAP_server_handshake(c_buf, pk, NULL,
                                             s_buf, s_keys, 40));
 
   /* client handshake 2 */
   memset(c_keys, 0, 40);
-  test_assert(! onion_skin_client_handshake(c_dh, s_buf, c_keys, 40));
+  test_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40));
 
   if (memcmp(c_keys, s_keys, 40)) {
     puts("Aiiiie");





More information about the tor-commits mailing list