summaryrefslogtreecommitdiff
path: root/src/feature
diff options
context:
space:
mode:
authorMicah Elizabeth Scott <beth@torproject.org>2023-03-14 20:45:36 -0700
committerMicah Elizabeth Scott <beth@torproject.org>2023-05-10 07:38:28 -0700
commit00d9e0d252687110189ea5a1ed0dce99a7984681 (patch)
treed1c936037c98231b423ebdfd010a95376dabb63a /src/feature
parent209a59face791159e167837214e22b6eaa3375b4 (diff)
downloadtor-00d9e0d252687110189ea5a1ed0dce99a7984681.tar.gz
tor-00d9e0d252687110189ea5a1ed0dce99a7984681.zip
hs_pow: Define seed_head as uint8_t[4] instead of uint32_t
This is more consistent with the specification, and it's much less confusing with endianness. This resolves the underlying cause of the earlier byte-swap. This patch itself does not change the wire protocol at all, it's just tidying up the types we use at the trunnel layer. Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
Diffstat (limited to 'src/feature')
-rw-r--r--src/feature/hs/hs_cell.c6
-rw-r--r--src/feature/hs/hs_pow.c38
-rw-r--r--src/feature/hs/hs_pow.h18
-rw-r--r--src/feature/hs/hs_service.c6
4 files changed, 38 insertions, 30 deletions
diff --git a/src/feature/hs/hs_cell.c b/src/feature/hs/hs_cell.c
index 190f0f3b5a..dce360fd91 100644
--- a/src/feature/hs/hs_cell.c
+++ b/src/feature/hs/hs_cell.c
@@ -405,8 +405,9 @@ build_introduce_pow_extension(const hs_pow_solution_t *pow_solution,
&pow_solution->nonce, TRUNNEL_POW_NONCE_LEN);
trn_cell_extension_pow_set_pow_effort(pow_ext, pow_solution->effort);
- trn_cell_extension_pow_set_pow_seed(pow_ext, pow_solution->seed_head);
+ memcpy(trn_cell_extension_pow_getarray_pow_seed(pow_ext),
+ pow_solution->seed_head, TRUNNEL_POW_SEED_HEAD_LEN);
memcpy(trn_cell_extension_pow_getarray_pow_solution(pow_ext),
&pow_solution->equix_solution, TRUNNEL_POW_SOLUTION_LEN);
@@ -829,7 +830,8 @@ handle_introduce2_encrypted_cell_pow_extension(const hs_service_t *service,
/* Effort E */
sol.effort = trn_cell_extension_pow_get_pow_effort(pow);
/* Seed C */
- sol.seed_head = trn_cell_extension_pow_get_pow_seed(pow);
+ memcpy(&sol.seed_head, trn_cell_extension_pow_getconstarray_pow_seed(pow),
+ HS_POW_SEED_HEAD_LEN);
/* Nonce N */
memcpy(&sol.nonce, trn_cell_extension_pow_getconstarray_pow_nonce(pow),
HS_POW_NONCE_LEN);
diff --git a/src/feature/hs/hs_pow.c b/src/feature/hs/hs_pow.c
index e41f271fec..77fec689e4 100644
--- a/src/feature/hs/hs_pow.c
+++ b/src/feature/hs/hs_pow.c
@@ -26,8 +26,10 @@
/** Cache entry for (nonce, seed) replay protection. */
typedef struct nonce_cache_entry_t {
HT_ENTRY(nonce_cache_entry_t) node;
- uint8_t nonce[HS_POW_NONCE_LEN];
- uint32_t seed_head;
+ struct {
+ uint8_t nonce[HS_POW_NONCE_LEN];
+ uint8_t seed_head[HS_POW_SEED_HEAD_LEN];
+ } bytes;
} nonce_cache_entry_t;
/** Return true if the two (nonce, seed) replay cache entries are the same */
@@ -35,15 +37,14 @@ static inline int
nonce_cache_entries_eq_(const struct nonce_cache_entry_t *entry1,
const struct nonce_cache_entry_t *entry2)
{
- return fast_memeq(entry1->nonce, entry2->nonce, HS_POW_NONCE_LEN) &&
- entry1->seed_head == entry2->seed_head;
+ return fast_memeq(&entry1->bytes, &entry2->bytes, sizeof entry1->bytes);
}
/** Hash function to hash the (nonce, seed) tuple entry. */
static inline unsigned
nonce_cache_entry_hash_(const struct nonce_cache_entry_t *ent)
{
- return (unsigned)siphash24g(ent->nonce, HS_POW_NONCE_LEN) + ent->seed_head;
+ return (unsigned)siphash24g(&ent->bytes, sizeof ent->bytes);
}
static HT_HEAD(nonce_cache_table_ht, nonce_cache_entry_t)
@@ -62,7 +63,7 @@ static int
nonce_cache_entry_has_seed(nonce_cache_entry_t *ent, void *data)
{
/* Returning nonzero makes HT_FOREACH_FN remove the element from the HT */
- return ent->seed_head == *(uint32_t *)data;
+ return fast_memeq(ent->bytes.seed_head, data, HS_POW_SEED_HEAD_LEN);
}
/** Helper: Increment a given nonce and set it in the challenge at the right
@@ -186,7 +187,8 @@ hs_pow_solve(const hs_pow_desc_params_t *pow_params,
/* Store the effort E. */
pow_solution_out->effort = effort;
/* We only store the first 4 bytes of the seed C. */
- pow_solution_out->seed_head = tor_ntohl(get_uint32(pow_params->seed));
+ memcpy(pow_solution_out->seed_head, pow_params->seed,
+ sizeof(pow_solution_out->seed_head));
/* Store the solution S */
memcpy(&pow_solution_out->equix_solution, sol,
sizeof(pow_solution_out->equix_solution));
@@ -235,11 +237,11 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state,
/* Find a valid seed C that starts with the seed head. Fail if no such seed
* exists. */
- if (tor_ntohl(get_uint32(pow_state->seed_current))
- == pow_solution->seed_head) {
+ if (fast_memeq(pow_state->seed_current, pow_solution->seed_head,
+ HS_POW_SEED_HEAD_LEN)) {
seed = pow_state->seed_current;
- } else if (tor_ntohl(get_uint32(pow_state->seed_previous))
- == pow_solution->seed_head) {
+ } else if (fast_memeq(pow_state->seed_previous, pow_solution->seed_head,
+ HS_POW_SEED_HEAD_LEN)) {
seed = pow_state->seed_previous;
} else {
log_warn(LD_REND, "Seed head didn't match either seed.");
@@ -247,8 +249,9 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state,
}
/* Fail if N = POW_NONCE is present in the replay cache. */
- memcpy(search.nonce, pow_solution->nonce, HS_POW_NONCE_LEN);
- search.seed_head = pow_solution->seed_head;
+ memcpy(search.bytes.nonce, pow_solution->nonce, HS_POW_NONCE_LEN);
+ memcpy(search.bytes.seed_head, pow_solution->seed_head,
+ HS_POW_SEED_HEAD_LEN);
entry = HT_FIND(nonce_cache_table_ht, &nonce_cache_table, &search);
if (entry) {
log_warn(LD_REND, "Found (nonce, seed) tuple in the replay cache.");
@@ -283,8 +286,9 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state,
/* Add the (nonce, seed) tuple to the replay cache. */
entry = tor_malloc_zero(sizeof(nonce_cache_entry_t));
- memcpy(entry->nonce, pow_solution->nonce, HS_POW_NONCE_LEN);
- entry->seed_head = pow_solution->seed_head;
+ memcpy(entry->bytes.nonce, pow_solution->nonce, HS_POW_NONCE_LEN);
+ memcpy(entry->bytes.seed_head, pow_solution->seed_head,
+ HS_POW_SEED_HEAD_LEN);
HT_INSERT(nonce_cache_table_ht, &nonce_cache_table, entry);
done:
@@ -296,11 +300,11 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state,
/** Remove entries from the (nonce, seed) replay cache which are for the seed
* beginning with seed_head. */
void
-hs_pow_remove_seed_from_cache(uint32_t seed)
+hs_pow_remove_seed_from_cache(const uint8_t *seed_head)
{
/* If nonce_cache_entry_has_seed returns 1, the entry is removed. */
HT_FOREACH_FN(nonce_cache_table_ht, &nonce_cache_table,
- nonce_cache_entry_has_seed, &seed);
+ nonce_cache_entry_has_seed, (void*)seed_head);
}
/** Free a given PoW service state. */
diff --git a/src/feature/hs/hs_pow.h b/src/feature/hs/hs_pow.h
index 6eb03ef64e..3d7018ab30 100644
--- a/src/feature/hs/hs_pow.h
+++ b/src/feature/hs/hs_pow.h
@@ -27,6 +27,8 @@
#define HS_POW_HASH_LEN 4
/** Length of random seed used in the PoW scheme. */
#define HS_POW_SEED_LEN 32
+/** Length of seed identification heading in the PoW scheme. */
+#define HS_POW_SEED_HEAD_LEN 4
/** Length of an effort value */
#define HS_POW_EFFORT_LEN sizeof(uint32_t)
/** Length of a PoW challenge. Construction as per prop327 is:
@@ -45,7 +47,7 @@ typedef struct hs_pow_desc_params_t {
/** 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? */
+ /** Random 32-byte seed used as input the the PoW hash function */
uint8_t seed[HS_POW_SEED_LEN];
/** Specifies effort value that clients should aim for when contacting the
@@ -110,14 +112,14 @@ typedef struct hs_pow_service_state_t {
/* Struct to store a solution to the PoW challenge. */
typedef struct hs_pow_solution_t {
- /* The 16 byte nonce used in the solution. */
+ /* The nonce chosen to satisfy the PoW challenge's conditions. */
uint8_t nonce[HS_POW_NONCE_LEN];
- /* The effort used in the solution. */
+ /* The effort used in this solution. */
uint32_t effort;
- /* The first four bytes of the seed used in the solution. */
- uint32_t seed_head;
+ /* A prefix of the seed used in this solution, so it can be identified. */
+ uint8_t seed_head[HS_POW_SEED_HEAD_LEN];
/* The Equi-X solution used in the solution. */
equix_solution equix_solution;
@@ -133,7 +135,7 @@ int hs_pow_solve(const hs_pow_desc_params_t *pow_params,
int hs_pow_verify(const hs_pow_service_state_t *pow_state,
const hs_pow_solution_t *pow_solution);
-void hs_pow_remove_seed_from_cache(uint32_t seed);
+void hs_pow_remove_seed_from_cache(const uint8_t *seed_head);
void hs_pow_free_service_state(hs_pow_service_state_t *state);
int hs_pow_queue_work(uint32_t intro_circ_identifier,
@@ -162,9 +164,9 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state,
}
static inline void
-hs_pow_remove_seed_from_cache(uint32_t seed)
+hs_pow_remove_seed_from_cache(const uint8_t *seed_head)
{
- (void)seed;
+ (void)seed_head;
}
static inline void
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index a9070024cb..44d39e6525 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -2650,7 +2650,7 @@ rotate_pow_seeds(hs_service_t *service, time_t now)
/* Before we overwrite the previous seed lets scrub entries corresponding
* to it in the nonce replay cache. */
- hs_pow_remove_seed_from_cache(get_uint32(pow_state->seed_previous));
+ hs_pow_remove_seed_from_cache(pow_state->seed_previous);
/* Keep track of the current seed that we are now rotating. */
memcpy(pow_state->seed_previous, pow_state->seed_current, HS_POW_SEED_LEN);
@@ -2658,8 +2658,8 @@ rotate_pow_seeds(hs_service_t *service, time_t now)
/* Generate a new random seed to use from now on. Make sure the seed head
* is different to that of the previous seed. The following while loop
* will run at least once as the seeds will initially be equal. */
- while (get_uint32(pow_state->seed_previous) ==
- get_uint32(pow_state->seed_current)) {
+ while (fast_memeq(pow_state->seed_previous, pow_state->seed_current,
+ HS_POW_SEED_HEAD_LEN)) {
crypto_rand((char *)pow_state->seed_current, HS_POW_SEED_LEN);
}