test: Unit test for the hs cache decrypt on new auth

Part of #30382

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2019-06-06 09:36:02 -04:00 committed by George Kadianakis
parent c0dd5324b3
commit 3892ac7c71
5 changed files with 144 additions and 1 deletions

View File

@ -2140,4 +2140,10 @@ get_hs_client_auths_map(void)
return client_auths; return client_auths;
} }
STATIC void
set_hs_client_auths_map(digest256map_t *map)
{
client_auths = map;
}
#endif /* defined(TOR_UNIT_TESTS) */ #endif /* defined(TOR_UNIT_TESTS) */

View File

@ -115,6 +115,7 @@ STATIC void retry_all_socks_conn_waiting_for_desc(void);
#ifdef TOR_UNIT_TESTS #ifdef TOR_UNIT_TESTS
STATIC digest256map_t *get_hs_client_auths_map(void); STATIC digest256map_t *get_hs_client_auths_map(void);
STATIC void set_hs_client_auths_map(digest256map_t *map);
#endif /* defined(TOR_UNIT_TESTS) */ #endif /* defined(TOR_UNIT_TESTS) */

View File

@ -1,12 +1,16 @@
/* Copyright (c) 2017-2019, The Tor Project, Inc. */ /* Copyright (c) 2017-2019, The Tor Project, Inc. */
/* See LICENSE for licensing information */ /* See LICENSE for licensing information */
#define HS_CLIENT_PRIVATE
#include "core/or/or.h" #include "core/or/or.h"
#include "lib/crypt_ops/crypto_ed25519.h" #include "lib/crypt_ops/crypto_ed25519.h"
#include "test/test.h" #include "test/test.h"
#include "feature/nodelist/torcert.h" #include "feature/nodelist/torcert.h"
#include "feature/hs/hs_client.h"
#include "feature/hs/hs_common.h" #include "feature/hs/hs_common.h"
#include "feature/hs/hs_service.h"
#include "test/hs_test_helpers.h" #include "test/hs_test_helpers.h"
hs_desc_intro_point_t * hs_desc_intro_point_t *
@ -207,6 +211,35 @@ hs_helper_build_hs_desc_no_ip(const ed25519_keypair_t *signing_kp)
return hs_helper_build_hs_desc_impl(1, signing_kp); return hs_helper_build_hs_desc_impl(1, signing_kp);
} }
hs_descriptor_t *
hs_helper_build_hs_desc_with_client_auth(
const uint8_t *descriptor_cookie,
const curve25519_public_key_t *client_pk,
const ed25519_keypair_t *signing_kp)
{
curve25519_keypair_t auth_ephemeral_kp;
hs_descriptor_t *desc = hs_helper_build_hs_desc_impl(0, signing_kp);
hs_desc_authorized_client_t *desc_client;
/* The number of client authorized auth has tobe a multiple of
* HS_DESC_AUTH_CLIENT_MULTIPLE so remove one that we'll replace. */
desc_client = smartlist_get(desc->superencrypted_data.clients, 0);
smartlist_remove(desc->superencrypted_data.clients, desc_client);
hs_desc_authorized_client_free(desc_client);
desc_client = tor_malloc_zero(sizeof(hs_desc_authorized_client_t));
curve25519_keypair_generate(&auth_ephemeral_kp, 0);
memcpy(&desc->superencrypted_data.auth_ephemeral_pubkey,
&auth_ephemeral_kp.pubkey, sizeof(curve25519_public_key_t));
hs_desc_build_authorized_client(desc->subcredential, client_pk,
&auth_ephemeral_kp.seckey,
descriptor_cookie, desc_client);
smartlist_add(desc->superencrypted_data.clients, desc_client);
return desc;
}
void void
hs_helper_desc_equal(const hs_descriptor_t *desc1, hs_helper_desc_equal(const hs_descriptor_t *desc1,
const hs_descriptor_t *desc2) const hs_descriptor_t *desc2)
@ -353,3 +386,19 @@ hs_helper_desc_equal(const hs_descriptor_t *desc1,
; ;
} }
void
hs_helper_add_client_auth(const ed25519_public_key_t *service_pk,
const curve25519_secret_key_t *client_sk)
{
digest256map_t *client_auths = get_hs_client_auths_map();
if (client_auths == NULL) {
client_auths = digest256map_new();
set_hs_client_auths_map(client_auths);
}
hs_client_service_authorization_t *auth =
tor_malloc_zero(sizeof(hs_client_service_authorization_t));
memcpy(&auth->enc_seckey, client_sk, sizeof(curve25519_secret_key_t));
hs_build_address(service_pk, HS_VERSION_THREE, auth->onion_address);
digest256map_set(client_auths, service_pk->pubkey, auth);
}

View File

@ -15,11 +15,18 @@ hs_descriptor_t *hs_helper_build_hs_desc_no_ip(
const ed25519_keypair_t *signing_kp); const ed25519_keypair_t *signing_kp);
hs_descriptor_t *hs_helper_build_hs_desc_with_ip( hs_descriptor_t *hs_helper_build_hs_desc_with_ip(
const ed25519_keypair_t *signing_kp); const ed25519_keypair_t *signing_kp);
hs_descriptor_t *hs_helper_build_hs_desc_with_client_auth(
const uint8_t *descriptor_cookie,
const curve25519_public_key_t *client_pk,
const ed25519_keypair_t *signing_kp);
void hs_helper_desc_equal(const hs_descriptor_t *desc1, void hs_helper_desc_equal(const hs_descriptor_t *desc1,
const hs_descriptor_t *desc2); const hs_descriptor_t *desc2);
void void
hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp, hs_helper_get_subcred_from_identity_keypair(ed25519_keypair_t *signing_kp,
uint8_t *subcred_out); uint8_t *subcred_out);
void hs_helper_add_client_auth(const ed25519_public_key_t *service_pk,
const curve25519_secret_key_t *client_sk);
#endif /* !defined(TOR_HS_TEST_HELPERS_H) */ #endif /* !defined(TOR_HS_TEST_HELPERS_H) */

View File

@ -20,9 +20,10 @@
#include "feature/nodelist/networkstatus.h" #include "feature/nodelist/networkstatus.h"
#include "core/mainloop/connection.h" #include "core/mainloop/connection.h"
#include "core/proto/proto_http.h" #include "core/proto/proto_http.h"
#include "lib/crypt_ops/crypto_format.h"
#include "core/or/circuitlist.h" #include "core/or/circuitlist.h"
#include "core/or/channel.h" #include "core/or/channel.h"
#include "lib/crypt_ops/crypto_format.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/edge_connection_st.h" #include "core/or/edge_connection_st.h"
#include "core/or/or_circuit_st.h" #include "core/or/or_circuit_st.h"
@ -567,6 +568,83 @@ test_client_cache(void *arg)
} }
} }
/** Test that we can store HS descriptors in the client HS cache. */
static void
test_client_cache_decrypt(void *arg)
{
int ret;
char *desc_encoded = NULL;
uint8_t descriptor_cookie[HS_DESC_DESCRIPTOR_COOKIE_LEN];
curve25519_keypair_t client_kp;
ed25519_keypair_t service_kp;
hs_descriptor_t *desc = NULL;
const hs_descriptor_t *search_desc;
const char *search_desc_encoded;
(void) arg;
/* Initialize HSDir cache subsystem */
hs_init();
MOCK(networkstatus_get_live_consensus,
mock_networkstatus_get_live_consensus);
/* Set consensus time */
parse_rfc1123_time("Sat, 26 Oct 1985 13:00:00 UTC",
&mock_ns.valid_after);
parse_rfc1123_time("Sat, 26 Oct 1985 14:00:00 UTC",
&mock_ns.fresh_until);
parse_rfc1123_time("Sat, 26 Oct 1985 16:00:00 UTC",
&mock_ns.valid_until);
/* Generate a valid descriptor with normal values. */
{
ret = ed25519_keypair_generate(&service_kp, 0);
tt_int_op(ret, OP_EQ, 0);
ret = curve25519_keypair_generate(&client_kp, 0);
tt_int_op(ret, OP_EQ, 0);
crypto_rand((char *) descriptor_cookie, sizeof(descriptor_cookie));
desc = hs_helper_build_hs_desc_with_client_auth(descriptor_cookie,
&client_kp.pubkey,
&service_kp);
tt_assert(desc);
ret = hs_desc_encode_descriptor(desc, &service_kp, descriptor_cookie,
&desc_encoded);
tt_int_op(ret, OP_EQ, 0);
}
/* Put it in the cache. Should not be decrypted since the client
* authorization creds were not added to the global map. */
ret = hs_cache_store_as_client(desc_encoded, &service_kp.pubkey);
tt_int_op(ret, OP_EQ, HS_DESC_DECODE_NEED_CLIENT_AUTH);
/* We should not be able to decrypt anything. */
ret = hs_cache_client_new_auth_parse(&service_kp.pubkey);
tt_int_op(ret, OP_EQ, false);
/* Add client auth to global map. */
hs_helper_add_client_auth(&service_kp.pubkey, &client_kp.seckey);
/* We should not be able to decrypt anything. */
ret = hs_cache_client_new_auth_parse(&service_kp.pubkey);
tt_int_op(ret, OP_EQ, true);
/* Lookup the cache to make sure it is usable and there. */
search_desc = hs_cache_lookup_as_client(&service_kp.pubkey);
tt_assert(search_desc);
search_desc_encoded = hs_cache_lookup_encoded_as_client(&service_kp.pubkey);
tt_mem_op(search_desc_encoded, OP_EQ, desc_encoded, strlen(desc_encoded));
done:
hs_descriptor_free(desc);
tor_free(desc_encoded);
hs_free_all();
UNMOCK(networkstatus_get_live_consensus);
}
struct testcase_t hs_cache[] = { struct testcase_t hs_cache[] = {
/* Encoding tests. */ /* Encoding tests. */
{ "directory", test_directory, TT_FORK, { "directory", test_directory, TT_FORK,
@ -579,6 +657,8 @@ struct testcase_t hs_cache[] = {
NULL, NULL }, NULL, NULL },
{ "client_cache", test_client_cache, TT_FORK, { "client_cache", test_client_cache, TT_FORK,
NULL, NULL }, NULL, NULL },
{ "client_cache_decrypt", test_client_cache_decrypt, TT_FORK,
NULL, NULL },
END_OF_TESTCASES END_OF_TESTCASES
}; };