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 +#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: