From a696559d7844f9e81ae5f8f82ab6e2b8aa421e25 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 13:29:04 -0400 Subject: [PATCH 01/16] prop350: Stop accepting CREATE and EXTEND. --- src/core/or/command.c | 8 ++++++++ src/feature/relay/circuitbuild_relay.c | 6 ++++++ 2 files changed, 14 insertions(+) diff --git a/src/core/or/command.c b/src/core/or/command.c index cad7a173b6..c35400d7a1 100644 --- a/src/core/or/command.c +++ b/src/core/or/command.c @@ -331,6 +331,14 @@ command_process_create_cell(cell_t *cell, channel_t *chan) return; } + /* We no longer accept TAP, for any reason. */ + if (create_cell->handshake_type == ONION_HANDSHAKE_TYPE_TAP) { + tor_free(create_cell); + /* TODO: Should we collect statistics here? Should we log? */ + circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_TORPROTOCOL); + return; + } + /* Mark whether this circuit used TAP in case we need to use this * information for onion service statistics later on. */ if (create_cell->handshake_type == ONION_HANDSHAKE_TYPE_FAST || diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c index ce6cbe6df4..88b578c4a4 100644 --- a/src/feature/relay/circuitbuild_relay.c +++ b/src/feature/relay/circuitbuild_relay.c @@ -443,6 +443,12 @@ circuit_extend(struct cell_t *cell, struct circuit_t *circ) relay_header_unpack(&rh, cell->payload); + /* We no longer accept EXTEND messages; only EXTEND2. */ + if (rh.command == RELAY_COMMAND_EXTEND) { + /* TODO: Should we log this? */ + return -1; + } + if (extend_cell_parse(&ec, rh.command, cell->payload+RELAY_HEADER_SIZE, rh.length) < 0) { From f6f2d5c4a021d600d810086a795bf5b9f28e6a10 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 13:51:54 -0400 Subject: [PATCH 02/16] prop350: Remove all support for TAP, CREATE, and EXTEND. --- src/core/crypto/include.am | 2 - src/core/crypto/onion_crypto.c | 50 +------ src/core/crypto/onion_tap.c | 246 -------------------------------- src/core/crypto/onion_tap.h | 40 ------ src/core/or/circuitbuild.c | 1 - src/core/or/crypt_path_st.h | 1 - src/core/or/onion.c | 119 ++------------- src/feature/relay/onion_queue.c | 90 ++---------- src/test/bench.c | 71 --------- src/test/test.c | 211 +++------------------------ src/test/test_cell_formats.c | 127 ----------------- 11 files changed, 48 insertions(+), 910 deletions(-) delete mode 100644 src/core/crypto/onion_tap.c delete mode 100644 src/core/crypto/onion_tap.h diff --git a/src/core/crypto/include.am b/src/core/crypto/include.am index 2d53b3cb0b..651e8803d4 100644 --- a/src/core/crypto/include.am +++ b/src/core/crypto/include.am @@ -6,7 +6,6 @@ LIBTOR_APP_A_SOURCES += \ src/core/crypto/onion_fast.c \ src/core/crypto/onion_ntor.c \ src/core/crypto/onion_ntor_v3.c \ - src/core/crypto/onion_tap.c \ src/core/crypto/relay_crypto.c # ADD_C_FILE: INSERT HEADERS HERE. @@ -16,5 +15,4 @@ noinst_HEADERS += \ src/core/crypto/onion_fast.h \ src/core/crypto/onion_ntor.h \ src/core/crypto/onion_ntor_v3.h \ - src/core/crypto/onion_tap.h \ src/core/crypto/relay_crypto.h diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c index 0839d8903f..232dbcc5df 100644 --- a/src/core/crypto/onion_crypto.c +++ b/src/core/crypto/onion_crypto.c @@ -9,9 +9,9 @@ * \brief Functions to handle different kinds of circuit extension crypto. * * In this module, we provide a set of abstractions to create a uniform - * interface over the three circuit extension handshakes that Tor has used - * over the years (TAP, CREATE_FAST, and ntor). These handshakes are - * implemented in onion_tap.c, onion_fast.c, and onion_ntor.c respectively. + * interface over the circuit extension handshakes that Tor has used + * over the years (CREATE_FAST, ntor, hs_ntor, and ntorv3). + * These handshakes are implemented in the onion_*.c modules. * * All[*] of these handshakes follow a similar pattern: a client, knowing * some key from the relay it wants to extend through, generates the @@ -36,7 +36,6 @@ #include "core/crypto/onion_fast.h" #include "core/crypto/onion_ntor.h" #include "core/crypto/onion_ntor_v3.h" -#include "core/crypto/onion_tap.h" #include "feature/relay/router.h" #include "lib/crypt_ops/crypto_dh.h" #include "lib/crypt_ops/crypto_util.h" @@ -98,8 +97,6 @@ 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); @@ -139,18 +136,7 @@ onion_skin_create(int type, switch (type) { case ONION_HANDSHAKE_TYPE_TAP: - if (onion_skin_out_maxlen < TAP_ONIONSKIN_CHALLENGE_LEN) - return -1; - 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; + return -1; case ONION_HANDSHAKE_TYPE_FAST: if (fast_onionskin_create(&state_out->u.fast, onion_skin_out) < 0) return -1; @@ -288,18 +274,7 @@ onion_skin_server_handshake(int type, switch (type) { case ONION_HANDSHAKE_TYPE_TAP: - if (reply_out_maxlen < TAP_ONIONSKIN_REPLY_LEN) - return -1; - 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+DH1024_KEY_LEN, DIGEST_LEN); - break; + return -1; case ONION_HANDSHAKE_TYPE_FAST: if (reply_out_maxlen < CREATED_FAST_LEN) return -1; @@ -474,20 +449,7 @@ onion_skin_client_handshake(int type, switch (type) { case ONION_HANDSHAKE_TYPE_TAP: - if (reply_len != TAP_ONIONSKIN_REPLY_LEN) { - if (msg_out) - *msg_out = "TAP reply was not of the correct length."; - return -1; - } - if (onion_skin_TAP_client_handshake(handshake_state->u.tap, - (const char*)reply, - (char *)keys_out, keys_out_len, - msg_out) < 0) - return -1; - - memcpy(rend_authenticator_out, reply+DH1024_KEY_LEN, DIGEST_LEN); - - return 0; + return -1; case ONION_HANDSHAKE_TYPE_FAST: if (reply_len != CREATED_FAST_LEN) { if (msg_out) diff --git a/src/core/crypto/onion_tap.c b/src/core/crypto/onion_tap.c deleted file mode 100644 index 08ec3ec936..0000000000 --- a/src/core/crypto/onion_tap.c +++ /dev/null @@ -1,246 +0,0 @@ -/* Copyright (c) 2001 Matej Pfajfar. - * Copyright (c) 2001-2004, Roger Dingledine. - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file onion_tap.c - * \brief Functions to implement the original Tor circuit extension handshake - * (a.k.a TAP). - * - * The "TAP" handshake is the first one that was widely used in Tor: It - * combines RSA1024-OAEP and AES128-CTR to perform a hybrid encryption over - * the first message DH1024 key exchange. (The RSA-encrypted part of the - * encryption is authenticated; the AES-encrypted part isn't. This was - * not a smart choice.) - * - * We didn't call it "TAP" ourselves -- Ian Goldberg named it in "On the - * Security of the Tor Authentication Protocol". (Spoiler: it's secure, but - * its security is kind of fragile and implementation dependent. Never modify - * this implementation without reading and understanding that paper at least.) - * - * We have deprecated TAP since the ntor handshake came into general use. It - * is still used for hidden service IP and RP connections, however. - * - * This handshake, like the other circuit-extension handshakes, is - * invoked from onion.c. - **/ - -#include "core/or/or.h" -#include "app/config/config.h" -#include "lib/crypt_ops/crypto_dh.h" -#include "lib/crypt_ops/crypto_rand.h" -#include "lib/crypt_ops/crypto_util.h" -#include "core/crypto/onion_tap.h" -#include "feature/stats/rephist.h" - -/*----------------------------------------------------------------------*/ - -/** Given a router's 128 byte public key, - * stores the following in onion_skin_out: - * - [42 bytes] OAEP padding - * - [16 bytes] Symmetric key for encrypting blob past RSA - * - [70 bytes] g^x part 1 (inside the RSA) - * - [58 bytes] g^x part 2 (symmetrically encrypted) - * - * Stores the DH private key into handshake_state_out for later completion - * of the handshake. - * - * The meeting point/cookies and auth are zeroed out for now. - */ -int -onion_skin_TAP_create(crypto_pk_t *dest_router_key, - crypto_dh_t **handshake_state_out, - char *onion_skin_out) /* TAP_ONIONSKIN_CHALLENGE_LEN bytes */ -{ - char challenge[DH1024_KEY_LEN]; - crypto_dh_t *dh = NULL; - int dhbytes, pkbytes; - - tor_assert(dest_router_key); - tor_assert(handshake_state_out); - tor_assert(onion_skin_out); - *handshake_state_out = NULL; - memset(onion_skin_out, 0, TAP_ONIONSKIN_CHALLENGE_LEN); - - if (!(dh = crypto_dh_new(DH_TYPE_CIRCUIT))) - goto err; - - dhbytes = crypto_dh_get_bytes(dh); - pkbytes = (int) crypto_pk_keysize(dest_router_key); - tor_assert(dhbytes == 128); - tor_assert(pkbytes == 128); - - if (crypto_dh_get_public(dh, challenge, dhbytes)) - goto err; - - /* set meeting point, meeting cookie, etc here. Leave zero for now. */ - if (crypto_pk_obsolete_public_hybrid_encrypt(dest_router_key, onion_skin_out, - TAP_ONIONSKIN_CHALLENGE_LEN, - challenge, DH1024_KEY_LEN, - PK_PKCS1_OAEP_PADDING, 1)<0) - goto err; - - memwipe(challenge, 0, sizeof(challenge)); - *handshake_state_out = dh; - - return 0; - err: - /* LCOV_EXCL_START - * We only get here if RSA encryption fails or DH keygen fails. Those - * shouldn't be possible. */ - memwipe(challenge, 0, sizeof(challenge)); - if (dh) crypto_dh_free(dh); - return -1; - /* LCOV_EXCL_STOP */ -} - -/** Given an encrypted DH public key as generated by onion_skin_create, - * and the private key for this onion router, generate the reply (128-byte - * DH plus the first 20 bytes of shared key material), and store the - * next key_out_len bytes of key material in key_out. - */ -int -onion_skin_TAP_server_handshake( - /*TAP_ONIONSKIN_CHALLENGE_LEN*/ - const char *onion_skin, - crypto_pk_t *private_key, - crypto_pk_t *prev_private_key, - /*TAP_ONIONSKIN_REPLY_LEN*/ - char *handshake_reply_out, - char *key_out, - size_t key_out_len) -{ - char challenge[TAP_ONIONSKIN_CHALLENGE_LEN]; - crypto_dh_t *dh = NULL; - ssize_t len; - char *key_material=NULL; - size_t key_material_len=0; - int i; - crypto_pk_t *k; - - len = -1; - for (i=0;i<2;++i) { - k = i==0?private_key:prev_private_key; - if (!k) - break; - len = crypto_pk_obsolete_private_hybrid_decrypt(k, challenge, - TAP_ONIONSKIN_CHALLENGE_LEN, - onion_skin, - TAP_ONIONSKIN_CHALLENGE_LEN, - PK_PKCS1_OAEP_PADDING,0); - if (len>0) - break; - } - if (len<0) { - log_info(LD_PROTOCOL, - "Couldn't decrypt onionskin: client may be using old onion key"); - goto err; - } else if (len != DH1024_KEY_LEN) { - log_fn(LOG_PROTOCOL_WARN, LD_PROTOCOL, - "Unexpected onionskin length after decryption: %ld", - (long)len); - goto err; - } - - dh = crypto_dh_new(DH_TYPE_CIRCUIT); - if (!dh) { - /* LCOV_EXCL_START - * Failure to allocate a DH key should be impossible. - */ - log_warn(LD_BUG, "Couldn't allocate DH key"); - goto err; - /* LCOV_EXCL_STOP */ - } - if (crypto_dh_get_public(dh, handshake_reply_out, DH1024_KEY_LEN)) { - /* LCOV_EXCL_START - * This can only fail if the length of the key we just allocated is too - * big. That should be impossible. */ - log_info(LD_GENERAL, "crypto_dh_get_public failed."); - goto err; - /* LCOV_EXCL_STOP */ - } - - key_material_len = DIGEST_LEN+key_out_len; - key_material = tor_malloc(key_material_len); - len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, dh, challenge, - DH1024_KEY_LEN, key_material, - key_material_len); - if (len < 0) { - log_info(LD_GENERAL, "crypto_dh_compute_secret failed."); - goto err; - } - - /* send back H(K|0) as proof that we learned K. */ - memcpy(handshake_reply_out+DH1024_KEY_LEN, key_material, DIGEST_LEN); - - /* use the rest of the key material for our shared keys, digests, etc */ - memcpy(key_out, key_material+DIGEST_LEN, key_out_len); - - memwipe(challenge, 0, sizeof(challenge)); - memwipe(key_material, 0, key_material_len); - tor_free(key_material); - crypto_dh_free(dh); - return 0; - err: - memwipe(challenge, 0, sizeof(challenge)); - if (key_material) { - memwipe(key_material, 0, key_material_len); - tor_free(key_material); - } - if (dh) crypto_dh_free(dh); - - return -1; -} - -/** Finish the client side of the DH handshake. - * Given the 128 byte DH reply + 20 byte hash as generated by - * onion_skin_server_handshake and the handshake state generated by - * onion_skin_create, verify H(K) with the first 20 bytes of shared - * key material, then generate key_out_len more bytes of shared key - * material and store them in key_out. - * - * After the invocation, call crypto_dh_free on handshake_state. - */ -int -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, - const char **msg_out) -{ - ssize_t len; - char *key_material=NULL; - size_t key_material_len; - tor_assert(crypto_dh_get_bytes(handshake_state) == DH1024_KEY_LEN); - - key_material_len = DIGEST_LEN + key_out_len; - key_material = tor_malloc(key_material_len); - len = crypto_dh_compute_secret(LOG_PROTOCOL_WARN, handshake_state, - handshake_reply, DH1024_KEY_LEN, key_material, - key_material_len); - if (len < 0) { - if (msg_out) - *msg_out = "DH computation failed."; - goto err; - } - - if (tor_memneq(key_material, handshake_reply+DH1024_KEY_LEN, DIGEST_LEN)) { - /* H(K) does *not* match. Something fishy. */ - if (msg_out) - *msg_out = "Digest DOES NOT MATCH on onion handshake. Bug or attack."; - goto err; - } - - /* use the rest of the key material for our shared keys, digests, etc */ - memcpy(key_out, key_material+DIGEST_LEN, key_out_len); - - memwipe(key_material, 0, key_material_len); - tor_free(key_material); - return 0; - err: - memwipe(key_material, 0, key_material_len); - tor_free(key_material); - return -1; -} diff --git a/src/core/crypto/onion_tap.h b/src/core/crypto/onion_tap.h deleted file mode 100644 index 341270c981..0000000000 --- a/src/core/crypto/onion_tap.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (c) 2001 Matej Pfajfar. - * Copyright (c) 2001-2004, Roger Dingledine. - * Copyright (c) 2004-2006, Roger Dingledine, Nick Mathewson. - * Copyright (c) 2007-2021, The Tor Project, Inc. */ -/* See LICENSE for licensing information */ - -/** - * \file onion_tap.h - * \brief Header file for onion_tap.c. - **/ - -#ifndef TOR_ONION_TAP_H -#define TOR_ONION_TAP_H - -#define TAP_ONIONSKIN_CHALLENGE_LEN (PKCS1_OAEP_PADDING_OVERHEAD+\ - CIPHER_KEY_LEN+\ - DH1024_KEY_LEN) -#define TAP_ONIONSKIN_REPLY_LEN (DH1024_KEY_LEN+DIGEST_LEN) - -struct crypto_dh_t; -struct crypto_pk_t; - -int onion_skin_TAP_create(struct crypto_pk_t *router_key, - struct crypto_dh_t **handshake_state_out, - char *onion_skin_out); - -int onion_skin_TAP_server_handshake(const char *onion_skin, - struct crypto_pk_t *private_key, - struct crypto_pk_t *prev_private_key, - char *handshake_reply_out, - char *key_out, - size_t key_out_len); - -int onion_skin_TAP_client_handshake(struct crypto_dh_t *handshake_state, - const char *handshake_reply, - char *key_out, - size_t key_out_len, - const char **msg_out); - -#endif /* !defined(TOR_ONION_TAP_H) */ diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index 878436339b..d4dcdec417 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -33,7 +33,6 @@ #include "core/crypto/hs_ntor.h" #include "core/crypto/onion_crypto.h" #include "core/crypto/onion_fast.h" -#include "core/crypto/onion_tap.h" #include "core/mainloop/connection.h" #include "core/mainloop/mainloop.h" #include "core/or/channel.h" diff --git a/src/core/or/crypt_path_st.h b/src/core/or/crypt_path_st.h index fdc6b6fbb2..fc6391f2f8 100644 --- a/src/core/or/crypt_path_st.h +++ b/src/core/or/crypt_path_st.h @@ -26,7 +26,6 @@ struct onion_handshake_state_t { uint16_t tag; union { struct fast_handshake_state_t *fast; - struct crypto_dh_t *tap; struct ntor_handshake_state_t *ntor; struct ntor3_handshake_state_t *ntor3; } u; diff --git a/src/core/or/onion.c b/src/core/or/onion.c index 0bdd2a6d35..07c26a80e8 100644 --- a/src/core/or/onion.c +++ b/src/core/or/onion.c @@ -44,7 +44,6 @@ #include "core/crypto/onion_crypto.h" #include "core/crypto/onion_fast.h" #include "core/crypto/onion_ntor.h" -#include "core/crypto/onion_tap.h" #include "core/or/onion.h" #include "feature/nodelist/networkstatus.h" @@ -61,10 +60,7 @@ check_create_cell(const create_cell_t *cell, int unknown_ok) { switch (cell->cell_type) { case CELL_CREATE: - if (cell->handshake_type != ONION_HANDSHAKE_TYPE_TAP && - cell->handshake_type != ONION_HANDSHAKE_TYPE_NTOR) - return -1; - break; + return -1; case CELL_CREATE_FAST: if (cell->handshake_type != ONION_HANDSHAKE_TYPE_FAST) return -1; @@ -77,9 +73,7 @@ check_create_cell(const create_cell_t *cell, int unknown_ok) switch (cell->handshake_type) { case ONION_HANDSHAKE_TYPE_TAP: - if (cell->handshake_len != TAP_ONIONSKIN_CHALLENGE_LEN) - return -1; - break; + return -1; case ONION_HANDSHAKE_TYPE_FAST: if (cell->handshake_len != CREATE_FAST_LEN) return -1; @@ -160,14 +154,7 @@ create_cell_parse(create_cell_t *cell_out, const cell_t *cell_in) { switch (cell_in->command) { case CELL_CREATE: - if (tor_memeq(cell_in->payload, NTOR_CREATE_MAGIC, 16)) { - create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, - NTOR_ONIONSKIN_LEN, cell_in->payload+16); - } else { - create_cell_init(cell_out, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, - TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->payload); - } - break; + return -1; case CELL_CREATE_FAST: create_cell_init(cell_out, CELL_CREATE_FAST, ONION_HANDSHAKE_TYPE_FAST, CREATE_FAST_LEN, cell_in->payload); @@ -190,10 +177,7 @@ check_created_cell(const created_cell_t *cell) { switch (cell->cell_type) { case CELL_CREATED: - if (cell->handshake_len != TAP_ONIONSKIN_REPLY_LEN && - cell->handshake_len != NTOR_REPLY_LEN) - return -1; - break; + return -1; case CELL_CREATED_FAST: if (cell->handshake_len != CREATED_FAST_LEN) return -1; @@ -216,10 +200,7 @@ created_cell_parse(created_cell_t *cell_out, const cell_t *cell_in) switch (cell_in->command) { case CELL_CREATED: - cell_out->cell_type = CELL_CREATED; - cell_out->handshake_len = TAP_ONIONSKIN_REPLY_LEN; - memcpy(cell_out->reply, cell_in->payload, TAP_ONIONSKIN_REPLY_LEN); - break; + return -1; case CELL_CREATED_FAST: cell_out->cell_type = CELL_CREATED_FAST; cell_out->handshake_len = CREATED_FAST_LEN; @@ -260,52 +241,21 @@ check_extend_cell(const extend_cell_t *cell) } } if (cell->create_cell.cell_type == CELL_CREATE) { - if (cell->cell_type != RELAY_COMMAND_EXTEND) - return -1; + return -1; } else if (cell->create_cell.cell_type == CELL_CREATE2) { - if (cell->cell_type != RELAY_COMMAND_EXTEND2 && - cell->cell_type != RELAY_COMMAND_EXTEND) + if (cell->cell_type != RELAY_COMMAND_EXTEND2) return -1; } else { /* In particular, no CREATE_FAST cells are allowed */ return -1; } - if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST) + if (cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_FAST || + cell->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_TAP) return -1; return check_create_cell(&cell->create_cell, 1); } -static int -extend_cell_from_extend1_cell_body(extend_cell_t *cell_out, - const extend1_cell_body_t *cell) -{ - tor_assert(cell_out); - tor_assert(cell); - 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) @@ -408,19 +358,7 @@ extend_cell_parse,(extend_cell_t *cell_out, switch (command) { case RELAY_COMMAND_EXTEND: - { - 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; - } - int r = extend_cell_from_extend1_cell_body(cell_out, cell); - extend1_cell_body_free(cell); - if (r < 0) - return r; - } + return -1; break; case RELAY_COMMAND_EXTEND2: { @@ -479,13 +417,7 @@ extended_cell_parse(extended_cell_t *cell_out, switch (command) { case RELAY_COMMAND_EXTENDED: - if (payload_len != TAP_ONIONSKIN_REPLY_LEN) - return -1; - cell_out->cell_type = RELAY_COMMAND_EXTENDED; - cell_out->created_cell.cell_type = CELL_CREATED; - cell_out->created_cell.handshake_len = TAP_ONIONSKIN_REPLY_LEN; - memcpy(cell_out->created_cell.reply, payload, TAP_ONIONSKIN_REPLY_LEN); - break; + return -1; case RELAY_COMMAND_EXTENDED2: { cell_out->cell_type = RELAY_COMMAND_EXTENDED2; @@ -627,26 +559,7 @@ extend_cell_format(uint8_t *command_out, uint16_t *len_out, switch (cell_in->cell_type) { case RELAY_COMMAND_EXTEND: - { - if (BUG(cell_in->create_cell.handshake_type == - ONION_HANDSHAKE_TYPE_NTOR_V3)) { - log_warn(LD_BUG, "Extend cells cannot contain ntorv3!"); - return -1; - } - *command_out = RELAY_COMMAND_EXTEND; - *len_out = 6 + TAP_ONIONSKIN_CHALLENGE_LEN + DIGEST_LEN; - set_uint32(p, tor_addr_to_ipv4n(&cell_in->orport_ipv4.addr)); - set_uint16(p+4, htons(cell_in->orport_ipv4.port)); - if (cell_in->create_cell.handshake_type == ONION_HANDSHAKE_TYPE_NTOR) { - memcpy(p+6, NTOR_CREATE_MAGIC, 16); - memcpy(p+22, cell_in->create_cell.onionskin, NTOR_ONIONSKIN_LEN); - } else { - memcpy(p+6, cell_in->create_cell.onionskin, - TAP_ONIONSKIN_CHALLENGE_LEN); - } - memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, cell_in->node_id, DIGEST_LEN); - } - break; + return -1; case RELAY_COMMAND_EXTEND2: { uint8_t n_specifiers = 1; @@ -737,13 +650,7 @@ extended_cell_format(uint8_t *command_out, uint16_t *len_out, switch (cell_in->cell_type) { case RELAY_COMMAND_EXTENDED: - { - *command_out = RELAY_COMMAND_EXTENDED; - *len_out = TAP_ONIONSKIN_REPLY_LEN; - memcpy(payload_out, cell_in->created_cell.reply, - TAP_ONIONSKIN_REPLY_LEN); - } - break; + return -1; case RELAY_COMMAND_EXTENDED2: { *command_out = RELAY_COMMAND_EXTENDED2; diff --git a/src/feature/relay/onion_queue.c b/src/feature/relay/onion_queue.c index f3f4b169f4..9632b51063 100644 --- a/src/feature/relay/onion_queue.c +++ b/src/feature/relay/onion_queue.c @@ -50,10 +50,6 @@ #define ONION_QUEUE_MAX_DELAY_MIN 1 #define ONION_QUEUE_MAX_DELAY_MAX INT32_MAX -#define NUM_NTORS_PER_TAP_DEFAULT 10 -#define NUM_NTORS_PER_TAP_MIN 1 -#define NUM_NTORS_PER_TAP_MAX 100000 - /** 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 { @@ -84,17 +80,9 @@ static int ol_entries[MAX_QUEUE_IDX+1]; static void onion_queue_entry_remove(onion_queue_t *victim); /** Consensus parameters. */ -static int32_t ns_num_ntors_per_tap = NUM_NTORS_PER_TAP_DEFAULT; static time_t ns_onion_queue_wait_cutoff = ONION_QUEUE_WAIT_CUTOFF_DEFAULT; static uint32_t ns_onion_queue_max_delay = ONION_QUEUE_MAX_DELAY_DEFAULT; -/** Return the number of ntors per tap from the cached parameter. */ -static inline int32_t -get_num_ntors_per_tap(void) -{ - return ns_num_ntors_per_tap; -} - /** Return the onion queue wait cutoff value from the cached parameter. */ static inline time_t get_onion_queue_wait_cutoff(void) @@ -146,8 +134,12 @@ have_room_for_onionskin(uint16_t type) const or_options_t *options = get_options(); int num_cpus; uint64_t max_onion_queue_delay; - uint64_t tap_usec, ntor_usec; - uint64_t ntor_during_tap_usec, tap_during_ntor_usec; + uint64_t ntor_usec; + + /* We never allow TAP. */ + if (type == ONION_HANDSHAKE_TYPE_TAP) { + return 0; + } /* If we've got fewer than 50 entries, we always have room for one more. */ if (ol_entries[type] < 50) @@ -164,44 +156,15 @@ have_room_for_onionskin(uint16_t type) /* Compute how many microseconds we'd expect to need to clear all * onionskins in various combinations of the queues. */ - /* How long would it take to process all the TAP cells in the queue? */ - tap_usec = estimated_usec_for_onionskins( - ol_entries[ONION_HANDSHAKE_TYPE_TAP], - ONION_HANDSHAKE_TYPE_TAP) / num_cpus; - /* How long would it take to process all the NTor cells in the queue? */ ntor_usec = estimated_usec_for_onionskins( ol_entries[ONION_HANDSHAKE_TYPE_NTOR], ONION_HANDSHAKE_TYPE_NTOR) / num_cpus; - /* How long would it take to process the tap cells that we expect to - * process while draining the ntor queue? */ - tap_during_ntor_usec = estimated_usec_for_onionskins( - MIN(ol_entries[ONION_HANDSHAKE_TYPE_TAP], - ol_entries[ONION_HANDSHAKE_TYPE_NTOR] / get_num_ntors_per_tap()), - ONION_HANDSHAKE_TYPE_TAP) / num_cpus; - - /* How long would it take to process the ntor cells that we expect to - * process while draining the tap queue? */ - ntor_during_tap_usec = estimated_usec_for_onionskins( - MIN(ol_entries[ONION_HANDSHAKE_TYPE_NTOR], - ol_entries[ONION_HANDSHAKE_TYPE_TAP] * get_num_ntors_per_tap()), - ONION_HANDSHAKE_TYPE_NTOR) / num_cpus; - /* See whether that exceeds MaxOnionQueueDelay. If so, we can't queue * this. */ if (type == ONION_HANDSHAKE_TYPE_NTOR && - (ntor_usec + tap_during_ntor_usec) / 1000 > max_onion_queue_delay) - return 0; - - if (type == ONION_HANDSHAKE_TYPE_TAP && - (tap_usec + ntor_during_tap_usec) / 1000 > max_onion_queue_delay) - return 0; - - /* If we support the ntor handshake, then don't let TAP handshakes use - * more than 2/3 of the space on the queue. */ - if (type == ONION_HANDSHAKE_TYPE_TAP && - tap_usec / 1000 > max_onion_queue_delay * 2 / 3) + (ntor_usec / 1000) > max_onion_queue_delay) return 0; return 1; @@ -292,38 +255,7 @@ onion_pending_add(or_circuit_t *circ, create_cell_t *onionskin) static uint16_t decide_next_handshake_type(void) { - /* The number of times we've chosen ntor lately when both were available. */ - static int recently_chosen_ntors = 0; - - if (!ol_entries[ONION_HANDSHAKE_TYPE_NTOR]) - return ONION_HANDSHAKE_TYPE_TAP; /* no ntors? try tap */ - - if (!ol_entries[ONION_HANDSHAKE_TYPE_TAP]) { - - /* Nick wants us to prioritize new tap requests when there aren't - * any in the queue and we've processed k ntor cells since the last - * tap cell. This strategy is maybe a good idea, since it starves tap - * less in the case where tap is rare, or maybe a poor idea, since it - * makes the new tap cell unfairly jump in front of ntor cells that - * got here first. In any case this edge case will only become relevant - * once tap is rare. We should reevaluate whether we like this decision - * once tap gets more rare. */ - if (ol_entries[ONION_HANDSHAKE_TYPE_NTOR] && - recently_chosen_ntors <= get_num_ntors_per_tap()) - ++recently_chosen_ntors; - - return ONION_HANDSHAKE_TYPE_NTOR; /* no taps? try ntor */ - } - - /* They both have something queued. Pick ntor if we haven't done that - * too much lately. */ - if (++recently_chosen_ntors <= get_num_ntors_per_tap()) { - return ONION_HANDSHAKE_TYPE_NTOR; - } - - /* Else, it's time to let tap have its turn. */ - recently_chosen_ntors = 0; - return ONION_HANDSHAKE_TYPE_TAP; + return ONION_HANDSHAKE_TYPE_NTOR; } /** Remove the highest priority item from ol_list[] and return it, or @@ -445,10 +377,4 @@ onion_consensus_has_changed(const networkstatus_t *ns) ONION_QUEUE_WAIT_CUTOFF_DEFAULT, ONION_QUEUE_WAIT_CUTOFF_MIN, ONION_QUEUE_WAIT_CUTOFF_MAX); - - ns_num_ntors_per_tap = - networkstatus_get_param(ns, "NumNTorsPerTAP", - NUM_NTORS_PER_TAP_DEFAULT, - NUM_NTORS_PER_TAP_MIN, - NUM_NTORS_PER_TAP_MAX); } diff --git a/src/test/bench.c b/src/test/bench.c index a76e600cfa..044351b4be 100644 --- a/src/test/bench.c +++ b/src/test/bench.c @@ -11,7 +11,6 @@ #include "orconfig.h" #include "core/or/or.h" -#include "core/crypto/onion_tap.h" #include "core/crypto/relay_crypto.h" #include "lib/intmath/weakrng.h" @@ -126,75 +125,6 @@ bench_aes(void) crypto_cipher_free(c); } -static void -bench_onion_TAP(void) -{ - const int iters = 1<<9; - int i; - crypto_pk_t *key, *key2; - uint64_t start, end; - char os[TAP_ONIONSKIN_CHALLENGE_LEN]; - char or[TAP_ONIONSKIN_REPLY_LEN]; - crypto_dh_t *dh_out = NULL; - - key = crypto_pk_new(); - key2 = crypto_pk_new(); - if (crypto_pk_generate_key_with_bits(key, 1024) < 0) - goto done; - if (crypto_pk_generate_key_with_bits(key2, 1024) < 0) - goto done; - - reset_perftime(); - start = perftime(); - for (i = 0; i < iters; ++i) { - 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_TAP_create(key, &dh_out, os); - start = perftime(); - for (i = 0; i < iters; ++i) { - char key_out[CPATH_KEY_MATERIAL_LEN]; - 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", - NANOCOUNT(start, end, iters)/1e3); - - start = perftime(); - for (i = 0; i < iters; ++i) { - char key_out[CPATH_KEY_MATERIAL_LEN]; - 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", - NANOCOUNT(start, end, iters)/1e3); - - start = perftime(); - for (i = 0; i < iters; ++i) { - crypto_dh_t *dh; - char key_out[CPATH_KEY_MATERIAL_LEN]; - int s; - dh = crypto_dh_dup(dh_out); - s = onion_skin_TAP_client_handshake(dh, or, key_out, sizeof(key_out), - NULL); - crypto_dh_free(dh); - tor_assert(s == 0); - } - end = perftime(); - printf("Client-side, part 2: %f usec.\n", - NANOCOUNT(start, end, iters)/1e3); - - done: - crypto_dh_free(dh_out); - crypto_pk_free(key); - crypto_pk_free(key2); -} - static void bench_onion_ntor_impl(void) { @@ -754,7 +684,6 @@ static struct benchmark_t benchmarks[] = { ENT(siphash), ENT(digest), ENT(aes), - ENT(onion_TAP), ENT(onion_ntor), ENT(ed25519), ENT(rand), diff --git a/src/test/test.c b/src/test/test.c index 2030a8336e..317b570d8e 100644 --- a/src/test/test.c +++ b/src/test/test.c @@ -50,7 +50,6 @@ #include "core/or/onion.h" #include "core/crypto/onion_ntor.h" #include "core/crypto/onion_fast.h" -#include "core/crypto/onion_tap.h" #include "core/or/policies.h" #include "lib/sandbox/sandbox.h" #include "app/config/statefile.h" @@ -61,150 +60,6 @@ #include "core/or/or_circuit_st.h" #include "feature/relay/onion_queue.h" -/** Run unit tests for the onion handshake code. */ -static void -test_onion_handshake(void *arg) -{ - /* client-side */ - crypto_dh_t *c_dh = NULL; - char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; - char c_keys[40]; - /* server-side */ - char s_buf[TAP_ONIONSKIN_REPLY_LEN]; - char s_keys[40]; - int i; - /* shared */ - crypto_pk_t *pk = NULL, *pk2 = NULL; - - (void)arg; - pk = pk_generate(0); - pk2 = pk_generate(1); - - /* client handshake 1. */ - memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); - - for (i = 1; i <= 3; ++i) { - crypto_pk_t *k1, *k2; - if (i==1) { - /* server handshake: only one key known. */ - k1 = pk; k2 = NULL; - } else if (i==2) { - /* server handshake: try the right key first. */ - k1 = pk; k2 = pk2; - } else { - /* server handshake: try the right key second. */ - k1 = pk2; k2 = pk; - } - - memset(s_buf, 0, TAP_ONIONSKIN_REPLY_LEN); - memset(s_keys, 0, 40); - tt_assert(! onion_skin_TAP_server_handshake(c_buf, k1, k2, - s_buf, s_keys, 40)); - - /* client handshake 2 */ - memset(c_keys, 0, 40); - tt_assert(! onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, - 40, NULL)); - - tt_mem_op(c_keys,OP_EQ, s_keys, 40); - memset(s_buf, 0, 40); - tt_mem_op(c_keys,OP_NE, s_buf, 40); - } - done: - crypto_dh_free(c_dh); - crypto_pk_free(pk); - crypto_pk_free(pk2); -} - -static void -test_bad_onion_handshake(void *arg) -{ - char junk_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; - char junk_buf2[TAP_ONIONSKIN_CHALLENGE_LEN]; - /* client-side */ - crypto_dh_t *c_dh = NULL; - char c_buf[TAP_ONIONSKIN_CHALLENGE_LEN]; - char c_keys[40]; - /* server-side */ - char s_buf[TAP_ONIONSKIN_REPLY_LEN]; - char s_keys[40]; - /* shared */ - crypto_pk_t *pk = NULL, *pk2 = NULL; - - (void)arg; - - pk = pk_generate(0); - pk2 = pk_generate(1); - - /* Server: Case 1: the encrypted data is degenerate. */ - memset(junk_buf, 0, sizeof(junk_buf)); - crypto_pk_obsolete_public_hybrid_encrypt(pk, - junk_buf2, TAP_ONIONSKIN_CHALLENGE_LEN, - junk_buf, DH1024_KEY_LEN, - PK_PKCS1_OAEP_PADDING, 1); - tt_int_op(-1, OP_EQ, - onion_skin_TAP_server_handshake(junk_buf2, pk, NULL, - s_buf, s_keys, 40)); - - /* Server: Case 2: the encrypted data is not long enough. */ - memset(junk_buf, 0, sizeof(junk_buf)); - memset(junk_buf2, 0, sizeof(junk_buf2)); - crypto_pk_public_encrypt(pk, junk_buf2, sizeof(junk_buf2), - junk_buf, 48, PK_PKCS1_OAEP_PADDING); - tt_int_op(-1, OP_EQ, - onion_skin_TAP_server_handshake(junk_buf2, pk, NULL, - s_buf, s_keys, 40)); - - /* client handshake 1: do it straight. */ - memset(c_buf, 0, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_assert(! onion_skin_TAP_create(pk, &c_dh, c_buf)); - - /* Server: Case 3: we just don't have the right key. */ - tt_int_op(-1, OP_EQ, - onion_skin_TAP_server_handshake(c_buf, pk2, NULL, - s_buf, s_keys, 40)); - - /* Server: Case 4: The RSA-encrypted portion is corrupt. */ - c_buf[64] ^= 33; - tt_int_op(-1, OP_EQ, - onion_skin_TAP_server_handshake(c_buf, pk, NULL, - s_buf, s_keys, 40)); - c_buf[64] ^= 33; - - /* (Let the server proceed) */ - tt_int_op(0, OP_EQ, - onion_skin_TAP_server_handshake(c_buf, pk, NULL, - s_buf, s_keys, 40)); - - /* Client: Case 1: The server sent back junk. */ - const char *msg = NULL; - s_buf[64] ^= 33; - tt_int_op(-1, OP_EQ, - onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); - s_buf[64] ^= 33; - tt_str_op(msg, OP_EQ, "Digest DOES NOT MATCH on onion handshake. " - "Bug or attack."); - - /* Let the client finish; make sure it can. */ - msg = NULL; - tt_int_op(0, OP_EQ, - onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); - tt_mem_op(s_keys,OP_EQ, c_keys, 40); - tt_ptr_op(msg, OP_EQ, NULL); - - /* Client: Case 2: The server sent back a degenerate DH. */ - memset(s_buf, 0, sizeof(s_buf)); - tt_int_op(-1, OP_EQ, - onion_skin_TAP_client_handshake(c_dh, s_buf, c_keys, 40, &msg)); - tt_str_op(msg, OP_EQ, "DH computation failed."); - - done: - crypto_dh_free(c_dh); - crypto_pk_free(pk); - crypto_pk_free(pk2); -} - static void test_ntor_handshake(void *arg) { @@ -306,37 +161,35 @@ test_fast_handshake(void *arg) static void test_onion_queues(void *arg) { - uint8_t buf1[TAP_ONIONSKIN_CHALLENGE_LEN] = {0}; + uint8_t buf1[NTOR_ONIONSKIN_LEN] = {0}; uint8_t buf2[NTOR_ONIONSKIN_LEN] = {0}; or_circuit_t *circ1 = or_circuit_new(0, NULL); or_circuit_t *circ2 = or_circuit_new(0, NULL); - create_cell_t *onionskin = NULL, *create2_ptr; + create_cell_t *onionskin = NULL, *create1_ptr; create_cell_t *create1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create2 = tor_malloc_zero(sizeof(create_cell_t)); (void)arg; - create2_ptr = create2; /* remember, but do not free */ + create1_ptr = create1; /* remember, but do not free */ - create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, - TAP_ONIONSKIN_CHALLENGE_LEN, buf1); + create_cell_init(create1, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, + NTOR_ONIONSKIN_LEN, buf1); create_cell_init(create2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, buf2); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(0,OP_EQ, onion_pending_add(circ1, create1)); create1 = NULL; - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_int_op(0,OP_EQ, onion_pending_add(circ2, create2)); - create2 = NULL; tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_ptr_op(circ2,OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_ptr_op(onionskin, OP_EQ, create2_ptr); + tt_int_op(0,OP_EQ, onion_pending_add(circ2, create2)); + create2 = NULL; + tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + + tt_ptr_op(circ1,OP_EQ, onion_next_task(&onionskin)); + tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); + tt_ptr_op(onionskin, OP_EQ, create1_ptr); clear_pending_onions(); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); @@ -365,24 +218,19 @@ test_onion_queues(void *arg) static void test_onion_queue_order(void *arg) { - uint8_t buf_tap[TAP_ONIONSKIN_CHALLENGE_LEN] = {0}; uint8_t buf_ntor[NTOR_ONIONSKIN_LEN] = {0}; uint8_t buf_ntor3[CELL_PAYLOAD_SIZE] = {0}; - or_circuit_t *circ_tap = or_circuit_new(0, NULL); or_circuit_t *circ_ntor = or_circuit_new(0, NULL); or_circuit_t *circ_ntor3 = or_circuit_new(0, NULL); create_cell_t *onionskin = NULL; - create_cell_t *create_tap1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create_ntor1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create_ntor2 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create_v3ntor1 = tor_malloc_zero(sizeof(create_cell_t)); create_cell_t *create_v3ntor2 = tor_malloc_zero(sizeof(create_cell_t)); (void)arg; - create_cell_init(create_tap1, CELL_CREATE, ONION_HANDSHAKE_TYPE_TAP, - TAP_ONIONSKIN_CHALLENGE_LEN, buf_tap); create_cell_init(create_ntor1, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, NTOR_ONIONSKIN_LEN, buf_ntor); create_cell_init(create_ntor2, CELL_CREATE, ONION_HANDSHAKE_TYPE_NTOR, @@ -393,78 +241,63 @@ test_onion_queue_order(void *arg) NTOR_ONIONSKIN_LEN, buf_ntor3); /* sanity check queue init */ - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); - - /* Add tap first so we can ensure it comes out last */ - tt_int_op(0,OP_EQ, onion_pending_add(circ_tap, create_tap1)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); /* Now add interleaving ntor2 and ntor3, to ensure they share * the same queue and come out in this order */ tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor, create_ntor1)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor3, create_v3ntor1)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor, create_ntor2)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_int_op(0,OP_EQ, onion_pending_add(circ_ntor3, create_v3ntor2)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(4,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(4,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); /* Now remove 5 tasks, ensuring order and queue sizes */ tt_ptr_op(circ_ntor, OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(3,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_ptr_op(onionskin, OP_EQ, create_ntor1); tt_ptr_op(circ_ntor3, OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(2,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_ptr_op(onionskin, OP_EQ, create_v3ntor1); tt_ptr_op(circ_ntor, OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); + tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); tt_ptr_op(onionskin, OP_EQ, create_ntor2); tt_ptr_op(circ_ntor3, OP_EQ, onion_next_task(&onionskin)); - tt_int_op(1,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); - tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); - tt_ptr_op(onionskin, OP_EQ, create_v3ntor2); - - tt_ptr_op(circ_tap, OP_EQ, onion_next_task(&onionskin)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR_V3)); - tt_ptr_op(onionskin, OP_EQ, create_tap1); + tt_ptr_op(onionskin, OP_EQ, create_v3ntor2); clear_pending_onions(); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_TAP)); tt_int_op(0,OP_EQ, onion_num_pending(ONION_HANDSHAKE_TYPE_NTOR)); done: - circuit_free_(TO_CIRCUIT(circ_tap)); circuit_free_(TO_CIRCUIT(circ_ntor)); circuit_free_(TO_CIRCUIT(circ_ntor3)); - tor_free(create_tap1); tor_free(create_ntor1); tor_free(create_ntor2); tor_free(create_v3ntor1); @@ -740,8 +573,6 @@ test_circuit_timeout(void *arg) { #name, test_ ## name , TT_FORK, NULL, NULL } static struct testcase_t test_array[] = { - ENT(onion_handshake), - { "bad_onion_handshake", test_bad_onion_handshake, 0, NULL, NULL }, ENT(onion_queues), ENT(onion_queue_order), { "ntor_handshake", test_ntor_handshake, 0, NULL, NULL }, diff --git a/src/test/test_cell_formats.c b/src/test/test_cell_formats.c index b7b149cd66..e01a3461fc 100644 --- a/src/test/test_cell_formats.c +++ b/src/test/test_cell_formats.c @@ -14,7 +14,6 @@ #include "app/config/config.h" #include "lib/crypt_ops/crypto_rand.h" #include "core/or/onion.h" -#include "core/crypto/onion_tap.h" #include "core/crypto/onion_fast.h" #include "core/crypto/onion_ntor.h" #include "core/or/relay.h" @@ -399,21 +398,6 @@ test_cfmt_create_cells(void *arg) /* === Let's try parsing some good cells! */ - /* A valid create cell. */ - memset(&cell, 0, sizeof(cell)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); - cell.command = CELL_CREATE; - memcpy(cell.payload, b, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell)); - tt_int_op(CELL_CREATE, OP_EQ, cc.cell_type); - tt_int_op(ONION_HANDSHAKE_TYPE_TAP, OP_EQ, cc.handshake_type); - tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, OP_EQ, cc.handshake_len); - tt_mem_op(cc.onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); - tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc)); - tt_int_op(cell.command, OP_EQ, cell2.command); - tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A valid create_fast cell. */ memset(&cell, 0, sizeof(cell)); memset(b, 0, sizeof(b)); @@ -429,22 +413,6 @@ test_cfmt_create_cells(void *arg) tt_int_op(cell.command, OP_EQ, cell2.command); tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A valid create2 cell with a TAP payload */ - memset(&cell, 0, sizeof(cell)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); - cell.command = CELL_CREATE2; - memcpy(cell.payload, "\x00\x00\x00\xBA", 4); /* TAP, 186 bytes long */ - memcpy(cell.payload+4, b, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell)); - tt_int_op(CELL_CREATE2, OP_EQ, cc.cell_type); - tt_int_op(ONION_HANDSHAKE_TYPE_TAP, OP_EQ, cc.handshake_type); - tt_int_op(TAP_ONIONSKIN_CHALLENGE_LEN, OP_EQ, cc.handshake_len); - tt_mem_op(cc.onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN + 10); - tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc)); - tt_int_op(cell.command, OP_EQ, cell2.command); - tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A valid create2 cell with an ntor payload */ memset(&cell, 0, sizeof(cell)); memset(b, 0, sizeof(b)); @@ -461,22 +429,6 @@ test_cfmt_create_cells(void *arg) tt_int_op(cell.command, OP_EQ, cell2.command); tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A valid create cell with an ntor payload, in legacy format. */ - memset(&cell, 0, sizeof(cell)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, NTOR_ONIONSKIN_LEN); - cell.command = CELL_CREATE; - memcpy(cell.payload, "ntorNTORntorNTOR", 16); - memcpy(cell.payload+16, b, NTOR_ONIONSKIN_LEN); - tt_int_op(0, OP_EQ, create_cell_parse(&cc, &cell)); - tt_int_op(CELL_CREATE, OP_EQ, cc.cell_type); - tt_int_op(ONION_HANDSHAKE_TYPE_NTOR, OP_EQ, cc.handshake_type); - tt_int_op(NTOR_ONIONSKIN_LEN, OP_EQ, cc.handshake_len); - tt_mem_op(cc.onionskin,OP_EQ, b, NTOR_ONIONSKIN_LEN + 10); - tt_int_op(0, OP_EQ, create_cell_format(&cell2, &cc)); - tt_int_op(cell.command, OP_EQ, cell2.command); - tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* == Okay, now let's try to parse some impossible stuff. */ /* It has to be some kind of a create cell! */ @@ -517,20 +469,6 @@ test_cfmt_created_cells(void *arg) (void)arg; - /* A good CREATED cell */ - memset(&cell, 0, sizeof(cell)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN); - cell.command = CELL_CREATED; - memcpy(cell.payload, b, TAP_ONIONSKIN_REPLY_LEN); - tt_int_op(0, OP_EQ, created_cell_parse(&cc, &cell)); - tt_int_op(CELL_CREATED, OP_EQ, cc.cell_type); - tt_int_op(TAP_ONIONSKIN_REPLY_LEN, OP_EQ, cc.handshake_len); - tt_mem_op(cc.reply,OP_EQ, b, TAP_ONIONSKIN_REPLY_LEN + 10); - tt_int_op(0, OP_EQ, created_cell_format(&cell2, &cc)); - tt_int_op(cell.command, OP_EQ, cell2.command); - tt_mem_op(cell.payload,OP_EQ, cell2.payload, CELL_PAYLOAD_SIZE); - /* A good CREATED_FAST cell */ memset(&cell, 0, sizeof(cell)); memset(b, 0, sizeof(b)); @@ -606,54 +544,6 @@ test_cfmt_extend_cells(void *arg) (void) arg; - /* Let's start with a simple EXTEND cell. */ - memset(p, 0, sizeof(p)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_CHALLENGE_LEN); - memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */ - memcpy(p+6,b,TAP_ONIONSKIN_CHALLENGE_LEN); - memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20); - tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND, - p, 26+TAP_ONIONSKIN_CHALLENGE_LEN)); - tt_int_op(RELAY_COMMAND_EXTEND, OP_EQ, ec.cell_type); - tt_str_op("18.244.0.1", OP_EQ, fmt_addr(&ec.orport_ipv4.addr)); - tt_int_op(258, OP_EQ, ec.orport_ipv4.port); - tt_int_op(AF_UNSPEC, OP_EQ, tor_addr_family(&ec.orport_ipv6.addr)); - tt_mem_op(ec.node_id,OP_EQ, "electroencephalogram", 20); - tt_int_op(cc->cell_type, OP_EQ, CELL_CREATE); - tt_int_op(cc->handshake_type, OP_EQ, ONION_HANDSHAKE_TYPE_TAP); - tt_int_op(cc->handshake_len, OP_EQ, TAP_ONIONSKIN_CHALLENGE_LEN); - tt_mem_op(cc->onionskin,OP_EQ, b, TAP_ONIONSKIN_CHALLENGE_LEN+20); - tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); - tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND); - tt_int_op(p2_len, OP_EQ, 26+TAP_ONIONSKIN_CHALLENGE_LEN); - tt_mem_op(p2,OP_EQ, p, RELAY_PAYLOAD_SIZE); - - /* Let's do an ntor stuffed in a legacy EXTEND cell */ - memset(p, 0, sizeof(p)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, NTOR_ONIONSKIN_LEN); - memcpy(p, "\x12\xf4\x00\x01\x01\x02", 6); /* 18 244 0 1 : 258 */ - memcpy(p+6,"ntorNTORntorNTOR", 16); - memcpy(p+22, b, NTOR_ONIONSKIN_LEN); - memcpy(p+6+TAP_ONIONSKIN_CHALLENGE_LEN, "electroencephalogram", 20); - tt_int_op(0, OP_EQ, extend_cell_parse(&ec, RELAY_COMMAND_EXTEND, - p, 26+TAP_ONIONSKIN_CHALLENGE_LEN)); - tt_int_op(RELAY_COMMAND_EXTEND, OP_EQ, ec.cell_type); - tt_str_op("18.244.0.1", OP_EQ, fmt_addr(&ec.orport_ipv4.addr)); - tt_int_op(258, OP_EQ, ec.orport_ipv4.port); - tt_int_op(AF_UNSPEC, OP_EQ, tor_addr_family(&ec.orport_ipv6.addr)); - tt_mem_op(ec.node_id,OP_EQ, "electroencephalogram", 20); - tt_int_op(cc->cell_type, OP_EQ, CELL_CREATE2); - tt_int_op(cc->handshake_type, OP_EQ, ONION_HANDSHAKE_TYPE_NTOR); - tt_int_op(cc->handshake_len, OP_EQ, NTOR_ONIONSKIN_LEN); - tt_mem_op(cc->onionskin,OP_EQ, b, NTOR_ONIONSKIN_LEN+20); - tt_int_op(0, OP_EQ, extend_cell_format(&p2_cmd, &p2_len, p2, &ec)); - tt_int_op(p2_cmd, OP_EQ, RELAY_COMMAND_EXTEND); - tt_int_op(p2_len, OP_EQ, 26+TAP_ONIONSKIN_CHALLENGE_LEN); - tt_mem_op(p2,OP_EQ, p, RELAY_PAYLOAD_SIZE); - tt_int_op(0, OP_EQ, create_cell_format_relayed(&cell, cc)); - /* Now let's do a minimal ntor EXTEND2 cell. */ memset(&ec, 0xff, sizeof(ec)); memset(p, 0, sizeof(p)); @@ -896,23 +786,6 @@ test_cfmt_extended_cells(void *arg) (void) arg; - /* Try a regular EXTENDED cell. */ - memset(&ec, 0xff, sizeof(ec)); - memset(p, 0, sizeof(p)); - memset(b, 0, sizeof(b)); - crypto_rand((char*)b, TAP_ONIONSKIN_REPLY_LEN); - memcpy(p,b,TAP_ONIONSKIN_REPLY_LEN); - tt_int_op(0, OP_EQ, extended_cell_parse(&ec, RELAY_COMMAND_EXTENDED, p, - TAP_ONIONSKIN_REPLY_LEN)); - tt_int_op(RELAY_COMMAND_EXTENDED, OP_EQ, ec.cell_type); - tt_int_op(cc->cell_type, OP_EQ, CELL_CREATED); - tt_int_op(cc->handshake_len, OP_EQ, TAP_ONIONSKIN_REPLY_LEN); - tt_mem_op(cc->reply,OP_EQ, b, TAP_ONIONSKIN_REPLY_LEN); - tt_int_op(0, OP_EQ, extended_cell_format(&p2_cmd, &p2_len, p2, &ec)); - tt_int_op(RELAY_COMMAND_EXTENDED, OP_EQ, p2_cmd); - tt_int_op(TAP_ONIONSKIN_REPLY_LEN, OP_EQ, p2_len); - tt_mem_op(p2,OP_EQ, p, sizeof(p2)); - /* Try an EXTENDED2 cell */ memset(&ec, 0xff, sizeof(ec)); memset(p, 0, sizeof(p)); From f631145cbf2d0a8f1f170e206c38c77edfba8bad Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 13:54:26 -0400 Subject: [PATCH 03/16] Remove support for deciding to use CREATE/EXTEND/TAP. --- src/core/or/circuitbuild.c | 34 ++++++++++------------------------ 1 file changed, 10 insertions(+), 24 deletions(-) diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index d4dcdec417..bbfb247b1a 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -889,20 +889,14 @@ circuit_pick_create_handshake(uint8_t *cell_type_out, { /* torspec says: In general, clients SHOULD use CREATE whenever they are * using the TAP handshake, and CREATE2 otherwise. */ - if (extend_info_supports_ntor(ei)) { - *cell_type_out = CELL_CREATE2; - /* Only use ntor v3 with exits that support congestion control, - * and only when it is enabled. */ - if (ei->exit_supports_congestion_control && - congestion_control_enabled()) - *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR_V3; - else - *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR; - } else { - /* XXXX030 Remove support for deciding to use TAP and EXTEND. */ - *cell_type_out = CELL_CREATE; - *handshake_type_out = ONION_HANDSHAKE_TYPE_TAP; - } + *cell_type_out = CELL_CREATE2; + /* Only use ntor v3 with exits that support congestion control, + * and only when it is enabled. */ + if (ei->exit_supports_congestion_control && + congestion_control_enabled()) + *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR_V3; + else + *handshake_type_out = ONION_HANDSHAKE_TYPE_NTOR; } /** Decide whether to use a TAP or ntor handshake for extending to ei @@ -923,16 +917,8 @@ circuit_pick_extend_handshake(uint8_t *cell_type_out, uint8_t t; circuit_pick_create_handshake(&t, handshake_type_out, ei); - /* torspec says: Clients SHOULD use the EXTEND format whenever sending a TAP - * handshake... In other cases, clients SHOULD use EXTEND2. */ - if (*handshake_type_out != ONION_HANDSHAKE_TYPE_TAP) { - *cell_type_out = RELAY_COMMAND_EXTEND2; - *create_cell_type_out = CELL_CREATE2; - } else { - /* XXXX030 Remove support for deciding to use TAP and EXTEND. */ - *cell_type_out = RELAY_COMMAND_EXTEND; - *create_cell_type_out = CELL_CREATE; - } + *cell_type_out = RELAY_COMMAND_EXTEND2; + *create_cell_type_out = CELL_CREATE2; } /** From 07f0a2b964eedd1ced201f2d1d82ec0089fac371 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 14:04:04 -0400 Subject: [PATCH 04/16] Make onion-key body optional in microdescs Also, stop storing onion keys in microdesc_t. (In prop350, for microdescs, we are making the body optional; the "onion-key" entry is still mandatory, so that we can tell where microdescs begin.) --- src/feature/dirparse/microdesc_parse.c | 7 ++----- src/feature/dirparse/parsecommon.c | 13 ++++++++++++- src/feature/dirparse/parsecommon.h | 1 + src/feature/nodelist/microdesc.c | 2 -- src/feature/nodelist/microdesc_st.h | 8 -------- src/feature/nodelist/nodelist.c | 5 +---- 6 files changed, 16 insertions(+), 20 deletions(-) diff --git a/src/feature/dirparse/microdesc_parse.c b/src/feature/dirparse/microdesc_parse.c index beb38bda30..eef52f14f3 100644 --- a/src/feature/dirparse/microdesc_parse.c +++ b/src/feature/dirparse/microdesc_parse.c @@ -30,7 +30,7 @@ /** List of tokens recognized in microdescriptors */ // clang-format off static token_rule_t microdesc_token_table[] = { - T1_START("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024), + T1_START("onion-key", K_ONION_KEY, NO_ARGS, OPT_KEY_1024), T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ), T0N("id", K_ID, GE(2), NO_OBJ ), T0N("a", K_A, GE(1), NO_OBJ ), @@ -200,14 +200,11 @@ microdesc_parse_fields(microdesc_t *md, } tok = find_by_keyword(tokens, K_ONION_KEY); - if (!crypto_pk_public_exponent_ok(tok->key)) { + if (tok && tok->key && !crypto_pk_public_exponent_ok(tok->key)) { log_warn(LD_DIR, "Relay's onion key had invalid exponent."); goto err; } - md->onion_pkey = tor_memdup(tok->object_body, tok->object_size); - md->onion_pkey_len = tok->object_size; - crypto_pk_free(tok->key); if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) { curve25519_public_key_t k; diff --git a/src/feature/dirparse/parsecommon.c b/src/feature/dirparse/parsecommon.c index d7a6d65346..be1457b730 100644 --- a/src/feature/dirparse/parsecommon.c +++ b/src/feature/dirparse/parsecommon.c @@ -215,6 +215,16 @@ token_check_object(memarea_t *area, const char *kwd, RET_ERR(ebuf); } break; + case OPT_KEY_1024: + /* If there is anything, it must be a 1024-bit RSA key. */ + if (tok->object_body && !tok->key) { + tor_snprintf(ebuf, sizeof(ebuf), "Unexpected object for %s", kwd); + RET_ERR(ebuf); + } + if (!tok->key) { + break; + } + FALLTHROUGH; case NEED_KEY_1024: /* There must be a 1024-bit public key. */ if (tok->key && crypto_pk_num_bits(tok->key) != PK_BYTES*8) { tor_snprintf(ebuf, sizeof(ebuf), "Wrong size on key for %s: %d bits", @@ -395,7 +405,8 @@ get_next_token(memarea_t *area, } if (!strcmp(tok->object_type, "RSA PUBLIC KEY")) { /* If it's a public key */ - if (o_syn != NEED_KEY && o_syn != NEED_KEY_1024 && o_syn != OBJ_OK) { + if (o_syn != OPT_KEY_1024 && o_syn != NEED_KEY && + o_syn != NEED_KEY_1024 && o_syn != OBJ_OK) { RET_ERR("Unexpected public key."); } tok->key = crypto_pk_asn1_decode(tok->object_body, tok->object_size); diff --git a/src/feature/dirparse/parsecommon.h b/src/feature/dirparse/parsecommon.h index 9333ec4b27..d48d27499f 100644 --- a/src/feature/dirparse/parsecommon.h +++ b/src/feature/dirparse/parsecommon.h @@ -220,6 +220,7 @@ typedef struct directory_token_t { typedef enum { NO_OBJ, /**< No object, ever. */ NEED_OBJ, /**< Object is required. */ + OPT_KEY_1024, /**< If object is present, it must be a 1024 bit public key */ NEED_KEY_1024, /**< Object is required, and must be a 1024 bit public key */ NEED_KEY, /**< Object is required, and must be a public key. */ OBJ_OK, /**< Object is optional. */ diff --git a/src/feature/nodelist/microdesc.c b/src/feature/nodelist/microdesc.c index 9e5f0bb9a4..3fd0f23fb5 100644 --- a/src/feature/nodelist/microdesc.c +++ b/src/feature/nodelist/microdesc.c @@ -909,8 +909,6 @@ microdesc_free_(microdesc_t *md, const char *fname, int lineno) //tor_assert(md->held_in_map == 0); //tor_assert(md->held_by_nodes == 0); - if (md->onion_pkey) - tor_free(md->onion_pkey); tor_free(md->onion_curve25519_pkey); tor_free(md->ed25519_identity_pkey); if (md->body && md->saved_location != SAVED_IN_CACHE) diff --git a/src/feature/nodelist/microdesc_st.h b/src/feature/nodelist/microdesc_st.h index ad56b6d6c2..c642e6e12b 100644 --- a/src/feature/nodelist/microdesc_st.h +++ b/src/feature/nodelist/microdesc_st.h @@ -63,14 +63,6 @@ struct microdesc_t { /* Fields in the microdescriptor. */ - /** - * Public RSA TAP key for onions, ASN.1 encoded. We store this - * in its encoded format since storing it as a crypto_pk_t uses - * significantly more memory. */ - char *onion_pkey; - /** Length of onion_pkey, in bytes. */ - size_t onion_pkey_len; - /** As routerinfo_t.onion_curve25519_pkey */ struct curve25519_public_key_t *onion_curve25519_pkey; /** Ed25519 identity key, if included. */ diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c index bbaa51a407..09b10f10f6 100644 --- a/src/feature/nodelist/nodelist.c +++ b/src/feature/nodelist/nodelist.c @@ -2052,11 +2052,8 @@ node_get_rsa_onion_key(const node_t *node) if (node->ri) { onion_pkey = node->ri->onion_pkey; onion_pkey_len = node->ri->onion_pkey_len; - } else if (node->rs && node->md) { - onion_pkey = node->md->onion_pkey; - onion_pkey_len = node->md->onion_pkey_len; } else { - /* No descriptor or microdescriptor. */ + /* No descriptor; we don't take onion keys from microdescs. */ goto end; } pk = router_get_rsa_onion_pkey(onion_pkey, onion_pkey_len); From 0428aef13a4043d2181b52e62c019d5cb4710283 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 14:15:04 -0400 Subject: [PATCH 05/16] Remove TAP key from extend_info_t --- src/core/or/circuitbuild.c | 33 +------------------------- src/core/or/circuitbuild.h | 1 - src/core/or/circuituse.c | 2 +- src/core/or/extend_info_st.h | 2 -- src/core/or/extendinfo.c | 21 ---------------- src/core/or/extendinfo.h | 2 -- src/feature/client/bridges.c | 6 +++-- src/feature/hs/hs_common.c | 2 +- src/feature/relay/circuitbuild_relay.c | 1 - src/feature/relay/selftest.c | 6 ++--- src/test/test_circuitpadding.c | 2 +- src/test/test_conflux_pool.c | 2 +- src/test/test_hs_client.c | 8 +++---- 13 files changed, 15 insertions(+), 73 deletions(-) diff --git a/src/core/or/circuitbuild.c b/src/core/or/circuitbuild.c index bbfb247b1a..bcf44ca248 100644 --- a/src/core/or/circuitbuild.c +++ b/src/core/or/circuitbuild.c @@ -411,13 +411,6 @@ onion_populate_cpath(origin_circuit_t *circ) /* We would like every path to support ntor, but we have to allow for some * edge cases. */ tor_assert(circuit_get_cpath_len(circ)); - if (circuit_can_use_tap(circ)) { - /* Circuits from clients to intro points, and hidden services to rend - * points do not support ntor, because the hidden service protocol does - * not include ntor onion keys. This is also true for Single Onion - * Services. */ - return 0; - } if (circuit_get_cpath_len(circ) == 1) { /* Allow for bootstrapping: when we're fetching directly from a fallback, @@ -2626,29 +2619,6 @@ build_state_get_exit_nickname(cpath_build_state_t *state) return state->chosen_exit->nickname; } -/* Is circuit purpose allowed to use the deprecated TAP encryption protocol? - * The hidden service protocol still uses TAP for some connections, because - * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */ -static int -circuit_purpose_can_use_tap_impl(uint8_t purpose) -{ - return (purpose == CIRCUIT_PURPOSE_S_CONNECT_REND || - purpose == CIRCUIT_PURPOSE_C_INTRODUCING); -} - -/* Is circ allowed to use the deprecated TAP encryption protocol? - * The hidden service protocol still uses TAP for some connections, because - * ntor onion keys aren't included in HS descriptors or INTRODUCE cells. */ -int -circuit_can_use_tap(const origin_circuit_t *circ) -{ - tor_assert(circ); - tor_assert(circ->cpath); - tor_assert(circ->cpath->extend_info); - return (circuit_purpose_can_use_tap_impl(circ->base_.purpose) && - extend_info_supports_tap(circ->cpath->extend_info)); -} - /* Does circ have an onion key which it's allowed to use? */ int circuit_has_usable_onion_key(const origin_circuit_t *circ) @@ -2656,8 +2626,7 @@ circuit_has_usable_onion_key(const origin_circuit_t *circ) tor_assert(circ); tor_assert(circ->cpath); tor_assert(circ->cpath->extend_info); - return (extend_info_supports_ntor(circ->cpath->extend_info) || - circuit_can_use_tap(circ)); + return extend_info_supports_ntor(circ->cpath->extend_info); } /** Find the circuits that are waiting to find out whether their guards are diff --git a/src/core/or/circuitbuild.h b/src/core/or/circuitbuild.h index c76259fc29..ac3bf52135 100644 --- a/src/core/or/circuitbuild.h +++ b/src/core/or/circuitbuild.h @@ -48,7 +48,6 @@ MOCK_DECL(int, circuit_all_predicted_ports_handled, (time_t now, int circuit_append_new_exit(origin_circuit_t *circ, extend_info_t *info); int circuit_extend_to_new_exit(origin_circuit_t *circ, extend_info_t *info); -int circuit_can_use_tap(const origin_circuit_t *circ); int circuit_has_usable_onion_key(const origin_circuit_t *circ); const uint8_t *build_state_get_exit_rsa_id(cpath_build_state_t *state); MOCK_DECL(const node_t *, diff --git a/src/core/or/circuituse.c b/src/core/or/circuituse.c index ac9005e1d4..33886e9919 100644 --- a/src/core/or/circuituse.c +++ b/src/core/or/circuituse.c @@ -2473,7 +2473,7 @@ circuit_get_open_circ_or_launch(entry_connection_t *conn, extend_info = extend_info_new(conn->chosen_exit_name+1, digest, NULL, /* Ed25519 ID */ - NULL, NULL, /* onion keys */ + NULL, /* onion keys */ &addr, conn->socks_request->port, NULL, false); diff --git a/src/core/or/extend_info_st.h b/src/core/or/extend_info_st.h index 2ab0beb7e6..5f59bd2299 100644 --- a/src/core/or/extend_info_st.h +++ b/src/core/or/extend_info_st.h @@ -34,8 +34,6 @@ struct extend_info_t { /** IP/Port values for this hop's ORPort(s). Any unused values are set * to a null address. */ tor_addr_port_t orports[EXTEND_INFO_MAX_ADDRS]; - /** TAP onion key for this hop. */ - crypto_pk_t *onion_key; /** Ntor onion key for this hop. */ curve25519_public_key_t curve25519_onion_key; /** True if this hop is to be used as an _exit_, diff --git a/src/core/or/extendinfo.c b/src/core/or/extendinfo.c index ca623f09ce..b37d9831ed 100644 --- a/src/core/or/extendinfo.c +++ b/src/core/or/extendinfo.c @@ -33,7 +33,6 @@ extend_info_t * extend_info_new(const char *nickname, const char *rsa_id_digest, const ed25519_public_key_t *ed_id, - crypto_pk_t *onion_key, const curve25519_public_key_t *ntor_key, const tor_addr_t *addr, uint16_t port, const protover_summary_flags_t *pv, @@ -46,8 +45,6 @@ extend_info_new(const char *nickname, memcpy(&info->ed_identity, ed_id, sizeof(ed25519_public_key_t)); if (nickname) strlcpy(info->nickname, nickname, sizeof(info->nickname)); - if (onion_key) - info->onion_key = crypto_pk_dup_key(onion_key); if (ntor_key) memcpy(&info->curve25519_onion_key, ntor_key, sizeof(curve25519_public_key_t)); @@ -149,13 +146,11 @@ extend_info_from_node(const node_t *node, int for_direct_connect, /* Retrieve the curve25519 pubkey. */ const curve25519_public_key_t *curve_pubkey = node_get_curve25519_onion_key(node); - rsa_pubkey = node_get_rsa_onion_key(node); if (valid_addr && node->ri) { info = extend_info_new(node->ri->nickname, node->identity, ed_pubkey, - rsa_pubkey, curve_pubkey, &ap.addr, ap.port, @@ -165,7 +160,6 @@ extend_info_from_node(const node_t *node, int for_direct_connect, info = extend_info_new(node->rs->nickname, node->identity, ed_pubkey, - rsa_pubkey, curve_pubkey, &ap.addr, ap.port, @@ -173,7 +167,6 @@ extend_info_from_node(const node_t *node, int for_direct_connect, for_exit); } - crypto_pk_free(rsa_pubkey); return info; } @@ -183,7 +176,6 @@ extend_info_free_(extend_info_t *info) { if (!info) return; - crypto_pk_free(info->onion_key); tor_free(info); } @@ -196,22 +188,9 @@ extend_info_dup(extend_info_t *info) tor_assert(info); newinfo = tor_malloc(sizeof(extend_info_t)); memcpy(newinfo, info, sizeof(extend_info_t)); - if (info->onion_key) - newinfo->onion_key = crypto_pk_dup_key(info->onion_key); - else - newinfo->onion_key = NULL; return newinfo; } -/* Does ei have a valid TAP key? */ -int -extend_info_supports_tap(const extend_info_t* ei) -{ - tor_assert(ei); - /* Valid TAP keys are not NULL */ - return ei->onion_key != NULL; -} - /* Does ei have a valid ntor key? */ int extend_info_supports_ntor(const extend_info_t* ei) diff --git a/src/core/or/extendinfo.h b/src/core/or/extendinfo.h index 6d1f20597b..3419a4e043 100644 --- a/src/core/or/extendinfo.h +++ b/src/core/or/extendinfo.h @@ -15,7 +15,6 @@ extend_info_t *extend_info_new(const char *nickname, const char *rsa_id_digest, const struct ed25519_public_key_t *ed_id, - crypto_pk_t *onion_key, const struct curve25519_public_key_t *ntor_key, const tor_addr_t *addr, uint16_t port, const struct protover_summary_flags_t *pv, @@ -27,7 +26,6 @@ void extend_info_free_(extend_info_t *info); #define extend_info_free(info) \ FREE_AND_NULL(extend_info_t, extend_info_free_, (info)) int extend_info_addr_is_allowed(const tor_addr_t *addr); -int extend_info_supports_tap(const extend_info_t* ei); int extend_info_supports_ntor(const extend_info_t* ei); int extend_info_supports_ntor_v3(const extend_info_t *ei); int extend_info_has_preferred_onion_key(const extend_info_t* ei); diff --git a/src/feature/client/bridges.c b/src/feature/client/bridges.c index a0375828a7..f4f7ac23a3 100644 --- a/src/feature/client/bridges.c +++ b/src/feature/client/bridges.c @@ -316,7 +316,8 @@ addr_is_a_configured_bridge(const tor_addr_t *addr, /** If we have a bridge configured whose digest matches * ei->identity_digest, or a bridge with no known digest whose address * matches ei->addr:ei->port, return 1. Else return 0. - * If ei->onion_key is NULL, check for address/port matches only. + * If ei has no onion key configured, check for address/port matches + * only. * * Note that if the extend_info_t contains multiple addresses, we return true * only if _every_ address is a bridge. @@ -324,7 +325,8 @@ addr_is_a_configured_bridge(const tor_addr_t *addr, int extend_info_is_a_configured_bridge(const extend_info_t *ei) { - const char *digest = ei->onion_key ? ei->identity_digest : NULL; + const char *digest = curve25519_public_key_is_ok(&ei->curve25519_onion_key) + ? ei->identity_digest : NULL; const tor_addr_port_t *ap1 = NULL, *ap2 = NULL; if (! tor_addr_is_null(&ei->orports[0].addr)) ap1 = &ei->orports[0]; diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c index cd7e4890d1..e16ec89ccb 100644 --- a/src/feature/hs/hs_common.c +++ b/src/feature/hs/hs_common.c @@ -1686,7 +1686,7 @@ hs_get_extend_info_from_lspecs(const smartlist_t *lspecs, /* We do have everything for which we think we can connect successfully. */ info = extend_info_new(NULL, legacy_id, - (have_ed25519_id) ? &ed25519_pk : NULL, NULL, + (have_ed25519_id) ? &ed25519_pk : NULL, onion_key, &ap.addr, ap.port, NULL, false); done: return info; diff --git a/src/feature/relay/circuitbuild_relay.c b/src/feature/relay/circuitbuild_relay.c index 88b578c4a4..5ece5b4adc 100644 --- a/src/feature/relay/circuitbuild_relay.c +++ b/src/feature/relay/circuitbuild_relay.c @@ -389,7 +389,6 @@ circuit_open_connection_for_extend(const struct extend_cell_t *ec, circ->n_hop = extend_info_new(NULL /*nickname*/, (const char*)ec->node_id, &ec->ed_pubkey, - NULL, /*onion_key*/ NULL, /*curve25519_key*/ &chosen_ap->addr, chosen_ap->port, diff --git a/src/feature/relay/selftest.c b/src/feature/relay/selftest.c index 399b6bca6e..0a80a5d47e 100644 --- a/src/feature/relay/selftest.c +++ b/src/feature/relay/selftest.c @@ -201,7 +201,6 @@ have_orport_for_family(int family) static extend_info_t * extend_info_from_router(const routerinfo_t *r, int family) { - crypto_pk_t *rsa_pubkey; extend_info_t *info; tor_addr_port_t ap; @@ -224,15 +223,14 @@ extend_info_from_router(const routerinfo_t *r, int family) /* We don't have an ORPort for the requested family. */ return NULL; } - rsa_pubkey = router_get_rsa_onion_pkey(r->onion_pkey, r->onion_pkey_len); info = extend_info_new(r->nickname, r->cache_info.identity_digest, ed_id_key, - rsa_pubkey, r->onion_curve25519_pkey, + r->onion_curve25519_pkey, &ap.addr, ap.port, /* TODO-324: Should self-test circuits use * congestion control? */ NULL, false); - crypto_pk_free(rsa_pubkey); + return info; } diff --git a/src/test/test_circuitpadding.c b/src/test/test_circuitpadding.c index 63b7136a11..95401465c1 100644 --- a/src/test/test_circuitpadding.c +++ b/src/test/test_circuitpadding.c @@ -1608,7 +1608,7 @@ simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay, hop->extend_info = extend_info_new( padding ? "padding" : "non-padding", - digest, NULL, NULL, NULL, + digest, NULL, NULL, &addr, padding, NULL, false); cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0); diff --git a/src/test/test_conflux_pool.c b/src/test/test_conflux_pool.c index 05dc7b14ff..6fe3c8b65b 100644 --- a/src/test/test_conflux_pool.c +++ b/src/test/test_conflux_pool.c @@ -349,7 +349,7 @@ simulate_single_hop_extend(origin_circuit_t *client, int exit) hop->extend_info = extend_info_new( exit ? "exit" : "non-exit", - digest, NULL, NULL, NULL, + digest, NULL, NULL, &addr, exit, NULL, exit); cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0); diff --git a/src/test/test_hs_client.c b/src/test/test_hs_client.c index a02dca1b60..ac6f940cc7 100644 --- a/src/test/test_hs_client.c +++ b/src/test/test_hs_client.c @@ -1192,7 +1192,7 @@ test_socks_hs_errors(void *arg) ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, - NULL, NULL, NULL, &addr, + NULL, NULL, &addr, 4242, NULL, false); /* Attach socks connection to this rendezvous circuit. */ ocirc->p_streams = ENTRY_TO_EDGE_CONN(socks_conn); @@ -1287,7 +1287,7 @@ test_close_intro_circuit_failure(void *arg) ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, - NULL, NULL, NULL, &addr, + NULL, NULL, &addr, 4242, NULL, false); ed25519_pubkey_copy(ô->hs_ident->intro_auth_pk, &intro_kp.pubkey); @@ -1314,7 +1314,7 @@ test_close_intro_circuit_failure(void *arg) ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, - NULL, NULL, NULL, &addr, + NULL, NULL, &addr, 4242, NULL, false); ed25519_pubkey_copy(ô->hs_ident->intro_auth_pk, &intro_kp.pubkey); @@ -1337,7 +1337,7 @@ test_close_intro_circuit_failure(void *arg) ocirc->build_state = tor_malloc_zero(sizeof(cpath_build_state_t)); /* Code path will log this exit so build it. */ ocirc->build_state->chosen_exit = extend_info_new("TestNickname", digest, - NULL, NULL, NULL, &addr, + NULL, NULL, &addr, 4242, NULL, false); ed25519_pubkey_copy(ô->hs_ident->intro_auth_pk, &intro_kp.pubkey); From cbbfb812a8eca6587ea2af12693d5c2357146f57 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 14:16:11 -0400 Subject: [PATCH 06/16] Remove node_get_rsa_onion_key --- src/feature/nodelist/nodelist.c | 28 ---------------------------- src/feature/nodelist/nodelist.h | 1 - 2 files changed, 29 deletions(-) diff --git a/src/feature/nodelist/nodelist.c b/src/feature/nodelist/nodelist.c index 09b10f10f6..735361d417 100644 --- a/src/feature/nodelist/nodelist.c +++ b/src/feature/nodelist/nodelist.c @@ -2034,34 +2034,6 @@ node_get_curve25519_onion_key(const node_t *node) return NULL; } -/* Return a newly allocacted RSA onion public key taken from the given node. - * - * Return NULL if node is NULL or no RSA onion public key can be found. It is - * the caller responsibility to free the returned object. */ -crypto_pk_t * -node_get_rsa_onion_key(const node_t *node) -{ - crypto_pk_t *pk = NULL; - const char *onion_pkey; - size_t onion_pkey_len; - - if (!node) { - goto end; - } - - if (node->ri) { - onion_pkey = node->ri->onion_pkey; - onion_pkey_len = node->ri->onion_pkey_len; - } else { - /* No descriptor; we don't take onion keys from microdescs. */ - goto end; - } - pk = router_get_rsa_onion_pkey(onion_pkey, onion_pkey_len); - - end: - return pk; -} - /** Refresh the country code of ri. This function MUST be called on * each router when the GeoIP database is reloaded, and on all new routers. */ void diff --git a/src/feature/nodelist/nodelist.h b/src/feature/nodelist/nodelist.h index 3d5ad9c0ea..948a293f0c 100644 --- a/src/feature/nodelist/nodelist.h +++ b/src/feature/nodelist/nodelist.h @@ -109,7 +109,6 @@ void node_get_pref_ipv6_dirport(const node_t *node, tor_addr_port_t *ap_out); int node_has_curve25519_onion_key(const node_t *node); const struct curve25519_public_key_t *node_get_curve25519_onion_key( const node_t *node); -crypto_pk_t *node_get_rsa_onion_key(const node_t *node); MOCK_DECL(const smartlist_t *, nodelist_get_list, (void)); From 4cdf56a17376a09612d741054efd11a3016d578c Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 14:30:32 -0400 Subject: [PATCH 07/16] Rename "onion_pkey" fields in routerinfo_t, and make them optional. (Renaming them has forced me to look at every place where they are used, so I can make sure that they are really optional now.) --- src/feature/dirauth/dirvote.c | 8 ++++++-- src/feature/dirparse/routerparse.c | 12 ++++++++---- src/feature/nodelist/routerinfo_st.h | 9 ++++++--- src/feature/nodelist/routerlist.c | 25 +++++++++++++++++++++---- src/feature/relay/router.c | 27 +++++++++++++++------------ src/test/test_dir.c | 20 +++++++++++--------- src/test/test_hs_service.c | 2 -- src/test/test_router.c | 4 ++-- 8 files changed, 69 insertions(+), 38 deletions(-) diff --git a/src/feature/dirauth/dirvote.c b/src/feature/dirauth/dirvote.c index f8290cde6d..1386d75e0f 100644 --- a/src/feature/dirauth/dirvote.c +++ b/src/feature/dirauth/dirvote.c @@ -3870,8 +3870,12 @@ dirvote_create_microdescriptor(const routerinfo_t *ri, int consensus_method) size_t keylen; smartlist_t *chunks = smartlist_new(); char *output = NULL; - crypto_pk_t *rsa_pubkey = router_get_rsa_onion_pkey(ri->onion_pkey, - ri->onion_pkey_len); + crypto_pk_t *rsa_pubkey = router_get_rsa_onion_pkey(ri->tap_onion_pkey, + ri->tap_onion_pkey_len); + if (!rsa_pubkey) { + /* We do not yet support creating MDs for relays without TAP onion keys. */ + goto done; + } if (crypto_pk_write_public_key_to_string(rsa_pubkey, &key, &keylen)<0) goto done; diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c index 844057c47e..47f6803fcd 100644 --- a/src/feature/dirparse/routerparse.c +++ b/src/feature/dirparse/routerparse.c @@ -601,8 +601,8 @@ router_parse_entry_from_string(const char *s, const char *end, "Relay's onion key had invalid exponent."); goto err; } - router->onion_pkey = tor_memdup(tok->object_body, tok->object_size); - router->onion_pkey_len = tok->object_size; + router->tap_onion_pkey = tor_memdup(tok->object_body, tok->object_size); + router->tap_onion_pkey_len = tok->object_size; crypto_pk_free(tok->key); if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) { @@ -776,8 +776,12 @@ router_parse_entry_from_string(const char *s, const char *end, goto err; } - rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey, - router->onion_pkey_len); + rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey, + router->tap_onion_pkey_len); + if (rsa_pubkey == NULL) { + log_warn(LD_DIR, "No pubkey for TAP cross-verification."); + goto err; + } if (check_tap_onion_key_crosscert( (const uint8_t*)cc_tap_tok->object_body, (int)cc_tap_tok->object_size, diff --git a/src/feature/nodelist/routerinfo_st.h b/src/feature/nodelist/routerinfo_st.h index 50134b2b96..a5c00c85c5 100644 --- a/src/feature/nodelist/routerinfo_st.h +++ b/src/feature/nodelist/routerinfo_st.h @@ -33,10 +33,13 @@ struct routerinfo_t { /** * Public RSA TAP key for onions, ASN.1 encoded. We store this * in its encoded format since storing it as a crypto_pk_t uses - * significantly more memory. */ - char *onion_pkey; + * significantly more memory. + * + * This may be absent. + */ + char *tap_onion_pkey; /** Length of onion_pkey, in bytes. */ - size_t onion_pkey_len; + size_t tap_onion_pkey_len; crypto_pk_t *identity_pkey; /**< Public RSA key for signing. */ /** Public curve25519 key for onions */ diff --git a/src/feature/nodelist/routerlist.c b/src/feature/nodelist/routerlist.c index 63de68dda7..7904f7d032 100644 --- a/src/feature/nodelist/routerlist.c +++ b/src/feature/nodelist/routerlist.c @@ -930,8 +930,8 @@ routerinfo_free_(routerinfo_t *router) tor_free(router->platform); tor_free(router->protocol_list); tor_free(router->contact_info); - if (router->onion_pkey) - tor_free(router->onion_pkey); + if (router->tap_onion_pkey) + tor_free(router->tap_onion_pkey); tor_free(router->onion_curve25519_pkey); if (router->identity_pkey) crypto_pk_free(router->identity_pkey); @@ -2957,6 +2957,24 @@ router_reset_descriptor_download_failures(void) /** We allow uptime to vary from how much it ought to be by this much. */ #define ROUTER_ALLOW_UPTIME_DRIFT (6*60*60) +/** Return true iff r1 and r2 have the same TAP onion keys. */ +static int +router_tap_onion_keys_eq(const routerinfo_t *r1, const routerinfo_t *r2) +{ + if (r1->tap_onion_pkey_len != r2->tap_onion_pkey_len) + return 0; + + if ((r1->tap_onion_pkey == NULL) && (r2->tap_onion_pkey == NULL)) { + return 1; + } else if ((r1->tap_onion_pkey != NULL) && (r2->tap_onion_pkey != NULL)) { + return tor_memeq(r1->tap_onion_pkey, r2->tap_onion_pkey, + r1->tap_onion_pkey_len); + } else { + /* One is NULL; one is not. */ + return 0; + } +} + /** Return true iff the only differences between r1 and r2 are such that * would not cause a recent (post 0.1.1.6) dirserver to republish. */ @@ -2982,8 +3000,7 @@ router_differences_are_cosmetic(const routerinfo_t *r1, const routerinfo_t *r2) r1->ipv6_orport != r2->ipv6_orport || r1->ipv4_dirport != r2->ipv4_dirport || r1->purpose != r2->purpose || - r1->onion_pkey_len != r2->onion_pkey_len || - !tor_memeq(r1->onion_pkey, r2->onion_pkey, r1->onion_pkey_len) || + !router_tap_onion_keys_eq(r1,r2) || !crypto_pk_eq_keys(r1->identity_pkey, r2->identity_pkey) || strcasecmp(r1->platform, r2->platform) || (r1->contact_info && !r2->contact_info) || /* contact_info is optional */ diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 1ed9630e09..1a29b54494 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -2139,8 +2139,8 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out)) directory_permits_begindir_requests(options); ri->cache_info.published_on = time(NULL); /* get_onion_key() must invoke from main thread */ - router_set_rsa_onion_pkey(get_onion_key(), &ri->onion_pkey, - &ri->onion_pkey_len); + router_set_rsa_onion_pkey(get_onion_key(), &ri->tap_onion_pkey, + &ri->tap_onion_pkey_len); ri->onion_curve25519_pkey = tor_memdup(&get_current_curve25519_keypair()->pubkey, @@ -2777,7 +2777,7 @@ router_dump_router_to_string(routerinfo_t *router, char published[ISO_TIME_LEN+1]; char fingerprint[FINGERPRINT_LEN+1]; char *extra_info_line = NULL; - size_t onion_pkeylen, identity_pkeylen; + size_t onion_pkeylen=0, identity_pkeylen; char *family_line = NULL; char *extra_or_address = NULL; const or_options_t *options = get_options(); @@ -2835,12 +2835,14 @@ router_dump_router_to_string(routerinfo_t *router, } /* PEM-encode the onion key */ - rsa_pubkey = router_get_rsa_onion_pkey(router->onion_pkey, - router->onion_pkey_len); - if (crypto_pk_write_public_key_to_string(rsa_pubkey, - &onion_pkey,&onion_pkeylen)<0) { - log_warn(LD_BUG,"write onion_pkey to string failed!"); - goto err; + rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey, + router->tap_onion_pkey_len); + if (rsa_pubkey) { + if (crypto_pk_write_public_key_to_string(rsa_pubkey, + &onion_pkey,&onion_pkeylen)<0) { + log_warn(LD_BUG,"write onion_pkey to string failed!"); + goto err; + } } /* PEM-encode the identity key */ @@ -2851,7 +2853,7 @@ router_dump_router_to_string(routerinfo_t *router, } /* Cross-certify with RSA key */ - if (tap_key && router->cache_info.signing_key_cert && + if (tap_key && rsa_pubkey && router->cache_info.signing_key_cert && router->cache_info.signing_key_cert->signing_key_included) { char buf[256]; int tap_cc_len = 0; @@ -2976,7 +2978,7 @@ router_dump_router_to_string(routerinfo_t *router, "uptime %ld\n" "bandwidth %d %d %d\n" "%s%s" - "onion-key\n%s" + "%s%s" "signing-key\n%s" "%s%s" "%s%s%s", @@ -2997,7 +2999,8 @@ router_dump_router_to_string(routerinfo_t *router, extra_info_line ? extra_info_line : "", (options->DownloadExtraInfo || options->V3AuthoritativeDir) ? "caches-extra-info\n" : "", - onion_pkey, identity_pkey, + onion_pkey?"onion-key\n":"", onion_pkey?onion_pkey:"", + identity_pkey, rsa_tap_cc_line ? rsa_tap_cc_line : "", ntor_cc_line ? ntor_cc_line : "", family_line, diff --git a/src/test/test_dir.c b/src/test/test_dir.c index a86638f8c9..9dd530fc77 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -217,7 +217,7 @@ basic_routerinfo_new(const char *nickname, uint32_t ipv4_addr, r1->ipv4_dirport = dir_port; r1->supports_tunnelled_dir_requests = 1; - router_set_rsa_onion_pkey(pk1, &r1->onion_pkey, &r1->onion_pkey_len); + router_set_rsa_onion_pkey(pk1, &r1->tap_onion_pkey, &r1->tap_onion_pkey_len); r1->identity_pkey = pk2; r1->bandwidthrate = bandwidthrate; @@ -382,8 +382,8 @@ get_new_onion_key_block(const routerinfo_t *r1) { char *block = NULL; tor_assert(r1); - crypto_pk_t *pk_tmp = router_get_rsa_onion_pkey(r1->onion_pkey, - r1->onion_pkey_len); + crypto_pk_t *pk_tmp = router_get_rsa_onion_pkey(r1->tap_onion_pkey, + r1->tap_onion_pkey_len); block = get_new_rsa_key_block("onion-key", pk_tmp); crypto_pk_free(pk_tmp); return block; @@ -587,8 +587,8 @@ setup_mocks_for_fresh_descriptor(const routerinfo_t *r1, if (rsa_onion_keypair) { mocked_onionkey = crypto_pk_dup_key(rsa_onion_keypair); } else { - mocked_onionkey = router_get_rsa_onion_pkey(r1->onion_pkey, - r1->onion_pkey_len); + mocked_onionkey = router_get_rsa_onion_pkey(r1->tap_onion_pkey, + r1->tap_onion_pkey_len); } MOCK(get_onion_key, mock_get_onion_key); } @@ -643,10 +643,12 @@ STMT_BEGIN \ tt_int_op(rp1->bandwidthrate,OP_EQ, r1->bandwidthrate); \ tt_int_op(rp1->bandwidthburst,OP_EQ, r1->bandwidthburst); \ tt_int_op(rp1->bandwidthcapacity,OP_EQ, r1->bandwidthcapacity); \ - crypto_pk_t *rp1_onion_pkey = router_get_rsa_onion_pkey(rp1->onion_pkey, \ - rp1->onion_pkey_len); \ - crypto_pk_t *r1_onion_pkey = router_get_rsa_onion_pkey(r1->onion_pkey, \ - r1->onion_pkey_len); \ + crypto_pk_t *rp1_onion_pkey = router_get_rsa_onion_pkey( \ + rp1->tap_onion_pkey, \ + rp1->tap_onion_pkey_len); \ + crypto_pk_t *r1_onion_pkey = router_get_rsa_onion_pkey( \ + r1->tap_onion_pkey, \ + r1->tap_onion_pkey_len); \ tt_int_op(crypto_pk_cmp_keys(rp1_onion_pkey, r1_onion_pkey), OP_EQ, 0); \ crypto_pk_free(rp1_onion_pkey); \ crypto_pk_free(r1_onion_pkey); \ diff --git a/src/test/test_hs_service.c b/src/test/test_hs_service.c index dc60c7ca29..6f254f16e8 100644 --- a/src/test/test_hs_service.c +++ b/src/test/test_hs_service.c @@ -1605,7 +1605,6 @@ test_build_update_descriptors(void *arg) tt_int_op(ret, OP_EQ, 0); ri.onion_curve25519_pkey = tor_malloc_zero(sizeof(curve25519_public_key_t)); - ri.onion_pkey = tor_malloc_zero(140); curve25519_public_key_generate(ri.onion_curve25519_pkey, &curve25519_secret_key); memset(ri.cache_info.identity_digest, 'A', DIGEST_LEN); @@ -1631,7 +1630,6 @@ test_build_update_descriptors(void *arg) update_all_descriptors_intro_points(now); tor_free(node->ri->onion_curve25519_pkey); /* Avoid memleak. */ tor_free(node->ri->cache_info.signing_key_cert); - tor_free(node->ri->onion_pkey); expect_log_msg_containing("just picked 1 intro points and wanted 3 for next " "descriptor. It currently has 0 intro points. " "Launching ESTABLISH_INTRO circuit shortly."); diff --git a/src/test/test_router.c b/src/test/test_router.c index 47084bba01..64efedfa46 100644 --- a/src/test/test_router.c +++ b/src/test/test_router.c @@ -60,8 +60,8 @@ rtr_tests_gen_routerinfo(crypto_pk_t *ident_key, crypto_pk_t *tap_key) mock_routerinfo->identity_pkey = crypto_pk_dup_key(ident_key); mock_routerinfo->protocol_list = tor_strdup("Cons=1-2 Desc=1-2 DirCache=1-2"); - router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->onion_pkey, - &mock_routerinfo->onion_pkey_len); + router_set_rsa_onion_pkey(tap_key, &mock_routerinfo->tap_onion_pkey, + &mock_routerinfo->tap_onion_pkey_len); mock_routerinfo->bandwidthrate = 9001; mock_routerinfo->bandwidthburst = 9002; From 6c3dd447623e2d203cf54655af6989774cd2506d Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 14:40:11 -0400 Subject: [PATCH 08/16] routerparse: Simplify checking for now-mandatory elements All of these elements are now mandatory, so we can now simplify our logic for making sure that they are all present or all not-present. --- src/feature/dirparse/routerparse.c | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c index 47f6803fcd..b3653a79e7 100644 --- a/src/feature/dirparse/routerparse.c +++ b/src/feature/dirparse/routerparse.c @@ -627,24 +627,16 @@ router_parse_entry_from_string(const char *s, const char *end, { directory_token_t *ed_sig_tok, *ed_cert_tok, *cc_tap_tok, *cc_ntor_tok, *master_key_tok; - ed_sig_tok = find_opt_by_keyword(tokens, K_ROUTER_SIG_ED25519); - ed_cert_tok = find_opt_by_keyword(tokens, K_IDENTITY_ED25519); - master_key_tok = find_opt_by_keyword(tokens, K_MASTER_KEY_ED25519); + ed_sig_tok = find_by_keyword(tokens, K_ROUTER_SIG_ED25519); + ed_cert_tok = find_by_keyword(tokens, K_IDENTITY_ED25519); + master_key_tok = find_by_keyword(tokens, K_MASTER_KEY_ED25519); cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT); - cc_ntor_tok = find_opt_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT); - int n_ed_toks = !!ed_sig_tok + !!ed_cert_tok + - !!cc_tap_tok + !!cc_ntor_tok; - if ((n_ed_toks != 0 && n_ed_toks != 4) || - (n_ed_toks == 4 && !router->onion_curve25519_pkey)) { - log_warn(LD_DIR, "Router descriptor with only partial ed25519/" - "cross-certification support"); - goto err; - } - if (master_key_tok && !ed_sig_tok) { - log_warn(LD_DIR, "Router descriptor has ed25519 master key but no " - "certificate"); + cc_ntor_tok = find_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT); + + IF_BUG_ONCE(! (ed_sig_tok && ed_cert_tok&& cc_ntor_tok &&master_key_tok)) { goto err; } + if (ed_sig_tok) { tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok); const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok); From 73b73c07e17ae9ff90abdec3752719c6928b9ed0 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 14:55:27 -0400 Subject: [PATCH 09/16] Routerparse: accept routerdescs without TAP keys. --- src/feature/dirparse/routerparse.c | 116 ++++++++++++++++------------- 1 file changed, 66 insertions(+), 50 deletions(-) diff --git a/src/feature/dirparse/routerparse.c b/src/feature/dirparse/routerparse.c index b3653a79e7..6289b4c018 100644 --- a/src/feature/dirparse/routerparse.c +++ b/src/feature/dirparse/routerparse.c @@ -90,7 +90,7 @@ const token_rule_t routerdesc_token_table[] = { T1_START( "router", K_ROUTER, GE(5), NO_OBJ ), T01("ipv6-policy", K_IPV6_POLICY, CONCAT_ARGS, NO_OBJ), T1( "signing-key", K_SIGNING_KEY, NO_ARGS, NEED_KEY_1024 ), - T1( "onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ), + T01("onion-key", K_ONION_KEY, NO_ARGS, NEED_KEY_1024 ), T1("ntor-onion-key", K_ONION_KEY_NTOR, GE(1), NO_OBJ ), T1_END( "router-signature", K_ROUTER_SIGNATURE, NO_ARGS, NEED_OBJ ), T1( "published", K_PUBLISHED, CONCAT_ARGS, NO_OBJ ), @@ -107,7 +107,7 @@ const token_rule_t routerdesc_token_table[] = { T1("identity-ed25519", K_IDENTITY_ED25519, NO_ARGS, NEED_OBJ ), T1("master-key-ed25519", K_MASTER_KEY_ED25519, GE(1), NO_OBJ ), T1("router-sig-ed25519", K_ROUTER_SIG_ED25519, GE(1), NO_OBJ ), - T1("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ), + T01("onion-key-crosscert", K_ONION_KEY_CROSSCERT, NO_ARGS, NEED_OBJ ), T1("ntor-onion-key-crosscert", K_NTOR_ONION_KEY_CROSSCERT, EQ(1), NEED_OBJ ), @@ -595,15 +595,17 @@ router_parse_entry_from_string(const char *s, const char *end, if (parse_iso_time(tok->args[0], &router->cache_info.published_on) < 0) goto err; - tok = find_by_keyword(tokens, K_ONION_KEY); - if (!crypto_pk_public_exponent_ok(tok->key)) { - log_warn(LD_DIR, - "Relay's onion key had invalid exponent."); - goto err; + tok = find_opt_by_keyword(tokens, K_ONION_KEY); + if (tok) { + if (!crypto_pk_public_exponent_ok(tok->key)) { + log_warn(LD_DIR, + "Relay's onion key had invalid exponent."); + goto err; + } + router->tap_onion_pkey = tor_memdup(tok->object_body, tok->object_size); + router->tap_onion_pkey_len = tok->object_size; + crypto_pk_free(tok->key); } - router->tap_onion_pkey = tor_memdup(tok->object_body, tok->object_size); - router->tap_onion_pkey_len = tok->object_size; - crypto_pk_free(tok->key); if ((tok = find_opt_by_keyword(tokens, K_ONION_KEY_NTOR))) { curve25519_public_key_t k; @@ -630,15 +632,65 @@ router_parse_entry_from_string(const char *s, const char *end, ed_sig_tok = find_by_keyword(tokens, K_ROUTER_SIG_ED25519); ed_cert_tok = find_by_keyword(tokens, K_IDENTITY_ED25519); master_key_tok = find_by_keyword(tokens, K_MASTER_KEY_ED25519); - cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT); cc_ntor_tok = find_by_keyword(tokens, K_NTOR_ONION_KEY_CROSSCERT); + /* This, and only this, is optional. */ + cc_tap_tok = find_opt_by_keyword(tokens, K_ONION_KEY_CROSSCERT); + + if (bool_neq(cc_tap_tok==NULL, router->tap_onion_pkey==NULL)) { + log_warn(LD_DIR, "Router descriptor had only one of (onion-key, " + "onion-key-crosscert)."); + goto err; + } IF_BUG_ONCE(! (ed_sig_tok && ed_cert_tok&& cc_ntor_tok &&master_key_tok)) { goto err; } - if (ed_sig_tok) { - tor_assert(ed_cert_tok && cc_tap_tok && cc_ntor_tok); + tor_cert_t *cert; + { + /* Parse the identity certificate */ + cert = tor_cert_parse( + (const uint8_t*)ed_cert_tok->object_body, + ed_cert_tok->object_size); + if (! cert) { + log_warn(LD_DIR, "Couldn't parse ed25519 cert"); + goto err; + } + /* makes sure it gets freed. */ + router->cache_info.signing_key_cert = cert; + + if (cert->cert_type != CERT_TYPE_ID_SIGNING || + ! cert->signing_key_included) { + log_warn(LD_DIR, "Invalid form for ed25519 cert"); + goto err; + } + } + + if (cc_tap_tok) { + rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey, + router->tap_onion_pkey_len); + if (rsa_pubkey == NULL) { + log_warn(LD_DIR, "No pubkey for TAP cross-verification."); + goto err; + } + if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) { + log_warn(LD_DIR, "Wrong object type on onion-key-crosscert " + "in descriptor"); + goto err; + } + if (check_tap_onion_key_crosscert( + (const uint8_t*)cc_tap_tok->object_body, + (int)cc_tap_tok->object_size, + rsa_pubkey, + &cert->signing_key, + (const uint8_t*)router->cache_info.identity_digest)<0) { + log_warn(LD_DIR, "Incorrect TAP cross-verification"); + goto err; + } + } + + { + tor_assert(ed_sig_tok && ed_cert_tok && cc_ntor_tok); const int ed_cert_token_pos = smartlist_pos(tokens, ed_cert_tok); if (ed_cert_token_pos == -1 || router_token_pos == -1 || (ed_cert_token_pos != router_token_pos + 1 && @@ -660,35 +712,14 @@ router_parse_entry_from_string(const char *s, const char *end, "in descriptor"); goto err; } - if (strcmp(cc_tap_tok->object_type, "CROSSCERT")) { - log_warn(LD_DIR, "Wrong object type on onion-key-crosscert " - "in descriptor"); - goto err; - } if (strcmp(cc_ntor_tok->args[0], "0") && strcmp(cc_ntor_tok->args[0], "1")) { log_warn(LD_DIR, "Bad sign bit on ntor-onion-key-crosscert"); goto err; } int ntor_cc_sign_bit = !strcmp(cc_ntor_tok->args[0], "1"); - uint8_t d256[DIGEST256_LEN]; const char *signed_start, *signed_end; - tor_cert_t *cert = tor_cert_parse( - (const uint8_t*)ed_cert_tok->object_body, - ed_cert_tok->object_size); - if (! cert) { - log_warn(LD_DIR, "Couldn't parse ed25519 cert"); - goto err; - } - /* makes sure it gets freed. */ - router->cache_info.signing_key_cert = cert; - - if (cert->cert_type != CERT_TYPE_ID_SIGNING || - ! cert->signing_key_included) { - log_warn(LD_DIR, "Invalid form for ed25519 cert"); - goto err; - } if (master_key_tok) { /* This token is optional, but if it's present, it must match @@ -738,6 +769,7 @@ router_parse_entry_from_string(const char *s, const char *end, crypto_digest_add_bytes(d, ED_DESC_SIGNATURE_PREFIX, strlen(ED_DESC_SIGNATURE_PREFIX)); crypto_digest_add_bytes(d, signed_start, signed_end-signed_start); + crypto_digest_get_digest(d, (char*)d256, sizeof(d256)); crypto_digest_free(d); @@ -768,22 +800,6 @@ router_parse_entry_from_string(const char *s, const char *end, goto err; } - rsa_pubkey = router_get_rsa_onion_pkey(router->tap_onion_pkey, - router->tap_onion_pkey_len); - if (rsa_pubkey == NULL) { - log_warn(LD_DIR, "No pubkey for TAP cross-verification."); - goto err; - } - if (check_tap_onion_key_crosscert( - (const uint8_t*)cc_tap_tok->object_body, - (int)cc_tap_tok->object_size, - rsa_pubkey, - &cert->signing_key, - (const uint8_t*)router->cache_info.identity_digest)<0) { - log_warn(LD_DIR, "Incorrect TAP cross-verification"); - goto err; - } - /* We check this before adding it to the routerlist. */ router->cert_expiration_time = expires; } From 37f95e8dd2ce877c664b8b34bc4bcc99c6ab3002 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 15:03:15 -0400 Subject: [PATCH 10/16] process_descs: Authorities require TAP keys for now. --- src/feature/dirauth/process_descs.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/feature/dirauth/process_descs.c b/src/feature/dirauth/process_descs.c index 95acb31173..5b76e937ab 100644 --- a/src/feature/dirauth/process_descs.c +++ b/src/feature/dirauth/process_descs.c @@ -762,6 +762,16 @@ dirserv_add_descriptor(routerinfo_t *ri, const char **msg, const char *source) log_info(LD_DIR, "Assessing new descriptor: %s: %s", ri->nickname, ri->platform); + /* For now, TAP keys are still required. */ + if (! ri->tap_onion_pkey) { + log_info(LD_DIRSERV, "Rejecting descriptor from %s (source: %s); " + "it has no TAP key.", + router_describe(ri), source); + *msg = "Missing TAP key in descriptor."; + r = ROUTER_AUTHDIR_REJECTS; + goto fail; + } + /* Check whether this descriptor is semantically identical to the last one * from this server. (We do this here and not in router_add_to_routerlist * because we want to be able to accept the newest router descriptor that From 48c1bebd9ee9ad2aa3e6071038d3d9299b66ff0b Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 16:48:00 -0400 Subject: [PATCH 11/16] Remove a now-unused variable. --- src/core/or/extendinfo.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/core/or/extendinfo.c b/src/core/or/extendinfo.c index b37d9831ed..6954335cc2 100644 --- a/src/core/or/extendinfo.c +++ b/src/core/or/extendinfo.c @@ -97,7 +97,6 @@ extend_info_t * extend_info_from_node(const node_t *node, int for_direct_connect, bool for_exit) { - crypto_pk_t *rsa_pubkey = NULL; extend_info_t *info = NULL; tor_addr_port_t ap; int valid_addr = 0; From 71ca75cb199d4a925fc29e938fd5f013cba21049 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 17:23:20 -0400 Subject: [PATCH 12/16] Add a test for a microdesc with no onion key. --- src/test/test_microdesc.c | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/src/test/test_microdesc.c b/src/test/test_microdesc.c index 315a38f257..1209811fb9 100644 --- a/src/test/test_microdesc.c +++ b/src/test/test_microdesc.c @@ -760,6 +760,35 @@ test_md_parse_id_ed25519(void *arg) teardown_capture_of_logs(); } +static void +test_md_parse_no_onion_key(void *arg) +{ + (void)arg; + + /* A correct MD with no onion key. */ + const char GOOD_MD[] = + "onion-key\n" + "ntor-onion-key AppBt6CSeb1kKid/36ototmFA24ddfW5JpjWPLuoJgs=\n" + "id ed25519 VGhpcyBpc24ndCBhY3R1YWxseSBhIHB1YmxpYyBrZXk\n"; + + smartlist_t *mds = NULL; + + mds = microdescs_parse_from_string(GOOD_MD, + NULL, 1, SAVED_NOWHERE, NULL); + tt_assert(mds); + tt_int_op(smartlist_len(mds), OP_EQ, 1); + const microdesc_t *md = smartlist_get(mds, 0); + tt_mem_op(md->ed25519_identity_pkey, OP_EQ, + "This isn't actually a public key", ED25519_PUBKEY_LEN); + + done: + if (mds) { + SMARTLIST_FOREACH(mds, microdesc_t *, m, microdesc_free(m)); + smartlist_free(mds); + } + teardown_capture_of_logs(); +} + static int mock_rgsbd_called = 0; static routerstatus_t *mock_rgsbd_val_a = NULL; static routerstatus_t *mock_rgsbd_val_b = NULL; @@ -894,6 +923,7 @@ struct testcase_t microdesc_tests[] = { { "generate", test_md_generate, 0, NULL, NULL }, { "parse", test_md_parse, 0, NULL, NULL }, { "parse_id_ed25519", test_md_parse_id_ed25519, 0, NULL, NULL }, + { "parse_no_onion_key", test_md_parse_no_onion_key, 0, NULL, NULL }, { "reject_cache", test_md_reject_cache, TT_FORK, NULL, NULL }, { "corrupt_desc", test_md_corrupt_desc, TT_FORK, NULL, NULL }, END_OF_TESTCASES From ff66aa306b3d71cb501aa4e9ab7bbf34308c123f Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 17:48:42 -0400 Subject: [PATCH 13/16] Add a test for parsing a routerdesc with no TAP key. --- src/test/test_dir.c | 67 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/src/test/test_dir.c b/src/test/test_dir.c index 9dd530fc77..b34711dcad 100644 --- a/src/test/test_dir.c +++ b/src/test/test_dir.c @@ -1305,6 +1305,72 @@ test_dir_parse_router_list(void *arg) #undef ADD } +/* Made with chutney and a patched tor: Has no onion-key or + * onion-key-crosscert */ +static const char ROUTERDESC_NO_ONION_KEY[] = +"router test001a 127.0.0.1 5001 0 7001\n" +"identity-ed25519\n" +"-----BEGIN ED25519 CERT-----\n" +"AQQAB0xWARbCJfDrX0OTtpM0fDxU9cLweMnZeUq/KBfAN1wwWHtMAQAgBADBQJ1o\n" +"ClrXUenWC90FYEUQDpMSdxdxKlrR83rYy+keGe61WQHYP0ebowJC19UvPnYryLeA\n" +"Gnhko2WwmbUDGicdnY4j2VSFU15oxBjln65IznZJyiZM4zGE1GkNZzKGmQY=\n" +"-----END ED25519 CERT-----\n" +"master-key-ed25519 wUCdaApa11Hp1gvdBWBFEA6TEncXcSpa0fN62MvpHhk\n" +"or-address [::]:5001\n" +"platform Tor 0.4.9.0-alpha-dev on Linux\n" +"proto Conflux=1 Cons=1-2 Desc=1-2 DirCache=2 FlowCtrl=1-2 HSDir=2 " + "HSIntro=4-5 HSRend=1-2 Link=1-5 LinkAuth=1,3 Microdesc=1-2 Padding=2 " + "Relay=1-4\n" +"published 2024-06-24 21:34:22\n" +"fingerprint FD3A 6FA4 E716 C379 3CBA FEC3 39EA 01C8 B49D 7189\n" +"uptime 0\n" +"bandwidth 1073741824 1073741824 0\n" +"extra-info-digest 9946CAC41485EDFFDD83F7DAF1A088C30563126C " + "lpAMRlRTy9QR2xVCu1nnnxOHA2I05TTKvCSPPcr1geo\n" +"caches-extra-info\n" +"signing-key\n" +"-----BEGIN RSA PUBLIC KEY-----\n" +"MIGJAoGBALcIIij7gNpvSZPvaCLDDNyyQZq7fR0aXiHgmiIc5hYVcBl+zF5sTX6a\n" +"jQF+GQdbSHcRzA1IMWPXnA7+nGOxSNayrQwExuf7ESsBaQHU81/dmV+rgTwtcd3K\n" +"9lobTQUm+idLvGjVF5P1XJkduPvURIgpIfXT1ZHJUQhwxWSw8MmnAgMBAAE=\n" +"-----END RSA PUBLIC KEY-----\n" +"ntor-onion-key-crosscert 1\n" +"-----BEGIN ED25519 CERT-----\n" +"AQoAB0wmAcFAnWgKWtdR6dYL3QVgRRAOkxJ3F3EqWtHzetjL6R4ZAFPSCMLyQ82v\n" +"dvcpZDa7C/qp8TsJn2Z8v77RjRc2QD1KYDzGfg5euwlB1lu8+IR38l3mmC1PXXhe\n" +"ZB84q4aUdAA=\n" +"-----END ED25519 CERT-----\n" +"hidden-service-dir\n" +"contact auth1@test.test\n" +"ntor-onion-key m0dedSB2vjtvz08bNu+LCdIApVuspRlzXbsphXZ62zQ\n" +"reject *:*\n" +"tunnelled-dir-server\n" +"router-sig-ed25519 VMwmiN9KhWWFSFSuVZxG1g46mb2QhMhv0UlatvPKyAV+1jPl" + "EbDFaO1Qur0335Rn0ToysC6UqB1p78pefX67Aw\n" +"router-signature\n" +"-----BEGIN SIGNATURE-----\n" +"q9Hxy4FJVIK2ks/ByBv8P1p7Pc68ie/TTlDN+tce9opPlijy9+ze9/Gd2SKonRm1\n" +"J+WBj/kKYKw+YoUExIT0qMfa6QTCOe/ecp1sNmgeW0YfloP4Nv8goi3S0k4yrPk/\n" +"qw6TIXGYJpvrdR1Qe7+MEl2K1Okqsy5amtOU400lYRA=\n" +"-----END SIGNATURE-----\n" + ; + +static void +test_dir_parse_no_onion_keyrouter_list(void *arg) +{ + (void) arg; + + routerinfo_t *ri = + router_parse_entry_from_string(ROUTERDESC_NO_ONION_KEY, NULL, + 0, 1, 0, NULL); + + tt_assert(ri); + tt_assert(ri->tap_onion_pkey == NULL); + + done: + routerinfo_free(ri); +} + static download_status_t dls_minimal; static download_status_t dls_maximal; static download_status_t dls_bad_fingerprint; @@ -7229,6 +7295,7 @@ struct testcase_t dir_tests[] = { DIR(routerinfo_parsing, 0), DIR(extrainfo_parsing, 0), DIR(parse_router_list, TT_FORK), + DIR(parse_no_onion_keyrouter_list, TT_FORK), DIR(load_routers, TT_FORK), DIR(load_extrainfo, TT_FORK), DIR(getinfo_extra, 0), From 9466cc9fdc86eb3211aa410827583a81e366bf26 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Mon, 24 Jun 2024 19:53:50 -0400 Subject: [PATCH 14/16] Update supported protovers for prop350 Relay=1 is no longer supported; it corresponds to TAP. Microdesc=3 and Desc=3 are now supported; they correspond to the ability to handle (micro)descriptors without TAP onion keys. --- src/core/or/protover.c | 6 +++--- src/test/test_protover.c | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/core/or/protover.c b/src/core/or/protover.c index 175bfbdab0..1ac32bf06c 100644 --- a/src/core/or/protover.c +++ b/src/core/or/protover.c @@ -389,7 +389,7 @@ protocol_list_supports_protocol_or_later(const char *list, /* All protocol version that this relay version supports. */ #define PR_CONFLUX_V "1" #define PR_CONS_V "1-2" -#define PR_DESC_V "1-2" +#define PR_DESC_V "1-3" #define PR_DIRCACHE_V "2" #define PR_FLOWCTRL_V "1-2" #define PR_HSDIR_V "2" @@ -401,9 +401,9 @@ protocol_list_supports_protocol_or_later(const char *list, #else #define PR_LINKAUTH_V "3" #endif -#define PR_MICRODESC_V "1-2" +#define PR_MICRODESC_V "1-3" #define PR_PADDING_V "2" -#define PR_RELAY_V "1-4" +#define PR_RELAY_V "2-4" /** Return the string containing the supported version for the given protocol * type. */ diff --git a/src/test/test_protover.c b/src/test/test_protover.c index 9d14fd678a..9a10cf649f 100644 --- a/src/test/test_protover.c +++ b/src/test/test_protover.c @@ -329,7 +329,7 @@ test_protover_supports_version(void *arg) * headers. */ #define PROTOVER_LINKAUTH_V1 1 #define PROTOVER_LINKAUTH_V2 2 -#define PROTOVER_RELAY_V1 1 +#define PROTOVER_RELAY_V2 2 /* Deprecated HSIntro versions */ #define PROTOVER_HS_INTRO_DEPRECATED_1 1 @@ -397,7 +397,7 @@ test_protover_supported_protocols(void *arg) /* Relay protovers do not appear anywhere in the code. */ tt_assert(protocol_list_supports_protocol(supported_protocols, PRT_RELAY, - PROTOVER_RELAY_V1)); + PROTOVER_RELAY_V2)); tt_assert(protocol_list_supports_protocol(supported_protocols, PRT_RELAY, PROTOVER_RELAY_EXTEND2)); From 6c8b93538c5361d04c80da24ae7d2bb0be3d5d22 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 25 Jun 2024 09:01:21 -0400 Subject: [PATCH 15/16] Do not publish TAP key when publish-dummy-tap-key is 0. --- src/feature/relay/router.c | 37 ++++++++++++++++++++++++++++++++----- 1 file changed, 32 insertions(+), 5 deletions(-) diff --git a/src/feature/relay/router.c b/src/feature/relay/router.c index 1a29b54494..ab5fe697bc 100644 --- a/src/feature/relay/router.c +++ b/src/feature/relay/router.c @@ -211,8 +211,13 @@ set_onion_key(crypto_pk_t *k) mark_my_descriptor_dirty("set onion key"); } -/** Return the current onion key. Requires that the onion key has been - * loaded or generated. */ +/** Return the current TAP onion key. Requires that the onion key has been + * loaded or generated. + * + * Note that this key is no longer used for anything; we only keep it around + * because (as of June 2024) other Tor instances all expect to find it in + * our routerdescs. + **/ MOCK_IMPL(crypto_pk_t *, get_onion_key,(void)) { @@ -220,6 +225,25 @@ get_onion_key,(void)) return onionkey; } +/** + * Return true iff we should include our TAP onion key in our router + * descriptor. + */ +static int +should_publish_tap_onion_key(void) +{ +#define SHOULD_PUBLISH_TAP_MIN 0 +#define SHOULD_PUBLISH_TAP_MAX 1 + /* Note that we err on the side of publishing. */ +#define SHOULD_PUBLISH_TAP_DFLT 1 + + return networkstatus_get_param(NULL, + "publish-dummy-tap-key", + SHOULD_PUBLISH_TAP_DFLT, + SHOULD_PUBLISH_TAP_MIN, + SHOULD_PUBLISH_TAP_MAX); +} + /** Store a full copy of the current onion key into *key, and a full * copy of the most recent onion key into *last. Store NULL into * a pointer if the corresponding key does not exist. @@ -2138,9 +2162,12 @@ router_build_fresh_unsigned_routerinfo,(routerinfo_t **ri_out)) ri->supports_tunnelled_dir_requests = directory_permits_begindir_requests(options); ri->cache_info.published_on = time(NULL); - /* get_onion_key() must invoke from main thread */ - router_set_rsa_onion_pkey(get_onion_key(), &ri->tap_onion_pkey, - &ri->tap_onion_pkey_len); + + if (should_publish_tap_onion_key()) { + /* get_onion_key() must invoke from main thread */ + router_set_rsa_onion_pkey(get_onion_key(), &ri->tap_onion_pkey, + &ri->tap_onion_pkey_len); + } ri->onion_curve25519_pkey = tor_memdup(&get_current_curve25519_keypair()->pubkey, From e4307daef0fca2cd21cbccee06f86b0560306f25 Mon Sep 17 00:00:00 2001 From: Nick Mathewson Date: Tue, 25 Jun 2024 08:35:12 -0400 Subject: [PATCH 16/16] Changes file for proposal 350 phase 1 --- changes/tap-out-part-1 | 12 ++++++++++++ 1 file changed, 12 insertions(+) create mode 100644 changes/tap-out-part-1 diff --git a/changes/tap-out-part-1 b/changes/tap-out-part-1 new file mode 100644 index 0000000000..3d8a445f12 --- /dev/null +++ b/changes/tap-out-part-1 @@ -0,0 +1,12 @@ + o Removed features (obsolete): + - Relays no longer support the obsolete TAP circuit extension + protocol. (For backward compatibility, however, relays still continue to + include TAP keys in their descriptors.) Implements part + of proposal 350. + - Removed some vestigial code for selecting the TAP circuit extension + protocol. + + o Minor features (forward-compatibility): + - We now correctly parse microdescriptors and router descriptors + that do not include TAP onion keys. (For backward compatibility, + authorities continue to require these keys.) Implements part of proposal 350.