Tor  0.4.3.0-alpha-dev
hs_circuit.c
Go to the documentation of this file.
1 /* Copyright (c) 2017-2020, 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"
13 #include "core/or/circuitbuild.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 "feature/client/circpathbias.h"
20 #include "feature/hs/hs_cell.h"
21 #include "feature/hs/hs_circuit.h"
23 #include "feature/hs/hs_client.h"
24 #include "feature/hs/hs_ident.h"
25 #include "feature/hs/hs_service.h"
30 #include "feature/stats/rephist.h"
34 
35 /* Trunnel. */
36 #include "trunnel/ed25519_cert.h"
37 #include "trunnel/hs/cell_common.h"
38 #include "trunnel/hs/cell_establish_intro.h"
39 
41 #include "core/or/crypt_path_st.h"
44 
45 /** A circuit is about to become an e2e rendezvous circuit. Check
46  * <b>circ_purpose</b> and ensure that it's properly set. Return true iff
47  * circuit purpose is properly set, otherwise return false. */
48 static int
49 circuit_purpose_is_correct_for_rend(unsigned int circ_purpose,
50  int is_service_side)
51 {
52  if (is_service_side) {
53  if (circ_purpose != CIRCUIT_PURPOSE_S_CONNECT_REND) {
54  log_warn(LD_BUG,
55  "HS e2e circuit setup with wrong purpose (%d)", circ_purpose);
56  return 0;
57  }
58  }
59 
60  if (!is_service_side) {
61  if (circ_purpose != CIRCUIT_PURPOSE_C_REND_READY &&
63  log_warn(LD_BUG,
64  "Client e2e circuit setup with wrong purpose (%d)", circ_purpose);
65  return 0;
66  }
67  }
68 
69  return 1;
70 }
71 
72 /** Create and return a crypt path for the final hop of a v3 prop224 rendezvous
73  * circuit. Initialize the crypt path crypto using the output material from the
74  * ntor key exchange at <b>ntor_key_seed</b>.
75  *
76  * If <b>is_service_side</b> is set, we are the hidden service and the final
77  * hop of the rendezvous circuit is the client on the other side. */
78 static crypt_path_t *
79 create_rend_cpath(const uint8_t *ntor_key_seed, size_t seed_len,
80  int is_service_side)
81 {
82  uint8_t keys[HS_NTOR_KEY_EXPANSION_KDF_OUT_LEN];
83  crypt_path_t *cpath = NULL;
84 
85  /* Do the key expansion */
86  if (hs_ntor_circuit_key_expansion(ntor_key_seed, seed_len,
87  keys, sizeof(keys)) < 0) {
88  goto err;
89  }
90 
91  /* Setup the cpath */
92  cpath = tor_malloc_zero(sizeof(crypt_path_t));
93  cpath->magic = CRYPT_PATH_MAGIC;
94 
95  if (cpath_init_circuit_crypto(cpath, (char*)keys, sizeof(keys),
96  is_service_side, 1) < 0) {
97  tor_free(cpath);
98  goto err;
99  }
100 
101  err:
102  memwipe(keys, 0, sizeof(keys));
103  return cpath;
104 }
105 
106 /** We are a v2 legacy HS client: Create and return a crypt path for the hidden
107  * service on the other side of the rendezvous circuit <b>circ</b>. Initialize
108  * the crypt path crypto using the body of the RENDEZVOUS1 cell at
109  * <b>rend_cell_body</b> (which must be at least DH1024_KEY_LEN+DIGEST_LEN
110  * bytes).
111  */
112 static crypt_path_t *
113 create_rend_cpath_legacy(origin_circuit_t *circ, const uint8_t *rend_cell_body)
114 {
115  crypt_path_t *hop = NULL;
116  char keys[DIGEST_LEN+CPATH_KEY_MATERIAL_LEN];
117 
118  /* first DH1024_KEY_LEN bytes are g^y from the service. Finish the dh
119  * handshake...*/
120  tor_assert(circ->build_state);
122  hop = circ->build_state->pending_final_cpath;
123 
125  if (crypto_dh_compute_secret(LOG_PROTOCOL_WARN, hop->rend_dh_handshake_state,
126  (char*)rend_cell_body, DH1024_KEY_LEN,
127  keys, DIGEST_LEN+CPATH_KEY_MATERIAL_LEN)<0) {
128  log_warn(LD_GENERAL, "Couldn't complete DH handshake.");
129  goto err;
130  }
131  /* ... and set up cpath. */
133  keys+DIGEST_LEN, sizeof(keys)-DIGEST_LEN,
134  0, 0) < 0)
135  goto err;
136 
137  /* Check whether the digest is right... */
138  if (tor_memneq(keys, rend_cell_body+DH1024_KEY_LEN, DIGEST_LEN)) {
139  log_warn(LD_PROTOCOL, "Incorrect digest of key material.");
140  goto err;
141  }
142 
143  /* clean up the crypto stuff we just made */
144  crypto_dh_free(hop->rend_dh_handshake_state);
145  hop->rend_dh_handshake_state = NULL;
146 
147  goto done;
148 
149  err:
150  hop = NULL;
151 
152  done:
153  memwipe(keys, 0, sizeof(keys));
154  return hop;
155 }
156 
157 /** Append the final <b>hop</b> to the cpath of the rend <b>circ</b>, and mark
158  * <b>circ</b> ready for use to transfer HS relay cells. */
159 static void
161  int is_service_side)
162 {
163  tor_assert(circ);
164  tor_assert(hop);
165 
166  /* Notify the circuit state machine that we are splicing this circuit */
167  int new_circ_purpose = is_service_side ?
169  circuit_change_purpose(TO_CIRCUIT(circ), new_circ_purpose);
170 
171  /* All is well. Extend the circuit. */
172  hop->state = CPATH_STATE_OPEN;
173  /* Set the windows to default. */
176 
177  /* Now that this circuit has finished connecting to its destination,
178  * make sure circuit_get_open_circ_or_launch is willing to return it
179  * so we can actually use it. */
180  circ->hs_circ_has_timed_out = 0;
181 
182  /* Append the hop to the cpath of this circuit */
183  cpath_extend_linked_list(&circ->cpath, hop);
184 
185  /* In legacy code, 'pending_final_cpath' points to the final hop we just
186  * appended to the cpath. We set the original pointer to NULL so that we
187  * don't double free it. */
188  if (circ->build_state) {
189  circ->build_state->pending_final_cpath = NULL;
190  }
191 
192  /* Finally, mark circuit as ready to be used for client streams */
193  if (!is_service_side) {
195  }
196 }
197 
198 /** For a given circuit and a service introduction point object, register the
199  * intro circuit to the circuitmap. This supports legacy intro point. */
200 static void
202  origin_circuit_t *circ)
203 {
204  tor_assert(ip);
205  tor_assert(circ);
206 
207  if (ip->base.is_only_legacy) {
209  ip->legacy_key_digest);
210  } else {
212  &ip->auth_key_kp.pubkey);
213  }
214 }
215 
216 /** Return the number of opened introduction circuit for the given circuit that
217  * is matching its identity key. */
218 static unsigned int
220  const hs_service_descriptor_t *desc)
221 {
222  unsigned int count = 0;
223 
224  tor_assert(service);
225  tor_assert(desc);
226 
227  DIGEST256MAP_FOREACH(desc->intro_points.map, key,
228  const hs_service_intro_point_t *, ip) {
229  const circuit_t *circ;
231  if (ocirc == NULL) {
232  continue;
233  }
234  circ = TO_CIRCUIT(ocirc);
237  /* Having a circuit not for the requested service is really bad. */
239  &ocirc->hs_ident->identity_pk));
240  /* Only count opened circuit and skip circuit that will be closed. */
241  if (!circ->marked_for_close && circ->state == CIRCUIT_STATE_OPEN) {
242  count++;
243  }
244  } DIGEST256MAP_FOREACH_END;
245  return count;
246 }
247 
248 /** From a given service, rendezvous cookie and handshake info, create a
249  * rendezvous point circuit identifier. This can't fail. */
252  const uint8_t *rendezvous_cookie,
253  const curve25519_public_key_t *server_pk,
254  const hs_ntor_rend_cell_keys_t *keys)
255 {
256  hs_ident_circuit_t *ident;
257  uint8_t handshake_info[CURVE25519_PUBKEY_LEN + DIGEST256_LEN];
258 
259  tor_assert(service);
260  tor_assert(rendezvous_cookie);
261  tor_assert(server_pk);
262  tor_assert(keys);
263 
264  ident = hs_ident_circuit_new(&service->keys.identity_pk);
265  /* Copy the RENDEZVOUS_COOKIE which is the unique identifier. */
266  memcpy(ident->rendezvous_cookie, rendezvous_cookie,
267  sizeof(ident->rendezvous_cookie));
268  /* Build the HANDSHAKE_INFO which looks like this:
269  * SERVER_PK [32 bytes]
270  * AUTH_INPUT_MAC [32 bytes]
271  */
272  memcpy(handshake_info, server_pk->public_key, CURVE25519_PUBKEY_LEN);
273  memcpy(handshake_info + CURVE25519_PUBKEY_LEN, keys->rend_cell_auth_mac,
274  DIGEST256_LEN);
275  tor_assert(sizeof(ident->rendezvous_handshake_info) ==
276  sizeof(handshake_info));
277  memcpy(ident->rendezvous_handshake_info, handshake_info,
278  sizeof(ident->rendezvous_handshake_info));
279  /* Finally copy the NTOR_KEY_SEED for e2e encryption on the circuit. */
280  tor_assert(sizeof(ident->rendezvous_ntor_key_seed) ==
281  sizeof(keys->ntor_key_seed));
282  memcpy(ident->rendezvous_ntor_key_seed, keys->ntor_key_seed,
283  sizeof(ident->rendezvous_ntor_key_seed));
284  return ident;
285 }
286 
287 /** From a given service and service intro point, create an introduction point
288  * circuit identifier. This can't fail. */
289 static hs_ident_circuit_t *
291  const hs_service_intro_point_t *ip)
292 {
293  hs_ident_circuit_t *ident;
294 
295  tor_assert(service);
296  tor_assert(ip);
297 
298  ident = hs_ident_circuit_new(&service->keys.identity_pk);
299  ed25519_pubkey_copy(&ident->intro_auth_pk, &ip->auth_key_kp.pubkey);
300 
301  return ident;
302 }
303 
304 /** For a given introduction point and an introduction circuit, send the
305  * ESTABLISH_INTRO cell. The service object is used for logging. This can fail
306  * and if so, the circuit is closed and the intro point object is flagged
307  * that the circuit is not established anymore which is important for the
308  * retry mechanism. */
309 static void
312 {
313  ssize_t cell_len;
314  uint8_t payload[RELAY_PAYLOAD_SIZE];
315 
316  tor_assert(service);
317  tor_assert(ip);
318  tor_assert(circ);
319 
320  /* Encode establish intro cell. */
322  &service->config, ip, payload);
323  if (cell_len < 0) {
324  log_warn(LD_REND, "Unable to encode ESTABLISH_INTRO cell for service %s "
325  "on circuit %u. Closing circuit.",
326  safe_str_client(service->onion_address),
327  TO_CIRCUIT(circ)->n_circ_id);
328  goto err;
329  }
330 
331  /* Send the cell on the circuit. */
332  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
333  RELAY_COMMAND_ESTABLISH_INTRO,
334  (char *) payload, cell_len,
335  circ->cpath->prev) < 0) {
336  log_info(LD_REND, "Unable to send ESTABLISH_INTRO cell for service %s "
337  "on circuit %u.",
338  safe_str_client(service->onion_address),
339  TO_CIRCUIT(circ)->n_circ_id);
340  /* On error, the circuit has been closed. */
341  goto done;
342  }
343 
344  /* Record the attempt to use this circuit. */
346  goto done;
347 
348  err:
349  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
350  done:
351  memwipe(payload, 0, sizeof(payload));
352 }
353 
354 /** Return a string constant describing the anonymity of service. */
355 static const char *
357 {
358  if (service->config.is_single_onion) {
359  return "single onion";
360  } else {
361  return "hidden";
362  }
363 }
364 
365 /** For a given service, the ntor onion key and a rendezvous cookie, launch a
366  * circuit to the rendezvous point specified by the link specifiers. On
367  * success, a circuit identifier is attached to the circuit with the needed
368  * data. This function will try to open a circuit for a maximum value of
369  * MAX_REND_FAILURES then it will give up. */
370 static void
372  const hs_service_intro_point_t *ip,
373  const hs_cell_introduce2_data_t *data)
374 {
375  int circ_needs_uptime;
376  time_t now = time(NULL);
377  extend_info_t *info = NULL;
378  origin_circuit_t *circ;
379 
380  tor_assert(service);
381  tor_assert(ip);
382  tor_assert(data);
383 
384  circ_needs_uptime = hs_service_requires_uptime_circ(service->config.ports);
385 
386  /* Get the extend info data structure for the chosen rendezvous point
387  * specified by the given link specifiers. */
389  &data->onion_pk,
390  service->config.is_single_onion);
391  if (info == NULL) {
392  /* We are done here, we can't extend to the rendezvous point. */
393  log_fn(LOG_PROTOCOL_WARN, LD_REND,
394  "Not enough info to open a circuit to a rendezvous point for "
395  "%s service %s.",
397  safe_str_client(service->onion_address));
398  goto end;
399  }
400 
401  for (int i = 0; i < MAX_REND_FAILURES; i++) {
403  if (circ_needs_uptime) {
404  circ_flags |= CIRCLAUNCH_NEED_UPTIME;
405  }
406  /* Firewall and policies are checked when getting the extend info.
407  *
408  * We only use a one-hop path on the first attempt. If the first attempt
409  * fails, we use a 3-hop path for reachability / reliability.
410  * See the comment in retry_service_rendezvous_point() for details. */
411  if (service->config.is_single_onion && i == 0) {
412  circ_flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
413  }
414 
416  circ_flags);
417  if (circ != NULL) {
418  /* Stop retrying, we have a circuit! */
419  break;
420  }
421  }
422  if (circ == NULL) {
423  log_warn(LD_REND, "Giving up on launching a rendezvous circuit to %s "
424  "for %s service %s",
425  safe_str_client(extend_info_describe(info)),
427  safe_str_client(service->onion_address));
428  goto end;
429  }
430  log_info(LD_REND, "Rendezvous circuit launched to %s with cookie %s "
431  "for %s service %s",
432  safe_str_client(extend_info_describe(info)),
433  safe_str_client(hex_str((const char *) data->rendezvous_cookie,
434  REND_COOKIE_LEN)),
436  safe_str_client(service->onion_address));
437  tor_assert(circ->build_state);
438  /* Rendezvous circuit have a specific timeout for the time spent on trying
439  * to connect to the rendezvous point. */
441 
442  /* Create circuit identifier and key material. */
443  {
445  curve25519_keypair_t ephemeral_kp;
446  /* No need for extra strong, this is only for this circuit life time. This
447  * key will be used for the RENDEZVOUS1 cell that will be sent on the
448  * circuit once opened. */
449  curve25519_keypair_generate(&ephemeral_kp, 0);
450  if (hs_ntor_service_get_rendezvous1_keys(&ip->auth_key_kp.pubkey,
451  &ip->enc_key_kp,
452  &ephemeral_kp, &data->client_pk,
453  &keys) < 0) {
454  /* This should not really happened but just in case, don't make tor
455  * freak out, close the circuit and move on. */
456  log_info(LD_REND, "Unable to get RENDEZVOUS1 key material for "
457  "service %s",
458  safe_str_client(service->onion_address));
459  circuit_mark_for_close(TO_CIRCUIT(circ), END_CIRC_REASON_INTERNAL);
460  goto end;
461  }
462  circ->hs_ident = create_rp_circuit_identifier(service,
463  data->rendezvous_cookie,
464  &ephemeral_kp.pubkey, &keys);
465  memwipe(&ephemeral_kp, 0, sizeof(ephemeral_kp));
466  memwipe(&keys, 0, sizeof(keys));
467  tor_assert(circ->hs_ident);
468  }
469 
470  end:
471  extend_info_free(info);
472 }
473 
474 /** Return true iff the given service rendezvous circuit circ is allowed for a
475  * relaunch to the rendezvous point. */
476 static int
478 {
479  tor_assert(circ);
480  /* This is initialized when allocating an origin circuit. */
481  tor_assert(circ->build_state);
483 
484  /* XXX: Retrying under certain condition. This is related to #22455. */
485 
486  /* Avoid to relaunch twice a circuit to the same rendezvous point at the
487  * same time. */
489  log_info(LD_REND, "Rendezvous circuit to %s has already been retried. "
490  "Skipping retry.",
491  safe_str_client(
493  goto disallow;
494  }
495 
496  /* We check failure_count >= hs_get_service_max_rend_failures()-1 below, and
497  * the -1 is because we increment the failure count for our current failure
498  * *after* this clause. */
499  int max_rend_failures = hs_get_service_max_rend_failures() - 1;
500 
501  /* A failure count that has reached maximum allowed or circuit that expired,
502  * we skip relaunching. */
503  if (circ->build_state->failure_count > max_rend_failures ||
504  circ->build_state->expiry_time <= time(NULL)) {
505  log_info(LD_REND, "Attempt to build a rendezvous circuit to %s has "
506  "failed with %d attempts and expiry time %ld. "
507  "Giving up building.",
508  safe_str_client(
510  circ->build_state->failure_count,
511  (long int) circ->build_state->expiry_time);
512  goto disallow;
513  }
514 
515  /* Allowed to relaunch. */
516  return 1;
517  disallow:
518  return 0;
519 }
520 
521 /** Retry the rendezvous point of circ by launching a new circuit to it. */
522 static void
524 {
525  int flags = 0;
526  origin_circuit_t *new_circ;
527  cpath_build_state_t *bstate;
528 
529  tor_assert(circ);
530  /* This is initialized when allocating an origin circuit. */
531  tor_assert(circ->build_state);
533 
534  /* Ease our life. */
535  bstate = circ->build_state;
536 
537  log_info(LD_REND, "Retrying rendezvous point circuit to %s",
538  safe_str_client(extend_info_describe(bstate->chosen_exit)));
539 
540  /* Get the current build state flags for the next circuit. */
541  flags |= (bstate->need_uptime) ? CIRCLAUNCH_NEED_UPTIME : 0;
542  flags |= (bstate->need_capacity) ? CIRCLAUNCH_NEED_CAPACITY : 0;
543  flags |= (bstate->is_internal) ? CIRCLAUNCH_IS_INTERNAL : 0;
544 
545  /* We do NOT add the onehop tunnel flag even though it might be a single
546  * onion service. The reason is that if we failed once to connect to the RP
547  * with a direct connection, we consider that chances are that we will fail
548  * again so try a 3-hop circuit and hope for the best. Because the service
549  * has no anonymity (single onion), this change of behavior won't affect
550  * security directly. */
551 
553  bstate->chosen_exit, flags);
554  if (new_circ == NULL) {
555  log_warn(LD_REND, "Failed to launch rendezvous circuit to %s",
556  safe_str_client(extend_info_describe(bstate->chosen_exit)));
557  goto done;
558  }
559 
560  /* Transfer build state information to the new circuit state in part to
561  * catch any other failures. */
562  new_circ->build_state->failure_count = bstate->failure_count+1;
563  new_circ->build_state->expiry_time = bstate->expiry_time;
564  new_circ->hs_ident = hs_ident_circuit_dup(circ->hs_ident);
565 
566  done:
567  return;
568 }
569 
570 /** Using the given descriptor intro point ip, the node of the
571  * rendezvous point rp_node and the service's subcredential, populate the
572  * already allocated intro1_data object with the needed key material and link
573  * specifiers.
574  *
575  * Return 0 on success or a negative value if we couldn't properly filled the
576  * introduce1 data from the RP node. In other word, it means the RP node is
577  * unusable to use in the introduction. */
578 static int
580  const node_t *rp_node,
581  const uint8_t *subcredential,
582  hs_cell_introduce1_data_t *intro1_data)
583 {
584  int ret = -1;
585  smartlist_t *rp_lspecs;
586 
587  tor_assert(ip);
588  tor_assert(rp_node);
589  tor_assert(subcredential);
590  tor_assert(intro1_data);
591 
592  /* Build the link specifiers from the node at the end of the rendezvous
593  * circuit that we opened for this introduction. */
594  rp_lspecs = node_get_link_specifier_smartlist(rp_node, 0);
595  if (smartlist_len(rp_lspecs) == 0) {
596  /* We can't rendezvous without link specifiers. */
597  smartlist_free(rp_lspecs);
598  goto end;
599  }
600 
601  /* Populate the introduce1 data object. */
602  memset(intro1_data, 0, sizeof(hs_cell_introduce1_data_t));
603  if (ip->legacy.key != NULL) {
604  intro1_data->is_legacy = 1;
605  intro1_data->legacy_key = ip->legacy.key;
606  }
607  intro1_data->auth_pk = &ip->auth_key_cert->signed_key;
608  intro1_data->enc_pk = &ip->enc_key;
609  intro1_data->subcredential = subcredential;
610  intro1_data->link_specifiers = rp_lspecs;
611  intro1_data->onion_pk = node_get_curve25519_onion_key(rp_node);
612  if (intro1_data->onion_pk == NULL) {
613  /* We can't rendezvous without the curve25519 onion key. */
614  goto end;
615  }
616  /* Success, we have valid introduce data. */
617  ret = 0;
618 
619  end:
620  return ret;
621 }
622 
623 /** Helper: cleanup function for client circuit. This is for every HS version.
624  * It is called from hs_circ_cleanup_on_free() entry point. */
625 static void
627 {
628  tor_assert(circ);
629 
630  if (circuit_is_hs_v2(circ)) {
632  } else if (circuit_is_hs_v3(circ)) {
634  }
635  /* It is possible the circuit has an HS purpose but no identifier (rend_data
636  * or hs_ident). Thus possible that this passess through. */
637 }
638 
639 /* ========== */
640 /* Public API */
641 /* ========== */
642 
643 /** Return an introduction point circuit matching the given intro point object.
644  * NULL is returned is no such circuit can be found. */
647 {
648  tor_assert(ip);
649 
650  if (ip->base.is_only_legacy) {
652  } else {
654  &ip->auth_key_kp.pubkey);
655  }
656 }
657 
658 /** Return an introduction point established circuit matching the given intro
659  * point object. The circuit purpose has to be CIRCUIT_PURPOSE_S_INTRO. NULL
660  * is returned is no such circuit can be found. */
663 {
664  origin_circuit_t *circ;
665 
666  tor_assert(ip);
667 
668  if (ip->base.is_only_legacy) {
670  } else {
672  &ip->auth_key_kp.pubkey);
673  }
674 
675  /* Only return circuit if it is established. */
676  return (circ && TO_CIRCUIT(circ)->purpose == CIRCUIT_PURPOSE_S_INTRO) ?
677  circ : NULL;
678 }
679 
680 /** Called when we fail building a rendezvous circuit at some point other than
681  * the last hop: launches a new circuit to the same rendezvous point. This
682  * supports legacy service.
683  *
684  * We currently relaunch connections to rendezvous points if:
685  * - A rendezvous circuit timed out before connecting to RP.
686  * - The rendezvous circuit failed to connect to the RP.
687  *
688  * We avoid relaunching a connection to this rendezvous point if:
689  * - We have already tried MAX_REND_FAILURES times to connect to this RP,
690  * - We've been trying to connect to this RP for more than MAX_REND_TIMEOUT
691  * seconds, or
692  * - We've already retried this specific rendezvous circuit.
693  */
694 void
696 {
697  tor_assert(circ);
699 
700  /* Check if we are allowed to relaunch to the rendezvous point of circ. */
702  goto done;
703  }
704 
705  /* Flag the circuit that we are relaunching, to avoid to relaunch twice a
706  * circuit to the same rendezvous point at the same time. */
708 
709  /* Legacy services don't have a hidden service ident. */
710  if (circ->hs_ident) {
712  } else {
714  }
715 
716  done:
717  return;
718 }
719 
720 /** For a given service and a service intro point, launch a circuit to the
721  * extend info ei. If the service is a single onion, and direct_conn is true,
722  * a one-hop circuit will be requested.
723  *
724  * Return 0 if the circuit was successfully launched and tagged
725  * with the correct identifier. On error, a negative value is returned. */
726 int
728  const hs_service_intro_point_t *ip,
729  extend_info_t *ei,
730  bool direct_conn)
731 {
732  /* Standard flags for introduction circuit. */
733  int ret = -1, circ_flags = CIRCLAUNCH_NEED_UPTIME | CIRCLAUNCH_IS_INTERNAL;
734  origin_circuit_t *circ;
735 
736  tor_assert(service);
737  tor_assert(ip);
738  tor_assert(ei);
739 
740  /* Update circuit flags in case of a single onion service that requires a
741  * direct connection. */
742  tor_assert_nonfatal(ip->circuit_retries > 0);
743  /* Only single onion services can make direct conns */
744  if (BUG(!service->config.is_single_onion && direct_conn)) {
745  goto end;
746  }
747  /* We only use a one-hop path on the first attempt. If the first attempt
748  * fails, we use a 3-hop path for reachability / reliability.
749  * (Unlike v2, retries is incremented by the caller before it calls this
750  * function.) */
751  if (direct_conn && ip->circuit_retries == 1) {
752  circ_flags |= CIRCLAUNCH_ONEHOP_TUNNEL;
753  }
754 
755  log_info(LD_REND, "Launching a circuit to intro point %s for service %s.",
756  safe_str_client(extend_info_describe(ei)),
757  safe_str_client(service->onion_address));
758 
759  /* Note down the launch for the retry period. Even if the circuit fails to
760  * be launched, we still want to respect the retry period to avoid stress on
761  * the circuit subsystem. */
762  service->state.num_intro_circ_launched++;
764  ei, circ_flags);
765  if (circ == NULL) {
766  goto end;
767  }
768 
769  /* Setup the circuit identifier and attach it to it. */
770  circ->hs_ident = create_intro_circuit_identifier(service, ip);
771  tor_assert(circ->hs_ident);
772  /* Register circuit in the global circuitmap. */
773  register_intro_circ(ip, circ);
774 
775  /* Success. */
776  ret = 0;
777  end:
778  return ret;
779 }
780 
781 /** Called when a service introduction point circuit is done building. Given
782  * the service and intro point object, this function will send the
783  * ESTABLISH_INTRO cell on the circuit. Return 0 on success. Return 1 if the
784  * circuit has been repurposed to General because we already have too many
785  * opened. */
786 int
789  const hs_service_descriptor_t *desc,
790  origin_circuit_t *circ)
791 {
792  int ret = 0;
793  unsigned int num_intro_circ, num_needed_circ;
794 
795  tor_assert(service);
796  tor_assert(ip);
797  tor_assert(desc);
798  tor_assert(circ);
799 
800  /* Cound opened circuits that have sent ESTABLISH_INTRO cells or are already
801  * established introduction circuits */
802  num_intro_circ = count_opened_desc_intro_point_circuits(service, desc);
803  num_needed_circ = service->config.num_intro_points;
804  if (num_intro_circ > num_needed_circ) {
805  /* There are too many opened valid intro circuit for what the service
806  * needs so repurpose this one. */
807 
808  /* XXX: Legacy code checks options->ExcludeNodes and if not NULL it just
809  * closes the circuit. I have NO idea why it does that so it hasn't been
810  * added here. I can only assume in case our ExcludeNodes list changes but
811  * in that case, all circuit are flagged unusable (config.c). --dgoulet */
812 
813  log_info(LD_CIRC | LD_REND, "Introduction circuit just opened but we "
814  "have enough for service %s. Repurposing "
815  "it to general and leaving internal.",
816  safe_str_client(service->onion_address));
818  /* Remove it from the circuitmap. */
820  /* Cleaning up the hidden service identifier and repurpose. */
821  hs_ident_circuit_free(circ->hs_ident);
822  circ->hs_ident = NULL;
823  if (circuit_should_use_vanguards(TO_CIRCUIT(circ)->purpose))
825  else
827 
828  /* Inform that this circuit just opened for this new purpose. */
829  circuit_has_opened(circ);
830  /* This return value indicate to the caller that the IP object should be
831  * removed from the service because it's corresponding circuit has just
832  * been repurposed. */
833  ret = 1;
834  goto done;
835  }
836 
837  log_info(LD_REND, "Introduction circuit %u established for service %s.",
838  TO_CIRCUIT(circ)->n_circ_id,
839  safe_str_client(service->onion_address));
841 
842  /* Time to send an ESTABLISH_INTRO cell on this circuit. On error, this call
843  * makes sure the circuit gets closed. */
844  send_establish_intro(service, ip, circ);
845 
846  done:
847  return ret;
848 }
849 
850 /** Called when a service rendezvous point circuit is done building. Given the
851  * service and the circuit, this function will send a RENDEZVOUS1 cell on the
852  * circuit using the information in the circuit identifier. If the cell can't
853  * be sent, the circuit is closed. */
854 void
856  origin_circuit_t *circ)
857 {
858  size_t payload_len;
859  uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
860 
861  tor_assert(service);
862  tor_assert(circ);
863  tor_assert(circ->hs_ident);
864 
865  /* Some useful logging. */
866  log_info(LD_REND, "Rendezvous circuit %u has opened with cookie %s "
867  "for service %s",
868  TO_CIRCUIT(circ)->n_circ_id,
869  hex_str((const char *) circ->hs_ident->rendezvous_cookie,
871  safe_str_client(service->onion_address));
873 
874  /* This can't fail. */
875  payload_len = hs_cell_build_rendezvous1(
877  sizeof(circ->hs_ident->rendezvous_cookie),
879  sizeof(circ->hs_ident->rendezvous_handshake_info),
880  payload);
881 
882  /* Pad the payload with random bytes so it matches the size of a legacy cell
883  * which is normally always bigger. Also, the size of a legacy cell is
884  * always smaller than the RELAY_PAYLOAD_SIZE so this is safe. */
885  if (payload_len < HS_LEGACY_RENDEZVOUS_CELL_SIZE) {
886  crypto_rand((char *) payload + payload_len,
887  HS_LEGACY_RENDEZVOUS_CELL_SIZE - payload_len);
888  payload_len = HS_LEGACY_RENDEZVOUS_CELL_SIZE;
889  }
890 
891  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
892  RELAY_COMMAND_RENDEZVOUS1,
893  (const char *) payload, payload_len,
894  circ->cpath->prev) < 0) {
895  /* On error, circuit is closed. */
896  log_warn(LD_REND, "Unable to send RENDEZVOUS1 cell on circuit %u "
897  "for service %s",
898  TO_CIRCUIT(circ)->n_circ_id,
899  safe_str_client(service->onion_address));
900  goto done;
901  }
902 
903  /* Setup end-to-end rendezvous circuit between the client and us. */
906  sizeof(circ->hs_ident->rendezvous_ntor_key_seed),
907  1) < 0) {
908  log_warn(LD_GENERAL, "Failed to setup circ");
909  goto done;
910  }
911 
912  done:
913  memwipe(payload, 0, sizeof(payload));
914 }
915 
916 /** Circ has been expecting an INTRO_ESTABLISHED cell that just arrived. Handle
917  * the INTRO_ESTABLISHED cell payload of length payload_len arriving on the
918  * given introduction circuit circ. The service is only used for logging
919  * purposes. Return 0 on success else a negative value. */
920 int
922  const hs_service_intro_point_t *ip,
923  origin_circuit_t *circ,
924  const uint8_t *payload, size_t payload_len)
925 {
926  int ret = -1;
927 
928  tor_assert(service);
929  tor_assert(ip);
930  tor_assert(circ);
931  tor_assert(payload);
932 
933  if (BUG(TO_CIRCUIT(circ)->purpose != CIRCUIT_PURPOSE_S_ESTABLISH_INTRO)) {
934  goto done;
935  }
936 
937  /* Try to parse the payload into a cell making sure we do actually have a
938  * valid cell. For a legacy node, it's an empty payload so as long as we
939  * have the cell, we are good. */
940  if (!ip->base.is_only_legacy &&
941  hs_cell_parse_intro_established(payload, payload_len) < 0) {
942  log_warn(LD_REND, "Unable to parse the INTRO_ESTABLISHED cell on "
943  "circuit %u for service %s",
944  TO_CIRCUIT(circ)->n_circ_id,
945  safe_str_client(service->onion_address));
946  goto done;
947  }
948 
949  /* Switch the purpose to a fully working intro point. */
951  /* Getting a valid INTRODUCE_ESTABLISHED means we've successfully used the
952  * circuit so update our pathbias subsystem. */
954  /* Success. */
955  ret = 0;
956 
957  done:
958  return ret;
959 }
960 
961 /** We just received an INTRODUCE2 cell on the established introduction circuit
962  * circ. Handle the INTRODUCE2 payload of size payload_len for the given
963  * circuit and service. This cell is associated with the intro point object ip
964  * and the subcredential. Return 0 on success else a negative value. */
965 int
967  const origin_circuit_t *circ,
969  const uint8_t *subcredential,
970  const uint8_t *payload, size_t payload_len)
971 {
972  int ret = -1;
973  time_t elapsed;
975 
976  tor_assert(service);
977  tor_assert(circ);
978  tor_assert(ip);
979  tor_assert(subcredential);
980  tor_assert(payload);
981 
982  /* Populate the data structure with everything we need for the cell to be
983  * parsed, decrypted and key material computed correctly. */
984  data.auth_pk = &ip->auth_key_kp.pubkey;
985  data.enc_kp = &ip->enc_key_kp;
986  data.subcredential = subcredential;
987  data.payload = payload;
988  data.payload_len = payload_len;
990  data.replay_cache = ip->replay_cache;
991 
992  if (hs_cell_parse_introduce2(&data, circ, service) < 0) {
993  goto done;
994  }
995 
996  /* Check whether we've seen this REND_COOKIE before to detect repeats. */
999  data.rendezvous_cookie, sizeof(data.rendezvous_cookie),
1000  &elapsed)) {
1001  /* A Tor client will send a new INTRODUCE1 cell with the same REND_COOKIE
1002  * as its previous one if its intro circ times out while in state
1003  * CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT. If we received the first
1004  * INTRODUCE1 cell (the intro-point relay converts it into an INTRODUCE2
1005  * cell), we are already trying to connect to that rend point (and may
1006  * have already succeeded); drop this cell. */
1007  log_info(LD_REND, "We received an INTRODUCE2 cell with same REND_COOKIE "
1008  "field %ld seconds ago. Dropping cell.",
1009  (long int) elapsed);
1010  goto done;
1011  }
1012 
1013  /* At this point, we just confirmed that the full INTRODUCE2 cell is valid
1014  * so increment our counter that we've seen one on this intro point. */
1015  ip->introduce2_count++;
1016 
1017  /* Launch rendezvous circuit with the onion key and rend cookie. */
1018  launch_rendezvous_point_circuit(service, ip, &data);
1019  /* Success. */
1020  ret = 0;
1021 
1022  done:
1023  link_specifier_smartlist_free(data.link_specifiers);
1024  memwipe(&data, 0, sizeof(data));
1025  return ret;
1026 }
1027 
1028 /** Circuit <b>circ</b> just finished the rend ntor key exchange. Use the key
1029  * exchange output material at <b>ntor_key_seed</b> and setup <b>circ</b> to
1030  * serve as a rendezvous end-to-end circuit between the client and the
1031  * service. If <b>is_service_side</b> is set, then we are the hidden service
1032  * and the other side is the client.
1033  *
1034  * Return 0 if the operation went well; in case of error return -1. */
1035 int
1037  const uint8_t *ntor_key_seed, size_t seed_len,
1038  int is_service_side)
1039 {
1040  if (BUG(!circuit_purpose_is_correct_for_rend(TO_CIRCUIT(circ)->purpose,
1041  is_service_side))) {
1042  return -1;
1043  }
1044 
1045  crypt_path_t *hop = create_rend_cpath(ntor_key_seed, seed_len,
1046  is_service_side);
1047  if (!hop) {
1048  log_warn(LD_REND, "Couldn't get v3 %s cpath!",
1049  is_service_side ? "service-side" : "client-side");
1050  return -1;
1051  }
1052 
1053  finalize_rend_circuit(circ, hop, is_service_side);
1054 
1055  return 0;
1056 }
1057 
1058 /** We are a v2 legacy HS client and we just received a RENDEZVOUS1 cell
1059  * <b>rend_cell_body</b> on <b>circ</b>. Finish up the DH key exchange and then
1060  * extend the crypt path of <b>circ</b> so that the hidden service is on the
1061  * other side. */
1062 int
1064  const uint8_t *rend_cell_body)
1065 {
1066 
1068  TO_CIRCUIT(circ)->purpose, 0))) {
1069  return -1;
1070  }
1071 
1072  crypt_path_t *hop = create_rend_cpath_legacy(circ, rend_cell_body);
1073  if (!hop) {
1074  log_warn(LD_GENERAL, "Couldn't get v2 cpath.");
1075  return -1;
1076  }
1077 
1078  finalize_rend_circuit(circ, hop, 0);
1079 
1080  return 0;
1081 }
1082 
1083 /** Given the introduction circuit intro_circ, the rendezvous circuit
1084  * rend_circ, a descriptor intro point object ip and the service's
1085  * subcredential, send an INTRODUCE1 cell on intro_circ.
1086  *
1087  * This will also setup the circuit identifier on rend_circ containing the key
1088  * material for the handshake and e2e encryption. Return 0 on success else
1089  * negative value. Because relay_send_command_from_edge() closes the circuit
1090  * on error, it is possible that intro_circ is closed on error. */
1091 int
1093  origin_circuit_t *rend_circ,
1094  const hs_desc_intro_point_t *ip,
1095  const uint8_t *subcredential)
1096 {
1097  int ret = -1;
1098  ssize_t payload_len;
1099  uint8_t payload[RELAY_PAYLOAD_SIZE] = {0};
1100  hs_cell_introduce1_data_t intro1_data;
1101 
1102  tor_assert(intro_circ);
1103  tor_assert(rend_circ);
1104  tor_assert(ip);
1105  tor_assert(subcredential);
1106 
1107  /* It is undefined behavior in hs_cell_introduce1_data_clear() if intro1_data
1108  * has been declared on the stack but not initialized. Here, we set it to 0.
1109  */
1110  memset(&intro1_data, 0, sizeof(hs_cell_introduce1_data_t));
1111 
1112  /* This takes various objects in order to populate the introduce1 data
1113  * object which is used to build the content of the cell. */
1114  const node_t *exit_node = build_state_get_exit_node(rend_circ->build_state);
1115  if (exit_node == NULL) {
1116  log_info(LD_REND, "Unable to get rendezvous point for circuit %u. "
1117  "Failing.", TO_CIRCUIT(intro_circ)->n_circ_id);
1118  goto done;
1119  }
1120 
1121  /* We should never select an invalid rendezvous point in theory but if we
1122  * do, this function will fail to populate the introduce data. */
1123  if (setup_introduce1_data(ip, exit_node, subcredential, &intro1_data) < 0) {
1124  log_warn(LD_REND, "Unable to setup INTRODUCE1 data. The chosen rendezvous "
1125  "point is unusable. Closing circuit.");
1126  goto close;
1127  }
1128 
1129  /* Final step before we encode a cell, we setup the circuit identifier which
1130  * will generate both the rendezvous cookie and client keypair for this
1131  * connection. Those are put in the ident. */
1132  intro1_data.rendezvous_cookie = rend_circ->hs_ident->rendezvous_cookie;
1133  intro1_data.client_kp = &rend_circ->hs_ident->rendezvous_client_kp;
1134 
1135  memcpy(intro_circ->hs_ident->rendezvous_cookie,
1136  rend_circ->hs_ident->rendezvous_cookie,
1137  sizeof(intro_circ->hs_ident->rendezvous_cookie));
1138 
1139  /* From the introduce1 data object, this will encode the INTRODUCE1 cell
1140  * into payload which is then ready to be sent as is. */
1141  payload_len = hs_cell_build_introduce1(&intro1_data, payload);
1142  if (BUG(payload_len < 0)) {
1143  goto close;
1144  }
1145 
1146  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(intro_circ),
1147  RELAY_COMMAND_INTRODUCE1,
1148  (const char *) payload, payload_len,
1149  intro_circ->cpath->prev) < 0) {
1150  /* On error, circuit is closed. */
1151  log_warn(LD_REND, "Unable to send INTRODUCE1 cell on circuit %u.",
1152  TO_CIRCUIT(intro_circ)->n_circ_id);
1153  goto done;
1154  }
1155 
1156  /* Success. */
1157  ret = 0;
1158  goto done;
1159 
1160  close:
1161  circuit_mark_for_close(TO_CIRCUIT(rend_circ), END_CIRC_REASON_INTERNAL);
1162  done:
1163  hs_cell_introduce1_data_clear(&intro1_data);
1164  memwipe(payload, 0, sizeof(payload));
1165  return ret;
1166 }
1167 
1168 /** Send an ESTABLISH_RENDEZVOUS cell along the rendezvous circuit circ. On
1169  * success, 0 is returned else -1 and the circuit is marked for close. */
1170 int
1172 {
1173  ssize_t cell_len = 0;
1174  uint8_t cell[RELAY_PAYLOAD_SIZE] = {0};
1175 
1176  tor_assert(circ);
1178 
1179  log_info(LD_REND, "Send an ESTABLISH_RENDEZVOUS cell on circuit %u",
1180  TO_CIRCUIT(circ)->n_circ_id);
1181 
1182  /* Set timestamp_dirty, because circuit_expire_building expects it,
1183  * and the rend cookie also means we've used the circ. */
1184  TO_CIRCUIT(circ)->timestamp_dirty = time(NULL);
1185 
1186  /* We've attempted to use this circuit. Probe it if we fail */
1188 
1189  /* Generate the RENDEZVOUS_COOKIE and place it in the identifier so we can
1190  * complete the handshake when receiving the acknowledgement. */
1192  /* Generate the client keypair. No need to be extra strong, not long term */
1194 
1195  cell_len =
1197  cell);
1198  if (BUG(cell_len < 0)) {
1199  goto err;
1200  }
1201 
1202  if (relay_send_command_from_edge(CONTROL_CELL_ID, TO_CIRCUIT(circ),
1203  RELAY_COMMAND_ESTABLISH_RENDEZVOUS,
1204  (const char *) cell, cell_len,
1205  circ->cpath->prev) < 0) {
1206  /* Circuit has been marked for close */
1207  log_warn(LD_REND, "Unable to send ESTABLISH_RENDEZVOUS cell on "
1208  "circuit %u", TO_CIRCUIT(circ)->n_circ_id);
1209  memwipe(cell, 0, cell_len);
1210  goto err;
1211  }
1212 
1213  memwipe(cell, 0, cell_len);
1214  return 0;
1215  err:
1216  return -1;
1217 }
1218 
1219 /** Circuit cleanup strategy:
1220  *
1221  * What follows is a series of functions that notifies the HS subsystem of 3
1222  * different circuit cleanup phase: close, free and repurpose.
1223  *
1224  * Tor can call any of those in any orders so they have to be safe between
1225  * each other. In other words, the free should never depend on close to be
1226  * called before.
1227  *
1228  * The "on_close()" is called from circuit_mark_for_close() which is
1229  * considered the tor fast path and thus as little work as possible should
1230  * done in that function. Currently, we only remove the circuit from the HS
1231  * circuit map and move on.
1232  *
1233  * The "on_free()" is called from circuit circuit_free_() and it is very
1234  * important that at the end of the function, no state or objects related to
1235  * this circuit remains alive.
1236  *
1237  * The "on_repurpose()" is called from circuit_change_purpose() for which we
1238  * simply remove it from the HS circuit map. We do not have other cleanup
1239  * requirements after that.
1240  *
1241  * NOTE: The onion service code, specifically the service code, cleans up
1242  * lingering objects or state if any of its circuit disappear which is why
1243  * our cleanup strategy doesn't involve any service specific actions. As long
1244  * as the circuit is removed from the HS circuit map, it won't be used.
1245  */
1246 
1247 /** We are about to close this <b>circ</b>. Clean it up from any related HS
1248  * data structures. This function can be called multiple times safely for the
1249  * same circuit. */
1250 void
1252 {
1253  tor_assert(circ);
1254 
1255  /* On close, we simply remove it from the circuit map. It can not be used
1256  * anymore. We keep this code path fast and lean. */
1257 
1258  if (circ->hs_token) {
1260  }
1261 }
1262 
1263 /** We are about to free this <b>circ</b>. Clean it up from any related HS
1264  * data structures. This function can be called multiple times safely for the
1265  * same circuit. */
1266 void
1268 {
1269  tor_assert(circ);
1270 
1271  /* NOTE: Bulk of the work of cleaning up a circuit is done here. */
1272 
1275  }
1276 
1277  /* We have no assurance that the given HS circuit has been closed before and
1278  * thus removed from the HS map. This actually happens in unit tests. */
1279  if (circ->hs_token) {
1281  }
1282 }
1283 
1284 /** We are about to repurpose this <b>circ</b>. Clean it up from any related
1285  * HS data structures. This function can be called multiple times safely for
1286  * the same circuit. */
1287 void
1289 {
1290  tor_assert(circ);
1291 
1292  /* On repurpose, we simply remove it from the circuit map but we do not do
1293  * the on_free actions since we don't treat a repurpose as something we need
1294  * to report in the client cache failure. */
1295 
1296  if (circ->hs_token) {
1298  }
1299 }
1300 
1301 /** Return true iff the given established client rendezvous circuit was sent
1302  * into the INTRODUCE1 cell. This is called so we can take a decision on
1303  * expiring or not the circuit.
1304  *
1305  * The caller MUST make sure the circuit is an established client rendezvous
1306  * circuit (purpose: CIRCUIT_PURPOSE_C_REND_READY).
1307  *
1308  * This function supports all onion service versions. */
1309 bool
1311 {
1312  tor_assert(circ);
1313  /* This can only be called for a rendezvous circuit that is an established
1314  * confirmed rendezsvous circuit but without an introduction ACK. */
1316 
1317  /* The v2 and v3 circuit are handled differently:
1318  *
1319  * v2: A circ's pending_final_cpath field is non-NULL iff it is a rend circ
1320  * and we have tried to send an INTRODUCE1 cell specifying it. Thus, if the
1321  * pending_final_cpath field *is* NULL, then we want to not spare it.
1322  *
1323  * v3: When the INTRODUCE1 cell is sent, the introduction encryption public
1324  * key is copied in the rendezvous circuit hs identifier. If it is a valid
1325  * key, we know that this circuit is waiting the ACK on the introduction
1326  * circuit. We want to _not_ spare the circuit if the key was never set. */
1327 
1328  if (circ->rend_data) {
1329  /* v2. */
1330  if (circ->build_state && circ->build_state->pending_final_cpath != NULL) {
1331  return true;
1332  }
1333  } else if (circ->hs_ident) {
1334  /* v3. */
1336  return true;
1337  }
1338  } else {
1339  /* A circuit with an HS purpose without an hs_ident or rend_data in theory
1340  * can not happen. In case, scream loudly and return false to the caller
1341  * that the rendezvous was not sent in the INTRO1 cell. */
1342  tor_assert_nonfatal_unreached();
1343  }
1344 
1345  /* The rendezvous has not been specified in the INTRODUCE1 cell. */
1346  return false;
1347 }
#define RELAY_PAYLOAD_SIZE
Definition: or.h:605
int hs_circuit_setup_e2e_rend_circ_legacy_client(origin_circuit_t *circ, const uint8_t *rend_cell_body)
Definition: hs_circuit.c:1063
#define CIRCLAUNCH_ONEHOP_TUNNEL
Definition: circuituse.h:39
#define CIRCLAUNCH_IS_INTERNAL
Definition: circuituse.h:46
hs_service_state_t state
Definition: hs_service.h:291
void crypto_rand(char *to, size_t n)
Definition: crypto_rand.c:477
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:1690
#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED
Definition: circuitlist.h:88
static int can_relaunch_service_rendezvous_point(const origin_circuit_t *circ)
Definition: hs_circuit.c:477
unsigned int num_intro_circ_launched
Definition: hs_service.h:266
Common functions for using (pseudo-)random number generators.
Definition: node_st.h:34
digest256map_t * map
Definition: hs_service.h:97
Header file containing service data for the HS subsytem.
Headers for crypto_dh.c.
void cpath_extend_linked_list(crypt_path_t **head_ptr, crypt_path_t *new_hop)
Definition: crypt_path.c:44
uint8_t rendezvous_cookie[HS_REND_COOKIE_LEN]
Definition: hs_ident.h:60
int curve25519_public_key_is_ok(const curve25519_public_key_t *key)
smartlist_t * link_specifiers
Definition: hs_cell.h:40
ed25519_public_key_t signed_key
Definition: torcert.h:30
void circuit_try_attaching_streams(origin_circuit_t *circ)
Definition: circuituse.c:1755
Header file containing client data for the HS subsytem.
extend_info_t * chosen_exit
const char * extend_info_describe(const extend_info_t *ei)
Definition: describe.c:204
const uint8_t * payload
Definition: hs_cell.h:62
curve25519_keypair_t rendezvous_client_kp
Definition: hs_ident.h:72
replaycache_t * replay_cache
Definition: hs_cell.h:77
void rend_service_relaunch_rendezvous(origin_circuit_t *oldcirc)
Definition: rendservice.c:3016
unsigned int num_intro_points
Definition: hs_service.h:224
#define LD_GENERAL
Definition: log.h:62
#define CIRCLAUNCH_NEED_UPTIME
Definition: circuituse.h:41
void hs_circ_cleanup_on_repurpose(circuit_t *circ)
Definition: hs_circuit.c:1288
Path structures for origin circuits.
static void launch_rendezvous_point_circuit(const hs_service_t *service, const hs_service_intro_point_t *ip, const hs_cell_introduce2_data_t *data)
Definition: hs_circuit.c:371
bool hs_circ_is_rend_sent_in_intro1(const origin_circuit_t *circ)
Definition: hs_circuit.c:1310
bool circuit_is_hs_v3(const circuit_t *circ)
Definition: circuituse.c:2014
#define LOG_INFO
Definition: log.h:45
Header file for describe.c.
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:608
Header file for nodelist.c.
#define CIRCWINDOW_START
Definition: or.h:501
uint8_t state
Definition: circuit_st.h:110
struct hs_desc_intro_point_t::@16 legacy
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:915
curve25519_keypair_t enc_key_kp
Definition: hs_service.h:51
replaycache_t * replay_cache
Definition: hs_service.h:78
uint8_t purpose
Definition: circuit_st.h:111
#define MAX_REND_TIMEOUT
Definition: hs_common.h:50
#define HS_REND_COOKIE_LEN
Definition: hs_ident.h:30
const curve25519_public_key_t * onion_pk
Definition: hs_cell.h:34
Node information structure.
#define TO_CIRCUIT(x)
Definition: or.h:951
#define CIRCUIT_PURPOSE_C_REND_READY
Definition: circuitlist.h:85
Header file for config.c.
hs_ident_circuit_t * hs_ident_circuit_new(const ed25519_public_key_t *identity_pk)
Definition: hs_ident.c:16
crypt_path_t * cpath
#define tor_assert(expr)
Definition: util_bug.h:102
struct crypt_path_t * prev
Definition: crypt_path_st.h:75
static void finalize_rend_circuit(origin_circuit_t *circ, crypt_path_t *hop, int is_service_side)
Definition: hs_circuit.c:160
#define CIRCUIT_PURPOSE_S_ESTABLISH_INTRO
Definition: circuitlist.h:103
#define tor_free(p)
Definition: malloc.h:52
int hs_circ_handle_introduce2(const hs_service_t *service, const origin_circuit_t *circ, hs_service_intro_point_t *ip, const uint8_t *subcredential, const uint8_t *payload, size_t payload_len)
Definition: hs_circuit.c:966
uint16_t marked_for_close
Definition: circuit_st.h:189
static void retry_service_rendezvous_point(const origin_circuit_t *circ)
Definition: hs_circuit.c:523
int replaycache_add_test_and_elapsed(replaycache_t *r, const void *data, size_t len, time_t *elapsed)
Definition: replaycache.c:195
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:251
origin_circuit_t * hs_circuitmap_get_intro_circ_v2_service_side(const uint8_t *digest)
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition: crypto_util.c:55
smartlist_t * ports
Definition: hs_service.h:207
smartlist_t * smartlist_new(void)
curve25519_public_key_t client_pk
Definition: hs_cell.h:73
const ed25519_public_key_t * auth_pk
Definition: hs_cell.h:28
static int setup_introduce1_data(const hs_desc_intro_point_t *ip, const node_t *rp_node, const uint8_t *subcredential, hs_cell_introduce1_data_t *intro1_data)
Definition: hs_circuit.c:579
void hs_circ_cleanup_on_free(circuit_t *circ)
Definition: hs_circuit.c:1267
#define STATIC
Definition: testsupport.h:32
#define tor_memneq(a, b, sz)
Definition: di_ops.h:21
Circuit-build-stse structure.
#define MAX_REND_FAILURES
Definition: hs_common.h:47
const curve25519_public_key_t * enc_pk
Definition: hs_cell.h:30
int circuit_should_use_vanguards(uint8_t purpose)
Definition: circuituse.c:2031
unsigned int is_legacy
Definition: hs_cell.h:23
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:787
#define DIGEST256_LEN
Definition: digest_sizes.h:23
Header file for policies.c.
void hs_client_circuit_cleanup_on_free(const circuit_t *circ)
Definition: hs_client.c:1739
origin_circuit_t * hs_circuitmap_get_intro_circ_v3_service_side(const ed25519_public_key_t *auth_key)
int ed25519_pubkey_eq(const ed25519_public_key_t *key1, const ed25519_public_key_t *key2)
int32_t circuit_initial_package_window(void)
Definition: circuitlist.c:972
const curve25519_public_key_t * node_get_curve25519_onion_key(const node_t *node)
Definition: nodelist.c:1889
Common functions for cryptographic routines.
Header for hs_ntor.c.
#define LD_CIRC
Definition: log.h:82
origin_circuit_t * hs_circ_service_get_intro_circ(const hs_service_intro_point_t *ip)
Definition: hs_circuit.c:646
int hs_circ_send_establish_rendezvous(origin_circuit_t *circ)
Definition: hs_circuit.c:1171
uint8_t rendezvous_handshake_info[CURVE25519_PUBKEY_LEN+DIGEST256_LEN]
Definition: hs_ident.h:68
unsigned int is_only_legacy
Definition: hs_intropoint.h:19
void hs_circ_cleanup_on_close(circuit_t *circ)
Definition: hs_circuit.c:1251
char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1]
Definition: hs_service.h:284
#define DIGEST_LEN
Definition: digest_sizes.h:20
Origin circuit structure.
void hs_circ_service_rp_has_opened(const hs_service_t *service, origin_circuit_t *circ)
Definition: hs_circuit.c:855
Header file containing cell data for the whole HS subsytem.
void ed25519_pubkey_copy(ed25519_public_key_t *dest, const ed25519_public_key_t *src)
uint8_t rendezvous_cookie[REND_COOKIE_LEN]
Definition: hs_cell.h:71
Master header file for Tor-specific functionality.
const ed25519_public_key_t * auth_pk
Definition: hs_cell.h:53
#define CIRCUIT_STATE_OPEN
Definition: circuitlist.h:32
const char * hex_str(const char *from, size_t fromlen)
Definition: binascii.c:34
Header file for circuitbuild.c.
curve25519_public_key_t onion_pk
Definition: hs_cell.h:69
struct crypto_dh_t * rend_dh_handshake_state
Definition: crypt_path_st.h:55
Header file for rephist.c.
char rend_circ_nonce[DIGEST_LEN]
Definition: crypt_path_st.h:58
ed25519_keypair_t auth_key_kp
Definition: hs_service.h:48
hs_service_keys_t keys
Definition: hs_service.h:294
Header file containing circuit and connection identifier data for the whole HS subsytem.
struct hs_token_t * hs_token
Definition: circuit_st.h:216
void hs_circuitmap_register_intro_circ_v3_service_side(origin_circuit_t *circ, const ed25519_public_key_t *auth_key)
Header file for circuituse.c.
ed25519_public_key_t identity_pk
Definition: hs_ident.h:45
ed25519_public_key_t intro_auth_pk
Definition: hs_ident.h:51
hs_service_config_t config
Definition: hs_service.h:297
const node_t * build_state_get_exit_node(cpath_build_state_t *state)
ed25519_public_key_t identity_pk
Definition: hs_service.h:172
unsigned int is_single_onion
Definition: hs_service.h:239
#define CIRCUIT_PURPOSE_C_ESTABLISH_REND
Definition: circuitlist.h:83
bool circuit_is_hs_v2(const circuit_t *circ)
Definition: circuituse.c:2006
const crypto_pk_t * legacy_key
Definition: hs_cell.h:26
Header file for hs_circuitmap.c.
#define CIRCUIT_PURPOSE_S_CONNECT_REND
Definition: circuitlist.h:109
#define LD_REND
Definition: log.h:84
Header file for circuitlist.c.
Header file for rendservice.c.
void circuit_log_path(int severity, unsigned int domain, origin_circuit_t *circ)
Definition: circuitbuild.c:357
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:727
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:150
#define CIRCLAUNCH_NEED_CAPACITY
Definition: circuituse.h:43
curve25519_public_key_t enc_key
void hs_circuitmap_remove_circuit(circuit_t *circ)
#define CIRCUIT_PURPOSE_S_INTRO
Definition: circuitlist.h:106
static crypt_path_t * create_rend_cpath_legacy(origin_circuit_t *circ, const uint8_t *rend_cell_body)
Definition: hs_circuit.c:113
#define DH1024_KEY_LEN
Definition: dh_sizes.h:20
int hs_circ_send_introduce1(origin_circuit_t *intro_circ, origin_circuit_t *rend_circ, const hs_desc_intro_point_t *ip, const uint8_t *subcredential)
Definition: hs_circuit.c:1092
ssize_t hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data, uint8_t *cell_out)
Definition: hs_cell.c:950
#define CIRCUIT_PURPOSE_HS_VANGUARDS
Definition: circuitlist.h:130
Header file containing circuit data for the whole HS subsytem.
const curve25519_keypair_t * client_kp
Definition: hs_cell.h:38
const uint8_t * rendezvous_cookie
Definition: hs_cell.h:36
hs_ident_circuit_t * hs_ident_circuit_dup(const hs_ident_circuit_t *src)
Definition: hs_ident.c:37
unsigned int hs_circ_has_timed_out
hs_service_intropoints_t intro_points
Definition: hs_service.h:156
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:290
const uint8_t * subcredential
Definition: hs_cell.h:60
void circuit_has_opened(origin_circuit_t *circ)
Definition: circuituse.c:1681
Header file for crypt_path.c.
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:1036
origin_circuit_t * circuit_launch_by_extend_info(uint8_t purpose, extend_info_t *extend_info, int flags)
Definition: circuituse.c:2101
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:921
int hs_get_service_max_rend_failures(void)
Definition: hs_common.c:232
replaycache_t * replay_cache_rend_cookie
Definition: hs_service.h:273
Header file for relay.c.
crypt_path_t * pending_final_cpath
static const char * get_service_anonymity_string(const hs_service_t *service)
Definition: hs_circuit.c:356
void hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data)
Definition: hs_cell.c:1072
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:589
uint8_t rendezvous_ntor_key_seed[DIGEST256_LEN]
Definition: hs_ident.h:76
static int circuit_purpose_is_correct_for_rend(unsigned int circ_purpose, int is_service_side)
Definition: hs_circuit.c:49
cpath_build_state_t * build_state
#define CIRCUIT_PURPOSE_C_REND_JOINED
Definition: circuitlist.h:90
static void send_establish_intro(const hs_service_t *service, hs_service_intro_point_t *ip, origin_circuit_t *circ)
Definition: hs_circuit.c:310
rend_data_t * rend_data
#define HS_LEGACY_RENDEZVOUS_CELL_SIZE
Definition: hs_common.h:131
bool circuit_purpose_is_hs_client(const uint8_t purpose)
Definition: circuituse.c:1983
origin_circuit_t * hs_circ_service_get_established_intro_circ(const hs_service_intro_point_t *ip)
Definition: hs_circuit.c:662
int curve25519_keypair_generate(curve25519_keypair_t *keypair_out, int extra_strong)
#define log_fn(severity, domain, args,...)
Definition: log.h:287
void rend_client_circuit_cleanup_on_free(const circuit_t *circ)
Definition: rendclient.c:1257
curve25519_public_key_t intro_enc_pk
Definition: hs_ident.h:55
static void register_intro_circ(const hs_service_intro_point_t *ip, origin_circuit_t *circ)
Definition: hs_circuit.c:201
#define CIRCUIT_PURPOSE_C_GENERAL
Definition: circuitlist.h:72
const curve25519_keypair_t * enc_kp
Definition: hs_cell.h:57
void pathbias_count_use_attempt(origin_circuit_t *circ)
Definition: circpathbias.c:604
void circuit_change_purpose(circuit_t *circ, uint8_t new_purpose)
Definition: circuituse.c:3095
const uint8_t * subcredential
Definition: hs_cell.h:32
ssize_t hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
Definition: hs_cell.c:732
ssize_t hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie, uint8_t *cell_out)
Definition: hs_cell.c:993
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:79
#define REND_COOKIE_LEN
Definition: or.h:399
hs_intropoint_t base
Definition: hs_service.h:40
ssize_t crypto_dh_compute_secret(int severity, crypto_dh_t *dh, const char *pubkey, size_t pubkey_len, char *secret_out, size_t secret_bytes_out)
Definition: crypto_dh.c:79
static unsigned int count_opened_desc_intro_point_circuits(const hs_service_t *service, const hs_service_descriptor_t *desc)
Definition: hs_circuit.c:219
void hs_circ_retry_service_rendezvous_point(origin_circuit_t *circ)
Definition: hs_circuit.c:695
#define CIRCUIT_PURPOSE_S_REND_JOINED
Definition: circuitlist.h:112
struct hs_ident_circuit_t * hs_ident
Header file for rendclient.c.
ssize_t hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data, const origin_circuit_t *circ, const hs_service_t *service)
Definition: hs_cell.c:755
#define LD_PROTOCOL
Definition: log.h:72
int hs_service_requires_uptime_circ(const smartlist_t *ports)
Definition: hs_common.c:1109
smartlist_t * link_specifiers
Definition: hs_cell.h:75
void hs_circuitmap_register_intro_circ_v2_service_side(origin_circuit_t *circ, const uint8_t *digest)
void pathbias_mark_use_success(origin_circuit_t *circ)
Definition: circpathbias.c:661
unsigned int hs_service_side_rend_circ_has_been_relaunched
static void cleanup_on_free_client_circ(circuit_t *circ)
Definition: hs_circuit.c:626
#define LD_BUG
Definition: log.h:86
#define CURVE25519_PUBKEY_LEN
Definition: x25519_sizes.h:20
uint8_t state
Definition: crypt_path_st.h:68
uint8_t legacy_key_digest[DIGEST_LEN]
Definition: hs_service.h:58
tor_cert_t * auth_key_cert