1 /* Copyright (c) 2019-2020, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
6 * \brief Header file containing PoW denial of service defenses for the HS
7 * subsystem for all versions.
13 typedef unsigned __int128 uint128_t
;
15 #include "ext/equix/include/equix.h"
17 #include "lib/evloop/compat_libevent.h"
18 #include "lib/smartlist_core/smartlist_core.h"
20 #define HS_POW_SUGGESTED_EFFORT_DEFAULT 100 // HRPR TODO 5000
21 /* Service updates the suggested effort every HS_UPDATE_PERIOD seconds. */
22 #define HS_UPDATE_PERIOD 300 // HRPR TODO Should be consensus
24 /** Length of random nonce (N) used in the PoW scheme. */
25 #define HS_POW_NONCE_LEN 16
26 /** Length of an E-quiX solution (S) in bytes. */
27 #define HS_POW_EQX_SOL_LEN 16
28 /** Length of blake2b hash result (R) used in the PoW scheme. */
29 #define HS_POW_HASH_LEN 4
30 /** Length of random seed used in the PoW scheme. */
31 #define HS_POW_SEED_LEN 32
32 /** Length of an effort value */
33 #define HS_POW_EFFORT_LEN sizeof(uint32_t)
34 /** Length of a PoW challenge. Construction as per prop327 is:
35 * (C || N || INT_32(E))
37 #define HS_POW_CHALLENGE_LEN \
38 (HS_POW_SEED_LEN + HS_POW_NONCE_LEN + HS_POW_EFFORT_LEN)
40 /** Type of PoW in the descriptor. */
45 /** Proof-of-Work parameters for DoS defense located in a descriptor. */
46 typedef struct hs_pow_desc_params_t
{
47 /** Type of PoW system being used. */
48 hs_pow_desc_type_t type
;
50 /** Random 32-byte seed used as input the the PoW hash function. Decoded? */
51 uint8_t seed
[HS_POW_SEED_LEN
];
53 /** Specifies effort value that clients should aim for when contacting the
55 uint32_t suggested_effort
;
57 /** Timestamp after which the above seed expires. */
58 time_t expiration_time
;
59 } hs_pow_desc_params_t
;
61 /** State and parameters of PoW defenses, stored in the service state. */
62 typedef struct hs_pow_service_state_t
{
63 /* If PoW defenses are enabled this is a priority queue containing acceptable
64 * requests that are awaiting rendezvous circuits to built, where priority is
65 * based on the amount of effort that was exerted in the PoW. */
66 smartlist_t
*rend_request_pqueue
;
68 /* HRPR TODO Is this cursed? Including compat_libevent for this. feb 24 */
69 /* When PoW defenses are enabled, this event pops rendezvous requests from
70 * the service's priority queue; higher effort is higher priority. */
71 mainloop_event_t
*pop_pqueue_ev
;
73 /* The current seed being used in the PoW defenses. */
74 uint8_t seed_current
[HS_POW_SEED_LEN
];
76 /* The previous seed that was used in the PoW defenses. We accept solutions
77 * for both the current and previous seed. */
78 uint8_t seed_previous
[HS_POW_SEED_LEN
];
80 /* The time at which the current seed expires and rotates for a new one. */
81 time_t expiration_time
;
83 /* The minimum effort required for a valid solution. */
86 /* The suggested effort that clients should use in order for their request to
87 * be serviced in a timely manner. */
88 uint32_t suggested_effort
;
90 /* The following values are used when calculating and updating the suggested
91 * effort every HS_UPDATE_PERIOD seconds. */
93 /* Number of intro requests the service can handle per second. */
94 uint32_t svc_bottom_capacity
;
95 /* The next time at which to update the suggested effort. */
96 time_t next_effort_update
;
97 /* Sum of effort of all valid requests received since the last update. */
98 uint64_t total_effort
;
99 } hs_pow_service_state_t
;
101 /* Struct to store a solution to the PoW challenge. */
102 typedef struct hs_pow_solution_t
{
103 /** HRPR TODO are we best off storing this as a byte array, as trunnel doesnt
104 * support uint128 (?) */
105 /* The 16 byte nonce used in the solution. */
108 /* The effort used in the solution. */
111 /* The first four bytes of the seed used in the solution. */
114 /* The Equi-X solution used in the solution. */
115 equix_solution equix_solution
;
119 int hs_pow_solve(const hs_pow_desc_params_t
*pow_params
,
120 hs_pow_solution_t
*pow_solution_out
);
122 int hs_pow_verify(const hs_pow_service_state_t
*pow_state
,
123 const hs_pow_solution_t
*pow_solution
);
125 void hs_pow_remove_seed_from_cache(uint32_t seed
);
127 #endif /* !defined(TOR_HS_POW_H) */