[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-commits] [tor] 06/77: hs: Descriptor support for PoW



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@xxxxxxxxxxxxxx>
AuthorDate: Tue Jun 28 11:09:43 2022 -0400

    hs: Descriptor support for PoW
    
    Signed-off-by: David Goulet <dgoulet@xxxxxxxxxxxxxx>
---
 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.
_______________________________________________
tor-commits mailing list
tor-commits@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-commits