hs_pow: Add CompiledProofOfWorkHash torrc option

This exposes the new fallback behavior in hashx via a new AUTOBOOL
configuration option, available to both clients and services. The
default should be fine for nearly everyone, but it might be necessary
to enable or disable the compiler manually for diagnostic purposes.

Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
This commit is contained in:
Micah Elizabeth Scott
2023-05-28 19:45:41 -07:00
parent a397a92be2
commit 415c0354b2
7 changed files with 48 additions and 5 deletions
+15
View File
@@ -3119,6 +3119,21 @@ The following options are per onion service:
The maximum burst size for rendezvous requests handled from the
priority queue at once. (Default: 2500)
These options are applicable to both onion services and their clients:
[[CompiledProofOfWorkHash]] **CompiledProofOfWorkHash** **0**|**1**|**auto**::
When proof-of-work DoS mitigation is active, both the services themselves
and the clients which connect will use a dynamically generated hash
function as part of the puzzle computation.
+
If this option is set to 1, puzzles will only be solved and verified using
the compiled implementation (about 20x faster) and we choose to fail rather
than using a slower fallback. If it's 0, the compiler will never be used.
By default, the compiler is always tried if possible but the interpreter is
available as a fallback. (Default: auto)
See also <<opt-list-modules,`--list-modules`>>, these proof of work options
have no effect unless the "`pow`" module is enabled at compile time.
== DIRECTORY AUTHORITY SERVER OPTIONS
+1
View File
@@ -380,6 +380,7 @@ static const config_var_t option_vars_[] = {
V(ClientTransportPlugin, LINELIST, NULL),
V(ClientUseIPv6, BOOL, "1"),
V(ClientUseIPv4, BOOL, "1"),
V(CompiledProofOfWorkHash, AUTOBOOL, "auto"),
V(ConfluxEnabled, AUTOBOOL, "auto"),
VAR("ConfluxClientUX", STRING, ConfluxClientUX_option,
"throughput"),
+5
View File
@@ -723,6 +723,11 @@ struct or_options_t {
* accessing this value directly. */
int ClientPreferIPv6DirPort;
/** If true, always use the compiled hash implementation. If false, always
* the interpreter. Default of "auto" allows a dynamic fallback from
* copmiler to interpreter. */
int CompiledProofOfWorkHash;
/** If true, the tor client will use conflux for its general purpose
* circuits which excludes onion service traffic. */
int ConfluxEnabled;
+2 -1
View File
@@ -750,7 +750,8 @@ consider_sending_introduce1(origin_circuit_t *intro_circ,
*/
if (have_module_pow() && desc->encrypted_data.pow_params) {
hs_pow_solver_inputs_t pow_inputs = {
.effort = desc->encrypted_data.pow_params->suggested_effort
.effort = desc->encrypted_data.pow_params->suggested_effort,
.CompiledProofOfWorkHash = get_options()->CompiledProofOfWorkHash
};
ed25519_pubkey_copy(&pow_inputs.service_blinded_id,
&desc->plaintext_data.blinded_pubkey);
+22 -4
View File
@@ -175,9 +175,24 @@ unpack_equix_solution(const uint8_t *bytes_in,
}
}
/** Helper: Map the CompiledProofOfWorkHash configuration option to its
* corresponding equix_ctx_flags bit. */
static equix_ctx_flags
hs_pow_equix_option_flags(int CompiledProofOfWorkHash)
{
if (CompiledProofOfWorkHash == 0) {
return 0;
} else if (CompiledProofOfWorkHash == 1) {
return EQUIX_CTX_MUST_COMPILE;
} else {
tor_assert_nonfatal(CompiledProofOfWorkHash == -1);
return EQUIX_CTX_TRY_COMPILE;
}
}
/** Solve the EquiX/blake2b PoW scheme using the parameters in pow_params, and
* store the solution in pow_solution_out. Returns 0 on success and -1
* otherwise. Called by a client. */
* otherwise. Called by a client, from a cpuworker thread. */
int
hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs,
hs_pow_solution_t *pow_solution_out)
@@ -198,7 +213,10 @@ hs_pow_solve(const hs_pow_solver_inputs_t *pow_inputs,
challenge = build_equix_challenge(&pow_inputs->service_blinded_id,
pow_inputs->seed, nonce, effort);
ctx = equix_alloc(EQUIX_CTX_SOLVE | EQUIX_CTX_TRY_COMPILE);
/* This runs on a cpuworker, let's not access global get_options().
* Instead, the particular options we need are captured in pow_inputs. */
ctx = equix_alloc(EQUIX_CTX_SOLVE |
hs_pow_equix_option_flags(pow_inputs->CompiledProofOfWorkHash));
if (!ctx) {
goto end;
}
@@ -339,7 +357,8 @@ hs_pow_verify(const ed25519_public_key_t *service_blinded_id,
goto done;
}
ctx = equix_alloc(EQUIX_CTX_VERIFY | EQUIX_CTX_TRY_COMPILE);
ctx = equix_alloc(EQUIX_CTX_VERIFY |
hs_pow_equix_option_flags(get_options()->CompiledProofOfWorkHash));
if (!ctx) {
goto done;
}
@@ -428,7 +447,6 @@ pow_worker_threadfn(void *state_, void *work_)
job->pow_solution_out = tor_malloc_zero(sizeof(hs_pow_solution_t));
if (hs_pow_solve(&job->pow_inputs, job->pow_solution_out)) {
log_warn(LD_REND, "Failed to run the proof of work solver");
tor_free(job->pow_solution_out);
job->pow_solution_out = NULL; /* how we signal that we came up empty */
}
+2
View File
@@ -84,6 +84,8 @@ typedef struct hs_pow_solver_inputs_t {
/** Effort chosen by the client. May be higher or lower than
* suggested_effort in the descriptor. */
uint32_t effort;
/** Configuration option, choice of hash implementation. AUTOBOOL. */
int CompiledProofOfWorkHash;
} hs_pow_solver_inputs_t;
/** State and parameters of PoW defenses, stored in the service state. */
+1
View File
@@ -218,6 +218,7 @@ test_hs_pow_vectors(void *arg)
hs_pow_solution_t solution = { 0 };
hs_pow_solver_inputs_t input = {
.effort = vectors[vec_i].effort,
.CompiledProofOfWorkHash = -1
};
tt_int_op(strlen(service_blinded_id_hex), OP_EQ, 2 * HS_POW_ID_LEN);