Commit f58d4dfc authored by Nick Mathewson's avatar Nick Mathewson 🤹
Browse files

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.
parent 5fa1c748
Loading
Loading
Loading
Loading
+68 −54
Original line number Original line Diff line number Diff line
@@ -27,6 +27,7 @@
#include "main.h"
#include "main.h"
#include "networkstatus.h"
#include "networkstatus.h"
#include "nodelist.h"
#include "nodelist.h"
#include "onion.h"
#include "onion_tap.h"
#include "onion_tap.h"
#include "onion_fast.h"
#include "onion_fast.h"
#include "policies.h"
#include "policies.h"
@@ -54,7 +55,9 @@ static channel_t * channel_connect_for_circuit(const tor_addr_t *addr,
                                               uint16_t port,
                                               uint16_t port,
                                               const char *id_digest);
                                               const char *id_digest);
static int circuit_deliver_create_cell(circuit_t *circ,
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 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 crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
static int onion_extend_cpath(origin_circuit_t *circ);
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 */
        /* pull the create cell out of circ->onionskin, and send it */
        tor_assert(circ->n_chan_onionskin);
        tor_assert(circ->n_chan_onionskin);
        if (circuit_deliver_create_cell(circ,CELL_CREATE,
        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);
          circuit_mark_for_close(circ, END_CIRC_REASON_RESOURCELIMIT);
          continue;
          continue;
        }
        }
@@ -491,12 +495,12 @@ circuit_n_chan_done(channel_t *chan, int status)
 * for the outgoing
 * for the outgoing
 * circuit <b>circ</b>, and deliver a cell of type <b>cell_type</b>
 * 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>
 * (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.
 * Return -1 if we failed to find a suitable circid, else return 0.
 */
 */
static int
static int
circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
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;
  cell_t cell;
  circid_t id;
  circid_t id;
@@ -518,7 +522,7 @@ circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type,
  cell.command = cell_type;
  cell.command = cell_type;
  cell.circ_id = circ->n_circ_id;
  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,
  append_cell_to_circuit_queue(circ, circ->n_chan, &cell,
                               CELL_DIRECTION_OUT, 0);
                               CELL_DIRECTION_OUT, 0);


@@ -611,8 +615,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
{
{
  crypt_path_t *hop;
  crypt_path_t *hop;
  const node_t *node;
  const node_t *node;
  char payload[2+4+DIGEST_LEN+ONIONSKIN_CHALLENGE_LEN];
  uint8_t payload[2+4+DIGEST_LEN+MAX_ONIONSKIN_CHALLENGE_LEN];
  char *onionskin;
  uint8_t *onionskin;
  uint16_t handshake_type;
  int onionskin_len;
  size_t payload_len;
  size_t payload_len;


  tor_assert(circ);
  tor_assert(circ);
@@ -633,30 +639,29 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
       * send an old slow create cell.
       * send an old slow create cell.
       */
       */
      cell_type = CELL_CREATE;
      cell_type = CELL_CREATE;
      if (onion_skin_create(circ->cpath->extend_info->onion_key,
      handshake_type = ONION_HANDSHAKE_TYPE_TAP;
                            &(circ->cpath->dh_handshake_state),
                            payload) < 0) {
        log_warn(LD_CIRC,"onion_skin_create (first hop) failed.");
        return - END_CIRC_REASON_INTERNAL;
      }
      note_request("cell: create", 1);
      note_request("cell: create", 1);
    } else {
    } else {
      /* We are not an OR, and we're building the first hop of a circuit to a
      /* 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
       * new OR: we can be speedy and use CREATE_FAST to save an RSA operation
       * and a DH operation. */
       * and a DH operation. */
      cell_type = CELL_CREATE_FAST;
      cell_type = CELL_CREATE_FAST;
      handshake_type = ONION_HANDSHAKE_TYPE_FAST;
      note_request("cell: create fast", 1);
    }


    memset(payload, 0, sizeof(payload));
    memset(payload, 0, sizeof(payload));
      if (fast_onionskin_create(&circ->cpath->fast_handshake_state,
    onionskin_len = onion_skin_create(handshake_type,
                                (uint8_t *)payload) < 0) {
                                      circ->cpath->extend_info,
        log_warn(LD_CIRC,"onion_skin_create FAST (first hop) failed.");
                                      &circ->cpath->handshake_state,
                                      payload);
    if (onionskin_len < 0) {
      log_warn(LD_CIRC,"onion_skin_create (first hop) failed.");
      return - END_CIRC_REASON_INTERNAL;
      return - END_CIRC_REASON_INTERNAL;
    }
    }


      note_request("cell: create fast", 1);
    if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload,
    }
                                    onionskin_len) < 0)

    if (circuit_deliver_create_cell(TO_CIRCUIT(circ), cell_type, payload) < 0)
      return - END_CIRC_REASON_RESOURCELIMIT;
      return - END_CIRC_REASON_RESOURCELIMIT;


    circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
    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));
    set_uint16(payload+4, htons(hop->extend_info->port));


    onionskin = payload+2+4;
    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);
           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;


    if (onion_skin_create(hop->extend_info->onion_key,
    handshake_type = ONION_HANDSHAKE_TYPE_TAP;
                          &(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.");
      log_warn(LD_CIRC,"onion_skin_create failed.");
      return - END_CIRC_REASON_INTERNAL;
      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 */
     * it to a create cell and then send to hop */
    if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
    if (relay_send_command_from_edge(0, TO_CIRCUIT(circ),
                                     RELAY_COMMAND_EXTEND,
                                     RELAY_COMMAND_EXTEND,
                                     payload, payload_len, hop->prev) < 0)
                                     (char*)payload, payload_len,
                                     hop->prev) < 0)
      return 0; /* circuit is closed */
      return 0; /* circuit is closed */


    hop->state = CPATH_STATE_AWAITING_KEYS;
    hop->state = CPATH_STATE_AWAITING_KEYS;
@@ -826,7 +836,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)


  relay_header_unpack(&rh, cell->payload);
  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,
    log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL,
           "Wrong length %d on extend cell. Closing circuit.",
           "Wrong length %d on extend cell. Closing circuit.",
           rh.length);
           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));
  n_port = ntohs(get_uint16(cell->payload+RELAY_HEADER_SIZE+4));
  onionskin = (char*) cell->payload+RELAY_HEADER_SIZE+4+2;
  onionskin = (char*) cell->payload+RELAY_HEADER_SIZE+4+2;
  id_digest = (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);
  tor_addr_from_ipv4h(&n_addr, n_addr32);


  if (!n_port || !n_addr32) {
  if (!n_port || !n_addr32) {
@@ -890,8 +900,10 @@ circuit_extend(cell_t *cell, circuit_t *circ)
                                    NULL /*onion_key*/,
                                    NULL /*onion_key*/,
                                    &n_addr, n_port);
                                    &n_addr, n_port);


    circ->n_chan_onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
    circ->n_chan_onionskin = tor_malloc(TAP_ONIONSKIN_CHALLENGE_LEN);
    memcpy(circ->n_chan_onionskin, onionskin, 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);
    circuit_set_state(circ, CIRCUIT_STATE_CHAN_WAIT);


    if (should_launch) {
    if (should_launch) {
@@ -917,7 +929,8 @@ circuit_extend(cell_t *cell, circuit_t *circ)
            "n_chan is %s",
            "n_chan is %s",
            channel_get_canonical_remote_descr(n_chan));
            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 -1;
  return 0;
  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);
  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,
    uint16_t handshake_type = 0xffff;
                                    DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
    if (reply_type == CELL_CREATED)
      log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
      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;
      return -END_CIRC_REASON_TORPROTOCOL;
    }
    }
    /* Remember hash of g^xy */

    memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
    if (onion_skin_client_handshake(handshake_type,
  } else if (reply_type == CELL_CREATED_FAST && !hop->dh_handshake_state) {
                                    &hop->handshake_state,
    if (fast_client_handshake(hop->fast_handshake_state, reply,
                                    reply,
                              (uint8_t*)keys,
                                    (uint8_t*)keys, sizeof(keys),
                              DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
                                    (uint8_t*)hop->handshake_digest) < 0) {
      log_warn(LD_CIRC,"fast_client_handshake failed.");
      log_warn(LD_CIRC,"onion_skin_client_handshake failed.");
      return -END_CIRC_REASON_TORPROTOCOL;
      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 */
  onion_handshake_state_release(&hop->handshake_state);
  hop->dh_handshake_state = NULL;

  memset(hop->fast_handshake_state, 0, sizeof(hop->fast_handshake_state));


  if (circuit_init_cpath_crypto(hop, keys, 0)<0) {
  if (circuit_init_cpath_crypto(hop, keys, 0)<0) {
    return -END_CIRC_REASON_TORPROTOCOL;
    return -END_CIRC_REASON_TORPROTOCOL;
@@ -1470,7 +1484,7 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, int reason)
 */
 */
int
int
onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload,
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;
  cell_t cell;
  crypt_path_t *tmp_cpath;
  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);
  circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN);


  memcpy(cell.payload, payload,
  memcpy(cell.payload, payload, payload_len);
         cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2);


  log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.",
  log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.",
            (unsigned int)get_uint32(keys),
            (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;
  tmp_cpath->magic = 0;
  tor_free(tmp_cpath);
  tor_free(tmp_cpath);


  /* XXXX Move responsibility for extracting this. */
  if (cell_type == CELL_CREATED)
  if (cell_type == CELL_CREATED)
    memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN);
    memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN);
  else
  else
+2 −1
Original line number Original line Diff line number Diff line
@@ -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 circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer,
                      int reason);
                      int reason);
int onionskin_answer(or_circuit_t *circ, uint8_t cell_type,
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 circuit_all_predicted_ports_handled(time_t now, int *need_uptime,
                                        int *need_capacity);
                                        int *need_capacity);


+4 −3
Original line number Original line Diff line number Diff line
@@ -744,8 +744,8 @@ circuit_free_cpath_node(crypt_path_t *victim)
  crypto_cipher_free(victim->b_crypto);
  crypto_cipher_free(victim->b_crypto);
  crypto_digest_free(victim->f_digest);
  crypto_digest_free(victim->f_digest);
  crypto_digest_free(victim->b_digest);
  crypto_digest_free(victim->b_digest);
  crypto_dh_free(victim->dh_handshake_state);
  onion_handshake_state_release(&victim->handshake_state);
  fast_handshake_state_free(victim->fast_handshake_state);
  crypto_dh_free(victim->rend_dh_handshake_state);
  extend_info_free(victim->extend_info);
  extend_info_free(victim->extend_info);


  memwipe(victim, 0xBB, sizeof(crypt_path_t)); /* poison memory */
  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);
      tor_assert(cp->b_crypto);
      /* fall through */
      /* fall through */
    case CPATH_STATE_CLOSED:
    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;
      break;
    case CPATH_STATE_AWAITING_KEYS:
    case CPATH_STATE_AWAITING_KEYS:
      /* tor_assert(cp->dh_handshake_state); */
      /* tor_assert(cp->dh_handshake_state); */
+6 −4
Original line number Original line Diff line number Diff line
@@ -30,6 +30,7 @@
#include "hibernate.h"
#include "hibernate.h"
#include "nodelist.h"
#include "nodelist.h"
//#include "onion.h"
//#include "onion.h"
#include "onion_tap.h"
#include "onion_fast.h"
#include "onion_fast.h"
#include "relay.h"
#include "relay.h"
#include "router.h"
#include "router.h"
@@ -254,8 +255,8 @@ command_process_create_cell(cell_t *cell, channel_t *chan)
  circ->base_.purpose = CIRCUIT_PURPOSE_OR;
  circ->base_.purpose = CIRCUIT_PURPOSE_OR;
  circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
  circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_ONIONSKIN_PENDING);
  if (cell->command == CELL_CREATE) {
  if (cell->command == CELL_CREATE) {
    char *onionskin = tor_malloc(ONIONSKIN_CHALLENGE_LEN);
    char *onionskin = tor_malloc(TAP_ONIONSKIN_CHALLENGE_LEN);
    memcpy(onionskin, cell->payload, ONIONSKIN_CHALLENGE_LEN);
    memcpy(onionskin, cell->payload, TAP_ONIONSKIN_CHALLENGE_LEN);


    /* hand it off to the cpuworkers, and then return. */
    /* hand it off to the cpuworkers, and then return. */
    if (assign_onionskin_to_cpuworker(NULL, circ, onionskin) < 0) {
    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);
      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
      return;
      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.");
      log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing.");
      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
      circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
      return;
      return;
@@ -340,7 +342,7 @@ command_process_created_cell(cell_t *cell, channel_t *chan)
    log_debug(LD_OR,
    log_debug(LD_OR,
              "Converting created cell to extended relay cell, sending.");
              "Converting created cell to extended relay cell, sending.");
    relay_send_command_from_edge(0, circ, RELAY_COMMAND_EXTENDED,
    relay_send_command_from_edge(0, circ, RELAY_COMMAND_EXTENDED,
                                 (char*)cell->payload, ONIONSKIN_REPLY_LEN,
                                 (char*)cell->payload, TAP_ONIONSKIN_REPLY_LEN,
                                 NULL);
                                 NULL);
  }
  }
}
}
+21 −19
Original line number Original line Diff line number Diff line
@@ -35,7 +35,7 @@
#define TAG_LEN 10
#define TAG_LEN 10
/** How many bytes are sent from the cpuworker back to tor? */
/** How many bytes are sent from the cpuworker back to tor? */
#define LEN_ONION_RESPONSE \
#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. */
/** How many cpuworkers we have running right now. */
static int num_cpuworkers=0;
static int num_cpuworkers=0;
@@ -185,7 +185,8 @@ connection_cpu_process_inbuf(connection_t *conn)
    }
    }
    tor_assert(! CIRCUIT_IS_ORIGIN(circ));
    tor_assert(! CIRCUIT_IS_ORIGIN(circ));
    if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN,
    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.");
      log_warn(LD_OR,"onionskin_answer failed. Closing.");
      circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
      circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL);
      goto done_processing;
      goto done_processing;
@@ -214,11 +215,11 @@ connection_cpu_process_inbuf(connection_t *conn)
 *   Request format:
 *   Request format:
 *          Task type           [1 byte, always CPUWORKER_TASK_ONION]
 *          Task type           [1 byte, always CPUWORKER_TASK_ONION]
 *          Opaque tag          TAG_LEN
 *          Opaque tag          TAG_LEN
 *          Onionskin challenge ONIONSKIN_CHALLENGE_LEN
 *          Onionskin challenge TAP_ONIONSKIN_CHALLENGE_LEN
 *   Response format:
 *   Response format:
 *          Success/failure     [1 byte, boolean.]
 *          Success/failure     [1 byte, boolean.]
 *          Opaque tag          TAG_LEN
 *          Opaque tag          TAG_LEN
 *          Onionskin challenge ONIONSKIN_REPLY_LEN
 *          Onionskin challenge TAP_ONIONSKIN_REPLY_LEN
 *          Negotiated keys     KEY_LEN*2+DIGEST_LEN*2
 *          Negotiated keys     KEY_LEN*2+DIGEST_LEN*2
 *
 *
 *  (Note: this _should_ be by addr/port, since we're concerned with specific
 *  (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
static void
cpuworker_main(void *data)
cpuworker_main(void *data)
{
{
  char question[ONIONSKIN_CHALLENGE_LEN];
  char question[TAP_ONIONSKIN_CHALLENGE_LEN];
  uint8_t question_type;
  uint8_t question_type;
  tor_socket_t *fdarray = data;
  tor_socket_t *fdarray = data;
  tor_socket_t fd;
  tor_socket_t fd;


  /* variables for onion processing */
  /* variables for onion processing */
  char keys[CPATH_KEY_MATERIAL_LEN];
  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 buf[LEN_ONION_RESPONSE];
  char tag[TAG_LEN];
  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 */
  fd = fdarray[1]; /* this side is ours */
#ifndef TOR_IS_MULTITHREADED
#ifndef TOR_IS_MULTITHREADED
@@ -248,7 +249,7 @@ cpuworker_main(void *data)
#endif
#endif
  tor_free(data);
  tor_free(data);


  dup_onion_keys(&onion_key, &last_onion_key);
  setup_server_onion_keys(&onion_keys);


  for (;;) {
  for (;;) {
    ssize_t r;
    ssize_t r;
@@ -275,15 +276,18 @@ cpuworker_main(void *data)
      goto end;
      goto end;
    }
    }


    if (read_all(fd, question, ONIONSKIN_CHALLENGE_LEN, 1) !=
    if (read_all(fd, question, TAP_ONIONSKIN_CHALLENGE_LEN, 1) !=
        ONIONSKIN_CHALLENGE_LEN) {
        TAP_ONIONSKIN_CHALLENGE_LEN) {
      log_err(LD_BUG,"read question failed. Exiting.");
      log_err(LD_BUG,"read question failed. Exiting.");
      goto end;
      goto end;
    }
    }


    if (question_type == CPUWORKER_TASK_ONION) {
    if (question_type == CPUWORKER_TASK_ONION) {
      if (onion_skin_server_handshake(question, onion_key, last_onion_key,
      if (onion_skin_server_handshake(ONION_HANDSHAKE_TYPE_TAP,
          reply_to_proxy, keys, CPATH_KEY_MATERIAL_LEN) < 0) {
                         (const uint8_t*)question,
                         &onion_keys,
                         (uint8_t*)reply_to_proxy,
                         (uint8_t*)keys, CPATH_KEY_MATERIAL_LEN) < 0) {
        /* failure */
        /* failure */
        log_debug(LD_OR,"onion_skin_server_handshake failed.");
        log_debug(LD_OR,"onion_skin_server_handshake failed.");
        *buf = 0; /* indicate failure in first byte */
        *buf = 0; /* indicate failure in first byte */
@@ -295,8 +299,9 @@ cpuworker_main(void *data)
        log_debug(LD_OR,"onion_skin_server_handshake succeeded.");
        log_debug(LD_OR,"onion_skin_server_handshake succeeded.");
        buf[0] = 1; /* 1 means success */
        buf[0] = 1; /* 1 means success */
        memcpy(buf+1,tag,TAG_LEN);
        memcpy(buf+1,tag,TAG_LEN);
        memcpy(buf+1+TAG_LEN,reply_to_proxy,ONIONSKIN_REPLY_LEN);
        memcpy(buf+1+TAG_LEN,reply_to_proxy,TAP_ONIONSKIN_REPLY_LEN);
        memcpy(buf+1+TAG_LEN+ONIONSKIN_REPLY_LEN,keys,CPATH_KEY_MATERIAL_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) {
      if (write_all(fd, buf, LEN_ONION_RESPONSE, 1) != LEN_ONION_RESPONSE) {
        log_err(LD_BUG,"writing response buf failed. Exiting.");
        log_err(LD_BUG,"writing response buf failed. Exiting.");
@@ -306,10 +311,7 @@ cpuworker_main(void *data)
    }
    }
  }
  }
 end:
 end:
  if (onion_key)
  release_server_onion_keys(&onion_keys);
    crypto_pk_free(onion_key);
  if (last_onion_key)
    crypto_pk_free(last_onion_key);
  tor_close_socket(fd);
  tor_close_socket(fd);
  crypto_thread_cleanup();
  crypto_thread_cleanup();
  spawn_exit();
  spawn_exit();
@@ -497,7 +499,7 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker,
    qbuf[0] = CPUWORKER_TASK_ONION;
    qbuf[0] = CPUWORKER_TASK_ONION;
    connection_write_to_buf(qbuf, 1, cpuworker);
    connection_write_to_buf(qbuf, 1, cpuworker);
    connection_write_to_buf(tag, sizeof(tag), 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);
    tor_free(onionskin);
  }
  }
  return 0;
  return 0;
Loading