mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-30 23:53:32 +01:00
Merge remote-tracking branch 'asn/ticket23420_032_01'
This commit is contained in:
commit
777e828ef3
4
changes/ticket23420
Normal file
4
changes/ticket23420
Normal file
@ -0,0 +1,4 @@
|
||||
o Minor bugfixes (hidden service v3):
|
||||
- Pad RENDEZVOUS cell up to the size of the legacy cell which is much
|
||||
bigger so the rendezvous point can't distinguish which hidden service
|
||||
protocol is being used. Fixes ticket 23420.; bugfix on 0.3.2.1-alpha.
|
@ -5,6 +5,8 @@
|
||||
* \file hs_circuit.c
|
||||
**/
|
||||
|
||||
#define HS_CIRCUIT_PRIVATE
|
||||
|
||||
#include "or.h"
|
||||
#include "circpathbias.h"
|
||||
#include "circuitbuild.h"
|
||||
@ -18,10 +20,10 @@
|
||||
#include "router.h"
|
||||
|
||||
#include "hs_cell.h"
|
||||
#include "hs_circuit.h"
|
||||
#include "hs_ident.h"
|
||||
#include "hs_ntor.h"
|
||||
#include "hs_service.h"
|
||||
#include "hs_circuit.h"
|
||||
|
||||
/* Trunnel. */
|
||||
#include "ed25519_cert.h"
|
||||
@ -235,7 +237,7 @@ count_opened_desc_intro_point_circuits(const hs_service_t *service,
|
||||
|
||||
/* From a given service, rendezvous cookie and handshake info, create a
|
||||
* rendezvous point circuit identifier. This can't fail. */
|
||||
static hs_ident_circuit_t *
|
||||
STATIC hs_ident_circuit_t *
|
||||
create_rp_circuit_identifier(const hs_service_t *service,
|
||||
const uint8_t *rendezvous_cookie,
|
||||
const curve25519_public_key_t *server_pk,
|
||||
@ -820,6 +822,15 @@ hs_circ_service_rp_has_opened(const hs_service_t *service,
|
||||
sizeof(circ->hs_ident->rendezvous_handshake_info),
|
||||
payload);
|
||||
|
||||
/* Pad the payload with random bytes so it matches the size of a legacy cell
|
||||
* which is normally always bigger. Also, the size of a legacy cell is
|
||||
* always smaller than the RELAY_PAYLOAD_SIZE so this is safe. */
|
||||
if (payload_len < HS_LEGACY_RENDEZVOUS_CELL_SIZE) {
|
||||
crypto_rand((char *) payload + payload_len,
|
||||
HS_LEGACY_RENDEZVOUS_CELL_SIZE - payload_len);
|
||||
payload_len = HS_LEGACY_RENDEZVOUS_CELL_SIZE;
|
||||
}
|
||||
|
||||
if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
|
||||
RELAY_COMMAND_RENDEZVOUS1,
|
||||
(const char *) payload, payload_len,
|
||||
|
@ -59,5 +59,15 @@ int hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ,
|
||||
int hs_circuit_setup_e2e_rend_circ_legacy_client(origin_circuit_t *circ,
|
||||
const uint8_t *rend_cell_body);
|
||||
|
||||
#ifdef HS_CIRCUIT_PRIVATE
|
||||
|
||||
STATIC hs_ident_circuit_t *
|
||||
create_rp_circuit_identifier(const hs_service_t *service,
|
||||
const uint8_t *rendezvous_cookie,
|
||||
const curve25519_public_key_t *server_pk,
|
||||
const hs_ntor_rend_cell_keys_t *keys);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* !defined(TOR_HS_CIRCUIT_H) */
|
||||
|
||||
|
@ -845,7 +845,7 @@ handle_introduce_ack(origin_circuit_t *circ, const uint8_t *payload,
|
||||
/* Called when we get a RENDEZVOUS2 cell on the rendezvous circuit circ. The
|
||||
* encoded cell is in payload of length payload_len. Return 0 on success or a
|
||||
* negative value on error. On error, the circuit is marked for close. */
|
||||
static int
|
||||
STATIC int
|
||||
handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
|
||||
size_t payload_len)
|
||||
{
|
||||
|
@ -77,6 +77,9 @@ client_get_random_intro(const ed25519_public_key_t *service_pk);
|
||||
STATIC extend_info_t *
|
||||
desc_intro_point_to_extend_info(const hs_desc_intro_point_t *ip);
|
||||
|
||||
STATIC int handle_rendezvous2(origin_circuit_t *circ, const uint8_t *payload,
|
||||
size_t payload_len);
|
||||
|
||||
#endif /* defined(HS_CLIENT_PRIVATE) */
|
||||
|
||||
#endif /* !defined(TOR_HS_CLIENT_H) */
|
||||
|
@ -118,6 +118,12 @@
|
||||
/* Default value of hsdir spread fetch (hsdir_spread_fetch). */
|
||||
#define HS_DEFAULT_HSDIR_SPREAD_FETCH 3
|
||||
|
||||
/* The size of a legacy RENDEZVOUS1 cell which adds up to 168 bytes. It is
|
||||
* bigger than the 84 bytes needed for version 3 so we need to pad up to that
|
||||
* length so it is indistinguishable between versions. */
|
||||
#define HS_LEGACY_RENDEZVOUS_CELL_SIZE \
|
||||
(REND_COOKIE_LEN + DH_KEY_LEN + DIGEST_LEN)
|
||||
|
||||
/* Type of authentication key used by an introduction point. */
|
||||
typedef enum {
|
||||
HS_AUTH_KEY_TYPE_LEGACY = 1,
|
||||
|
@ -3398,7 +3398,7 @@ rend_service_rendezvous_has_opened(origin_circuit_t *circuit)
|
||||
/* Send the cell */
|
||||
if (relay_send_command_from_edge(0, TO_CIRCUIT(circuit),
|
||||
RELAY_COMMAND_RENDEZVOUS1,
|
||||
buf, REND_COOKIE_LEN+DH_KEY_LEN+DIGEST_LEN,
|
||||
buf, HS_LEGACY_RENDEZVOUS_CELL_SIZE,
|
||||
circuit->cpath->prev)<0) {
|
||||
log_warn(LD_GENERAL, "Couldn't send RENDEZVOUS1 cell.");
|
||||
goto done;
|
||||
|
@ -14,10 +14,12 @@
|
||||
#define HS_COMMON_PRIVATE
|
||||
#define HS_SERVICE_PRIVATE
|
||||
#define HS_INTROPOINT_PRIVATE
|
||||
#define HS_CIRCUIT_PRIVATE
|
||||
#define MAIN_PRIVATE
|
||||
#define NETWORKSTATUS_PRIVATE
|
||||
#define STATEFILE_PRIVATE
|
||||
#define TOR_CHANNEL_INTERNAL_
|
||||
#define HS_CLIENT_PRIVATE
|
||||
|
||||
#include "test.h"
|
||||
#include "test_helpers.h"
|
||||
@ -37,11 +39,12 @@
|
||||
|
||||
#include "hs_common.h"
|
||||
#include "hs_config.h"
|
||||
#include "hs_circuit.h"
|
||||
#include "hs_ident.h"
|
||||
#include "hs_intropoint.h"
|
||||
#include "hs_ntor.h"
|
||||
#include "hs_circuit.h"
|
||||
#include "hs_service.h"
|
||||
#include "hs_client.h"
|
||||
#include "main.h"
|
||||
#include "rendservice.h"
|
||||
#include "statefile.h"
|
||||
@ -1366,6 +1369,130 @@ test_revision_counter_state(void *arg)
|
||||
service_descriptor_free(desc_two);
|
||||
}
|
||||
|
||||
/** Global vars used by test_rendezvous1_parsing() */
|
||||
char rend1_payload[RELAY_PAYLOAD_SIZE];
|
||||
size_t rend1_payload_len = 0;
|
||||
|
||||
/** Mock for relay_send_command_from_edge() to send a RENDEZVOUS1 cell. Instead
|
||||
* of sending it to the network, instead save it to the global `rend1_payload`
|
||||
* variable so that we can inspect it in the test_rendezvous1_parsing()
|
||||
* test. */
|
||||
static int
|
||||
mock_relay_send_rendezvous1(streamid_t stream_id, circuit_t *circ,
|
||||
uint8_t relay_command, const char *payload,
|
||||
size_t payload_len,
|
||||
crypt_path_t *cpath_layer,
|
||||
const char *filename, int lineno)
|
||||
{
|
||||
(void) stream_id;
|
||||
(void) circ;
|
||||
(void) relay_command;
|
||||
(void) cpath_layer;
|
||||
(void) filename;
|
||||
(void) lineno;
|
||||
|
||||
memcpy(rend1_payload, payload, payload_len);
|
||||
rend1_payload_len = payload_len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** Send a RENDEZVOUS1 as a service, and parse it as a client. */
|
||||
static void
|
||||
test_rendezvous1_parsing(void *arg)
|
||||
{
|
||||
int retval;
|
||||
static const char *test_addr =
|
||||
"4acth47i6kxnvkewtm6q7ib2s3ufpo5sqbsnzjpbi7utijcltosqemad.onion";
|
||||
hs_service_t *service = NULL;
|
||||
origin_circuit_t *service_circ = NULL;
|
||||
origin_circuit_t *client_circ = NULL;
|
||||
ed25519_keypair_t ip_auth_kp;
|
||||
curve25519_keypair_t ephemeral_kp;
|
||||
curve25519_keypair_t client_kp;
|
||||
curve25519_keypair_t ip_enc_kp;
|
||||
int flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
|
||||
|
||||
(void) arg;
|
||||
|
||||
MOCK(relay_send_command_from_edge_, mock_relay_send_rendezvous1);
|
||||
|
||||
{
|
||||
/* Let's start by setting up the service that will start the rend */
|
||||
service = tor_malloc_zero(sizeof(hs_service_t));
|
||||
ed25519_secret_key_generate(&service->keys.identity_sk, 0);
|
||||
ed25519_public_key_generate(&service->keys.identity_pk,
|
||||
&service->keys.identity_sk);
|
||||
memcpy(service->onion_address, test_addr, sizeof(service->onion_address));
|
||||
tt_assert(service);
|
||||
}
|
||||
|
||||
{
|
||||
/* Now let's set up the service rendezvous circuit and its keys. */
|
||||
service_circ = helper_create_origin_circuit(CIRCUIT_PURPOSE_S_CONNECT_REND,
|
||||
flags);
|
||||
tor_free(service_circ->hs_ident);
|
||||
hs_ntor_rend_cell_keys_t hs_ntor_rend_cell_keys;
|
||||
uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN];
|
||||
curve25519_keypair_generate(&ip_enc_kp, 0);
|
||||
curve25519_keypair_generate(&ephemeral_kp, 0);
|
||||
curve25519_keypair_generate(&client_kp, 0);
|
||||
ed25519_keypair_generate(&ip_auth_kp, 0);
|
||||
retval = hs_ntor_service_get_rendezvous1_keys(&ip_auth_kp.pubkey,
|
||||
&ip_enc_kp,
|
||||
&ephemeral_kp,
|
||||
&client_kp.pubkey,
|
||||
&hs_ntor_rend_cell_keys);
|
||||
tt_int_op(retval, OP_EQ, 0);
|
||||
|
||||
memset(rendezvous_cookie, 2, sizeof(rendezvous_cookie));
|
||||
service_circ->hs_ident =
|
||||
create_rp_circuit_identifier(service, rendezvous_cookie,
|
||||
&ephemeral_kp.pubkey,
|
||||
&hs_ntor_rend_cell_keys);
|
||||
}
|
||||
|
||||
/* Send out the RENDEZVOUS1 and make sure that our mock func worked */
|
||||
tt_assert(tor_mem_is_zero(rend1_payload, 32));
|
||||
hs_circ_service_rp_has_opened(service, service_circ);
|
||||
tt_assert(!tor_mem_is_zero(rend1_payload, 32));
|
||||
tt_int_op(rend1_payload_len, OP_EQ, HS_LEGACY_RENDEZVOUS_CELL_SIZE);
|
||||
|
||||
/******************************/
|
||||
|
||||
/** Now let's create the client rendezvous circuit */
|
||||
client_circ =
|
||||
helper_create_origin_circuit(CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED,
|
||||
flags);
|
||||
/* fix up its circ ident */
|
||||
ed25519_pubkey_copy(&client_circ->hs_ident->intro_auth_pk,
|
||||
&ip_auth_kp.pubkey);
|
||||
memcpy(&client_circ->hs_ident->rendezvous_client_kp,
|
||||
&client_kp, sizeof(client_circ->hs_ident->rendezvous_client_kp));
|
||||
memcpy(&client_circ->hs_ident->intro_enc_pk.public_key,
|
||||
&ip_enc_kp.pubkey.public_key,
|
||||
sizeof(client_circ->hs_ident->intro_enc_pk.public_key));
|
||||
|
||||
/* Now parse the rendezvous2 circuit and make sure it was fine. We are
|
||||
* skipping 20 bytes off its payload, since that's the rendezvous cookie
|
||||
* which is only present in REND1. */
|
||||
retval = handle_rendezvous2(client_circ,
|
||||
(uint8_t*)rend1_payload+20,
|
||||
rend1_payload_len-20);
|
||||
tt_int_op(retval, OP_EQ, 0);
|
||||
|
||||
/* TODO: We are only simulating client/service here. We could also simulate
|
||||
* the rendezvous point by plugging in rend_mid_establish_rendezvous(). We
|
||||
* would need an extra circuit and some more stuff but it's doable. */
|
||||
|
||||
done:
|
||||
circuit_free(TO_CIRCUIT(service_circ));
|
||||
circuit_free(TO_CIRCUIT(client_circ));
|
||||
hs_service_free(service);
|
||||
hs_free_all();
|
||||
UNMOCK(relay_send_command_from_edge_);
|
||||
}
|
||||
|
||||
struct testcase_t hs_service_tests[] = {
|
||||
{ "e2e_rend_circuit_setup", test_e2e_rend_circuit_setup, TT_FORK,
|
||||
NULL, NULL },
|
||||
@ -1395,6 +1522,8 @@ struct testcase_t hs_service_tests[] = {
|
||||
NULL, NULL },
|
||||
{ "revision_counter_state", test_revision_counter_state, TT_FORK,
|
||||
NULL, NULL },
|
||||
{ "rendezvous1_parsing", test_rendezvous1_parsing, TT_FORK,
|
||||
NULL, NULL },
|
||||
|
||||
END_OF_TESTCASES
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user