From: Nick Mathewson Date: Wed, 28 May 2025 16:22:03 +0000 (-0400) Subject: relay crypto: functions to get key material length. X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e9eb21ed1e78f7a912e3157e4cc17911e09b9ec0;p=thirdparty%2Ftor.git relay crypto: functions to get key material length. --- diff --git a/src/core/crypto/onion_crypto.c b/src/core/crypto/onion_crypto.c index 232dbcc5df..f8088745d2 100644 --- 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 type, responding to the client request in onion_skin @@ -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 index baddd704e0..bc69f4ef25 100644 --- 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 crypto 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 index 5340c07338..5e04dd1cd1 100644 --- 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 index 1e900861fe..9dbc6a65ff 100644 --- 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 index 21e0139f81..baef282f3b 100644 --- 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 crypto from the key material in key_data. * * If is_hs_v3 is set, this cpath will be used for next gen hidden - * service circuits and key_data must be at least + * service circuits and key_data must be * HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN bytes in length. * * If is_hs_v3 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 index 636ca2e216..8a07a8bdd4 100644 --- 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);