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
, 0, 0);
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
, 0, 0);
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 TRUNNEL_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: test circuitmap free_all function outside of
510 * test_intro_point_registration to prevent Coverity from seeing a
511 * double free if the assertion hypothetically fails.
514 test_circuitmap_free_all(void)
516 hs_circuitmap_ht
*the_hs_circuitmap
= NULL
;
518 the_hs_circuitmap
= get_hs_circuitmap();
519 tt_assert(the_hs_circuitmap
);
520 hs_circuitmap_free_all();
521 the_hs_circuitmap
= get_hs_circuitmap();
522 tt_ptr_op(the_hs_circuitmap
, OP_EQ
, NULL
);
527 /** Successfully register a v2 intro point and a v3 intro point. Ensure that HS
528 * circuitmap is maintained properly. */
530 test_intro_point_registration(void *arg
)
532 hs_circuitmap_ht
*the_hs_circuitmap
= NULL
;
534 or_circuit_t
*intro_circ
= NULL
;
535 trn_cell_establish_intro_t
*establish_intro_cell
= NULL
;
536 ed25519_public_key_t auth_key
;
538 or_circuit_t
*returned_intro_circ
= NULL
;
542 MOCK(hs_intro_send_intro_established_cell
, mock_send_intro_established_cell
);
544 hs_circuitmap_init();
546 /* Check that the circuitmap is currently empty */
548 the_hs_circuitmap
= get_hs_circuitmap();
549 tt_assert(the_hs_circuitmap
);
550 tt_int_op(0, OP_EQ
, HT_SIZE(the_hs_circuitmap
));
551 /* Do a circuitmap query in any case */
552 returned_intro_circ
=hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key
);
553 tt_ptr_op(returned_intro_circ
, OP_EQ
, NULL
);
556 /* Create a v3 intro point */
558 intro_circ
= or_circuit_new(0, NULL
);
559 tt_assert(intro_circ
);
560 establish_intro_cell
= helper_establish_intro_v3(intro_circ
);
562 /* Check that the intro point was registered on the HS circuitmap */
563 the_hs_circuitmap
= get_hs_circuitmap();
564 tt_assert(the_hs_circuitmap
);
565 tt_int_op(1, OP_EQ
, HT_SIZE(the_hs_circuitmap
));
566 get_auth_key_from_cell(&auth_key
, RELAY_COMMAND_ESTABLISH_INTRO
,
567 establish_intro_cell
);
568 returned_intro_circ
=
569 hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key
);
570 tt_ptr_op(intro_circ
, OP_EQ
, returned_intro_circ
);
573 /* XXX Continue test and try to register a second v3 intro point with the
574 * same auth key. Make sure that old intro circuit gets closed. */
577 circuit_free_(TO_CIRCUIT(intro_circ
));
578 trn_cell_establish_intro_free(establish_intro_cell
);
579 test_circuitmap_free_all();
581 UNMOCK(hs_intro_send_intro_established_cell
);
585 test_introduce1_suitable_circuit(void *arg
)
588 or_circuit_t
*circ
= NULL
;
592 /* Valid suitable circuit. */
594 circ
= or_circuit_new(0, NULL
);
595 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
596 ret
= circuit_is_suitable_for_introduce1(circ
);
597 circuit_free_(TO_CIRCUIT(circ
));
598 tt_int_op(ret
, OP_EQ
, 1);
601 /* Test if the circuit purpose safeguard works correctly. */
603 circ
= or_circuit_new(0, NULL
);
604 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_INTRO_POINT
);
605 ret
= circuit_is_suitable_for_introduce1(circ
);
606 circuit_free_(TO_CIRCUIT(circ
));
607 tt_int_op(ret
, OP_EQ
, 0);
610 /* Test the non-edge circuit safeguard works correctly. */
612 circ
= or_circuit_new(0, NULL
);
613 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
614 /* Bogus pointer, the check is against NULL on n_chan. */
615 circ
->base_
.n_chan
= (channel_t
*) circ
;
616 ret
= circuit_is_suitable_for_introduce1(circ
);
617 circuit_free_(TO_CIRCUIT(circ
));
618 tt_int_op(ret
, OP_EQ
, 0);
621 /* Mangle the circuit a bit more so see if our only one INTRODUCE1 cell
622 * limit works correctly. */
624 circ
= or_circuit_new(0, NULL
);
625 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
626 circ
->already_received_introduce1
= 1;
627 ret
= circuit_is_suitable_for_introduce1(circ
);
628 circuit_free_(TO_CIRCUIT(circ
));
629 tt_int_op(ret
, OP_EQ
, 0);
637 test_introduce1_is_legacy(void *arg
)
640 uint8_t request
[256];
644 /* For a cell to be considered legacy, according to the specification, the
645 * first 20 bytes MUST BE non-zero else it's a v3 cell. */
646 memset(request
, 'a', DIGEST_LEN
);
647 memset(request
+ DIGEST_LEN
, 0, sizeof(request
) - DIGEST_LEN
);
648 ret
= introduce1_cell_is_legacy(request
);
649 tt_int_op(ret
, OP_EQ
, 1);
651 /* This is a NON legacy cell. */
652 memset(request
, 0, DIGEST_LEN
);
653 memset(request
+ DIGEST_LEN
, 'a', sizeof(request
) - DIGEST_LEN
);
654 ret
= introduce1_cell_is_legacy(request
);
655 tt_int_op(ret
, OP_EQ
, 0);
662 test_introduce1_validation(void *arg
)
665 trn_cell_introduce1_t
*cell
= NULL
;
669 /* Create our decoy cell that we'll modify as we go to test the validation
670 * function of that parsed cell. */
671 cell
= helper_create_introduce1_cell();
674 /* It should NOT be a legacy cell which will trigger a BUG(). */
675 memset(cell
->legacy_key_id
, 'a', sizeof(cell
->legacy_key_id
));
676 tor_capture_bugs_(1);
677 ret
= validate_introduce1_parsed_cell(cell
);
678 tor_end_capture_bugs_();
679 tt_int_op(ret
, OP_EQ
, -1);
680 /* Reset legacy ID and make sure it's correct. */
681 memset(cell
->legacy_key_id
, 0, sizeof(cell
->legacy_key_id
));
682 ret
= validate_introduce1_parsed_cell(cell
);
683 tt_int_op(ret
, OP_EQ
, 0);
685 /* Non existing auth key type. */
686 cell
->auth_key_type
= 42;
687 ret
= validate_introduce1_parsed_cell(cell
);
688 tt_int_op(ret
, OP_EQ
, -1);
689 /* Reset is to correct value and make sure it's correct. */
690 cell
->auth_key_type
= TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519
;
691 ret
= validate_introduce1_parsed_cell(cell
);
692 tt_int_op(ret
, OP_EQ
, 0);
694 /* Really bad key length. */
695 cell
->auth_key_len
= 0;
696 ret
= validate_introduce1_parsed_cell(cell
);
697 tt_int_op(ret
, OP_EQ
, -1);
698 cell
->auth_key_len
= UINT16_MAX
;
699 ret
= validate_introduce1_parsed_cell(cell
);
700 tt_int_op(ret
, OP_EQ
, -1);
701 /* Correct size, let's try that. */
702 cell
->auth_key_len
= sizeof(ed25519_public_key_t
);
703 ret
= validate_introduce1_parsed_cell(cell
);
704 tt_int_op(ret
, OP_EQ
, 0);
705 /* Set an invalid size of the auth key buffer. */
706 trn_cell_introduce1_setlen_auth_key(cell
, 3);
707 ret
= validate_introduce1_parsed_cell(cell
);
708 tt_int_op(ret
, OP_EQ
, -1);
709 /* Reset auth key buffer and make sure it works. */
710 trn_cell_introduce1_setlen_auth_key(cell
, sizeof(ed25519_public_key_t
));
711 ret
= validate_introduce1_parsed_cell(cell
);
712 tt_int_op(ret
, OP_EQ
, 0);
714 /* Empty encrypted section. */
715 trn_cell_introduce1_setlen_encrypted(cell
, 0);
716 ret
= validate_introduce1_parsed_cell(cell
);
717 tt_int_op(ret
, OP_EQ
, -1);
718 /* Reset it to some non zero bytes and validate. */
719 trn_cell_introduce1_setlen_encrypted(cell
, 1);
720 ret
= validate_introduce1_parsed_cell(cell
);
721 tt_int_op(ret
, OP_EQ
, 0);
724 trn_cell_introduce1_free(cell
);
728 test_received_introduce1_handling(void *arg
)
731 uint8_t *request
= NULL
, buf
[128];
732 trn_cell_introduce1_t
*cell
= NULL
;
733 or_circuit_t
*circ
= NULL
;
737 MOCK(relay_send_command_from_edge_
, mock_relay_send_command_from_edge
);
739 hs_circuitmap_init();
741 /* Too small request length. An INTRODUCE1 expect at the very least a
742 * DIGEST_LEN size. */
744 memset(buf
, 0, sizeof(buf
));
745 circ
= helper_create_intro_circuit();
746 ret
= hs_intro_received_introduce1(circ
, buf
, DIGEST_LEN
- 1);
747 tt_int_op(ret
, OP_EQ
, -1);
748 circuit_free_(TO_CIRCUIT(circ
));
751 /* We have a unit test only for the suitability of a circuit to receive an
752 * INTRODUCE1 cell so from now on we'll only test the handling of a cell. */
756 circ
= helper_create_intro_circuit();
757 uint8_t test
[2]; /* Too small request. */
758 memset(test
, 0, sizeof(test
));
759 ret
= handle_introduce1(circ
, test
, sizeof(test
));
760 tor_free(circ
->p_chan
);
761 circuit_free_(TO_CIRCUIT(circ
));
762 tt_int_op(ret
, OP_EQ
, -1);
767 cell
= helper_create_introduce1_cell();
768 ssize_t request_len
= trn_cell_introduce1_encoded_len(cell
);
769 tt_int_op((int)request_len
, OP_GT
, 0);
770 request
= tor_malloc_zero(request_len
);
771 ssize_t encoded_len
=
772 trn_cell_introduce1_encode(request
, request_len
, cell
);
773 tt_int_op((int)encoded_len
, OP_GT
, 0);
775 circ
= helper_create_intro_circuit();
776 or_circuit_t
*service_circ
= helper_create_intro_circuit();
777 circuit_change_purpose(TO_CIRCUIT(service_circ
),
778 CIRCUIT_PURPOSE_INTRO_POINT
);
779 /* Register the circuit in the map for the auth key of the cell. */
780 ed25519_public_key_t auth_key
;
781 const uint8_t *cell_auth_key
=
782 trn_cell_introduce1_getconstarray_auth_key(cell
);
783 memcpy(auth_key
.pubkey
, cell_auth_key
, ED25519_PUBKEY_LEN
);
784 hs_circuitmap_register_intro_circ_v3_relay_side(service_circ
, &auth_key
);
785 ret
= hs_intro_received_introduce1(circ
, request
, request_len
);
786 circuit_free_(TO_CIRCUIT(circ
));
787 circuit_free_(TO_CIRCUIT(service_circ
));
788 tt_int_op(ret
, OP_EQ
, 0);
791 /* Valid legacy cell. */
794 trn_cell_introduce1_free(cell
);
795 cell
= helper_create_introduce1_cell();
796 uint8_t *legacy_key_id
= trn_cell_introduce1_getarray_legacy_key_id(cell
);
797 memset(legacy_key_id
, 'a', DIGEST_LEN
);
798 /* Add an arbitrary amount of data for the payload of a v2 cell. */
799 size_t request_len
= trn_cell_introduce1_encoded_len(cell
) + 256;
800 tt_size_op(request_len
, OP_GT
, 0);
801 request
= tor_malloc_zero(request_len
+ 256);
802 ssize_t encoded_len
=
803 trn_cell_introduce1_encode(request
, request_len
, cell
);
804 tt_int_op((int)encoded_len
, OP_GT
, 0);
806 circ
= helper_create_intro_circuit();
807 or_circuit_t
*service_circ
= helper_create_intro_circuit();
808 circuit_change_purpose(TO_CIRCUIT(service_circ
),
809 CIRCUIT_PURPOSE_INTRO_POINT
);
810 /* Register the circuit in the map for the auth key of the cell. */
811 uint8_t token
[REND_TOKEN_LEN
];
812 memcpy(token
, legacy_key_id
, sizeof(token
));
813 hs_circuitmap_register_intro_circ_v2_relay_side(service_circ
, token
);
814 ret
= hs_intro_received_introduce1(circ
, request
, request_len
);
815 circuit_free_(TO_CIRCUIT(circ
));
816 circuit_free_(TO_CIRCUIT(service_circ
));
817 tt_int_op(ret
, OP_EQ
, 0);
821 trn_cell_introduce1_free(cell
);
823 hs_circuitmap_free_all();
824 UNMOCK(relay_send_command_from_edge_
);
827 struct testcase_t hs_intropoint_tests
[] = {
828 { "intro_point_registration",
829 test_intro_point_registration
, TT_FORK
, NULL
, NULL
},
831 { "receive_establish_intro_wrong_keytype",
832 test_establish_intro_wrong_keytype
, TT_FORK
, NULL
, NULL
},
834 { "receive_establish_intro_wrong_keytype2",
835 test_establish_intro_wrong_keytype2
, TT_FORK
, NULL
, NULL
},
837 { "receive_establish_intro_wrong_purpose",
838 test_establish_intro_wrong_purpose
, TT_FORK
, NULL
, NULL
},
840 { "receive_establish_intro_wrong_sig",
841 test_establish_intro_wrong_sig
, TT_FORK
, NULL
, NULL
},
843 { "receive_establish_intro_wrong_sig_len",
844 test_establish_intro_wrong_sig_len
, TT_FORK
, NULL
, NULL
},
846 { "receive_establish_intro_wrong_auth_key_len",
847 test_establish_intro_wrong_auth_key_len
, TT_FORK
, NULL
, NULL
},
849 { "receive_establish_intro_wrong_mac",
850 test_establish_intro_wrong_mac
, TT_FORK
, NULL
, NULL
},
852 { "introduce1_suitable_circuit",
853 test_introduce1_suitable_circuit
, TT_FORK
, NULL
, NULL
},
855 { "introduce1_is_legacy",
856 test_introduce1_is_legacy
, TT_FORK
, NULL
, NULL
},
858 { "introduce1_validation",
859 test_introduce1_validation
, TT_FORK
, NULL
, NULL
},
861 { "received_introduce1_handling",
862 test_received_introduce1_handling
, TT_FORK
, NULL
, NULL
},