summaryrefslogtreecommitdiff
path: root/src/or/circuitbuild.c
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2012-12-04 21:27:07 -0500
committerNick Mathewson <nickm@torproject.org>2013-01-03 11:29:46 -0500
commitf58d4dfcd61aec7ea1900873ca08ecc31d7a7ef7 (patch)
tree12e9b9fbcbbaf319638926575b913daaea05f7e9 /src/or/circuitbuild.c
parent5fa1c7484cba293e6467acbca06a4143ce9da68d (diff)
downloadtor-f58d4dfcd61aec7ea1900873ca08ecc31d7a7ef7.tar.gz
tor-f58d4dfcd61aec7ea1900873ca08ecc31d7a7ef7.zip
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.
Diffstat (limited to 'src/or/circuitbuild.c')
-rw-r--r--src/or/circuitbuild.c122
1 files changed, 68 insertions, 54 deletions
diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c
index b6cf1252f6..8393ba1717 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