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