mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-24 04:13:28 +01:00
hs: Descriptor support for PoW
Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
parent
51ce0bb6ef
commit
26957b47ac
@ -173,6 +173,7 @@ typedef enum {
|
|||||||
R3_DESC_AUTH_CLIENT,
|
R3_DESC_AUTH_CLIENT,
|
||||||
R3_ENCRYPTED,
|
R3_ENCRYPTED,
|
||||||
R3_FLOW_CONTROL,
|
R3_FLOW_CONTROL,
|
||||||
|
R3_POW_PARAMS,
|
||||||
|
|
||||||
R_IPO_IDENTIFIER,
|
R_IPO_IDENTIFIER,
|
||||||
R_IPO_IP_ADDRESS,
|
R_IPO_IP_ADDRESS,
|
||||||
|
@ -68,6 +68,7 @@
|
|||||||
#include "feature/dirparse/parsecommon.h"
|
#include "feature/dirparse/parsecommon.h"
|
||||||
#include "feature/hs/hs_cache.h"
|
#include "feature/hs/hs_cache.h"
|
||||||
#include "feature/hs/hs_config.h"
|
#include "feature/hs/hs_config.h"
|
||||||
|
#include "feature/hs/hs_pow.h"
|
||||||
#include "feature/nodelist/torcert.h" /* tor_cert_encode_ed22519() */
|
#include "feature/nodelist/torcert.h" /* tor_cert_encode_ed22519() */
|
||||||
#include "lib/memarea/memarea.h"
|
#include "lib/memarea/memarea.h"
|
||||||
#include "lib/crypt_ops/crypto_format.h"
|
#include "lib/crypt_ops/crypto_format.h"
|
||||||
@ -96,6 +97,7 @@
|
|||||||
#define str_ip_legacy_key_cert "legacy-key-cert"
|
#define str_ip_legacy_key_cert "legacy-key-cert"
|
||||||
#define str_intro_point_start "\n" str_intro_point " "
|
#define str_intro_point_start "\n" str_intro_point " "
|
||||||
#define str_flow_control "flow-control"
|
#define str_flow_control "flow-control"
|
||||||
|
#define str_pow_params "pow-params"
|
||||||
/* Constant string value for the construction to encrypt the encrypted data
|
/* Constant string value for the construction to encrypt the encrypted data
|
||||||
* section. */
|
* section. */
|
||||||
#define str_enc_const_superencryption "hsdir-superencrypted-data"
|
#define str_enc_const_superencryption "hsdir-superencrypted-data"
|
||||||
@ -117,6 +119,16 @@ static const struct {
|
|||||||
{ 0, NULL }
|
{ 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. */
|
/** Descriptor ruleset. */
|
||||||
static token_rule_t hs_desc_v3_token_table[] = {
|
static token_rule_t hs_desc_v3_token_table[] = {
|
||||||
T1_START(str_hs_desc, R_HS_DESCRIPTOR, EQ(1), NO_OBJ),
|
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_intro_auth_required, R3_INTRO_AUTH_REQUIRED, GE(1), NO_OBJ),
|
||||||
T01(str_single_onion, R3_SINGLE_ONION_SERVICE, ARGS, 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_flow_control, R3_FLOW_CONTROL, GE(2), NO_OBJ),
|
||||||
|
T01(str_pow_params, R3_POW_PARAMS, GE(3), NO_OBJ),
|
||||||
END_OF_TABLE
|
END_OF_TABLE
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -777,6 +790,31 @@ get_inner_encrypted_layer_plaintext(const hs_descriptor_t *desc)
|
|||||||
protover_get_supported(PRT_FLOWCTRL),
|
protover_get_supported(PRT_FLOWCTRL),
|
||||||
congestion_control_sendme_inc());
|
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. */
|
/* Build the introduction point(s) section. */
|
||||||
@ -2053,6 +2091,70 @@ desc_sig_is_valid(const char *b64_sig,
|
|||||||
return ret;
|
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
|
/** Decode descriptor plaintext data for version 3. Given a list of tokens, an
|
||||||
* allocated plaintext object that will be populated and the encoded
|
* allocated plaintext object that will be populated and the encoded
|
||||||
* descriptor with its length. The last one is needed for signature
|
* 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;
|
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
|
/* Initialize the descriptor's introduction point list before we start
|
||||||
* decoding. Having 0 intro point is valid. Then decode them all. */
|
* decoding. Having 0 intro point is valid. Then decode them all. */
|
||||||
desc_encrypted_out->intro_points = smartlist_new();
|
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);
|
smartlist_free(desc->intro_points);
|
||||||
}
|
}
|
||||||
tor_free(desc->flow_control_pv);
|
tor_free(desc->flow_control_pv);
|
||||||
|
tor_free(desc->pow_params);
|
||||||
memwipe(desc, 0, sizeof(*desc));
|
memwipe(desc, 0, sizeof(*desc));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,6 +172,9 @@ typedef struct hs_desc_encrypted_data_t {
|
|||||||
char *flow_control_pv;
|
char *flow_control_pv;
|
||||||
uint8_t sendme_inc;
|
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. */
|
/** A list of intro points. Contains hs_desc_intro_point_t objects. */
|
||||||
smartlist_t *intro_points;
|
smartlist_t *intro_points;
|
||||||
} hs_desc_encrypted_data_t;
|
} hs_desc_encrypted_data_t;
|
||||||
|
@ -37,10 +37,15 @@ typedef unsigned __int128 uint128_t;
|
|||||||
#define HS_POW_CHALLENGE_LEN \
|
#define HS_POW_CHALLENGE_LEN \
|
||||||
(HS_POW_SEED_LEN + HS_POW_NONCE_LEN + HS_POW_EFFORT_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. */
|
/** Proof-of-Work parameters for DoS defense located in a descriptor. */
|
||||||
typedef struct hs_pow_desc_params_t {
|
typedef struct hs_pow_desc_params_t {
|
||||||
/** Type of PoW system being used, for example "v1". */
|
/** Type of PoW system being used. */
|
||||||
char *type;
|
hs_pow_desc_type_t type;
|
||||||
|
|
||||||
/** Random 32-byte seed used as input the the PoW hash function. Decoded? */
|
/** Random 32-byte seed used as input the the PoW hash function. Decoded? */
|
||||||
uint8_t seed[HS_POW_SEED_LEN];
|
uint8_t seed[HS_POW_SEED_LEN];
|
||||||
|
Loading…
Reference in New Issue
Block a user