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