Tor 0.4.9.13
Loading...
Searching...
No Matches
hs_cell.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_cell.c
6 * \brief Hidden service API for cell creation and handling.
7 **/
8
9#include "core/or/or.h"
10#include "app/config/config.h"
13
14#include "feature/hs/hs_cell.h"
15#include "feature/hs/hs_ob.h"
16#include "core/crypto/hs_ntor.h"
19
21
22/* Trunnel. */
23#include "trunnel/congestion_control.h"
24#include "trunnel/ed25519_cert.h"
25#include "trunnel/extension.h"
26#include "trunnel/hs/cell_establish_intro.h"
27#include "trunnel/hs/cell_introduce1.h"
28#include "trunnel/hs/cell_rendezvous.h"
29
30/** Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is
31 * the cell content up to the ENCRYPTED section of length encoded_cell_len.
32 * The encrypted param is the start of the ENCRYPTED section of length
33 * encrypted_len. The mac_key is the key needed for the computation of the MAC
34 * derived from the ntor handshake of length mac_key_len.
35 *
36 * The length mac_out_len must be at least DIGEST256_LEN. */
37static void
38compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len,
39 const uint8_t *encrypted, size_t encrypted_len,
40 const uint8_t *mac_key, size_t mac_key_len,
41 uint8_t *mac_out, size_t mac_out_len)
42{
43 size_t offset = 0;
44 size_t mac_msg_len;
45 uint8_t mac_msg[RELAY_PAYLOAD_SIZE_MAX] = {0};
46
47 tor_assert(encoded_cell);
48 tor_assert(encrypted);
49 tor_assert(mac_key);
50 tor_assert(mac_out);
51 tor_assert(mac_out_len >= DIGEST256_LEN);
52
53 /* Compute the size of the message which is basically the entire cell until
54 * the MAC field of course. */
55 mac_msg_len = encoded_cell_len + (encrypted_len - DIGEST256_LEN);
56 tor_assert(mac_msg_len <= sizeof(mac_msg));
57
58 /* First, put the encoded cell in the msg. */
59 memcpy(mac_msg, encoded_cell, encoded_cell_len);
60 offset += encoded_cell_len;
61 /* Second, put the CLIENT_PK + ENCRYPTED_DATA but omit the MAC field (which
62 * is junk at this point). */
63 memcpy(mac_msg + offset, encrypted, (encrypted_len - DIGEST256_LEN));
64 offset += (encrypted_len - DIGEST256_LEN);
65 tor_assert(offset == mac_msg_len);
66
67 crypto_mac_sha3_256(mac_out, mac_out_len,
68 mac_key, mac_key_len,
69 mac_msg, mac_msg_len);
70 memwipe(mac_msg, 0, sizeof(mac_msg));
71}
72
73/**
74 * From a set of keys, a list of subcredentials, and the ENCRYPTED section of
75 * an INTRODUCE2 cell, return an array of newly allocated intro cell keys
76 * structures. Finally, the client public key is copied in client_pk. On
77 * error, return NULL.
78 **/
81 const curve25519_keypair_t *enc_key,
82 size_t n_subcredentials,
83 const hs_subcredential_t *subcredentials,
84 const uint8_t *encrypted_section,
85 curve25519_public_key_t *client_pk)
86{
88
89 tor_assert(auth_key);
90 tor_assert(enc_key);
91 tor_assert(n_subcredentials > 0);
92 tor_assert(subcredentials);
93 tor_assert(encrypted_section);
94 tor_assert(client_pk);
95
96 keys = tor_calloc(n_subcredentials, sizeof(hs_ntor_intro_cell_keys_t));
97
98 /* First bytes of the ENCRYPTED section are the client public key. */
99 memcpy(client_pk->public_key, encrypted_section, CURVE25519_PUBKEY_LEN);
100
101 if (hs_ntor_service_get_introduce1_keys_multi(auth_key, enc_key, client_pk,
102 n_subcredentials,
103 subcredentials, keys) < 0) {
104 /* Don't rely on the caller to wipe this on error. */
105 memwipe(client_pk, 0, sizeof(curve25519_public_key_t));
106 tor_free(keys);
107 keys = NULL;
108 }
109 return keys;
110}
111
112/** Using the given encryption key, decrypt the encrypted_section of length
113 * encrypted_section_len of an INTRODUCE2 cell and return a newly allocated
114 * buffer containing the decrypted data. On decryption failure, NULL is
115 * returned. */
116static uint8_t *
117decrypt_introduce2(const uint8_t *enc_key, const uint8_t *encrypted_section,
118 size_t encrypted_section_len)
119{
120 uint8_t *decrypted = NULL;
121 crypto_cipher_t *cipher = NULL;
122
123 tor_assert(enc_key);
124 tor_assert(encrypted_section);
125
126 /* Decrypt ENCRYPTED section. */
127 cipher = crypto_cipher_new_with_bits((char *) enc_key,
129 tor_assert(cipher);
130
131 /* This is symmetric encryption so can't be bigger than the encrypted
132 * section length. */
133 decrypted = tor_malloc_zero(encrypted_section_len);
134 if (crypto_cipher_decrypt(cipher, (char *) decrypted,
135 (const char *) encrypted_section,
136 encrypted_section_len) < 0) {
137 tor_free(decrypted);
138 decrypted = NULL;
139 goto done;
140 }
141
142 done:
143 crypto_cipher_free(cipher);
144 return decrypted;
145}
146
147/** Given a pointer to the decrypted data of the ENCRYPTED section of an
148 * INTRODUCE2 cell of length decrypted_len, parse and validate the cell
149 * content. Return a newly allocated cell structure or NULL on error. The
150 * circuit and service object are only used for logging purposes. */
151static trn_cell_introduce_encrypted_t *
152parse_introduce2_encrypted(const uint8_t *decrypted_data,
153 size_t decrypted_len, const origin_circuit_t *circ,
154 const hs_service_t *service)
155{
156 trn_cell_introduce_encrypted_t *enc_cell = NULL;
157
158 tor_assert(decrypted_data);
159 tor_assert(circ);
160 tor_assert(service);
161
162 if (trn_cell_introduce_encrypted_parse(&enc_cell, decrypted_data,
163 decrypted_len) < 0) {
164 log_info(LD_REND, "Unable to parse the decrypted ENCRYPTED section of "
165 "the INTRODUCE2 cell on circuit %u for service %s",
166 TO_CIRCUIT(circ)->n_circ_id,
167 safe_str_client(service->onion_address));
168 goto err;
169 }
170
171 if (trn_cell_introduce_encrypted_get_onion_key_type(enc_cell) !=
172 TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR) {
173 log_info(LD_REND, "INTRODUCE2 onion key type is invalid. Got %u but "
174 "expected %u on circuit %u for service %s",
175 trn_cell_introduce_encrypted_get_onion_key_type(enc_cell),
176 TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR,
177 TO_CIRCUIT(circ)->n_circ_id,
178 safe_str_client(service->onion_address));
179 goto err;
180 }
181
182 if (trn_cell_introduce_encrypted_getlen_onion_key(enc_cell) !=
184 log_info(LD_REND, "INTRODUCE2 onion key length is invalid. Got %u but "
185 "expected %d on circuit %u for service %s",
186 (unsigned)trn_cell_introduce_encrypted_getlen_onion_key(enc_cell),
187 CURVE25519_PUBKEY_LEN, TO_CIRCUIT(circ)->n_circ_id,
188 safe_str_client(service->onion_address));
189 goto err;
190 }
191 /* XXX: Validate NSPEC field as well. */
192
193 return enc_cell;
194 err:
195 trn_cell_introduce_encrypted_free(enc_cell);
196 return NULL;
197}
198
199/** Parse an INTRODUCE2 cell from payload of size payload_len for the given
200 * service and circuit which are used only for logging purposes. The resulting
201 * parsed cell is put in cell_ptr_out.
202 *
203 * Return 0 on success else a negative value and cell_ptr_out is untouched. */
204static int
206 const origin_circuit_t *circ, const uint8_t *payload,
207 size_t payload_len,
208 trn_cell_introduce1_t **cell_ptr_out)
209{
210 trn_cell_introduce1_t *cell = NULL;
211
212 tor_assert(service);
213 tor_assert(circ);
214 tor_assert(payload);
215 tor_assert(cell_ptr_out);
216
217 /* Parse the cell so we can start cell validation. */
218 if (trn_cell_introduce1_parse(&cell, payload, payload_len) < 0) {
219 log_info(LD_PROTOCOL, "Unable to parse INTRODUCE2 cell on circuit %u "
220 "for service %s",
221 TO_CIRCUIT(circ)->n_circ_id,
222 safe_str_client(service->onion_address));
223 goto err;
224 }
225
226 /* Success. */
227 *cell_ptr_out = cell;
228 return 0;
229 err:
230 return -1;
231}
232
233/** Set the onion public key onion_pk in cell, the encrypted section of an
234 * INTRODUCE1 cell. */
235static void
236introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell,
237 const uint8_t *onion_pk)
238{
239 tor_assert(cell);
240 tor_assert(onion_pk);
241 /* There is only one possible key type for a non legacy cell. */
242 trn_cell_introduce_encrypted_set_onion_key_type(cell,
243 TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR);
244 trn_cell_introduce_encrypted_set_onion_key_len(cell, CURVE25519_PUBKEY_LEN);
245 trn_cell_introduce_encrypted_setlen_onion_key(cell, CURVE25519_PUBKEY_LEN);
246 memcpy(trn_cell_introduce_encrypted_getarray_onion_key(cell), onion_pk,
247 trn_cell_introduce_encrypted_getlen_onion_key(cell));
248}
249
250/** Set the link specifiers in lspecs in cell, the encrypted section of an
251 * INTRODUCE1 cell. */
252static void
253introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell,
254 const smartlist_t *lspecs)
255{
256 tor_assert(cell);
257 tor_assert(lspecs);
258 tor_assert(smartlist_len(lspecs) > 0);
259 tor_assert(smartlist_len(lspecs) <= UINT8_MAX);
260
261 uint8_t lspecs_num = (uint8_t) smartlist_len(lspecs);
262 trn_cell_introduce_encrypted_set_nspec(cell, lspecs_num);
263 /* We aren't duplicating the link specifiers object here which means that
264 * the ownership goes to the trn_cell_introduce_encrypted_t cell and those
265 * object will be freed when the cell is. */
266 SMARTLIST_FOREACH(lspecs, link_specifier_t *, ls,
267 trn_cell_introduce_encrypted_add_nspecs(cell, ls));
268}
269
270/** Set padding in the enc_cell only if needed that is the total length of both
271 * sections are below the minimum required for an INTRODUCE1 cell. */
272static void
273introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell,
274 trn_cell_introduce_encrypted_t *enc_cell)
275{
276 tor_assert(cell);
277 tor_assert(enc_cell);
278 /* This is the length we expect to have once encoded of the whole cell. */
279 ssize_t full_len = trn_cell_introduce1_encoded_len(cell) +
280 trn_cell_introduce_encrypted_encoded_len(enc_cell);
281 tor_assert(full_len > 0);
282 if (full_len < HS_CELL_INTRODUCE1_MIN_SIZE) {
283 size_t padding = HS_CELL_INTRODUCE1_MIN_SIZE - full_len;
284 trn_cell_introduce_encrypted_setlen_pad(enc_cell, padding);
285 memset(trn_cell_introduce_encrypted_getarray_pad(enc_cell), 0,
286 trn_cell_introduce_encrypted_getlen_pad(enc_cell));
287 }
288}
289
290/** Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell
291 * and the INTRODUCE1 data.
292 *
293 * It is very important that the caller sets every field
294 * in data so the computation of the INTRODUCE1 keys doesn't fail.
295 *
296 * Return 0 on success, -1 if we should fail the circuit. */
297static int
298introduce1_encrypt_and_encode(trn_cell_introduce1_t *cell,
299 const trn_cell_introduce_encrypted_t *enc_cell,
300 const hs_cell_introduce1_data_t *data)
301{
302 size_t offset = 0;
303 ssize_t encrypted_len;
304 ssize_t encoded_cell_len, encoded_enc_cell_len;
305 uint8_t encoded_cell[RELAY_PAYLOAD_SIZE_MAX] = {0};
306 uint8_t encoded_enc_cell[RELAY_PAYLOAD_SIZE_MAX] = {0};
307 uint8_t *encrypted = NULL;
308 uint8_t mac[DIGEST256_LEN];
309 crypto_cipher_t *cipher = NULL;
311
312 tor_assert(cell);
313 tor_assert(enc_cell);
314 tor_assert(data);
315
316 /* Encode the cells up to now of what we have so we can perform the MAC
317 * computation on it. */
318 encoded_cell_len = trn_cell_introduce1_encode(encoded_cell,
319 sizeof(encoded_cell), cell);
320 /* We have a much more serious issue if this isn't true. */
321 tor_assert(encoded_cell_len > 0);
322
323 encoded_enc_cell_len =
324 trn_cell_introduce_encrypted_encode(encoded_enc_cell,
325 sizeof(encoded_enc_cell), enc_cell);
326 /* We have a much more serious issue if this isn't true. */
327 tor_assert(encoded_enc_cell_len > 0);
328
329 /* Get the key material for the encryption. */
330 if (hs_ntor_client_get_introduce1_keys(data->auth_pk, data->enc_pk,
331 data->client_kp,
332 data->subcredential, &keys) < 0) {
333 /* this can happen in practice if e.g. the onion service is rude
334 * and sets one of its introduction keys to all-zero. */
335 return -1;
336 }
337
338 /* Prepare cipher with the encryption key just computed. */
339 cipher = crypto_cipher_new_with_bits((const char *) keys.enc_key,
340 sizeof(keys.enc_key) * 8);
341 tor_assert(cipher);
342
343 /* Compute the length of the ENCRYPTED section which is the CLIENT_PK,
344 * ENCRYPTED_DATA and MAC length. */
345 encrypted_len = sizeof(data->client_kp->pubkey) + encoded_enc_cell_len +
346 sizeof(mac);
347 tor_assert(encrypted_len < RELAY_PAYLOAD_SIZE_MAX);
348 encrypted = tor_malloc_zero(encrypted_len);
349
350 /* Put the CLIENT_PK first. */
351 memcpy(encrypted, data->client_kp->pubkey.public_key,
352 sizeof(data->client_kp->pubkey.public_key));
353 offset += sizeof(data->client_kp->pubkey.public_key);
354 /* Then encrypt and set the ENCRYPTED_DATA. This can't fail. */
355 crypto_cipher_encrypt(cipher, (char *) encrypted + offset,
356 (const char *) encoded_enc_cell, encoded_enc_cell_len);
357 crypto_cipher_free(cipher);
358 offset += encoded_enc_cell_len;
359 /* Compute MAC from the above and put it in the buffer. This function will
360 * make the adjustment to the encrypted_len to omit the MAC length. */
361 compute_introduce_mac(encoded_cell, encoded_cell_len,
362 encrypted, encrypted_len,
363 keys.mac_key, sizeof(keys.mac_key),
364 mac, sizeof(mac));
365 memcpy(encrypted + offset, mac, sizeof(mac));
366 offset += sizeof(mac);
367 tor_assert(offset == (size_t) encrypted_len);
368
369 /* Set the ENCRYPTED section in the cell. */
370 trn_cell_introduce1_setlen_encrypted(cell, encrypted_len);
371 memcpy(trn_cell_introduce1_getarray_encrypted(cell),
372 encrypted, encrypted_len);
373
374 /* Cleanup. */
375 memwipe(&keys, 0, sizeof(keys));
376 memwipe(mac, 0, sizeof(mac));
377 memwipe(encrypted, 0, encrypted_len);
378 memwipe(encoded_enc_cell, 0, sizeof(encoded_enc_cell));
379 tor_free(encrypted);
380 return 0;
381}
382
383/** Build the PoW cell extension and put it in the given extensions object.
384 * Return 0 on success, -1 on failure. */
385static int
387 trn_extension_t *extensions)
388{
389 ssize_t ret;
390 size_t pow_ext_encoded_len;
391 uint8_t *field_array;
392 trn_extension_field_t *field = NULL;
393 trn_cell_extension_pow_t *pow_ext = NULL;
394
395 tor_assert(pow_solution);
396 tor_assert(extensions);
397
398 /* We are creating a cell extension field of type PoW solution. */
399 field = trn_extension_field_new();
400 trn_extension_field_set_field_type(field, TRUNNEL_EXT_TYPE_POW);
401
402 /* Build PoW extension field. */
403 pow_ext = trn_cell_extension_pow_new();
404
405 /* Copy PoW solution values into PoW extension cell. */
406
407 /* Equi-X base scheme */
408 trn_cell_extension_pow_set_pow_version(pow_ext, TRUNNEL_POW_VERSION_EQUIX);
409
410 memcpy(trn_cell_extension_pow_getarray_pow_nonce(pow_ext),
411 &pow_solution->nonce, TRUNNEL_POW_NONCE_LEN);
412
413 trn_cell_extension_pow_set_pow_effort(pow_ext, pow_solution->effort);
414
415 memcpy(trn_cell_extension_pow_getarray_pow_seed(pow_ext),
416 pow_solution->seed_head, TRUNNEL_POW_SEED_HEAD_LEN);
417 memcpy(trn_cell_extension_pow_getarray_pow_solution(pow_ext),
418 pow_solution->equix_solution, TRUNNEL_POW_SOLUTION_LEN);
419
420 /* Set the field with the encoded PoW extension. */
421 ret = trn_cell_extension_pow_encoded_len(pow_ext);
422 if (BUG(ret <= 0)) {
423 goto err;
424 }
425 pow_ext_encoded_len = ret;
426
427 /* Set length field and the field array size length. */
428 trn_extension_field_set_field_len(field, pow_ext_encoded_len);
429 trn_extension_field_setlen_field(field, pow_ext_encoded_len);
430 /* Encode the PoW extension into the cell extension field. */
431 field_array = trn_extension_field_getarray_field(field);
432 ret = trn_cell_extension_pow_encode(field_array,
433 trn_extension_field_getlen_field(field), pow_ext);
434 if (BUG(ret <= 0)) {
435 goto err;
436 }
437 tor_assert(ret == (ssize_t)pow_ext_encoded_len);
438
439 /* Finally, encode field into the cell extension. */
440 trn_extension_add_fields(extensions, field);
441
442 /* We've just add an extension field to the cell extensions so increment the
443 * total number. */
444 trn_extension_set_num(extensions, trn_extension_get_num(extensions) + 1);
445
446 /* Cleanup. PoW extension has been encoded at this point. */
447 trn_cell_extension_pow_free(pow_ext);
448
449 return 0;
450
451err:
452 trn_extension_field_free(field);
453 trn_cell_extension_pow_free(pow_ext);
454 return -1;
455}
456
457/** Build and set the INTRODUCE congestion control extension in the given
458 * extensions. */
459static void
460build_introduce_cc_extension(trn_extension_t *extensions)
461{
462 trn_extension_field_t *field = NULL;
463
464 /* Build CC request extension. */
465 field = trn_extension_field_new();
466 trn_extension_field_set_field_type(field,
467 TRUNNEL_EXT_TYPE_CC_REQUEST);
468
469 /* No payload indicating a request to use congestion control. */
470 trn_extension_field_set_field_len(field, 0);
471
472 /* Build final extension. */
473 trn_extension_add_fields(extensions, field);
474 trn_extension_set_num(extensions, trn_extension_get_num(extensions) + 1);
475}
476
477/** Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means
478 * set it, encrypt it, and encode it. Return 0 on success, -1 on failure. */
479static int
480introduce1_set_encrypted(trn_cell_introduce1_t *cell,
481 const hs_cell_introduce1_data_t *data)
482{
483 trn_cell_introduce_encrypted_t *enc_cell;
484 trn_extension_t *ext;
485
486 tor_assert(cell);
487 tor_assert(data);
488
489 enc_cell = trn_cell_introduce_encrypted_new();
490 tor_assert(enc_cell);
491
492 /* Setup extension(s) if any. */
493 ext = trn_extension_new();
494 tor_assert(ext);
495 /* Build congestion control extension if enabled. */
496 if (data->cc_enabled) {
498 }
499 /* Build PoW extension if present. */
500 if (data->pow_solution) {
502 }
503 trn_cell_introduce_encrypted_set_extensions(enc_cell, ext);
504
505 /* Set the rendezvous cookie. */
506 memcpy(trn_cell_introduce_encrypted_getarray_rend_cookie(enc_cell),
508
509 /* Set the onion public key. */
510 introduce1_set_encrypted_onion_key(enc_cell, data->onion_pk->public_key);
511
512 /* Set the link specifiers. */
514
515 /* Set padding. */
516 introduce1_set_encrypted_padding(cell, enc_cell);
517
518 /* Encrypt and encode it in the cell. */
519 if (introduce1_encrypt_and_encode(cell, enc_cell, data) < 0)
520 return -1;
521
522 /* Cleanup. */
523 trn_cell_introduce_encrypted_free(enc_cell);
524 return 0;
525}
526
527/** Set the authentication key in the INTRODUCE1 cell from the given data. */
528static void
529introduce1_set_auth_key(trn_cell_introduce1_t *cell,
530 const hs_cell_introduce1_data_t *data)
531{
532 tor_assert(cell);
533 tor_assert(data);
534 /* There is only one possible type for a non legacy cell. */
535 trn_cell_introduce1_set_auth_key_type(cell,
536 TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519);
537 trn_cell_introduce1_set_auth_key_len(cell, ED25519_PUBKEY_LEN);
538 trn_cell_introduce1_setlen_auth_key(cell, ED25519_PUBKEY_LEN);
539 memcpy(trn_cell_introduce1_getarray_auth_key(cell),
540 data->auth_pk->pubkey, trn_cell_introduce1_getlen_auth_key(cell));
541}
542
543/** Build and add to the given DoS cell extension the given parameter type and
544 * value. */
545static void
546build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext,
547 uint8_t param_type, uint64_t param_value)
548{
549 trn_cell_extension_dos_param_t *dos_param =
550 trn_cell_extension_dos_param_new();
551
552 /* Extra safety. We should never send an unknown parameter type. */
553 tor_assert(param_type == TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC ||
554 param_type == TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC);
555
556 trn_cell_extension_dos_param_set_type(dos_param, param_type);
557 trn_cell_extension_dos_param_set_value(dos_param, param_value);
558 trn_cell_extension_dos_add_params(dos_ext, dos_param);
559
560 /* Not freeing the trunnel object because it is now owned by dos_ext. */
561}
562
563/** Build the DoS defense cell extension and put it in the given extensions
564 * object. Return 0 on success, -1 on failure. (Right now, failure is only
565 * possible if there is a bug.) */
566static int
568 trn_extension_t *extensions)
569{
570 ssize_t ret;
571 size_t dos_ext_encoded_len;
572 uint8_t *field_array;
573 trn_extension_field_t *field = NULL;
574 trn_cell_extension_dos_t *dos_ext = NULL;
575
576 tor_assert(service_config);
577 tor_assert(extensions);
578
579 /* We are creating a cell extension field of the type DoS. */
580 field = trn_extension_field_new();
581 trn_extension_field_set_field_type(field,
582 TRUNNEL_CELL_EXTENSION_TYPE_DOS);
583
584 /* Build DoS extension field. We will put in two parameters. */
585 dos_ext = trn_cell_extension_dos_new();
586 trn_cell_extension_dos_set_n_params(dos_ext, 2);
587
588 /* Build DoS parameter INTRO2 rate per second. */
590 TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC,
591 service_config->intro_dos_rate_per_sec);
592 /* Build DoS parameter INTRO2 burst per second. */
594 TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC,
595 service_config->intro_dos_burst_per_sec);
596
597 /* Set the field with the encoded DoS extension. */
598 ret = trn_cell_extension_dos_encoded_len(dos_ext);
599 if (BUG(ret <= 0)) {
600 goto err;
601 }
602 dos_ext_encoded_len = ret;
603 /* Set length field and the field array size length. */
604 trn_extension_field_set_field_len(field, dos_ext_encoded_len);
605 trn_extension_field_setlen_field(field, dos_ext_encoded_len);
606 /* Encode the DoS extension into the cell extension field. */
607 field_array = trn_extension_field_getarray_field(field);
608 ret = trn_cell_extension_dos_encode(field_array,
609 trn_extension_field_getlen_field(field), dos_ext);
610 if (BUG(ret <= 0)) {
611 goto err;
612 }
613 tor_assert(ret == (ssize_t) dos_ext_encoded_len);
614
615 /* Finally, encode field into the cell extension. */
616 trn_extension_add_fields(extensions, field);
617
618 /* We've just add an extension field to the cell extensions so increment the
619 * total number. */
620 trn_extension_set_num(extensions, trn_extension_get_num(extensions) + 1);
621
622 /* Cleanup. DoS extension has been encoded at this point. */
623 trn_cell_extension_dos_free(dos_ext);
624
625 return 0;
626
627 err:
628 trn_extension_field_free(field);
629 trn_cell_extension_dos_free(dos_ext);
630 return -1;
631}
632
633/* ========== */
634/* Public API */
635/* ========== */
636
637/** Allocate and build all the ESTABLISH_INTRO cell extension. The given
638 * extensions pointer is always set to a valid cell extension object. */
639STATIC trn_extension_t *
641 const hs_service_intro_point_t *ip)
642{
643 int ret;
644 trn_extension_t *extensions;
645
646 tor_assert(service_config);
647 tor_assert(ip);
648
649 extensions = trn_extension_new();
650 trn_extension_set_num(extensions, 0);
651
652 /* If the defense has been enabled service side (by the operator with a
653 * torrc option) and the intro point does support it. */
654 if (service_config->has_dos_defense_enabled &&
656 /* This function takes care to increment the number of extensions. */
657 ret = build_establish_intro_dos_extension(service_config, extensions);
658 if (ret < 0) {
659 /* Return no extensions on error. */
660 goto end;
661 }
662 }
663
664 end:
665 return extensions;
666}
667
668/** Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point
669 * object. The encoded cell is put in cell_out that MUST at least be of the
670 * size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on success else
671 * a negative value and cell_out is untouched. */
672ssize_t
673hs_cell_build_establish_intro(const char *circ_nonce,
674 const hs_service_config_t *service_config,
675 const hs_service_intro_point_t *ip,
676 uint8_t *cell_out)
677{
678 ssize_t cell_len = -1;
679 uint16_t sig_len = ED25519_SIG_LEN;
680 trn_cell_establish_intro_t *cell = NULL;
681 trn_extension_t *extensions;
682
683 tor_assert(circ_nonce);
684 tor_assert(service_config);
685 tor_assert(ip);
686
687 /* Build the extensions, if any. */
688 extensions = build_establish_intro_extensions(service_config, ip);
689
690 /* Set extension data. None used here. */
691 cell = trn_cell_establish_intro_new();
692 trn_cell_establish_intro_set_extensions(cell, extensions);
693 /* Set signature size. Array is then allocated in the cell. We need to do
694 * this early so we can use trunnel API to get the signature length. */
695 trn_cell_establish_intro_set_sig_len(cell, sig_len);
696 trn_cell_establish_intro_setlen_sig(cell, sig_len);
697
698 /* Set AUTH_KEY_TYPE: 2 means ed25519 */
699 trn_cell_establish_intro_set_auth_key_type(cell,
700 TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519);
701
702 /* Set AUTH_KEY and AUTH_KEY_LEN field. Must also set byte-length of
703 * AUTH_KEY to match */
704 {
705 uint16_t auth_key_len = ED25519_PUBKEY_LEN;
706 trn_cell_establish_intro_set_auth_key_len(cell, auth_key_len);
707 trn_cell_establish_intro_setlen_auth_key(cell, auth_key_len);
708 /* We do this call _after_ setting the length because it's reallocated at
709 * that point only. */
710 uint8_t *auth_key_ptr = trn_cell_establish_intro_getarray_auth_key(cell);
711 memcpy(auth_key_ptr, ip->auth_key_kp.pubkey.pubkey, auth_key_len);
712 }
713
714 /* Calculate HANDSHAKE_AUTH field (MAC). */
715 {
716 ssize_t tmp_cell_enc_len = 0;
717 ssize_t tmp_cell_mac_offset =
718 sig_len + sizeof(cell->sig_len) +
719 trn_cell_establish_intro_getlen_handshake_mac(cell);
720 uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE_MAX] = {0};
721 uint8_t mac[TRUNNEL_SHA3_256_LEN], *handshake_ptr;
722
723 /* We first encode the current fields we have in the cell so we can
724 * compute the MAC using the raw bytes. */
725 tmp_cell_enc_len = trn_cell_establish_intro_encode(tmp_cell_enc,
726 sizeof(tmp_cell_enc),
727 cell);
728 if (BUG(tmp_cell_enc_len < 0)) {
729 goto done;
730 }
731 /* Sanity check. */
732 tor_assert(tmp_cell_enc_len > tmp_cell_mac_offset);
733
734 /* Circuit nonce is always DIGEST_LEN according to tor-spec.txt. */
735 crypto_mac_sha3_256(mac, sizeof(mac),
736 (uint8_t *) circ_nonce, DIGEST_LEN,
737 tmp_cell_enc, tmp_cell_enc_len - tmp_cell_mac_offset);
738 handshake_ptr = trn_cell_establish_intro_getarray_handshake_mac(cell);
739 memcpy(handshake_ptr, mac, sizeof(mac));
740
741 memwipe(mac, 0, sizeof(mac));
742 memwipe(tmp_cell_enc, 0, sizeof(tmp_cell_enc));
743 }
744
745 /* Calculate the cell signature SIG. */
746 {
747 ssize_t tmp_cell_enc_len = 0;
748 ssize_t tmp_cell_sig_offset = (sig_len + sizeof(cell->sig_len));
749 uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE_MAX] = {0}, *sig_ptr;
751
752 /* We first encode the current fields we have in the cell so we can
753 * compute the signature from the raw bytes of the cell. */
754 tmp_cell_enc_len = trn_cell_establish_intro_encode(tmp_cell_enc,
755 sizeof(tmp_cell_enc),
756 cell);
757 if (BUG(tmp_cell_enc_len < 0)) {
758 goto done;
759 }
760
761 if (ed25519_sign_prefixed(&sig, tmp_cell_enc,
762 tmp_cell_enc_len - tmp_cell_sig_offset,
764 log_warn(LD_BUG, "Unable to make signature for ESTABLISH_INTRO cell.");
765 goto done;
766 }
767 /* Copy the signature into the cell. */
768 sig_ptr = trn_cell_establish_intro_getarray_sig(cell);
769 memcpy(sig_ptr, sig.sig, sig_len);
770
771 memwipe(tmp_cell_enc, 0, sizeof(tmp_cell_enc));
772 }
773
774 /* Encode the cell. Can't be bigger than a standard cell. */
775 cell_len = trn_cell_establish_intro_encode(cell_out,
777 cell);
778
779 done:
780 trn_cell_establish_intro_free(cell);
781 return cell_len;
782}
783
784/** Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we
785 * are successful at parsing it, return the length of the parsed cell else a
786 * negative value on error. */
787ssize_t
788hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
789{
790 ssize_t ret;
791 trn_cell_intro_established_t *cell = NULL;
792
793 tor_assert(payload);
794
795 /* Try to parse the payload into a cell making sure we do actually have a
796 * valid cell. */
797 ret = trn_cell_intro_established_parse(&cell, payload, payload_len);
798 if (ret >= 0) {
799 /* On success, we do not keep the cell, we just notify the caller that it
800 * was successfully parsed. */
801 trn_cell_intro_established_free(cell);
802 }
803 return ret;
804}
805
806/** Parse the cell PoW solution extension. Return 0 on success and data
807 * structure is updated with the PoW effort. Return -1 on any kind of error
808 * including if PoW couldn't be verified. */
809static int
811 const hs_service_intro_point_t *ip,
812 const trn_extension_field_t *field,
814{
815 int ret = -1;
816 trn_cell_extension_pow_t *pow = NULL;
818
819 tor_assert(field);
820 tor_assert(ip);
821
822 if (!service->state.pow_state) {
823 log_info(LD_REND, "Unsolicited PoW solution in INTRODUCE2 request.");
824 goto end;
825 }
826
827 if (trn_cell_extension_pow_parse(&pow,
828 trn_extension_field_getconstarray_field(field),
829 trn_extension_field_getlen_field(field)) < 0) {
830 goto end;
831 }
832
833 /* There is only one version supported at the moment so validate we at least
834 * have that. */
835 if (trn_cell_extension_pow_get_pow_version(pow) !=
836 TRUNNEL_POW_VERSION_EQUIX) {
837 log_debug(LD_REND, "Unsupported PoW version. Malformed INTRODUCE2");
838 goto end;
839 }
840
841 /* Effort E */
842 sol.effort = trn_cell_extension_pow_get_pow_effort(pow);
843 /* Seed C */
844 memcpy(sol.seed_head, trn_cell_extension_pow_getconstarray_pow_seed(pow),
846 /* Nonce N */
847 memcpy(sol.nonce, trn_cell_extension_pow_getconstarray_pow_nonce(pow),
849 /* Solution S */
850 memcpy(sol.equix_solution,
851 trn_cell_extension_pow_getconstarray_pow_solution(pow),
853
854 if (hs_pow_verify(&ip->blinded_id, service->state.pow_state, &sol)) {
855 log_info(LD_REND, "PoW INTRODUCE2 request failed to verify.");
856 goto end;
857 }
858
859 log_info(LD_REND, "PoW INTRODUCE2 request successfully verified.");
860 data->rdv_data.pow_effort = sol.effort;
861
862 /* Successfully parsed and verified the PoW solution */
863 ret = 0;
864
865 end:
866 trn_cell_extension_pow_free(pow);
867 return ret;
868}
869
870/** For the encrypted INTRO2 cell in <b>encrypted_section</b>, use the crypto
871 * material in <b>data</b> to compute the right ntor keys. Also validate the
872 * INTRO2 MAC to ensure that the keys are the right ones.
873 *
874 * Return NULL on failure to either produce the key material or on MAC
875 * validation. Else return a newly allocated intro keys object. */
878 const uint8_t *encrypted_section,
879 size_t encrypted_section_len)
880{
881 hs_ntor_intro_cell_keys_t *intro_keys = NULL;
882 hs_ntor_intro_cell_keys_t *intro_keys_result = NULL;
883
884 /* Build the key material out of the key material found in the cell. */
885 intro_keys = get_introduce2_key_material(data->auth_pk, data->enc_kp,
886 data->n_subcredentials,
887 data->subcredentials,
888 encrypted_section,
889 &data->rdv_data.client_pk);
890 if (intro_keys == NULL) {
891 log_info(LD_REND, "Invalid INTRODUCE2 encrypted data. Unable to "
892 "compute key material");
893 return NULL;
894 }
895
896 /* Make sure we are not about to underflow. */
897 if (BUG(encrypted_section_len < DIGEST256_LEN)) {
898 return NULL;
899 }
900
901 /* Validate MAC from the cell and our computed key material. The MAC field
902 * in the cell is at the end of the encrypted section. */
903 intro_keys_result = tor_malloc_zero(sizeof(*intro_keys_result));
904 for (unsigned i = 0; i < data->n_subcredentials; ++i) {
905 uint8_t mac[DIGEST256_LEN];
906
907 /* The MAC field is at the very end of the ENCRYPTED section. */
908 size_t mac_offset = encrypted_section_len - sizeof(mac);
909 /* Compute the MAC. Use the entire encoded payload with a length up to the
910 * ENCRYPTED section. */
912 data->payload_len - encrypted_section_len,
913 encrypted_section, encrypted_section_len,
914 intro_keys[i].mac_key,
915 sizeof(intro_keys[i].mac_key),
916 mac, sizeof(mac));
917 /* Time-invariant conditional copy: if the MAC is what we expected, then
918 * set intro_keys_result to intro_keys[i]. Otherwise, don't: but don't
919 * leak which one it was! */
920 bool equal = tor_memeq(mac, encrypted_section + mac_offset, sizeof(mac));
921 memcpy_if_true_timei(equal, intro_keys_result, &intro_keys[i],
922 sizeof(*intro_keys_result));
923 }
924
925 /* We no longer need intro_keys. */
926 memwipe(intro_keys, 0,
928 tor_free(intro_keys);
929
930 if (safe_mem_is_zero(intro_keys_result, sizeof(*intro_keys_result))) {
931 log_info(LD_REND, "Invalid MAC validation for INTRODUCE2 cell");
932 tor_free(intro_keys_result); /* sets intro_keys_result to NULL */
933 }
934
935 return intro_keys_result;
936}
937
938/** Parse the given INTRODUCE cell extension. Update the data object
939 * accordingly depending on the extension. Return 0 if it validated
940 * correctly, or return -1 if it is malformed (for example because it
941 * includes a PoW that doesn't verify). */
942static int
944 const hs_service_intro_point_t *ip,
946 const trn_extension_field_t *field)
947{
948 int ret = 0;
949 trn_extension_field_cc_t *cc_field = NULL;
950
951 tor_assert(data);
952 tor_assert(field);
953
954 switch (trn_extension_field_get_field_type(field)) {
955 case TRUNNEL_EXT_TYPE_CC_REQUEST:
956 /* CC requests, enable it. */
957 data->rdv_data.cc_enabled = 1;
958 data->pv.protocols_known = 1;
960 break;
961 case TRUNNEL_EXT_TYPE_POW:
962 /* PoW request. If successful, the effort is put in the data. */
964 field, data) < 0) {
965 log_fn(LOG_PROTOCOL_WARN, LD_REND, "Invalid PoW cell extension.");
966 ret = -1;
967 }
968 break;
969 default:
970 break;
971 }
972
973 trn_extension_field_cc_free(cc_field);
974 return ret;
975}
976
977/** Parse the INTRODUCE2 cell using data which contains everything we need to
978 * do so and contains the destination buffers of information we extract and
979 * compute from the cell. Return 0 on success else a negative value. The
980 * service and circ are only used for logging purposes. */
981ssize_t
983 const origin_circuit_t *circ,
984 const hs_service_t *service,
985 const hs_service_intro_point_t *ip)
986{
987 int ret = -1;
988 time_t elapsed;
989 uint8_t *decrypted = NULL;
990 size_t encrypted_section_len;
991 const uint8_t *encrypted_section;
992 trn_cell_introduce1_t *cell = NULL;
993 trn_cell_introduce_encrypted_t *enc_cell = NULL;
994 hs_ntor_intro_cell_keys_t *intro_keys = NULL;
995
996 tor_assert(data);
997 tor_assert(circ);
998 tor_assert(service);
999
1000 /* Parse the cell into a decoded data structure pointed by cell_ptr. */
1001 if (parse_introduce2_cell(service, circ, data->payload, data->payload_len,
1002 &cell) < 0) {
1003 goto done;
1004 }
1005
1006 log_info(LD_REND, "Received a decodable INTRODUCE2 cell on circuit %u "
1007 "for service %s. Decoding encrypted section...",
1008 TO_CIRCUIT(circ)->n_circ_id,
1009 safe_str_client(service->onion_address));
1010
1011 encrypted_section = trn_cell_introduce1_getconstarray_encrypted(cell);
1012 encrypted_section_len = trn_cell_introduce1_getlen_encrypted(cell);
1013
1014 /* Encrypted section must at least contain the CLIENT_PK and MAC which is
1015 * defined in section 3.3.2 of the specification. */
1016 if (encrypted_section_len < (CURVE25519_PUBKEY_LEN + DIGEST256_LEN)) {
1017 log_info(LD_REND, "Invalid INTRODUCE2 encrypted section length "
1018 "for service %s. Dropping cell.",
1019 safe_str_client(service->onion_address));
1020 goto done;
1021 }
1022
1023 /* Bound insertions even between periodic introduction point expiry checks.
1024 * Retain existing entries until this introduction point is destroyed. */
1026 goto done;
1027 }
1028
1029 /* Reject known replays before authentication, but do not cache a new cell
1030 * until all cell validation has succeeded. */
1031 if (replaycache_test_and_elapsed(data->replay_cache, encrypted_section,
1032 encrypted_section_len, &elapsed)) {
1033 log_warn(LD_REND, "Possible replay detected! An INTRODUCE2 cell with the "
1034 "same ENCRYPTED section was seen %ld seconds ago. "
1035 "Dropping cell.", (long int) elapsed);
1036 goto done;
1037 }
1038
1039 /* First bytes of the ENCRYPTED section are the client public key (they are
1040 * guaranteed to exist because of the length check above). We are gonna use
1041 * the client public key to compute the ntor keys and decrypt the payload:
1042 */
1043 memcpy(&data->rdv_data.client_pk.public_key, encrypted_section,
1045
1046 /* Get the right INTRODUCE2 ntor keys and verify the cell MAC */
1047 intro_keys = get_introduce2_keys_and_verify_mac(data, encrypted_section,
1048 encrypted_section_len);
1049 if (!intro_keys) {
1050 log_warn(LD_REND, "Could not get valid INTRO2 keys on circuit %u "
1051 "for service %s", TO_CIRCUIT(circ)->n_circ_id,
1052 safe_str_client(service->onion_address));
1053 goto done;
1054 }
1055
1056 {
1057 /* The ENCRYPTED_DATA section starts just after the CLIENT_PK. */
1058 const uint8_t *encrypted_data =
1059 encrypted_section + sizeof(data->rdv_data.client_pk);
1060 /* It's symmetric encryption so it's correct to use the ENCRYPTED length
1061 * for decryption. Computes the length of ENCRYPTED_DATA meaning removing
1062 * the CLIENT_PK and MAC length. */
1063 size_t encrypted_data_len =
1064 encrypted_section_len -
1065 (sizeof(data->rdv_data.client_pk) + DIGEST256_LEN);
1066
1067 /* This decrypts the ENCRYPTED_DATA section of the cell. */
1068 decrypted = decrypt_introduce2(intro_keys->enc_key,
1069 encrypted_data, encrypted_data_len);
1070 if (decrypted == NULL) {
1071 log_info(LD_REND, "Unable to decrypt the ENCRYPTED section of an "
1072 "INTRODUCE2 cell on circuit %u for service %s",
1073 TO_CIRCUIT(circ)->n_circ_id,
1074 safe_str_client(service->onion_address));
1075 goto done;
1076 }
1077
1078 /* Parse this blob into an encrypted cell structure so we can then extract
1079 * the data we need out of it. */
1080 enc_cell = parse_introduce2_encrypted(decrypted, encrypted_data_len,
1081 circ, service);
1082 memwipe(decrypted, 0, encrypted_data_len);
1083 if (enc_cell == NULL) {
1084 goto done;
1085 }
1086 }
1087
1088 /* XXX: Implement client authorization checks. */
1089
1090 /* Extract onion key and rendezvous cookie from the cell used for the
1091 * rendezvous point circuit e2e encryption. */
1092 memcpy(data->rdv_data.onion_pk.public_key,
1093 trn_cell_introduce_encrypted_getconstarray_onion_key(enc_cell),
1096 log_fn(LOG_PROTOCOL_WARN, LD_REND,
1097 "Invalid rendezvous onion key in INTRODUCE2 cell on "
1098 "circuit %u for service %s. Dropping cell.",
1099 TO_CIRCUIT(circ)->n_circ_id,
1100 safe_str_client(service->onion_address));
1101 goto done;
1102 }
1103 memcpy(data->rdv_data.rendezvous_cookie,
1104 trn_cell_introduce_encrypted_getconstarray_rend_cookie(enc_cell),
1105 sizeof(data->rdv_data.rendezvous_cookie));
1106
1107 /* Extract rendezvous link specifiers. */
1108 for (size_t idx = 0;
1109 idx < trn_cell_introduce_encrypted_get_nspec(enc_cell); idx++) {
1110 link_specifier_t *lspec =
1111 trn_cell_introduce_encrypted_get_nspecs(enc_cell, idx);
1112 if (BUG(!lspec)) {
1113 goto done;
1114 }
1115 link_specifier_t *lspec_dup = link_specifier_dup(lspec);
1116 if (BUG(!lspec_dup)) {
1117 goto done;
1118 }
1119 smartlist_add(data->rdv_data.link_specifiers, lspec_dup);
1120 }
1121
1122 /* Extract any extensions. */
1123 const trn_extension_t *extensions =
1124 trn_cell_introduce_encrypted_get_extensions(enc_cell);
1125 if (extensions != NULL) {
1126 for (size_t idx = 0; idx < trn_extension_get_num(extensions); idx++) {
1127 const trn_extension_field_t *field =
1128 trn_extension_getconst_fields(extensions, idx);
1129 if (BUG(field == NULL)) {
1130 /* The number of extensions should match the number of fields. */
1131 break;
1132 }
1133 if (parse_introduce_cell_extension(service, ip, data, field) < 0) {
1134 goto done;
1135 }
1136 }
1137 }
1138
1139 /* If the client asked for congestion control, but we don't support it,
1140 * that's a failure. It should not have asked, based on our descriptor. */
1142 goto done;
1143 }
1144
1145 /* Only validated cells consume cache space and count towards cache-based
1146 * rotation. Keep these even if the caller rejects the rendezvous cookie:
1147 * its replay cache expires entries, while this cache must not. */
1148 replaycache_add_and_test(data->replay_cache, encrypted_section,
1149 encrypted_section_len);
1150
1151 /* Success. */
1152 ret = 0;
1153 log_info(LD_REND,
1154 "Valid INTRODUCE2 cell. Willing to launch rendezvous circuit.");
1155
1156 done:
1157 if (intro_keys) {
1158 memwipe(intro_keys, 0, sizeof(hs_ntor_intro_cell_keys_t));
1159 tor_free(intro_keys);
1160 }
1161 tor_free(decrypted);
1162 trn_cell_introduce_encrypted_free(enc_cell);
1163 trn_cell_introduce1_free(cell);
1164 return ret;
1165}
1166
1167/** Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake
1168 * info. The encoded cell is put in cell_out and the length of the data is
1169 * returned. This can't fail. */
1170ssize_t
1171hs_cell_build_rendezvous1(const uint8_t *rendezvous_cookie,
1172 size_t rendezvous_cookie_len,
1173 const uint8_t *rendezvous_handshake_info,
1174 size_t rendezvous_handshake_info_len,
1175 uint8_t *cell_out)
1176{
1177 ssize_t cell_len;
1178 trn_cell_rendezvous1_t *cell;
1179
1180 tor_assert(rendezvous_cookie);
1181 tor_assert(rendezvous_handshake_info);
1182 tor_assert(cell_out);
1183
1184 cell = trn_cell_rendezvous1_new();
1185 /* Set the RENDEZVOUS_COOKIE. */
1186 memcpy(trn_cell_rendezvous1_getarray_rendezvous_cookie(cell),
1187 rendezvous_cookie, rendezvous_cookie_len);
1188 /* Set the HANDSHAKE_INFO. */
1189 trn_cell_rendezvous1_setlen_handshake_info(cell,
1190 rendezvous_handshake_info_len);
1191 memcpy(trn_cell_rendezvous1_getarray_handshake_info(cell),
1192 rendezvous_handshake_info, rendezvous_handshake_info_len);
1193 /* Encoding. */
1194 cell_len = trn_cell_rendezvous1_encode(cell_out,
1196 tor_assert(cell_len > 0);
1197
1198 trn_cell_rendezvous1_free(cell);
1199 return cell_len;
1200}
1201
1202/** Build an INTRODUCE1 cell from the given data. The encoded cell is put in
1203 * cell_out which must be of at least size RELAY_PAYLOAD_SIZE. On success, the
1204 * encoded length is returned else a negative value and the content of
1205 * cell_out should be ignored. */
1206ssize_t
1208 uint8_t *cell_out)
1209{
1210 ssize_t cell_len;
1211 trn_cell_introduce1_t *cell;
1212 trn_extension_t *ext;
1213
1214 tor_assert(data);
1215 tor_assert(cell_out);
1216
1217 cell = trn_cell_introduce1_new();
1218 tor_assert(cell);
1219
1220 /* Set extension data. None are used. */
1221 ext = trn_extension_new();
1222 tor_assert(ext);
1223 trn_extension_set_num(ext, 0);
1224 trn_cell_introduce1_set_extensions(cell, ext);
1225
1226 /* Set the authentication key. */
1227 introduce1_set_auth_key(cell, data);
1228
1229 /* Set the encrypted section. This will set, encrypt and encode the
1230 * ENCRYPTED section in the cell. After this, we'll be ready to encode. */
1231 if (introduce1_set_encrypted(cell, data) < 0)
1232 return -1;
1233
1234 /* Final encoding. */
1235 cell_len = trn_cell_introduce1_encode(cell_out,
1237
1238 trn_cell_introduce1_free(cell);
1239 return cell_len;
1240}
1241
1242/** Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The
1243 * encoded cell is put in cell_out which must be of at least
1244 * RELAY_PAYLOAD_SIZE. On success, the encoded length is returned and the
1245 * caller should clear up the content of the cell.
1246 *
1247 * This function can't fail. */
1248ssize_t
1249hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie,
1250 uint8_t *cell_out)
1251{
1252 tor_assert(rendezvous_cookie);
1253 tor_assert(cell_out);
1254
1255 memcpy(cell_out, rendezvous_cookie, HS_REND_COOKIE_LEN);
1256 return HS_REND_COOKIE_LEN;
1257}
1258
1259/** Handle an INTRODUCE_ACK cell encoded in payload of length payload_len.
1260 * Return the status code on success else a negative value if the cell as not
1261 * decodable. */
1262int
1263hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len)
1264{
1265 int ret = -1;
1266 trn_cell_introduce_ack_t *cell = NULL;
1267
1268 tor_assert(payload);
1269
1270 if (trn_cell_introduce_ack_parse(&cell, payload, payload_len) < 0) {
1271 log_info(LD_REND, "Invalid INTRODUCE_ACK cell. Unable to parse it.");
1272 goto end;
1273 }
1274
1275 ret = trn_cell_introduce_ack_get_status(cell);
1276
1277 end:
1278 trn_cell_introduce_ack_free(cell);
1279 return ret;
1280}
1281
1282/** Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On
1283 * success, handshake_info contains the data in the HANDSHAKE_INFO field, and
1284 * 0 is returned. On error, a negative value is returned. */
1285int
1286hs_cell_parse_rendezvous2(const uint8_t *payload, size_t payload_len,
1287 uint8_t *handshake_info, size_t handshake_info_len)
1288{
1289 int ret = -1;
1290 trn_cell_rendezvous2_t *cell = NULL;
1291
1292 tor_assert(payload);
1293 tor_assert(handshake_info);
1294
1295 if (trn_cell_rendezvous2_parse(&cell, payload, payload_len) < 0) {
1296 log_info(LD_REND, "Invalid RENDEZVOUS2 cell. Unable to parse it.");
1297 goto end;
1298 }
1299
1300 /* Static size, we should never have an issue with this else we messed up
1301 * our code flow. */
1302 tor_assert(trn_cell_rendezvous2_getlen_handshake_info(cell) ==
1303 handshake_info_len);
1304 memcpy(handshake_info,
1305 trn_cell_rendezvous2_getconstarray_handshake_info(cell),
1306 handshake_info_len);
1307 ret = 0;
1308
1309 end:
1310 trn_cell_rendezvous2_free(cell);
1311 return ret;
1312}
1313
1314/** Clear the given INTRODUCE1 data structure data. */
1315void
1317{
1318 if (data == NULL) {
1319 return;
1320 }
1321 /* Object in this list have been moved to the cell object when building it
1322 * so they've been freed earlier. We do that in order to avoid duplicating
1323 * them leading to more memory and CPU time being used for nothing. */
1324 smartlist_free(data->link_specifiers);
1325 /* The data object has no ownership of any members. */
1326 memwipe(data, 0, sizeof(hs_cell_introduce1_data_t));
1327}
Header file for config.c.
bool congestion_control_enabled(void)
Public APIs for congestion control.
crypto_cipher_t * crypto_cipher_new_with_bits(const char *key, int bits)
int crypto_cipher_decrypt(crypto_cipher_t *env, char *to, const char *from, size_t fromlen)
int crypto_cipher_encrypt(crypto_cipher_t *env, char *to, const char *from, size_t fromlen)
int curve25519_public_key_is_ok(const curve25519_public_key_t *key)
Header for crypto_curve25519.c.
void crypto_mac_sha3_256(uint8_t *mac_out, size_t len_out, const uint8_t *key, size_t key_len, const uint8_t *msg, size_t msg_len)
int ed25519_sign_prefixed(ed25519_signature_t *signature_out, const uint8_t *msg, size_t msg_len, const char *prefix_str, const ed25519_keypair_t *keypair)
void memwipe(void *mem, uint8_t byte, size_t sz)
Definition crypto_util.c:55
Common functions for cryptographic routines.
void memcpy_if_true_timei(bool s, void *dest, const void *src, size_t n)
Definition di_ops.c:296
int tor_memeq(const void *a, const void *b, size_t sz)
Definition di_ops.c:107
int safe_mem_is_zero(const void *mem, size_t sz)
Definition di_ops.c:224
#define DIGEST_LEN
#define DIGEST256_LEN
static int handle_introduce2_encrypted_cell_pow_extension(const hs_service_t *service, const hs_service_intro_point_t *ip, const trn_extension_field_t *field, hs_cell_introduce2_data_t *data)
Definition hs_cell.c:810
static void build_introduce_cc_extension(trn_extension_t *extensions)
Definition hs_cell.c:460
ssize_t hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie, uint8_t *cell_out)
Definition hs_cell.c:1249
STATIC trn_extension_t * build_establish_intro_extensions(const hs_service_config_t *service_config, const hs_service_intro_point_t *ip)
Definition hs_cell.c:640
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:982
static void build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext, uint8_t param_type, uint64_t param_value)
Definition hs_cell.c:546
static int build_establish_intro_dos_extension(const hs_service_config_t *service_config, trn_extension_t *extensions)
Definition hs_cell.c:567
static void compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len, const uint8_t *encrypted, size_t encrypted_len, const uint8_t *mac_key, size_t mac_key_len, uint8_t *mac_out, size_t mac_out_len)
Definition hs_cell.c:38
static hs_ntor_intro_cell_keys_t * get_introduce2_key_material(const ed25519_public_key_t *auth_key, const curve25519_keypair_t *enc_key, size_t n_subcredentials, const hs_subcredential_t *subcredentials, const uint8_t *encrypted_section, curve25519_public_key_t *client_pk)
Definition hs_cell.c:80
static uint8_t * decrypt_introduce2(const uint8_t *enc_key, const uint8_t *encrypted_section, size_t encrypted_section_len)
Definition hs_cell.c:117
static void introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell, const smartlist_t *lspecs)
Definition hs_cell.c:253
static int parse_introduce2_cell(const hs_service_t *service, const origin_circuit_t *circ, const uint8_t *payload, size_t payload_len, trn_cell_introduce1_t **cell_ptr_out)
Definition hs_cell.c:205
ssize_t hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
Definition hs_cell.c:788
static int parse_introduce_cell_extension(const hs_service_t *service, const hs_service_intro_point_t *ip, hs_cell_introduce2_data_t *data, const trn_extension_field_t *field)
Definition hs_cell.c:943
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:673
int hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len)
Definition hs_cell.c:1263
static trn_cell_introduce_encrypted_t * parse_introduce2_encrypted(const uint8_t *decrypted_data, size_t decrypted_len, const origin_circuit_t *circ, const hs_service_t *service)
Definition hs_cell.c:152
static hs_ntor_intro_cell_keys_t * get_introduce2_keys_and_verify_mac(hs_cell_introduce2_data_t *data, const uint8_t *encrypted_section, size_t encrypted_section_len)
Definition hs_cell.c:877
void hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data)
Definition hs_cell.c:1316
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:1171
static int introduce1_set_encrypted(trn_cell_introduce1_t *cell, const hs_cell_introduce1_data_t *data)
Definition hs_cell.c:480
ssize_t hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data, uint8_t *cell_out)
Definition hs_cell.c:1207
int hs_cell_parse_rendezvous2(const uint8_t *payload, size_t payload_len, uint8_t *handshake_info, size_t handshake_info_len)
Definition hs_cell.c:1286
static void introduce1_set_auth_key(trn_cell_introduce1_t *cell, const hs_cell_introduce1_data_t *data)
Definition hs_cell.c:529
static int build_introduce_pow_extension(const hs_pow_solution_t *pow_solution, trn_extension_t *extensions)
Definition hs_cell.c:386
static void introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell, trn_cell_introduce_encrypted_t *enc_cell)
Definition hs_cell.c:273
static int introduce1_encrypt_and_encode(trn_cell_introduce1_t *cell, const trn_cell_introduce_encrypted_t *enc_cell, const hs_cell_introduce1_data_t *data)
Definition hs_cell.c:298
static void introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell, const uint8_t *onion_pk)
Definition hs_cell.c:236
Header file containing cell data for the whole HS subsystem.
#define HS_CELL_INTRODUCE1_MIN_SIZE
Definition hs_cell.h:18
link_specifier_t * link_specifier_dup(const link_specifier_t *src)
Definition hs_common.c:1758
#define ESTABLISH_INTRO_SIG_PREFIX
Definition hs_common.h:50
#define HS_REND_COOKIE_LEN
Definition hs_ident.h:30
int hs_ntor_service_get_introduce1_keys_multi(const struct ed25519_public_key_t *intro_auth_pubkey, const struct curve25519_keypair_t *intro_enc_keypair, const struct curve25519_public_key_t *client_ephemeral_enc_pubkey, size_t n_subcredentials, const hs_subcredential_t *subcredentials, hs_ntor_intro_cell_keys_t *hs_ntor_intro_cell_keys_out)
Definition hs_ntor.c:473
Header for hs_ntor.c.
Header file for the specific code for onion balance.
int hs_pow_verify(const ed25519_public_key_t *service_blinded_id, const hs_pow_service_state_t *pow_state, const hs_pow_solution_t *pow_solution)
Definition hs_pow.c:312
#define HS_POW_EQX_SOL_LEN
Definition hs_pow.h:31
#define HS_POW_NONCE_LEN
Definition hs_pow.h:29
#define HS_POW_SEED_HEAD_LEN
Definition hs_pow.h:43
#define log_fn(severity, domain, args,...)
Definition log.h:283
#define LD_REND
Definition log.h:84
#define LD_PROTOCOL
Definition log.h:72
#define LD_BUG
Definition log.h:86
#define tor_free(p)
Definition malloc.h:56
Master header file for Tor-specific functionality.
#define REND_COOKIE_LEN
Definition or.h:405
#define TO_CIRCUIT(x)
Definition or.h:951
#define RELAY_PAYLOAD_SIZE_MAX
Definition or.h:576
Origin circuit structure.
size_t replay_cache_count(const replaycache_t *r)
int replaycache_test_and_elapsed(const replaycache_t *r, const void *data, size_t len, time_t *elapsed)
int replaycache_add_and_test(replaycache_t *r, const void *data, size_t len)
Header file for replaycache.c.
void smartlist_add(smartlist_t *sl, void *element)
#define SMARTLIST_FOREACH(sl, type, var, cmd)
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
protover_summary_flags_t pv
Definition hs_cell.h:102
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
unsigned int has_dos_defense_enabled
Definition hs_service.h:265
unsigned int support_intro2_dos_defense
Definition hs_service.h:98
ed25519_keypair_t auth_key_kp
Definition hs_service.h:60
ed25519_public_key_t blinded_id
Definition hs_service.h:67
hs_pow_service_state_t * pow_state
Definition hs_service.h:311
hs_service_state_t state
Definition hs_service.h:325
char onion_address[HS_SERVICE_ADDR_LEN_BASE32+1]
Definition hs_service.h:318
unsigned int supports_congestion_control
Definition or.h:839
unsigned int protocols_known
Definition or.h:786
#define STATIC
Definition testsupport.h:32
#define tor_assert(expr)
Definition util_bug.h:103
#define ED25519_SIG_LEN
#define ED25519_PUBKEY_LEN
#define CURVE25519_PUBKEY_LEN