Tor 0.4.9.2-alpha-dev
All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Modules Pages
hs_circuit.c
Go to the documentation of this file.
1/* Copyright (c) 2017-2021, The Tor Project, Inc. */
2/* See LICENSE for licensing information */
3
4/**
5 * \file hs_circuit.c
6 **/
7
8#define HS_CIRCUIT_PRIVATE
9
10#include "core/or/or.h"
11#include "app/config/config.h"
12#include "core/crypto/hs_ntor.h"
14#include "core/or/circuitlist.h"
15#include "core/or/circuituse.h"
16#include "core/or/policies.h"
17#include "core/or/relay.h"
18#include "core/or/crypt_path.h"
19#include "core/or/extendinfo.h"
22#include "feature/client/circpathbias.h"
23#include "feature/hs/hs_cell.h"
26#include "feature/hs/hs_ob.h"
29#include "feature/hs/hs_ident.h"
39
40/* Trunnel. */
41#include "trunnel/ed25519_cert.h"
42#include "trunnel/hs/cell_establish_intro.h"
43
50
51/** Helper: Free a pending rend object. */
52static inline void
54{
55 if (!req) {
56 return;
57 }
58 link_specifier_smartlist_free(req->rdv_data.link_specifiers);
59 memwipe(req, 0, sizeof(pending_rend_t));
60 tor_free(req);
61}
62
63/** A circuit is about to become an e2e rendezvous circuit. Check
64 * <b>circ_purpose</b> and ensure that it's properly set. Return true iff
65 * circuit purpose is properly set, otherwise return false. */
66static int
67circuit_purpose_is_correct_for_rend(unsigned int circ_purpose,
68 int is_service_side)
69{
70 if (is_service_side) {
71 if (circ_purpose != CIRCUIT_PURPOSE_S_CONNECT_REND) {
72 log_warn(LD_BUG,
73 "HS e2e circuit setup with wrong purpose (%d)", circ_purpose);
74 return 0;
75 }
76 }
77
78 if (!is_service_side) {
79 if (circ_purpose != CIRCUIT_PURPOSE_C_REND_READY &&
81 log_warn(LD_BUG,
82 "Client e2e circuit setup with wrong purpose (%d)", circ_purpose);
83 return 0;
84 }
85 }
86
87 return 1;
88}
89
90/** Create and return a crypt path for the final hop of a v3 prop224 rendezvous
91 * circuit. Initialize the crypt path crypto using the output material from the
92 * ntor key exchange at <b>ntor_key_seed</b>.
93 *
94 * If <b>is_service_side</b> is set, we are the hidden service and the final
95 * hop of the rendezvous circuit is the client on the other side. */
96static crypt_path_t *
97create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len,
98 int is_service_side)
99{
100 uint8_t keys[HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN];
101 crypt_path_t *cpath = NULL;
102
103 /* Do the key expansion */
104 if (hs_ntor_circuit_key_expansion(ntor_key_seed, seed_len,
105 keys, sizeof(keys)) < 0) {
106 goto err;
107 }
108
109 /* Setup the cpath */
110 cpath = tor_malloc_zero(sizeof(crypt_path_t));
111 cpath->magic = CRYPT_PATH_MAGIC;
112
113 // TODO CGO: Pick relay cell format based on capabilities.
115 relay_crypto_alg_t alg = is_service_side ? RELAY_CRYPTO_ALG_TOR1_HSS :
117
118 if (cpath_init_circuit_crypto(alg, cpath, (char*)keys, sizeof(keys)) < 0) {
119 tor_free(cpath);
120 goto err;
121 }
122
123 err:
124 memwipe(keys, 0, sizeof(keys));
125 return cpath;
126}
127
128/** Append the final <b>hop</b> to the cpath of the rend <b>circ</b>, and mark
129 * <b>circ</b> ready for use to transfer HS relay cells. */
130static void
132 int is_service_side)
133{
134 tor_assert(circ);
135 tor_assert(hop);
136
137 /* Notify the circuit state machine that we are splicing this circuit */
138 int new_circ_purpose = is_service_side ?
140 circuit_change_purpose(TO_CIRCUIT(circ), new_circ_purpose);
141
142 /* All is well. Extend the circuit. */
143 hop->state = CPATH_STATE_OPEN;
144 /* Set the windows to default. */
147
148 /* If congestion control, transfer ccontrol onto the cpath. */
149 if (TO_CIRCUIT(circ)->ccontrol) {
150 hop->ccontrol = TO_CIRCUIT(circ)->ccontrol;
151 TO_CIRCUIT(circ)->ccontrol = NULL;
152 }
153
154 /* Append the hop to the cpath of this circuit */
155 cpath_extend_linked_list(&circ->cpath, hop);
156
157 /* Finally, mark circuit as ready to be used for client streams */
158 if (!is_service_side) {
160 }
161}
162
163/** For a given circuit and a service introduction point object, register the
164 * intro circuit to the circuitmap. */
165static void
167 origin_circuit_t *circ)
168{
169 tor_assert(ip);
170 tor_assert(circ);
171
173 &ip->auth_key_kp.pubkey);
174}
175
176/** Return the number of opened introduction circuit for the given circuit that
177 * is matching its identity key. */
178static unsigned int
180 const hs_service_descriptor_t *desc)
181{
182 unsigned int count = 0;
183
184 tor_assert(service);
185 tor_assert(desc);
186
187 DIGEST256MAP_FOREACH(desc->intro_points.map, key,
188 const hs_service_intro_point_t *, ip) {
189 const circuit_t *circ;
191 if (ocirc == NULL) {
192 continue;
193 }
194 circ = TO_CIRCUIT(ocirc);
197 /* Having a circuit not for the requested service is really bad. */
199 &ocirc->hs_ident->identity_pk));
200 /* Only count opened circuit and skip circuit that will be closed. */
201 if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN) {
202 count++;
203 }
204 } DIGEST256MAP_FOREACH_END;
205 return count;
206}
207
208/** From a given service, rendezvous cookie and handshake info, create a
209 * rendezvous point circuit identifier. This can't fail. */
212 const uint8_t *rendezvous_cookie,
213 const curve25519_public_key_t *server_pk,
214 const hs_ntor_rend_cell_keys_t *keys)
215{
216 hs_ident_circuit_t *ident;
217 uint8_t handshake_info[CURVE25519_PUBKEY_LEN + DIGEST256_LEN];
218
219 tor_assert(service);
220 tor_assert(rendezvous_cookie);
221 tor_assert(server_pk);
222 tor_assert(keys);
223
224 ident = hs_ident_circuit_new(&service->keys.identity_pk);
225 /* Copy the RENDEZVOUS_COOKIE which is the unique identifier. */
226 memcpy(ident->rendezvous_cookie, rendezvous_cookie,
227 sizeof(ident->rendezvous_cookie));
228 /* Build the HANDSHAKE_INFO which looks like this:
229 * SERVER_PK [32 bytes]
230 * AUTH_INPUT_MAC [32 bytes]
231 */
232 memcpy(handshake_info, server_pk->public_key, CURVE25519_PUBKEY_LEN);
233 memcpy(handshake_info + CURVE25519_PUBKEY_LEN, keys->rend_cell_auth_mac,
235 tor_assert(sizeof(ident->rendezvous_handshake_info) ==
236 sizeof(handshake_info));
237 memcpy(ident->rendezvous_handshake_info, handshake_info,
238 sizeof(ident->rendezvous_handshake_info));
239 /* Finally copy the NTOR_KEY_SEED for e2e encryption on the circuit. */
240 tor_assert(sizeof(ident->rendezvous_ntor_key_seed) ==
241 sizeof(keys->ntor_key_seed));
242 memcpy(ident->rendezvous_ntor_key_seed, keys->ntor_key_seed,
243 sizeof(ident->rendezvous_ntor_key_seed));
244 return ident;
245}
246
247/** From a given service and service intro point, create an introduction point
248 * circuit identifier. This can't fail. */
249static hs_ident_circuit_t *
251 const hs_service_intro_point_t *ip)
252{
253 hs_ident_circuit_t *ident;
254
255 tor_assert(service);
256 tor_assert(ip);
257
258 ident = hs_ident_circuit_new(&service->keys.identity_pk);
259 ed25519_pubkey_copy(&ident->intro_auth_pk, &ip->auth_key_kp.pubkey);
260 tor_assert_nonfatal(!ed25519_public_key_is_zero(&ident->intro_auth_pk));
261
262 return ident;
263}
264
265/** For a given introduction point and an introduction circuit, send the
266 * ESTABLISH_INTRO cell. The service object is used for logging. This can fail
267 * and if so, the circuit is closed and the intro point object is flagged
268 * that the circuit is not established anymore which is important for the
269 * retry mechanism. */
270static void
273{
274 ssize_t cell_len;
275 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX];
276
277 tor_assert(service);
278 tor_assert(ip);
279 tor_assert(circ);
280
281 /* Encode establish intro cell. */
283 &service->config, ip, payload);
284 if (cell_len < 0) {
285 log_warn(LD_REND, "Unable to encode ESTABLISH_INTRO cell for service %s "
286 "on circuit %u. Closing circuit.",
287 safe_str_client(service->onion_address),
288 TO_CIRCUIT(circ)->n_circ_id);
289 goto err;
290 }
291
292 /* Send the cell on the circuit. */
293 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
294 RELAY_COMMAND_ESTABLISH_INTRO,
295 (char *) payload, cell_len,
296 circ->cpath->prev) < 0) {
297 log_info(LD_REND, "Unable to send ESTABLISH_INTRO cell for service %s "
298 "on circuit %u.",
299 safe_str_client(service->onion_address),
300 TO_CIRCUIT(circ)->n_circ_id);
301 /* On error, the circuit has been closed. */
302 goto done;
303 }
304
305 /* Record the attempt to use this circuit. */
307 goto done;
308
309 err:
310 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
311 done:
312 memwipe(payload, 0, sizeof(payload));
313}
314
315/** Return a string constant describing the anonymity of service. */
316static const char *
318{
319 if (service->config.is_single_onion) {
320 return "single onion";
321 } else {
322 return "hidden";
323 }
324}
325
326/** For a given service, the ntor onion key and a rendezvous cookie, launch a
327 * circuit to the rendezvous point specified by the link specifiers. On
328 * success, a circuit identifier is attached to the circuit with the needed
329 * data. This function will try to open a circuit for a maximum value of
330 * MAX_REND_FAILURES then it will give up. */
331MOCK_IMPL(STATIC void,
333 const ed25519_public_key_t *ip_auth_pubkey,
334 const curve25519_keypair_t *ip_enc_key_kp,
335 const hs_cell_intro_rdv_data_t *rdv_data,
336 time_t now))
337{
338 int circ_needs_uptime;
339 extend_info_t *info = NULL;
340 origin_circuit_t *circ;
341
342 tor_assert(service);
343 tor_assert(ip_auth_pubkey);
344 tor_assert(ip_enc_key_kp);
345 tor_assert(rdv_data);
346
347 circ_needs_uptime = hs_service_requires_uptime_circ(service->config.ports);
348
349 /* Get the extend info data structure for the chosen rendezvous point
350 * specified by the given link specifiers. */
352 &rdv_data->onion_pk,
353 service->config.is_single_onion);
354 if (info == NULL) {
355 /* We are done here, we can't extend to the rendezvous point. */
356 log_fn(LOG_PROTOCOL_WARN, LD_REND,
357 "Not enough info to open a circuit to a rendezvous point for "
358 "%s service %s.",
360 safe_str_client(service->onion_address));
361 goto end;
362 }
363
364 for (int i = 0; i < MAX_REND_FAILURES; i++) {
366 if (circ_needs_uptime) {
367 circ_flags |= CIRCLAUNCH_NEED_UPTIME;
368 }
369 /* Firewall and policies are checked when getting the extend info.
370 *
371 * We only use a one-hop path on the first attempt. If the first attempt
372 * fails, we use a 3-hop path for reachability / reliability.
373 * See the comment in retry_service_rendezvous_point() for details. */
374 if (service->config.is_single_onion && i == 0) {
375 circ_flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
376 }
377
379 circ_flags);
380 if (circ != NULL) {
381 /* Stop retrying, we have a circuit! */
382 break;
383 }
384 }
385 if (circ == NULL) {
386 log_warn(LD_REND, "Giving up on launching a rendezvous circuit to %s "
387 "for %s service %s",
388 safe_str_client(extend_info_describe(info)),
390 safe_str_client(service->onion_address));
391 goto end;
392 }
393 /* Update metrics with this new rendezvous circuit launched. */
395
396 log_info(LD_REND, "Rendezvous circuit launched to %s with cookie %s "
397 "for %s service %s",
398 safe_str_client(extend_info_describe(info)),
399 safe_str_client(hex_str((const char *)
400 rdv_data->rendezvous_cookie,
403 safe_str_client(service->onion_address));
404 tor_assert(circ->build_state);
405 /* Rendezvous circuit have a specific timeout for the time spent on trying
406 * to connect to the rendezvous point. */
408
409 /* Create circuit identifier and key material. */
410 {
412 curve25519_keypair_t ephemeral_kp;
413 /* No need for extra strong, this is only for this circuit life time. This
414 * key will be used for the RENDEZVOUS1 cell that will be sent on the
415 * circuit once opened. */
416 curve25519_keypair_generate(&ephemeral_kp, 0);
417 if (hs_ntor_service_get_rendezvous1_keys(ip_auth_pubkey,
418 ip_enc_key_kp,
419 &ephemeral_kp,
420 &rdv_data->client_pk,
421 &keys) < 0) {
422 /* This should not really happened but just in case, don't make tor
423 * freak out, close the circuit and move on. */
424 log_info(LD_REND, "Unable to get RENDEZVOUS1 key material for "
425 "service %s",
426 safe_str_client(service->onion_address));
427 circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
428 goto end;
429 }
431 rdv_data->rendezvous_cookie,
432 &ephemeral_kp.pubkey, &keys);
433 memwipe(&ephemeral_kp, 0, sizeof(ephemeral_kp));
434 memwipe(&keys, 0, sizeof(keys));
435 tor_assert(circ->hs_ident);
436 }
437
438 /* Remember PoW state if this introduction included a valid proof of work
439 * client puzzle extension. */
440 if (rdv_data->pow_effort > 0) {
441 circ->hs_pow_effort = rdv_data->pow_effort;
442 circ->hs_with_pow_circ = 1;
443 }
444
445 /* Setup congestion control if asked by the client from the INTRO cell. */
446 if (rdv_data->cc_enabled) {
448 service->config.is_single_onion);
449 }
450
451 end:
452 extend_info_free(info);
453}
454
455/** Return true iff the given service rendezvous circuit circ is allowed for a
456 * relaunch to the rendezvous point. */
457static int
459{
460 tor_assert(circ);
461 /* This is initialized when allocating an origin circuit. */
462 tor_assert(circ->build_state);
464
465 /* XXX: Retrying under certain condition. This is related to #22455. */
466
467 /* We check failure_count >= hs_get_service_max_rend_failures()-1 below, and
468 * the -1 is because we increment the failure count for our current failure
469 * *after* this clause. */
470 int max_rend_failures = hs_get_service_max_rend_failures() - 1;
471
472 /* A failure count that has reached maximum allowed or circuit that expired,
473 * we skip relaunching. */
474 if (circ->build_state->failure_count > max_rend_failures ||
475 circ->build_state->expiry_time <= time(NULL)) {
476 log_info(LD_REND, "Attempt to build a rendezvous circuit to %s has "
477 "failed with %d attempts and expiry time %ld. "
478 "Giving up building.",
479 safe_str_client(
482 (long int) circ->build_state->expiry_time);
483 goto disallow;
484 }
485
486 /* Allowed to relaunch. */
487 return 1;
488 disallow:
489 return 0;
490}
491
492/** Retry the rendezvous point of circ by launching a new circuit to it. */
493static void
495{
496 int flags = 0;
497 origin_circuit_t *new_circ;
498 cpath_build_state_t *bstate;
499
500 tor_assert(circ);
501 /* This is initialized when allocating an origin circuit. */
502 tor_assert(circ->build_state);
504
505 /* Ease our life. */
506 bstate = circ->build_state;
507
508 log_info(LD_REND, "Retrying rendezvous point circuit to %s",
509 safe_str_client(extend_info_describe(bstate->chosen_exit)));
510
511 /* Get the current build state flags for the next circuit. */
512 flags |= (bstate->need_uptime) ? CIRCLAUNCH_NEED_UPTIME : 0;
513 flags |= (bstate->need_capacity) ? CIRCLAUNCH_NEED_CAPACITY : 0;
514 flags |= (bstate->is_internal) ? CIRCLAUNCH_IS_INTERNAL : 0;
515
516 /* We do NOT add the onehop tunnel flag even though it might be a single
517 * onion service. The reason is that if we failed once to connect to the RP
518 * with a direct connection, we consider that chances are that we will fail
519 * again so try a 3-hop circuit and hope for the best. Because the service
520 * has no anonymity (single onion), this change of behavior won't affect
521 * security directly. */
522
524 bstate->chosen_exit, flags);
525 if (new_circ == NULL) {
526 log_warn(LD_REND, "Failed to launch rendezvous circuit to %s",
527 safe_str_client(extend_info_describe(bstate->chosen_exit)));
528
530 HS_METRICS_ERR_RDV_RETRY);
531
532 goto done;
533 }
534
535 /* Transfer build state information to the new circuit state in part to
536 * catch any other failures. */
537 new_circ->build_state->failure_count = bstate->failure_count+1;
538 new_circ->build_state->expiry_time = bstate->expiry_time;
539 new_circ->hs_ident = hs_ident_circuit_dup(circ->hs_ident);
540
541 /* Setup congestion control if asked by the client from the INTRO cell. */
542 if (TO_CIRCUIT(circ)->ccontrol) {
543 /* As per above, in this case, we are a full 3 hop rend, even if we're a
544 * single-onion service. */
546 TO_CIRCUIT(circ)->ccontrol->sendme_inc,
547 false);
548 }
549
550 done:
551 return;
552}
553
554/** Using the given descriptor intro point ip, the node of the
555 * rendezvous point rp_node and the service's subcredential, populate the
556 * already allocated intro1_data object with the needed key material and link
557 * specifiers.
558 *
559 * Return 0 on success or a negative value if we couldn't properly filled the
560 * introduce1 data from the RP node. In other word, it means the RP node is
561 * unusable to use in the introduction. */
562static int
564 const node_t *rp_node,
565 const hs_subcredential_t *subcredential,
566 hs_cell_introduce1_data_t *intro1_data)
567{
568 int ret = -1;
569 smartlist_t *rp_lspecs;
570
571 tor_assert(ip);
572 tor_assert(rp_node);
573 tor_assert(subcredential);
574 tor_assert(intro1_data);
575
576 /* Build the link specifiers from the node at the end of the rendezvous
577 * circuit that we opened for this introduction. */
578 rp_lspecs = node_get_link_specifier_smartlist(rp_node, 0);
579 if (smartlist_len(rp_lspecs) == 0) {
580 /* We can't rendezvous without link specifiers. */
581 smartlist_free(rp_lspecs);
582 goto end;
583 }
584
585 /* Populate the introduce1 data object. */
586 memset(intro1_data, 0, sizeof(hs_cell_introduce1_data_t));
587 intro1_data->auth_pk = &ip->auth_key_cert->signed_key;
588 intro1_data->enc_pk = &ip->enc_key;
589 intro1_data->subcredential = subcredential;
590 intro1_data->link_specifiers = rp_lspecs;
591 intro1_data->onion_pk = node_get_curve25519_onion_key(rp_node);
592 if (intro1_data->onion_pk == NULL) {
593 /* We can't rendezvous without the curve25519 onion key. */
594 goto end;
595 }
596
597 /* Success, we have valid introduce data. */
598 ret = 0;
599
600 end:
601 return ret;
602}
603
604/** Helper: cleanup function for client circuit. This is for every HS version.
605 * It is called from hs_circ_cleanup_on_close() entry point. */
606static void
608{
609 tor_assert(circ);
610
611 if (circuit_is_hs_v3(circ)) {
613 }
614 /* It is possible the circuit has an HS purpose but no identifier (hs_ident).
615 * Thus possible that this passes through. */
616}
617
618/** Helper: cleanup function for client circuit. This is for every HS version.
619 * It is called from hs_circ_cleanup_on_free() entry point. */
620static void
622{
623 tor_assert(circ);
624
625 if (circuit_is_hs_v3(circ)) {
627 }
628 /* It is possible the circuit has an HS purpose but no identifier (hs_ident).
629 * Thus possible that this passes through. */
630}
631
632/** Return less than 0 if a precedes b, 0 if a equals b and greater than 0 if
633 * b precedes a. Note that *higher* effort is *earlier* in the pqueue. */
634static int
635compare_rend_request_by_effort_(const void *_a, const void *_b)
636{
637 const pending_rend_t *a = _a, *b = _b;
638 if (a->rdv_data.pow_effort > b->rdv_data.pow_effort) {
639 return -1;
640 } else if (a->rdv_data.pow_effort == b->rdv_data.pow_effort) {
641 /* tie-breaker! use the time it was added to the queue. older better. */
642 if (a->enqueued_ts < b->enqueued_ts)
643 return -1;
644 if (a->enqueued_ts > b->enqueued_ts)
645 return 1;
646 return 0;
647 } else {
648 return 1;
649 }
650}
651
652/** Return 1 if a request waiting in our service-side pqueue is old
653 * enough that we should just discard it rather than trying to respond,
654 * or 0 if we still like it. As a heuristic, choose half of the total
655 * permitted time interval (so we don't approve trying to respond to
656 * requests when we will then give up on them a moment later).
657 */
658static int
660{
661 if ((req->enqueued_ts + MAX_REND_TIMEOUT/2) < now)
662 return 1;
663 return 0;
664}
665
666/** Our rendezvous request priority queue is too full; keep the first
667 * pqueue_high_level/2 entries and discard the rest.
668 */
669static void
671{
672 smartlist_t *old_pqueue = pow_state->rend_request_pqueue;
673 smartlist_t *new_pqueue = pow_state->rend_request_pqueue = smartlist_new();
674
675 log_info(LD_REND, "Rendezvous request priority queue has "
676 "reached capacity (%d). Discarding the bottom half.",
677 smartlist_len(old_pqueue));
678
679 while (smartlist_len(old_pqueue) &&
680 smartlist_len(new_pqueue) < pow_state->pqueue_high_level/2) {
681 /* while there are still old ones, and the new one isn't full yet */
682 pending_rend_t *req =
683 smartlist_pqueue_pop(old_pqueue,
685 offsetof(pending_rend_t, idx));
686 if (queued_rend_request_is_too_old(req, now)) {
687 log_info(LD_REND, "While trimming, rend request has been pending "
688 "for too long; discarding.");
689
690 pow_state->max_trimmed_effort = MAX(pow_state->max_trimmed_effort,
691 req->rdv_data.pow_effort);
692
694 } else {
695 smartlist_pqueue_add(new_pqueue,
697 offsetof(pending_rend_t, idx), req);
698 }
699 }
700
701 /* Ok, we have rescued all the entries we want to keep. The rest are
702 * all excess. */
703 SMARTLIST_FOREACH_BEGIN(old_pqueue, pending_rend_t *, req) {
704 pow_state->max_trimmed_effort = MAX(pow_state->max_trimmed_effort,
705 req->rdv_data.pow_effort);
707 } SMARTLIST_FOREACH_END(req);
708 smartlist_free(old_pqueue);
709}
710
711/** Count up how many pending outgoing (CIRCUIT_PURPOSE_S_CONNECT_REND)
712 * circuits there are for this service. Used in the PoW rate limiting
713 * world to decide whether it's time to launch any new ones.
714 */
715static int
717{
718 origin_circuit_t *ocirc = NULL;
719 int count = 0;
720 while ((ocirc = circuit_get_next_by_purpose(ocirc,
722 /* Count up circuits that are v3 and for this service. */
723 if (ocirc->hs_ident != NULL &&
725 &service->keys.identity_pk)) {
726 count++;
727 }
728 }
729 return count;
730}
731
732/** Peek at the top entry on the pending rend pqueue, which must not be empty.
733 * If its level of effort is at least what we're suggesting for that service
734 * right now, return 1, else return 0.
735 */
736int
738{
739 tor_assert(pow_state->rend_request_pqueue);
740 tor_assert(smartlist_len(pow_state->rend_request_pqueue));
741
742 pending_rend_t *req =
743 smartlist_get(pow_state->rend_request_pqueue, 0);
744
745 if (req->rdv_data.pow_effort >= pow_state->suggested_effort)
746 return 1;
747
748 return 0;
749}
750
751/** Abandon and free all pending rend requests, leaving the pqueue empty. */
752void
754{
755 tor_assert(pow_state->rend_request_pqueue);
756 while (smartlist_len(pow_state->rend_request_pqueue)) {
757 pending_rend_t *req = smartlist_pop_last(pow_state->rend_request_pqueue);
759 }
760}
761
762/** What is the threshold of in-progress (CIRCUIT_PURPOSE_S_CONNECT_REND)
763 * rendezvous responses above which we won't launch new low-effort rendezvous
764 * responses? (Intro2 cells with suitable PoW effort are not affected
765 * by this threshold.) */
766#define MAX_CHEAP_REND_CIRCUITS_IN_PROGRESS 16
767
768static void
769handle_rend_pqueue_cb(mainloop_event_t *ev, void *arg)
770{
771 hs_service_t *service = arg;
772 hs_pow_service_state_t *pow_state = service->state.pow_state;
773 time_t now = time(NULL);
774 int in_flight = count_service_rp_circuits_pending(service);
775
776 (void) ev; /* Not using the returned event, make compiler happy. */
777
778 log_info(LD_REND, "Considering launching more rendezvous responses. "
779 "%d in-flight, %d pending.",
780 in_flight,
781 smartlist_len(pow_state->rend_request_pqueue));
782
783 /* Process only one rend request per callback, so that this work will not
784 * be prioritized over other event loop callbacks. We may need to retry
785 * in order to find one request that's still viable. */
786 while (smartlist_len(pow_state->rend_request_pqueue) > 0) {
787
788 /* first, peek at the top result to see if we want to pop it */
789 if (in_flight >= MAX_CHEAP_REND_CIRCUITS_IN_PROGRESS &&
791 /* We have queued requests, but they are all low priority, and also
792 * we have too many in-progress rendezvous responses. Don't launch
793 * any more. Schedule ourselves to reassess in a bit. */
794 log_info(LD_REND, "Next request to launch is low priority, and "
795 "%d in-flight already. Waiting to launch more.", in_flight);
796 const struct timeval delay_tv = { 0, 100000 };
797 mainloop_event_schedule(pow_state->pop_pqueue_ev, &delay_tv);
798 return; /* done here! no cleanup needed. */
799 }
800
801 if (pow_state->using_pqueue_bucket) {
802 token_bucket_ctr_refill(&pow_state->pqueue_bucket,
803 (uint32_t) monotime_coarse_absolute_sec());
804
805 if (token_bucket_ctr_get(&pow_state->pqueue_bucket) > 0) {
806 token_bucket_ctr_dec(&pow_state->pqueue_bucket, 1);
807 } else {
808 /* Waiting for pqueue rate limit to refill, come back later */
809 const struct timeval delay_tv = { 0, 100000 };
810 mainloop_event_schedule(pow_state->pop_pqueue_ev, &delay_tv);
811 return;
812 }
813 }
814
815 /* Pop next request by effort. */
816 pending_rend_t *req =
817 smartlist_pqueue_pop(pow_state->rend_request_pqueue,
819 offsetof(pending_rend_t, idx));
820
822 smartlist_len(pow_state->rend_request_pqueue));
823
824 log_info(LD_REND, "Dequeued pending rendezvous request with effort: %u. "
825 "Waited %d. "
826 "Remaining requests: %u",
827 req->rdv_data.pow_effort,
828 (int)(now - req->enqueued_ts),
829 smartlist_len(pow_state->rend_request_pqueue));
830
831 if (queued_rend_request_is_too_old(req, now)) {
832 log_info(LD_REND, "Top rend request has been pending for too long; "
833 "discarding and moving to the next one.");
835 continue; /* do not increment count, this one's free */
836 }
837
838 /* Launch the rendezvous circuit. */
839 launch_rendezvous_point_circuit(service, &req->ip_auth_pubkey,
840 &req->ip_enc_key_kp, &req->rdv_data, now);
842
843 ++pow_state->rend_handled;
844 ++in_flight;
845 break;
846 }
847
848 /* If there are still some pending rendezvous circuits in the pqueue then
849 * reschedule the event in order to continue handling them. */
850 if (smartlist_len(pow_state->rend_request_pqueue) > 0) {
851 mainloop_event_activate(pow_state->pop_pqueue_ev);
852
853 if (smartlist_len(pow_state->rend_request_pqueue) >=
854 pow_state->pqueue_low_level) {
855 pow_state->had_queue = 1;
856 }
857 }
858}
859
860/** Given the information needed to launch a rendezvous circuit and an
861 * effort value, enqueue the rendezvous request in the service's PoW priority
862 * queue with the effort being the priority.
863 *
864 * Return 0 if we successfully enqueued the request else -1. */
865static int
867 hs_cell_introduce2_data_t *data, time_t now)
868{
869 hs_pow_service_state_t *pow_state = NULL;
870 pending_rend_t *req = NULL;
871
872 tor_assert(service);
873 tor_assert(ip);
874 tor_assert(data);
875
876 /* Ease our lives */
877 pow_state = service->state.pow_state;
878
879 req = tor_malloc_zero(sizeof(pending_rend_t));
880
881 /* Copy over the rendezvous request the needed data to launch a circuit. */
882 ed25519_pubkey_copy(&req->ip_auth_pubkey, &ip->auth_key_kp.pubkey);
883 memcpy(&req->ip_enc_key_kp, &ip->enc_key_kp, sizeof(req->ip_enc_key_kp));
884 memcpy(&req->rdv_data, &data->rdv_data, sizeof(req->rdv_data));
885 /* Invalidate the link specifier pointer in the introduce2 data so it
886 * doesn't get freed under us. */
887 data->rdv_data.link_specifiers = NULL;
888 req->idx = -1;
889 req->enqueued_ts = now;
890
891 /* Enqueue the rendezvous request. */
892 smartlist_pqueue_add(pow_state->rend_request_pqueue,
894 offsetof(pending_rend_t, idx), req);
895
897 smartlist_len(pow_state->rend_request_pqueue));
898
899 log_info(LD_REND, "Enqueued rendezvous request with effort: %u. "
900 "Queued requests: %u",
901 req->rdv_data.pow_effort,
902 smartlist_len(pow_state->rend_request_pqueue));
903
904 /* Initialize the priority queue event if it hasn't been done so already. */
905 if (pow_state->pop_pqueue_ev == NULL) {
906 pow_state->pop_pqueue_ev =
907 mainloop_event_postloop_new(handle_rend_pqueue_cb, (void *)service);
908 }
909
910 /* Activate event, we just enqueued a rendezvous request. */
911 mainloop_event_activate(pow_state->pop_pqueue_ev);
912
913 /* See if there are so many cells queued that we need to cull. */
914 if (smartlist_len(pow_state->rend_request_pqueue) >=
915 pow_state->pqueue_high_level) {
916 trim_rend_pqueue(pow_state, now);
918 smartlist_len(pow_state->rend_request_pqueue));
919 }
920
921 return 0;
922}
923
924/* ========== */
925/* Public API */
926/* ========== */
927
928/** Setup on the given circuit congestion control with the given parameters.
929 *
930 * This function assumes that congestion control is enabled on the network and
931 * so it is the caller responsability to make sure of it. */
932void
934 uint8_t sendme_inc, bool is_single_onion)
935{
936 circuit_t *circ = NULL;
937 circuit_params_t circ_params = {0};
938
939 tor_assert(origin_circ);
940
941 /* Ease our lives */
942 circ = TO_CIRCUIT(origin_circ);
943
944 circ_params.cc_enabled = true;
945 circ_params.sendme_inc_cells = sendme_inc;
946
947 /* It is setup on the circuit in order to indicate that congestion control is
948 * enabled. It will be transferred to the RP crypt_path_t once the handshake
949 * is finalized in finalize_rend_circuit() for both client and service
950 * because the final hop is not available until then. */
951
952 if (is_single_onion) {
953 circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION_SOS);
954 } else {
955 if (get_options()->HSLayer3Nodes) {
956 circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION_VG);
957 } else {
958 circ->ccontrol = congestion_control_new(&circ_params, CC_PATH_ONION);
959 }
960 }
961}
962
963/** Return an introduction point circuit matching the given intro point object.
964 * NULL is returned is no such circuit can be found. */
967{
968 tor_assert(ip);
969
971}
972
973/** Return an introduction point established circuit matching the given intro
974 * point object. The circuit purpose has to be CIRCUIT_PURPOSE_S_INTRO. NULL
975 * is returned is no such circuit can be found. */
978{
979 origin_circuit_t *circ;
980
981 tor_assert(ip);
982
984
985 /* Only return circuit if it is established. */
986 return (circ && TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO) ?
987 circ : NULL;
988}
989
990/** Called when we fail building a rendezvous circuit at some point other than
991 * the last hop: launches a new circuit to the same rendezvous point.
992 *
993 * We currently relaunch connections to rendezvous points if:
994 * - A rendezvous circuit timed out before connecting to RP.
995 * - The rendezvous circuit failed to connect to the RP.
996 *
997 * We avoid relaunching a connection to this rendezvous point if:
998 * - We have already tried MAX_REND_FAILURES times to connect to this RP,
999 * - We've been trying to connect to this RP for more than MAX_REND_TIMEOUT
1000 * seconds, or
1001 * - We've already retried this specific rendezvous circuit.
1002 */
1003void
1005{
1006 tor_assert(circ);
1008
1009 /* Check if we are allowed to relaunch to the rendezvous point of circ. */
1011 goto done;
1012 }
1013
1014 /* Legacy services don't have a hidden service ident. */
1015 if (circ->hs_ident) {
1017 }
1018
1019 done:
1020 return;
1021}
1022
1023/** For a given service and a service intro point, launch a circuit to the
1024 * extend info ei. If the service is a single onion, and direct_conn is true,
1025 * a one-hop circuit will be requested.
1026 *
1027 * Return 0 if the circuit was successfully launched and tagged
1028 * with the correct identifier. On error, a negative value is returned. */
1029int
1031 const hs_service_intro_point_t *ip,
1032 extend_info_t *ei,
1033 bool direct_conn)
1034{
1035 /* Standard flags for introduction circuit. */
1036 int ret = -1, circ_flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
1037 origin_circuit_t *circ;
1038
1039 tor_assert(service);
1040 tor_assert(ip);
1041 tor_assert(ei);
1042
1043 /* Update circuit flags in case of a single onion service that requires a
1044 * direct connection. */
1045 tor_assert_nonfatal(ip->circuit_retries > 0);
1046 /* Only single onion services can make direct conns */
1047 if (BUG(!service->config.is_single_onion && direct_conn)) {
1048 goto end;
1049 }
1050 /* We only use a one-hop path on the first attempt. If the first attempt
1051 * fails, we use a 3-hop path for reachability / reliability. */
1052 if (direct_conn && ip->circuit_retries == 1) {
1053 circ_flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
1054 }
1055
1056 log_info(LD_REND, "Launching a circuit to intro point %s for service %s.",
1057 safe_str_client(extend_info_describe(ei)),
1058 safe_str_client(service->onion_address));
1059
1060 /* Note down the launch for the retry period. Even if the circuit fails to
1061 * be launched, we still want to respect the retry period to avoid stress on
1062 * the circuit subsystem. */
1063 service->state.num_intro_circ_launched++;
1065 ei, circ_flags);
1066 if (circ == NULL) {
1067 goto end;
1068 }
1069
1070 /* Setup the circuit identifier and attach it to it. */
1071 circ->hs_ident = create_intro_circuit_identifier(service, ip);
1072 tor_assert(circ->hs_ident);
1073 /* Register circuit in the global circuitmap. */
1074 register_intro_circ(ip, circ);
1075
1076 /* Success. */
1077 ret = 0;
1078 end:
1079 return ret;
1080}
1081
1082/** Called when a service introduction point circuit is done building. Given
1083 * the service and intro point object, this function will send the
1084 * ESTABLISH_INTRO cell on the circuit. Return 0 on success. Return 1 if the
1085 * circuit has been repurposed to General because we already have too many
1086 * opened. */
1087int
1090 const hs_service_descriptor_t *desc,
1091 origin_circuit_t *circ)
1092{
1093 int ret = 0;
1094 unsigned int num_intro_circ, num_needed_circ;
1095
1096 tor_assert(service);
1097 tor_assert(ip);
1098 tor_assert(desc);
1099 tor_assert(circ);
1100
1101 /* Count opened circuits that have sent ESTABLISH_INTRO cells or are already
1102 * established introduction circuits */
1103 num_intro_circ = count_opened_desc_intro_point_circuits(service, desc);
1104 num_needed_circ = service->config.num_intro_points;
1105 if (num_intro_circ > num_needed_circ) {
1106 /* There are too many opened valid intro circuit for what the service
1107 * needs so repurpose this one. */
1108
1109 /* XXX: Legacy code checks options->ExcludeNodes and if not NULL it just
1110 * closes the circuit. I have NO idea why it does that so it hasn't been
1111 * added here. I can only assume in case our ExcludeNodes list changes but
1112 * in that case, all circuit are flagged unusable (config.c). --dgoulet */
1113
1114 log_info(LD_CIRC | LD_REND, "Introduction circuit just opened but we "
1115 "have enough for service %s. Repurposing "
1116 "it to general and leaving internal.",
1117 safe_str_client(service->onion_address));
1119 /* Remove it from the circuitmap. */
1121 /* Cleaning up the hidden service identifier and repurpose. */
1122 hs_ident_circuit_free(circ->hs_ident);
1123 circ->hs_ident = NULL;
1124 if (circuit_should_use_vanguards(TO_CIRCUIT(circ)->purpose))
1126 else
1128
1129 /* Inform that this circuit just opened for this new purpose. */
1130 circuit_has_opened(circ);
1131 /* This return value indicate to the caller that the IP object should be
1132 * removed from the service because it's corresponding circuit has just
1133 * been repurposed. */
1134 ret = 1;
1135 goto done;
1136 }
1137
1138 log_info(LD_REND, "Introduction circuit %u established for service %s.",
1139 TO_CIRCUIT(circ)->n_circ_id,
1140 safe_str_client(service->onion_address));
1142
1143 /* Time to send an ESTABLISH_INTRO cell on this circuit. On error, this call
1144 * makes sure the circuit gets closed. */
1145 send_establish_intro(service, ip, circ);
1146
1147 done:
1148 return ret;
1149}
1150
1151/** Called when a service rendezvous point circuit is done building. Given the
1152 * service and the circuit, this function will send a RENDEZVOUS1 cell on the
1153 * circuit using the information in the circuit identifier. If the cell can't
1154 * be sent, the circuit is closed. */
1155void
1157 origin_circuit_t *circ)
1158{
1159 size_t payload_len;
1160 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
1161
1162 tor_assert(service);
1163 tor_assert(circ);
1164 tor_assert(circ->hs_ident);
1165
1166 /* Some useful logging. */
1167 log_info(LD_REND, "Rendezvous circuit %u has opened with cookie %s "
1168 "for service %s",
1169 TO_CIRCUIT(circ)->n_circ_id,
1170 hex_str((const char *) circ->hs_ident->rendezvous_cookie,
1172 safe_str_client(service->onion_address));
1174
1175 /* This can't fail. */
1176 payload_len = hs_cell_build_rendezvous1(
1178 sizeof(circ->hs_ident->rendezvous_cookie),
1180 sizeof(circ->hs_ident->rendezvous_handshake_info),
1181 payload);
1182
1183 /* Pad the payload with random bytes so it matches the size of a legacy cell
1184 * which is normally always bigger. Also, the size of a legacy cell is
1185 * always smaller than the RELAY_PAYLOAD_SIZE so this is safe. */
1186 if (payload_len < HS_LEGACY_RENDEZVOUS_CELL_SIZE) {
1187 crypto_rand((char *) payload + payload_len,
1188 HS_LEGACY_RENDEZVOUS_CELL_SIZE - payload_len);
1189 payload_len = HS_LEGACY_RENDEZVOUS_CELL_SIZE;
1190 }
1191
1192 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
1193 RELAY_COMMAND_RENDEZVOUS1,
1194 (const char *) payload,
1195 payload_len,
1196 circ->cpath->prev) < 0) {
1197 /* On error, circuit is closed. */
1198 log_warn(LD_REND, "Unable to send RENDEZVOUS1 cell on circuit %u "
1199 "for service %s",
1200 TO_CIRCUIT(circ)->n_circ_id,
1201 safe_str_client(service->onion_address));
1202
1204 HS_METRICS_ERR_RDV_RENDEZVOUS1);
1205 goto done;
1206 }
1207
1208 /* Setup end-to-end rendezvous circuit between the client and us. */
1211 sizeof(circ->hs_ident->rendezvous_ntor_key_seed),
1212 1) < 0) {
1213 log_warn(LD_GENERAL, "Failed to setup circ");
1214
1215 hs_metrics_failed_rdv(&service->keys.identity_pk, HS_METRICS_ERR_RDV_E2E);
1216 goto done;
1217 }
1218
1219 done:
1220 memwipe(payload, 0, sizeof(payload));
1221}
1222
1223/** Circ has been expecting an INTRO_ESTABLISHED cell that just arrived. Handle
1224 * the INTRO_ESTABLISHED cell payload of length payload_len arriving on the
1225 * given introduction circuit circ. The service is only used for logging
1226 * purposes. Return 0 on success else a negative value. */
1227int
1229 const hs_service_intro_point_t *ip,
1230 origin_circuit_t *circ,
1231 const uint8_t *payload, size_t payload_len)
1232{
1233 int ret = -1;
1234
1235 tor_assert(service);
1236 tor_assert(ip);
1237 tor_assert(circ);
1238 tor_assert(payload);
1239
1240 if (BUG(TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)) {
1241 goto done;
1242 }
1243
1244 /* Try to parse the payload into a cell making sure we do actually have a
1245 * valid cell. */
1246 if (hs_cell_parse_intro_established(payload, payload_len) < 0) {
1247 log_warn(LD_REND, "Unable to parse the INTRO_ESTABLISHED cell on "
1248 "circuit %u for service %s",
1249 TO_CIRCUIT(circ)->n_circ_id,
1250 safe_str_client(service->onion_address));
1251 goto done;
1252 }
1253
1254 /* Switch the purpose to a fully working intro point. */
1256 /* Getting a valid INTRODUCE_ESTABLISHED means we've successfully used the
1257 * circuit so update our pathbias subsystem. */
1259 /* Success. */
1260 ret = 0;
1261
1262 done:
1263 return ret;
1264}
1265
1266/**
1267 * Go into <b>data</b> and add the right subcredential to be able to handle
1268 * this incoming cell.
1269 *
1270 * <b>desc_subcred</b> is the subcredential of the descriptor that corresponds
1271 * to the intro point that received this intro request. This subcredential
1272 * should be used if we are not an onionbalance instance.
1273 *
1274 * Return 0 if everything went well, or -1 in case of internal error.
1275 */
1276static int
1279 const hs_subcredential_t *desc_subcred)
1280{
1281 /* Handle the simple case first: We are not an onionbalance instance and we
1282 * should just use the regular descriptor subcredential */
1283 if (!hs_ob_service_is_instance(service)) {
1284 data->n_subcredentials = 1;
1285 data->subcredentials = desc_subcred;
1286 return 0;
1287 }
1288
1289 /* This should not happen since we should have made onionbalance
1290 * subcredentials when we created our descriptors. */
1291 if (BUG(!service->state.ob_subcreds)) {
1292 return -1;
1293 }
1294
1295 /* We are an onionbalance instance: */
1296 data->n_subcredentials = service->state.n_ob_subcreds;
1297 data->subcredentials = service->state.ob_subcreds;
1298
1299 return 0;
1300}
1301
1302/** We just received an INTRODUCE2 cell on the established introduction circuit
1303 * circ. Handle the INTRODUCE2 payload of size payload_len for the given
1304 * circuit and service. This cell is associated with the intro point object ip
1305 * and the subcredential. Return 0 on success else a negative value. */
1306int
1308 const origin_circuit_t *circ,
1310 const hs_subcredential_t *subcredential,
1311 const uint8_t *payload, size_t payload_len)
1312{
1313 int ret = -1;
1314 time_t elapsed;
1316 time_t now = time(NULL);
1317
1318 tor_assert(service);
1319 tor_assert(circ);
1320 tor_assert(ip);
1321 tor_assert(subcredential);
1322 tor_assert(payload);
1323
1324 /* Populate the data structure with everything we need for the cell to be
1325 * parsed, decrypted and key material computed correctly. */
1326 data.auth_pk = &ip->auth_key_kp.pubkey;
1327 data.enc_kp = &ip->enc_key_kp;
1328 data.payload = payload;
1329 data.payload_len = payload_len;
1330 data.replay_cache = ip->replay_cache;
1332 data.rdv_data.cc_enabled = 0;
1333 data.rdv_data.pow_effort = 0;
1334
1336 subcredential)) {
1338 HS_METRICS_ERR_INTRO_REQ_SUBCREDENTIAL);
1339 goto done;
1340 }
1341
1342 if (hs_cell_parse_introduce2(&data, circ, service, ip) < 0) {
1343 hs_metrics_reject_intro_req(service, HS_METRICS_ERR_INTRO_REQ_INTRODUCE2);
1344 goto done;
1345 }
1346
1347 /* Check whether we've seen this REND_COOKIE before to detect repeats. */
1351 sizeof(data.rdv_data.rendezvous_cookie),
1352 &elapsed)) {
1353 /* A Tor client will send a new INTRODUCE1 cell with the same REND_COOKIE
1354 * as its previous one if its intro circ times out while in state
1355 * CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT. If we received the first
1356 * INTRODUCE1 cell (the intro-point relay converts it into an INTRODUCE2
1357 * cell), we are already trying to connect to that rend point (and may
1358 * have already succeeded); drop this cell. */
1359 log_info(LD_REND, "We received an INTRODUCE2 cell with same REND_COOKIE "
1360 "field %ld seconds ago. Dropping cell.",
1361 (long int) elapsed);
1363 HS_METRICS_ERR_INTRO_REQ_INTRODUCE2_REPLAY);
1364 goto done;
1365 }
1366
1367 /* At this point, we just confirmed that the full INTRODUCE2 cell is valid
1368 * so increment our counter that we've seen one on this intro point. */
1369 ip->introduce2_count++;
1370
1371 /* Add the rendezvous request to the priority queue if PoW defenses are
1372 * enabled, otherwise rendezvous as usual. */
1373 if (have_module_pow() && service->config.has_pow_defenses_enabled) {
1374 log_info(LD_REND,
1375 "Adding introduction request to pqueue with effort: %u",
1376 data.rdv_data.pow_effort);
1377 if (enqueue_rend_request(service, ip, &data, now) < 0) {
1378 goto done;
1379 }
1380
1381 /* Track the total effort in valid requests received this period */
1382 service->state.pow_state->total_effort += data.rdv_data.pow_effort;
1383
1384 /* Successfully added rend circuit to priority queue. */
1385 ret = 0;
1386 goto done;
1387 }
1388
1389 /* Launch rendezvous circuit with the onion key and rend cookie. */
1390 launch_rendezvous_point_circuit(service, &ip->auth_key_kp.pubkey,
1391 &ip->enc_key_kp, &data.rdv_data, now);
1392 /* Success. */
1393 ret = 0;
1394
1395 done:
1396 /* Note that if PoW defenses are enabled, this is NULL. */
1397 link_specifier_smartlist_free(data.rdv_data.link_specifiers);
1398 memwipe(&data, 0, sizeof(data));
1399 return ret;
1400}
1401
1402/** Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
1403 * exchange output material at <b>ntor_key_seed</b> and setup <b>circ</b> to
1404 * serve as a rendezvous end-to-end circuit between the client and the
1405 * service. If <b>is_service_side</b> is set, then we are the hidden service
1406 * and the other side is the client.
1407 *
1408 * Return 0 if the operation went well; in case of error return -1. */
1409int
1411 const uint8_t *ntor_key_seed, size_t seed_len,
1412 int is_service_side)
1413{
1414 if (BUG(!circuit_purpose_is_correct_for_rend(TO_CIRCUIT(circ)->purpose,
1415 is_service_side))) {
1416 return -1;
1417 }
1418
1419 crypt_path_t *hop = create_rend_cpath(ntor_key_seed, seed_len,
1420 is_service_side);
1421 if (!hop) {
1422 log_warn(LD_REND, "Couldn't get v3 %s cpath!",
1423 is_service_side ? "service-side" : "client-side");
1424 return -1;
1425 }
1426
1427 finalize_rend_circuit(circ, hop, is_service_side);
1428
1429 return 0;
1430}
1431
1432/** Given the introduction circuit intro_circ, the rendezvous circuit
1433 * rend_circ, a descriptor intro point object ip and the service's
1434 * subcredential, send an INTRODUCE1 cell on intro_circ.
1435 *
1436 * This will also setup the circuit identifier on rend_circ containing the key
1437 * material for the handshake and e2e encryption. Return 0 on success else
1438 * negative value. Because relay_send_command_from_edge() closes the circuit
1439 * on error, it is possible that intro_circ is closed on error. */
1440int
1442 origin_circuit_t *rend_circ,
1443 const hs_desc_intro_point_t *ip,
1444 const hs_subcredential_t *subcredential,
1445 const hs_pow_solution_t *pow_solution)
1446{
1447 int ret = -1;
1448 ssize_t payload_len;
1449 uint8_t payload[RELAY_PAYLOAD_SIZE_MAX] = {0};
1450 hs_cell_introduce1_data_t intro1_data;
1451
1452 tor_assert(intro_circ);
1453 tor_assert(rend_circ);
1454 tor_assert(ip);
1455 tor_assert(subcredential);
1456
1457 /* It is undefined behavior in hs_cell_introduce1_data_clear() if intro1_data
1458 * has been declared on the stack but not initialized. Here, we set it to 0.
1459 */
1460 memset(&intro1_data, 0, sizeof(hs_cell_introduce1_data_t));
1461
1462 /* This takes various objects in order to populate the introduce1 data
1463 * object which is used to build the content of the cell. */
1464 const node_t *exit_node = build_state_get_exit_node(rend_circ->build_state);
1465 if (exit_node == NULL) {
1466 log_info(LD_REND, "Unable to get rendezvous point for circuit %u. "
1467 "Failing.", TO_CIRCUIT(intro_circ)->n_circ_id);
1468 goto done;
1469 }
1470
1471 /* We should never select an invalid rendezvous point in theory but if we
1472 * do, this function will fail to populate the introduce data. */
1473 if (setup_introduce1_data(ip, exit_node, subcredential, &intro1_data) < 0) {
1474 log_info(LD_REND, "Unable to setup INTRODUCE1 data. The chosen rendezvous "
1475 "point is unusable. Closing circuit.");
1476 goto close;
1477 }
1478
1479 /* Set the PoW solution if any. */
1480 intro1_data.pow_solution = pow_solution;
1481
1482 /* If the rend circ was set up for congestion control, add that to the
1483 * intro data, to signal it in an extension */
1484 if (TO_CIRCUIT(rend_circ)->ccontrol) {
1485 intro1_data.cc_enabled = 1;
1486 }
1487
1488 /* Final step before we encode a cell, we setup the circuit identifier which
1489 * will generate both the rendezvous cookie and client keypair for this
1490 * connection. Those are put in the ident. */
1491 intro1_data.rendezvous_cookie = rend_circ->hs_ident->rendezvous_cookie;
1492 intro1_data.client_kp = &rend_circ->hs_ident->rendezvous_client_kp;
1493
1494 memcpy(intro_circ->hs_ident->rendezvous_cookie,
1495 rend_circ->hs_ident->rendezvous_cookie,
1496 sizeof(intro_circ->hs_ident->rendezvous_cookie));
1497
1498 /* From the introduce1 data object, this will encode the INTRODUCE1 cell
1499 * into payload which is then ready to be sent as is. */
1500 payload_len = hs_cell_build_introduce1(&intro1_data, payload);
1501 if (BUG(payload_len < 0)) {
1502 goto close;
1503 }
1504
1505 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(intro_circ),
1506 RELAY_COMMAND_INTRODUCE1,
1507 (const char *) payload, payload_len,
1508 intro_circ->cpath->prev) < 0) {
1509 /* On error, circuit is closed. */
1510 log_warn(LD_REND, "Unable to send INTRODUCE1 cell on circuit %u.",
1511 TO_CIRCUIT(intro_circ)->n_circ_id);
1512 goto done;
1513 }
1514
1515 /* Success. */
1516 ret = 0;
1517 goto done;
1518
1519 close:
1520 circuit_mark_for_close(TO_CIRCUIT(rend_circ), END_CIRC_REASON_INTERNAL);
1521 done:
1522 hs_cell_introduce1_data_clear(&intro1_data);
1523 memwipe(payload, 0, sizeof(payload));
1524 return ret;
1525}
1526
1527/** Send an ESTABLISH_RENDEZVOUS cell along the rendezvous circuit circ. On
1528 * success, 0 is returned else -1 and the circuit is marked for close. */
1529int
1531{
1532 ssize_t cell_len = 0;
1533 uint8_t cell[RELAY_PAYLOAD_SIZE_MAX] = {0};
1534
1535 tor_assert(circ);
1537
1538 log_info(LD_REND, "Send an ESTABLISH_RENDEZVOUS cell on circuit %u",
1539 TO_CIRCUIT(circ)->n_circ_id);
1540
1541 /* Set timestamp_dirty, because circuit_expire_building expects it,
1542 * and the rend cookie also means we've used the circ. */
1543 TO_CIRCUIT(circ)->timestamp_dirty = time(NULL);
1544
1545 /* We've attempted to use this circuit. Probe it if we fail */
1547
1548 /* Generate the RENDEZVOUS_COOKIE and place it in the identifier so we can
1549 * complete the handshake when receiving the acknowledgement. */
1551 /* Generate the client keypair. No need to be extra strong, not long term */
1553
1554 cell_len =
1556 cell);
1557 if (BUG(cell_len < 0)) {
1558 goto err;
1559 }
1560
1561 if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
1562 RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
1563 (const char *) cell, cell_len,
1564 circ->cpath->prev) < 0) {
1565 /* Circuit has been marked for close */
1566 log_warn(LD_REND, "Unable to send ESTABLISH_RENDEZVOUS cell on "
1567 "circuit %u", TO_CIRCUIT(circ)->n_circ_id);
1568 memwipe(cell, 0, cell_len);
1569 goto err;
1570 }
1571
1572 memwipe(cell, 0, cell_len);
1573 return 0;
1574 err:
1575 return -1;
1576}
1577
1578/** Circuit cleanup strategy:
1579 *
1580 * What follows is a series of functions that notifies the HS subsystem of 3
1581 * different circuit cleanup phase: close, free and repurpose.
1582 *
1583 * Tor can call any of those in any orders so they have to be safe between
1584 * each other. In other words, the free should never depend on close to be
1585 * called before.
1586 *
1587 * The "on_close()" is called from circuit_mark_for_close() which is
1588 * considered the tor fast path and thus as little work as possible should
1589 * done in that function. Currently, we only remove the circuit from the HS
1590 * circuit map and move on.
1591 *
1592 * The "on_free()" is called from circuit circuit_free_() and it is very
1593 * important that at the end of the function, no state or objects related to
1594 * this circuit remains alive.
1595 *
1596 * The "on_repurpose()" is called from circuit_change_purpose() for which we
1597 * simply remove it from the HS circuit map. We do not have other cleanup
1598 * requirements after that.
1599 *
1600 * NOTE: The onion service code, specifically the service code, cleans up
1601 * lingering objects or state if any of its circuit disappear which is why
1602 * our cleanup strategy doesn't involve any service specific actions. As long
1603 * as the circuit is removed from the HS circuit map, it won't be used.
1604 */
1605
1606/** We are about to close this <b>circ</b>. Clean it up from any related HS
1607 * data structures. This function can be called multiple times safely for the
1608 * same circuit. */
1609void
1611{
1612 tor_assert(circ);
1613
1616 }
1617
1619 if (circuit_is_hs_v3(circ)) {
1621 }
1622 }
1623
1624 /* On close, we simply remove it from the circuit map. It can not be used
1625 * anymore. We keep this code path fast and lean. */
1626
1627 if (circ->hs_token) {
1629 }
1630}
1631
1632/** We are about to free this <b>circ</b>. Clean it up from any related HS
1633 * data structures. This function can be called multiple times safely for the
1634 * same circuit. */
1635void
1637{
1638 tor_assert(circ);
1639
1640 /* NOTE: Bulk of the work of cleaning up a circuit is done here. */
1641
1644 }
1645
1646 /* We have no assurance that the given HS circuit has been closed before and
1647 * thus removed from the HS map. This actually happens in unit tests. */
1648 if (circ->hs_token) {
1650 }
1651}
1652
1653/** We are about to repurpose this <b>circ</b>. Clean it up from any related
1654 * HS data structures. This function can be called multiple times safely for
1655 * the same circuit. */
1656void
1658{
1659 tor_assert(circ);
1660
1661 /* On repurpose, we simply remove it from the circuit map but we do not do
1662 * the on_free actions since we don't treat a repurpose as something we need
1663 * to report in the client cache failure. */
1664
1665 if (circ->hs_token) {
1667 }
1668
1669 switch (circ->purpose) {
1671 /* This circuit was connecting to a rendezvous point but it is being
1672 * repurposed so we need to relaunch an attempt else the client will be
1673 * left hanging waiting for the rendezvous. */
1675 break;
1676 default:
1677 break;
1678 }
1679}
1680
1681/** Return true iff the given established client rendezvous circuit was sent
1682 * into the INTRODUCE1 cell. This is called so we can take a decision on
1683 * expiring or not the circuit.
1684 *
1685 * The caller MUST make sure the circuit is an established client rendezvous
1686 * circuit (purpose: CIRCUIT_PURPOSE_C_REND_READY).
1687 *
1688 * This function supports all onion service versions. */
1689bool
1691{
1692 tor_assert(circ);
1693 /* This can only be called for a rendezvous circuit that is an established
1694 * confirmed rendezsvous circuit but without an introduction ACK. */
1696
1697 /* When the INTRODUCE1 cell is sent, the introduction encryption public
1698 * key is copied in the rendezvous circuit hs identifier. If it is a valid
1699 * key, we know that this circuit is waiting the ACK on the introduction
1700 * circuit. We want to _not_ spare the circuit if the key was never set. */
1701
1702 if (circ->hs_ident) {
1703 /* v3. */
1705 return true;
1706 }
1707 } else {
1708 /* A circuit with an HS purpose without an hs_ident in theory can not
1709 * happen. In case, scream loudly and return false to the caller that the
1710 * rendezvous was not sent in the INTRO1 cell. */
1712 }
1713
1714 /* The rendezvous has not been specified in the INTRODUCE1 cell. */
1715 return false;
1716}
const char * hex_str(const char *from, size_t fromlen)
Definition: binascii.c:34
void pathbias_count_use_attempt(origin_circuit_t *circ)
Definition: circpathbias.c:626
void pathbias_mark_use_success(origin_circuit_t *circ)
Definition: circpathbias.c:683
void circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
Definition: circuitbuild.c:358
const node_t * build_state_get_exit_node(cpath_build_state_t *state)
Header file for circuitbuild.c.
origin_circuit_t * circuit_get_next_by_purpose(origin_circuit_t *start, uint8_t purpose)
Definition: circuitlist.c:1804
origin_circuit_t * TO_ORIGIN_CIRCUIT(circuit_t *x)
Definition: circuitlist.c:185
int32_t circuit_initial_package_window(void)
Definition: circuitlist.c:1007
Header file for circuitlist.c.
#define CIRCUIT_PURPOSE_S_CONNECT_REND
Definition: circuitlist.h:107
#define CIRCUIT_STATE_OPEN
Definition: circuitlist.h:32
#define CIRCUIT_PURPOSE_C_REND_JOINED
Definition: circuitlist.h:88
#define CIRCUIT_PURPOSE_S_INTRO
Definition: circuitlist.h:104
#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED
Definition: circuitlist.h:86
#define CIRCUIT_PURPOSE_S_REND_JOINED
Definition: circuitlist.h:110
#define CIRCUIT_PURPOSE_C_REND_READY
Definition: circuitlist.h:83
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
Definition: circuitlist.h:101
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND
Definition: circuitlist.h:81
#define CIRCUIT_PURPOSE_C_GENERAL
Definition: circuitlist.h:70
#define CIRCUIT_PURPOSE_HS_VANGUARDS
Definition: circuitlist.h:131
bool circuit_is_hs_v3(const circuit_t *circ)
Definition: circuituse.c:2001
bool circuit_purpose_is_hs_service(const uint8_t purpose)
Definition: circuituse.c:1986
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
Definition: circuituse.c:3099
int circuit_should_use_vanguards(uint8_t purpose)
Definition: circuituse.c:2018
void circuit_has_opened(origin_circuit_t *circ)
Definition: circuituse.c:1664
bool circuit_purpose_is_hs_client(const uint8_t purpose)
Definition: circuituse.c:1978
origin_circuit_t * circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info, int flags)
Definition: circuituse.c:2094
void circuit_try_attaching_streams(origin_circuit_t *circ)
Definition: circuituse.c:1744
Header file for circuituse.c.
#define CIRCLAUNCH_NEED_CAPACITY
Definition: circuituse.h:43
#define CIRCLAUNCH_ONEHOP_TUNNEL
Definition: circuituse.h:39
#define CIRCLAUNCH_IS_INTERNAL
Definition: circuituse.h:46
#define CIRCLAUNCH_NEED_UPTIME
Definition: circuituse.h:41
#define MAX(a, b)
Definition: cmp.h:22
mainloop_event_t * mainloop_event_postloop_new(void(*cb)(mainloop_event_t *, void *), void *userdata)
int mainloop_event_schedule(mainloop_event_t *event, const struct timeval *tv)
void mainloop_event_activate(mainloop_event_t *event)
Functions and types for monotonic times.
const or_options_t * get_options(void)
Definition: config.c:947
Header file for config.c.
congestion_control_t * congestion_control_new(const circuit_params_t *params, cc_path_t path)
Public APIs for congestion control.
static uint8_t congestion_control_sendme_inc(void)
Structure definitions for congestion control.
Circuit-build-stse structure.
int cpath_init_circuit_crypto(relay_crypto_alg_t alg, crypt_path_t *cpath, const char *key_data, size_t key_data_len)
Definition: crypt_path.c:148
void cpath_extend_linked_list(crypt_path_t **head_ptr, crypt_path_t *new_hop)
Definition: crypt_path.c:42
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)
Headers for crypto_dh.c.
void ed25519_pubkey_copy(ed25519_public_key_t *dest, const ed25519_public_key_t *src)
int ed25519_public_key_is_zero(const ed25519_public_key_t *pubkey)
int ed25519_pubkey_eq(const ed25519_public_key_t *key1, const ed25519_public_key_t *key2)
void crypto_rand(char *to, size_t n)
Definition: crypto_rand.c:479
Common functions for using (pseudo-)random number generators.
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
Common functions for cryptographic routines.
const char * extend_info_describe(const extend_info_t *ei)
Definition: describe.c:224
Header file for describe.c.
#define DIGEST256_LEN
Definition: digest_sizes.h:23
Extend-info structure.
Header for core/or/extendinfo.c.
ssize_t hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie, uint8_t *cell_out)
Definition: hs_cell.c:1219
ssize_t hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, const origin_circuit_t *circ, const hs_service_t *service, const hs_service_intro_point_t *ip)
Definition: hs_cell.c:974
ssize_t hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
Definition: hs_cell.c:780
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)
Definition: hs_cell.c:665
void hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data)
Definition: hs_cell.c:1286
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)
Definition: hs_cell.c:1142
ssize_t hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data, uint8_t *cell_out)
Definition: hs_cell.c:1178
Header file containing cell data for the whole HS subsystem.
int top_of_rend_pqueue_is_worthwhile(hs_pow_service_state_t *pow_state)
Definition: hs_circuit.c:737
static int queued_rend_request_is_too_old(pending_rend_t *req, time_t now)
Definition: hs_circuit.c:659
void hs_circ_service_rp_has_opened(const hs_service_t *service, origin_circuit_t *circ)
Definition: hs_circuit.c:1156
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)
Definition: hs_circuit.c:1277
origin_circuit_t * hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
Definition: hs_circuit.c:966
void hs_circ_cleanup_on_repurpose(circuit_t *circ)
Definition: hs_circuit.c:1657
static void cleanup_on_close_client_circ(circuit_t *circ)
Definition: hs_circuit.c:607
static void register_intro_circ(const hs_service_intro_point_t *ip, origin_circuit_t *circ)
Definition: hs_circuit.c:166
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, const hs_pow_solution_t *pow_solution)
Definition: hs_circuit.c:1441
int hs_circ_launch_intro_point(hs_service_t *service, const hs_service_intro_point_t *ip, extend_info_t *ei, bool direct_conn)
Definition: hs_circuit.c:1030
static void finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop, int is_service_side)
Definition: hs_circuit.c:131
void hs_circ_setup_congestion_control(origin_circuit_t *origin_circ, uint8_t sendme_inc, bool is_single_onion)
Definition: hs_circuit.c:933
static int count_service_rp_circuits_pending(hs_service_t *service)
Definition: hs_circuit.c:716
origin_circuit_t * hs_circ_service_get_established_intro_circ(const hs_service_intro_point_t *ip)
Definition: hs_circuit.c:977
static hs_ident_circuit_t * create_intro_circuit_identifier(const hs_service_t *service, const hs_service_intro_point_t *ip)
Definition: hs_circuit.c:250
static void retry_service_rendezvous_point(const origin_circuit_t *circ)
Definition: hs_circuit.c:494
static void free_pending_rend(pending_rend_t *req)
Definition: hs_circuit.c:53
#define MAX_CHEAP_REND_CIRCUITS_IN_PROGRESS
Definition: hs_circuit.c:766
void rend_pqueue_clear(hs_pow_service_state_t *pow_state)
Definition: hs_circuit.c:753
static void trim_rend_pqueue(hs_pow_service_state_t *pow_state, time_t now)
Definition: hs_circuit.c:670
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)
Definition: hs_circuit.c:1088
STATIC void launch_rendezvous_point_circuit(const hs_service_t *service, const ed25519_public_key_t *ip_auth_pubkey, const curve25519_keypair_t *ip_enc_key_kp, const hs_cell_intro_rdv_data_t *rdv_data, time_t now)
Definition: hs_circuit.c:336
static void cleanup_on_free_client_circ(circuit_t *circ)
Definition: hs_circuit.c:621
void hs_circ_cleanup_on_close(circuit_t *circ)
Definition: hs_circuit.c:1610
static int compare_rend_request_by_effort_(const void *_a, const void *_b)
Definition: hs_circuit.c:635
static void send_establish_intro(const hs_service_t *service, hs_service_intro_point_t *ip, origin_circuit_t *circ)
Definition: hs_circuit.c:271
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)
Definition: hs_circuit.c:1307
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)
Definition: hs_circuit.c:1228
static int can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
Definition: hs_circuit.c:458
static unsigned int count_opened_desc_intro_point_circuits(const hs_service_t *service, const hs_service_descriptor_t *desc)
Definition: hs_circuit.c:179
bool hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ)
Definition: hs_circuit.c:1690
void hs_circ_retry_service_rendezvous_point(const origin_circuit_t *circ)
Definition: hs_circuit.c:1004
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)
Definition: hs_circuit.c:211
static int circuit_purpose_is_correct_for_rend(unsigned int circ_purpose, int is_service_side)
Definition: hs_circuit.c:67
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)
Definition: hs_circuit.c:563
int hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
Definition: hs_circuit.c:1530
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)
Definition: hs_circuit.c:1410
void hs_circ_cleanup_on_free(circuit_t *circ)
Definition: hs_circuit.c:1636
static int enqueue_rend_request(const hs_service_t *service, hs_service_intro_point_t *ip, hs_cell_introduce2_data_t *data, time_t now)
Definition: hs_circuit.c:866
static crypt_path_t * create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len, int is_service_side)
Definition: hs_circuit.c:97
static const char * get_service_anonymity_string(const hs_service_t *service)
Definition: hs_circuit.c:317
Header file containing circuit data for the whole HS subsystem.
void hs_circuitmap_remove_circuit(circuit_t *circ)
void hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ, const ed25519_public_key_t *auth_key)
origin_circuit_t * hs_circuitmap_get_intro_circ_v3_service_side(const ed25519_public_key_t *auth_key)
Header file for hs_circuitmap.c.
void hs_client_circuit_cleanup_on_close(const circuit_t *circ)
Definition: hs_client.c:2048
void hs_client_circuit_cleanup_on_free(const circuit_t *circ)
Definition: hs_client.c:2079
Header file containing client data for the HS subsystem.
int hs_get_service_max_rend_failures(void)
Definition: hs_common.c:233
extend_info_t * hs_get_extend_info_from_lspecs(const smartlist_t *lspecs, const curve25519_public_key_t *onion_key, int direct_conn)
Definition: hs_common.c:1596
int hs_service_requires_uptime_circ(const smartlist_t *ports)
Definition: hs_common.c:1016
Header file containing common data for the whole HS subsystem.
#define HS_LEGACY_RENDEZVOUS_CELL_SIZE
Definition: hs_common.h:121
#define MAX_REND_FAILURES
Definition: hs_common.h:44
#define MAX_REND_TIMEOUT
Definition: hs_common.h:47
hs_ident_circuit_t * hs_ident_circuit_new(const ed25519_public_key_t *identity_pk)
Definition: hs_ident.c:16
hs_ident_circuit_t * hs_ident_circuit_dup(const hs_ident_circuit_t *src)
Definition: hs_ident.c:37
Header file containing circuit and connection identifier data for the whole HS subsystem.
#define HS_REND_COOKIE_LEN
Definition: hs_ident.h:30
Header for feature/hs/hs_metrics.c.
#define hs_metrics_new_rdv(i)
Definition: hs_metrics.h:74
#define hs_metrics_pow_pqueue_rdv(s, n)
Definition: hs_metrics.h:78
#define hs_metrics_failed_rdv(i, reason)
Definition: hs_metrics.h:63
#define hs_metrics_reject_intro_req(s, reason)
Definition: hs_metrics.h:42
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)
Definition: hs_ntor.c:615
Header for hs_ntor.c.
bool hs_ob_service_is_instance(const hs_service_t *service)
Definition: hs_ob.c:201
Header file for the specific code for onion balance.
void hs_service_circuit_cleanup_on_close(const circuit_t *circ)
Definition: hs_service.c:3942
Header file containing service data for the HS subsystem.
#define log_fn(severity, domain, args,...)
Definition: log.h:283
#define LD_REND
Definition: log.h:84
#define LD_BUG
Definition: log.h:86
#define LD_GENERAL
Definition: log.h:62
#define LD_CIRC
Definition: log.h:82
#define LOG_INFO
Definition: log.h:45
#define tor_free(p)
Definition: malloc.h:56
Node information structure.
const curve25519_public_key_t * node_get_curve25519_onion_key(const node_t *node)
Definition: nodelist.c:2059
Header file for nodelist.c.
Header file for onion_crypto.c.
Master header file for Tor-specific functionality.
#define REND_COOKIE_LEN
Definition: or.h:401
#define TO_CIRCUIT(x)
Definition: or.h:947
#define CIRCWINDOW_START
Definition: or.h:442
#define RELAY_PAYLOAD_SIZE_MAX
Definition: or.h:572
@ RELAY_CELL_FORMAT_V0
Definition: or.h:536
Origin circuit structure.
Header file for policies.c.
Header file for relay.c.
relay_crypto_alg_t
Definition: relay_crypto.h:16
@ RELAY_CRYPTO_ALG_TOR1_HSS
Definition: relay_crypto.h:26
@ RELAY_CRYPTO_ALG_TOR1_HSC
Definition: relay_crypto.h:22
Header file for rephist.c.
int replaycache_add_test_and_elapsed(replaycache_t *r, const void *data, size_t len, time_t *elapsed)
Definition: replaycache.c:195
void * smartlist_pqueue_pop(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset)
Definition: smartlist.c:755
void smartlist_pqueue_add(smartlist_t *sl, int(*compare)(const void *a, const void *b), ptrdiff_t idx_field_offset, void *item)
Definition: smartlist.c:726
void * smartlist_pop_last(smartlist_t *sl)
smartlist_t * smartlist_new(void)
#define SMARTLIST_FOREACH_BEGIN(sl, type, var)
uint8_t sendme_inc_cells
Definition: onion_crypto.h:37
struct hs_token_t * hs_token
Definition: circuit_st.h:227
uint8_t state
Definition: circuit_st.h:111
uint16_t marked_for_close
Definition: circuit_st.h:200
uint8_t purpose
Definition: circuit_st.h:112
struct congestion_control_t * ccontrol
Definition: circuit_st.h:260
extend_info_t * chosen_exit
struct crypt_path_t * prev
Definition: crypt_path_st.h:78
uint8_t state
Definition: crypt_path_st.h:71
relay_cell_fmt_t relay_cell_format
Definition: crypt_path_st.h:90
char rend_circ_nonce[DIGEST_LEN]
Definition: crypt_path_st.h:61
struct congestion_control_t * ccontrol
Definition: crypt_path_st.h:87
curve25519_public_key_t onion_pk
Definition: hs_cell.h:54
uint8_t rendezvous_cookie[REND_COOKIE_LEN]
Definition: hs_cell.h:56
unsigned int cc_enabled
Definition: hs_cell.h:62
curve25519_public_key_t client_pk
Definition: hs_cell.h:58
smartlist_t * link_specifiers
Definition: hs_cell.h:60
const ed25519_public_key_t * auth_pk
Definition: hs_cell.h:31
const struct hs_subcredential_t * subcredential
Definition: hs_cell.h:35
const hs_pow_solution_t * pow_solution
Definition: hs_cell.h:47
const curve25519_keypair_t * client_kp
Definition: hs_cell.h:41
const curve25519_public_key_t * enc_pk
Definition: hs_cell.h:33
unsigned int cc_enabled
Definition: hs_cell.h:45
const uint8_t * rendezvous_cookie
Definition: hs_cell.h:39
const curve25519_public_key_t * onion_pk
Definition: hs_cell.h:37
smartlist_t * link_specifiers
Definition: hs_cell.h:43
const ed25519_public_key_t * auth_pk
Definition: hs_cell.h:77
const curve25519_keypair_t * enc_kp
Definition: hs_cell.h:81
replaycache_t * replay_cache
Definition: hs_cell.h:100
const struct hs_subcredential_t * subcredentials
Definition: hs_cell.h:89
const uint8_t * payload
Definition: hs_cell.h:91
hs_cell_intro_rdv_data_t rdv_data
Definition: hs_cell.h:98
curve25519_public_key_t enc_key
tor_cert_t * auth_key_cert
uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN]
Definition: hs_ident.h:60
ed25519_public_key_t intro_auth_pk
Definition: hs_ident.h:51
curve25519_keypair_t rendezvous_client_kp
Definition: hs_ident.h:72
curve25519_public_key_t intro_enc_pk
Definition: hs_ident.h:55
uint8_t rendezvous_ntor_key_seed[DIGEST256_LEN]
Definition: hs_ident.h:76
ed25519_public_key_t identity_pk
Definition: hs_ident.h:45
uint8_t rendezvous_handshake_info[CURVE25519_PUBKEY_LEN+DIGEST256_LEN]
Definition: hs_ident.h:68
unsigned int is_single_onion
Definition: hs_service.h:252
smartlist_t * ports
Definition: hs_service.h:223
unsigned int num_intro_points
Definition: hs_service.h:240
unsigned int has_pow_defenses_enabled
Definition: hs_service.h:270
hs_service_intropoints_t intro_points
Definition: hs_service.h:172
ed25519_keypair_t auth_key_kp
Definition: hs_service.h:60
replaycache_t * replay_cache
Definition: hs_service.h:94
curve25519_keypair_t enc_key_kp
Definition: hs_service.h:63
digest256map_t * map
Definition: hs_service.h:113
ed25519_public_key_t identity_pk
Definition: hs_service.h:188
replaycache_t * replay_cache_rend_cookie
Definition: hs_service.h:295
hs_pow_service_state_t * pow_state
Definition: hs_service.h:311
unsigned int num_intro_circ_launched
Definition: hs_service.h:288
hs_service_state_t state
Definition: hs_service.h:325
char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1]
Definition: hs_service.h:318
hs_service_config_t config
Definition: hs_service.h:331
hs_service_keys_t keys
Definition: hs_service.h:328
Definition: node_st.h:34
struct hs_ident_circuit_t * hs_ident
crypt_path_t * cpath
cpath_build_state_t * build_state
unsigned int hs_with_pow_circ
time_t enqueued_ts
Definition: hs_circuit.h:32
ed25519_public_key_t signed_key
Definition: torcert.h:33
#define STATIC
Definition: testsupport.h:32
#define MOCK_IMPL(rv, funcname, arglist)
Definition: testsupport.h:133
void token_bucket_ctr_refill(token_bucket_ctr_t *bucket, uint32_t now_ts_sec)
Definition: token_bucket.c:296
#define tor_assert_nonfatal_unreached()
Definition: util_bug.h:177
#define tor_assert(expr)
Definition: util_bug.h:103
#define CURVE25519_PUBKEY_LEN
Definition: x25519_sizes.h:20