18#include "ext/equix/include/equix.h"
47 return fast_memeq(&entry1->bytes, &entry2->bytes,
sizeof entry1->bytes);
54 return (
unsigned)siphash24g(&ent->bytes,
sizeof ent->bytes);
58 nonce_cache_table = HT_INITIALIZER();
87 uint8_t prev = nonce[i];
88 if (++nonce[i] > prev) {
99 const uint8_t *seed,
const uint8_t *nonce,
100 const uint32_t effort)
109 "Constructing EquiX challenge with "
110 "blinded service id %s, effort: %d",
134 const uint8_t *solution_bytes,
135 const uint32_t effort)
153 return RE <= UINT32_MAX;
161 for (
unsigned i = 0; i < EQUIX_NUM_IDX; i++) {
162 bytes_out[i*2+0] = (uint8_t)sol_in->idx[i];
163 bytes_out[i*2+1] = (uint8_t)(sol_in->idx[i] >> 8);
172 for (
unsigned i = 0; i < EQUIX_NUM_IDX; i++) {
173 sol_out->idx[i] = (uint16_t)bytes_in[i*2+0] |
174 (uint16_t)bytes_in[i*2+1] << 8;
180static equix_ctx_flags
183 if (CompiledProofOfWorkHash == 0) {
185 }
else if (CompiledProofOfWorkHash == 1) {
186 return EQUIX_CTX_MUST_COMPILE;
188 tor_assert_nonfatal(CompiledProofOfWorkHash == -1);
189 return EQUIX_CTX_TRY_COMPILE;
202 uint8_t *challenge = NULL;
207 const uint32_t effort = pow_inputs->
effort;
214 pow_inputs->
seed, nonce, effort);
218 ctx = equix_alloc(EQUIX_CTX_SOLVE |
227 log_info(
LD_REND,
"Solving proof of work (effort %u)", effort);
237 for (
unsigned i = 0; i < buffer.count; i++) {
245 pow_solution_out->effort = effort;
247 memcpy(pow_solution_out->seed_head, pow_inputs->
seed,
248 sizeof(pow_solution_out->seed_head));
250 memcpy(&pow_solution_out->equix_solution,
251 sol_bytes,
sizeof sol_bytes);
256 log_info(
LD_REND,
"Proof of work solution (effort %u) found "
257 "using %s implementation in %u.%06u seconds",
259 (EQUIX_SOLVER_DID_USE_COMPILER & buffer.flags)
260 ?
"compiled" :
"interpreted",
261 (
unsigned)(duration_usec / 1000000),
262 (
unsigned)(duration_usec % 1000000));
271 case EQUIX_FAIL_CHALLENGE:
277 case EQUIX_FAIL_COMPILE:
279 log_warn(
LD_REND,
"Proof of work solver failed, "
280 "compile error with no fallback enabled.");
285 case EQUIX_FAIL_ORDER:
286 case EQUIX_FAIL_PARTIAL_SUM:
287 case EQUIX_FAIL_FINAL_SUM:
290 case EQUIX_FAIL_NO_SOLVER:
291 case EQUIX_FAIL_INTERNAL:
317 uint8_t *challenge = NULL;
320 const uint8_t *seed = NULL;
329 if (
fast_memeq(pow_state->seed_current, pow_solution->seed_head,
331 seed = pow_state->seed_current;
332 }
else if (
fast_memeq(pow_state->seed_previous, pow_solution->seed_head,
334 seed = pow_state->seed_previous;
336 log_warn(
LD_REND,
"Seed head didn't match either seed.");
342 memcpy(search.bytes.seed_head, pow_solution->seed_head,
344 entry = HT_FIND(nonce_cache_table_ht, &nonce_cache_table, &search);
346 log_warn(
LD_REND,
"Found (nonce, seed) tuple in the replay cache.");
351 challenge = build_equix_challenge(service_blinded_id, seed,
352 pow_solution->nonce, pow_solution->effort);
355 pow_solution->effort)) {
356 log_warn(
LD_REND,
"Verification of challenge effort in PoW failed.");
360 ctx = equix_alloc(EQUIX_CTX_VERIFY |
371 if (result != EQUIX_OK) {
372 log_warn(
LD_REND,
"Verification of EquiX solution in PoW failed.");
382 memcpy(entry->bytes.seed_head, pow_solution->seed_head,
384 HT_INSERT(nonce_cache_table_ht, &nonce_cache_table, entry);
398 HT_FOREACH_FN(nonce_cache_table_ht, &nonce_cache_table,
399 nonce_cache_entry_match_seed_and_free, (
void*)seed_head);
410 tor_assert(smartlist_len(state->rend_request_pqueue) == 0);
411 smartlist_free(state->rend_request_pqueue);
412 mainloop_event_free(state->pop_pqueue_ev);
498 if (service_identity_pk)
503 if (intro_circ && rend_circ && service_identity_pk && desc && ip &&
507 log_info(
LD_REND,
"Got a PoW solution we like! Shipping it!");
526 log_warn(
LD_REND,
"PoW cpuworker returned with no solution");
528 log_info(
LD_REND,
"PoW solution completed but we can "
529 "no longer locate its circuit");
544 const uint8_t *rend_circ_cookie,
555 memcpy(&job->rend_circ_cookie, rend_circ_cookie,
556 sizeof job->rend_circ_cookie);
Inline functions for reading and writing multibyte values from the middle of strings,...
static uint32_t tor_htonl(uint32_t a)
static void set_uint32(void *cp, uint32_t v)
static uint32_t get_uint32(const void *cp)
origin_circuit_t * circuit_get_by_global_id(uint32_t id)
Header file for circuitlist.c.
Compatibility adapter providing blake2b using ext/equix/hashx.
int64_t monotime_diff_usec(const monotime_t *start, const monotime_t *end)
Functions and types for monotonic times.
void monotime_get(monotime_t *out)
const or_options_t * get_options(void)
Header file for config.c.
workqueue_entry_t * cpuworker_queue_work(workqueue_priority_t priority, workqueue_reply_t(*fn)(void *, void *), void(*reply_fn)(void *), void *arg)
Header file for cpuworker.c.
int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
void crypto_rand(char *to, size_t n)
Common functions for using (pseudo-)random number generators.
Compile-time assertions: CTASSERT(expression).
#define fast_memeq(a, b, c)
CTASSERT(NUMBER_SECOND_GUARDS< 20)
const hs_descriptor_t * hs_cache_lookup_as_client(const ed25519_public_key_t *key)
Header file for hs_cache.c.
void rend_pqueue_clear(hs_pow_service_state_t *pow_state)
HT_PROTOTYPE(hs_circuitmap_ht, circuit_t, hs_circuitmap_node, hs_circuit_hash_token, hs_circuits_have_same_token)
origin_circuit_t * hs_circuitmap_get_established_rend_circ_client_side(const uint8_t *cookie)
Header file for hs_circuitmap.c.
const hs_desc_intro_point_t * find_desc_intro_point_by_ident(const hs_ident_circuit_t *ident, const hs_descriptor_t *desc)
int send_introduce1(origin_circuit_t *intro_circ, origin_circuit_t *rend_circ, const hs_descriptor_t *desc, hs_pow_solution_t *pow_solution, const hs_desc_intro_point_t *ip)
Header file containing client data for the HS subsystem.
Header file for hs_descriptor.c.
#define HS_REND_COOKIE_LEN
static unsigned nonce_cache_entry_hash_(const struct nonce_cache_entry_t *ent)
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)
static bool validate_equix_challenge(const uint8_t *challenge, const uint8_t *solution_bytes, const uint32_t effort)
static void pack_equix_solution(const equix_solution *sol_in, uint8_t *bytes_out)
static equix_ctx_flags hs_pow_equix_option_flags(int CompiledProofOfWorkHash)
static void pow_worker_replyfn(void *work_)
static void unpack_equix_solution(const uint8_t *bytes_in, equix_solution *sol_out)
int hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs, hs_pow_solution_t *pow_solution_out)
static void increment_and_set_nonce(uint8_t *nonce, uint8_t *challenge)
int hs_pow_queue_work(uint32_t intro_circ_identifier, const uint8_t *rend_circ_cookie, const hs_pow_solver_inputs_t *pow_inputs)
static int nonce_cache_entries_eq_(const struct nonce_cache_entry_t *entry1, const struct nonce_cache_entry_t *entry2)
static void pow_worker_job_free(pow_worker_job_t *job)
static workqueue_reply_t pow_worker_threadfn(void *state_, void *work_)
void hs_pow_remove_seed_from_cache(const uint8_t *seed_head)
void hs_pow_free_service_state(hs_pow_service_state_t *state)
Header file containing PoW denial of service defenses for the HS subsystem for all versions.
#define HS_POW_EQX_SOL_LEN
#define HS_POW_NONCE_OFFSET
#define HS_POW_EFFORT_LEN
#define HS_POW_CHALLENGE_LEN
#define HS_POW_SEED_HEAD_LEN
#define HS_POW_PSTRING_LEN
typedef HT_HEAD(hs_service_ht, hs_service_t) hs_service_ht
void * tor_reallocarray_(void *ptr, size_t sz1, size_t sz2)
void tor_free_(void *mem)
Master header file for Tor-specific functionality.
Origin circuit structure.
ed25519_public_key_t identity_pk
struct hs_ident_circuit_t * hs_ident
unsigned int hs_currently_solving_pow
unsigned int hs_with_pow_circ
hs_pow_solver_inputs_t pow_inputs
uint32_t intro_circ_identifier
hs_pow_solution_t * pow_solution_out
#define tor_assert_nonfatal_unreached()