8 #define HS_CIRCUIT_PRIVATE
20 #include "feature/client/circpathbias.h"
37 #include "trunnel/ed25519_cert.h"
38 #include "trunnel/hs/cell_common.h"
39 #include "trunnel/hs/cell_establish_intro.h"
53 if (is_service_side) {
56 "HS e2e circuit setup with wrong purpose (%d)", circ_purpose);
61 if (!is_service_side) {
65 "Client e2e circuit setup with wrong purpose (%d)", circ_purpose);
83 uint8_t keys[HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN];
88 keys,
sizeof(keys)) < 0) {
94 cpath->magic = CRYPT_PATH_MAGIC;
97 is_service_side, 1) < 0) {
103 memwipe(keys, 0,
sizeof(keys));
117 int new_circ_purpose = is_service_side ?
122 hop->
state = CPATH_STATE_OPEN;
136 if (!is_service_side) {
160 unsigned int count = 0;
182 } DIGEST256MAP_FOREACH_END;
190 const uint8_t *rendezvous_cookie,
214 sizeof(handshake_info));
219 sizeof(keys->ntor_key_seed));
260 &service->
config, ip, payload);
262 log_warn(
LD_REND,
"Unable to encode ESTABLISH_INTRO cell for service %s "
263 "on circuit %u. Closing circuit.",
270 if (relay_send_command_from_edge(CONTROL_CELL_ID,
TO_CIRCUIT(circ),
271 RELAY_COMMAND_ESTABLISH_INTRO,
272 (
char *) payload, cell_len,
274 log_info(
LD_REND,
"Unable to send ESTABLISH_INTRO cell for service %s "
287 circuit_mark_for_close(
TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
289 memwipe(payload, 0,
sizeof(payload));
297 return "single onion";
313 int circ_needs_uptime;
314 time_t now = time(NULL);
332 "Not enough info to open a circuit to a rendezvous point for "
341 if (circ_needs_uptime) {
361 log_warn(
LD_REND,
"Giving up on launching a rendezvous circuit to %s "
371 log_info(
LD_REND,
"Rendezvous circuit launched to %s with cookie %s "
391 if (hs_ntor_service_get_rendezvous1_keys(&ip->
auth_key_kp.pubkey,
397 log_info(
LD_REND,
"Unable to get RENDEZVOUS1 key material for "
400 circuit_mark_for_close(
TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
405 &ephemeral_kp.pubkey, &keys);
406 memwipe(&ephemeral_kp, 0,
sizeof(ephemeral_kp));
407 memwipe(&keys, 0,
sizeof(keys));
412 extend_info_free(info);
430 log_info(
LD_REND,
"Rendezvous circuit to %s has already been retried. "
446 log_info(
LD_REND,
"Attempt to build a rendezvous circuit to %s has "
447 "failed with %d attempts and expiry time %ld. "
448 "Giving up building.",
478 log_info(
LD_REND,
"Retrying rendezvous point circuit to %s",
495 if (new_circ == NULL) {
496 log_warn(
LD_REND,
"Failed to launch rendezvous circuit to %s",
535 rp_lspecs = node_get_link_specifier_smartlist(rp_node, 0);
536 if (smartlist_len(rp_lspecs) == 0) {
538 smartlist_free(rp_lspecs);
549 if (intro1_data->
onion_pk == NULL) {
689 log_info(
LD_REND,
"Launching a circuit to intro point %s for service %s.",
727 unsigned int num_intro_circ, num_needed_circ;
738 if (num_intro_circ > num_needed_circ) {
747 log_info(
LD_CIRC |
LD_REND,
"Introduction circuit just opened but we "
748 "have enough for service %s. Repurposing "
749 "it to general and leaving internal.",
755 hs_ident_circuit_free(circ->
hs_ident);
771 log_info(
LD_REND,
"Introduction circuit %u established for service %s.",
800 log_info(
LD_REND,
"Rendezvous circuit %u has opened with cookie %s "
825 if (relay_send_command_from_edge(CONTROL_CELL_ID,
TO_CIRCUIT(circ),
826 RELAY_COMMAND_RENDEZVOUS1,
827 (
const char *) payload, payload_len,
830 log_warn(
LD_REND,
"Unable to send RENDEZVOUS1 cell on circuit %u "
847 memwipe(payload, 0,
sizeof(payload));
858 const uint8_t *payload,
size_t payload_len)
874 log_warn(
LD_REND,
"Unable to parse the INTRO_ESTABLISHED cell on "
875 "circuit %u for service %s",
918 if (BUG(!service->
state.ob_subcreds)) {
938 const uint8_t *payload,
size_t payload_len)
960 &data, subcredential)) {
979 log_info(
LD_REND,
"We received an INTRODUCE2 cell with same REND_COOKIE "
980 "field %ld seconds ago. Dropping cell.",
996 memwipe(&data, 0,
sizeof(data));
1009 const uint8_t *ntor_key_seed,
size_t seed_len,
1010 int is_service_side)
1013 is_service_side))) {
1020 log_warn(
LD_REND,
"Couldn't get v3 %s cpath!",
1021 is_service_side ?
"service-side" :
"client-side");
1045 ssize_t payload_len;
1062 if (exit_node == NULL) {
1063 log_info(
LD_REND,
"Unable to get rendezvous point for circuit %u. "
1064 "Failing.",
TO_CIRCUIT(intro_circ)->n_circ_id);
1071 log_info(
LD_REND,
"Unable to setup INTRODUCE1 data. The chosen rendezvous "
1072 "point is unusable. Closing circuit.");
1089 if (BUG(payload_len < 0)) {
1093 if (relay_send_command_from_edge(CONTROL_CELL_ID,
TO_CIRCUIT(intro_circ),
1094 RELAY_COMMAND_INTRODUCE1,
1095 (
const char *) payload, payload_len,
1098 log_warn(
LD_REND,
"Unable to send INTRODUCE1 cell on circuit %u.",
1108 circuit_mark_for_close(
TO_CIRCUIT(rend_circ), END_CIRC_REASON_INTERNAL);
1111 memwipe(payload, 0,
sizeof(payload));
1120 ssize_t cell_len = 0;
1126 log_info(
LD_REND,
"Send an ESTABLISH_RENDEZVOUS cell on circuit %u",
1131 TO_CIRCUIT(circ)->timestamp_dirty = time(NULL);
1145 if (BUG(cell_len < 0)) {
1149 if (relay_send_command_from_edge(CONTROL_CELL_ID,
TO_CIRCUIT(circ),
1150 RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
1151 (
const char *) cell, cell_len,
1154 log_warn(
LD_REND,
"Unable to send ESTABLISH_RENDEZVOUS cell on "
const char * hex_str(const char *from, size_t fromlen)
void pathbias_count_use_attempt(origin_circuit_t *circ)
void pathbias_mark_use_success(origin_circuit_t *circ)
void circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
const node_t * build_state_get_exit_node(cpath_build_state_t *state)
Header file for circuitbuild.c.
int32_t circuit_initial_package_window(void)
Header file for circuitlist.c.
#define CIRCUIT_PURPOSE_S_CONNECT_REND
#define CIRCUIT_STATE_OPEN
#define CIRCUIT_PURPOSE_C_REND_JOINED
#define CIRCUIT_PURPOSE_S_INTRO
#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED
#define CIRCUIT_PURPOSE_S_REND_JOINED
#define CIRCUIT_PURPOSE_C_REND_READY
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND
#define CIRCUIT_PURPOSE_C_GENERAL
#define CIRCUIT_PURPOSE_HS_VANGUARDS
bool circuit_is_hs_v3(const circuit_t *circ)
bool circuit_purpose_is_hs_service(const uint8_t purpose)
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
int circuit_should_use_vanguards(uint8_t purpose)
void circuit_has_opened(origin_circuit_t *circ)
bool circuit_purpose_is_hs_client(const uint8_t purpose)
origin_circuit_t * circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info, int flags)
void circuit_try_attaching_streams(origin_circuit_t *circ)
Header file for circuituse.c.
#define CIRCLAUNCH_NEED_CAPACITY
#define CIRCLAUNCH_ONEHOP_TUNNEL
#define CIRCLAUNCH_IS_INTERNAL
#define CIRCLAUNCH_NEED_UPTIME
Header file for config.c.
Circuit-build-stse structure.
int cpath_init_circuit_crypto(crypt_path_t *cpath, const char *key_data, size_t key_data_len, int reverse, int is_hs_v3)
void cpath_extend_linked_list(crypt_path_t **head_ptr, crypt_path_t *new_hop)
Header file for crypt_path.c.
Path structures for origin circuits.
int curve25519_keypair_generate(curve25519_keypair_t *keypair_out, int extra_strong)
int curve25519_public_key_is_ok(const curve25519_public_key_t *key)
void ed25519_pubkey_copy(ed25519_public_key_t *dest, const ed25519_public_key_t *src)
int ed25519_pubkey_eq(const ed25519_public_key_t *key1, const ed25519_public_key_t *key2)
void crypto_rand(char *to, size_t n)
Common functions for using (pseudo-)random number generators.
void memwipe(void *mem, uint8_t byte, size_t sz)
Common functions for cryptographic routines.
const char * extend_info_describe(const extend_info_t *ei)
Header file for describe.c.
Header for core/or/extendinfo.c.
ssize_t hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie, uint8_t *cell_out)
ssize_t hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
ssize_t hs_cell_build_establish_intro(const char *circ_nonce, const hs_service_config_t *service_config, const hs_service_intro_point_t *ip, uint8_t *cell_out)
void hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data)
ssize_t hs_cell_build_rendezvous1(const uint8_t *rendezvous_cookie, size_t rendezvous_cookie_len, const uint8_t *rendezvous_handshake_info, size_t rendezvous_handshake_info_len, uint8_t *cell_out)
ssize_t hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data, uint8_t *cell_out)
ssize_t hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, const origin_circuit_t *circ, const hs_service_t *service)
Header file containing cell data for the whole HS subsystem.
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)
void hs_circ_service_rp_has_opened(const hs_service_t *service, origin_circuit_t *circ)
static int get_subcredential_for_handling_intro2_cell(const hs_service_t *service, hs_cell_introduce2_data_t *data, const hs_subcredential_t *desc_subcred)
void hs_circ_cleanup_on_repurpose(circuit_t *circ)
static void cleanup_on_close_client_circ(circuit_t *circ)
static void register_intro_circ(const hs_service_intro_point_t *ip, origin_circuit_t *circ)
origin_circuit_t * hs_circ_service_get_established_intro_circ(const hs_service_intro_point_t *ip)
int hs_circ_launch_intro_point(hs_service_t *service, const hs_service_intro_point_t *ip, extend_info_t *ei, bool direct_conn)
static void finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop, int is_service_side)
static hs_ident_circuit_t * create_intro_circuit_identifier(const hs_service_t *service, const hs_service_intro_point_t *ip)
STATIC void launch_rendezvous_point_circuit(const hs_service_t *service, const hs_service_intro_point_t *ip, const hs_cell_introduce2_data_t *data)
static const char * get_service_anonymity_string(const hs_service_t *service)
int hs_circ_send_introduce1(origin_circuit_t *intro_circ, origin_circuit_t *rend_circ, const hs_desc_intro_point_t *ip, const hs_subcredential_t *subcredential)
static void retry_service_rendezvous_point(const origin_circuit_t *circ)
static crypt_path_t * create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len, int is_service_side)
int hs_circ_service_intro_has_opened(hs_service_t *service, hs_service_intro_point_t *ip, const hs_service_descriptor_t *desc, origin_circuit_t *circ)
static void cleanup_on_free_client_circ(circuit_t *circ)
void hs_circ_cleanup_on_close(circuit_t *circ)
static void send_establish_intro(const hs_service_t *service, hs_service_intro_point_t *ip, origin_circuit_t *circ)
int hs_circ_handle_introduce2(const hs_service_t *service, const origin_circuit_t *circ, hs_service_intro_point_t *ip, const hs_subcredential_t *subcredential, const uint8_t *payload, size_t payload_len)
void hs_circ_retry_service_rendezvous_point(origin_circuit_t *circ)
int hs_circ_handle_intro_established(const hs_service_t *service, const hs_service_intro_point_t *ip, origin_circuit_t *circ, const uint8_t *payload, size_t payload_len)
static int can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
static unsigned int count_opened_desc_intro_point_circuits(const hs_service_t *service, const hs_service_descriptor_t *desc)
origin_circuit_t * hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
bool hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ)
static int circuit_purpose_is_correct_for_rend(unsigned int circ_purpose, int is_service_side)
static int setup_introduce1_data(const hs_desc_intro_point_t *ip, const node_t *rp_node, const hs_subcredential_t *subcredential, hs_cell_introduce1_data_t *intro1_data)
int hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
int hs_circuit_setup_e2e_rend_circ(origin_circuit_t *circ, const uint8_t *ntor_key_seed, size_t seed_len, int is_service_side)
void hs_circ_cleanup_on_free(circuit_t *circ)
Header file containing circuit data for the whole HS subsystem.
void hs_circuitmap_remove_circuit(circuit_t *circ)
origin_circuit_t * hs_circuitmap_get_intro_circ_v3_service_side(const ed25519_public_key_t *auth_key)
void hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ, const ed25519_public_key_t *auth_key)
Header file for hs_circuitmap.c.
void hs_client_circuit_cleanup_on_close(const circuit_t *circ)
void hs_client_circuit_cleanup_on_free(const circuit_t *circ)
Header file containing client data for the HS subsystem.
int hs_get_service_max_rend_failures(void)
extend_info_t * hs_get_extend_info_from_lspecs(const smartlist_t *lspecs, const curve25519_public_key_t *onion_key, int direct_conn)
int hs_service_requires_uptime_circ(const smartlist_t *ports)
#define HS_LEGACY_RENDEZVOUS_CELL_SIZE
#define MAX_REND_FAILURES
hs_ident_circuit_t * hs_ident_circuit_dup(const hs_ident_circuit_t *src)
hs_ident_circuit_t * hs_ident_circuit_new(const ed25519_public_key_t *identity_pk)
Header file containing circuit and connection identifier data for the whole HS subsystem.
#define HS_REND_COOKIE_LEN
Header for feature/hs/hs_metrics.c.
#define hs_metrics_new_rdv(i)
int hs_ntor_circuit_key_expansion(const uint8_t *ntor_key_seed, size_t seed_len, uint8_t *keys_out, size_t keys_out_len)
bool hs_ob_service_is_instance(const hs_service_t *service)
Header file for the specific code for onion balance.
void hs_service_circuit_cleanup_on_close(const circuit_t *circ)
Header file containing service data for the HS subsystem.
#define log_fn(severity, domain, args,...)
Node information structure.
const curve25519_public_key_t * node_get_curve25519_onion_key(const node_t *node)
Header file for nodelist.c.
Master header file for Tor-specific functionality.
#define RELAY_PAYLOAD_SIZE
Origin circuit structure.
Header file for policies.c.
Header file for rephist.c.
int replaycache_add_test_and_elapsed(replaycache_t *r, const void *data, size_t len, time_t *elapsed)
smartlist_t * smartlist_new(void)
struct hs_token_t * hs_token
uint16_t marked_for_close
extend_info_t * chosen_exit
unsigned int need_capacity
struct crypt_path_t * prev
char rend_circ_nonce[DIGEST_LEN]
const ed25519_public_key_t * auth_pk
const struct hs_subcredential_t * subcredential
const curve25519_keypair_t * client_kp
const curve25519_public_key_t * enc_pk
const uint8_t * rendezvous_cookie
const curve25519_public_key_t * onion_pk
smartlist_t * link_specifiers
curve25519_public_key_t onion_pk
const ed25519_public_key_t * auth_pk
const curve25519_keypair_t * enc_kp
uint8_t rendezvous_cookie[REND_COOKIE_LEN]
replaycache_t * replay_cache
const struct hs_subcredential_t * subcredentials
curve25519_public_key_t client_pk
smartlist_t * link_specifiers
curve25519_public_key_t enc_key
tor_cert_t * auth_key_cert
uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN]
ed25519_public_key_t intro_auth_pk
curve25519_keypair_t rendezvous_client_kp
curve25519_public_key_t intro_enc_pk
uint8_t rendezvous_ntor_key_seed[DIGEST256_LEN]
ed25519_public_key_t identity_pk
uint8_t rendezvous_handshake_info[CURVE25519_PUBKEY_LEN+DIGEST256_LEN]
unsigned int is_single_onion
unsigned int num_intro_points
hs_service_intropoints_t intro_points
ed25519_keypair_t auth_key_kp
replaycache_t * replay_cache
curve25519_keypair_t enc_key_kp
uint64_t introduce2_count
ed25519_public_key_t identity_pk
replaycache_t * replay_cache_rend_cookie
unsigned int num_intro_circ_launched
char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1]
hs_service_config_t config
unsigned int hs_service_side_rend_circ_has_been_relaunched
struct hs_ident_circuit_t * hs_ident
cpath_build_state_t * build_state
unsigned int hs_circ_has_timed_out
ed25519_public_key_t signed_key
#define MOCK_IMPL(rv, funcname, arglist)
#define tor_assert_nonfatal_unreached()
#define CURVE25519_PUBKEY_LEN