commit ff249ee4a6ea665bb7ed1c7ab53d4d6b0eb9db78 Author: George Kadianakis desnacked@riseup.net Date: Tue Aug 8 11:45:45 2017 +0300
Start caching disaster SRV values.
Also add some unittests. --- src/or/hs_common.c | 56 ++++++++++++++++++++++++++++++++++++++++++++++- src/or/hs_common.h | 5 +++++ src/test/test_hs_common.c | 53 +++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 112 insertions(+), 2 deletions(-)
diff --git a/src/or/hs_common.c b/src/or/hs_common.c index 62cda34bd..2b637eb78 100644 --- a/src/or/hs_common.c +++ b/src/or/hs_common.c @@ -503,7 +503,7 @@ rend_data_get_pk_digest(const rend_data_t *rend_data, size_t *len_out) /* Using the given time period number, compute the disaster shared random * value and put it in srv_out. It MUST be at least DIGEST256_LEN bytes. */ static void -get_disaster_srv(uint64_t time_period_num, uint8_t *srv_out) +compute_disaster_srv(uint64_t time_period_num, uint8_t *srv_out) { crypto_digest_t *digest;
@@ -534,6 +534,60 @@ get_disaster_srv(uint64_t time_period_num, uint8_t *srv_out) crypto_digest_free(digest); }
+/** Due to the high cost of computing the disaster SRV and that potentially we + * would have to do it thousands of times in a row, we always cache the + * computer disaster SRV (and its corresponding time period num) in case we + * want to reuse it soon after. We need to cache two SRVs, one for each active + * time period (in case of overlap mode). + */ +static uint8_t cached_disaster_srv[2][DIGEST256_LEN]; +static uint64_t cached_time_period_nums[2] = {0}; + +/** Compute the disaster SRV value for this <b>time_period_num</b> and put it + * in <b>srv_out</b> (of size at least DIGEST256_LEN). First check our caches + * to see if we have already computed it. */ +STATIC void +get_disaster_srv(uint64_t time_period_num, uint8_t *srv_out) +{ + if (time_period_num == cached_time_period_nums[0]) { + memcpy(srv_out, cached_disaster_srv[0], DIGEST256_LEN); + return; + } else if (time_period_num == cached_time_period_nums[1]) { + memcpy(srv_out, cached_disaster_srv[1], DIGEST256_LEN); + return; + } else { + int replace_idx; + // Replace the lower period number. + if (cached_time_period_nums[0] <= cached_time_period_nums[1]) { + replace_idx = 0; + } else { + replace_idx = 1; + } + cached_time_period_nums[replace_idx] = time_period_num; + compute_disaster_srv(time_period_num, cached_disaster_srv[replace_idx]); + memcpy(srv_out, cached_disaster_srv[replace_idx], DIGEST256_LEN); + return; + } +} + +#ifdef TOR_UNIT_TESTS + +/** Get the first cached disaster SRV. Only used by unittests. */ +STATIC uint8_t * +get_first_cached_disaster_srv(void) +{ + return cached_disaster_srv[0]; +} + +/** Get the second cached disaster SRV. Only used by unittests. */ +STATIC uint8_t * +get_second_cached_disaster_srv(void) +{ + return cached_disaster_srv[1]; +} + +#endif + /* When creating a blinded key, we need a parameter which construction is as * follow: H(pubkey | [secret] | ed25519-basepoint | nonce). * diff --git a/src/or/hs_common.h b/src/or/hs_common.h index 7e37f81e5..5004e0208 100644 --- a/src/or/hs_common.h +++ b/src/or/hs_common.h @@ -224,10 +224,15 @@ int hs_set_conn_addr_port(const smartlist_t *ports, edge_connection_t *conn);
#ifdef HS_COMMON_PRIVATE
+STATIC void get_disaster_srv(uint64_t time_period_num, uint8_t *srv_out); + #ifdef TOR_UNIT_TESTS
STATIC uint64_t get_time_period_length(void);
+STATIC uint8_t *get_first_cached_disaster_srv(void); +STATIC uint8_t *get_second_cached_disaster_srv(void); + #endif /* TOR_UNIT_TESTS */
#endif /* HS_COMMON_PRIVATE */ diff --git a/src/test/test_hs_common.c b/src/test/test_hs_common.c index 3041d24a6..d79d80bfa 100644 --- a/src/test/test_hs_common.c +++ b/src/test/test_hs_common.c @@ -434,6 +434,57 @@ test_responsible_hsdirs(void *arg) networkstatus_vote_free(mock_ns); }
+/** Test disaster SRV computation and caching */ +static void +test_disaster_srv(void *arg) +{ + uint8_t *cached_disaster_srv_one = NULL; + uint8_t *cached_disaster_srv_two = NULL; + uint8_t srv_one[DIGEST256_LEN] = {0}; + uint8_t srv_two[DIGEST256_LEN] = {0}; + uint8_t srv_three[DIGEST256_LEN] = {0}; + uint8_t srv_four[DIGEST256_LEN] = {0}; + uint8_t srv_five[DIGEST256_LEN] = {0}; + + (void) arg; + + /* Get the cached SRVs: we gonna use them later for verification */ + cached_disaster_srv_one = get_first_cached_disaster_srv(); + cached_disaster_srv_two = get_second_cached_disaster_srv(); + + /* Compute some srvs */ + get_disaster_srv(1, srv_one); + get_disaster_srv(2, srv_two); + + /* Check that the cached ones where updated */ + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_one, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_two, DIGEST256_LEN); + + /* Ask for an SRV that has already been computed */ + get_disaster_srv(2, srv_two); + /* and check that the cache entries have not changed */ + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_one, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_two, DIGEST256_LEN); + + /* Ask for a new SRV */ + get_disaster_srv(3, srv_three); + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_three, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_two, DIGEST256_LEN); + + /* Ask for another SRV: none of the original SRVs should now be cached */ + get_disaster_srv(4, srv_four); + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_three, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_four, DIGEST256_LEN); + + /* Ask for yet another SRV */ + get_disaster_srv(5, srv_five); + tt_mem_op(cached_disaster_srv_one, OP_EQ, srv_five, DIGEST256_LEN); + tt_mem_op(cached_disaster_srv_two, OP_EQ, srv_four, DIGEST256_LEN); + + done: + ; +} + struct testcase_t hs_common_tests[] = { { "build_address", test_build_address, TT_FORK, NULL, NULL }, @@ -449,7 +500,7 @@ struct testcase_t hs_common_tests[] = { NULL, NULL }, { "desc_responsible_hsdirs", test_responsible_hsdirs, TT_FORK, NULL, NULL }, - + { "disaster_srv", test_disaster_srv, TT_FORK, NULL, NULL },
END_OF_TESTCASES };