This is an automated email from the git hooks/post-receive script.
dgoulet pushed a commit to branch main in repository tor.
commit e643a708793f748bf7c3dd4978762429e51411cf Author: Micah Elizabeth Scott beth@torproject.org AuthorDate: Mon May 8 23:58:30 2023 -0700
hs_pow: Modify challenge format, include blinded HS id
This is a protocol breaking change that implements nickm's changes to prop 327 to add an algorithm personalization string and blinded HS id to the EquiX challenge string for our onion service client puzzle.
This corresponds with the spec changes in torspec!130, and it fixes a proposed vulnerability documented in ticket tor#40789.
Clients and services prior to this patch will no longer be compatible with the proposed "v1" proof-of-work protocol.
Signed-off-by: Micah Elizabeth Scott beth@torproject.org --- src/feature/hs/hs_cell.c | 16 +++++--- src/feature/hs/hs_cell.h | 3 +- src/feature/hs/hs_circuit.c | 2 +- src/feature/hs/hs_client.c | 2 + src/feature/hs/hs_pow.c | 51 +++++++++++++++++------- src/feature/hs/hs_pow.h | 25 +++++++++--- src/feature/hs/hs_service.c | 8 ++++ src/feature/hs/hs_service.h | 4 ++ src/test/test_hs_pow.c | 55 ++++++++++++++++++-------- src/test/test_hs_pow_slow.c | 95 +++++++++++++++++++++++++++++++-------------- 10 files changed, 187 insertions(+), 74 deletions(-)
diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c index d3639cb92f..0039825f3c 100644 --- a/src/feature/hs/hs_cell.c +++ b/src/feature/hs/hs_cell.c @@ -799,14 +799,16 @@ hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len) * including if PoW couldn't be verified. */ static int handle_introduce2_encrypted_cell_pow_extension(const hs_service_t *service, - const trn_extension_field_t *field, - hs_cell_introduce2_data_t *data) + const hs_service_intro_point_t *ip, + const trn_extension_field_t *field, + hs_cell_introduce2_data_t *data) { int ret = -1; trn_cell_extension_pow_t *pow = NULL; hs_pow_solution_t sol;
tor_assert(field); + tor_assert(ip);
if (!service->state.pow_state) { log_info(LD_REND, "Unsolicited PoW solution in INTRODUCE2 request."); @@ -840,7 +842,7 @@ handle_introduce2_encrypted_cell_pow_extension(const hs_service_t *service, trn_cell_extension_pow_getconstarray_pow_solution(pow), HS_POW_EQX_SOL_LEN);
- if (hs_pow_verify(service->state.pow_state, &sol)) { + if (hs_pow_verify(&ip->blinded_id, service->state.pow_state, &sol)) { log_info(LD_REND, "PoW INTRODUCE2 request failed to verify."); goto end; } @@ -930,6 +932,7 @@ get_introduce2_keys_and_verify_mac(hs_cell_introduce2_data_t *data, * includes a PoW that doesn't verify). */ static int parse_introduce_cell_extension(const hs_service_t *service, + const hs_service_intro_point_t *ip, hs_cell_introduce2_data_t *data, const trn_extension_field_t *field) { @@ -948,7 +951,7 @@ parse_introduce_cell_extension(const hs_service_t *service, break; case TRUNNEL_EXT_TYPE_POW: /* PoW request. If successful, the effort is put in the data. */ - if (handle_introduce2_encrypted_cell_pow_extension(service, + if (handle_introduce2_encrypted_cell_pow_extension(service, ip, field, data) < 0) { log_fn(LOG_PROTOCOL_WARN, LD_REND, "Invalid PoW cell extension."); ret = -1; @@ -969,7 +972,8 @@ parse_introduce_cell_extension(const hs_service_t *service, ssize_t hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, const origin_circuit_t *circ, - const hs_service_t *service) + const hs_service_t *service, + const hs_service_intro_point_t *ip) { int ret = -1; time_t elapsed; @@ -1102,7 +1106,7 @@ hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, /* The number of extensions should match the number of fields. */ break; } - if (parse_introduce_cell_extension(service, data, field) < 0) { + if (parse_introduce_cell_extension(service, ip, data, field) < 0) { goto done; } } diff --git a/src/feature/hs/hs_cell.h b/src/feature/hs/hs_cell.h index 7b547991e6..02631cf376 100644 --- a/src/feature/hs/hs_cell.h +++ b/src/feature/hs/hs_cell.h @@ -122,7 +122,8 @@ ssize_t hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len); ssize_t hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, const origin_circuit_t *circ, - const hs_service_t *service); + const hs_service_t *service, + const hs_service_intro_point_t *ip); int hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len); int hs_cell_parse_rendezvous2(const uint8_t *payload, size_t payload_len, uint8_t *handshake_info, diff --git a/src/feature/hs/hs_circuit.c b/src/feature/hs/hs_circuit.c index 9311a26169..4c27f417c5 100644 --- a/src/feature/hs/hs_circuit.c +++ b/src/feature/hs/hs_circuit.c @@ -1333,7 +1333,7 @@ hs_circ_handle_introduce2(const hs_service_t *service, goto done; }
- if (hs_cell_parse_introduce2(&data, circ, service) < 0) { + if (hs_cell_parse_introduce2(&data, circ, service, ip) < 0) { hs_metrics_reject_intro_req(service, HS_METRICS_ERR_INTRO_REQ_INTRODUCE2); goto done; } diff --git a/src/feature/hs/hs_client.c b/src/feature/hs/hs_client.c index d8df1d0772..0e4b3ca0c3 100644 --- a/src/feature/hs/hs_client.c +++ b/src/feature/hs/hs_client.c @@ -752,6 +752,8 @@ consider_sending_introduce1(origin_circuit_t *intro_circ, hs_pow_solver_inputs_t pow_inputs = { .effort = desc->encrypted_data.pow_params->suggested_effort }; + ed25519_pubkey_copy(&pow_inputs.service_blinded_id, + &desc->plaintext_data.blinded_pubkey); memcpy(pow_inputs.seed, desc->encrypted_data.pow_params->seed, sizeof pow_inputs.seed); log_debug(LD_REND, "PoW params present in descriptor, suggested_effort=%u", diff --git a/src/feature/hs/hs_pow.c b/src/feature/hs/hs_pow.c index 1a23c69836..f75b3cb119 100644 --- a/src/feature/hs/hs_pow.c +++ b/src/feature/hs/hs_pow.c @@ -9,6 +9,8 @@
#include <stdio.h>
+#include "core/or/or.h" +#include "app/config/config.h" #include "ext/ht.h" #include "ext/compat_blake2.h" #include "core/or/circuitlist.h" @@ -20,6 +22,7 @@ #include "feature/hs/hs_client.h" #include "feature/hs/hs_pow.h" #include "lib/crypt_ops/crypto_rand.h" +#include "lib/crypt_ops/crypto_format.h" #include "lib/arch/bytes.h" #include "lib/cc/ctassert.h" #include "core/mainloop/cpuworker.h" @@ -85,7 +88,7 @@ increment_and_set_nonce(uint8_t *nonce, uint8_t *challenge) break; } } - memcpy(challenge + HS_POW_SEED_LEN, nonce, HS_POW_NONCE_LEN); + memcpy(challenge + HS_POW_NONCE_OFFSET, nonce, HS_POW_NONCE_LEN); }
/* Helper: Allocate an EquiX context, using the much faster compiled @@ -105,18 +108,32 @@ build_equix_ctx(equix_ctx_flags flags) return ctx; }
-/* Helper: Build EquiX challenge (C || N || INT_32(E)) and return a newly - * allocated buffer containing it. */ +/* Helper: Build EquiX challenge (P || ID || C || N || INT_32(E)) and return + * a newly allocated buffer containing it. */ static uint8_t * -build_equix_challenge(const uint8_t *seed, const uint8_t *nonce, +build_equix_challenge(const ed25519_public_key_t *blinded_id, + const uint8_t *seed, const uint8_t *nonce, const uint32_t effort) { - /* Build EquiX challenge (C || N || INT_32(E)). */ size_t offset = 0; uint8_t *challenge = tor_malloc_zero(HS_POW_CHALLENGE_LEN);
- memcpy(challenge, seed, HS_POW_SEED_LEN); + CTASSERT(HS_POW_ID_LEN == sizeof *blinded_id); + tor_assert_nonfatal(!ed25519_public_key_is_zero(blinded_id)); + + log_debug(LD_REND, + "Constructing EquiX challenge with " + "blinded service id %s, effort: %d", + safe_str_client(ed25519_fmt(blinded_id)), + effort); + + memcpy(challenge + offset, HS_POW_PSTRING, HS_POW_PSTRING_LEN); + offset += HS_POW_PSTRING_LEN; + memcpy(challenge + offset, blinded_id, HS_POW_ID_LEN); + offset += HS_POW_ID_LEN; + memcpy(challenge + offset, seed, HS_POW_SEED_LEN); offset += HS_POW_SEED_LEN; + tor_assert(HS_POW_NONCE_OFFSET == offset); memcpy(challenge + offset, nonce, HS_POW_NONCE_LEN); offset += HS_POW_NONCE_LEN; set_uint32(challenge + offset, tor_htonl(effort)); @@ -193,8 +210,9 @@ hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs, /* Generate a random nonce N. */ crypto_rand((char *)nonce, sizeof nonce);
- /* Build EquiX challenge (C || N || INT_32(E)). */ - challenge = build_equix_challenge(pow_inputs->seed, nonce, effort); + /* Build EquiX challenge string */ + challenge = build_equix_challenge(&pow_inputs->service_blinded_id, + pow_inputs->seed, nonce, effort);
ctx = build_equix_ctx(EQUIX_CTX_SOLVE); if (!ctx) { @@ -243,7 +261,8 @@ hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs, * parameters found in pow_state. Returns 0 on success and -1 otherwise. Called * by the service. */ int -hs_pow_verify(const hs_pow_service_state_t *pow_state, +hs_pow_verify(const ed25519_public_key_t *service_blinded_id, + const hs_pow_service_state_t *pow_state, const hs_pow_solution_t *pow_solution) { int ret = -1; @@ -254,6 +273,8 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state,
tor_assert(pow_state); tor_assert(pow_solution); + tor_assert(service_blinded_id); + tor_assert_nonfatal(!ed25519_public_key_is_zero(service_blinded_id));
/* Find a valid seed C that starts with the seed head. Fail if no such seed * exists. */ @@ -278,13 +299,13 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state, goto done; }
- /* Build the challenge with the param we have. */ - challenge = build_equix_challenge(seed, pow_solution->nonce, - pow_solution->effort); + /* Build the challenge with the params we have. */ + challenge = build_equix_challenge(service_blinded_id, seed, + pow_solution->nonce, pow_solution->effort);
if (!validate_equix_challenge(challenge, pow_solution->equix_solution, pow_solution->effort)) { - log_warn(LD_REND, "Equi-X solution and effort was too large."); + log_warn(LD_REND, "Verification of challenge effort in PoW failed."); goto done; }
@@ -293,7 +314,7 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state, goto done; }
- /* Fail if equix_verify(C || N || E, S) != EQUIX_OK */ + /* Fail if equix_verify() != EQUIX_OK */ equix_solution equix_sol; unpack_equix_solution(pow_solution->equix_solution, &equix_sol); equix_result result = equix_verify(ctx, challenge, HS_POW_CHALLENGE_LEN, @@ -482,6 +503,8 @@ hs_pow_queue_work(uint32_t intro_circ_identifier, tor_assert(in_main_thread()); tor_assert(rend_circ_cookie); tor_assert(pow_inputs); + tor_assert_nonfatal( + !ed25519_public_key_is_zero(&pow_inputs->service_blinded_id));
pow_worker_job_t *job = tor_malloc_zero(sizeof(*job)); job->intro_circ_identifier = intro_circ_identifier; diff --git a/src/feature/hs/hs_pow.h b/src/feature/hs/hs_pow.h index 481c293cc5..3418d7a0cb 100644 --- a/src/feature/hs/hs_pow.h +++ b/src/feature/hs/hs_pow.h @@ -13,6 +13,7 @@ #include "lib/evloop/compat_libevent.h" #include "lib/evloop/token_bucket.h" #include "lib/smartlist_core/smartlist_core.h" +#include "lib/crypt_ops/crypto_ed25519.h"
/* Service updates the suggested effort every HS_UPDATE_PERIOD seconds. * This parameter controls how often we can change hs descriptor data to @@ -30,17 +31,27 @@ #define HS_POW_EQX_SOL_LEN 16 /** Length of blake2b hash result (R) used in the PoW scheme. */ #define HS_POW_HASH_LEN 4 +/** Length of algorithm personalization string (P) used in the PoW scheme */ +#define HS_POW_PSTRING_LEN 16 +/** Algorithm personalization string (P) */ +#define HS_POW_PSTRING "Tor hs intro v1\0" +/** Length of the blinded public ID for the onion service (ID) */ +#define HS_POW_ID_LEN 32 /** Length of random seed used in the PoW scheme. */ #define HS_POW_SEED_LEN 32 /** Length of seed identification heading in the PoW scheme. */ #define HS_POW_SEED_HEAD_LEN 4 /** Length of an effort value */ #define HS_POW_EFFORT_LEN sizeof(uint32_t) +/** Offset of the nonce value within the challenge string */ +#define HS_POW_NONCE_OFFSET \ + (HS_POW_PSTRING_LEN + HS_POW_ID_LEN + HS_POW_SEED_LEN) /** Length of a PoW challenge. Construction as per prop327 is: - * (C || N || INT_32(E)) + * (P || ID || C || N || INT_32(E)) */ #define HS_POW_CHALLENGE_LEN \ - (HS_POW_SEED_LEN + HS_POW_NONCE_LEN + HS_POW_EFFORT_LEN) + (HS_POW_PSTRING_LEN + HS_POW_ID_LEN + \ + HS_POW_SEED_LEN + HS_POW_NONCE_LEN + HS_POW_EFFORT_LEN)
/** Type of PoW in the descriptor. */ typedef enum { @@ -68,7 +79,8 @@ typedef struct hs_pow_desc_params_t { typedef struct hs_pow_solver_inputs_t { /** Seed value from a current descriptor */ uint8_t seed[HS_POW_SEED_LEN]; - + /** Blinded public ID for the onion service this puzzle is bound to */ + ed25519_public_key_t service_blinded_id; /** Effort chosen by the client. May be higher or ower than * suggested_effort in the descriptor. */ uint32_t effort; @@ -152,7 +164,8 @@ typedef struct hs_pow_solution_t { int hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs, hs_pow_solution_t *pow_solution_out);
-int hs_pow_verify(const hs_pow_service_state_t *pow_state, +int hs_pow_verify(const ed25519_public_key_t *service_blinded_id, + const hs_pow_service_state_t *pow_state, const hs_pow_solution_t *pow_solution);
void hs_pow_remove_seed_from_cache(const uint8_t *seed_head); @@ -175,9 +188,11 @@ hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs, }
static inline int -hs_pow_verify(const hs_pow_service_state_t *pow_state, +hs_pow_verify(const ed25519_public_key_t *service_blinded_id, + const hs_pow_service_state_t *pow_state, const hs_pow_solution_t *pow_solution) { + (void)service_blinded_id; (void)pow_state; (void)pow_solution; return -1; diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c index a7e4e40a71..3ef2a9120c 100644 --- a/src/feature/hs/hs_service.c +++ b/src/feature/hs/hs_service.c @@ -2304,6 +2304,14 @@ pick_needed_intro_points(hs_service_t *service, safe_str_client(service->onion_address)); goto done; } + + /* Save a copy of the specific version of the blinded ID that we + * use to reach this intro point. Needed to validate proof-of-work + * solutions that are bound to this specific service. */ + tor_assert(desc->desc); + ed25519_pubkey_copy(&ip->blinded_id, + &desc->desc->plaintext_data.blinded_pubkey); + /* Valid intro point object, add it to the descriptor current map. */ service_intro_point_add(desc->intro_points.map, ip); } diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h index e7e53e73a3..36d67719ca 100644 --- a/src/feature/hs/hs_service.h +++ b/src/feature/hs/hs_service.h @@ -62,6 +62,10 @@ typedef struct hs_service_intro_point_t { /** Encryption keypair for the "ntor" type. */ curve25519_keypair_t enc_key_kp;
+ /** Blinded public ID for this service, from this intro point's + * active time period. */ + ed25519_public_key_t blinded_id; + /** Legacy key if that intro point doesn't support v3. This should be used if * the base object legacy flag is set. */ crypto_pk_t *legacy_key; diff --git a/src/test/test_hs_pow.c b/src/test/test_hs_pow.c index 909a2b569e..072fbacff4 100644 --- a/src/test/test_hs_pow.c +++ b/src/test/test_hs_pow.c @@ -264,6 +264,7 @@ test_hs_pow_vectors(void *arg) uint32_t validated_effort; int expected_retval; const char *seed_hex; + const char *service_blinded_id_hex; const char *nonce_hex; const char *sol_hex; const char *encoded_hex; @@ -272,6 +273,7 @@ test_hs_pow_vectors(void *arg) /* All zero, expect invalid */ 1, 0, -1, "0000000000000000000000000000000000000000000000000000000000000000", + "1111111111111111111111111111111111111111111111111111111111111111", "00000000000000000000000000000000", "00000000000000000000000000000000", "01" "00000000000000000000000000000000" @@ -282,67 +284,74 @@ test_hs_pow_vectors(void *arg) /* Valid zero-effort solution */ 0, 0, 0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "55555555555555555555555555555555", "fd57d7676238c0ad1d5473aa2d0cbff5", + "1111111111111111111111111111111111111111111111111111111111111111", + "55555555555555555555555555555555", "4312f87ceab844c78e1c793a913812d7", "01" "55555555555555555555555555555555" "00000000" "aaaaaaaa" - "fd57d7676238c0ad1d5473aa2d0cbff5" + "4312f87ceab844c78e1c793a913812d7" }, { /* Valid high-effort solution */ 1000000, 1000000, 0, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "16505855555555555555555555555555", "bf2c2d345e5773b5c32ec5596244bdbc", + "1111111111111111111111111111111111111111111111111111111111111111", + "59217255555555555555555555555555", "0f3db97b9cac20c1771680a1a34848d3", "01" - "16505855555555555555555555555555" + "59217255555555555555555555555555" "000f4240" "aaaaaaaa" - "bf2c2d345e5773b5c32ec5596244bdbc" + "0f3db97b9cac20c1771680a1a34848d3" }, { /* Reject replays */ 1000000, 0, -1, "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "16505855555555555555555555555555", "bf2c2d345e5773b5c32ec5596244bdbc", + "1111111111111111111111111111111111111111111111111111111111111111", + "59217255555555555555555555555555", "0f3db97b9cac20c1771680a1a34848d3", "01" - "16505855555555555555555555555555" + "59217255555555555555555555555555" "000f4240" "aaaaaaaa" - "bf2c2d345e5773b5c32ec5596244bdbc" + "0f3db97b9cac20c1771680a1a34848d3" }, { /* The claimed effort must exactly match what's in the challenge */ 99999, 0, -1, "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f", - "cdd49fdbc34326d9d2f18ed277469c63", "7f153437c58620d3ea4717746093dde6", + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "2eff9fdbc34326d9d2f18ed277469c63", "400cb091139f86b352119f6e131802d6", "01" - "cdd49fdbc34326d9d2f18ed277469c63" + "2eff9fdbc34326d9d2f18ed277469c63" "0001869f" "86fb0acf" - "7f153437c58620d3ea4717746093dde6" + "400cb091139f86b352119f6e131802d6" }, { /* Otherwise good solution but with a corrupted nonce */ 100000, 0, -1, "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f", - "cdd49fdbc34326d9d2f18ed270469c63", "7f153437c58620d3ea4717746093dde6", + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "2eff9fdbc34326d9a2f18ed277469c63", "400cb091139f86b352119f6e131802d6", "01" - "cdd49fdbc34326d9d2f18ed270469c63" + "2eff9fdbc34326d9a2f18ed277469c63" "000186a0" "86fb0acf" - "7f153437c58620d3ea4717746093dde6" + "400cb091139f86b352119f6e131802d6" }, { /* Corrected version of above */ 100000, 100000, 0, "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f", - "cdd49fdbc34326d9d2f18ed277469c63", "7f153437c58620d3ea4717746093dde6", + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "2eff9fdbc34326d9d2f18ed277469c63", "400cb091139f86b352119f6e131802d6", "01" - "cdd49fdbc34326d9d2f18ed277469c63" + "2eff9fdbc34326d9d2f18ed277469c63" "000186a0" "86fb0acf" - "7f153437c58620d3ea4717746093dde6" + "400cb091139f86b352119f6e131802d6" } };
testing_hs_pow_service_t *tsvc = testing_hs_pow_service_new(); hs_pow_service_state_t *pow_state = tor_malloc_zero(sizeof *pow_state); tsvc->service.state.pow_state = pow_state; + tsvc->service.desc_current = service_descriptor_new(); pow_state->rend_request_pqueue = smartlist_new();
char *mem_op_hex_tmp = NULL; @@ -353,6 +362,7 @@ test_hs_pow_vectors(void *arg) const unsigned num_vectors = sizeof vectors / sizeof vectors[0]; for (unsigned vec_i = 0; vec_i < num_vectors; vec_i++) { const int expected_retval = vectors[vec_i].expected_retval; + const char *service_blinded_id_hex = vectors[vec_i].service_blinded_id_hex; const char *seed_hex = vectors[vec_i].seed_hex; const char *nonce_hex = vectors[vec_i].nonce_hex; const char *sol_hex = vectors[vec_i].sol_hex; @@ -368,10 +378,19 @@ test_hs_pow_vectors(void *arg) }; int retval;
+ tt_int_op(strlen(service_blinded_id_hex), OP_EQ, 2 * HS_POW_ID_LEN); tt_int_op(strlen(seed_hex), OP_EQ, 2 * HS_POW_SEED_LEN); tt_int_op(strlen(nonce_hex), OP_EQ, 2 * sizeof solution.nonce); tt_int_op(strlen(sol_hex), OP_EQ, 2 * sizeof solution.equix_solution);
+ tt_assert(tsvc->service.desc_current); + ed25519_public_key_t *desc_blinded_pubkey = + &tsvc->service.desc_current->desc->plaintext_data.blinded_pubkey; + + tt_int_op(base16_decode((char*)desc_blinded_pubkey->pubkey, + HS_POW_ID_LEN, service_blinded_id_hex, + 2 * HS_POW_ID_LEN), + OP_EQ, HS_POW_ID_LEN); tt_int_op(base16_decode((char*)pow_state->seed_previous, HS_POW_SEED_LEN, seed_hex, 2 * HS_POW_SEED_LEN), OP_EQ, HS_POW_SEED_LEN); @@ -382,6 +401,7 @@ test_hs_pow_vectors(void *arg) sol_hex, 2 * HS_POW_EQX_SOL_LEN), OP_EQ, HS_POW_EQX_SOL_LEN);
+ ed25519_pubkey_copy(&tsvc->service_ip->blinded_id, desc_blinded_pubkey); memcpy(solution.seed_head, pow_state->seed_previous, HS_POW_SEED_HEAD_LEN);
/* Try to encode 'solution' into a relay cell */ @@ -468,6 +488,7 @@ test_hs_pow_vectors(void *arg) tor_free(decrypted); trn_cell_introduce1_free(cell); trn_cell_introduce_encrypted_free(enc_cell); + service_descriptor_free(tsvc->service.desc_current); testing_hs_pow_service_free(tsvc); hs_pow_remove_seed_from_cache(NULL); } diff --git a/src/test/test_hs_pow_slow.c b/src/test/test_hs_pow_slow.c index e7d1311cee..e21eee3395 100644 --- a/src/test/test_hs_pow_slow.c +++ b/src/test/test_hs_pow_slow.c @@ -21,6 +21,7 @@
static int testing_one_hs_pow_solution(const hs_pow_solution_t *ref_solution, + const ed25519_public_key_t *service_blinded_id, const uint8_t *seed) { int retval = -1; @@ -52,7 +53,8 @@ testing_one_hs_pow_solution(const hs_pow_solution_t *ref_solution, sol_buffer.equix_solution[variant / 2 % HS_POW_EQX_SOL_LEN]++; }
- tt_int_op(expected, OP_EQ, hs_pow_verify(s, &sol_buffer)); + tt_int_op(expected, OP_EQ, + hs_pow_verify(service_blinded_id, s, &sol_buffer)); } }
@@ -77,109 +79,136 @@ test_hs_pow_vectors(void *arg) uint32_t effort; const char *solve_rng_hex; const char *seed_hex; + const char *service_blinded_id_hex; const char *nonce_hex; const char *sol_hex; } vectors[] = { { 0, "55555555555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "55555555555555555555555555555555", "fd57d7676238c0ad1d5473aa2d0cbff5" + "1111111111111111111111111111111111111111111111111111111111111111", + "55555555555555555555555555555555", "4312f87ceab844c78e1c793a913812d7" }, { 1, "55555555555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "55555555555555555555555555555555", "703d8bc75492e8f90d836dd21bde61fc" + "1111111111111111111111111111111111111111111111111111111111111111", + "55555555555555555555555555555555", "84355542ab2b3f79532ef055144ac5ab" + }, + { + 1, "55555555555555555555555555555555", + "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", + "1111111111111111111111111111111111111111111111111111111111111110", + "55555555555555555555555555555555", "115e4b70da858792fc205030b8c83af9" }, { 2, "55555555555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "56555555555555555555555555555555", "c2374478d35040b53e4eb9aa9f16e9ec" + "1111111111111111111111111111111111111111111111111111111111111111", + "55555555555555555555555555555555", "4600a93a535ed76dc746c99942ab7de2" }, { 10, "55555555555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "5c555555555555555555555555555555", "b167af85e25a0c961928eff53672c1f8" + "1111111111111111111111111111111111111111111111111111111111111111", + "56555555555555555555555555555555", "128bbda5df2929c3be086de2aad34aed" }, { 10, "ffffffffffffffffffffffffffffffff", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "02000000000000000000000000000000", "954e4464715842d391712bb3b2289ff8" + "1111111111111111111111111111111111111111111111111111111111111111", + "01000000000000000000000000000000", "203af985537fadb23f3ed5873b4c81ce" }, { 1337, "7fffffffffffffffffffffffffffffff", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "eaffffffffffffffffffffffffffffff", "dbab3eb9045f85f8162c482d43f7d6fc" + "4111111111111111111111111111111111111111111111111111111111111111", + "01000000000000000000000000000000", "31c377cb72796ed80ae77df6ac1d6bfd" }, { - 31337, "00410000000000000000000000000000", + 31337, "34a20000000000000000000000000000", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "23410000000000000000000000000000", "545ddd60e33bfa73ec75aada68608ee8" + "1111111111111111111111111111111111111111111111111111111111111111", + "36a20000000000000000000000000000", "ca6899b91113aaf7536f28db42526bff" }, { - 100, "6b555555555555555555555555555555", + 100, "55555555555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "6b555555555555555555555555555555", "7e14e98fed2f35a1b293b39d56b260e9" + "1111111111111111111111111111111111111111111111111111111111111111", + "56555555555555555555555555555555", "3a4122a240bd7abfc922ab3cbb9479ed" }, { - 1000, "0e565555555555555555555555555555", + 1000, "d3555555555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "0e565555555555555555555555555555", "514963616e0b986afb1414afa88b85ff" + "1111111111111111111111111111111111111111111111111111111111111111", + "d4555555555555555555555555555555", "338cc08f57697ce8ac2e4b453057d6e9" }, { - 10000, "80835555555555555555555555555555", + 10000, "c5715555555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "89835555555555555555555555555555", "7a5164905f8aaec152126258a2462ae6" + "1111111111111111111111111111111111111111111111111111111111111111", + "c8715555555555555555555555555555", "9f2d3d4ed831ac96ad34c25fb59ff3e2" }, { - 100000, "fd995655555555555555555555555555", + 100000, "418d5655555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "fd995655555555555555555555555555", "8b27f2664340bc88dd5335821a68f5ff" + "1111111111111111111111111111111111111111111111111111111111111111", + "428d5655555555555555555555555555", "9863f3acd2d15adfd244a7ca61d4c6ff" }, { - 1000000, "15505855555555555555555555555555", + 1000000, "58217255555555555555555555555555", "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", - "16505855555555555555555555555555", "bf2c2d345e5773b5c32ec5596244bdbc" + "1111111111111111111111111111111111111111111111111111111111111111", + "59217255555555555555555555555555", "0f3db97b9cac20c1771680a1a34848d3" }, { 1, "d0aec1669384bfe5ed39cd724d6c7954", "c52be1f8a5e6cc3b8fb71cfdbe272cbc91d4d035400f2f94fb0d0074794e0a07", - "d0aec1669384bfe5ed39cd724d6c7954", "9e062190e23b34a80562818b14cf4ae5" + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "d1aec1669384bfe5ed39cd724d6c7954", "462606e5f8c2f3f844127b8bfdd6b4ff" }, { 1, "b4d0e611e6935750fcf9406aae131f62", "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f", - "b4d0e611e6935750fcf9406aae131f62", "a01cf4457a016488df4fa45f0864b6fb" + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "b4d0e611e6935750fcf9406aae131f62", "9f3fbd50b1a83fb63284bde44318c0fd" }, { 1, "b4d0e611e6935750fcf9406aae131f62", "9dfbd06d86fed8e12de3ab214e1a63ea61f46253fe08346a20378da70c4a327d", - "b5d0e611e6935750fcf9406aae131f62", "5944a260423392780f10b25b7e2502d3" + "bec632eb76123956f99a06d394fcbee8f135b8ed01f2e90aabe404cb0346744a", + "b4d0e611e6935750fcf9406aae131f62", "161baa7490356292d020065fdbe55ffc" }, { 1, "40559fdbc34326d9d2f18ed277469c63", "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f", - "40559fdbc34326d9d2f18ed277469c63", "31139564ca5262a4f82b9385b2832fce" + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "40559fdbc34326d9d2f18ed277469c63", "fa649c6a2c5c0bb6a3511b9ea4b448d1" }, { - 10000, "70559fdbc34326d9d2f18ed277469c63", + 10000, "34569fdbc34326d9d2f18ed277469c63", "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f", - "72559fdbc34326d9d2f18ed277469c63", "262c6c82025c53b69b0bf255606ca3e2" + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "36569fdbc34326d9d2f18ed277469c63", "2802951e623c74adc443ab93e99633ee" }, { - 100000, "c0d49fdbc34326d9d2f18ed277469c63", + 100000, "2cff9fdbc34326d9d2f18ed277469c63", "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f", - "cdd49fdbc34326d9d2f18ed277469c63", "7f153437c58620d3ea4717746093dde6" + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "2eff9fdbc34326d9d2f18ed277469c63", "400cb091139f86b352119f6e131802d6" }, { - 1000000, "40fdb1dbc34326d9d2f18ed277469c63", + 1000000, "5243b3dbc34326d9d2f18ed277469c63", "86fb0acf4932cda44dbb451282f415479462dd10cb97ff5e7e8e2a53c3767a7f", - "4cfdb1dbc34326d9d2f18ed277469c63", "b31bbb45340e17a14c2156c0b66780e7" + "bfd298428562e530c52bdb36d81a0e293ef4a0e94d787f0f8c0c611f4f9e78ed", + "5543b3dbc34326d9d2f18ed277469c63", "b47c718b56315e9697173a6bac1feaa4" }, };
const unsigned num_vectors = sizeof vectors / sizeof vectors[0]; for (unsigned vec_i = 0; vec_i < num_vectors; vec_i++) { const char *seed_hex = vectors[vec_i].seed_hex; + const char *service_blinded_id_hex = vectors[vec_i].service_blinded_id_hex; const char *solve_rng_hex = vectors[vec_i].solve_rng_hex; const char *nonce_hex = vectors[vec_i].nonce_hex; const char *sol_hex = vectors[vec_i].sol_hex; @@ -191,11 +220,16 @@ test_hs_pow_vectors(void *arg) .effort = vectors[vec_i].effort, };
+ tt_int_op(strlen(service_blinded_id_hex), OP_EQ, 2 * HS_POW_ID_LEN); tt_int_op(strlen(seed_hex), OP_EQ, 2 * sizeof input.seed); tt_int_op(strlen(solve_rng_hex), OP_EQ, 2 * sizeof rng_bytes); tt_int_op(strlen(nonce_hex), OP_EQ, 2 * sizeof solution.nonce); tt_int_op(strlen(sol_hex), OP_EQ, 2 * sizeof solution.equix_solution);
+ tt_int_op(base16_decode((char*)input.service_blinded_id.pubkey, + HS_POW_ID_LEN, service_blinded_id_hex, + 2 * HS_POW_ID_LEN), + OP_EQ, HS_POW_ID_LEN); tt_int_op(base16_decode((char*)input.seed, HS_POW_SEED_LEN, seed_hex, 2 * HS_POW_SEED_LEN), OP_EQ, HS_POW_SEED_LEN); @@ -223,7 +257,8 @@ test_hs_pow_vectors(void *arg) tt_mem_op(&solution.equix_solution, OP_EQ, &output.equix_solution, sizeof output.equix_solution);
- tt_int_op(testing_one_hs_pow_solution(&output, input.seed), OP_EQ, 0); + tt_int_op(testing_one_hs_pow_solution(&output, &input.service_blinded_id, + input.seed), OP_EQ, 0); }
done: