[tor-commits] [tor] 06/77: hs: Descriptor support for PoW
gitolite role
git at cupani.torproject.org
Wed May 10 15:46:50 UTC 2023
This is an automated email from the git hooks/post-receive script.
dgoulet pushed a commit to branch main
in repository tor.
commit 26957b47ac8aff33e8c6a6de2a227c0182749206
Author: David Goulet <dgoulet at torproject.org>
AuthorDate: Tue Jun 28 11:09:43 2022 -0400
hs: Descriptor support for PoW
Signed-off-by: David Goulet <dgoulet at torproject.org>
---
src/feature/dirparse/parsecommon.h | 1 +
src/feature/hs/hs_descriptor.c | 115 +++++++++++++++++++++++++++++++++++++
src/feature/hs/hs_descriptor.h | 3 +
src/feature/hs/hs_pow.h | 9 ++-
4 files changed, 126 insertions(+), 2 deletions(-)
diff --git a/src/feature/dirparse/parsecommon.h b/src/feature/dirparse/parsecommon.h
index 675c5f68d5..9333ec4b27 100644
--- a/src/feature/dirparse/parsecommon.h
+++ b/src/feature/dirparse/parsecommon.h
@@ -173,6 +173,7 @@ typedef enum {
R3_DESC_AUTH_CLIENT,
R3_ENCRYPTED,
R3_FLOW_CONTROL,
+ R3_POW_PARAMS,
R_IPO_IDENTIFIER,
R_IPO_IP_ADDRESS,
diff --git a/src/feature/hs/hs_descriptor.c b/src/feature/hs/hs_descriptor.c
index 15ad9d8efb..27152a8bf0 100644
--- a/src/feature/hs/hs_descriptor.c
+++ b/src/feature/hs/hs_descriptor.c
@@ -68,6 +68,7 @@
#include "feature/dirparse/parsecommon.h"
#include "feature/hs/hs_cache.h"
#include "feature/hs/hs_config.h"
+#include "feature/hs/hs_pow.h"
#include "feature/nodelist/torcert.h" /* tor_cert_encode_ed22519() */
#include "lib/memarea/memarea.h"
#include "lib/crypt_ops/crypto_format.h"
@@ -96,6 +97,7 @@
#define str_ip_legacy_key_cert "legacy-key-cert"
#define str_intro_point_start "\n" str_intro_point " "
#define str_flow_control "flow-control"
+#define str_pow_params "pow-params"
/* Constant string value for the construction to encrypt the encrypted data
* section. */
#define str_enc_const_superencryption "hsdir-superencrypted-data"
@@ -117,6 +119,16 @@ static const struct {
{ 0, NULL }
};
+/** PoW supported types. */
+static const struct {
+ hs_pow_desc_type_t type;
+ const char *identifier;
+} pow_types[] = {
+ { HS_POW_DESC_V1, "v1"},
+ /* Indicate end of array. */
+ { 0, NULL }
+};
+
/** Descriptor ruleset. */
static token_rule_t hs_desc_v3_token_table[] = {
T1_START(str_hs_desc, R_HS_DESCRIPTOR, EQ(1), NO_OBJ),
@@ -143,6 +155,7 @@ static token_rule_t hs_desc_encrypted_v3_token_table[] = {
T01(str_intro_auth_required, R3_INTRO_AUTH_REQUIRED, GE(1), NO_OBJ),
T01(str_single_onion, R3_SINGLE_ONION_SERVICE, ARGS, NO_OBJ),
T01(str_flow_control, R3_FLOW_CONTROL, GE(2), NO_OBJ),
+ T01(str_pow_params, R3_POW_PARAMS, GE(3), NO_OBJ),
END_OF_TABLE
};
@@ -777,6 +790,31 @@ get_inner_encrypted_layer_plaintext(const hs_descriptor_t *desc)
protover_get_supported(PRT_FLOWCTRL),
congestion_control_sendme_inc());
}
+
+ /* Add PoW parameters if present. */
+ if (desc->encrypted_data.pow_params) {
+ /* Base64 the seed */
+ size_t seed_b64_len = base64_encode_size(HS_POW_SEED_LEN, 0) + 1;
+ char *seed_b64 = tor_malloc_zero(seed_b64_len);
+ int ret = base64_encode(seed_b64, seed_b64_len,
+ (char *)desc->encrypted_data.pow_params->seed,
+ HS_POW_SEED_LEN, 0);
+ /* Return length doesn't count the NUL byte. */
+ tor_assert((size_t) ret == (seed_b64_len - 1));
+
+ /* Convert the expiration time to space-less ISO format. */
+ char time_buf[ISO_TIME_LEN + 1];
+ format_iso_time_nospace(time_buf,
+ desc->encrypted_data.pow_params->expiration_time);
+
+ /* Add "pow-params" line to descriptor encoding. */
+ smartlist_add_asprintf(lines, "%s %s %s %u %s\n", str_pow_params,
+ pow_types[desc->encrypted_data.pow_params->type].identifier,
+ seed_b64,
+ desc->encrypted_data.pow_params->suggested_effort,
+ time_buf);
+ tor_free(seed_b64);
+ }
}
/* Build the introduction point(s) section. */
@@ -2053,6 +2091,70 @@ desc_sig_is_valid(const char *b64_sig,
return ret;
}
+/** Given the token tok for PoW params, decode it as hs_pow_desc_params_t.
+ * tok->args MUST contain at least 4 elements Return 0 on success else -1 on
+ * failure. */
+static int
+decode_pow_params(const directory_token_t *tok,
+ hs_pow_desc_params_t *pow_params)
+{
+ int ret = -1;
+
+ tor_assert(tok);
+ tor_assert(tok->n_args >= 4);
+ tor_assert(pow_params);
+
+ /* Find the type of PoW system being used. */
+ int match = 0;
+ for (int idx = 0; pow_types[idx].identifier; idx++) {
+ if (!strncmp(tok->args[0], pow_types[idx].identifier,
+ strlen(pow_types[idx].identifier))) {
+ pow_params->type = pow_types[idx].type;
+ match = 1;
+ break;
+ }
+ }
+ if (!match) {
+ log_warn(LD_REND, "Unknown PoW type from descriptor.");
+ goto done;
+ }
+
+ if (base64_decode((char *)pow_params->seed, sizeof(pow_params->seed),
+ tok->args[1], strlen(tok->args[1])) !=
+ sizeof(pow_params->seed)) {
+ log_warn(LD_REND, "Unparseable seed %s in PoW params",
+ escaped(tok->args[1]));
+ goto done;
+ }
+
+ int ok;
+ unsigned long effort =
+ tor_parse_ulong(tok->args[2], 10, 1, UINT32_MAX, &ok, NULL);
+ if (!ok) {
+ log_warn(LD_REND, "Unparseable suggested effort %s in PoW params",
+ escaped(tok->args[2]));
+ goto done;
+ }
+ pow_params->suggested_effort = effort;
+
+ /* Parse the expiration time of the PoW params. */
+ time_t expiration_time = 0;
+ if (parse_iso_time_nospace(tok->args[3], &expiration_time)) {
+ log_warn(LD_REND, "Unparseable expiration time %s in PoW params",
+ escaped(tok->args[3]));
+ goto done;
+ }
+ /* Validation of this time is done in client_desc_has_arrived() so we can
+ * trigger a fetch if expired. */
+ pow_params->expiration_time = expiration_time;
+
+ /* Success. */
+ ret = 0;
+
+ done:
+ return ret;
+}
+
/** Decode descriptor plaintext data for version 3. Given a list of tokens, an
* allocated plaintext object that will be populated and the encoded
* descriptor with its length. The last one is needed for signature
@@ -2364,6 +2466,18 @@ desc_decode_encrypted_v3(const hs_descriptor_t *desc,
desc_encrypted_out->sendme_inc = sendme_inc;
}
+ /* Get PoW if any. */
+ tok = find_opt_by_keyword(tokens, R3_POW_PARAMS);
+ if (tok) {
+ hs_pow_desc_params_t *pow_params =
+ tor_malloc_zero(sizeof(hs_pow_desc_params_t));
+ if (decode_pow_params(tok, pow_params)) {
+ tor_free(pow_params);
+ goto err;
+ }
+ desc_encrypted_out->pow_params = pow_params;
+ }
+
/* Initialize the descriptor's introduction point list before we start
* decoding. Having 0 intro point is valid. Then decode them all. */
desc_encrypted_out->intro_points = smartlist_new();
@@ -2775,6 +2889,7 @@ hs_desc_encrypted_data_free_contents(hs_desc_encrypted_data_t *desc)
smartlist_free(desc->intro_points);
}
tor_free(desc->flow_control_pv);
+ tor_free(desc->pow_params);
memwipe(desc, 0, sizeof(*desc));
}
diff --git a/src/feature/hs/hs_descriptor.h b/src/feature/hs/hs_descriptor.h
index fbfc4715a9..c89dc0b580 100644
--- a/src/feature/hs/hs_descriptor.h
+++ b/src/feature/hs/hs_descriptor.h
@@ -172,6 +172,9 @@ typedef struct hs_desc_encrypted_data_t {
char *flow_control_pv;
uint8_t sendme_inc;
+ /** PoW parameters. If NULL, it is not present. */
+ hs_pow_desc_params_t *pow_params;
+
/** A list of intro points. Contains hs_desc_intro_point_t objects. */
smartlist_t *intro_points;
} hs_desc_encrypted_data_t;
diff --git a/src/feature/hs/hs_pow.h b/src/feature/hs/hs_pow.h
index cd4f228565..7f5e297470 100644
--- a/src/feature/hs/hs_pow.h
+++ b/src/feature/hs/hs_pow.h
@@ -37,10 +37,15 @@ typedef unsigned __int128 uint128_t;
#define HS_POW_CHALLENGE_LEN \
(HS_POW_SEED_LEN + HS_POW_NONCE_LEN + HS_POW_EFFORT_LEN)
+/** Type of PoW in the descriptor. */
+typedef enum {
+ HS_POW_DESC_V1 = 1,
+} hs_pow_desc_type_t;
+
/** Proof-of-Work parameters for DoS defense located in a descriptor. */
typedef struct hs_pow_desc_params_t {
- /** Type of PoW system being used, for example "v1". */
- char *type;
+ /** Type of PoW system being used. */
+ hs_pow_desc_type_t type;
/** Random 32-byte seed used as input the the PoW hash function. Decoded? */
uint8_t seed[HS_POW_SEED_LEN];
--
To stop receiving notification emails like this one, please contact
the administrator of this repository.
More information about the tor-commits
mailing list