Migrate extend2/create2 cell encoding to Trunnel
(Not extended2/created2; that's too simple.) Incidentally, add ed25519 identities to the mix when we have them.
This commit is contained in:
parent
1be671f505
commit
e054211237
|
@ -1041,6 +1041,10 @@ circuit_send_next_onion_skin(origin_circuit_t *circ)
|
|||
ec.orport_ipv4.port = hop->extend_info->port;
|
||||
tor_addr_make_unspec(&ec.orport_ipv6.addr);
|
||||
memcpy(ec.node_id, hop->extend_info->identity_digest, DIGEST_LEN);
|
||||
/* 15056 Either here or in the onion.c encoding code, we should make an
|
||||
* option to decide whether we declare the ED identity (if we know one) */
|
||||
memcpy(&ec.ed_pubkey, &hop->extend_info->ed_identity,
|
||||
sizeof(ed25519_public_key_t));
|
||||
|
||||
len = onion_skin_create(ec.create_cell.handshake_type,
|
||||
hop->extend_info,
|
||||
|
@ -1181,7 +1185,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
|
|||
}
|
||||
|
||||
n_chan = channel_get_for_extend((const char*)ec.node_id,
|
||||
/* ed25519 ID: put it here. 15056 */
|
||||
/*&ec.ed25519_id 15056 */
|
||||
&ec.orport_ipv4.addr,
|
||||
&msg,
|
||||
&should_launch);
|
||||
|
@ -1193,7 +1197,7 @@ circuit_extend(cell_t *cell, circuit_t *circ)
|
|||
|
||||
circ->n_hop = extend_info_new(NULL /*nickname*/,
|
||||
(const char*)ec.node_id,
|
||||
NULL, /*ed25519 ID: get from ec. 15056*/
|
||||
&ec.ed_pubkey,
|
||||
NULL, /*onion_key*/
|
||||
NULL, /*curve25519_key*/
|
||||
&ec.orport_ipv4.addr,
|
||||
|
@ -2367,7 +2371,7 @@ extend_info_new(const char *nickname,
|
|||
{
|
||||
extend_info_t *info = tor_malloc_zero(sizeof(extend_info_t));
|
||||
memcpy(info->identity_digest, rsa_id_digest, DIGEST_LEN);
|
||||
if (ed_id)
|
||||
if (ed_id && !ed25519_public_key_is_zero(ed_id))
|
||||
memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t));
|
||||
if (nickname)
|
||||
strlcpy(info->nickname, nickname, sizeof(info->nickname));
|
||||
|
|
287
src/or/onion.c
287
src/or/onion.c
|
@ -76,6 +76,9 @@
|
|||
#include "rephist.h"
|
||||
#include "router.h"
|
||||
|
||||
// trunnel
|
||||
#include "ed25519_cert.h"
|
||||
|
||||
/** Type for a linked list of circuits that are waiting for a free CPU worker
|
||||
* to process a waiting onion handshake. */
|
||||
typedef struct onion_queue_t {
|
||||
|
@ -871,13 +874,111 @@ check_extend_cell(const extend_cell_t *cell)
|
|||
return check_create_cell(&cell->create_cell, 1);
|
||||
}
|
||||
|
||||
/** Protocol constants for specifier types in EXTEND2
|
||||
* @{
|
||||
*/
|
||||
#define SPECTYPE_IPV4 0
|
||||
#define SPECTYPE_IPV6 1
|
||||
#define SPECTYPE_LEGACY_ID 2
|
||||
/** @} */
|
||||
static int
|
||||
extend_cell_from_extend1_cell_body(extend_cell_t *cell_out,
|
||||
const extend1_cell_body_t *cell)
|
||||
{
|
||||
tor_assert(cell_out);
|
||||
memset(cell_out, 0, sizeof(*cell_out));
|
||||
tor_addr_make_unspec(&cell_out->orport_ipv4.addr);
|
||||
tor_addr_make_unspec(&cell_out->orport_ipv6.addr);
|
||||
|
||||
cell_out->cell_type = RELAY_COMMAND_EXTEND;
|
||||
tor_addr_from_ipv4h(&cell_out->orport_ipv4.addr, cell->ipv4addr);
|
||||
cell_out->orport_ipv4.port = cell->port;
|
||||
if (tor_memeq(cell->onionskin, NTOR_CREATE_MAGIC, 16)) {
|
||||
cell_out->create_cell.cell_type = CELL_CREATE2;
|
||||
cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_NTOR;
|
||||
cell_out->create_cell.handshake_len = NTOR_ONIONSKIN_LEN;
|
||||
memcpy(cell_out->create_cell.onionskin, cell->onionskin + 16,
|
||||
NTOR_ONIONSKIN_LEN);
|
||||
} else {
|
||||
cell_out->create_cell.cell_type = CELL_CREATE;
|
||||
cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
|
||||
cell_out->create_cell.handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN;
|
||||
memcpy(cell_out->create_cell.onionskin, cell->onionskin,
|
||||
TAP_ONIONSKIN_CHALLENGE_LEN);
|
||||
}
|
||||
memcpy(cell_out->node_id, cell->identity, DIGEST_LEN);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
create_cell_from_create2_cell_body(create_cell_t *cell_out,
|
||||
const create2_cell_body_t *cell)
|
||||
{
|
||||
tor_assert(cell_out);
|
||||
memset(cell_out, 0, sizeof(create_cell_t));
|
||||
if (BUG(cell->handshake_len > sizeof(cell_out->onionskin))) {
|
||||
/* This should be impossible because there just isn't enough room in the
|
||||
* input cell to make the handshake_len this large and provide a
|
||||
* handshake_data to match. */
|
||||
return -1;
|
||||
}
|
||||
|
||||
cell_out->cell_type = CELL_CREATE2;
|
||||
cell_out->handshake_type = cell->handshake_type;
|
||||
cell_out->handshake_len = cell->handshake_len;
|
||||
memcpy(cell_out->onionskin,
|
||||
create2_cell_body_getconstarray_handshake_data(cell),
|
||||
cell->handshake_len);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
extend_cell_from_extend2_cell_body(extend_cell_t *cell_out,
|
||||
const extend2_cell_body_t *cell)
|
||||
{
|
||||
tor_assert(cell_out);
|
||||
int found_ipv4 = 0, found_ipv6 = 0, found_rsa_id = 0, found_ed_id = 0;
|
||||
memset(cell_out, 0, sizeof(*cell_out));
|
||||
tor_addr_make_unspec(&cell_out->orport_ipv4.addr);
|
||||
tor_addr_make_unspec(&cell_out->orport_ipv6.addr);
|
||||
cell_out->cell_type = RELAY_COMMAND_EXTEND2;
|
||||
|
||||
unsigned i;
|
||||
for (i = 0; i < cell->n_spec; ++i) {
|
||||
const link_specifier_t *ls = extend2_cell_body_getconst_ls(cell, i);
|
||||
switch (ls->ls_type) {
|
||||
case LS_IPV4:
|
||||
if (found_ipv4)
|
||||
continue;
|
||||
found_ipv4 = 1;
|
||||
tor_addr_from_ipv4h(&cell_out->orport_ipv4.addr, ls->un_ipv4_addr);
|
||||
cell_out->orport_ipv4.port = ls->un_ipv4_port;
|
||||
break;
|
||||
case LS_IPV6:
|
||||
if (found_ipv6)
|
||||
continue;
|
||||
found_ipv6 = 1;
|
||||
tor_addr_from_ipv6_bytes(&cell_out->orport_ipv6.addr,
|
||||
(const char *)ls->un_ipv6_addr);
|
||||
cell_out->orport_ipv6.port = ls->un_ipv6_port;
|
||||
break;
|
||||
case LS_LEGACY_ID:
|
||||
if (found_rsa_id)
|
||||
return -1;
|
||||
found_rsa_id = 1;
|
||||
memcpy(cell_out->node_id, ls->un_legacy_id, 20);
|
||||
break;
|
||||
case LS_ED25519_ID:
|
||||
if (found_ed_id)
|
||||
return -1;
|
||||
found_ed_id = 1;
|
||||
memcpy(cell_out->ed_pubkey.pubkey, ls->un_ed25519_id, 32);
|
||||
break;
|
||||
default:
|
||||
/* Ignore this, whatever it is. */
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found_rsa_id || !found_ipv4) /* These are mandatory */
|
||||
return -1;
|
||||
|
||||
return create_cell_from_create2_cell_body(&cell_out->create_cell,
|
||||
cell->create2);
|
||||
}
|
||||
|
||||
/** Parse an EXTEND or EXTEND2 cell (according to <b>command</b>) from the
|
||||
* <b>payload_length</b> bytes of <b>payload</b> into <b>cell_out</b>. Return
|
||||
|
@ -886,101 +987,41 @@ int
|
|||
extend_cell_parse(extend_cell_t *cell_out, const uint8_t command,
|
||||
const uint8_t *payload, size_t payload_length)
|
||||
{
|
||||
const uint8_t *eop;
|
||||
|
||||
memset(cell_out, 0, sizeof(*cell_out));
|
||||
if (payload_length > RELAY_PAYLOAD_SIZE)
|
||||
return -1;
|
||||
eop = payload + payload_length;
|
||||
|
||||
switch (command) {
|
||||
case RELAY_COMMAND_EXTEND:
|
||||
{
|
||||
if (payload_length != 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN)
|
||||
extend1_cell_body_t *cell = NULL;
|
||||
if (extend1_cell_body_parse(&cell, payload, payload_length)<0 ||
|
||||
cell == NULL) {
|
||||
if (cell)
|
||||
extend1_cell_body_free(cell);
|
||||
return -1;
|
||||
|
||||
cell_out->cell_type = RELAY_COMMAND_EXTEND;
|
||||
tor_addr_from_ipv4n(&cell_out->orport_ipv4.addr, get_uint32(payload));
|
||||
cell_out->orport_ipv4.port = ntohs(get_uint16(payload+4));
|
||||
tor_addr_make_unspec(&cell_out->orport_ipv6.addr);
|
||||
if (tor_memeq(payload + 6, NTOR_CREATE_MAGIC, 16)) {
|
||||
cell_out->create_cell.cell_type = CELL_CREATE2;
|
||||
cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_NTOR;
|
||||
cell_out->create_cell.handshake_len = NTOR_ONIONSKIN_LEN;
|
||||
memcpy(cell_out->create_cell.onionskin, payload + 22,
|
||||
NTOR_ONIONSKIN_LEN);
|
||||
} else {
|
||||
cell_out->create_cell.cell_type = CELL_CREATE;
|
||||
cell_out->create_cell.handshake_type = ONION_HANDSHAKE_TYPE_TAP;
|
||||
cell_out->create_cell.handshake_len = TAP_ONIONSKIN_CHALLENGE_LEN;
|
||||
memcpy(cell_out->create_cell.onionskin, payload + 6,
|
||||
TAP_ONIONSKIN_CHALLENGE_LEN);
|
||||
}
|
||||
memcpy(cell_out->node_id, payload + 6 + TAP_ONIONSKIN_CHALLENGE_LEN,
|
||||
DIGEST_LEN);
|
||||
break;
|
||||
int r = extend_cell_from_extend1_cell_body(cell_out, cell);
|
||||
extend1_cell_body_free(cell);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
case RELAY_COMMAND_EXTEND2:
|
||||
{
|
||||
uint8_t n_specs, spectype, speclen;
|
||||
int i;
|
||||
int found_ipv4 = 0, found_ipv6 = 0, found_id = 0;
|
||||
tor_addr_make_unspec(&cell_out->orport_ipv4.addr);
|
||||
tor_addr_make_unspec(&cell_out->orport_ipv6.addr);
|
||||
|
||||
if (payload_length == 0)
|
||||
extend2_cell_body_t *cell = NULL;
|
||||
if (extend2_cell_body_parse(&cell, payload, payload_length) < 0 ||
|
||||
cell == NULL) {
|
||||
if (cell)
|
||||
extend2_cell_body_free(cell);
|
||||
return -1;
|
||||
|
||||
cell_out->cell_type = RELAY_COMMAND_EXTEND2;
|
||||
n_specs = *payload++;
|
||||
/* Parse the specifiers. We'll only take the first IPv4 and first IPv6
|
||||
* address, and the node ID, and ignore everything else */
|
||||
for (i = 0; i < n_specs; ++i) {
|
||||
if (eop - payload < 2)
|
||||
return -1;
|
||||
spectype = payload[0];
|
||||
speclen = payload[1];
|
||||
payload += 2;
|
||||
if (eop - payload < speclen)
|
||||
return -1;
|
||||
switch (spectype) {
|
||||
case SPECTYPE_IPV4:
|
||||
if (speclen != 6)
|
||||
return -1;
|
||||
if (!found_ipv4) {
|
||||
tor_addr_from_ipv4n(&cell_out->orport_ipv4.addr,
|
||||
get_uint32(payload));
|
||||
cell_out->orport_ipv4.port = ntohs(get_uint16(payload+4));
|
||||
found_ipv4 = 1;
|
||||
}
|
||||
break;
|
||||
case SPECTYPE_IPV6:
|
||||
if (speclen != 18)
|
||||
return -1;
|
||||
if (!found_ipv6) {
|
||||
tor_addr_from_ipv6_bytes(&cell_out->orport_ipv6.addr,
|
||||
(const char*)payload);
|
||||
cell_out->orport_ipv6.port = ntohs(get_uint16(payload+16));
|
||||
found_ipv6 = 1;
|
||||
}
|
||||
break;
|
||||
case SPECTYPE_LEGACY_ID:
|
||||
if (speclen != 20)
|
||||
return -1;
|
||||
if (found_id)
|
||||
return -1;
|
||||
memcpy(cell_out->node_id, payload, 20);
|
||||
found_id = 1;
|
||||
break;
|
||||
}
|
||||
payload += speclen;
|
||||
}
|
||||
if (!found_id || !found_ipv4)
|
||||
return -1;
|
||||
if (parse_create2_payload(&cell_out->create_cell,payload,eop-payload)<0)
|
||||
return -1;
|
||||
break;
|
||||
int r = extend_cell_from_extend2_cell_body(cell_out, cell);
|
||||
extend2_cell_body_free(cell);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
return -1;
|
||||
}
|
||||
|
@ -1137,12 +1178,11 @@ int
|
|||
extend_cell_format(uint8_t *command_out, uint16_t *len_out,
|
||||
uint8_t *payload_out, const extend_cell_t *cell_in)
|
||||
{
|
||||
uint8_t *p, *eop;
|
||||
uint8_t *p;
|
||||
if (check_extend_cell(cell_in) < 0)
|
||||
return -1;
|
||||
|
||||
p = payload_out;
|
||||
eop = payload_out + RELAY_PAYLOAD_SIZE;
|
||||
|
||||
memset(p, 0, RELAY_PAYLOAD_SIZE);
|
||||
|
||||
|
@ -1165,33 +1205,56 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out,
|
|||
break;
|
||||
case RELAY_COMMAND_EXTEND2:
|
||||
{
|
||||
uint8_t n = 2;
|
||||
uint8_t n_specifiers = 2;
|
||||
*command_out = RELAY_COMMAND_EXTEND2;
|
||||
extend2_cell_body_t *cell = extend2_cell_body_new();
|
||||
link_specifier_t *ls;
|
||||
{
|
||||
/* IPv4 specifier first. */
|
||||
ls = link_specifier_new();
|
||||
extend2_cell_body_add_ls(cell, ls);
|
||||
ls->ls_type = LS_IPV4;
|
||||
ls->ls_len = 6;
|
||||
ls->un_ipv4_addr = tor_addr_to_ipv4h(&cell_in->orport_ipv4.addr);
|
||||
ls->un_ipv4_port = cell_in->orport_ipv4.port;
|
||||
}
|
||||
{
|
||||
/* Then RSA id */
|
||||
ls = link_specifier_new();
|
||||
extend2_cell_body_add_ls(cell, ls);
|
||||
ls->ls_type = LS_LEGACY_ID;
|
||||
ls->ls_len = DIGEST_LEN;
|
||||
memcpy(ls->un_legacy_id, cell_in->node_id, DIGEST_LEN);
|
||||
}
|
||||
if (should_include_ed25519_id_extend_cells(NULL, get_options()) &&
|
||||
!ed25519_public_key_is_zero(&cell_in->ed_pubkey)) {
|
||||
/* Then, maybe, the ed25519 id! */
|
||||
++n_specifiers;
|
||||
ls = link_specifier_new();
|
||||
extend2_cell_body_add_ls(cell, ls);
|
||||
ls->ls_type = LS_ED25519_ID;
|
||||
ls->ls_len = 32;
|
||||
memcpy(ls->un_ed25519_id, cell_in->ed_pubkey.pubkey, 32);
|
||||
}
|
||||
cell->n_spec = n_specifiers;
|
||||
|
||||
*p++ = n; /* 2 identifiers */
|
||||
*p++ = SPECTYPE_IPV4; /* First is IPV4. */
|
||||
*p++ = 6; /* It's 6 bytes long. */
|
||||
set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr));
|
||||
set_uint16(p+4, htons(cell_in->orport_ipv4.port));
|
||||
p += 6;
|
||||
*p++ = SPECTYPE_LEGACY_ID; /* Next is an identity digest. */
|
||||
*p++ = 20; /* It's 20 bytes long */
|
||||
memcpy(p, cell_in->node_id, DIGEST_LEN);
|
||||
p += 20;
|
||||
|
||||
/* Now we can send the handshake */
|
||||
set_uint16(p, htons(cell_in->create_cell.handshake_type));
|
||||
set_uint16(p+2, htons(cell_in->create_cell.handshake_len));
|
||||
p += 4;
|
||||
|
||||
if (cell_in->create_cell.handshake_len > eop - p)
|
||||
return -1;
|
||||
|
||||
memcpy(p, cell_in->create_cell.onionskin,
|
||||
/* Now, the handshake */
|
||||
cell->create2 = create2_cell_body_new();
|
||||
cell->create2->handshake_type = cell_in->create_cell.handshake_type;
|
||||
cell->create2->handshake_len = cell_in->create_cell.handshake_len;
|
||||
create2_cell_body_setlen_handshake_data(cell->create2,
|
||||
cell_in->create_cell.handshake_len);
|
||||
memcpy(create2_cell_body_getarray_handshake_data(cell->create2),
|
||||
cell_in->create_cell.onionskin,
|
||||
cell_in->create_cell.handshake_len);
|
||||
|
||||
p += cell_in->create_cell.handshake_len;
|
||||
*len_out = p - payload_out;
|
||||
ssize_t len_encoded = extend2_cell_body_encode(
|
||||
payload_out, RELAY_PAYLOAD_SIZE,
|
||||
cell);
|
||||
extend2_cell_body_free(cell);
|
||||
if (len_encoded < 0 || len_encoded > UINT16_MAX)
|
||||
return -1;
|
||||
*len_out = (uint16_t) len_encoded;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
|
|
@ -85,6 +85,8 @@ typedef struct extend_cell_t {
|
|||
tor_addr_port_t orport_ipv6;
|
||||
/** Identity fingerprint of the node we're conecting to.*/
|
||||
uint8_t node_id[DIGEST_LEN];
|
||||
/** Ed25519 public identity key. Zero if not set. */
|
||||
ed25519_public_key_t ed_pubkey;
|
||||
/** The "create cell" embedded in this extend cell. Note that unlike the
|
||||
* create cells we generate ourself, this once can have a handshake type we
|
||||
* don't recognize. */
|
||||
|
|
Loading…
Reference in New Issue