mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-27 22:03:31 +01:00
hs_pow: Don't require uint128_t
We were using a native uint128_t to represent the hs_pow nonce, but as the comments note it's more portable and more flexible to use a byte array. Indeed the uint128_t was a problem for 32-bit platforms. This swaps in a new implementation that uses multiple machine words to implement the nonce incrementation. Signed-off-by: Micah Elizabeth Scott <beth@torproject.org>
This commit is contained in:
parent
1a3afeb387
commit
209a59face
@ -7,8 +7,6 @@
|
|||||||
* when a hidden service is defending against DoS attacks.
|
* when a hidden service is defending against DoS attacks.
|
||||||
**/
|
**/
|
||||||
|
|
||||||
typedef unsigned __int128 uint128_t;
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "ext/ht.h"
|
#include "ext/ht.h"
|
||||||
@ -20,6 +18,7 @@ typedef unsigned __int128 uint128_t;
|
|||||||
#include "feature/hs/hs_client.h"
|
#include "feature/hs/hs_client.h"
|
||||||
#include "feature/hs/hs_pow.h"
|
#include "feature/hs/hs_pow.h"
|
||||||
#include "lib/crypt_ops/crypto_rand.h"
|
#include "lib/crypt_ops/crypto_rand.h"
|
||||||
|
#include "lib/cc/ctassert.h"
|
||||||
#include "core/mainloop/cpuworker.h"
|
#include "core/mainloop/cpuworker.h"
|
||||||
#include "lib/evloop/workqueue.h"
|
#include "lib/evloop/workqueue.h"
|
||||||
|
|
||||||
@ -27,7 +26,7 @@ typedef unsigned __int128 uint128_t;
|
|||||||
/** Cache entry for (nonce, seed) replay protection. */
|
/** Cache entry for (nonce, seed) replay protection. */
|
||||||
typedef struct nonce_cache_entry_t {
|
typedef struct nonce_cache_entry_t {
|
||||||
HT_ENTRY(nonce_cache_entry_t) node;
|
HT_ENTRY(nonce_cache_entry_t) node;
|
||||||
uint128_t nonce;
|
uint8_t nonce[HS_POW_NONCE_LEN];
|
||||||
uint32_t seed_head;
|
uint32_t seed_head;
|
||||||
} nonce_cache_entry_t;
|
} nonce_cache_entry_t;
|
||||||
|
|
||||||
@ -36,7 +35,7 @@ static inline int
|
|||||||
nonce_cache_entries_eq_(const struct nonce_cache_entry_t *entry1,
|
nonce_cache_entries_eq_(const struct nonce_cache_entry_t *entry1,
|
||||||
const struct nonce_cache_entry_t *entry2)
|
const struct nonce_cache_entry_t *entry2)
|
||||||
{
|
{
|
||||||
return entry1->nonce == entry2->nonce &&
|
return fast_memeq(entry1->nonce, entry2->nonce, HS_POW_NONCE_LEN) &&
|
||||||
entry1->seed_head == entry2->seed_head;
|
entry1->seed_head == entry2->seed_head;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -44,7 +43,7 @@ nonce_cache_entries_eq_(const struct nonce_cache_entry_t *entry1,
|
|||||||
static inline unsigned
|
static inline unsigned
|
||||||
nonce_cache_entry_hash_(const struct nonce_cache_entry_t *ent)
|
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->nonce, HS_POW_NONCE_LEN) + ent->seed_head;
|
||||||
}
|
}
|
||||||
|
|
||||||
static HT_HEAD(nonce_cache_table_ht, nonce_cache_entry_t)
|
static HT_HEAD(nonce_cache_table_ht, nonce_cache_entry_t)
|
||||||
@ -69,9 +68,14 @@ nonce_cache_entry_has_seed(nonce_cache_entry_t *ent, void *data)
|
|||||||
/** Helper: Increment a given nonce and set it in the challenge at the right
|
/** Helper: Increment a given nonce and set it in the challenge at the right
|
||||||
* offset. Use by the solve function. */
|
* offset. Use by the solve function. */
|
||||||
static inline void
|
static inline void
|
||||||
increment_and_set_nonce(uint128_t *nonce, uint8_t *challenge)
|
increment_and_set_nonce(uint8_t *nonce, uint8_t *challenge)
|
||||||
{
|
{
|
||||||
(*nonce)++;
|
for (unsigned i = 0; i < HS_POW_NONCE_LEN; i++) {
|
||||||
|
uint8_t prev = nonce[i];
|
||||||
|
if (++nonce[i] > prev) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
memcpy(challenge + HS_POW_SEED_LEN, nonce, HS_POW_NONCE_LEN);
|
memcpy(challenge + HS_POW_SEED_LEN, nonce, HS_POW_NONCE_LEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -95,7 +99,7 @@ build_equix_ctx(equix_ctx_flags flags)
|
|||||||
/* Helper: Build EquiX challenge (C || N || INT_32(E)) and return a newly
|
/* Helper: Build EquiX challenge (C || N || INT_32(E)) and return a newly
|
||||||
* allocated buffer containing it. */
|
* allocated buffer containing it. */
|
||||||
static uint8_t *
|
static uint8_t *
|
||||||
build_equix_challenge(const uint8_t *seed, const uint128_t nonce,
|
build_equix_challenge(const uint8_t *seed, const uint8_t *nonce,
|
||||||
const uint32_t effort)
|
const uint32_t effort)
|
||||||
{
|
{
|
||||||
/* Build EquiX challenge (C || N || INT_32(E)). */
|
/* Build EquiX challenge (C || N || INT_32(E)). */
|
||||||
@ -104,7 +108,7 @@ build_equix_challenge(const uint8_t *seed, const uint128_t nonce,
|
|||||||
|
|
||||||
memcpy(challenge, seed, HS_POW_SEED_LEN);
|
memcpy(challenge, seed, HS_POW_SEED_LEN);
|
||||||
offset += HS_POW_SEED_LEN;
|
offset += HS_POW_SEED_LEN;
|
||||||
memcpy(challenge + offset, &nonce, HS_POW_NONCE_LEN);
|
memcpy(challenge + offset, nonce, HS_POW_NONCE_LEN);
|
||||||
offset += HS_POW_NONCE_LEN;
|
offset += HS_POW_NONCE_LEN;
|
||||||
set_uint32(challenge + offset, tor_htonl(effort));
|
set_uint32(challenge + offset, tor_htonl(effort));
|
||||||
offset += HS_POW_EFFORT_LEN;
|
offset += HS_POW_EFFORT_LEN;
|
||||||
@ -146,7 +150,7 @@ hs_pow_solve(const hs_pow_desc_params_t *pow_params,
|
|||||||
hs_pow_solution_t *pow_solution_out)
|
hs_pow_solution_t *pow_solution_out)
|
||||||
{
|
{
|
||||||
int ret = -1;
|
int ret = -1;
|
||||||
uint128_t nonce;
|
uint8_t nonce[HS_POW_NONCE_LEN];
|
||||||
uint8_t *challenge = NULL;
|
uint8_t *challenge = NULL;
|
||||||
equix_ctx *ctx = NULL;
|
equix_ctx *ctx = NULL;
|
||||||
|
|
||||||
@ -157,7 +161,7 @@ hs_pow_solve(const hs_pow_desc_params_t *pow_params,
|
|||||||
uint32_t effort = pow_params->suggested_effort;
|
uint32_t effort = pow_params->suggested_effort;
|
||||||
|
|
||||||
/* Generate a random nonce N. */
|
/* Generate a random nonce N. */
|
||||||
crypto_rand((char *)&nonce, sizeof(uint128_t));
|
crypto_rand((char *)nonce, sizeof nonce);
|
||||||
|
|
||||||
/* Build EquiX challenge (C || N || INT_32(E)). */
|
/* Build EquiX challenge (C || N || INT_32(E)). */
|
||||||
challenge = build_equix_challenge(pow_params->seed, nonce, effort);
|
challenge = build_equix_challenge(pow_params->seed, nonce, effort);
|
||||||
@ -178,7 +182,7 @@ hs_pow_solve(const hs_pow_desc_params_t *pow_params,
|
|||||||
/* Check an Equi-X solution against the effort threshold */
|
/* Check an Equi-X solution against the effort threshold */
|
||||||
if (validate_equix_challenge(challenge, sol, effort)) {
|
if (validate_equix_challenge(challenge, sol, effort)) {
|
||||||
/* Store the nonce N. */
|
/* Store the nonce N. */
|
||||||
pow_solution_out->nonce = nonce;
|
memcpy(pow_solution_out->nonce, nonce, HS_POW_NONCE_LEN);
|
||||||
/* Store the effort E. */
|
/* Store the effort E. */
|
||||||
pow_solution_out->effort = effort;
|
pow_solution_out->effort = effort;
|
||||||
/* We only store the first 4 bytes of the seed C. */
|
/* We only store the first 4 bytes of the seed C. */
|
||||||
@ -195,7 +199,7 @@ hs_pow_solve(const hs_pow_desc_params_t *pow_params,
|
|||||||
|
|
||||||
/* No solutions for this nonce and/or none that passed the effort
|
/* No solutions for this nonce and/or none that passed the effort
|
||||||
* threshold, increment and try again. */
|
* threshold, increment and try again. */
|
||||||
increment_and_set_nonce(&nonce, challenge);
|
increment_and_set_nonce(nonce, challenge);
|
||||||
}
|
}
|
||||||
|
|
||||||
end:
|
end:
|
||||||
@ -243,7 +247,7 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Fail if N = POW_NONCE is present in the replay cache. */
|
/* Fail if N = POW_NONCE is present in the replay cache. */
|
||||||
search.nonce = pow_solution->nonce;
|
memcpy(search.nonce, pow_solution->nonce, HS_POW_NONCE_LEN);
|
||||||
search.seed_head = pow_solution->seed_head;
|
search.seed_head = pow_solution->seed_head;
|
||||||
entry = HT_FIND(nonce_cache_table_ht, &nonce_cache_table, &search);
|
entry = HT_FIND(nonce_cache_table_ht, &nonce_cache_table, &search);
|
||||||
if (entry) {
|
if (entry) {
|
||||||
@ -279,7 +283,7 @@ hs_pow_verify(const hs_pow_service_state_t *pow_state,
|
|||||||
|
|
||||||
/* Add the (nonce, seed) tuple to the replay cache. */
|
/* Add the (nonce, seed) tuple to the replay cache. */
|
||||||
entry = tor_malloc_zero(sizeof(nonce_cache_entry_t));
|
entry = tor_malloc_zero(sizeof(nonce_cache_entry_t));
|
||||||
entry->nonce = pow_solution->nonce;
|
memcpy(entry->nonce, pow_solution->nonce, HS_POW_NONCE_LEN);
|
||||||
entry->seed_head = pow_solution->seed_head;
|
entry->seed_head = pow_solution->seed_head;
|
||||||
HT_INSERT(nonce_cache_table_ht, &nonce_cache_table, entry);
|
HT_INSERT(nonce_cache_table_ht, &nonce_cache_table, entry);
|
||||||
|
|
||||||
|
@ -10,8 +10,6 @@
|
|||||||
#ifndef TOR_HS_POW_H
|
#ifndef TOR_HS_POW_H
|
||||||
#define TOR_HS_POW_H
|
#define TOR_HS_POW_H
|
||||||
|
|
||||||
typedef unsigned __int128 uint128_t;
|
|
||||||
|
|
||||||
#include "ext/equix/include/equix.h"
|
#include "ext/equix/include/equix.h"
|
||||||
|
|
||||||
#include "lib/evloop/compat_libevent.h"
|
#include "lib/evloop/compat_libevent.h"
|
||||||
@ -112,10 +110,8 @@ typedef struct hs_pow_service_state_t {
|
|||||||
|
|
||||||
/* Struct to store a solution to the PoW challenge. */
|
/* Struct to store a solution to the PoW challenge. */
|
||||||
typedef struct hs_pow_solution_t {
|
typedef struct hs_pow_solution_t {
|
||||||
/** HRPR TODO are we best off storing this as a byte array, as trunnel doesnt
|
|
||||||
* support uint128 (?) */
|
|
||||||
/* The 16 byte nonce used in the solution. */
|
/* The 16 byte nonce used in the solution. */
|
||||||
uint128_t nonce;
|
uint8_t nonce[HS_POW_NONCE_LEN];
|
||||||
|
|
||||||
/* The effort used in the solution. */
|
/* The effort used in the solution. */
|
||||||
uint32_t effort;
|
uint32_t effort;
|
||||||
|
@ -48,7 +48,7 @@ testing_one_hs_pow_solution(const hs_pow_solution_t *ref_solution,
|
|||||||
expected = 0;
|
expected = 0;
|
||||||
}
|
}
|
||||||
} else if (variant & 1) {
|
} else if (variant & 1) {
|
||||||
sol_buffer.nonce += variant;
|
sol_buffer.nonce[variant % HS_POW_NONCE_LEN]++;
|
||||||
} else {
|
} else {
|
||||||
sol_buffer.equix_solution.idx[variant % EQUIX_NUM_IDX]++;
|
sol_buffer.equix_solution.idx[variant % EQUIX_NUM_IDX]++;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user