Line data Source code
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"
11 : #include "lib/crypt_ops/crypto_util.h"
12 : #include "feature/hs_common/replaycache.h"
13 :
14 : #include "feature/hs/hs_cell.h"
15 : #include "feature/hs/hs_ob.h"
16 : #include "core/crypto/hs_ntor.h"
17 :
18 : #include "core/or/origin_circuit_st.h"
19 :
20 : /* Trunnel. */
21 : #include "trunnel/ed25519_cert.h"
22 : #include "trunnel/hs/cell_common.h"
23 : #include "trunnel/hs/cell_establish_intro.h"
24 : #include "trunnel/hs/cell_introduce1.h"
25 : #include "trunnel/hs/cell_rendezvous.h"
26 :
27 : /** Compute the MAC of an INTRODUCE cell in mac_out. The encoded_cell param is
28 : * the cell content up to the ENCRYPTED section of length encoded_cell_len.
29 : * The encrypted param is the start of the ENCRYPTED section of length
30 : * encrypted_len. The mac_key is the key needed for the computation of the MAC
31 : * derived from the ntor handshake of length mac_key_len.
32 : *
33 : * The length mac_out_len must be at least DIGEST256_LEN. */
34 : static void
35 30 : compute_introduce_mac(const uint8_t *encoded_cell, size_t encoded_cell_len,
36 : const uint8_t *encrypted, size_t encrypted_len,
37 : const uint8_t *mac_key, size_t mac_key_len,
38 : uint8_t *mac_out, size_t mac_out_len)
39 : {
40 30 : size_t offset = 0;
41 30 : size_t mac_msg_len;
42 30 : uint8_t mac_msg[RELAY_PAYLOAD_SIZE] = {0};
43 :
44 30 : tor_assert(encoded_cell);
45 30 : tor_assert(encrypted);
46 30 : tor_assert(mac_key);
47 30 : tor_assert(mac_out);
48 30 : tor_assert(mac_out_len >= DIGEST256_LEN);
49 :
50 : /* Compute the size of the message which is basically the entire cell until
51 : * the MAC field of course. */
52 30 : mac_msg_len = encoded_cell_len + (encrypted_len - DIGEST256_LEN);
53 30 : tor_assert(mac_msg_len <= sizeof(mac_msg));
54 :
55 : /* First, put the encoded cell in the msg. */
56 30 : memcpy(mac_msg, encoded_cell, encoded_cell_len);
57 30 : offset += encoded_cell_len;
58 : /* Second, put the CLIENT_PK + ENCRYPTED_DATA but omit the MAC field (which
59 : * is junk at this point). */
60 30 : memcpy(mac_msg + offset, encrypted, (encrypted_len - DIGEST256_LEN));
61 30 : offset += (encrypted_len - DIGEST256_LEN);
62 30 : tor_assert(offset == mac_msg_len);
63 :
64 30 : crypto_mac_sha3_256(mac_out, mac_out_len,
65 : mac_key, mac_key_len,
66 : mac_msg, mac_msg_len);
67 30 : memwipe(mac_msg, 0, sizeof(mac_msg));
68 30 : }
69 :
70 : /**
71 : * From a set of keys, a list of subcredentials, and the ENCRYPTED section of
72 : * an INTRODUCE2 cell, return an array of newly allocated intro cell keys
73 : * structures. Finally, the client public key is copied in client_pk. On
74 : * error, return NULL.
75 : **/
76 : static hs_ntor_intro_cell_keys_t *
77 7 : get_introduce2_key_material(const ed25519_public_key_t *auth_key,
78 : const curve25519_keypair_t *enc_key,
79 : size_t n_subcredentials,
80 : const hs_subcredential_t *subcredentials,
81 : const uint8_t *encrypted_section,
82 : curve25519_public_key_t *client_pk)
83 : {
84 7 : hs_ntor_intro_cell_keys_t *keys;
85 :
86 7 : tor_assert(auth_key);
87 7 : tor_assert(enc_key);
88 7 : tor_assert(n_subcredentials > 0);
89 7 : tor_assert(subcredentials);
90 7 : tor_assert(encrypted_section);
91 7 : tor_assert(client_pk);
92 :
93 7 : keys = tor_calloc(n_subcredentials, sizeof(hs_ntor_intro_cell_keys_t));
94 :
95 : /* First bytes of the ENCRYPTED section are the client public key. */
96 7 : memcpy(client_pk->public_key, encrypted_section, CURVE25519_PUBKEY_LEN);
97 :
98 7 : if (hs_ntor_service_get_introduce1_keys_multi(auth_key, enc_key, client_pk,
99 : n_subcredentials,
100 : subcredentials, keys) < 0) {
101 : /* Don't rely on the caller to wipe this on error. */
102 1 : memwipe(client_pk, 0, sizeof(curve25519_public_key_t));
103 1 : tor_free(keys);
104 1 : keys = NULL;
105 : }
106 7 : return keys;
107 : }
108 :
109 : /** Using the given encryption key, decrypt the encrypted_section of length
110 : * encrypted_section_len of an INTRODUCE2 cell and return a newly allocated
111 : * buffer containing the decrypted data. On decryption failure, NULL is
112 : * returned. */
113 : static uint8_t *
114 5 : decrypt_introduce2(const uint8_t *enc_key, const uint8_t *encrypted_section,
115 : size_t encrypted_section_len)
116 : {
117 5 : uint8_t *decrypted = NULL;
118 5 : crypto_cipher_t *cipher = NULL;
119 :
120 5 : tor_assert(enc_key);
121 5 : tor_assert(encrypted_section);
122 :
123 : /* Decrypt ENCRYPTED section. */
124 5 : cipher = crypto_cipher_new_with_bits((char *) enc_key,
125 : CURVE25519_PUBKEY_LEN * 8);
126 5 : tor_assert(cipher);
127 :
128 : /* This is symmetric encryption so can't be bigger than the encrypted
129 : * section length. */
130 5 : decrypted = tor_malloc_zero(encrypted_section_len);
131 5 : if (crypto_cipher_decrypt(cipher, (char *) decrypted,
132 : (const char *) encrypted_section,
133 : encrypted_section_len) < 0) {
134 0 : tor_free(decrypted);
135 0 : decrypted = NULL;
136 0 : goto done;
137 : }
138 :
139 5 : done:
140 5 : crypto_cipher_free(cipher);
141 5 : return decrypted;
142 : }
143 :
144 : /** Given a pointer to the decrypted data of the ENCRYPTED section of an
145 : * INTRODUCE2 cell of length decrypted_len, parse and validate the cell
146 : * content. Return a newly allocated cell structure or NULL on error. The
147 : * circuit and service object are only used for logging purposes. */
148 : static trn_cell_introduce_encrypted_t *
149 5 : parse_introduce2_encrypted(const uint8_t *decrypted_data,
150 : size_t decrypted_len, const origin_circuit_t *circ,
151 : const hs_service_t *service)
152 : {
153 5 : trn_cell_introduce_encrypted_t *enc_cell = NULL;
154 :
155 5 : tor_assert(decrypted_data);
156 5 : tor_assert(circ);
157 5 : tor_assert(service);
158 :
159 5 : if (trn_cell_introduce_encrypted_parse(&enc_cell, decrypted_data,
160 : decrypted_len) < 0) {
161 0 : log_info(LD_REND, "Unable to parse the decrypted ENCRYPTED section of "
162 : "the INTRODUCE2 cell on circuit %u for service %s",
163 : TO_CIRCUIT(circ)->n_circ_id,
164 : safe_str_client(service->onion_address));
165 0 : goto err;
166 : }
167 :
168 5 : if (trn_cell_introduce_encrypted_get_onion_key_type(enc_cell) !=
169 : TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR) {
170 0 : log_info(LD_REND, "INTRODUCE2 onion key type is invalid. Got %u but "
171 : "expected %u on circuit %u for service %s",
172 : trn_cell_introduce_encrypted_get_onion_key_type(enc_cell),
173 : TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR,
174 : TO_CIRCUIT(circ)->n_circ_id,
175 : safe_str_client(service->onion_address));
176 0 : goto err;
177 : }
178 :
179 5 : if (trn_cell_introduce_encrypted_getlen_onion_key(enc_cell) !=
180 : CURVE25519_PUBKEY_LEN) {
181 0 : log_info(LD_REND, "INTRODUCE2 onion key length is invalid. Got %u but "
182 : "expected %d on circuit %u for service %s",
183 : (unsigned)trn_cell_introduce_encrypted_getlen_onion_key(enc_cell),
184 : CURVE25519_PUBKEY_LEN, TO_CIRCUIT(circ)->n_circ_id,
185 : safe_str_client(service->onion_address));
186 0 : goto err;
187 : }
188 : /* XXX: Validate NSPEC field as well. */
189 :
190 5 : return enc_cell;
191 0 : err:
192 0 : trn_cell_introduce_encrypted_free(enc_cell);
193 0 : return NULL;
194 : }
195 :
196 : /** Parse an INTRODUCE2 cell from payload of size payload_len for the given
197 : * service and circuit which are used only for logging purposes. The resulting
198 : * parsed cell is put in cell_ptr_out.
199 : *
200 : * Return 0 on success else a negative value and cell_ptr_out is untouched. */
201 : static int
202 8 : parse_introduce2_cell(const hs_service_t *service,
203 : const origin_circuit_t *circ, const uint8_t *payload,
204 : size_t payload_len,
205 : trn_cell_introduce1_t **cell_ptr_out)
206 : {
207 8 : trn_cell_introduce1_t *cell = NULL;
208 :
209 8 : tor_assert(service);
210 8 : tor_assert(circ);
211 8 : tor_assert(payload);
212 8 : tor_assert(cell_ptr_out);
213 :
214 : /* Parse the cell so we can start cell validation. */
215 8 : if (trn_cell_introduce1_parse(&cell, payload, payload_len) < 0) {
216 0 : log_info(LD_PROTOCOL, "Unable to parse INTRODUCE2 cell on circuit %u "
217 : "for service %s",
218 : TO_CIRCUIT(circ)->n_circ_id,
219 : safe_str_client(service->onion_address));
220 0 : goto err;
221 : }
222 :
223 : /* Success. */
224 8 : *cell_ptr_out = cell;
225 8 : return 0;
226 0 : err:
227 0 : return -1;
228 : }
229 :
230 : /** Set the onion public key onion_pk in cell, the encrypted section of an
231 : * INTRODUCE1 cell. */
232 : static void
233 4 : introduce1_set_encrypted_onion_key(trn_cell_introduce_encrypted_t *cell,
234 : const uint8_t *onion_pk)
235 : {
236 4 : tor_assert(cell);
237 4 : tor_assert(onion_pk);
238 : /* There is only one possible key type for a non legacy cell. */
239 4 : trn_cell_introduce_encrypted_set_onion_key_type(cell,
240 : TRUNNEL_HS_INTRO_ONION_KEY_TYPE_NTOR);
241 4 : trn_cell_introduce_encrypted_set_onion_key_len(cell, CURVE25519_PUBKEY_LEN);
242 4 : trn_cell_introduce_encrypted_setlen_onion_key(cell, CURVE25519_PUBKEY_LEN);
243 4 : memcpy(trn_cell_introduce_encrypted_getarray_onion_key(cell), onion_pk,
244 : trn_cell_introduce_encrypted_getlen_onion_key(cell));
245 4 : }
246 :
247 : /** Set the link specifiers in lspecs in cell, the encrypted section of an
248 : * INTRODUCE1 cell. */
249 : static void
250 4 : introduce1_set_encrypted_link_spec(trn_cell_introduce_encrypted_t *cell,
251 : const smartlist_t *lspecs)
252 : {
253 4 : tor_assert(cell);
254 4 : tor_assert(lspecs);
255 4 : tor_assert(smartlist_len(lspecs) > 0);
256 4 : tor_assert(smartlist_len(lspecs) <= UINT8_MAX);
257 :
258 4 : uint8_t lspecs_num = (uint8_t) smartlist_len(lspecs);
259 4 : trn_cell_introduce_encrypted_set_nspec(cell, lspecs_num);
260 : /* We aren't duplicating the link specifiers object here which means that
261 : * the ownership goes to the trn_cell_introduce_encrypted_t cell and those
262 : * object will be freed when the cell is. */
263 8 : SMARTLIST_FOREACH(lspecs, link_specifier_t *, ls,
264 : trn_cell_introduce_encrypted_add_nspecs(cell, ls));
265 4 : }
266 :
267 : /** Set padding in the enc_cell only if needed that is the total length of both
268 : * sections are below the minimum required for an INTRODUCE1 cell. */
269 : static void
270 4 : introduce1_set_encrypted_padding(const trn_cell_introduce1_t *cell,
271 : trn_cell_introduce_encrypted_t *enc_cell)
272 : {
273 4 : tor_assert(cell);
274 4 : tor_assert(enc_cell);
275 : /* This is the length we expect to have once encoded of the whole cell. */
276 4 : ssize_t full_len = trn_cell_introduce1_encoded_len(cell) +
277 4 : trn_cell_introduce_encrypted_encoded_len(enc_cell);
278 4 : tor_assert(full_len > 0);
279 4 : if (full_len < HS_CELL_INTRODUCE1_MIN_SIZE) {
280 4 : size_t padding = HS_CELL_INTRODUCE1_MIN_SIZE - full_len;
281 4 : trn_cell_introduce_encrypted_setlen_pad(enc_cell, padding);
282 4 : memset(trn_cell_introduce_encrypted_getarray_pad(enc_cell), 0,
283 : trn_cell_introduce_encrypted_getlen_pad(enc_cell));
284 : }
285 4 : }
286 :
287 : /** Encrypt the ENCRYPTED payload and encode it in the cell using the enc_cell
288 : * and the INTRODUCE1 data.
289 : *
290 : * This can't fail but it is very important that the caller sets every field
291 : * in data so the computation of the INTRODUCE1 keys doesn't fail. */
292 : static void
293 4 : introduce1_encrypt_and_encode(trn_cell_introduce1_t *cell,
294 : const trn_cell_introduce_encrypted_t *enc_cell,
295 : const hs_cell_introduce1_data_t *data)
296 : {
297 4 : size_t offset = 0;
298 4 : ssize_t encrypted_len;
299 4 : ssize_t encoded_cell_len, encoded_enc_cell_len;
300 4 : uint8_t encoded_cell[RELAY_PAYLOAD_SIZE] = {0};
301 4 : uint8_t encoded_enc_cell[RELAY_PAYLOAD_SIZE] = {0};
302 4 : uint8_t *encrypted = NULL;
303 4 : uint8_t mac[DIGEST256_LEN];
304 4 : crypto_cipher_t *cipher = NULL;
305 4 : hs_ntor_intro_cell_keys_t keys;
306 :
307 4 : tor_assert(cell);
308 4 : tor_assert(enc_cell);
309 4 : tor_assert(data);
310 :
311 : /* Encode the cells up to now of what we have to we can perform the MAC
312 : * computation on it. */
313 4 : encoded_cell_len = trn_cell_introduce1_encode(encoded_cell,
314 : sizeof(encoded_cell), cell);
315 : /* We have a much more serious issue if this isn't true. */
316 4 : tor_assert(encoded_cell_len > 0);
317 :
318 4 : encoded_enc_cell_len =
319 4 : trn_cell_introduce_encrypted_encode(encoded_enc_cell,
320 : sizeof(encoded_enc_cell), enc_cell);
321 : /* We have a much more serious issue if this isn't true. */
322 4 : tor_assert(encoded_enc_cell_len > 0);
323 :
324 : /* Get the key material for the encryption. */
325 4 : if (hs_ntor_client_get_introduce1_keys(data->auth_pk, data->enc_pk,
326 4 : data->client_kp,
327 4 : data->subcredential, &keys) < 0) {
328 0 : tor_assert_unreached();
329 : }
330 :
331 : /* Prepare cipher with the encryption key just computed. */
332 4 : cipher = crypto_cipher_new_with_bits((const char *) keys.enc_key,
333 : sizeof(keys.enc_key) * 8);
334 4 : tor_assert(cipher);
335 :
336 : /* Compute the length of the ENCRYPTED section which is the CLIENT_PK,
337 : * ENCRYPTED_DATA and MAC length. */
338 4 : encrypted_len = sizeof(data->client_kp->pubkey) + encoded_enc_cell_len +
339 : sizeof(mac);
340 4 : tor_assert(encrypted_len < RELAY_PAYLOAD_SIZE);
341 4 : encrypted = tor_malloc_zero(encrypted_len);
342 :
343 : /* Put the CLIENT_PK first. */
344 4 : memcpy(encrypted, data->client_kp->pubkey.public_key,
345 : sizeof(data->client_kp->pubkey.public_key));
346 4 : offset += sizeof(data->client_kp->pubkey.public_key);
347 : /* Then encrypt and set the ENCRYPTED_DATA. This can't fail. */
348 4 : crypto_cipher_encrypt(cipher, (char *) encrypted + offset,
349 : (const char *) encoded_enc_cell, encoded_enc_cell_len);
350 4 : crypto_cipher_free(cipher);
351 4 : offset += encoded_enc_cell_len;
352 : /* Compute MAC from the above and put it in the buffer. This function will
353 : * make the adjustment to the encrypted_len to omit the MAC length. */
354 4 : compute_introduce_mac(encoded_cell, encoded_cell_len,
355 : encrypted, encrypted_len,
356 : keys.mac_key, sizeof(keys.mac_key),
357 : mac, sizeof(mac));
358 4 : memcpy(encrypted + offset, mac, sizeof(mac));
359 4 : offset += sizeof(mac);
360 4 : tor_assert(offset == (size_t) encrypted_len);
361 :
362 : /* Set the ENCRYPTED section in the cell. */
363 4 : trn_cell_introduce1_setlen_encrypted(cell, encrypted_len);
364 4 : memcpy(trn_cell_introduce1_getarray_encrypted(cell),
365 : encrypted, encrypted_len);
366 :
367 : /* Cleanup. */
368 4 : memwipe(&keys, 0, sizeof(keys));
369 4 : memwipe(mac, 0, sizeof(mac));
370 4 : memwipe(encrypted, 0, sizeof(encrypted_len));
371 4 : memwipe(encoded_enc_cell, 0, sizeof(encoded_enc_cell));
372 4 : tor_free(encrypted);
373 4 : }
374 :
375 : /** Using the INTRODUCE1 data, setup the ENCRYPTED section in cell. This means
376 : * set it, encrypt it and encode it. */
377 : static void
378 4 : introduce1_set_encrypted(trn_cell_introduce1_t *cell,
379 : const hs_cell_introduce1_data_t *data)
380 : {
381 4 : trn_cell_introduce_encrypted_t *enc_cell;
382 4 : trn_cell_extension_t *ext;
383 :
384 4 : tor_assert(cell);
385 4 : tor_assert(data);
386 :
387 4 : enc_cell = trn_cell_introduce_encrypted_new();
388 4 : tor_assert(enc_cell);
389 :
390 : /* Set extension data. None are used. */
391 4 : ext = trn_cell_extension_new();
392 4 : tor_assert(ext);
393 4 : trn_cell_extension_set_num(ext, 0);
394 4 : trn_cell_introduce_encrypted_set_extensions(enc_cell, ext);
395 :
396 : /* Set the rendezvous cookie. */
397 4 : memcpy(trn_cell_introduce_encrypted_getarray_rend_cookie(enc_cell),
398 4 : data->rendezvous_cookie, REND_COOKIE_LEN);
399 :
400 : /* Set the onion public key. */
401 4 : introduce1_set_encrypted_onion_key(enc_cell, data->onion_pk->public_key);
402 :
403 : /* Set the link specifiers. */
404 4 : introduce1_set_encrypted_link_spec(enc_cell, data->link_specifiers);
405 :
406 : /* Set padding. */
407 4 : introduce1_set_encrypted_padding(cell, enc_cell);
408 :
409 : /* Encrypt and encode it in the cell. */
410 4 : introduce1_encrypt_and_encode(cell, enc_cell, data);
411 :
412 : /* Cleanup. */
413 4 : trn_cell_introduce_encrypted_free(enc_cell);
414 4 : }
415 :
416 : /** Set the authentication key in the INTRODUCE1 cell from the given data. */
417 : static void
418 4 : introduce1_set_auth_key(trn_cell_introduce1_t *cell,
419 : const hs_cell_introduce1_data_t *data)
420 : {
421 4 : tor_assert(cell);
422 4 : tor_assert(data);
423 : /* There is only one possible type for a non legacy cell. */
424 4 : trn_cell_introduce1_set_auth_key_type(cell,
425 : TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519);
426 4 : trn_cell_introduce1_set_auth_key_len(cell, ED25519_PUBKEY_LEN);
427 4 : trn_cell_introduce1_setlen_auth_key(cell, ED25519_PUBKEY_LEN);
428 4 : memcpy(trn_cell_introduce1_getarray_auth_key(cell),
429 4 : data->auth_pk->pubkey, trn_cell_introduce1_getlen_auth_key(cell));
430 4 : }
431 :
432 : /** Build and add to the given DoS cell extension the given parameter type and
433 : * value. */
434 : static void
435 14 : build_establish_intro_dos_param(trn_cell_extension_dos_t *dos_ext,
436 : uint8_t param_type, uint64_t param_value)
437 : {
438 14 : trn_cell_extension_dos_param_t *dos_param =
439 14 : trn_cell_extension_dos_param_new();
440 :
441 : /* Extra safety. We should never send an unknown parameter type. */
442 14 : tor_assert(param_type == TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC ||
443 : param_type == TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC);
444 :
445 14 : trn_cell_extension_dos_param_set_type(dos_param, param_type);
446 14 : trn_cell_extension_dos_param_set_value(dos_param, param_value);
447 14 : trn_cell_extension_dos_add_params(dos_ext, dos_param);
448 :
449 : /* Not freeing the trunnel object because it is now owned by dos_ext. */
450 14 : }
451 :
452 : /** Build the DoS defense cell extension and put it in the given extensions
453 : * object. Return 0 on success, -1 on failure. (Right now, failure is only
454 : * possible if there is a bug.) */
455 : static int
456 7 : build_establish_intro_dos_extension(const hs_service_config_t *service_config,
457 : trn_cell_extension_t *extensions)
458 : {
459 7 : ssize_t ret;
460 7 : size_t dos_ext_encoded_len;
461 7 : uint8_t *field_array;
462 7 : trn_cell_extension_field_t *field = NULL;
463 7 : trn_cell_extension_dos_t *dos_ext = NULL;
464 :
465 7 : tor_assert(service_config);
466 7 : tor_assert(extensions);
467 :
468 : /* We are creating a cell extension field of the type DoS. */
469 7 : field = trn_cell_extension_field_new();
470 7 : trn_cell_extension_field_set_field_type(field,
471 : TRUNNEL_CELL_EXTENSION_TYPE_DOS);
472 :
473 : /* Build DoS extension field. We will put in two parameters. */
474 7 : dos_ext = trn_cell_extension_dos_new();
475 7 : trn_cell_extension_dos_set_n_params(dos_ext, 2);
476 :
477 : /* Build DoS parameter INTRO2 rate per second. */
478 7 : build_establish_intro_dos_param(dos_ext,
479 : TRUNNEL_DOS_PARAM_TYPE_INTRO2_RATE_PER_SEC,
480 7 : service_config->intro_dos_rate_per_sec);
481 : /* Build DoS parameter INTRO2 burst per second. */
482 7 : build_establish_intro_dos_param(dos_ext,
483 : TRUNNEL_DOS_PARAM_TYPE_INTRO2_BURST_PER_SEC,
484 7 : service_config->intro_dos_burst_per_sec);
485 :
486 : /* Set the field with the encoded DoS extension. */
487 7 : ret = trn_cell_extension_dos_encoded_len(dos_ext);
488 7 : if (BUG(ret <= 0)) {
489 0 : goto err;
490 : }
491 7 : dos_ext_encoded_len = ret;
492 : /* Set length field and the field array size length. */
493 7 : trn_cell_extension_field_set_field_len(field, dos_ext_encoded_len);
494 7 : trn_cell_extension_field_setlen_field(field, dos_ext_encoded_len);
495 : /* Encode the DoS extension into the cell extension field. */
496 7 : field_array = trn_cell_extension_field_getarray_field(field);
497 7 : ret = trn_cell_extension_dos_encode(field_array,
498 : trn_cell_extension_field_getlen_field(field), dos_ext);
499 7 : if (BUG(ret <= 0)) {
500 0 : goto err;
501 : }
502 7 : tor_assert(ret == (ssize_t) dos_ext_encoded_len);
503 :
504 : /* Finally, encode field into the cell extension. */
505 7 : trn_cell_extension_add_fields(extensions, field);
506 :
507 : /* We've just add an extension field to the cell extensions so increment the
508 : * total number. */
509 14 : trn_cell_extension_set_num(extensions,
510 7 : trn_cell_extension_get_num(extensions) + 1);
511 :
512 : /* Cleanup. DoS extension has been encoded at this point. */
513 7 : trn_cell_extension_dos_free(dos_ext);
514 :
515 7 : return 0;
516 :
517 0 : err:
518 0 : trn_cell_extension_field_free(field);
519 0 : trn_cell_extension_dos_free(dos_ext);
520 0 : return -1;
521 : }
522 :
523 : /* ========== */
524 : /* Public API */
525 : /* ========== */
526 :
527 : /** Allocate and build all the ESTABLISH_INTRO cell extension. The given
528 : * extensions pointer is always set to a valid cell extension object. */
529 : STATIC trn_cell_extension_t *
530 18 : build_establish_intro_extensions(const hs_service_config_t *service_config,
531 : const hs_service_intro_point_t *ip)
532 : {
533 18 : int ret;
534 18 : trn_cell_extension_t *extensions;
535 :
536 18 : tor_assert(service_config);
537 18 : tor_assert(ip);
538 :
539 18 : extensions = trn_cell_extension_new();
540 18 : trn_cell_extension_set_num(extensions, 0);
541 :
542 : /* If the defense has been enabled service side (by the operator with a
543 : * torrc option) and the intro point does support it. */
544 18 : if (service_config->has_dos_defense_enabled &&
545 : ip->support_intro2_dos_defense) {
546 : /* This function takes care to increment the number of extensions. */
547 7 : ret = build_establish_intro_dos_extension(service_config, extensions);
548 7 : if (ret < 0) {
549 : /* Return no extensions on error. */
550 : goto end;
551 : }
552 : }
553 :
554 18 : end:
555 18 : return extensions;
556 : }
557 :
558 : /** Build an ESTABLISH_INTRO cell with the given circuit nonce and intro point
559 : * object. The encoded cell is put in cell_out that MUST at least be of the
560 : * size of RELAY_PAYLOAD_SIZE. Return the encoded cell length on success else
561 : * a negative value and cell_out is untouched. */
562 : ssize_t
563 15 : hs_cell_build_establish_intro(const char *circ_nonce,
564 : const hs_service_config_t *service_config,
565 : const hs_service_intro_point_t *ip,
566 : uint8_t *cell_out)
567 : {
568 15 : ssize_t cell_len = -1;
569 15 : uint16_t sig_len = ED25519_SIG_LEN;
570 15 : trn_cell_establish_intro_t *cell = NULL;
571 15 : trn_cell_extension_t *extensions;
572 :
573 15 : tor_assert(circ_nonce);
574 15 : tor_assert(service_config);
575 15 : tor_assert(ip);
576 :
577 : /* Build the extensions, if any. */
578 15 : extensions = build_establish_intro_extensions(service_config, ip);
579 :
580 : /* Set extension data. None used here. */
581 15 : cell = trn_cell_establish_intro_new();
582 15 : trn_cell_establish_intro_set_extensions(cell, extensions);
583 : /* Set signature size. Array is then allocated in the cell. We need to do
584 : * this early so we can use trunnel API to get the signature length. */
585 15 : trn_cell_establish_intro_set_sig_len(cell, sig_len);
586 15 : trn_cell_establish_intro_setlen_sig(cell, sig_len);
587 :
588 : /* Set AUTH_KEY_TYPE: 2 means ed25519 */
589 15 : trn_cell_establish_intro_set_auth_key_type(cell,
590 : TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519);
591 :
592 : /* Set AUTH_KEY and AUTH_KEY_LEN field. Must also set byte-length of
593 : * AUTH_KEY to match */
594 : {
595 15 : uint16_t auth_key_len = ED25519_PUBKEY_LEN;
596 15 : trn_cell_establish_intro_set_auth_key_len(cell, auth_key_len);
597 15 : trn_cell_establish_intro_setlen_auth_key(cell, auth_key_len);
598 : /* We do this call _after_ setting the length because it's reallocated at
599 : * that point only. */
600 15 : uint8_t *auth_key_ptr = trn_cell_establish_intro_getarray_auth_key(cell);
601 15 : memcpy(auth_key_ptr, ip->auth_key_kp.pubkey.pubkey, auth_key_len);
602 : }
603 :
604 : /* Calculate HANDSHAKE_AUTH field (MAC). */
605 : {
606 15 : ssize_t tmp_cell_enc_len = 0;
607 30 : ssize_t tmp_cell_mac_offset =
608 15 : sig_len + sizeof(cell->sig_len) +
609 15 : trn_cell_establish_intro_getlen_handshake_mac(cell);
610 15 : uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE] = {0};
611 15 : uint8_t mac[TRUNNEL_SHA3_256_LEN], *handshake_ptr;
612 :
613 : /* We first encode the current fields we have in the cell so we can
614 : * compute the MAC using the raw bytes. */
615 15 : tmp_cell_enc_len = trn_cell_establish_intro_encode(tmp_cell_enc,
616 : sizeof(tmp_cell_enc),
617 : cell);
618 15 : if (BUG(tmp_cell_enc_len < 0)) {
619 0 : goto done;
620 : }
621 : /* Sanity check. */
622 15 : tor_assert(tmp_cell_enc_len > tmp_cell_mac_offset);
623 :
624 : /* Circuit nonce is always DIGEST_LEN according to tor-spec.txt. */
625 15 : crypto_mac_sha3_256(mac, sizeof(mac),
626 : (uint8_t *) circ_nonce, DIGEST_LEN,
627 15 : tmp_cell_enc, tmp_cell_enc_len - tmp_cell_mac_offset);
628 15 : handshake_ptr = trn_cell_establish_intro_getarray_handshake_mac(cell);
629 15 : memcpy(handshake_ptr, mac, sizeof(mac));
630 :
631 15 : memwipe(mac, 0, sizeof(mac));
632 15 : memwipe(tmp_cell_enc, 0, sizeof(tmp_cell_enc));
633 : }
634 :
635 : /* Calculate the cell signature SIG. */
636 : {
637 15 : ssize_t tmp_cell_enc_len = 0;
638 15 : ssize_t tmp_cell_sig_offset = (sig_len + sizeof(cell->sig_len));
639 15 : uint8_t tmp_cell_enc[RELAY_PAYLOAD_SIZE] = {0}, *sig_ptr;
640 15 : ed25519_signature_t sig;
641 :
642 : /* We first encode the current fields we have in the cell so we can
643 : * compute the signature from the raw bytes of the cell. */
644 15 : tmp_cell_enc_len = trn_cell_establish_intro_encode(tmp_cell_enc,
645 : sizeof(tmp_cell_enc),
646 : cell);
647 15 : if (BUG(tmp_cell_enc_len < 0)) {
648 1 : goto done;
649 : }
650 :
651 15 : if (ed25519_sign_prefixed(&sig, tmp_cell_enc,
652 15 : tmp_cell_enc_len - tmp_cell_sig_offset,
653 : ESTABLISH_INTRO_SIG_PREFIX, &ip->auth_key_kp)) {
654 1 : log_warn(LD_BUG, "Unable to make signature for ESTABLISH_INTRO cell.");
655 1 : goto done;
656 : }
657 : /* Copy the signature into the cell. */
658 14 : sig_ptr = trn_cell_establish_intro_getarray_sig(cell);
659 14 : memcpy(sig_ptr, sig.sig, sig_len);
660 :
661 14 : memwipe(tmp_cell_enc, 0, sizeof(tmp_cell_enc));
662 : }
663 :
664 : /* Encode the cell. Can't be bigger than a standard cell. */
665 14 : cell_len = trn_cell_establish_intro_encode(cell_out, RELAY_PAYLOAD_SIZE,
666 : cell);
667 :
668 15 : done:
669 15 : trn_cell_establish_intro_free(cell);
670 15 : return cell_len;
671 : }
672 :
673 : /** Parse the INTRO_ESTABLISHED cell in the payload of size payload_len. If we
674 : * are successful at parsing it, return the length of the parsed cell else a
675 : * negative value on error. */
676 : ssize_t
677 1 : hs_cell_parse_intro_established(const uint8_t *payload, size_t payload_len)
678 : {
679 1 : ssize_t ret;
680 1 : trn_cell_intro_established_t *cell = NULL;
681 :
682 1 : tor_assert(payload);
683 :
684 : /* Try to parse the payload into a cell making sure we do actually have a
685 : * valid cell. */
686 1 : ret = trn_cell_intro_established_parse(&cell, payload, payload_len);
687 1 : if (ret >= 0) {
688 : /* On success, we do not keep the cell, we just notify the caller that it
689 : * was successfully parsed. */
690 1 : trn_cell_intro_established_free(cell);
691 : }
692 1 : return ret;
693 : }
694 :
695 : /** For the encrypted INTRO2 cell in <b>encrypted_section</b>, use the crypto
696 : * material in <b>data</b> to compute the right ntor keys. Also validate the
697 : * INTRO2 MAC to ensure that the keys are the right ones.
698 : *
699 : * Return NULL on failure to either produce the key material or on MAC
700 : * validation. Else return a newly allocated intro keys object. */
701 : static hs_ntor_intro_cell_keys_t *
702 7 : get_introduce2_keys_and_verify_mac(hs_cell_introduce2_data_t *data,
703 : const uint8_t *encrypted_section,
704 : size_t encrypted_section_len)
705 : {
706 7 : hs_ntor_intro_cell_keys_t *intro_keys = NULL;
707 7 : hs_ntor_intro_cell_keys_t *intro_keys_result = NULL;
708 :
709 : /* Build the key material out of the key material found in the cell. */
710 14 : intro_keys = get_introduce2_key_material(data->auth_pk, data->enc_kp,
711 : data->n_subcredentials,
712 7 : data->subcredentials,
713 : encrypted_section,
714 : &data->client_pk);
715 7 : if (intro_keys == NULL) {
716 1 : log_info(LD_REND, "Invalid INTRODUCE2 encrypted data. Unable to "
717 : "compute key material");
718 1 : return NULL;
719 : }
720 :
721 : /* Make sure we are not about to underflow. */
722 6 : if (BUG(encrypted_section_len < DIGEST256_LEN)) {
723 0 : return NULL;
724 : }
725 :
726 : /* Validate MAC from the cell and our computed key material. The MAC field
727 : * in the cell is at the end of the encrypted section. */
728 6 : intro_keys_result = tor_malloc_zero(sizeof(*intro_keys_result));
729 32 : for (unsigned i = 0; i < data->n_subcredentials; ++i) {
730 26 : uint8_t mac[DIGEST256_LEN];
731 :
732 : /* The MAC field is at the very end of the ENCRYPTED section. */
733 26 : size_t mac_offset = encrypted_section_len - sizeof(mac);
734 : /* Compute the MAC. Use the entire encoded payload with a length up to the
735 : * ENCRYPTED section. */
736 26 : compute_introduce_mac(data->payload,
737 26 : data->payload_len - encrypted_section_len,
738 : encrypted_section, encrypted_section_len,
739 26 : intro_keys[i].mac_key,
740 : sizeof(intro_keys[i].mac_key),
741 : mac, sizeof(mac));
742 : /* Time-invariant conditional copy: if the MAC is what we expected, then
743 : * set intro_keys_result to intro_keys[i]. Otherwise, don't: but don't
744 : * leak which one it was! */
745 26 : bool equal = tor_memeq(mac, encrypted_section + mac_offset, sizeof(mac));
746 26 : memcpy_if_true_timei(equal, intro_keys_result, &intro_keys[i],
747 : sizeof(*intro_keys_result));
748 : }
749 :
750 : /* We no longer need intro_keys. */
751 6 : memwipe(intro_keys, 0,
752 : sizeof(hs_ntor_intro_cell_keys_t) * data->n_subcredentials);
753 6 : tor_free(intro_keys);
754 :
755 6 : if (safe_mem_is_zero(intro_keys_result, sizeof(*intro_keys_result))) {
756 1 : log_info(LD_REND, "Invalid MAC validation for INTRODUCE2 cell");
757 1 : tor_free(intro_keys_result); /* sets intro_keys_result to NULL */
758 : }
759 :
760 : return intro_keys_result;
761 : }
762 :
763 : /** Parse the INTRODUCE2 cell using data which contains everything we need to
764 : * do so and contains the destination buffers of information we extract and
765 : * compute from the cell. Return 0 on success else a negative value. The
766 : * service and circ are only used for logging purposes. */
767 : ssize_t
768 8 : hs_cell_parse_introduce2(hs_cell_introduce2_data_t *data,
769 : const origin_circuit_t *circ,
770 : const hs_service_t *service)
771 : {
772 8 : int ret = -1;
773 8 : time_t elapsed;
774 8 : uint8_t *decrypted = NULL;
775 8 : size_t encrypted_section_len;
776 8 : const uint8_t *encrypted_section;
777 8 : trn_cell_introduce1_t *cell = NULL;
778 8 : trn_cell_introduce_encrypted_t *enc_cell = NULL;
779 8 : hs_ntor_intro_cell_keys_t *intro_keys = NULL;
780 :
781 8 : tor_assert(data);
782 8 : tor_assert(circ);
783 8 : tor_assert(service);
784 :
785 : /* Parse the cell into a decoded data structure pointed by cell_ptr. */
786 8 : if (parse_introduce2_cell(service, circ, data->payload, data->payload_len,
787 : &cell) < 0) {
788 0 : goto done;
789 : }
790 :
791 8 : log_info(LD_REND, "Received a decodable INTRODUCE2 cell on circuit %u "
792 : "for service %s. Decoding encrypted section...",
793 : TO_CIRCUIT(circ)->n_circ_id,
794 : safe_str_client(service->onion_address));
795 :
796 8 : encrypted_section = trn_cell_introduce1_getconstarray_encrypted(cell);
797 8 : encrypted_section_len = trn_cell_introduce1_getlen_encrypted(cell);
798 :
799 : /* Encrypted section must at least contain the CLIENT_PK and MAC which is
800 : * defined in section 3.3.2 of the specification. */
801 8 : if (encrypted_section_len < (CURVE25519_PUBKEY_LEN + DIGEST256_LEN)) {
802 0 : log_info(LD_REND, "Invalid INTRODUCE2 encrypted section length "
803 : "for service %s. Dropping cell.",
804 : safe_str_client(service->onion_address));
805 0 : goto done;
806 : }
807 :
808 : /* Check our replay cache for this introduction point. */
809 8 : if (replaycache_add_test_and_elapsed(data->replay_cache, encrypted_section,
810 : encrypted_section_len, &elapsed)) {
811 1 : log_warn(LD_REND, "Possible replay detected! An INTRODUCE2 cell with the "
812 : "same ENCRYPTED section was seen %ld seconds ago. "
813 : "Dropping cell.", (long int) elapsed);
814 1 : goto done;
815 : }
816 :
817 : /* First bytes of the ENCRYPTED section are the client public key (they are
818 : * guaranteed to exist because of the length check above). We are gonna use
819 : * the client public key to compute the ntor keys and decrypt the payload:
820 : */
821 7 : memcpy(&data->client_pk.public_key, encrypted_section,
822 : CURVE25519_PUBKEY_LEN);
823 :
824 : /* Get the right INTRODUCE2 ntor keys and verify the cell MAC */
825 7 : intro_keys = get_introduce2_keys_and_verify_mac(data, encrypted_section,
826 : encrypted_section_len);
827 7 : if (!intro_keys) {
828 2 : log_warn(LD_REND, "Could not get valid INTRO2 keys on circuit %u "
829 : "for service %s", TO_CIRCUIT(circ)->n_circ_id,
830 : safe_str_client(service->onion_address));
831 2 : goto done;
832 : }
833 :
834 : {
835 : /* The ENCRYPTED_DATA section starts just after the CLIENT_PK. */
836 5 : const uint8_t *encrypted_data =
837 : encrypted_section + sizeof(data->client_pk);
838 : /* It's symmetric encryption so it's correct to use the ENCRYPTED length
839 : * for decryption. Computes the length of ENCRYPTED_DATA meaning removing
840 : * the CLIENT_PK and MAC length. */
841 5 : size_t encrypted_data_len =
842 : encrypted_section_len - (sizeof(data->client_pk) + DIGEST256_LEN);
843 :
844 : /* This decrypts the ENCRYPTED_DATA section of the cell. */
845 5 : decrypted = decrypt_introduce2(intro_keys->enc_key,
846 : encrypted_data, encrypted_data_len);
847 5 : if (decrypted == NULL) {
848 0 : log_info(LD_REND, "Unable to decrypt the ENCRYPTED section of an "
849 : "INTRODUCE2 cell on circuit %u for service %s",
850 : TO_CIRCUIT(circ)->n_circ_id,
851 : safe_str_client(service->onion_address));
852 0 : goto done;
853 : }
854 :
855 : /* Parse this blob into an encrypted cell structure so we can then extract
856 : * the data we need out of it. */
857 5 : enc_cell = parse_introduce2_encrypted(decrypted, encrypted_data_len,
858 : circ, service);
859 5 : memwipe(decrypted, 0, encrypted_data_len);
860 5 : if (enc_cell == NULL) {
861 0 : goto done;
862 : }
863 : }
864 :
865 : /* XXX: Implement client authorization checks. */
866 :
867 : /* Extract onion key and rendezvous cookie from the cell used for the
868 : * rendezvous point circuit e2e encryption. */
869 5 : memcpy(data->onion_pk.public_key,
870 5 : trn_cell_introduce_encrypted_getconstarray_onion_key(enc_cell),
871 : CURVE25519_PUBKEY_LEN);
872 5 : memcpy(data->rendezvous_cookie,
873 5 : trn_cell_introduce_encrypted_getconstarray_rend_cookie(enc_cell),
874 : sizeof(data->rendezvous_cookie));
875 :
876 : /* Extract rendezvous link specifiers. */
877 5 : for (size_t idx = 0;
878 10 : idx < trn_cell_introduce_encrypted_get_nspec(enc_cell); idx++) {
879 5 : link_specifier_t *lspec =
880 5 : trn_cell_introduce_encrypted_get_nspecs(enc_cell, idx);
881 5 : if (BUG(!lspec)) {
882 0 : goto done;
883 : }
884 5 : link_specifier_t *lspec_dup = link_specifier_dup(lspec);
885 5 : if (BUG(!lspec_dup)) {
886 0 : goto done;
887 : }
888 5 : smartlist_add(data->link_specifiers, lspec_dup);
889 : }
890 :
891 : /* Success. */
892 5 : ret = 0;
893 5 : log_info(LD_REND, "Valid INTRODUCE2 cell. Launching rendezvous circuit.");
894 :
895 8 : done:
896 8 : if (intro_keys) {
897 5 : memwipe(intro_keys, 0, sizeof(hs_ntor_intro_cell_keys_t));
898 5 : tor_free(intro_keys);
899 : }
900 8 : tor_free(decrypted);
901 8 : trn_cell_introduce_encrypted_free(enc_cell);
902 8 : trn_cell_introduce1_free(cell);
903 8 : return ret;
904 : }
905 :
906 : /** Build a RENDEZVOUS1 cell with the given rendezvous cookie and handshake
907 : * info. The encoded cell is put in cell_out and the length of the data is
908 : * returned. This can't fail. */
909 : ssize_t
910 2 : hs_cell_build_rendezvous1(const uint8_t *rendezvous_cookie,
911 : size_t rendezvous_cookie_len,
912 : const uint8_t *rendezvous_handshake_info,
913 : size_t rendezvous_handshake_info_len,
914 : uint8_t *cell_out)
915 : {
916 2 : ssize_t cell_len;
917 2 : trn_cell_rendezvous1_t *cell;
918 :
919 2 : tor_assert(rendezvous_cookie);
920 2 : tor_assert(rendezvous_handshake_info);
921 2 : tor_assert(cell_out);
922 :
923 2 : cell = trn_cell_rendezvous1_new();
924 : /* Set the RENDEZVOUS_COOKIE. */
925 2 : memcpy(trn_cell_rendezvous1_getarray_rendezvous_cookie(cell),
926 : rendezvous_cookie, rendezvous_cookie_len);
927 : /* Set the HANDSHAKE_INFO. */
928 2 : trn_cell_rendezvous1_setlen_handshake_info(cell,
929 : rendezvous_handshake_info_len);
930 2 : memcpy(trn_cell_rendezvous1_getarray_handshake_info(cell),
931 : rendezvous_handshake_info, rendezvous_handshake_info_len);
932 : /* Encoding. */
933 2 : cell_len = trn_cell_rendezvous1_encode(cell_out, RELAY_PAYLOAD_SIZE, cell);
934 2 : tor_assert(cell_len > 0);
935 :
936 2 : trn_cell_rendezvous1_free(cell);
937 2 : return cell_len;
938 : }
939 :
940 : /** Build an INTRODUCE1 cell from the given data. The encoded cell is put in
941 : * cell_out which must be of at least size RELAY_PAYLOAD_SIZE. On success, the
942 : * encoded length is returned else a negative value and the content of
943 : * cell_out should be ignored. */
944 : ssize_t
945 4 : hs_cell_build_introduce1(const hs_cell_introduce1_data_t *data,
946 : uint8_t *cell_out)
947 : {
948 4 : ssize_t cell_len;
949 4 : trn_cell_introduce1_t *cell;
950 4 : trn_cell_extension_t *ext;
951 :
952 4 : tor_assert(data);
953 4 : tor_assert(cell_out);
954 :
955 4 : cell = trn_cell_introduce1_new();
956 4 : tor_assert(cell);
957 :
958 : /* Set extension data. None are used. */
959 4 : ext = trn_cell_extension_new();
960 4 : tor_assert(ext);
961 4 : trn_cell_extension_set_num(ext, 0);
962 4 : trn_cell_introduce1_set_extensions(cell, ext);
963 :
964 : /* Set the authentication key. */
965 4 : introduce1_set_auth_key(cell, data);
966 :
967 : /* Set the encrypted section. This will set, encrypt and encode the
968 : * ENCRYPTED section in the cell. After this, we'll be ready to encode. */
969 4 : introduce1_set_encrypted(cell, data);
970 :
971 : /* Final encoding. */
972 4 : cell_len = trn_cell_introduce1_encode(cell_out, RELAY_PAYLOAD_SIZE, cell);
973 :
974 4 : trn_cell_introduce1_free(cell);
975 4 : return cell_len;
976 : }
977 :
978 : /** Build an ESTABLISH_RENDEZVOUS cell from the given rendezvous_cookie. The
979 : * encoded cell is put in cell_out which must be of at least
980 : * RELAY_PAYLOAD_SIZE. On success, the encoded length is returned and the
981 : * caller should clear up the content of the cell.
982 : *
983 : * This function can't fail. */
984 : ssize_t
985 0 : hs_cell_build_establish_rendezvous(const uint8_t *rendezvous_cookie,
986 : uint8_t *cell_out)
987 : {
988 0 : tor_assert(rendezvous_cookie);
989 0 : tor_assert(cell_out);
990 :
991 0 : memcpy(cell_out, rendezvous_cookie, HS_REND_COOKIE_LEN);
992 0 : return HS_REND_COOKIE_LEN;
993 : }
994 :
995 : /** Handle an INTRODUCE_ACK cell encoded in payload of length payload_len.
996 : * Return the status code on success else a negative value if the cell as not
997 : * decodable. */
998 : int
999 0 : hs_cell_parse_introduce_ack(const uint8_t *payload, size_t payload_len)
1000 : {
1001 0 : int ret = -1;
1002 0 : trn_cell_introduce_ack_t *cell = NULL;
1003 :
1004 0 : tor_assert(payload);
1005 :
1006 0 : if (trn_cell_introduce_ack_parse(&cell, payload, payload_len) < 0) {
1007 0 : log_info(LD_REND, "Invalid INTRODUCE_ACK cell. Unable to parse it.");
1008 0 : goto end;
1009 : }
1010 :
1011 0 : ret = trn_cell_introduce_ack_get_status(cell);
1012 :
1013 0 : end:
1014 0 : trn_cell_introduce_ack_free(cell);
1015 0 : return ret;
1016 : }
1017 :
1018 : /** Handle a RENDEZVOUS2 cell encoded in payload of length payload_len. On
1019 : * success, handshake_info contains the data in the HANDSHAKE_INFO field, and
1020 : * 0 is returned. On error, a negative value is returned. */
1021 : int
1022 1 : hs_cell_parse_rendezvous2(const uint8_t *payload, size_t payload_len,
1023 : uint8_t *handshake_info, size_t handshake_info_len)
1024 : {
1025 1 : int ret = -1;
1026 1 : trn_cell_rendezvous2_t *cell = NULL;
1027 :
1028 1 : tor_assert(payload);
1029 1 : tor_assert(handshake_info);
1030 :
1031 1 : if (trn_cell_rendezvous2_parse(&cell, payload, payload_len) < 0) {
1032 0 : log_info(LD_REND, "Invalid RENDEZVOUS2 cell. Unable to parse it.");
1033 0 : goto end;
1034 : }
1035 :
1036 : /* Static size, we should never have an issue with this else we messed up
1037 : * our code flow. */
1038 1 : tor_assert(trn_cell_rendezvous2_getlen_handshake_info(cell) ==
1039 : handshake_info_len);
1040 2 : memcpy(handshake_info,
1041 1 : trn_cell_rendezvous2_getconstarray_handshake_info(cell),
1042 : handshake_info_len);
1043 1 : ret = 0;
1044 :
1045 1 : end:
1046 1 : trn_cell_rendezvous2_free(cell);
1047 1 : return ret;
1048 : }
1049 :
1050 : /** Clear the given INTRODUCE1 data structure data. */
1051 : void
1052 4 : hs_cell_introduce1_data_clear(hs_cell_introduce1_data_t *data)
1053 : {
1054 4 : if (data == NULL) {
1055 : return;
1056 : }
1057 : /* Object in this list have been moved to the cell object when building it
1058 : * so they've been freed earlier. We do that in order to avoid duplicating
1059 : * them leading to more memory and CPU time being used for nothing. */
1060 4 : smartlist_free(data->link_specifiers);
1061 : /* The data object has no ownership of any members. */
1062 4 : memwipe(data, 0, sizeof(hs_cell_introduce1_data_t));
1063 : }
|