tor

The Tor anonymity network
git clone https://git.dasho.dev/tor.git
Log | Files | Refs | README | LICENSE

commit e9eb21ed1e78f7a912e3157e4cc17911e09b9ec0
parent fd1720314a4df1e59a53677aab9d03d5d2078d74
Author: Nick Mathewson <nickm@torproject.org>
Date:   Wed, 28 May 2025 12:22:03 -0400

relay crypto: functions to get key material length.

Diffstat:
Msrc/core/crypto/onion_crypto.c | 7+++++--
Msrc/core/crypto/relay_crypto.c | 17+++++++++++++++++
Msrc/core/crypto/relay_crypto.h | 14++++++++++++++
Msrc/core/crypto/relay_crypto_cgo.c | 5++++-
Msrc/core/crypto/relay_crypto_tor1.c | 12+++++++++++-
Msrc/core/crypto/relay_crypto_tor1.h | 1+
6 files changed, 52 insertions(+), 4 deletions(-)

diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c @@ -41,6 +41,7 @@ #include "lib/crypt_ops/crypto_util.h" #include "feature/relay/routerkeys.h" #include "core/or/congestion_control_common.h" +#include "core/crypto/relay_crypto.h" #include "core/or/circuitbuild.h" @@ -247,9 +248,10 @@ negotiate_v3_ntor_server_circ_params(const uint8_t *param_request_msg, } /* This is the maximum value for keys_out_len passed to - * onion_skin_server_handshake, plus 16. We can make it bigger if needed: + * onion_skin_server_handshake, plus 20 for the rend_nonce. + * We can make it bigger if needed: * It just defines how many bytes to stack-allocate. */ -#define MAX_KEYS_TMP_LEN 128 +#define MAX_KEYS_TMP_LEN (MAX_RELAY_KEY_MATERIAL_LEN + DIGEST_LEN) /** Perform the second (server-side) step of a circuit-creation handshake of * type <b>type</b>, responding to the client request in <b>onion_skin</b> @@ -265,6 +267,7 @@ onion_skin_server_handshake(int type, const circuit_params_t *our_ns_params, uint8_t *reply_out, size_t reply_out_maxlen, + // XXXX keys_out_len will depend on the algorithm we're negotiating. uint8_t *keys_out, size_t keys_out_len, uint8_t *rend_nonce_out, circuit_params_t *params_out) diff --git a/src/core/crypto/relay_crypto.c b/src/core/crypto/relay_crypto.c @@ -188,6 +188,23 @@ relay_crypto_init(relay_crypto_t *crypto, return tor1_crypt_init(crypto, key_data, key_data_len, reverse, is_hs_v3); } +/** Return the amount of key material we need to initialize + * the given relay crypto algorithm. + * + * Return -1 if the algorithm is unrecognized. + */ +ssize_t +relay_crypto_key_material_len(relay_crypto_alg_t alg) +{ + switch (alg) { + case RELAY_CRYPTO_ALG_TOR1: + return tor1_key_material_len(false); + case RELAY_CRYPTO_ALG_TOR1_HS: + return tor1_key_material_len(true); + } + return -1; +} + /** Assert that <b>crypto</b> is valid and set. */ void relay_crypto_assert_ok(const relay_crypto_t *crypto) diff --git a/src/core/crypto/relay_crypto.h b/src/core/crypto/relay_crypto.h @@ -12,6 +12,20 @@ #ifndef TOR_RELAY_CRYPTO_H #define TOR_RELAY_CRYPTO_H +typedef enum relay_crypto_alg_t { + RELAY_CRYPTO_ALG_TOR1, + RELAY_CRYPTO_ALG_TOR1_HS, +} relay_crypto_alg_t; + +#define relay_crypto_alg_bitfield_t ENUM_BF(relay_crypto_alg_t) + +/** Largest possible return value for relay_crypto_key_material_len. */ +/* This is 2x the length needed for a single cgo direction with 256-bit AES + */ +#define MAX_RELAY_KEY_MATERIAL_LEN 224 + +ssize_t relay_crypto_key_material_len(relay_crypto_alg_t alg); + int relay_crypto_init(relay_crypto_t *crypto, const char *key_data, size_t key_data_len, int reverse, int is_hs_v3); diff --git a/src/core/crypto/relay_crypto_cgo.c b/src/core/crypto/relay_crypto_cgo.c @@ -21,6 +21,7 @@ #include "lib/arch/bytes.h" #include "ext/polyval/polyval.h" #include "core/crypto/relay_crypto_cgo.h" +#include "core/crypto/relay_crypto.h" #include "core/or/cell_st.h" #if 0 @@ -361,7 +362,9 @@ size_t cgo_key_material_len(int aesbits) { tor_assert(aesbits == 128 || aesbits == 192 || aesbits == 256); - return (cgo_uiv_keylen(aesbits) + CGO_TAG_LEN); + size_t r = (cgo_uiv_keylen(aesbits) + CGO_TAG_LEN); + tor_assert(r * 2 <= MAX_RELAY_KEY_MATERIAL_LEN); + return r; } /** diff --git a/src/core/crypto/relay_crypto_tor1.c b/src/core/crypto/relay_crypto_tor1.c @@ -191,10 +191,20 @@ tor1_crypt_client_backward(tor1_crypt_t *tor1, cell_t *cell) return false; } +/** Return the number of bytes that tor1_crypt_init expects. */ +size_t +tor1_key_material_len(bool is_hs) +{ + if (is_hs) + return HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN; + else + return CPATH_KEY_MATERIAL_LEN; +} + /** Initialize <b>crypto</b> from the key material in key_data. * * If <b>is_hs_v3</b> is set, this cpath will be used for next gen hidden - * service circuits and <b>key_data</b> must be at least + * service circuits and <b>key_data</b> must be * HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN bytes in length. * * If <b>is_hs_v3</b> is not set, key_data must contain CPATH_KEY_MATERIAL_LEN diff --git a/src/core/crypto/relay_crypto_tor1.h b/src/core/crypto/relay_crypto_tor1.h @@ -21,6 +21,7 @@ bool tor1_crypt_relay_forward(tor1_crypt_t *tor1, cell_t *cell); bool tor1_crypt_client_backward(tor1_crypt_t *tor1, cell_t *cell); void tor1_crypt_client_forward(tor1_crypt_t *tor1, cell_t *cell); +size_t tor1_key_material_len(bool is_hs); int tor1_crypt_init(relay_crypto_t *crypto, const char *key_data, size_t key_data_len, int reverse, int is_hs_v3);