1 /* Copyright (c) 2016-2021, 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"
17 #include "lib/time/compat_time.h"
19 #include "core/or/or.h"
20 #include "core/or/channel.h"
21 #include "core/or/circuitlist.h"
22 #include "core/or/circuituse.h"
24 #include "core/or/relay.h"
26 #include "feature/hs/hs_cell.h"
27 #include "feature/hs/hs_circuitmap.h"
28 #include "feature/hs/hs_common.h"
29 #include "feature/hs/hs_config.h"
30 #include "feature/hs/hs_dos.h"
31 #include "feature/hs/hs_intropoint.h"
32 #include "feature/hs/hs_service.h"
34 #include "core/or/or_circuit_st.h"
37 #include "trunnel/extension.h"
38 #include "trunnel/hs/cell_establish_intro.h"
39 #include "trunnel/hs/cell_introduce1.h"
42 new_establish_intro_cell(const char *circ_nonce
,
43 trn_cell_establish_intro_t
**cell_out
)
46 uint8_t buf
[RELAY_PAYLOAD_SIZE
] = {0};
47 trn_cell_establish_intro_t
*cell
= NULL
;
48 hs_service_intro_point_t
*ip
= NULL
;
49 hs_service_config_t config
;
51 memset(&config
, 0, sizeof(config
));
53 /* Ensure that *cell_out is NULL such that we can use to check if we need to
54 * free `cell` in case of an error. */
57 /* Auth key pair is generated in the constructor so we are all set for
58 * using this IP object. */
59 ip
= service_intro_point_new(NULL
);
61 cell_len
= hs_cell_build_establish_intro(circ_nonce
, &config
, ip
, buf
);
62 tt_i64_op(cell_len
, OP_GT
, 0);
64 cell_len
= trn_cell_establish_intro_parse(&cell
, buf
, sizeof(buf
));
65 tt_i64_op(cell_len
, OP_GT
, 0);
70 if (*cell_out
== NULL
)
71 trn_cell_establish_intro_free(cell
);
73 service_intro_point_free(ip
);
78 new_establish_intro_encoded_cell(const char *circ_nonce
, uint8_t *cell_out
)
81 hs_service_intro_point_t
*ip
= NULL
;
82 hs_service_config_t config
;
84 memset(&config
, 0, sizeof(config
));
86 /* Auth key pair is generated in the constructor so we are all set for
87 * using this IP object. */
88 ip
= service_intro_point_new(NULL
);
90 cell_len
= hs_cell_build_establish_intro(circ_nonce
, &config
, ip
, cell_out
);
91 tt_i64_op(cell_len
, OP_GT
, 0);
94 service_intro_point_free(ip
);
98 /* Mock function to avoid networking in unittests */
100 mock_send_intro_established_cell(or_circuit_t
*circ
)
107 mock_relay_send_command_from_edge(streamid_t stream_id
, circuit_t
*circ
,
108 uint8_t relay_command
, const char *payload
,
110 crypt_path_t
*cpath_layer
,
111 const char *filename
, int lineno
)
115 (void) relay_command
;
124 static or_circuit_t
*
125 helper_create_intro_circuit(void)
127 or_circuit_t
*circ
= or_circuit_new(0, NULL
);
129 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
130 token_bucket_ctr_init(&circ
->introduce2_bucket
, 100, 100,
131 (uint32_t) monotime_coarse_absolute_sec());
136 static trn_cell_introduce1_t
*
137 helper_create_introduce1_cell(void)
139 trn_cell_introduce1_t
*cell
= NULL
;
140 ed25519_keypair_t auth_key_kp
;
142 /* Generate the auth_key of the cell. */
143 if (ed25519_keypair_generate(&auth_key_kp
, 0) < 0) {
147 cell
= trn_cell_introduce1_new();
150 /* Set the auth key. */
152 size_t auth_key_len
= sizeof(auth_key_kp
.pubkey
);
153 trn_cell_introduce1_set_auth_key_type(cell
,
154 TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519
);
155 trn_cell_introduce1_set_auth_key_len(cell
, auth_key_len
);
156 trn_cell_introduce1_setlen_auth_key(cell
, auth_key_len
);
157 uint8_t *auth_key_ptr
= trn_cell_introduce1_getarray_auth_key(cell
);
158 memcpy(auth_key_ptr
, auth_key_kp
.pubkey
.pubkey
, auth_key_len
);
161 /* Set the cell extensions to none. */
163 trn_extension_t
*ext
= trn_extension_new();
164 trn_extension_set_num(ext
, 0);
165 trn_cell_introduce1_set_extensions(cell
, ext
);
168 /* Set the encrypted section to some data. */
170 size_t enc_len
= 128;
171 trn_cell_introduce1_setlen_encrypted(cell
, enc_len
);
172 uint8_t *enc_ptr
= trn_cell_introduce1_getarray_encrypted(cell
);
173 memset(enc_ptr
, 'a', enc_len
);
179 trn_cell_introduce1_free(cell
);
183 /* Try sending an ESTABLISH_INTRO cell on a circuit that is already an intro
184 * point. Should fail. */
186 test_establish_intro_wrong_purpose(void *arg
)
189 ssize_t cell_len
= 0;
190 char circ_nonce
[DIGEST_LEN
] = {0};
191 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
192 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
196 /* Get the auth key of the intro point */
197 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
198 memcpy(intro_circ
->rend_circ_nonce
, circ_nonce
, DIGEST_LEN
);
200 /* Set a bad circuit purpose!! :) */
201 circuit_change_purpose(TO_CIRCUIT(intro_circ
), CIRCUIT_PURPOSE_INTRO_POINT
);
203 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
204 attempt to parse it. */
205 cell_len
= new_establish_intro_encoded_cell(circ_nonce
, cell_body
);
206 tt_i64_op(cell_len
, OP_GT
, 0);
208 /* Receive the cell. Should fail. */
209 setup_full_capture_of_logs(LOG_INFO
);
210 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
211 expect_log_msg_containing("Rejecting ESTABLISH_INTRO on non-OR circuit.");
212 teardown_capture_of_logs();
213 tt_int_op(retval
, OP_EQ
, -1);
216 circuit_free_(TO_CIRCUIT(intro_circ
));
219 /* Prepare a circuit for accepting an ESTABLISH_INTRO cell */
221 helper_prepare_circ_for_intro(or_circuit_t
*circ
, const char *circ_nonce
)
223 /* Prepare the circuit for the incoming ESTABLISH_INTRO */
224 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
225 memcpy(circ
->rend_circ_nonce
, circ_nonce
, DIGEST_LEN
);
228 /* Send an empty ESTABLISH_INTRO cell. Should fail. */
230 test_establish_intro_wrong_keytype(void *arg
)
233 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
234 char circ_nonce
[DIGEST_LEN
] = {0};
238 /* Get the auth key of the intro point */
239 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
240 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
242 /* Receive the cell. Should fail. */
243 setup_full_capture_of_logs(LOG_INFO
);
244 retval
= hs_intro_received_establish_intro(intro_circ
, (uint8_t *) "", 0);
245 expect_log_msg_containing("Empty ESTABLISH_INTRO cell.");
246 teardown_capture_of_logs();
247 tt_int_op(retval
, OP_EQ
, -1);
250 circuit_free_(TO_CIRCUIT(intro_circ
));
253 /* Send an ESTABLISH_INTRO cell with an unknown auth key type. Should fail. */
255 test_establish_intro_wrong_keytype2(void *arg
)
258 char circ_nonce
[DIGEST_LEN
] = {0};
259 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
260 ssize_t cell_len
= 0;
261 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
265 /* Get the auth key of the intro point */
266 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
267 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
269 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
270 * attempt to parse it. */
271 cell_len
= new_establish_intro_encoded_cell(circ_nonce
, cell_body
);
272 tt_i64_op(cell_len
, OP_GT
, 0);
274 /* Mutate the auth key type! :) */
277 /* Receive the cell. Should fail. */
278 setup_full_capture_of_logs(LOG_INFO
);
279 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
280 expect_log_msg_containing("Unrecognized AUTH_KEY_TYPE 42.");
281 teardown_capture_of_logs();
282 tt_int_op(retval
, OP_EQ
, -1);
285 circuit_free_(TO_CIRCUIT(intro_circ
));
288 /* Send a legit ESTABLISH_INTRO cell but with a wrong MAC. Should fail. */
290 test_establish_intro_wrong_mac(void *arg
)
293 char circ_nonce
[DIGEST_LEN
] = {0};
294 ssize_t cell_len
= 0;
295 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
296 trn_cell_establish_intro_t
*cell
= NULL
;
297 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
301 /* Get the auth key of the intro point */
302 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
303 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
305 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
306 * attempt to parse it. */
307 cell_len
= new_establish_intro_cell(circ_nonce
, &cell
);
308 tt_i64_op(cell_len
, OP_GT
, 0);
311 /* Mangle one byte of the MAC. */
312 uint8_t *handshake_ptr
=
313 trn_cell_establish_intro_getarray_handshake_mac(cell
);
314 handshake_ptr
[TRUNNEL_SHA3_256_LEN
- 1]++;
315 /* We need to resign the payload with that change. */
317 ed25519_signature_t sig
;
318 ed25519_keypair_t key_struct
;
319 /* New keypair for the signature since we don't have access to the private
320 * key material generated earlier when creating the cell. */
321 retval
= ed25519_keypair_generate(&key_struct
, 0);
322 tt_int_op(retval
, OP_EQ
, 0);
323 uint8_t *auth_key_ptr
=
324 trn_cell_establish_intro_getarray_auth_key(cell
);
325 memcpy(auth_key_ptr
, key_struct
.pubkey
.pubkey
, ED25519_PUBKEY_LEN
);
326 /* Encode payload so we can sign it. */
327 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
329 tt_i64_op(cell_len
, OP_GT
, 0);
331 retval
= ed25519_sign_prefixed(&sig
, cell_body
,
333 (ED25519_SIG_LEN
+ sizeof(cell
->sig_len
)),
334 ESTABLISH_INTRO_SIG_PREFIX
, &key_struct
);
335 tt_int_op(retval
, OP_EQ
, 0);
336 /* And write the signature to the cell */
338 trn_cell_establish_intro_getarray_sig(cell
);
339 memcpy(sig_ptr
, sig
.sig
, cell
->sig_len
);
340 /* Re-encode with the new signature. */
341 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
343 tt_i64_op(cell_len
, OP_GT
, 0);
346 /* Receive the cell. Should fail because our MAC is wrong. */
347 setup_full_capture_of_logs(LOG_INFO
);
348 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
349 expect_log_msg_containing("ESTABLISH_INTRO handshake_auth not as expected");
350 teardown_capture_of_logs();
351 tt_int_op(retval
, OP_EQ
, -1);
354 trn_cell_establish_intro_free(cell
);
355 circuit_free_(TO_CIRCUIT(intro_circ
));
358 /* Send a legit ESTABLISH_INTRO cell but with a wrong auth key length. Should
361 test_establish_intro_wrong_auth_key_len(void *arg
)
364 char circ_nonce
[DIGEST_LEN
] = {0};
365 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
366 ssize_t cell_len
= 0;
367 size_t bad_auth_key_len
= ED25519_PUBKEY_LEN
- 1;
368 trn_cell_establish_intro_t
*cell
= NULL
;
369 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
373 /* Get the auth key of the intro point */
374 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
375 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
377 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
378 * attempt to parse it. */
379 cell_len
= new_establish_intro_cell(circ_nonce
, &cell
);
380 tt_i64_op(cell_len
, OP_GT
, 0);
383 /* Mangle the auth key length. */
384 trn_cell_establish_intro_set_auth_key_len(cell
, bad_auth_key_len
);
385 trn_cell_establish_intro_setlen_auth_key(cell
, bad_auth_key_len
);
387 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
389 tt_int_op(cell_len
, OP_GT
, 0);
391 /* Receive the cell. Should fail. */
392 setup_full_capture_of_logs(LOG_INFO
);
393 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
394 expect_log_msg_containing("ESTABLISH_INTRO auth key length is invalid");
395 teardown_capture_of_logs();
396 tt_int_op(retval
, OP_EQ
, -1);
399 trn_cell_establish_intro_free(cell
);
400 circuit_free_(TO_CIRCUIT(intro_circ
));
403 /* Send a legit ESTABLISH_INTRO cell but with a wrong sig length. Should
406 test_establish_intro_wrong_sig_len(void *arg
)
409 char circ_nonce
[DIGEST_LEN
] = {0};
410 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
411 ssize_t cell_len
= 0;
412 size_t bad_sig_len
= ED25519_SIG_LEN
- 1;
413 trn_cell_establish_intro_t
*cell
= NULL
;
414 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
418 /* Get the auth key of the intro point */
419 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
420 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
422 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
423 * attempt to parse it. */
424 cell_len
= new_establish_intro_cell(circ_nonce
, &cell
);
425 tt_i64_op(cell_len
, OP_GT
, 0);
428 /* Mangle the signature length. */
429 trn_cell_establish_intro_set_sig_len(cell
, bad_sig_len
);
430 trn_cell_establish_intro_setlen_sig(cell
, bad_sig_len
);
432 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
434 tt_int_op(cell_len
, OP_GT
, 0);
436 /* Receive the cell. Should fail. */
437 setup_full_capture_of_logs(LOG_INFO
);
438 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
, cell_len
);
439 expect_log_msg_containing("ESTABLISH_INTRO sig len is invalid");
440 teardown_capture_of_logs();
441 tt_int_op(retval
, OP_EQ
, -1);
444 trn_cell_establish_intro_free(cell
);
445 circuit_free_(TO_CIRCUIT(intro_circ
));
448 /* Send a legit ESTABLISH_INTRO cell but slightly change the signature. Should
451 test_establish_intro_wrong_sig(void *arg
)
454 char circ_nonce
[DIGEST_LEN
] = {0};
455 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
456 ssize_t cell_len
= 0;
457 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
461 /* Get the auth key of the intro point */
462 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
463 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
465 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
466 attempt to parse it. */
467 cell_len
= new_establish_intro_encoded_cell(circ_nonce
, cell_body
);
468 tt_i64_op(cell_len
, OP_GT
, 0);
470 /* Mutate the last byte (signature)! :) */
471 cell_body
[cell_len
- 1]++;
473 /* Receive the cell. Should fail. */
474 setup_full_capture_of_logs(LOG_INFO
);
475 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
,
477 expect_log_msg_containing("Failed to verify ESTABLISH_INTRO cell.");
478 teardown_capture_of_logs();
479 tt_int_op(retval
, OP_EQ
, -1);
482 circuit_free_(TO_CIRCUIT(intro_circ
));
485 /* Helper function: Send a well-formed v3 ESTABLISH_INTRO cell to
486 * <b>intro_circ</b>. Return the cell. */
487 static trn_cell_establish_intro_t
*
488 helper_establish_intro_v3(or_circuit_t
*intro_circ
)
491 char circ_nonce
[DIGEST_LEN
] = {0};
492 uint8_t cell_body
[RELAY_PAYLOAD_SIZE
];
493 ssize_t cell_len
= 0;
494 trn_cell_establish_intro_t
*cell
= NULL
;
496 tt_assert(intro_circ
);
498 /* Prepare the circuit for the incoming ESTABLISH_INTRO */
499 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
500 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
502 /* Create outgoing ESTABLISH_INTRO cell and extract its payload so that we
503 * attempt to parse it. */
504 cell_len
= new_establish_intro_cell(circ_nonce
, &cell
);
505 tt_i64_op(cell_len
, OP_GT
, 0);
507 cell_len
= trn_cell_establish_intro_encode(cell_body
, sizeof(cell_body
),
509 tt_int_op(cell_len
, OP_GT
, 0);
511 /* Receive the cell */
512 retval
= hs_intro_received_establish_intro(intro_circ
, cell_body
,
514 tt_int_op(retval
, OP_EQ
, 0);
520 /* Helper function: test circuitmap free_all function outside of
521 * test_intro_point_registration to prevent Coverity from seeing a
522 * double free if the assertion hypothetically fails.
525 test_circuitmap_free_all(void)
527 hs_circuitmap_ht
*the_hs_circuitmap
= NULL
;
529 the_hs_circuitmap
= get_hs_circuitmap();
530 tt_assert(the_hs_circuitmap
);
531 hs_circuitmap_free_all();
532 the_hs_circuitmap
= get_hs_circuitmap();
533 tt_ptr_op(the_hs_circuitmap
, OP_EQ
, NULL
);
538 /** Successfully register a v3 intro point. Ensure that HS
539 * circuitmap is maintained properly. */
541 test_intro_point_registration(void *arg
)
543 hs_circuitmap_ht
*the_hs_circuitmap
= NULL
;
545 or_circuit_t
*intro_circ
= NULL
;
546 trn_cell_establish_intro_t
*establish_intro_cell
= NULL
;
547 ed25519_public_key_t auth_key
;
549 or_circuit_t
*returned_intro_circ
= NULL
;
553 MOCK(hs_intro_send_intro_established_cell
, mock_send_intro_established_cell
);
555 hs_circuitmap_init();
557 /* Check that the circuitmap is currently empty */
559 the_hs_circuitmap
= get_hs_circuitmap();
560 tt_assert(the_hs_circuitmap
);
561 tt_int_op(0, OP_EQ
, HT_SIZE(the_hs_circuitmap
));
562 /* Do a circuitmap query in any case */
563 returned_intro_circ
=hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key
);
564 tt_ptr_op(returned_intro_circ
, OP_EQ
, NULL
);
567 /* Create a v3 intro point */
569 intro_circ
= or_circuit_new(0, NULL
);
570 tt_assert(intro_circ
);
571 establish_intro_cell
= helper_establish_intro_v3(intro_circ
);
573 /* Check that the intro point was registered on the HS circuitmap */
574 the_hs_circuitmap
= get_hs_circuitmap();
575 tt_assert(the_hs_circuitmap
);
576 tt_int_op(1, OP_EQ
, HT_SIZE(the_hs_circuitmap
));
577 get_auth_key_from_cell(&auth_key
, RELAY_COMMAND_ESTABLISH_INTRO
,
578 establish_intro_cell
);
579 returned_intro_circ
=
580 hs_circuitmap_get_intro_circ_v3_relay_side(&auth_key
);
581 tt_ptr_op(intro_circ
, OP_EQ
, returned_intro_circ
);
584 /* XXX Continue test and try to register a second v3 intro point with the
585 * same auth key. Make sure that old intro circuit gets closed. */
588 circuit_free_(TO_CIRCUIT(intro_circ
));
589 trn_cell_establish_intro_free(establish_intro_cell
);
590 test_circuitmap_free_all();
592 UNMOCK(hs_intro_send_intro_established_cell
);
596 test_introduce1_suitable_circuit(void *arg
)
599 or_circuit_t
*circ
= NULL
;
603 /* Valid suitable circuit. */
605 circ
= or_circuit_new(0, NULL
);
606 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
607 ret
= circuit_is_suitable_for_introduce1(circ
);
608 circuit_free_(TO_CIRCUIT(circ
));
609 tt_int_op(ret
, OP_EQ
, 1);
612 /* Test if the circuit purpose safeguard works correctly. */
614 circ
= or_circuit_new(0, NULL
);
615 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_INTRO_POINT
);
616 ret
= circuit_is_suitable_for_introduce1(circ
);
617 circuit_free_(TO_CIRCUIT(circ
));
618 tt_int_op(ret
, OP_EQ
, 0);
621 /* Test the non-edge circuit safeguard works correctly. */
623 circ
= or_circuit_new(0, NULL
);
624 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
625 /* Bogus pointer, the check is against NULL on n_chan. */
626 circ
->base_
.n_chan
= (channel_t
*) circ
;
627 ret
= circuit_is_suitable_for_introduce1(circ
);
628 circuit_free_(TO_CIRCUIT(circ
));
629 tt_int_op(ret
, OP_EQ
, 0);
632 /* Mangle the circuit a bit more so see if our only one INTRODUCE1 cell
633 * limit works correctly. */
635 circ
= or_circuit_new(0, NULL
);
636 circuit_change_purpose(TO_CIRCUIT(circ
), CIRCUIT_PURPOSE_OR
);
637 circ
->already_received_introduce1
= 1;
638 ret
= circuit_is_suitable_for_introduce1(circ
);
639 circuit_free_(TO_CIRCUIT(circ
));
640 tt_int_op(ret
, OP_EQ
, 0);
643 /* Single hop circuit should not be allowed. */
645 circ
= or_circuit_new(0, NULL
);
646 circ
->p_chan
= tor_malloc_zero(sizeof(channel_t
));
647 circ
->p_chan
->is_client
= 1;
648 ret
= circuit_is_suitable_for_introduce1(circ
);
649 tor_free(circ
->p_chan
);
650 circuit_free_(TO_CIRCUIT(circ
));
651 tt_int_op(ret
, OP_EQ
, 0);
659 test_introduce1_validation(void *arg
)
662 trn_cell_introduce1_t
*cell
= NULL
;
666 /* Create our decoy cell that we'll modify as we go to test the validation
667 * function of that parsed cell. */
668 cell
= helper_create_introduce1_cell();
671 /* Non existing auth key type. */
672 cell
->auth_key_type
= 42;
673 ret
= validate_introduce1_parsed_cell(cell
);
674 tt_int_op(ret
, OP_EQ
, -1);
675 /* Reset is to correct value and make sure it's correct. */
676 cell
->auth_key_type
= TRUNNEL_HS_INTRO_AUTH_KEY_TYPE_ED25519
;
677 ret
= validate_introduce1_parsed_cell(cell
);
678 tt_int_op(ret
, OP_EQ
, 0);
680 /* Really bad key length. */
681 cell
->auth_key_len
= 0;
682 ret
= validate_introduce1_parsed_cell(cell
);
683 tt_int_op(ret
, OP_EQ
, -1);
684 cell
->auth_key_len
= UINT16_MAX
;
685 ret
= validate_introduce1_parsed_cell(cell
);
686 tt_int_op(ret
, OP_EQ
, -1);
687 /* Correct size, let's try that. */
688 cell
->auth_key_len
= sizeof(ed25519_public_key_t
);
689 ret
= validate_introduce1_parsed_cell(cell
);
690 tt_int_op(ret
, OP_EQ
, 0);
691 /* Set an invalid size of the auth key buffer. */
692 trn_cell_introduce1_setlen_auth_key(cell
, 3);
693 ret
= validate_introduce1_parsed_cell(cell
);
694 tt_int_op(ret
, OP_EQ
, -1);
695 /* Reset auth key buffer and make sure it works. */
696 trn_cell_introduce1_setlen_auth_key(cell
, sizeof(ed25519_public_key_t
));
697 ret
= validate_introduce1_parsed_cell(cell
);
698 tt_int_op(ret
, OP_EQ
, 0);
700 /* Empty encrypted section. */
701 trn_cell_introduce1_setlen_encrypted(cell
, 0);
702 ret
= validate_introduce1_parsed_cell(cell
);
703 tt_int_op(ret
, OP_EQ
, -1);
704 /* Reset it to some non zero bytes and validate. */
705 trn_cell_introduce1_setlen_encrypted(cell
, 1);
706 ret
= validate_introduce1_parsed_cell(cell
);
707 tt_int_op(ret
, OP_EQ
, 0);
710 trn_cell_introduce1_free(cell
);
714 test_received_introduce1_handling(void *arg
)
717 uint8_t *request
= NULL
, buf
[128];
718 trn_cell_introduce1_t
*cell
= NULL
;
719 or_circuit_t
*circ
= NULL
;
723 MOCK(relay_send_command_from_edge_
, mock_relay_send_command_from_edge
);
725 hs_circuitmap_init();
727 /* Too small request length. An INTRODUCE1 expect at the very least a
728 * DIGEST_LEN size. */
730 memset(buf
, 0, sizeof(buf
));
731 circ
= helper_create_intro_circuit();
732 ret
= hs_intro_received_introduce1(circ
, buf
, DIGEST_LEN
- 1);
733 tt_int_op(ret
, OP_EQ
, -1);
734 circuit_free_(TO_CIRCUIT(circ
));
737 /* We have a unit test only for the suitability of a circuit to receive an
738 * INTRODUCE1 cell so from now on we'll only test the handling of a cell. */
742 circ
= helper_create_intro_circuit();
743 uint8_t test
[2]; /* Too small request. */
744 memset(test
, 0, sizeof(test
));
745 ret
= handle_introduce1(circ
, test
, sizeof(test
));
746 tor_free(circ
->p_chan
);
747 circuit_free_(TO_CIRCUIT(circ
));
748 tt_int_op(ret
, OP_EQ
, -1);
753 cell
= helper_create_introduce1_cell();
754 ssize_t request_len
= trn_cell_introduce1_encoded_len(cell
);
755 tt_int_op((int)request_len
, OP_GT
, 0);
756 request
= tor_malloc_zero(request_len
);
757 ssize_t encoded_len
=
758 trn_cell_introduce1_encode(request
, request_len
, cell
);
759 tt_int_op((int)encoded_len
, OP_GT
, 0);
761 circ
= helper_create_intro_circuit();
762 or_circuit_t
*service_circ
= helper_create_intro_circuit();
763 circuit_change_purpose(TO_CIRCUIT(service_circ
),
764 CIRCUIT_PURPOSE_INTRO_POINT
);
765 /* Register the circuit in the map for the auth key of the cell. */
766 ed25519_public_key_t auth_key
;
767 const uint8_t *cell_auth_key
=
768 trn_cell_introduce1_getconstarray_auth_key(cell
);
769 memcpy(auth_key
.pubkey
, cell_auth_key
, ED25519_PUBKEY_LEN
);
770 hs_circuitmap_register_intro_circ_v3_relay_side(service_circ
, &auth_key
);
771 ret
= hs_intro_received_introduce1(circ
, request
, request_len
);
772 circuit_free_(TO_CIRCUIT(circ
));
773 circuit_free_(TO_CIRCUIT(service_circ
));
774 tt_int_op(ret
, OP_EQ
, 0);
778 trn_cell_introduce1_free(cell
);
780 hs_circuitmap_free_all();
781 UNMOCK(relay_send_command_from_edge_
);
785 test_received_establish_intro_dos_ext(void *arg
)
788 ssize_t cell_len
= 0;
789 uint8_t cell
[RELAY_PAYLOAD_SIZE
] = {0};
790 char circ_nonce
[DIGEST_LEN
] = {0};
791 hs_service_intro_point_t
*ip
= NULL
;
792 hs_service_config_t config
;
793 or_circuit_t
*intro_circ
= or_circuit_new(0,NULL
);
797 MOCK(relay_send_command_from_edge_
, mock_relay_send_command_from_edge
);
799 hs_circuitmap_init();
802 crypto_rand(circ_nonce
, sizeof(circ_nonce
));
803 ip
= service_intro_point_new(NULL
);
805 ip
->support_intro2_dos_defense
= 1;
806 memset(&config
, 0, sizeof(config
));
807 config
.has_dos_defense_enabled
= 1;
808 config
.intro_dos_rate_per_sec
= 13;
809 config
.intro_dos_burst_per_sec
= 42;
810 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
811 /* The INTRO2 bucket should be 0 at this point. */
812 tt_u64_op(token_bucket_ctr_get(&intro_circ
->introduce2_bucket
), OP_EQ
, 0);
813 tt_u64_op(intro_circ
->introduce2_bucket
.cfg
.rate
, OP_EQ
, 0);
814 tt_int_op(intro_circ
->introduce2_bucket
.cfg
.burst
, OP_EQ
, 0);
815 tt_int_op(intro_circ
->introduce2_dos_defense_enabled
, OP_EQ
, 0);
817 /* Case 1: Build encoded cell. Usable DoS parameters. */
818 cell_len
= hs_cell_build_establish_intro(circ_nonce
, &config
, ip
, cell
);
819 tt_size_op(cell_len
, OP_GT
, 0);
820 /* Pass it to the intro point. */
821 ret
= hs_intro_received_establish_intro(intro_circ
, cell
, cell_len
);
822 tt_int_op(ret
, OP_EQ
, 0);
823 /* Should be set to the burst value. */
824 tt_u64_op(token_bucket_ctr_get(&intro_circ
->introduce2_bucket
), OP_EQ
, 42);
825 /* Validate the config of the intro2 bucket. */
826 tt_u64_op(intro_circ
->introduce2_bucket
.cfg
.rate
, OP_EQ
, 13);
827 tt_int_op(intro_circ
->introduce2_bucket
.cfg
.burst
, OP_EQ
, 42);
828 tt_int_op(intro_circ
->introduce2_dos_defense_enabled
, OP_EQ
, 1);
830 /* Need to reset the circuit in between test cases. */
831 circuit_free_(TO_CIRCUIT(intro_circ
));
832 intro_circ
= or_circuit_new(0,NULL
);
833 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
835 /* Case 2: Build encoded cell. Bad DoS parameters. */
836 config
.has_dos_defense_enabled
= 1;
837 config
.intro_dos_rate_per_sec
= UINT_MAX
;
838 config
.intro_dos_burst_per_sec
= 13;
839 cell_len
= hs_cell_build_establish_intro(circ_nonce
, &config
, ip
, cell
);
840 tt_size_op(cell_len
, OP_GT
, 0);
841 /* Pass it to the intro point. */
842 ret
= hs_intro_received_establish_intro(intro_circ
, cell
, cell_len
);
843 tt_int_op(ret
, OP_EQ
, 0);
844 tt_u64_op(token_bucket_ctr_get(&intro_circ
->introduce2_bucket
), OP_EQ
,
845 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT
);
846 tt_u64_op(intro_circ
->introduce2_bucket
.cfg
.rate
, OP_EQ
,
847 HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_DEFAULT
);
848 tt_int_op(intro_circ
->introduce2_bucket
.cfg
.burst
, OP_EQ
,
849 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT
);
850 tt_int_op(intro_circ
->introduce2_dos_defense_enabled
, OP_EQ
,
851 HS_CONFIG_V3_DOS_DEFENSE_DEFAULT
);
853 /* Need to reset the circuit in between test cases. */
854 circuit_free_(TO_CIRCUIT(intro_circ
));
855 intro_circ
= or_circuit_new(0,NULL
);
856 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
858 /* Case 3: Build encoded cell. Burst is smaller than rate. Not allowed. */
859 config
.has_dos_defense_enabled
= 1;
860 config
.intro_dos_rate_per_sec
= 87;
861 config
.intro_dos_burst_per_sec
= 45;
862 cell_len
= hs_cell_build_establish_intro(circ_nonce
, &config
, ip
, cell
);
863 tt_size_op(cell_len
, OP_GT
, 0);
864 /* Pass it to the intro point. */
865 ret
= hs_intro_received_establish_intro(intro_circ
, cell
, cell_len
);
866 tt_int_op(ret
, OP_EQ
, 0);
867 tt_u64_op(token_bucket_ctr_get(&intro_circ
->introduce2_bucket
), OP_EQ
,
868 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT
);
869 tt_u64_op(intro_circ
->introduce2_bucket
.cfg
.rate
, OP_EQ
,
870 HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_DEFAULT
);
871 tt_int_op(intro_circ
->introduce2_bucket
.cfg
.burst
, OP_EQ
,
872 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT
);
873 tt_int_op(intro_circ
->introduce2_dos_defense_enabled
, OP_EQ
,
874 HS_CONFIG_V3_DOS_DEFENSE_DEFAULT
);
876 /* Need to reset the circuit in between test cases. */
877 circuit_free_(TO_CIRCUIT(intro_circ
));
878 intro_circ
= or_circuit_new(0,NULL
);
879 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
881 /* Case 4: Build encoded cell. Rate is 0 but burst is not 0. Disables the
883 config
.has_dos_defense_enabled
= 1;
884 config
.intro_dos_rate_per_sec
= 0;
885 config
.intro_dos_burst_per_sec
= 45;
886 cell_len
= hs_cell_build_establish_intro(circ_nonce
, &config
, ip
, cell
);
887 tt_size_op(cell_len
, OP_GT
, 0);
888 /* Pass it to the intro point. */
889 ret
= hs_intro_received_establish_intro(intro_circ
, cell
, cell_len
);
890 tt_int_op(ret
, OP_EQ
, 0);
891 tt_u64_op(token_bucket_ctr_get(&intro_circ
->introduce2_bucket
), OP_EQ
,
892 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT
);
893 tt_u64_op(intro_circ
->introduce2_bucket
.cfg
.rate
, OP_EQ
,
894 HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_DEFAULT
);
895 tt_int_op(intro_circ
->introduce2_bucket
.cfg
.burst
, OP_EQ
,
896 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT
);
897 tt_int_op(intro_circ
->introduce2_dos_defense_enabled
, OP_EQ
,
898 HS_CONFIG_V3_DOS_DEFENSE_DEFAULT
);
900 /* Need to reset the circuit in between test cases. */
901 circuit_free_(TO_CIRCUIT(intro_circ
));
902 intro_circ
= or_circuit_new(0,NULL
);
903 helper_prepare_circ_for_intro(intro_circ
, circ_nonce
);
905 /* Case 5: Build encoded cell. Burst is 0 but rate is not 0. Disables the
907 config
.has_dos_defense_enabled
= 1;
908 config
.intro_dos_rate_per_sec
= 45;
909 config
.intro_dos_burst_per_sec
= 0;
910 cell_len
= hs_cell_build_establish_intro(circ_nonce
, &config
, ip
, cell
);
911 tt_size_op(cell_len
, OP_GT
, 0);
912 /* Pass it to the intro point. */
913 ret
= hs_intro_received_establish_intro(intro_circ
, cell
, cell_len
);
914 tt_int_op(ret
, OP_EQ
, 0);
915 tt_u64_op(token_bucket_ctr_get(&intro_circ
->introduce2_bucket
), OP_EQ
,
916 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT
);
917 tt_u64_op(intro_circ
->introduce2_bucket
.cfg
.rate
, OP_EQ
,
918 HS_CONFIG_V3_DOS_DEFENSE_RATE_PER_SEC_DEFAULT
);
919 tt_int_op(intro_circ
->introduce2_bucket
.cfg
.burst
, OP_EQ
,
920 HS_CONFIG_V3_DOS_DEFENSE_BURST_PER_SEC_DEFAULT
);
921 tt_int_op(intro_circ
->introduce2_dos_defense_enabled
, OP_EQ
,
922 HS_CONFIG_V3_DOS_DEFENSE_DEFAULT
);
925 circuit_free_(TO_CIRCUIT(intro_circ
));
926 service_intro_point_free(ip
);
927 hs_circuitmap_free_all();
928 UNMOCK(relay_send_command_from_edge_
);
932 hs_subsystem_setup_fn(const struct testcase_t
*tc
)
940 hs_subsystem_cleanup_fn(const struct testcase_t
*tc
, void *arg
)
948 static struct testcase_setup_t test_setup
= {
949 hs_subsystem_setup_fn
, hs_subsystem_cleanup_fn
952 struct testcase_t hs_intropoint_tests
[] = {
953 { "intro_point_registration",
954 test_intro_point_registration
, TT_FORK
, NULL
, &test_setup
},
956 { "receive_establish_intro_wrong_keytype",
957 test_establish_intro_wrong_keytype
, TT_FORK
, NULL
, &test_setup
},
959 { "receive_establish_intro_wrong_keytype2",
960 test_establish_intro_wrong_keytype2
, TT_FORK
, NULL
, &test_setup
},
962 { "receive_establish_intro_wrong_purpose",
963 test_establish_intro_wrong_purpose
, TT_FORK
, NULL
, &test_setup
},
965 { "receive_establish_intro_wrong_sig",
966 test_establish_intro_wrong_sig
, TT_FORK
, NULL
, &test_setup
},
968 { "receive_establish_intro_wrong_sig_len",
969 test_establish_intro_wrong_sig_len
, TT_FORK
, NULL
, &test_setup
},
971 { "receive_establish_intro_wrong_auth_key_len",
972 test_establish_intro_wrong_auth_key_len
, TT_FORK
, NULL
, &test_setup
},
974 { "receive_establish_intro_wrong_mac",
975 test_establish_intro_wrong_mac
, TT_FORK
, NULL
, &test_setup
},
977 { "introduce1_suitable_circuit",
978 test_introduce1_suitable_circuit
, TT_FORK
, NULL
, &test_setup
},
980 { "introduce1_validation",
981 test_introduce1_validation
, TT_FORK
, NULL
, &test_setup
},
983 { "received_introduce1_handling",
984 test_received_introduce1_handling
, TT_FORK
, NULL
, &test_setup
},
986 { "received_establish_intro_dos_ext",
987 test_received_establish_intro_dos_ext
, TT_FORK
, NULL
, &test_setup
},