From f7e590df05b1b3568a68ee3eae3965cb58e13de7 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 4 Dec 2012 16:09:52 -0500 Subject: Split onion.[ch] into onion{,_fast,_tap}.[ch] I'm going to want a generic "onionskin" type and set of wrappers, and for that, it will be helpful to isolate the different circuit creation handshakes. Now the original handshake is in onion_tap.[ch], the CREATE_FAST handshake is in onion_fast.[ch], and onion.[ch] now handles the onion queue. This commit does nothing but move code and adjust header files. --- src/or/cpuworker.c | 1 + 1 file changed, 1 insertion(+) (limited to 'src/or/cpuworker.c') diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 119892d710..3a3d68724f 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -23,6 +23,7 @@ #include "cpuworker.h" #include "main.h" #include "onion.h" +#include "onion_tap.h" #include "router.h" /** The maximum number of cpuworker processes we will keep around. */ -- cgit v1.2.3-54-g00ecf From f58d4dfcd61aec7ea1900873ca08ecc31d7a7ef7 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 4 Dec 2012 21:27:07 -0500 Subject: 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(-) (limited to 'src/or/cpuworker.c') 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 circ, and deliver a cell of type cell_type * (either CELL_CREATE or CELL_CREATE_FAST) with payload payload - * 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 78575afcf2..f83cb554cf 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 2c17fd2bbd..2565470e29 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 2718ec92b9..a33a9b1823 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 3a3d68724f..e8087c2b8c 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 f468adab22..90fc830dde 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 circ 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 keys 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 keys, but do not free keys + * 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 state, 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 type + * (one of ONION_HANDSHAKE_TYPE_*): generate the initial "onion skin" in + * onion_skin_out, and store any state information in state_out. + * 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 type, responding to the client request in onion_skin + * using the keys in keys. On success, write our response into + * reply_out, generate keys_out_len bytes worth of key material + * in keys_out_len, 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 type, using our state in handshake_state and the + * server's response in reply On success, generate keys_out_len + * bytes worth of key material in keys_out_len, set + * rend_authenticator_out 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 55ea3f9306..3c12e1f85f 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 4f305a49e3..80015fd3fa 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 464b8451df..0ec526cd02 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 3bd90c95ed..deae1bf8c3 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 6fada77005..f7407a8e95 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 3fb4025e69..61fb3aad84 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 09792bd1d7..08a7feb3ec 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 954304dd26..3733bec4d0 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 digest is equal to * my identity digest. */ int diff --git a/src/or/router.h b/src/or/router.h index 85c7d351d1..ea0b2ab4e3 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 567b1a4d7c..23560cd437 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 cc2d481c79..daac67ee47 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"); -- cgit v1.2.3-54-g00ecf From 2802ccaeb6b95e693af7736e58e91434d28ac6a2 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 5 Dec 2012 22:34:49 -0500 Subject: Teach cpuworker and others about create_cell_t and friends The unit of work sent to a cpuworker is now a create_cell_t; its response is now a created_cell_t. Several of the things that call or get called by this chain of logic now take create_cell_t or created_cell_t too. Since all cpuworkers are forked or spawned by Tor, they don't need a stable wire protocol, so we can just send structs. This saves us some insanity, and helps p --- src/or/circuitbuild.c | 36 +++------- src/or/circuitbuild.h | 8 ++- src/or/command.c | 73 +++++++++++++------ src/or/cpuworker.c | 189 +++++++++++++++++++++++++++----------------------- src/or/cpuworker.h | 3 +- src/or/onion.c | 57 ++++++++++----- src/or/onion.h | 13 ++-- src/or/or.h | 1 + src/or/relay.c | 20 ++++-- 9 files changed, 235 insertions(+), 165 deletions(-) (limited to 'src/or/cpuworker.c') diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 40aad6d992..40cb8e43ab 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1359,7 +1359,7 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) } /** A created or extended cell came back to us on the circuit, and it included - * reply as its body. (If reply_type is CELL_CREATED, the body + * reply_cell as its body. (If reply_type is CELL_CREATED, the body * contains (the second DH key, plus KH). If reply_type is * CELL_CREATED_FAST, the body contains a secret y and a hash H(x|y).) * @@ -1369,8 +1369,8 @@ entry_guard_inc_first_hop_count(entry_guard_t *guard) * Return - reason if we want to mark circ for close, else return 0. */ int -circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, - const uint8_t *reply) +circuit_finish_handshake(origin_circuit_t *circ, + const created_cell_t *reply) { char keys[CPATH_KEY_MATERIAL_LEN]; crypt_path_t *hop; @@ -1391,23 +1391,9 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, tor_assert(hop->state == CPATH_STATE_AWAITING_KEYS); { - 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; - } - - if (onion_skin_client_handshake(handshake_type, + if (onion_skin_client_handshake(hop->handshake_state.tag, &hop->handshake_state, - reply, + reply->reply, reply->handshake_len, (uint8_t*)keys, sizeof(keys), (uint8_t*)hop->rend_circ_nonce) < 0) { log_warn(LD_CIRC,"onion_skin_client_handshake failed."); @@ -1422,8 +1408,7 @@ circuit_finish_handshake(origin_circuit_t *circ, uint8_t reply_type, } hop->state = CPATH_STATE_OPEN; - log_info(LD_CIRC,"Finished building %scircuit hop:", - (reply_type == CELL_CREATED_FAST) ? "fast " : ""); + log_info(LD_CIRC,"Finished building circuit hop:"); circuit_log_path(LOG_INFO,LD_CIRC,circ); control_event_circuit_status(circ, CIRC_EVENT_EXTENDED, 0); @@ -1484,7 +1469,8 @@ 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, - size_t payload_len, const char *keys) + size_t payload_len, const char *keys, + const uint8_t *rend_circ_nonce) { cell_t cell; crypt_path_t *tmp_cpath; @@ -1515,11 +1501,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->rend_circ_nonce, cell.payload+DH_KEY_LEN, DIGEST_LEN); - else - memcpy(circ->rend_circ_nonce, cell.payload+DIGEST_LEN, DIGEST_LEN); + memcpy(circ->rend_circ_nonce, rend_circ_nonce, DIGEST_LEN); circ->is_first_hop = (cell_type == CELL_CREATED_FAST); diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index f83cb554cf..e53e6ba874 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -30,13 +30,15 @@ void circuit_note_clock_jumped(int seconds_elapsed); int circuit_extend(cell_t *cell, circuit_t *circ); int circuit_init_cpath_crypto(crypt_path_t *cpath, const char *key_data, int reverse); -int circuit_finish_handshake(origin_circuit_t *circ, uint8_t cell_type, - const uint8_t *reply); +struct created_cell_t; +int circuit_finish_handshake(origin_circuit_t *circ, + const struct created_cell_t *created_cell); 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, size_t payload_len, - const char *keys); + const char *keys, + const uint8_t *rend_circ_nonce); int circuit_all_predicted_ports_handled(time_t now, int *need_uptime, int *need_capacity); diff --git a/src/or/command.c b/src/or/command.c index a33a9b1823..c77e2ec8b0 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -29,9 +29,7 @@ #include "cpuworker.h" #include "hibernate.h" #include "nodelist.h" -//#include "onion.h" -#include "onion_tap.h" -#include "onion_fast.h" +#include "onion.h" #include "relay.h" #include "router.h" #include "routerlist.h" @@ -189,6 +187,7 @@ command_process_create_cell(cell_t *cell, channel_t *chan) or_circuit_t *circ; const or_options_t *options = get_options(); int id_is_high; + create_cell_t *create_cell; tor_assert(cell); tor_assert(chan); @@ -254,12 +253,18 @@ command_process_create_cell(cell_t *cell, channel_t *chan) circ = or_circuit_new(cell->circ_id, 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(TAP_ONIONSKIN_CHALLENGE_LEN); - memcpy(onionskin, cell->payload, TAP_ONIONSKIN_CHALLENGE_LEN); + create_cell = tor_malloc_zero(sizeof(create_cell_t)); + if (create_cell_parse(create_cell, cell) < 0) { + tor_free(create_cell); + log_fn(LOG_PROTOCOL_WARN, LD_OR, + "Bogus/unrecognized create cell; closing."); + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); + return; + } + if (create_cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST) { /* 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, create_cell) < 0) { log_debug(LD_GENERAL,"Failed to hand off onionskin. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_RESOURCELIMIT); return; @@ -268,27 +273,35 @@ command_process_create_cell(cell_t *cell, channel_t *chan) } else { /* This is a CREATE_FAST cell; we can handle it immediately without using * a CPU worker. */ - char keys[CPATH_KEY_MATERIAL_LEN]; - char reply[DIGEST_LEN*2]; - - tor_assert(cell->command == CELL_CREATE_FAST); + uint8_t keys[CPATH_KEY_MATERIAL_LEN]; + uint8_t reply[MAX_ONIONSKIN_REPLY_LEN]; + uint8_t rend_circ_nonce[DIGEST_LEN]; + int len; /* Make sure we never try to use the OR connection on which we * received this cell to satisfy an EXTEND request, */ channel_mark_client(chan); - if (fast_server_handshake(cell->payload, (uint8_t*)reply, - (uint8_t*)keys, sizeof(keys))<0) { + len = onion_skin_server_handshake(ONION_HANDSHAKE_TYPE_FAST, + create_cell->onionskin, + create_cell->handshake_len, + NULL, + reply, keys, CPATH_KEY_MATERIAL_LEN, + rend_circ_nonce); + tor_free(create_cell); + if (len < 0) { log_warn(LD_OR,"Failed to generate key material. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); + tor_free(create_cell); return; } - if (onionskin_answer(circ, CELL_CREATED_FAST, reply, sizeof(reply), - keys)<0) { + if (onionskin_answer(circ, CELL_CREATED_FAST, (const char *)reply, len, + (const char *)keys, rend_circ_nonce)<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; } + memwipe(keys, 0, sizeof(keys)); } } @@ -304,6 +317,7 @@ static void command_process_created_cell(cell_t *cell, channel_t *chan) { circuit_t *circ; + extended_cell_t extended_cell; circ = circuit_get_by_circid_channel(cell->circ_id, chan); @@ -321,12 +335,18 @@ command_process_created_cell(cell_t *cell, channel_t *chan) return; } + if (created_cell_parse(&extended_cell.created_cell, cell) < 0) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, "Unparseable created cell."); + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); + return; + } + if (CIRCUIT_IS_ORIGIN(circ)) { /* we're the OP. Handshake this. */ origin_circuit_t *origin_circ = TO_ORIGIN_CIRCUIT(circ); int err_reason = 0; log_debug(LD_OR,"at OP. Finishing handshake."); - if ((err_reason = circuit_finish_handshake(origin_circ, cell->command, - cell->payload)) < 0) { + if ((err_reason = circuit_finish_handshake(origin_circ, + &extended_cell.created_cell)) < 0) { log_warn(LD_OR,"circuit_finish_handshake failed."); circuit_mark_for_close(circ, -err_reason); return; @@ -339,11 +359,24 @@ command_process_created_cell(cell_t *cell, channel_t *chan) return; } } else { /* pack it into an extended relay cell, and send it. */ + uint8_t command=0; + uint16_t len=0; + uint8_t payload[RELAY_PAYLOAD_SIZE]; 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, TAP_ONIONSKIN_REPLY_LEN, - NULL); + memset(payload, 0, sizeof(payload)); + if (extended_cell.created_cell.cell_type == CELL_CREATED2) + extended_cell.cell_type = RELAY_COMMAND_EXTENDED2; + else + extended_cell.cell_type = RELAY_COMMAND_EXTENDED; + if (extended_cell_format(&command, &len, payload, &extended_cell) < 0) { + log_fn(LOG_PROTOCOL_WARN, LD_OR, "Can't format extended cell."); + circuit_mark_for_close(circ, END_CIRC_REASON_TORPROTOCOL); + return; + } + + relay_send_command_from_edge(0, circ, command, + (const char*)payload, len, NULL); } } diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index e8087c2b8c..a8ec0275a5 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -23,7 +23,6 @@ #include "cpuworker.h" #include "main.h" #include "onion.h" -#include "onion_tap.h" #include "router.h" /** The maximum number of cpuworker processes we will keep around. */ @@ -33,9 +32,6 @@ /** The tag specifies which circuit this onionskin was from. */ #define TAG_LEN 10 -/** How many bytes are sent from the cpuworker back to tor? */ -#define LEN_ONION_RESPONSE \ - (1+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN+CPATH_KEY_MATERIAL_LEN) /** How many cpuworkers we have running right now. */ static int num_cpuworkers=0; @@ -71,7 +67,7 @@ connection_cpu_finished_flushing(connection_t *conn) /** Pack global_id and circ_id; set *tag to the result. (See note on * cpuworker_main for wire format.) */ static void -tag_pack(char *tag, uint64_t chan_id, circid_t circ_id) +tag_pack(uint8_t *tag, uint64_t chan_id, circid_t circ_id) { /*XXXX RETHINK THIS WHOLE MESS !!!! !NM NM NM NM*/ /*XXXX DOUBLEPLUSTHIS!!!! AS AS AS AS*/ @@ -82,12 +78,38 @@ tag_pack(char *tag, uint64_t chan_id, circid_t circ_id) /** Unpack tag into addr, port, and circ_id. */ static void -tag_unpack(const char *tag, uint64_t *chan_id, circid_t *circ_id) +tag_unpack(const uint8_t *tag, uint64_t *chan_id, circid_t *circ_id) { *chan_id = get_uint64(tag); *circ_id = get_uint16(tag+8); } +/** DOCDOC */ +#define CPUWORKER_REQUEST_MAGIC 0xda4afeed +#define CPUWORKER_REPLY_MAGIC 0x5eedf00d + +/**DOCDOC*/ +typedef struct cpuworker_request_t { + uint32_t magic; + /** Opaque tag to identify the job */ + uint8_t tag[TAG_LEN]; + uint8_t task; + + create_cell_t create_cell; + /* Turn the above into a tagged union if needed. */ +} cpuworker_request_t; + +/**DOCDOC*/ +typedef struct cpuworker_reply_t { + uint32_t magic; + uint8_t tag[TAG_LEN]; + uint8_t success; + + created_cell_t created_cell; + uint8_t keys[CPATH_KEY_MATERIAL_LEN]; + uint8_t rend_auth_material[DIGEST_LEN]; +} cpuworker_reply_t; + /** Called when the onion key has changed and we need to spawn new * cpuworkers. Close all currently idle cpuworkers, and mark the last * rotation time as now. @@ -133,8 +155,6 @@ connection_cpu_reached_eof(connection_t *conn) int connection_cpu_process_inbuf(connection_t *conn) { - char success; - char buf[LEN_ONION_RESPONSE]; uint64_t chan_id; circid_t circ_id; channel_t *p_chan = NULL; @@ -147,15 +167,16 @@ connection_cpu_process_inbuf(connection_t *conn) return 0; if (conn->state == CPUWORKER_STATE_BUSY_ONION) { - if (connection_get_inbuf_len(conn) < LEN_ONION_RESPONSE) + cpuworker_reply_t rpl; + if (connection_get_inbuf_len(conn) < sizeof(cpuworker_reply_t)) return 0; /* not yet */ - tor_assert(connection_get_inbuf_len(conn) == LEN_ONION_RESPONSE); + tor_assert(connection_get_inbuf_len(conn) == sizeof(cpuworker_reply_t)); - connection_fetch_from_buf(&success,1,conn); - connection_fetch_from_buf(buf,LEN_ONION_RESPONSE-1,conn); + connection_fetch_from_buf((void*)&rpl,sizeof(cpuworker_reply_t),conn); + tor_assert(rpl.magic == CPUWORKER_REPLY_MAGIC); /* parse out the circ it was talking about */ - tag_unpack(buf, &chan_id, &circ_id); + tag_unpack(rpl.tag, &chan_id, &circ_id); circ = NULL; log_debug(LD_OR, "Unpacking cpuworker reply, chan_id is " U64_FORMAT @@ -166,7 +187,7 @@ connection_cpu_process_inbuf(connection_t *conn) if (p_chan) circ = circuit_get_by_circid_channel(circ_id, p_chan); - if (success == 0) { + if (rpl.success == 0) { log_debug(LD_OR, "decoding onionskin failed. " "(Old key or bad software.) Closing."); @@ -184,9 +205,12 @@ connection_cpu_process_inbuf(connection_t *conn) goto done_processing; } tor_assert(! CIRCUIT_IS_ORIGIN(circ)); - if (onionskin_answer(TO_OR_CIRCUIT(circ), CELL_CREATED, buf+TAG_LEN, - TAP_ONIONSKIN_REPLY_LEN, - buf+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN) < 0) { + if (onionskin_answer(TO_OR_CIRCUIT(circ), + rpl.created_cell.cell_type, + (const char*)rpl.created_cell.reply, + rpl.created_cell.handshake_len, + (const char*)rpl.keys, + rpl.rend_auth_material) < 0) { log_warn(LD_OR,"onionskin_answer failed. Closing."); circuit_mark_for_close(circ, END_CIRC_REASON_INTERNAL); goto done_processing; @@ -213,32 +237,21 @@ connection_cpu_process_inbuf(connection_t *conn) * Read and writes from fdarray[1]. Reads requests, writes answers. * * Request format: - * Task type [1 byte, always CPUWORKER_TASK_ONION] - * Opaque tag TAG_LEN - * Onionskin challenge TAP_ONIONSKIN_CHALLENGE_LEN + * cpuworker_request_t. * Response format: - * Success/failure [1 byte, boolean.] - * Opaque tag TAG_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 - * connections, not with routers (where we'd use identity).) + * cpuworker_reply_t */ static void cpuworker_main(void *data) { - char question[TAP_ONIONSKIN_CHALLENGE_LEN]; - uint8_t question_type; + /* For talking to the parent thread/process */ tor_socket_t *fdarray = data; tor_socket_t fd; /* variables for onion processing */ - char keys[CPATH_KEY_MATERIAL_LEN]; - char reply_to_proxy[MAX_ONIONSKIN_REPLY_LEN]; - char buf[LEN_ONION_RESPONSE]; - char tag[TAG_LEN]; server_onion_keys_t onion_keys; + cpuworker_request_t req; + cpuworker_reply_t rpl; fd = fdarray[1]; /* this side is ours */ #ifndef TOR_IS_MULTITHREADED @@ -252,65 +265,64 @@ cpuworker_main(void *data) setup_server_onion_keys(&onion_keys); for (;;) { - ssize_t r; - - if ((r = recv(fd, (void *)&question_type, 1, 0)) != 1) { -// log_fn(LOG_ERR,"read type failed. Exiting."); - if (r == 0) { - log_info(LD_OR, - "CPU worker exiting because Tor process closed connection " - "(either rotated keys or died)."); - } else { - log_info(LD_OR, - "CPU worker exiting because of error on connection to Tor " - "process."); - log_info(LD_OR,"(Error on %d was %s)", - fd, tor_socket_strerror(tor_socket_errno(fd))); - } + if (read_all(fd, (void *)&req, sizeof(req), 1) != sizeof(req)) { + log_info(LD_OR, "read request failed. Exiting."); goto end; } - tor_assert(question_type == CPUWORKER_TASK_ONION); - - if (read_all(fd, tag, TAG_LEN, 1) != TAG_LEN) { - log_err(LD_BUG,"read tag failed. Exiting."); - goto end; - } - - 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(ONION_HANDSHAKE_TYPE_TAP, - (const uint8_t*)question, - &onion_keys, - (uint8_t*)reply_to_proxy, - (uint8_t*)keys, CPATH_KEY_MATERIAL_LEN) < 0) { + tor_assert(req.magic == CPUWORKER_REQUEST_MAGIC); + + memset(&rpl, 0, sizeof(rpl)); + + if (req.task == CPUWORKER_TASK_ONION) { + const create_cell_t *cc = &req.create_cell; + created_cell_t *cell_out = &rpl.created_cell; + int n; + n = onion_skin_server_handshake(cc->handshake_type, + cc->onionskin, cc->handshake_len, + &onion_keys, + cell_out->reply, + rpl.keys, CPATH_KEY_MATERIAL_LEN, + rpl.rend_auth_material); + if (n < 0) { /* failure */ log_debug(LD_OR,"onion_skin_server_handshake failed."); - *buf = 0; /* indicate failure in first byte */ - memcpy(buf+1,tag,TAG_LEN); - /* send all zeros as answer */ - memset(buf+1+TAG_LEN, 0, LEN_ONION_RESPONSE-(1+TAG_LEN)); + memset(&rpl, 0, sizeof(rpl)); + memcpy(rpl.tag, req.tag, TAG_LEN); + rpl.success = 0; } else { /* success */ 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,TAP_ONIONSKIN_REPLY_LEN); - memcpy(buf+1+TAG_LEN+TAP_ONIONSKIN_REPLY_LEN,keys, - CPATH_KEY_MATERIAL_LEN); + memcpy(rpl.tag, req.tag, TAG_LEN); + cell_out->handshake_len = n; + switch (cc->cell_type) { + case CELL_CREATE: + cell_out->cell_type = CELL_CREATED; break; + case CELL_CREATE2: + cell_out->cell_type = CELL_CREATED2; break; + case CELL_CREATE_FAST: + cell_out->cell_type = CELL_CREATED_FAST; break; + default: + tor_assert(0); + goto end; + } + rpl.success = 1; } - if (write_all(fd, buf, LEN_ONION_RESPONSE, 1) != LEN_ONION_RESPONSE) { + rpl.magic = CPUWORKER_REPLY_MAGIC; + if (write_all(fd, (void*)&rpl, sizeof(rpl), 1) != sizeof(rpl)) { log_err(LD_BUG,"writing response buf failed. Exiting."); goto end; } log_debug(LD_OR,"finished writing response."); + } else if (req.task == CPUWORKER_TASK_SHUTDOWN) { + log_info(LD_OR,"Clean shutdown: exiting"); + goto end; } + memwipe(&req, 0, sizeof(req)); + memwipe(&rpl, 0, sizeof(req)); } end: + memwipe(&req, 0, sizeof(req)); + memwipe(&rpl, 0, sizeof(req)); release_server_onion_keys(&onion_keys); tor_close_socket(fd); crypto_thread_cleanup(); @@ -394,7 +406,7 @@ static void process_pending_task(connection_t *cpuworker) { or_circuit_t *circ; - char *onionskin = NULL; + create_cell_t *onionskin = NULL; tor_assert(cpuworker); @@ -447,10 +459,10 @@ cull_wedged_cpuworkers(void) */ int assign_onionskin_to_cpuworker(connection_t *cpuworker, - or_circuit_t *circ, char *onionskin) + or_circuit_t *circ, + create_cell_t *onionskin) { - char qbuf[1]; - char tag[TAG_LEN]; + cpuworker_request_t req; time_t now = approx_time(); static time_t last_culled_cpuworkers = 0; @@ -486,7 +498,10 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker, tor_free(onionskin); return -1; } - tag_pack(tag, circ->p_chan->global_identifier, + + memset(&req, 0, sizeof(req)); + req.magic = CPUWORKER_REQUEST_MAGIC; + tag_pack(req.tag, circ->p_chan->global_identifier, circ->p_circ_id); cpuworker->state = CPUWORKER_STATE_BUSY_ONION; @@ -496,11 +511,13 @@ assign_onionskin_to_cpuworker(connection_t *cpuworker, cpuworker->timestamp_lastwritten = time(NULL); num_cpuworkers_busy++; - 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, TAP_ONIONSKIN_CHALLENGE_LEN, cpuworker); + req.task = CPUWORKER_TASK_ONION; + memcpy(&req.create_cell, onionskin, sizeof(create_cell_t)); + tor_free(onionskin); + + connection_write_to_buf((void*)&req, sizeof(req), cpuworker); + memwipe(&req, 0, sizeof(req)); } return 0; } diff --git a/src/or/cpuworker.h b/src/or/cpuworker.h index 73c7eefd4c..f607e7d484 100644 --- a/src/or/cpuworker.h +++ b/src/or/cpuworker.h @@ -17,9 +17,10 @@ void cpuworkers_rotate(void); int connection_cpu_finished_flushing(connection_t *conn); int connection_cpu_reached_eof(connection_t *conn); int connection_cpu_process_inbuf(connection_t *conn); +struct create_cell_t; int assign_onionskin_to_cpuworker(connection_t *cpuworker, or_circuit_t *circ, - char *onionskin); + struct create_cell_t *onionskin); #endif diff --git a/src/or/onion.c b/src/or/onion.c index c1f2e5bec0..9326c2fff9 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -25,7 +25,7 @@ * to process a waiting onion handshake. */ typedef struct onion_queue_t { or_circuit_t *circ; - char *onionskin; + create_cell_t *onionskin; time_t when_added; struct onion_queue_t *next; } onion_queue_t; @@ -48,7 +48,7 @@ static int ol_length=0; * if ol_list is too long, in which case do nothing and return -1. */ int -onion_pending_add(or_circuit_t *circ, char *onionskin) +onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin) { onion_queue_t *tmp; time_t now = time(NULL); @@ -105,7 +105,7 @@ onion_pending_add(or_circuit_t *circ, char *onionskin) * NULL if the list is empty. */ or_circuit_t * -onion_next_task(char **onionskin_out) +onion_next_task(create_cell_t **onionskin_out) { or_circuit_t *circ; @@ -302,37 +302,60 @@ onion_skin_create(int type, * using the keys in keys. On success, write our response into * reply_out, generate keys_out_len bytes worth of key material * in keys_out_len, and return the length of the reply. On failure, - * return -1. */ + * return -1. + * DOCDOC rend_nonce_out + */ int onion_skin_server_handshake(int type, - const uint8_t *onion_skin, + const uint8_t *onion_skin, size_t onionskin_len, const server_onion_keys_t *keys, uint8_t *reply_out, - uint8_t *keys_out, size_t keys_out_len) + uint8_t *keys_out, size_t keys_out_len, + uint8_t *rend_nonce_out) { int r = -1; switch (type) { case ONION_HANDSHAKE_TYPE_TAP: + if (onionskin_len != TAP_ONIONSKIN_CHALLENGE_LEN) + return -1; 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; + memcpy(rend_nonce_out, reply_out+DH_KEY_LEN, DIGEST_LEN); break; case ONION_HANDSHAKE_TYPE_FAST: + if (onionskin_len != CREATE_FAST_LEN) + return -1; if (fast_server_handshake(onion_skin, reply_out, keys_out, keys_out_len)<0) return -1; r = CREATED_FAST_LEN; + memcpy(rend_nonce_out, reply_out+DIGEST_LEN, DIGEST_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) + if (onionskin_len != NTOR_ONIONSKIN_LEN) return -1; - r = NTOR_REPLY_LEN; + { + size_t keys_tmp_len = keys_out_len + DIGEST_LEN; + uint8_t *keys_tmp = tor_malloc(keys_out_len + DIGEST_LEN); + + if (onion_skin_ntor_server_handshake( + onion_skin, keys->curve25519_key_map, + keys->my_identity, + reply_out, keys_tmp, keys_tmp_len)<0) { + tor_free(keys_tmp); + return -1; + } + memcpy(keys_out, keys_tmp, keys_out_len); + memcpy(rend_nonce_out, keys_tmp+keys_out_len, DIGEST_LEN); + memwipe(keys_tmp, 0, keys_tmp_len); + tor_free(keys_tmp); + r = NTOR_REPLY_LEN; + } #else return -1; #endif @@ -343,12 +366,6 @@ onion_skin_server_handshake(int type, 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; } @@ -362,7 +379,7 @@ onion_skin_server_handshake(int type, int onion_skin_client_handshake(int type, const onion_handshake_state_t *handshake_state, - const uint8_t *reply, + const uint8_t *reply, size_t reply_len, uint8_t *keys_out, size_t keys_out_len, uint8_t *rend_authenticator_out) { @@ -371,6 +388,8 @@ onion_skin_client_handshake(int type, switch (type) { case ONION_HANDSHAKE_TYPE_TAP: + if (reply_len != TAP_ONIONSKIN_REPLY_LEN) + return -1; if (onion_skin_TAP_client_handshake(handshake_state->u.tap, (const char*)reply, (char *)keys_out, keys_out_len) < 0) @@ -380,6 +399,8 @@ onion_skin_client_handshake(int type, return 0; case ONION_HANDSHAKE_TYPE_FAST: + if (reply_len != CREATED_FAST_LEN) + return -1; if (fast_client_handshake(handshake_state->u.fast, reply, keys_out, keys_out_len) < 0) return -1; @@ -388,6 +409,8 @@ onion_skin_client_handshake(int type, return 0; #ifdef CURVE25519_ENABLED case ONION_HANDSHAKE_TYPE_NTOR: + if (reply_len != NTOR_REPLY_LEN) + return -1; { size_t keys_tmp_len = keys_out_len + DIGEST_LEN; uint8_t *keys_tmp = tor_malloc(keys_tmp_len); diff --git a/src/or/onion.h b/src/or/onion.h index 08e1a22ecf..36cb761188 100644 --- a/src/or/onion.h +++ b/src/or/onion.h @@ -12,8 +12,9 @@ #ifndef TOR_ONION_H #define TOR_ONION_H -int onion_pending_add(or_circuit_t *circ, char *onionskin); -or_circuit_t *onion_next_task(char **onionskin_out); +struct create_cell_t; +int onion_pending_add(or_circuit_t *circ, struct create_cell_t *onionskin); +or_circuit_t *onion_next_task(struct create_cell_t **onionskin_out); void onion_pending_remove(or_circuit_t *circ); void clear_pending_onions(void); @@ -39,14 +40,14 @@ int onion_skin_create(int type, onion_handshake_state_t *state_out, uint8_t *onion_skin_out); int onion_skin_server_handshake(int type, - const uint8_t *onion_skin, + const uint8_t *onion_skin, size_t onionskin_len, const server_onion_keys_t *keys, uint8_t *reply_out, - uint8_t *keys_out, size_t key_out_len); -// uint8_t *rend_authenticator_out); + uint8_t *keys_out, size_t key_out_len, + uint8_t *rend_nonce_out); int onion_skin_client_handshake(int type, const onion_handshake_state_t *handshake_state, - const uint8_t *reply, + const uint8_t *reply, size_t reply_len, uint8_t *keys_out, size_t key_out_len, uint8_t *rend_authenticator_out); diff --git a/src/or/or.h b/src/or/or.h index f9b0f1e0f6..5ea420f73e 100644 --- a/src/or/or.h +++ b/src/or/or.h @@ -280,6 +280,7 @@ typedef enum { #define CPUWORKER_STATE_MAX_ 2 #define CPUWORKER_TASK_ONION CPUWORKER_STATE_BUSY_ONION +#define CPUWORKER_TASK_SHUTDOWN 255 #define OR_CONN_STATE_MIN_ 1 /** State for a connection to an OR: waiting for connect() to finish. */ diff --git a/src/or/relay.c b/src/or/relay.c index d862e58341..d0c8c2291f 100644 --- a/src/or/relay.c +++ b/src/or/relay.c @@ -27,6 +27,7 @@ #include "mempool.h" #include "networkstatus.h" #include "nodelist.h" +#include "onion.h" #include "policies.h" #include "reasons.h" #include "relay.h" @@ -1296,11 +1297,20 @@ connection_edge_process_relay_cell(cell_t *cell, circuit_t *circ, return 0; } log_debug(domain,"Got an extended cell! Yay."); - if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ), - CELL_CREATED, - cell->payload+RELAY_HEADER_SIZE)) < 0) { - log_warn(domain,"circuit_finish_handshake failed."); - return reason; + { + extended_cell_t extended_cell; + if (extended_cell_parse(&extended_cell, rh.command, + (const uint8_t*)cell->payload+RELAY_HEADER_SIZE, + rh.length)<0) { + log_warn(LD_PROTOCOL, + "Can't parse EXTENDED cell; killing circuit."); + return -END_CIRC_REASON_TORPROTOCOL; + } + if ((reason = circuit_finish_handshake(TO_ORIGIN_CIRCUIT(circ), + &extended_cell.created_cell)) < 0) { + log_warn(domain,"circuit_finish_handshake failed."); + return reason; + } } if ((reason=circuit_send_next_onion_skin(TO_ORIGIN_CIRCUIT(circ)))<0) { log_info(domain,"circuit_send_next_onion_skin() failed."); -- cgit v1.2.3-54-g00ecf From 115e8fe9a5342d9f04e14d155d11e8c88f551c84 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Wed, 5 Dec 2012 23:44:27 -0500 Subject: Use created_cell_format where appropriate --- src/or/circuitbuild.c | 19 ++++++++++--------- src/or/circuitbuild.h | 4 ++-- src/or/command.c | 11 ++++++++--- src/or/cpuworker.c | 4 +--- src/or/onion.c | 3 ++- 5 files changed, 23 insertions(+), 18 deletions(-) (limited to 'src/or/cpuworker.c') diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 5ac2692bd4..43ad9f4235 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -1471,24 +1471,25 @@ circuit_truncated(origin_circuit_t *circ, crypt_path_t *layer, int reason) * cell back. */ int -onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, - size_t payload_len, const char *keys, +onionskin_answer(or_circuit_t *circ, + const created_cell_t *created_cell, + const char *keys, const uint8_t *rend_circ_nonce) { cell_t cell; crypt_path_t *tmp_cpath; + if (created_cell_format(&cell, created_cell) < 0) { + log_warn(LD_BUG,"couldn't format created cell"); + return -1; + } + cell.circ_id = circ->p_circ_id; + tmp_cpath = tor_malloc_zero(sizeof(crypt_path_t)); tmp_cpath->magic = CRYPT_PATH_MAGIC; - memset(&cell, 0, sizeof(cell_t)); - cell.command = cell_type; - cell.circ_id = circ->p_circ_id; - circuit_set_state(TO_CIRCUIT(circ), CIRCUIT_STATE_OPEN); - memcpy(cell.payload, payload, payload_len); - log_debug(LD_CIRC,"init digest forward 0x%.8x, backward 0x%.8x.", (unsigned int)get_uint32(keys), (unsigned int)get_uint32(keys+20)); @@ -1506,7 +1507,7 @@ onionskin_answer(or_circuit_t *circ, uint8_t cell_type, const char *payload, memcpy(circ->rend_circ_nonce, rend_circ_nonce, DIGEST_LEN); - circ->is_first_hop = (cell_type == CELL_CREATED_FAST); + circ->is_first_hop = (created_cell->cell_type == CELL_CREATED_FAST); append_cell_to_circuit_queue(TO_CIRCUIT(circ), circ->p_chan, &cell, CELL_DIRECTION_IN, 0); diff --git a/src/or/circuitbuild.h b/src/or/circuitbuild.h index e53e6ba874..23213e8e83 100644 --- a/src/or/circuitbuild.h +++ b/src/or/circuitbuild.h @@ -35,8 +35,8 @@ int circuit_finish_handshake(origin_circuit_t *circ, const struct created_cell_t *created_cell); 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, size_t payload_len, +int onionskin_answer(or_circuit_t *circ, + const struct created_cell_t *created_cell, const char *keys, const uint8_t *rend_circ_nonce); int circuit_all_predicted_ports_handled(time_t now, int *need_uptime, diff --git a/src/or/command.c b/src/or/command.c index c77e2ec8b0..773d19cb5d 100644 --- a/src/or/command.c +++ b/src/or/command.c @@ -274,19 +274,21 @@ command_process_create_cell(cell_t *cell, channel_t *chan) /* This is a CREATE_FAST cell; we can handle it immediately without using * a CPU worker. */ uint8_t keys[CPATH_KEY_MATERIAL_LEN]; - uint8_t reply[MAX_ONIONSKIN_REPLY_LEN]; uint8_t rend_circ_nonce[DIGEST_LEN]; int len; + created_cell_t created_cell; /* Make sure we never try to use the OR connection on which we * received this cell to satisfy an EXTEND request, */ channel_mark_client(chan); + memset(&created_cell, 0, sizeof(created_cell)); len = onion_skin_server_handshake(ONION_HANDSHAKE_TYPE_FAST, create_cell->onionskin, create_cell->handshake_len, NULL, - reply, keys, CPATH_KEY_MATERIAL_LEN, + created_cell.reply, + keys, CPATH_KEY_MATERIAL_LEN, rend_circ_nonce); tor_free(create_cell); if (len < 0) { @@ -295,7 +297,10 @@ command_process_create_cell(cell_t *cell, channel_t *chan) tor_free(create_cell); return; } - if (onionskin_answer(circ, CELL_CREATED_FAST, (const char *)reply, len, + created_cell.cell_type = CELL_CREATED_FAST; + created_cell.handshake_len = len; + + if (onionskin_answer(circ, &created_cell, (const char *)keys, rend_circ_nonce)<0) { log_warn(LD_OR,"Failed to reply to CREATE_FAST cell. Closing."); circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL); diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index a8ec0275a5..1ac8cd59af 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -206,9 +206,7 @@ connection_cpu_process_inbuf(connection_t *conn) } tor_assert(! CIRCUIT_IS_ORIGIN(circ)); if (onionskin_answer(TO_OR_CIRCUIT(circ), - rpl.created_cell.cell_type, - (const char*)rpl.created_cell.reply, - rpl.created_cell.handshake_len, + &rpl.created_cell, (const char*)rpl.keys, rpl.rend_auth_material) < 0) { log_warn(LD_OR,"onionskin_answer failed. Closing."); diff --git a/src/or/onion.c b/src/or/onion.c index 9326c2fff9..ce5eb93b1a 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -496,6 +496,8 @@ parse_create2_payload(create_cell_t *cell_out, const uint8_t *p, size_t p_len) if (cell_out->handshake_len > CELL_PAYLOAD_SIZE - 4 || cell_out->handshake_len > p_len - 4) return -1; + if (cell_out->handshake_type == ONION_HANDSHAKE_TYPE_FAST) + return -1; memcpy(cell_out->onionskin, p+4, cell_out->handshake_len); return 0; } @@ -710,7 +712,6 @@ extend_cell_parse(extend_cell_t *cell_out, const uint8_t command, return -1; if (parse_create2_payload(&cell_out->create_cell,payload,eop-payload)<0) return -1; - break; } default: -- cgit v1.2.3-54-g00ecf From 94cb7bd24d2ffda9038c267b3ee0837dd64ec903 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 25 Dec 2012 22:38:20 -0500 Subject: Complete all DOCDOC entries from the ntor branch --- src/or/circuitbuild.c | 8 ++++---- src/or/cpuworker.c | 21 ++++++++++++++++++--- src/or/onion.c | 5 ++--- src/or/onion_fast.c | 5 +++-- src/or/router.c | 36 ++++++++++++++++++------------------ 5 files changed, 45 insertions(+), 30 deletions(-) (limited to 'src/or/cpuworker.c') diff --git a/src/or/circuitbuild.c b/src/or/circuitbuild.c index 9300b049cb..552167fbe6 100644 --- a/src/or/circuitbuild.c +++ b/src/or/circuitbuild.c @@ -490,10 +490,10 @@ circuit_n_chan_done(channel_t *chan, int status) /** Find a new circid that isn't currently in use on the circ->n_chan * for the outgoing - * circuit circ, and deliver a cell of type cell_type - * (either CELL_CREATE or CELL_CREATE_FAST) with payload payload - * to this circuit. DOCDOC new arguments - * Return -1 if we failed to find a suitable circid, else return 0. + * circuit circ, and deliver the cell create_cell to this + * circuit. If relayed is true, this is a create cell somebody + * gave us via an EXTEND cell, so we shouldn't worry if we don't understand + * it. Return -1 if we failed to find a suitable circid, else return 0. */ static int circuit_deliver_create_cell(circuit_t *circ, const create_cell_t *create_cell, diff --git a/src/or/cpuworker.c b/src/or/cpuworker.c index 1ac8cd59af..3f8fc947b3 100644 --- a/src/or/cpuworker.c +++ b/src/or/cpuworker.c @@ -84,29 +84,44 @@ tag_unpack(const uint8_t *tag, uint64_t *chan_id, circid_t *circ_id) *circ_id = get_uint16(tag+8); } -/** DOCDOC */ +/** Magic numbers to make sure our cpuworker_requests don't grow any + * mis-framing bugs. */ #define CPUWORKER_REQUEST_MAGIC 0xda4afeed #define CPUWORKER_REPLY_MAGIC 0x5eedf00d -/**DOCDOC*/ +/** A request sent to a cpuworker. */ typedef struct cpuworker_request_t { + /** Magic number; must be CPUWORKER_REQUEST_MAGIC. */ uint32_t magic; /** Opaque tag to identify the job */ uint8_t tag[TAG_LEN]; + /** Task code. Must be one of CPUWORKER_TASK_* */ uint8_t task; + /** A create cell for the cpuworker to process. */ create_cell_t create_cell; + /* Turn the above into a tagged union if needed. */ } cpuworker_request_t; -/**DOCDOC*/ +/** A reply sent by a cpuworker. */ typedef struct cpuworker_reply_t { + /** Magic number; must be CPUWORKER_REPLY_MAGIC. */ uint32_t magic; + /** Opaque tag to identify the job; matches the request's tag.*/ uint8_t tag[TAG_LEN]; + /** True iff we got a successful request. */ uint8_t success; + /** Output of processing a create cell + * + * @{ + */ + /** The created cell to send back. */ created_cell_t created_cell; + /** The keys to use on this circuit. */ uint8_t keys[CPATH_KEY_MATERIAL_LEN]; + /** Input to use for authenticating introduce1 cells. */ uint8_t rend_auth_material[DIGEST_LEN]; } cpuworker_reply_t; diff --git a/src/or/onion.c b/src/or/onion.c index 56bc9a3b8a..fc3e621f73 100644 --- a/src/or/onion.c +++ b/src/or/onion.c @@ -304,9 +304,8 @@ onion_skin_create(int type, * type type, responding to the client request in onion_skin * using the keys in keys. On success, write our response into * reply_out, generate keys_out_len bytes worth of key material - * in keys_out_len, and return the length of the reply. On failure, - * return -1. - * DOCDOC rend_nonce_out + * in keys_out_len, a hidden service nonce to rend_nonce_out, + * and return the length of the reply. On failure, return -1. */ int onion_skin_server_handshake(int type, diff --git a/src/or/onion_fast.c b/src/or/onion_fast.c index f33b048c28..eb9eceba88 100644 --- a/src/or/onion_fast.c +++ b/src/or/onion_fast.c @@ -12,7 +12,7 @@ #include "or.h" #include "onion_fast.h" -/**DOCDOC*/ +/** Release all state held in victim. */ void fast_handshake_state_free(fast_handshake_state_t *victim) { @@ -22,7 +22,8 @@ fast_handshake_state_free(fast_handshake_state_t *victim) tor_free(victim); } -/** DOCDOC */ +/** Create the state needed to perform a CREATE_FAST hasnshake. Return 0 + * on success, -1 on failure. */ int fast_onionskin_create(fast_handshake_state_t **handshake_state_out, uint8_t *handshake_out) diff --git a/src/or/router.c b/src/or/router.c index a97db858b0..961fd48d1c 100644 --- a/src/or/router.c +++ b/src/or/router.c @@ -56,8 +56,10 @@ static crypto_pk_t *onionkey=NULL; * generated by clients that have an older version of our descriptor. */ static crypto_pk_t *lastonionkey=NULL; #ifdef CURVE25519_ENABLED -/**DOCDOC*/ +/** Current private ntor secret key: used to perform the ntor handshake. */ static curve25519_keypair_t curve25519_onion_key; +/** Previous private ntor secret key: used to perform the ntor handshake + * with clients that have an older version of our descriptor. */ static curve25519_keypair_t last_curve25519_onion_key; #endif /** Private server "identity key": used to sign directory info and TLS @@ -105,20 +107,6 @@ set_onion_key(crypto_pk_t *k) mark_my_descriptor_dirty("set onion key"); } -#if 0 -/**DOCDOC*/ -static void -set_curve25519_onion_key(const curve25519_keypair_t *kp) -{ - if (tor_memeq(&curve25519_onion_key, kp, sizeof(curve25519_keypair_t))) - return; - - tor_mutex_acquire(key_lock); - memcpy(&curve25519_onion_key, kp, sizeof(curve25519_keypair_t)); - tor_mutex_release(key_lock); -} -#endif - /** Return the current onion key. Requires that the onion key has been * loaded or generated. */ crypto_pk_t * @@ -147,12 +135,15 @@ dup_onion_keys(crypto_pk_t **key, crypto_pk_t **last) } #ifdef CURVE25519_ENABLED -/**DOCDOC only in main thread*/ +/** Return the current secret onion key for the ntor handshake. Must only + * be called from the main thread. */ static const curve25519_keypair_t * get_current_curve25519_keypair(void) { return &curve25519_onion_key; } +/** Return a map from KEYID (the key itself) to keypairs for use in the ntor + * handshake. Must only be called from the main thread. */ di_digest256_map_t * construct_ntor_key_map(void) { @@ -173,6 +164,8 @@ construct_ntor_key_map(void) return m; } +/** Helper used to deallocate a di_digest256_map_t returned by + * construct_ntor_key_map. */ static void ntor_key_map_free_helper(void *arg) { @@ -180,9 +173,12 @@ ntor_key_map_free_helper(void *arg) memwipe(k, 0, sizeof(*k)); tor_free(k); } +/** Release all storage from a keymap returned by construct_ntor_key_map. */ void ntor_key_map_free(di_digest256_map_t *map) { + if (!map) + return; dimap_free(map, ntor_key_map_free_helper); } #endif @@ -453,7 +449,11 @@ init_key_from_file(const char *fname, int generate, int severity) } #ifdef CURVE25519_ENABLED -/** DOCDOC */ +/** Load a curve25519 keypair from the file fname, writing it into + * keys_out. If the file isn't found and generate is true, + * create a new keypair and write it into the file. If there are errors, log + * them at level severity. Generate files using tag in their + * ASCII wrapper. */ static int init_curve25519_keypair_from_file(curve25519_keypair_t *keys_out, const char *fname, @@ -1599,7 +1599,7 @@ router_digest_is_me(const char *digest) tor_memeq(server_identitykey_digest, digest, DIGEST_LEN)); } -/** DOCDOC */ +/** Return my identity digest. */ const uint8_t * router_get_my_id_digest(void) { -- cgit v1.2.3-54-g00ecf