1 /* Copyright (c) 2016-2019, The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
5 * \file test_hs_service.c
6 * \brief Test hidden service functionality.
9 #define HS_SERVICE_PRIVATE
10 #define HS_INTROPOINT_PRIVATE
11 #define RENDSERVICE_PRIVATE
12 #define CIRCUITLIST_PRIVATE
14 #include "test/test.h"
15 #include "test/log_test_helpers.h"
16 #include "lib/crypt_ops/crypto_rand.h"
18 #include "core/or/or.h"
19 #include "core/or/circuitlist.h"
20 #include "core/or/circuituse.h"
22 #include "core/or/relay.h"
23 #include "feature/rend/rendservice.h"
25 #include "feature/hs/hs_cell.h"
26 #include "feature/hs/hs_circuitmap.h"
27 #include "feature/hs/hs_common.h"
28 #include "feature/hs/hs_intropoint.h"
29 #include "feature/hs/hs_service.h"
31 #include "core/or/or_circuit_st.h"
34 #include "trunnel/hs/cell_establish_intro.h"
35 #include "trunnel/hs/cell_introduce1.h"
36 #include "trunnel/hs/cell_common.h"
39 new_establish_intro_cell(const char *circ_nonce
,
40 trn_cell_establish_intro_t
**cell_out
)
43 uint8_t buf
[RELAY_PAYLOAD_SIZE
] = {0};
44 trn_cell_establish_intro_t
*cell
= NULL
;
45 hs_service_intro_point_t
*ip
= NULL
;
47 /* Ensure that *cell_out is NULL such that we can use to check if we need to
48 * free `cell` in case of an error. */
51 /* Auth key pair is generated in the constructor so we are all set for
52 * using this IP object. */
53 ip
= service_intro_point_new(NULL
);
55 cell_len
= hs_cell_build_establish_intro(circ_nonce
, ip
, buf
);
56 tt_i64_op(cell_len
, OP_GT
, 0);
58 cell_len
= trn_cell_establish_intro_parse(&cell
, buf
, sizeof(buf
));
59 tt_i64_op(cell_len
, OP_GT
, 0);
64 if (*cell_out
== NULL
)
65 trn_cell_establish_intro_free(cell
);
67 service_intro_point_free(ip
);
72 new_establish_intro_encoded_cell(const char *circ_nonce
, uint8_t *cell_out
)
75 hs_service_intro_point_t
*ip
= NULL
;
77 /* Auth key pair is generated in the constructor so we are all set for
78 * using this IP object. */
79 ip
= service_intro_point_new(NULL
);
81 cell_len
= hs_cell_build_establish_intro(circ_nonce
, ip
, cell_out
);
82 tt_i64_op(cell_len
, OP_GT
, 0);
85 service_intro_point_free(ip
);
89 /* Mock function to avoid networking in unittests */
91 mock_send_intro_established_cell(or_circuit_t
*circ
)
98 mock_relay_send_command_from_edge(streamid_t stream_id
, circuit_t
*circ
,
99 uint8_t relay_command
, const char *payload
,
101 crypt_path_t
*cpath_layer
,
102 const char *filename
, int lineno
)
106 (void) relay_command
;
115 static or_circuit_t
*
116 helper_create_intro_circuit(void)
118 or_circuit_t
*circ
= or_circuit_new(0, NULL
);
120 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
125 static trn_cell_introduce1_t
*
126 helper_create_introduce1_cell(void)
128 trn_cell_introduce1_t
*cell
= NULL
;
129 ed25519_keypair_t auth_key_kp
;
131 /* Generate the auth_key of the cell. */
132 if (ed25519_keypair_generate(&auth_key_kp
, 0) < 0) {
136 cell
= trn_cell_introduce1_new();
139 /* Set the auth key. */
141 size_t auth_key_len
= sizeof(auth_key_kp
.pubkey
);
142 trn_cell_introduce1_set_auth_key_type(cell
,
143 HS_INTRO_AUTH_KEY_TYPE_ED25519
);
144 trn_cell_introduce1_set_auth_key_len(cell
, auth_key_len
);
145 trn_cell_introduce1_setlen_auth_key(cell
, auth_key_len
);
146 uint8_t *auth_key_ptr
= trn_cell_introduce1_getarray_auth_key(cell
);
147 memcpy(auth_key_ptr
, auth_key_kp
.pubkey
.pubkey
, auth_key_len
);
150 /* Set the cell extensions to none. */
152 trn_cell_extension_t
*ext
= trn_cell_extension_new();
153 trn_cell_extension_set_num(ext
, 0);
154 trn_cell_introduce1_set_extensions(cell
, ext
);
157 /* Set the encrypted section to some data. */
159 size_t enc_len
= 128;
160 trn_cell_introduce1_setlen_encrypted(cell
, enc_len
);
161 uint8_t *enc_ptr
= trn_cell_introduce1_getarray_encrypted(cell
);
162 memset(enc_ptr
, 'a', enc_len
);
168 trn_cell_introduce1_free(cell
);
172 /* Try sending an ESTABLISH_INTRO cell on a circuit that is already an intro
173 * point. Should fail. */
175 test_establish_intro_wrong_purpose(void *arg
)
178 ssize_t cell_len
= 0;
179 char circ_nonce
[DIGEST_LEN
] = {0};
180 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
181 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
185 /* Get the auth key of the intro point */
186 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
187 memcpy(intro_circ
->rend_circ_nonce
, circ_nonce
, DIGEST_LEN
);
189 /* Set a bad circuit purpose!! :) */
190 circuit_change_purpose(TO_CIRCUIT(intro_circ
), CIRCUIT_PURPOSE_INTRO_POINT
);
192 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
193 attempt to parse it. */
194 cell_len
= new_establish_intro_encoded_cell(circ_nonce
, cell_body
);
195 tt_i64_op(cell_len
, OP_GT
, 0);
197 /* Receive the cell. Should fail. */
198 setup_full_capture_of_logs(LOG_INFO
);
199 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
200 expect_log_msg_containing("Rejecting ESTABLISH_INTRO on non-OR circuit.");
201 teardown_capture_of_logs();
202 tt_int_op(retval
, OP_EQ
, -1);
205 circuit_free_(TO_CIRCUIT(intro_circ
));
208 /* Prepare a circuit for accepting an ESTABLISH_INTRO cell */
210 helper_prepare_circ_for_intro(or_circuit_t
*circ
, const char *circ_nonce
)
212 /* Prepare the circuit for the incoming ESTABLISH_INTRO */
213 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
214 memcpy(circ
->rend_circ_nonce
, circ_nonce
, DIGEST_LEN
);
217 /* Send an empty ESTABLISH_INTRO cell. Should fail. */
219 test_establish_intro_wrong_keytype(void *arg
)
222 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
223 char circ_nonce
[DIGEST_LEN
] = {0};
227 /* Get the auth key of the intro point */
228 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
229 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
231 /* Receive the cell. Should fail. */
232 setup_full_capture_of_logs(LOG_INFO
);
233 retval
= hs_intro_received_establish_intro(intro_circ
, (uint8_t *) "", 0);
234 expect_log_msg_containing("Empty ESTABLISH_INTRO cell.");
235 teardown_capture_of_logs();
236 tt_int_op(retval
, OP_EQ
, -1);
239 circuit_free_(TO_CIRCUIT(intro_circ
));
242 /* Send an ESTABLISH_INTRO cell with an unknown auth key type. Should fail. */
244 test_establish_intro_wrong_keytype2(void *arg
)
247 char circ_nonce
[DIGEST_LEN
] = {0};
248 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
249 ssize_t cell_len
= 0;
250 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
254 /* Get the auth key of the intro point */
255 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
256 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
258 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
259 * attempt to parse it. */
260 cell_len
= new_establish_intro_encoded_cell(circ_nonce
, cell_body
);
261 tt_i64_op(cell_len
, OP_GT
, 0);
263 /* Mutate the auth key type! :) */
266 /* Receive the cell. Should fail. */
267 setup_full_capture_of_logs(LOG_INFO
);
268 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
269 expect_log_msg_containing("Unrecognized AUTH_KEY_TYPE 42.");
270 teardown_capture_of_logs();
271 tt_int_op(retval
, OP_EQ
, -1);
274 circuit_free_(TO_CIRCUIT(intro_circ
));
277 /* Send a legit ESTABLISH_INTRO cell but with a wrong MAC. Should fail. */
279 test_establish_intro_wrong_mac(void *arg
)
282 char circ_nonce
[DIGEST_LEN
] = {0};
283 ssize_t cell_len
= 0;
284 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
285 trn_cell_establish_intro_t
*cell
= NULL
;
286 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
290 /* Get the auth key of the intro point */
291 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
292 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
294 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
295 * attempt to parse it. */
296 cell_len
= new_establish_intro_cell(circ_nonce
, &cell
);
297 tt_i64_op(cell_len
, OP_GT
, 0);
300 /* Mangle one byte of the MAC. */
301 uint8_t *handshake_ptr
=
302 trn_cell_establish_intro_getarray_handshake_mac(cell
);
303 handshake_ptr
[TRUNNEL_SHA3_256_LEN
- 1]++;
304 /* We need to resign the payload with that change. */
306 ed25519_signature_t sig
;
307 ed25519_keypair_t key_struct
;
308 /* New keypair for the signature since we don't have access to the private
309 * key material generated earlier when creating the cell. */
310 retval
= ed25519_keypair_generate(&key_struct
, 0);
311 tt_int_op(retval
, OP_EQ
, 0);
312 uint8_t *auth_key_ptr
=
313 trn_cell_establish_intro_getarray_auth_key(cell
);
314 memcpy(auth_key_ptr
, key_struct
.pubkey
.pubkey
, ED25519_PUBKEY_LEN
);
315 /* Encode payload so we can sign it. */
316 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
318 tt_i64_op(cell_len
, OP_GT
, 0);
320 retval
= ed25519_sign_prefixed(&sig
, cell_body
,
322 (ED25519_SIG_LEN
+ sizeof(cell
->sig_len
)),
323 ESTABLISH_INTRO_SIG_PREFIX
, &key_struct
);
324 tt_int_op(retval
, OP_EQ
, 0);
325 /* And write the signature to the cell */
327 trn_cell_establish_intro_getarray_sig(cell
);
328 memcpy(sig_ptr
, sig
.sig
, cell
->sig_len
);
329 /* Re-encode with the new signature. */
330 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
332 tt_i64_op(cell_len
, OP_GT
, 0);
335 /* Receive the cell. Should fail because our MAC is wrong. */
336 setup_full_capture_of_logs(LOG_INFO
);
337 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
338 expect_log_msg_containing("ESTABLISH_INTRO handshake_auth not as expected");
339 teardown_capture_of_logs();
340 tt_int_op(retval
, OP_EQ
, -1);
343 trn_cell_establish_intro_free(cell
);
344 circuit_free_(TO_CIRCUIT(intro_circ
));
347 /* Send a legit ESTABLISH_INTRO cell but with a wrong auth key length. Should
350 test_establish_intro_wrong_auth_key_len(void *arg
)
353 char circ_nonce
[DIGEST_LEN
] = {0};
354 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
355 ssize_t cell_len
= 0;
356 size_t bad_auth_key_len
= ED25519_PUBKEY_LEN
- 1;
357 trn_cell_establish_intro_t
*cell
= NULL
;
358 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
362 /* Get the auth key of the intro point */
363 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
364 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
366 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
367 * attempt to parse it. */
368 cell_len
= new_establish_intro_cell(circ_nonce
, &cell
);
369 tt_i64_op(cell_len
, OP_GT
, 0);
372 /* Mangle the auth key length. */
373 trn_cell_establish_intro_set_auth_key_len(cell
, bad_auth_key_len
);
374 trn_cell_establish_intro_setlen_auth_key(cell
, bad_auth_key_len
);
376 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
378 tt_int_op(cell_len
, OP_GT
, 0);
380 /* Receive the cell. Should fail. */
381 setup_full_capture_of_logs(LOG_INFO
);
382 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
383 expect_log_msg_containing("ESTABLISH_INTRO auth key length is invalid");
384 teardown_capture_of_logs();
385 tt_int_op(retval
, OP_EQ
, -1);
388 trn_cell_establish_intro_free(cell
);
389 circuit_free_(TO_CIRCUIT(intro_circ
));
392 /* Send a legit ESTABLISH_INTRO cell but with a wrong sig length. Should
395 test_establish_intro_wrong_sig_len(void *arg
)
398 char circ_nonce
[DIGEST_LEN
] = {0};
399 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
400 ssize_t cell_len
= 0;
401 size_t bad_sig_len
= ED25519_SIG_LEN
- 1;
402 trn_cell_establish_intro_t
*cell
= NULL
;
403 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
407 /* Get the auth key of the intro point */
408 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
409 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
411 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
412 * attempt to parse it. */
413 cell_len
= new_establish_intro_cell(circ_nonce
, &cell
);
414 tt_i64_op(cell_len
, OP_GT
, 0);
417 /* Mangle the signature length. */
418 trn_cell_establish_intro_set_sig_len(cell
, bad_sig_len
);
419 trn_cell_establish_intro_setlen_sig(cell
, bad_sig_len
);
421 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
423 tt_int_op(cell_len
, OP_GT
, 0);
425 /* Receive the cell. Should fail. */
426 setup_full_capture_of_logs(LOG_INFO
);
427 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
428 expect_log_msg_containing("ESTABLISH_INTRO sig len is invalid");
429 teardown_capture_of_logs();
430 tt_int_op(retval
, OP_EQ
, -1);
433 trn_cell_establish_intro_free(cell
);
434 circuit_free_(TO_CIRCUIT(intro_circ
));
437 /* Send a legit ESTABLISH_INTRO cell but slightly change the signature. Should
440 test_establish_intro_wrong_sig(void *arg
)
443 char circ_nonce
[DIGEST_LEN
] = {0};
444 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
445 ssize_t cell_len
= 0;
446 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
450 /* Get the auth key of the intro point */
451 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
452 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
454 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
455 attempt to parse it. */
456 cell_len
= new_establish_intro_encoded_cell(circ_nonce
, cell_body
);
457 tt_i64_op(cell_len
, OP_GT
, 0);
459 /* Mutate the last byte (signature)! :) */
460 cell_body
[cell_len
- 1]++;
462 /* Receive the cell. Should fail. */
463 setup_full_capture_of_logs(LOG_INFO
);
464 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
,
466 expect_log_msg_containing("Failed to verify ESTABLISH_INTRO cell.");
467 teardown_capture_of_logs();
468 tt_int_op(retval
, OP_EQ
, -1);
471 circuit_free_(TO_CIRCUIT(intro_circ
));
474 /* Helper function: Send a well-formed v3 ESTABLISH_INTRO cell to
475 * <b>intro_circ</b>. Return the cell. */
476 static trn_cell_establish_intro_t
*
477 helper_establish_intro_v3(or_circuit_t
*intro_circ
)
480 char circ_nonce
[DIGEST_LEN
] = {0};
481 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
482 ssize_t cell_len
= 0;
483 trn_cell_establish_intro_t
*cell
= NULL
;
485 tt_assert(intro_circ
);
487 /* Prepare the circuit for the incoming ESTABLISH_INTRO */
488 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
489 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
491 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
492 * attempt to parse it. */
493 cell_len
= new_establish_intro_cell(circ_nonce
, &cell
);
494 tt_i64_op(cell_len
, OP_GT
, 0);
496 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
498 tt_int_op(cell_len
, OP_GT
, 0);
500 /* Receive the cell */
501 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
,
503 tt_int_op(retval
, OP_EQ
, 0);
509 /* Helper function: Send a well-formed v2 ESTABLISH_INTRO cell to
510 * <b>intro_circ</b>. Return the public key advertised in the cell. */
512 helper_establish_intro_v2(or_circuit_t
*intro_circ
)
514 crypto_pk_t
*key1
= NULL
;
516 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
517 ssize_t cell_len
= 0;
518 char circ_nonce
[DIGEST_LEN
] = {0};
520 tt_assert(intro_circ
);
522 /* Prepare the circuit for the incoming ESTABLISH_INTRO */
523 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
524 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
526 /* Send legacy establish_intro */
527 key1
= pk_generate(0);
529 /* Use old circ_nonce why not */
530 cell_len
= rend_service_encode_establish_intro_cell(
532 sizeof(cell_body
), key1
,
534 tt_int_op(cell_len
, OP_GT
, 0);
536 /* Receive legacy establish_intro */
537 retval
= hs_intro_received_establish_intro(intro_circ
,
538 cell_body
, (size_t) cell_len
);
539 tt_int_op(retval
, OP_EQ
, 0);
545 /* Helper function: test circuitmap free_all function outside of
546 * test_intro_point_registration to prevent Coverity from seeing a
547 * double free if the assertion hypothetically fails.
550 test_circuitmap_free_all(void)
552 hs_circuitmap_ht
*the_hs_circuitmap
= NULL
;
554 the_hs_circuitmap
= get_hs_circuitmap();
555 tt_assert(the_hs_circuitmap
);
556 hs_circuitmap_free_all();
557 the_hs_circuitmap
= get_hs_circuitmap();
558 tt_ptr_op(the_hs_circuitmap
, OP_EQ
, NULL
);
563 /** Successfully register a v2 intro point and a v3 intro point. Ensure that HS
564 * circuitmap is maintained properly. */
566 test_intro_point_registration(void *arg
)
569 hs_circuitmap_ht
*the_hs_circuitmap
= NULL
;
571 or_circuit_t
*intro_circ
= NULL
;
572 trn_cell_establish_intro_t
*establish_intro_cell
= NULL
;
573 ed25519_public_key_t auth_key
;
575 crypto_pk_t
*legacy_auth_key
= NULL
;
576 or_circuit_t
*legacy_intro_circ
= NULL
;
578 or_circuit_t
*returned_intro_circ
= NULL
;
582 MOCK(hs_intro_send_intro_established_cell
, mock_send_intro_established_cell
);
584 hs_circuitmap_init();
586 /* Check that the circuitmap is currently empty */
588 the_hs_circuitmap
= get_hs_circuitmap();
589 tt_assert(the_hs_circuitmap
);
590 tt_int_op(0, OP_EQ
, HT_SIZE(the_hs_circuitmap
));
591 /* Do a circuitmap query in any case */
592 returned_intro_circ
=hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key
);
593 tt_ptr_op(returned_intro_circ
, OP_EQ
, NULL
);
596 /* Create a v3 intro point */
598 intro_circ
= or_circuit_new(0, NULL
);
599 tt_assert(intro_circ
);
600 establish_intro_cell
= helper_establish_intro_v3(intro_circ
);
602 /* Check that the intro point was registered on the HS circuitmap */
603 the_hs_circuitmap
= get_hs_circuitmap();
604 tt_assert(the_hs_circuitmap
);
605 tt_int_op(1, OP_EQ
, HT_SIZE(the_hs_circuitmap
));
606 get_auth_key_from_cell(&auth_key
, RELAY_COMMAND_ESTABLISH_INTRO
,
607 establish_intro_cell
);
608 returned_intro_circ
=
609 hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key
);
610 tt_ptr_op(intro_circ
, OP_EQ
, returned_intro_circ
);
613 /* Create a v2 intro point */
615 char key_digest
[DIGEST_LEN
];
617 legacy_intro_circ
= or_circuit_new(1, NULL
);
618 tt_assert(legacy_intro_circ
);
619 legacy_auth_key
= helper_establish_intro_v2(legacy_intro_circ
);
620 tt_assert(legacy_auth_key
);
622 /* Check that the circuitmap now has two elements */
623 the_hs_circuitmap
= get_hs_circuitmap();
624 tt_assert(the_hs_circuitmap
);
625 tt_int_op(2, OP_EQ
, HT_SIZE(the_hs_circuitmap
));
627 /* Check that the new element is our legacy intro circuit. */
628 retval
= crypto_pk_get_digest(legacy_auth_key
, key_digest
);
629 tt_int_op(retval
, OP_EQ
, 0);
630 returned_intro_circ
=
631 hs_circuitmap_get_intro_circ_v2_relay_side((uint8_t*)key_digest
);
632 tt_ptr_op(legacy_intro_circ
, OP_EQ
, returned_intro_circ
);
635 /* XXX Continue test and try to register a second v3 intro point with the
636 * same auth key. Make sure that old intro circuit gets closed. */
639 crypto_pk_free(legacy_auth_key
);
640 circuit_free_(TO_CIRCUIT(intro_circ
));
641 circuit_free_(TO_CIRCUIT(legacy_intro_circ
));
642 trn_cell_establish_intro_free(establish_intro_cell
);
643 test_circuitmap_free_all();
645 UNMOCK(hs_intro_send_intro_established_cell
);
649 test_introduce1_suitable_circuit(void *arg
)
652 or_circuit_t
*circ
= NULL
;
656 /* Valid suitable circuit. */
658 circ
= or_circuit_new(0, NULL
);
659 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
660 ret
= circuit_is_suitable_for_introduce1(circ
);
661 circuit_free_(TO_CIRCUIT(circ
));
662 tt_int_op(ret
, OP_EQ
, 1);
665 /* Test if the circuit purpose safeguard works correctly. */
667 circ
= or_circuit_new(0, NULL
);
668 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_INTRO_POINT
);
669 ret
= circuit_is_suitable_for_introduce1(circ
);
670 circuit_free_(TO_CIRCUIT(circ
));
671 tt_int_op(ret
, OP_EQ
, 0);
674 /* Test the non-edge circuit safeguard works correctly. */
676 circ
= or_circuit_new(0, NULL
);
677 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
678 /* Bogus pointer, the check is against NULL on n_chan. */
679 circ
->base_
.n_chan
= (channel_t
*) circ
;
680 ret
= circuit_is_suitable_for_introduce1(circ
);
681 circuit_free_(TO_CIRCUIT(circ
));
682 tt_int_op(ret
, OP_EQ
, 0);
685 /* Mangle the circuit a bit more so see if our only one INTRODUCE1 cell
686 * limit works correctly. */
688 circ
= or_circuit_new(0, NULL
);
689 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
690 circ
->already_received_introduce1
= 1;
691 ret
= circuit_is_suitable_for_introduce1(circ
);
692 circuit_free_(TO_CIRCUIT(circ
));
693 tt_int_op(ret
, OP_EQ
, 0);
701 test_introduce1_is_legacy(void *arg
)
704 uint8_t request
[256];
708 /* For a cell to be considered legacy, according to the specification, the
709 * first 20 bytes MUST BE non-zero else it's a v3 cell. */
710 memset(request
, 'a', DIGEST_LEN
);
711 memset(request
+ DIGEST_LEN
, 0, sizeof(request
) - DIGEST_LEN
);
712 ret
= introduce1_cell_is_legacy(request
);
713 tt_int_op(ret
, OP_EQ
, 1);
715 /* This is a NON legacy cell. */
716 memset(request
, 0, DIGEST_LEN
);
717 memset(request
+ DIGEST_LEN
, 'a', sizeof(request
) - DIGEST_LEN
);
718 ret
= introduce1_cell_is_legacy(request
);
719 tt_int_op(ret
, OP_EQ
, 0);
726 test_introduce1_validation(void *arg
)
729 trn_cell_introduce1_t
*cell
= NULL
;
733 /* Create our decoy cell that we'll modify as we go to test the validation
734 * function of that parsed cell. */
735 cell
= helper_create_introduce1_cell();
738 /* It should NOT be a legacy cell which will trigger a BUG(). */
739 memset(cell
->legacy_key_id
, 'a', sizeof(cell
->legacy_key_id
));
740 tor_capture_bugs_(1);
741 ret
= validate_introduce1_parsed_cell(cell
);
742 tor_end_capture_bugs_();
743 tt_int_op(ret
, OP_EQ
, -1);
744 /* Reset legacy ID and make sure it's correct. */
745 memset(cell
->legacy_key_id
, 0, sizeof(cell
->legacy_key_id
));
746 ret
= validate_introduce1_parsed_cell(cell
);
747 tt_int_op(ret
, OP_EQ
, 0);
749 /* Non existing auth key type. */
750 cell
->auth_key_type
= 42;
751 ret
= validate_introduce1_parsed_cell(cell
);
752 tt_int_op(ret
, OP_EQ
, -1);
753 /* Reset is to correct value and make sure it's correct. */
754 cell
->auth_key_type
= HS_INTRO_AUTH_KEY_TYPE_ED25519
;
755 ret
= validate_introduce1_parsed_cell(cell
);
756 tt_int_op(ret
, OP_EQ
, 0);
758 /* Really bad key length. */
759 cell
->auth_key_len
= 0;
760 ret
= validate_introduce1_parsed_cell(cell
);
761 tt_int_op(ret
, OP_EQ
, -1);
762 cell
->auth_key_len
= UINT16_MAX
;
763 ret
= validate_introduce1_parsed_cell(cell
);
764 tt_int_op(ret
, OP_EQ
, -1);
765 /* Correct size, let's try that. */
766 cell
->auth_key_len
= sizeof(ed25519_public_key_t
);
767 ret
= validate_introduce1_parsed_cell(cell
);
768 tt_int_op(ret
, OP_EQ
, 0);
769 /* Set an invalid size of the auth key buffer. */
770 trn_cell_introduce1_setlen_auth_key(cell
, 3);
771 ret
= validate_introduce1_parsed_cell(cell
);
772 tt_int_op(ret
, OP_EQ
, -1);
773 /* Reset auth key buffer and make sure it works. */
774 trn_cell_introduce1_setlen_auth_key(cell
, sizeof(ed25519_public_key_t
));
775 ret
= validate_introduce1_parsed_cell(cell
);
776 tt_int_op(ret
, OP_EQ
, 0);
778 /* Empty encrypted section. */
779 trn_cell_introduce1_setlen_encrypted(cell
, 0);
780 ret
= validate_introduce1_parsed_cell(cell
);
781 tt_int_op(ret
, OP_EQ
, -1);
782 /* Reset it to some non zero bytes and validate. */
783 trn_cell_introduce1_setlen_encrypted(cell
, 1);
784 ret
= validate_introduce1_parsed_cell(cell
);
785 tt_int_op(ret
, OP_EQ
, 0);
788 trn_cell_introduce1_free(cell
);
792 test_received_introduce1_handling(void *arg
)
795 uint8_t *request
= NULL
, buf
[128];
796 trn_cell_introduce1_t
*cell
= NULL
;
797 or_circuit_t
*circ
= NULL
;
801 MOCK(relay_send_command_from_edge_
, mock_relay_send_command_from_edge
);
803 hs_circuitmap_init();
805 /* Too small request length. An INTRODUCE1 expect at the very least a
806 * DIGEST_LEN size. */
808 memset(buf
, 0, sizeof(buf
));
809 circ
= helper_create_intro_circuit();
810 ret
= hs_intro_received_introduce1(circ
, buf
, DIGEST_LEN
- 1);
811 tt_int_op(ret
, OP_EQ
, -1);
812 circuit_free_(TO_CIRCUIT(circ
));
815 /* We have a unit test only for the suitability of a circuit to receive an
816 * INTRODUCE1 cell so from now on we'll only test the handling of a cell. */
820 circ
= helper_create_intro_circuit();
821 uint8_t test
[2]; /* Too small request. */
822 memset(test
, 0, sizeof(test
));
823 ret
= handle_introduce1(circ
, test
, sizeof(test
));
824 tor_free(circ
->p_chan
);
825 circuit_free_(TO_CIRCUIT(circ
));
826 tt_int_op(ret
, OP_EQ
, -1);
831 cell
= helper_create_introduce1_cell();
832 ssize_t request_len
= trn_cell_introduce1_encoded_len(cell
);
833 tt_int_op((int)request_len
, OP_GT
, 0);
834 request
= tor_malloc_zero(request_len
);
835 ssize_t encoded_len
=
836 trn_cell_introduce1_encode(request
, request_len
, cell
);
837 tt_int_op((int)encoded_len
, OP_GT
, 0);
839 circ
= helper_create_intro_circuit();
840 or_circuit_t
*service_circ
= helper_create_intro_circuit();
841 circuit_change_purpose(TO_CIRCUIT(service_circ
),
842 CIRCUIT_PURPOSE_INTRO_POINT
);
843 /* Register the circuit in the map for the auth key of the cell. */
844 ed25519_public_key_t auth_key
;
845 const uint8_t *cell_auth_key
=
846 trn_cell_introduce1_getconstarray_auth_key(cell
);
847 memcpy(auth_key
.pubkey
, cell_auth_key
, ED25519_PUBKEY_LEN
);
848 hs_circuitmap_register_intro_circ_v3_relay_side(service_circ
, &auth_key
);
849 ret
= hs_intro_received_introduce1(circ
, request
, request_len
);
850 circuit_free_(TO_CIRCUIT(circ
));
851 circuit_free_(TO_CIRCUIT(service_circ
));
852 tt_int_op(ret
, OP_EQ
, 0);
855 /* Valid legacy cell. */
858 trn_cell_introduce1_free(cell
);
859 cell
= helper_create_introduce1_cell();
860 uint8_t *legacy_key_id
= trn_cell_introduce1_getarray_legacy_key_id(cell
);
861 memset(legacy_key_id
, 'a', DIGEST_LEN
);
862 /* Add an arbitrary amount of data for the payload of a v2 cell. */
863 size_t request_len
= trn_cell_introduce1_encoded_len(cell
) + 256;
864 tt_size_op(request_len
, OP_GT
, 0);
865 request
= tor_malloc_zero(request_len
+ 256);
866 ssize_t encoded_len
=
867 trn_cell_introduce1_encode(request
, request_len
, cell
);
868 tt_int_op((int)encoded_len
, OP_GT
, 0);
870 circ
= helper_create_intro_circuit();
871 or_circuit_t
*service_circ
= helper_create_intro_circuit();
872 circuit_change_purpose(TO_CIRCUIT(service_circ
),
873 CIRCUIT_PURPOSE_INTRO_POINT
);
874 /* Register the circuit in the map for the auth key of the cell. */
875 uint8_t token
[REND_TOKEN_LEN
];
876 memcpy(token
, legacy_key_id
, sizeof(token
));
877 hs_circuitmap_register_intro_circ_v2_relay_side(service_circ
, token
);
878 ret
= hs_intro_received_introduce1(circ
, request
, request_len
);
879 circuit_free_(TO_CIRCUIT(circ
));
880 circuit_free_(TO_CIRCUIT(service_circ
));
881 tt_int_op(ret
, OP_EQ
, 0);
885 trn_cell_introduce1_free(cell
);
887 hs_circuitmap_free_all();
888 UNMOCK(relay_send_command_from_edge_
);
891 struct testcase_t hs_intropoint_tests
[] = {
892 { "intro_point_registration",
893 test_intro_point_registration
, TT_FORK
, NULL
, NULL
},
895 { "receive_establish_intro_wrong_keytype",
896 test_establish_intro_wrong_keytype
, TT_FORK
, NULL
, NULL
},
898 { "receive_establish_intro_wrong_keytype2",
899 test_establish_intro_wrong_keytype2
, TT_FORK
, NULL
, NULL
},
901 { "receive_establish_intro_wrong_purpose",
902 test_establish_intro_wrong_purpose
, TT_FORK
, NULL
, NULL
},
904 { "receive_establish_intro_wrong_sig",
905 test_establish_intro_wrong_sig
, TT_FORK
, NULL
, NULL
},
907 { "receive_establish_intro_wrong_sig_len",
908 test_establish_intro_wrong_sig_len
, TT_FORK
, NULL
, NULL
},
910 { "receive_establish_intro_wrong_auth_key_len",
911 test_establish_intro_wrong_auth_key_len
, TT_FORK
, NULL
, NULL
},
913 { "receive_establish_intro_wrong_mac",
914 test_establish_intro_wrong_mac
, TT_FORK
, NULL
, NULL
},
916 { "introduce1_suitable_circuit",
917 test_introduce1_suitable_circuit
, TT_FORK
, NULL
, NULL
},
919 { "introduce1_is_legacy",
920 test_introduce1_is_legacy
, TT_FORK
, NULL
, NULL
},
922 { "introduce1_validation",
923 test_introduce1_validation
, TT_FORK
, NULL
, NULL
},
925 { "received_introduce1_handling",
926 test_received_introduce1_handling
, TT_FORK
, NULL
, NULL
},