|  | @@ -19,7 +19,8 @@ extern circuit_t *global_circuitlist;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /********* END VARIABLES ************/
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -static int circuit_deliver_create_cell(circuit_t *circ, char *payload);
 | 
	
		
			
				|  |  | +static int circuit_deliver_create_cell(circuit_t *circ,
 | 
	
		
			
				|  |  | +                                       uint8_t cell_type, char *payload);
 | 
	
		
			
				|  |  |  static int onion_pick_cpath_exit(circuit_t *circ, routerinfo_t *exit);
 | 
	
		
			
				|  |  |  static crypt_path_t *onion_next_hop_in_cpath(crypt_path_t *cpath);
 | 
	
		
			
				|  |  |  static int onion_next_router_in_cpath(circuit_t *circ, routerinfo_t **router);
 | 
	
	
		
			
				|  | @@ -374,7 +375,7 @@ void circuit_n_conn_done(connection_t *or_conn, int status) {
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |        } else {
 | 
	
		
			
				|  |  |          /* pull the create cell out of circ->onionskin, and send it */
 | 
	
		
			
				|  |  | -        if (circuit_deliver_create_cell(circ, circ->onionskin) < 0) {
 | 
	
		
			
				|  |  | +        if (circuit_deliver_create_cell(circ,CELL_CREATE,circ->onionskin) < 0) {
 | 
	
		
			
				|  |  |            circuit_mark_for_close(circ);
 | 
	
		
			
				|  |  |            continue;
 | 
	
		
			
				|  |  |          }
 | 
	
	
		
			
				|  | @@ -384,7 +385,7 @@ void circuit_n_conn_done(connection_t *or_conn, int status) {
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  static int
 | 
	
		
			
				|  |  | -circuit_deliver_create_cell(circuit_t *circ, char *payload) {
 | 
	
		
			
				|  |  | +circuit_deliver_create_cell(circuit_t *circ, uint8_t cell_type, char *payload) {
 | 
	
		
			
				|  |  |    cell_t cell;
 | 
	
		
			
				|  |  |    uint16_t id;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -392,6 +393,7 @@ circuit_deliver_create_cell(circuit_t *circ, char *payload) {
 | 
	
		
			
				|  |  |    tor_assert(circ->n_conn);
 | 
	
		
			
				|  |  |    tor_assert(circ->n_conn->type == CONN_TYPE_OR);
 | 
	
		
			
				|  |  |    tor_assert(payload);
 | 
	
		
			
				|  |  | +  tor_assert(cell_type == CELL_CREATE || cell_type == CELL_CREATE_FAST);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    id = get_unique_circ_id_by_conn(circ->n_conn);
 | 
	
		
			
				|  |  |    if (!id) {
 | 
	
	
		
			
				|  | @@ -402,7 +404,7 @@ circuit_deliver_create_cell(circuit_t *circ, char *payload) {
 | 
	
		
			
				|  |  |    circuit_set_circid_orconn(circ, id, circ->n_conn, N_CONN_CHANGED);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    memset(&cell, 0, sizeof(cell_t));
 | 
	
		
			
				|  |  | -  cell.command = CELL_CREATE;
 | 
	
		
			
				|  |  | +  cell.command = cell_type;
 | 
	
		
			
				|  |  |    cell.circ_id = circ->n_circ_id;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    memcpy(cell.payload, payload, ONIONSKIN_CHALLENGE_LEN);
 | 
	
	
		
			
				|  | @@ -434,6 +436,7 @@ int circuit_send_next_onion_skin(circuit_t *circ) {
 | 
	
		
			
				|  |  |    tor_assert(CIRCUIT_IS_ORIGIN(circ));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (circ->cpath->state == CPATH_STATE_CLOSED) {
 | 
	
		
			
				|  |  | +    uint8_t cell_type;
 | 
	
		
			
				|  |  |      log_fn(LOG_DEBUG,"First skin; sending create cell.");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      router = router_get_by_digest(circ->n_conn->identity_digest);
 | 
	
	
		
			
				|  | @@ -443,14 +446,30 @@ int circuit_send_next_onion_skin(circuit_t *circ) {
 | 
	
		
			
				|  |  |        return -1;
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (onion_skin_create(router->onion_pkey,
 | 
	
		
			
				|  |  | -                          &(circ->cpath->handshake_state),
 | 
	
		
			
				|  |  | -                          payload) < 0) {
 | 
	
		
			
				|  |  | -      log_fn(LOG_WARN,"onion_skin_create (first hop) failed.");
 | 
	
		
			
				|  |  | -      return -1;
 | 
	
		
			
				|  |  | +    if (get_options()->ORPort || !router->platform ||
 | 
	
		
			
				|  |  | +        !tor_version_as_new_as(router->platform, "0.1.0.6-rc")) {
 | 
	
		
			
				|  |  | +      /* We are an OR, or we are connecting to an old Tor: we should
 | 
	
		
			
				|  |  | +       * send an old slow create cell.
 | 
	
		
			
				|  |  | +       */
 | 
	
		
			
				|  |  | +      cell_type = CELL_CREATE;
 | 
	
		
			
				|  |  | +      if (onion_skin_create(router->onion_pkey,
 | 
	
		
			
				|  |  | +                            &(circ->cpath->dh_handshake_state),
 | 
	
		
			
				|  |  | +                            payload) < 0) {
 | 
	
		
			
				|  |  | +        log_fn(LOG_WARN,"onion_skin_create (first hop) failed.");
 | 
	
		
			
				|  |  | +        return -1;
 | 
	
		
			
				|  |  | +      }
 | 
	
		
			
				|  |  | +    } else {
 | 
	
		
			
				|  |  | +      /* We are not an OR, and we building the first hop of a circuit to
 | 
	
		
			
				|  |  | +       * a new OR: we can be speedy. */
 | 
	
		
			
				|  |  | +      cell_type = CELL_CREATE_FAST;
 | 
	
		
			
				|  |  | +      memset(payload, 0, sizeof(payload));
 | 
	
		
			
				|  |  | +      crypto_rand(circ->cpath->fast_handshake_state,
 | 
	
		
			
				|  |  | +                  sizeof(circ->cpath->fast_handshake_state));
 | 
	
		
			
				|  |  | +      memcpy(payload, circ->cpath->fast_handshake_state,
 | 
	
		
			
				|  |  | +             sizeof(circ->cpath->fast_handshake_state));
 | 
	
		
			
				|  |  |      }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (circuit_deliver_create_cell(circ, payload) < 0)
 | 
	
		
			
				|  |  | +    if (circuit_deliver_create_cell(circ, cell_type, payload) < 0)
 | 
	
		
			
				|  |  |        return -1;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |      circ->cpath->state = CPATH_STATE_AWAITING_KEYS;
 | 
	
	
		
			
				|  | @@ -491,7 +510,7 @@ int circuit_send_next_onion_skin(circuit_t *circ) {
 | 
	
		
			
				|  |  |      memcpy(payload+2+4+ONIONSKIN_CHALLENGE_LEN, hop->identity_digest, DIGEST_LEN);
 | 
	
		
			
				|  |  |      payload_len = 2+4+ONIONSKIN_CHALLENGE_LEN+DIGEST_LEN;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -    if (onion_skin_create(router->onion_pkey, &(hop->handshake_state), onionskin) < 0) {
 | 
	
		
			
				|  |  | +    if (onion_skin_create(router->onion_pkey, &(hop->dh_handshake_state), onionskin) < 0) {
 | 
	
		
			
				|  |  |        log_fn(LOG_WARN,"onion_skin_create failed.");
 | 
	
		
			
				|  |  |        return -1;
 | 
	
		
			
				|  |  |      }
 | 
	
	
		
			
				|  | @@ -589,7 +608,7 @@ int circuit_extend(cell_t *cell, circuit_t *circ) {
 | 
	
		
			
				|  |  |    memcpy(circ->n_conn_id_digest, n_conn->identity_digest, DIGEST_LEN);
 | 
	
		
			
				|  |  |    log_fn(LOG_DEBUG,"n_conn is %s:%u",n_conn->address,n_conn->port);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (circuit_deliver_create_cell(circ, onionskin) < 0)
 | 
	
		
			
				|  |  | +  if (circuit_deliver_create_cell(circ, CELL_CREATE, onionskin) < 0)
 | 
	
		
			
				|  |  |      return -1;
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
	
		
			
				|  | @@ -648,13 +667,14 @@ int circuit_init_cpath_crypto(crypt_path_t *cpath, char *key_data, int reverse)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  /** A created or extended cell came back to us on the circuit,
 | 
	
		
			
				|  |  |   * and it included <b>reply</b> (the second DH key, plus KH).
 | 
	
		
			
				|  |  | + * DOCDOC reply_type.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   * Calculate the appropriate keys and digests, make sure KH is
 | 
	
		
			
				|  |  |   * correct, and initialize this hop of the cpath.
 | 
	
		
			
				|  |  |   *
 | 
	
		
			
				|  |  |   * Return -1 if we want to mark circ for close, else return 0.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -int circuit_finish_handshake(circuit_t *circ, char *reply) {
 | 
	
		
			
				|  |  | +int circuit_finish_handshake(circuit_t *circ, uint8_t reply_type, char *reply) {
 | 
	
		
			
				|  |  |    unsigned char keys[CPATH_KEY_MATERIAL_LEN];
 | 
	
		
			
				|  |  |    crypt_path_t *hop;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -670,16 +690,31 @@ int circuit_finish_handshake(circuit_t *circ, char *reply) {
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |    tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  if (onion_skin_client_handshake(hop->handshake_state, reply, keys,
 | 
	
		
			
				|  |  | -                                  DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
 | 
	
		
			
				|  |  | -    log_fn(LOG_WARN,"onion_skin_client_handshake failed.");
 | 
	
		
			
				|  |  | +  if (reply_type == CELL_CREATED && hop->dh_handshake_state) {
 | 
	
		
			
				|  |  | +    if (onion_skin_client_handshake(hop->dh_handshake_state, reply, keys,
 | 
	
		
			
				|  |  | +                                    DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
 | 
	
		
			
				|  |  | +      log_fn(LOG_WARN,"onion_skin_client_handshake failed.");
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    /* 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, keys,
 | 
	
		
			
				|  |  | +                              DIGEST_LEN*2+CIPHER_KEY_LEN*2) < 0) {
 | 
	
		
			
				|  |  | +      log_fn(LOG_WARN,"fast_client_handshake failed.");
 | 
	
		
			
				|  |  | +      return -1;
 | 
	
		
			
				|  |  | +    }
 | 
	
		
			
				|  |  | +    memcpy(hop->handshake_digest, reply+DIGEST_LEN, DIGEST_LEN);
 | 
	
		
			
				|  |  | +  } else {
 | 
	
		
			
				|  |  | +    log_fn(LOG_WARN,"CREATED cell type did not match CREATE cell type.");
 | 
	
		
			
				|  |  |      return -1;
 | 
	
		
			
				|  |  |    }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  crypto_dh_free(hop->handshake_state); /* don't need it anymore */
 | 
	
		
			
				|  |  | -  hop->handshake_state = NULL;
 | 
	
		
			
				|  |  | -  /* Remember hash of g^xy */
 | 
	
		
			
				|  |  | -  memcpy(hop->handshake_digest, reply+DH_KEY_LEN, DIGEST_LEN);
 | 
	
		
			
				|  |  | +  if (hop->dh_handshake_state) {
 | 
	
		
			
				|  |  | +    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));
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    if (circuit_init_cpath_crypto(hop, keys, 0)<0) {
 | 
	
		
			
				|  |  |      return -1;
 | 
	
	
		
			
				|  | @@ -742,7 +777,7 @@ int circuit_truncated(circuit_t *circ, crypt_path_t *layer) {
 | 
	
		
			
				|  |  |  /** Given a response payload and keys, initialize, then send a created
 | 
	
		
			
				|  |  |   * cell back.
 | 
	
		
			
				|  |  |   */
 | 
	
		
			
				|  |  | -int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *keys) {
 | 
	
		
			
				|  |  | +int onionskin_answer(circuit_t *circ, uint8_t cell_type, unsigned char *payload, unsigned char *keys) {
 | 
	
		
			
				|  |  |    cell_t cell;
 | 
	
		
			
				|  |  |    crypt_path_t *tmp_cpath;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -750,14 +785,15 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key
 | 
	
		
			
				|  |  |    tmp_cpath->magic = CRYPT_PATH_MAGIC;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    memset(&cell, 0, sizeof(cell_t));
 | 
	
		
			
				|  |  | -  cell.command = CELL_CREATED;
 | 
	
		
			
				|  |  | +  cell.command = cell_type;
 | 
	
		
			
				|  |  |    cell.circ_id = circ->p_circ_id;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    circ->state = CIRCUIT_STATE_OPEN;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    log_fn(LOG_DEBUG,"Entering.");
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  memcpy(cell.payload, payload, ONIONSKIN_REPLY_LEN);
 | 
	
		
			
				|  |  | +  memcpy(cell.payload, payload,
 | 
	
		
			
				|  |  | +         cell_type == CELL_CREATED ? ONIONSKIN_REPLY_LEN : DIGEST_LEN*2);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    log_fn(LOG_INFO,"init digest forward 0x%.8x, backward 0x%.8x.",
 | 
	
		
			
				|  |  |           (unsigned int)*(uint32_t*)(keys), (unsigned int)*(uint32_t*)(keys+20));
 | 
	
	
		
			
				|  | @@ -773,7 +809,10 @@ int onionskin_answer(circuit_t *circ, unsigned char *payload, unsigned char *key
 | 
	
		
			
				|  |  |    tmp_cpath->magic = 0;
 | 
	
		
			
				|  |  |    tor_free(tmp_cpath);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -  memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN);
 | 
	
		
			
				|  |  | +  if (cell_type == CELL_CREATED)
 | 
	
		
			
				|  |  | +    memcpy(circ->handshake_digest, cell.payload+DH_KEY_LEN, DIGEST_LEN);
 | 
	
		
			
				|  |  | +  else
 | 
	
		
			
				|  |  | +    memcpy(circ->handshake_digest, cell.payload+DIGEST_LEN, DIGEST_LEN);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    connection_or_write_cell_to_buf(&cell, circ->p_conn);
 | 
	
		
			
				|  |  |    log_fn(LOG_DEBUG,"Finished sending 'created' cell.");
 | 
	
	
		
			
				|  | @@ -1457,4 +1496,3 @@ onion_append_hop(crypt_path_t **head_ptr, routerinfo_t *choice) {
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |    return 0;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  | -
 |