Line data Source code
1 : #define CHANNEL_OBJECT_PRIVATE
2 : #define TOR_TIMERS_PRIVATE
3 : #define CIRCUITPADDING_PRIVATE
4 : #define CIRCUITPADDING_MACHINES_PRIVATE
5 : #define NETWORKSTATUS_PRIVATE
6 : #define CRYPT_PATH_PRIVATE
7 : #define RELAY_PRIVATE
8 :
9 : #include "core/or/or.h"
10 : #include "test/test.h"
11 : #include "test/log_test_helpers.h"
12 : #include "lib/testsupport/testsupport.h"
13 : #include "core/or/connection_or.h"
14 : #include "core/or/channel.h"
15 : #include "core/or/channeltls.h"
16 : #include "core/or/crypt_path.h"
17 : #include <event.h>
18 : #include "lib/evloop/compat_libevent.h"
19 : #include "lib/time/compat_time.h"
20 : #include "lib/defs/time.h"
21 : #include "core/or/relay.h"
22 : #include "core/or/circuitlist.h"
23 : #include "core/or/circuitbuild.h"
24 : #include "core/or/circuitpadding.h"
25 : #include "core/or/circuitpadding_machines.h"
26 : #include "core/or/extendinfo.h"
27 : #include "core/mainloop/netstatus.h"
28 : #include "core/crypto/relay_crypto.h"
29 : #include "core/or/protover.h"
30 : #include "feature/nodelist/nodelist.h"
31 : #include "app/config/config.h"
32 :
33 : #include "feature/nodelist/routerstatus_st.h"
34 : #include "feature/nodelist/networkstatus_st.h"
35 : #include "feature/nodelist/node_st.h"
36 : #include "core/or/cell_st.h"
37 : #include "core/or/crypt_path_st.h"
38 : #include "core/or/or_circuit_st.h"
39 : #include "core/or/origin_circuit_st.h"
40 :
41 : #include "test/fakecircs.h"
42 : #include "test/rng_test_helpers.h"
43 :
44 : /* Start our monotime mocking at 1 second past whatever monotime_init()
45 : * thought the actual wall clock time was, for platforms with bad resolution
46 : * and weird timevalues during monotime_init() before mocking. */
47 : #define MONOTIME_MOCK_START (monotime_absolute_nsec()+\
48 : TOR_NSEC_PER_USEC*TOR_USEC_PER_SEC)
49 :
50 : extern smartlist_t *connection_array;
51 : void circuit_expire_old_circuits_clientside(void);
52 :
53 : circid_t get_unique_circ_id_by_chan(channel_t *chan);
54 : void helper_create_basic_machine(void);
55 : static void helper_create_conditional_machines(void);
56 :
57 : channel_t *new_fake_channel(void);
58 : void test_circuitpadding_negotiation(void *arg);
59 : void test_circuitpadding_wronghop(void *arg);
60 : void test_circuitpadding_conditions(void *arg);
61 :
62 : void test_circuitpadding_serialize(void *arg);
63 : void test_circuitpadding_rtt(void *arg);
64 : void test_circuitpadding_tokens(void *arg);
65 : void test_circuitpadding_state_length(void *arg);
66 :
67 : static void
68 : simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay,
69 : int padding);
70 : void free_fake_origin_circuit(origin_circuit_t *circ);
71 :
72 : static int deliver_negotiated = 1;
73 : static int64_t curr_mocked_time;
74 :
75 : static node_t padding_node;
76 : static node_t non_padding_node;
77 :
78 : static channel_t dummy_channel;
79 : static circpad_machine_spec_t circ_client_machine;
80 :
81 : static void
82 168 : timers_advance_and_run(int64_t msec_update)
83 : {
84 168 : curr_mocked_time += msec_update*TOR_NSEC_PER_MSEC;
85 168 : monotime_coarse_set_mock_time_nsec(curr_mocked_time);
86 168 : monotime_set_mock_time_nsec(curr_mocked_time);
87 168 : timers_run_pending();
88 168 : }
89 :
90 : static void
91 6 : nodes_init(void)
92 : {
93 6 : padding_node.rs = tor_malloc_zero(sizeof(routerstatus_t));
94 6 : padding_node.rs->pv.supports_hs_setup_padding = 1;
95 :
96 6 : non_padding_node.rs = tor_malloc_zero(sizeof(routerstatus_t));
97 6 : non_padding_node.rs->pv.supports_hs_setup_padding = 0;
98 6 : }
99 :
100 : static void
101 2 : nodes_free(void)
102 : {
103 2 : tor_free(padding_node.rs);
104 :
105 2 : tor_free(non_padding_node.rs);
106 2 : }
107 :
108 : static const node_t *
109 20 : node_get_by_id_mock(const char *identity_digest)
110 : {
111 20 : if (identity_digest[0] == 1) {
112 : return &padding_node;
113 3 : } else if (identity_digest[0] == 0) {
114 3 : return &non_padding_node;
115 : }
116 :
117 : return NULL;
118 : }
119 :
120 : static const node_t *
121 2 : circuit_get_nth_node_mock(origin_circuit_t *circ, int hop)
122 : {
123 2 : (void) circ;
124 2 : (void) hop;
125 :
126 2 : return &padding_node;
127 : }
128 :
129 : void
130 17 : free_fake_origin_circuit(origin_circuit_t *circ)
131 : {
132 17 : circpad_circuit_free_all_machineinfos(TO_CIRCUIT(circ));
133 17 : circuit_clear_cpath(circ);
134 17 : tor_free(circ);
135 17 : }
136 :
137 : void dummy_nop_timer(void);
138 :
139 : //static int dont_stop_libevent = 0;
140 :
141 : static circuit_t *client_side;
142 : static circuit_t *relay_side;
143 :
144 : static int n_client_cells = 0;
145 : static int n_relay_cells = 0;
146 :
147 : static int
148 : circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ,
149 : cell_direction_t cell_direction,
150 : crypt_path_t *layer_hint, streamid_t on_stream,
151 : const char *filename, int lineno);
152 :
153 : static void
154 : circuitmux_attach_circuit_mock(circuitmux_t *cmux, circuit_t *circ,
155 : cell_direction_t direction);
156 :
157 : static void
158 24 : circuitmux_attach_circuit_mock(circuitmux_t *cmux, circuit_t *circ,
159 : cell_direction_t direction)
160 : {
161 24 : (void)cmux;
162 24 : (void)circ;
163 24 : (void)direction;
164 :
165 24 : return;
166 : }
167 :
168 : static int
169 164 : circuit_package_relay_cell_mock(cell_t *cell, circuit_t *circ,
170 : cell_direction_t cell_direction,
171 : crypt_path_t *layer_hint, streamid_t on_stream,
172 : const char *filename, int lineno)
173 : {
174 164 : (void)cell; (void)on_stream; (void)filename; (void)lineno;
175 :
176 164 : if (circ == client_side) {
177 32 : if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATE) {
178 : // Deliver to relay
179 19 : circpad_handle_padding_negotiate(relay_side, cell);
180 : } else {
181 :
182 13 : int is_target_hop = circpad_padding_is_from_expected_hop(circ,
183 : layer_hint);
184 13 : tt_int_op(cell_direction, OP_EQ, CELL_DIRECTION_OUT);
185 13 : tt_int_op(is_target_hop, OP_EQ, 1);
186 :
187 : // No need to pretend a padding cell was sent: This event is
188 : // now emitted internally when the circuitpadding code sends them.
189 : //circpad_cell_event_padding_sent(client_side);
190 :
191 : // Receive padding cell at middle
192 13 : circpad_deliver_recognized_relay_cell_events(relay_side,
193 13 : cell->payload[0], NULL);
194 : }
195 32 : n_client_cells++;
196 132 : } else if (circ == relay_side) {
197 132 : tt_int_op(cell_direction, OP_EQ, CELL_DIRECTION_IN);
198 :
199 132 : if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATED) {
200 : // XXX: blah need right layer_hint..
201 22 : if (deliver_negotiated)
202 40 : circpad_handle_padding_negotiated(client_side, cell,
203 20 : TO_ORIGIN_CIRCUIT(client_side)
204 20 : ->cpath->next);
205 110 : } else if (cell->payload[0] == RELAY_COMMAND_PADDING_NEGOTIATE) {
206 1 : circpad_handle_padding_negotiate(client_side, cell);
207 : } else {
208 : // No need to pretend a padding cell was sent: This event is
209 : // now emitted internally when the circuitpadding code sends them.
210 : //circpad_cell_event_padding_sent(relay_side);
211 :
212 : // Receive padding cell at client
213 218 : circpad_deliver_recognized_relay_cell_events(client_side,
214 109 : cell->payload[0],
215 109 : TO_ORIGIN_CIRCUIT(client_side)->cpath->next);
216 : }
217 :
218 132 : n_relay_cells++;
219 : }
220 :
221 0 : done:
222 164 : timers_advance_and_run(1);
223 164 : return 0;
224 : }
225 :
226 : // Test reading and writing padding to strings (or options_t + consensus)
227 : void
228 0 : test_circuitpadding_serialize(void *arg)
229 : {
230 0 : (void)arg;
231 0 : }
232 :
233 : static signed_error_t
234 65554 : circpad_send_command_to_hop_mock(origin_circuit_t *circ, uint8_t hopnum,
235 : uint8_t relay_command, const uint8_t *payload,
236 : ssize_t payload_len)
237 : {
238 65554 : (void) circ;
239 65554 : (void) hopnum;
240 65554 : (void) relay_command;
241 65554 : (void) payload;
242 65554 : (void) payload_len;
243 65554 : return 0;
244 : }
245 :
246 : void
247 1 : test_circuitpadding_rtt(void *arg)
248 : {
249 : /* Test Plan:
250 : *
251 : * 1. Test RTT measurement server side
252 : * a. test usage of measured RTT
253 : * 2. Test termination of RTT measurement
254 : * a. test non-update of RTT
255 : * 3. Test client side circuit and non-application of RTT..
256 : */
257 1 : circpad_delay_t rtt_estimate;
258 1 : int64_t actual_mocked_monotime_start;
259 1 : (void)arg;
260 :
261 1 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
262 1 : MOCK(circpad_send_command_to_hop, circpad_send_command_to_hop_mock);
263 1 : testing_enable_reproducible_rng();
264 :
265 1 : dummy_channel.cmux = circuitmux_alloc();
266 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
267 1 : client_side = TO_CIRCUIT(origin_circuit_new());
268 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
269 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
270 :
271 1 : monotime_init();
272 1 : monotime_enable_test_mocking();
273 1 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
274 1 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
275 1 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
276 1 : curr_mocked_time = actual_mocked_monotime_start;
277 :
278 1 : timers_initialize();
279 1 : circpad_machines_init();
280 1 : helper_create_basic_machine();
281 :
282 1 : MOCK(circuit_package_relay_cell,
283 : circuit_package_relay_cell_mock);
284 :
285 1 : client_side->padding_machine[0] = &circ_client_machine;
286 1 : client_side->padding_info[0] = circpad_circuit_machineinfo_new(client_side,
287 : 0);
288 :
289 1 : relay_side->padding_machine[0] = &circ_client_machine;
290 1 : relay_side->padding_info[0] = circpad_circuit_machineinfo_new(client_side,0);
291 :
292 : /* Test 1: Test measuring RTT */
293 1 : circpad_cell_event_nonpadding_received(relay_side);
294 1 : tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_NE, 0);
295 :
296 1 : timers_advance_and_run(20);
297 :
298 1 : circpad_cell_event_nonpadding_sent(relay_side);
299 1 : tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_EQ, 0);
300 :
301 1 : tt_int_op(relay_side->padding_info[0]->rtt_estimate_usec, OP_GE, 19000);
302 1 : tt_int_op(relay_side->padding_info[0]->rtt_estimate_usec, OP_LE, 30000);
303 1 : tt_int_op(circpad_histogram_bin_to_usec(relay_side->padding_info[0], 0),
304 : OP_EQ,
305 : relay_side->padding_info[0]->rtt_estimate_usec+
306 : circpad_machine_current_state(
307 : relay_side->padding_info[0])->histogram_edges[0]);
308 :
309 1 : circpad_cell_event_nonpadding_received(relay_side);
310 1 : circpad_cell_event_nonpadding_received(relay_side);
311 1 : tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_NE, 0);
312 1 : timers_advance_and_run(20);
313 1 : circpad_cell_event_nonpadding_sent(relay_side);
314 1 : circpad_cell_event_nonpadding_sent(relay_side);
315 1 : tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_EQ, 0);
316 :
317 1 : tt_int_op(relay_side->padding_info[0]->rtt_estimate_usec, OP_GE, 20000);
318 1 : tt_int_op(relay_side->padding_info[0]->rtt_estimate_usec, OP_LE, 21000);
319 1 : tt_int_op(circpad_histogram_bin_to_usec(relay_side->padding_info[0], 0),
320 : OP_EQ,
321 : relay_side->padding_info[0]->rtt_estimate_usec+
322 : circpad_machine_current_state(
323 : relay_side->padding_info[0])->histogram_edges[0]);
324 :
325 : /* Test 2: Termination of RTT measurement (from the previous test) */
326 1 : tt_int_op(relay_side->padding_info[0]->stop_rtt_update, OP_EQ, 1);
327 1 : rtt_estimate = relay_side->padding_info[0]->rtt_estimate_usec;
328 :
329 1 : circpad_cell_event_nonpadding_received(relay_side);
330 1 : timers_advance_and_run(4);
331 1 : circpad_cell_event_nonpadding_sent(relay_side);
332 :
333 1 : tt_int_op(relay_side->padding_info[0]->rtt_estimate_usec, OP_EQ,
334 : rtt_estimate);
335 1 : tt_u64_op(relay_side->padding_info[0]->last_received_time_usec, OP_EQ, 0);
336 1 : tt_int_op(relay_side->padding_info[0]->stop_rtt_update, OP_EQ, 1);
337 1 : tt_int_op(circpad_histogram_bin_to_usec(relay_side->padding_info[0], 0),
338 : OP_EQ,
339 : relay_side->padding_info[0]->rtt_estimate_usec+
340 : circpad_machine_current_state(
341 : relay_side->padding_info[0])->histogram_edges[0]);
342 :
343 : /* Test 3: Make sure client side machine properly ignores RTT */
344 1 : circpad_cell_event_nonpadding_received(client_side);
345 1 : tt_u64_op(client_side->padding_info[0]->last_received_time_usec, OP_EQ, 0);
346 :
347 1 : timers_advance_and_run(20);
348 1 : circpad_cell_event_nonpadding_sent(client_side);
349 1 : tt_u64_op(client_side->padding_info[0]->last_received_time_usec, OP_EQ, 0);
350 :
351 1 : tt_int_op(client_side->padding_info[0]->rtt_estimate_usec, OP_EQ, 0);
352 1 : tt_int_op(circpad_histogram_bin_to_usec(client_side->padding_info[0], 0),
353 : OP_NE, client_side->padding_info[0]->rtt_estimate_usec);
354 1 : tt_int_op(circpad_histogram_bin_to_usec(client_side->padding_info[0], 0),
355 : OP_EQ,
356 : circpad_machine_current_state(
357 : client_side->padding_info[0])->histogram_edges[0]);
358 1 : done:
359 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
360 1 : circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
361 1 : circuitmux_free(dummy_channel.cmux);
362 1 : timers_shutdown();
363 1 : monotime_disable_test_mocking();
364 1 : UNMOCK(circuit_package_relay_cell);
365 1 : UNMOCK(circuitmux_attach_circuit);
366 1 : tor_free(circ_client_machine.states);
367 1 : testing_disable_reproducible_rng();
368 :
369 1 : return;
370 : }
371 :
372 : void
373 4 : helper_create_basic_machine(void)
374 : {
375 : /* Start, burst */
376 4 : circpad_machine_states_init(&circ_client_machine, 2);
377 :
378 4 : circ_client_machine.name = "basic";
379 :
380 4 : circ_client_machine.states[CIRCPAD_STATE_START].
381 4 : next_state[CIRCPAD_EVENT_NONPADDING_RECV] = CIRCPAD_STATE_BURST;
382 4 : circ_client_machine.states[CIRCPAD_STATE_START].use_rtt_estimate = 1;
383 :
384 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].
385 4 : next_state[CIRCPAD_EVENT_PADDING_RECV] = CIRCPAD_STATE_BURST;
386 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].
387 4 : next_state[CIRCPAD_EVENT_NONPADDING_RECV] = CIRCPAD_STATE_BURST;
388 :
389 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].
390 4 : next_state[CIRCPAD_EVENT_NONPADDING_SENT] = CIRCPAD_STATE_CANCEL;
391 :
392 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].token_removal =
393 : CIRCPAD_TOKEN_REMOVAL_HIGHER;
394 :
395 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_len = 5;
396 :
397 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[0] = 500;
398 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[1] = 2500;
399 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[2] = 5000;
400 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[3] = 10000;
401 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[4] = 20000;
402 :
403 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram[0] = 1;
404 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram[1] = 0;
405 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram[2] = 2;
406 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram[3] = 2;
407 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram[4] = 2;
408 :
409 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_total_tokens = 7;
410 4 : circ_client_machine.states[CIRCPAD_STATE_BURST].use_rtt_estimate = 1;
411 :
412 4 : return;
413 : }
414 :
415 : #define BIG_HISTOGRAM_LEN 10
416 :
417 : /** Setup a machine with a big histogram */
418 : static void
419 5 : helper_create_machine_with_big_histogram(circpad_removal_t removal_strategy)
420 : {
421 5 : const int tokens_per_bin = 2;
422 :
423 : /* Start, burst */
424 5 : circpad_machine_states_init(&circ_client_machine, 2);
425 :
426 5 : circpad_state_t *burst_state =
427 5 : &circ_client_machine.states[CIRCPAD_STATE_BURST];
428 :
429 5 : circ_client_machine.states[CIRCPAD_STATE_START].
430 5 : next_state[CIRCPAD_EVENT_NONPADDING_RECV] = CIRCPAD_STATE_BURST;
431 :
432 5 : burst_state->next_state[CIRCPAD_EVENT_PADDING_RECV] = CIRCPAD_STATE_BURST;
433 5 : burst_state->next_state[CIRCPAD_EVENT_NONPADDING_RECV] =CIRCPAD_STATE_BURST;
434 :
435 5 : burst_state->next_state[CIRCPAD_EVENT_NONPADDING_SENT] =CIRCPAD_STATE_CANCEL;
436 :
437 5 : burst_state->token_removal = CIRCPAD_TOKEN_REMOVAL_HIGHER;
438 :
439 5 : burst_state->histogram_len = BIG_HISTOGRAM_LEN;
440 :
441 5 : int n_tokens = 0;
442 5 : int i;
443 55 : for (i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
444 50 : burst_state->histogram[i] = tokens_per_bin;
445 50 : n_tokens += tokens_per_bin;
446 : }
447 :
448 5 : burst_state->histogram_edges[0] = 0;
449 5 : burst_state->histogram_edges[1] = 1;
450 5 : burst_state->histogram_edges[2] = 7;
451 5 : burst_state->histogram_edges[3] = 15;
452 5 : burst_state->histogram_edges[4] = 31;
453 5 : burst_state->histogram_edges[5] = 62;
454 5 : burst_state->histogram_edges[6] = 125;
455 5 : burst_state->histogram_edges[7] = 250;
456 5 : burst_state->histogram_edges[8] = 500;
457 5 : burst_state->histogram_edges[9] = 1000;
458 :
459 5 : burst_state->histogram_total_tokens = n_tokens;
460 5 : burst_state->length_dist.type = CIRCPAD_DIST_UNIFORM;
461 5 : burst_state->length_dist.param1 = n_tokens;
462 5 : burst_state->length_dist.param2 = n_tokens;
463 5 : burst_state->max_length = n_tokens;
464 5 : burst_state->length_includes_nonpadding = 1;
465 5 : burst_state->use_rtt_estimate = 0;
466 5 : burst_state->token_removal = removal_strategy;
467 5 : }
468 :
469 : static circpad_decision_t
470 29 : circpad_machine_schedule_padding_mock(circpad_machine_runtime_t *mi)
471 : {
472 29 : (void)mi;
473 29 : return 0;
474 : }
475 :
476 : static uint64_t
477 74 : mock_monotime_absolute_usec(void)
478 : {
479 74 : return 100;
480 : }
481 :
482 : /** Test higher token removal strategy by bin */
483 : static void
484 1 : test_circuitpadding_token_removal_higher(void *arg)
485 : {
486 1 : circpad_machine_runtime_t *mi;
487 1 : (void)arg;
488 :
489 : /* Mock it up */
490 1 : MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
491 1 : MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
492 1 : testing_enable_reproducible_rng();
493 :
494 : /* Setup test environment (time etc.) */
495 1 : client_side = TO_CIRCUIT(origin_circuit_new());
496 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
497 1 : monotime_enable_test_mocking();
498 :
499 : /* Create test machine */
500 1 : helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_HIGHER);
501 1 : client_side->padding_machine[0] = &circ_client_machine;
502 2 : client_side->padding_info[0] =
503 1 : circpad_circuit_machineinfo_new(client_side, 0);
504 :
505 : /* move the machine to the right state */
506 1 : circpad_cell_event_nonpadding_received(client_side);
507 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
508 : CIRCPAD_STATE_BURST);
509 :
510 : /* Get the machine and setup tokens */
511 1 : mi = client_side->padding_info[0];
512 1 : tt_assert(mi);
513 :
514 : /*************************************************************************/
515 :
516 1 : uint64_t current_time = monotime_absolute_usec();
517 :
518 : /* Test left boundaries of each histogram bin: */
519 1 : const circpad_delay_t bin_left_bounds[] =
520 : {0, 1, 7, 15, 31, 62, 125, 250, 500, 1000, CIRCPAD_DELAY_INFINITE};
521 12 : for (int i = 0; i <= BIG_HISTOGRAM_LEN ; i++) {
522 11 : tt_uint_op(bin_left_bounds[i], OP_EQ,
523 : circpad_histogram_bin_to_usec(mi, i));
524 : }
525 :
526 : /* Test right boundaries of each histogram bin: */
527 1 : const circpad_delay_t bin_right_bounds[] =
528 : {0, 6, 14, 30, 61, 124, 249, 499, 999, CIRCPAD_DELAY_INFINITE-1};
529 11 : for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
530 10 : tt_uint_op(bin_right_bounds[i], OP_EQ,
531 : histogram_get_bin_upper_bound(mi, i));
532 : }
533 :
534 : /* Check that all bins have two tokens right now */
535 11 : for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
536 10 : tt_int_op(mi->histogram[i], OP_EQ, 2);
537 : }
538 :
539 : /* This is the right order to remove tokens from this histogram. That is, we
540 : * first remove tokens from the 4th bin since 57 usec is nearest to the 4th
541 : * bin midpoint (31 + (62-31)/2 == 46). Then we remove from the 3rd bin for
542 : * the same reason, then from the 5th, etc. */
543 1 : const int bin_removal_order[] = {4, 5, 6, 7, 8};
544 1 : unsigned i;
545 :
546 : /* Remove all tokens from all bins apart from the infinity bin */
547 6 : for (i = 0; i < sizeof(bin_removal_order)/sizeof(int) ; i++) {
548 5 : int bin_to_remove = bin_removal_order[i];
549 5 : log_debug(LD_GENERAL, "Testing that %d attempt removes %d bin",
550 : i, bin_to_remove);
551 :
552 5 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 2);
553 :
554 5 : mi->padding_scheduled_at_usec = current_time - 57;
555 5 : circpad_cell_event_nonpadding_sent(client_side);
556 :
557 5 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 1);
558 :
559 5 : mi->padding_scheduled_at_usec = current_time - 57;
560 5 : circpad_cell_event_nonpadding_sent(client_side);
561 :
562 : /* Test that we cleaned out this bin. Don't do this in the case of the last
563 : bin since the tokens will get refilled */
564 5 : if (i != BIG_HISTOGRAM_LEN - 2) {
565 5 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 0);
566 : }
567 : }
568 :
569 : /* Check that all lower bins are not touched */
570 5 : for (i=0; i < 4 ; i++) {
571 4 : tt_int_op(mi->histogram[i], OP_EQ, 2);
572 : }
573 :
574 : /* Test below the lowest bin, for coverage */
575 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
576 : CIRCPAD_STATE_BURST);
577 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[0] = 100;
578 1 : mi->padding_scheduled_at_usec = current_time;
579 1 : circpad_cell_event_nonpadding_sent(client_side);
580 1 : tt_int_op(mi->histogram[0], OP_EQ, 1);
581 :
582 1 : done:
583 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
584 1 : monotime_disable_test_mocking();
585 1 : tor_free(circ_client_machine.states);
586 1 : testing_disable_reproducible_rng();
587 1 : }
588 :
589 : /** Test lower token removal strategy by bin */
590 : static void
591 1 : test_circuitpadding_token_removal_lower(void *arg)
592 : {
593 1 : circpad_machine_runtime_t *mi;
594 1 : (void)arg;
595 :
596 : /* Mock it up */
597 1 : MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
598 1 : MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
599 1 : testing_enable_reproducible_rng();
600 :
601 : /* Setup test environment (time etc.) */
602 1 : client_side = TO_CIRCUIT(origin_circuit_new());
603 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
604 1 : monotime_enable_test_mocking();
605 :
606 : /* Create test machine */
607 1 : helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_LOWER);
608 1 : client_side->padding_machine[0] = &circ_client_machine;
609 2 : client_side->padding_info[0] =
610 1 : circpad_circuit_machineinfo_new(client_side, 0);
611 :
612 : /* move the machine to the right state */
613 1 : circpad_cell_event_nonpadding_received(client_side);
614 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
615 : CIRCPAD_STATE_BURST);
616 :
617 : /* Get the machine and setup tokens */
618 1 : mi = client_side->padding_info[0];
619 1 : tt_assert(mi);
620 :
621 : /*************************************************************************/
622 :
623 1 : uint64_t current_time = monotime_absolute_usec();
624 :
625 : /* Test left boundaries of each histogram bin: */
626 1 : const circpad_delay_t bin_left_bounds[] =
627 : {0, 1, 7, 15, 31, 62, 125, 250, 500, 1000, CIRCPAD_DELAY_INFINITE};
628 12 : for (int i = 0; i <= BIG_HISTOGRAM_LEN ; i++) {
629 11 : tt_uint_op(bin_left_bounds[i], OP_EQ,
630 : circpad_histogram_bin_to_usec(mi, i));
631 : }
632 :
633 : /* Check that all bins have two tokens right now */
634 11 : for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
635 10 : tt_int_op(mi->histogram[i], OP_EQ, 2);
636 : }
637 :
638 : /* This is the right order to remove tokens from this histogram. That is, we
639 : * first remove tokens from the 4th bin since 57 usec is nearest to the 4th
640 : * bin midpoint (31 + (62-31)/2 == 46). Then we remove from the 3rd bin for
641 : * the same reason, then from the 5th, etc. */
642 1 : const int bin_removal_order[] = {4, 3, 2, 1, 0};
643 1 : unsigned i;
644 :
645 : /* Remove all tokens from all bins apart from the infinity bin */
646 6 : for (i = 0; i < sizeof(bin_removal_order)/sizeof(int) ; i++) {
647 5 : int bin_to_remove = bin_removal_order[i];
648 5 : log_debug(LD_GENERAL, "Testing that %d attempt removes %d bin",
649 : i, bin_to_remove);
650 :
651 5 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 2);
652 :
653 5 : mi->padding_scheduled_at_usec = current_time - 57;
654 5 : circpad_cell_event_nonpadding_sent(client_side);
655 :
656 5 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 1);
657 :
658 5 : mi->padding_scheduled_at_usec = current_time - 57;
659 5 : circpad_cell_event_nonpadding_sent(client_side);
660 :
661 : /* Test that we cleaned out this bin. Don't do this in the case of the last
662 : bin since the tokens will get refilled */
663 5 : if (i != BIG_HISTOGRAM_LEN - 2) {
664 5 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 0);
665 : }
666 : }
667 :
668 : /* Check that all higher bins are untouched */
669 6 : for (i = 5; i < BIG_HISTOGRAM_LEN ; i++) {
670 5 : tt_int_op(mi->histogram[i], OP_EQ, 2);
671 : }
672 :
673 : /* Test above the highest bin, for coverage */
674 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
675 : CIRCPAD_STATE_BURST);
676 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].
677 1 : histogram_edges[BIG_HISTOGRAM_LEN-2] = 100;
678 1 : mi->padding_scheduled_at_usec = current_time - 29202;
679 1 : circpad_cell_event_nonpadding_sent(client_side);
680 1 : tt_int_op(mi->histogram[BIG_HISTOGRAM_LEN-2], OP_EQ, 1);
681 :
682 1 : done:
683 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
684 1 : monotime_disable_test_mocking();
685 1 : tor_free(circ_client_machine.states);
686 1 : testing_disable_reproducible_rng();
687 1 : }
688 :
689 : /** Test closest token removal strategy by bin */
690 : static void
691 1 : test_circuitpadding_closest_token_removal(void *arg)
692 : {
693 1 : circpad_machine_runtime_t *mi;
694 1 : (void)arg;
695 :
696 : /* Mock it up */
697 1 : MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
698 1 : MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
699 1 : testing_enable_reproducible_rng();
700 :
701 : /* Setup test environment (time etc.) */
702 1 : client_side = TO_CIRCUIT(origin_circuit_new());
703 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
704 1 : monotime_enable_test_mocking();
705 :
706 : /* Create test machine */
707 1 : helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_CLOSEST);
708 1 : client_side->padding_machine[0] = &circ_client_machine;
709 2 : client_side->padding_info[0] =
710 1 : circpad_circuit_machineinfo_new(client_side, 0);
711 :
712 : /* move the machine to the right state */
713 1 : circpad_cell_event_nonpadding_received(client_side);
714 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
715 : CIRCPAD_STATE_BURST);
716 :
717 : /* Get the machine and setup tokens */
718 1 : mi = client_side->padding_info[0];
719 1 : tt_assert(mi);
720 :
721 : /*************************************************************************/
722 :
723 1 : uint64_t current_time = monotime_absolute_usec();
724 :
725 : /* Test left boundaries of each histogram bin: */
726 1 : const circpad_delay_t bin_left_bounds[] =
727 : {0, 1, 7, 15, 31, 62, 125, 250, 500, 1000, CIRCPAD_DELAY_INFINITE};
728 12 : for (int i = 0; i <= BIG_HISTOGRAM_LEN ; i++) {
729 11 : tt_uint_op(bin_left_bounds[i], OP_EQ,
730 : circpad_histogram_bin_to_usec(mi, i));
731 : }
732 :
733 : /* Check that all bins have two tokens right now */
734 11 : for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
735 10 : tt_int_op(mi->histogram[i], OP_EQ, 2);
736 : }
737 :
738 : /* This is the right order to remove tokens from this histogram. That is, we
739 : * first remove tokens from the 4th bin since 57 usec is nearest to the 4th
740 : * bin midpoint (31 + (62-31)/2 == 46). Then we remove from the 3rd bin for
741 : * the same reason, then from the 5th, etc. */
742 1 : const int bin_removal_order[] = {4, 3, 5, 2, 6, 1, 7, 0, 8, 9};
743 :
744 : /* Remove all tokens from all bins apart from the infinity bin */
745 10 : for (int i = 0; i < BIG_HISTOGRAM_LEN-1 ; i++) {
746 9 : int bin_to_remove = bin_removal_order[i];
747 9 : log_debug(LD_GENERAL, "Testing that %d attempt removes %d bin",
748 : i, bin_to_remove);
749 :
750 9 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 2);
751 :
752 9 : mi->padding_scheduled_at_usec = current_time - 57;
753 9 : circpad_cell_event_nonpadding_sent(client_side);
754 :
755 9 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 1);
756 :
757 9 : mi->padding_scheduled_at_usec = current_time - 57;
758 9 : circpad_cell_event_nonpadding_sent(client_side);
759 :
760 : /* Test that we cleaned out this bin. Don't do this in the case of the last
761 : bin since the tokens will get refilled */
762 9 : if (i != BIG_HISTOGRAM_LEN - 2) {
763 9 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 0);
764 : }
765 : }
766 :
767 : /* Check that all bins have been refilled */
768 11 : for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
769 10 : tt_int_op(mi->histogram[i], OP_EQ, 2);
770 : }
771 :
772 : /* Test below the lowest bin, for coverage */
773 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
774 : CIRCPAD_STATE_BURST);
775 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[0] = 100;
776 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[1] = 101;
777 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[2] = 120;
778 1 : mi->padding_scheduled_at_usec = current_time - 102;
779 1 : mi->histogram[0] = 0;
780 1 : circpad_cell_event_nonpadding_sent(client_side);
781 1 : tt_int_op(mi->histogram[1], OP_EQ, 1);
782 :
783 : /* Test above the highest bin, for coverage */
784 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
785 : CIRCPAD_STATE_BURST);
786 1 : mi->padding_scheduled_at_usec = current_time - 29202;
787 1 : circpad_cell_event_nonpadding_sent(client_side);
788 1 : tt_int_op(mi->histogram[BIG_HISTOGRAM_LEN-2], OP_EQ, 1);
789 :
790 1 : done:
791 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
792 1 : monotime_disable_test_mocking();
793 1 : tor_free(circ_client_machine.states);
794 1 : testing_disable_reproducible_rng();
795 1 : }
796 :
797 : /** Test closest token removal strategy with usec */
798 : static void
799 1 : test_circuitpadding_closest_token_removal_usec(void *arg)
800 : {
801 1 : circpad_machine_runtime_t *mi;
802 1 : (void)arg;
803 :
804 : /* Mock it up */
805 1 : MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
806 1 : MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
807 1 : testing_enable_reproducible_rng();
808 :
809 : /* Setup test environment (time etc.) */
810 1 : client_side = TO_CIRCUIT(origin_circuit_new());
811 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
812 1 : monotime_enable_test_mocking();
813 :
814 : /* Create test machine */
815 1 : helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_CLOSEST_USEC);
816 1 : client_side->padding_machine[0] = &circ_client_machine;
817 2 : client_side->padding_info[0] =
818 1 : circpad_circuit_machineinfo_new(client_side, 0);
819 :
820 : /* move the machine to the right state */
821 1 : circpad_cell_event_nonpadding_received(client_side);
822 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
823 : CIRCPAD_STATE_BURST);
824 :
825 : /* Get the machine and setup tokens */
826 1 : mi = client_side->padding_info[0];
827 1 : tt_assert(mi);
828 :
829 : /*************************************************************************/
830 :
831 1 : uint64_t current_time = monotime_absolute_usec();
832 :
833 : /* Test left boundaries of each histogram bin: */
834 1 : const circpad_delay_t bin_left_bounds[] =
835 : {0, 1, 7, 15, 31, 62, 125, 250, 500, 1000, CIRCPAD_DELAY_INFINITE};
836 12 : for (int i = 0; i <= BIG_HISTOGRAM_LEN ; i++) {
837 11 : tt_uint_op(bin_left_bounds[i], OP_EQ,
838 : circpad_histogram_bin_to_usec(mi, i));
839 : }
840 :
841 : /* XXX we want to test remove_token_exact and
842 : circpad_machine_remove_closest_token() with usec */
843 :
844 : /* Check that all bins have two tokens right now */
845 11 : for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
846 10 : tt_int_op(mi->histogram[i], OP_EQ, 2);
847 : }
848 :
849 : /* This is the right order to remove tokens from this histogram. That is, we
850 : * first remove tokens from the 4th bin since 57 usec is nearest to the 4th
851 : * bin midpoint (31 + (62-31)/2 == 46). Then we remove from the 3rd bin for
852 : * the same reason, then from the 5th, etc. */
853 1 : const int bin_removal_order[] = {4, 3, 5, 2, 1, 0, 6, 7, 8, 9};
854 :
855 : /* Remove all tokens from all bins apart from the infinity bin */
856 10 : for (int i = 0; i < BIG_HISTOGRAM_LEN-1 ; i++) {
857 9 : int bin_to_remove = bin_removal_order[i];
858 9 : log_debug(LD_GENERAL, "Testing that %d attempt removes %d bin",
859 : i, bin_to_remove);
860 :
861 9 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 2);
862 :
863 9 : mi->padding_scheduled_at_usec = current_time - 57;
864 9 : circpad_cell_event_nonpadding_sent(client_side);
865 :
866 9 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 1);
867 :
868 9 : mi->padding_scheduled_at_usec = current_time - 57;
869 9 : circpad_cell_event_nonpadding_sent(client_side);
870 :
871 : /* Test that we cleaned out this bin. Don't do this in the case of the last
872 : bin since the tokens will get refilled */
873 9 : if (i != BIG_HISTOGRAM_LEN - 2) {
874 9 : tt_int_op(mi->histogram[bin_to_remove], OP_EQ, 0);
875 : }
876 : }
877 :
878 : /* Check that all bins have been refilled */
879 11 : for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
880 10 : tt_int_op(mi->histogram[i], OP_EQ, 2);
881 : }
882 :
883 : /* Test below the lowest bin, for coverage */
884 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
885 : CIRCPAD_STATE_BURST);
886 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[0] = 100;
887 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[1] = 101;
888 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].histogram_edges[2] = 120;
889 1 : mi->padding_scheduled_at_usec = current_time - 102;
890 1 : mi->histogram[0] = 0;
891 1 : circpad_cell_event_nonpadding_sent(client_side);
892 1 : tt_int_op(mi->histogram[1], OP_EQ, 1);
893 :
894 : /* Test above the highest bin, for coverage */
895 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
896 : CIRCPAD_STATE_BURST);
897 1 : circ_client_machine.states[CIRCPAD_STATE_BURST].
898 1 : histogram_edges[BIG_HISTOGRAM_LEN-2] = 100;
899 1 : mi->padding_scheduled_at_usec = current_time - 29202;
900 1 : circpad_cell_event_nonpadding_sent(client_side);
901 1 : tt_int_op(mi->histogram[BIG_HISTOGRAM_LEN-2], OP_EQ, 1);
902 :
903 1 : done:
904 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
905 1 : monotime_disable_test_mocking();
906 1 : tor_free(circ_client_machine.states);
907 1 : testing_disable_reproducible_rng();
908 1 : }
909 :
910 : /** Test closest token removal strategy with usec */
911 : static void
912 1 : test_circuitpadding_token_removal_exact(void *arg)
913 : {
914 1 : circpad_machine_runtime_t *mi;
915 1 : (void)arg;
916 :
917 : /* Mock it up */
918 1 : MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
919 1 : MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
920 1 : testing_enable_reproducible_rng();
921 :
922 : /* Setup test environment (time etc.) */
923 1 : client_side = TO_CIRCUIT(origin_circuit_new());
924 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
925 1 : monotime_enable_test_mocking();
926 :
927 : /* Create test machine */
928 1 : helper_create_machine_with_big_histogram(CIRCPAD_TOKEN_REMOVAL_EXACT);
929 1 : client_side->padding_machine[0] = &circ_client_machine;
930 2 : client_side->padding_info[0] =
931 1 : circpad_circuit_machineinfo_new(client_side, 0);
932 :
933 : /* move the machine to the right state */
934 1 : circpad_cell_event_nonpadding_received(client_side);
935 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
936 : CIRCPAD_STATE_BURST);
937 :
938 : /* Get the machine and setup tokens */
939 1 : mi = client_side->padding_info[0];
940 1 : tt_assert(mi);
941 :
942 : /**********************************************************************/
943 1 : uint64_t current_time = monotime_absolute_usec();
944 :
945 : /* Ensure that we will clear out bin #4 with this usec */
946 1 : mi->padding_scheduled_at_usec = current_time - 57;
947 1 : tt_int_op(mi->histogram[4], OP_EQ, 2);
948 1 : circpad_cell_event_nonpadding_sent(client_side);
949 1 : mi->padding_scheduled_at_usec = current_time - 57;
950 1 : tt_int_op(mi->histogram[4], OP_EQ, 1);
951 1 : circpad_cell_event_nonpadding_sent(client_side);
952 1 : tt_int_op(mi->histogram[4], OP_EQ, 0);
953 :
954 : /* Ensure that we will not remove any other tokens even tho we try to, since
955 : * this is what the exact strategy dictates */
956 1 : mi->padding_scheduled_at_usec = current_time - 57;
957 1 : circpad_cell_event_nonpadding_sent(client_side);
958 11 : for (int i = 0; i < BIG_HISTOGRAM_LEN ; i++) {
959 10 : if (i != 4) {
960 10 : tt_int_op(mi->histogram[i], OP_EQ, 2);
961 : }
962 : }
963 :
964 1 : done:
965 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
966 1 : monotime_disable_test_mocking();
967 1 : tor_free(circ_client_machine.states);
968 1 : testing_disable_reproducible_rng();
969 1 : }
970 :
971 : #undef BIG_HISTOGRAM_LEN
972 :
973 : void
974 1 : test_circuitpadding_tokens(void *arg)
975 : {
976 1 : const circpad_state_t *state;
977 1 : circpad_machine_runtime_t *mi;
978 1 : int64_t actual_mocked_monotime_start;
979 1 : (void)arg;
980 :
981 1 : testing_enable_reproducible_rng();
982 :
983 : /** Test plan:
984 : *
985 : * 1. Test symmetry between bin_to_usec and usec_to_bin
986 : * a. Test conversion
987 : * b. Test edge transitions (lower, upper)
988 : * 2. Test remove higher on an empty bin
989 : * a. Normal bin
990 : * b. Infinity bin
991 : * c. Bin 0
992 : * d. No higher
993 : * 3. Test remove lower
994 : * a. Normal bin
995 : * b. Bin 0
996 : * c. No lower
997 : * 4. Test remove closest
998 : * a. Closest lower
999 : * b. Closest higher
1000 : * c. Closest 0
1001 : * d. Closest Infinity
1002 : */
1003 1 : client_side = TO_CIRCUIT(origin_circuit_new());
1004 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
1005 :
1006 1 : monotime_init();
1007 1 : monotime_enable_test_mocking();
1008 1 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
1009 1 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
1010 1 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
1011 1 : curr_mocked_time = actual_mocked_monotime_start;
1012 :
1013 : /* This is needed so that we are not considered to be dormant */
1014 1 : note_user_activity(20);
1015 :
1016 1 : timers_initialize();
1017 :
1018 1 : helper_create_basic_machine();
1019 1 : client_side->padding_machine[0] = &circ_client_machine;
1020 1 : client_side->padding_info[0] = circpad_circuit_machineinfo_new(client_side,
1021 : 0);
1022 :
1023 1 : mi = client_side->padding_info[0];
1024 :
1025 : // Pretend a non-padding cell was sent
1026 1 : circpad_cell_event_nonpadding_received(client_side);
1027 1 : circpad_cell_event_nonpadding_sent(client_side);
1028 : /* We have to save the infinity bin because one inf delay
1029 : * could have been chosen when we transition to burst */
1030 1 : circpad_hist_token_t inf_bin = mi->histogram[4];
1031 :
1032 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
1033 : CIRCPAD_STATE_BURST);
1034 :
1035 1 : state = circpad_machine_current_state(client_side->padding_info[0]);
1036 :
1037 : // Test 0: convert bin->usec->bin
1038 : // Bin 0+1 have different semantics
1039 3 : for (int bin = 0; bin < 2; bin++) {
1040 2 : circpad_delay_t usec =
1041 2 : circpad_histogram_bin_to_usec(client_side->padding_info[0], bin);
1042 2 : int bin2 = circpad_histogram_usec_to_bin(client_side->padding_info[0],
1043 : usec);
1044 2 : tt_int_op(bin, OP_EQ, bin2);
1045 : }
1046 3 : for (int bin = 2; bin < state->histogram_len-1; bin++) {
1047 2 : circpad_delay_t usec =
1048 2 : circpad_histogram_bin_to_usec(client_side->padding_info[0], bin);
1049 2 : int bin2 = circpad_histogram_usec_to_bin(client_side->padding_info[0],
1050 : usec);
1051 2 : tt_int_op(bin, OP_EQ, bin2);
1052 : /* Verify we round down */
1053 2 : bin2 = circpad_histogram_usec_to_bin(client_side->padding_info[0],
1054 : usec+3);
1055 2 : tt_int_op(bin, OP_EQ, bin2);
1056 :
1057 2 : bin2 = circpad_histogram_usec_to_bin(client_side->padding_info[0],
1058 : usec-1);
1059 2 : tt_int_op(bin, OP_EQ, bin2+1);
1060 : }
1061 :
1062 : // Test 1: converting usec->bin->usec->bin
1063 : // Bin 0+1 have different semantics.
1064 502 : for (circpad_delay_t i = 0; i <= state->histogram_edges[0]; i++) {
1065 501 : int bin = circpad_histogram_usec_to_bin(client_side->padding_info[0],
1066 : i);
1067 501 : circpad_delay_t usec =
1068 501 : circpad_histogram_bin_to_usec(client_side->padding_info[0], bin);
1069 501 : int bin2 = circpad_histogram_usec_to_bin(client_side->padding_info[0],
1070 : usec);
1071 501 : tt_int_op(bin, OP_EQ, bin2);
1072 501 : tt_int_op(i, OP_LE, usec);
1073 : }
1074 1 : for (circpad_delay_t i = state->histogram_edges[0]+1;
1075 10001 : i <= state->histogram_edges[0] +
1076 10001 : state->histogram_edges[state->histogram_len-2]; i++) {
1077 10000 : int bin = circpad_histogram_usec_to_bin(client_side->padding_info[0],
1078 : i);
1079 10000 : circpad_delay_t usec =
1080 10000 : circpad_histogram_bin_to_usec(client_side->padding_info[0], bin);
1081 10000 : int bin2 = circpad_histogram_usec_to_bin(client_side->padding_info[0],
1082 : usec);
1083 10000 : tt_int_op(bin, OP_EQ, bin2);
1084 10000 : tt_int_op(i, OP_GE, usec);
1085 : }
1086 :
1087 : /* 2.a. Normal higher bin */
1088 : {
1089 1 : tt_int_op(mi->histogram[2], OP_EQ, 2);
1090 1 : tt_int_op(mi->histogram[3], OP_EQ, 2);
1091 1 : circpad_machine_remove_higher_token(mi,
1092 1 : circpad_histogram_bin_to_usec(mi, 2)+1);
1093 1 : tt_int_op(mi->histogram[3], OP_EQ, 2);
1094 1 : tt_int_op(mi->histogram[2], OP_EQ, 1);
1095 :
1096 1 : circpad_machine_remove_higher_token(mi,
1097 1 : circpad_histogram_bin_to_usec(mi, 2)+1);
1098 1 : tt_int_op(mi->histogram[2], OP_EQ, 0);
1099 :
1100 1 : tt_int_op(mi->histogram[3], OP_EQ, 2);
1101 1 : circpad_machine_remove_higher_token(mi,
1102 1 : circpad_histogram_bin_to_usec(mi, 2)+1);
1103 1 : circpad_machine_remove_higher_token(mi,
1104 1 : circpad_histogram_bin_to_usec(mi, 2)+1);
1105 1 : tt_int_op(mi->histogram[3], OP_EQ, 0);
1106 1 : circpad_machine_remove_higher_token(mi,
1107 1 : circpad_histogram_bin_to_usec(mi, 2)+1);
1108 1 : tt_int_op(mi->histogram[3], OP_EQ, 0);
1109 : }
1110 :
1111 : /* 2.b. Higher Infinity bin */
1112 : {
1113 1 : tt_int_op(mi->histogram[4], OP_EQ, inf_bin);
1114 1 : circpad_machine_remove_higher_token(mi,
1115 1 : circpad_histogram_bin_to_usec(mi, 2)+1);
1116 1 : tt_int_op(mi->histogram[4], OP_EQ, inf_bin);
1117 :
1118 : /* Test past the infinity bin */
1119 1 : circpad_machine_remove_higher_token(mi,
1120 1 : circpad_histogram_bin_to_usec(mi, 5)+1000000);
1121 :
1122 1 : tt_int_op(mi->histogram[4], OP_EQ, inf_bin);
1123 : }
1124 :
1125 : /* 2.c. Bin 0 */
1126 : {
1127 1 : tt_int_op(mi->histogram[0], OP_EQ, 0);
1128 1 : mi->histogram[0] = 1;
1129 1 : circpad_machine_remove_higher_token(mi, state->histogram_edges[0]/2);
1130 1 : tt_int_op(mi->histogram[0], OP_EQ, 0);
1131 : }
1132 :
1133 : /* Drain the infinity bin and cause a refill */
1134 3 : while (inf_bin != 0) {
1135 2 : tt_int_op(mi->histogram[4], OP_EQ, inf_bin);
1136 2 : circpad_cell_event_nonpadding_received(client_side);
1137 2 : inf_bin--;
1138 : }
1139 :
1140 1 : circpad_cell_event_nonpadding_sent(client_side);
1141 :
1142 : // We should have refilled here.
1143 1 : tt_int_op(mi->histogram[4], OP_EQ, 2);
1144 :
1145 : /* 3.a. Bin 0 */
1146 : {
1147 1 : tt_int_op(mi->histogram[0], OP_EQ, 1);
1148 1 : circpad_machine_remove_higher_token(mi, state->histogram_edges[0]/2);
1149 1 : tt_int_op(mi->histogram[0], OP_EQ, 0);
1150 : }
1151 :
1152 : /* 3.b. Test remove lower normal bin */
1153 : {
1154 1 : tt_int_op(mi->histogram[3], OP_EQ, 2);
1155 1 : circpad_machine_remove_lower_token(mi,
1156 1 : circpad_histogram_bin_to_usec(mi, 3)+1);
1157 1 : circpad_machine_remove_lower_token(mi,
1158 1 : circpad_histogram_bin_to_usec(mi, 3)+1);
1159 1 : tt_int_op(mi->histogram[3], OP_EQ, 0);
1160 1 : tt_int_op(mi->histogram[2], OP_EQ, 2);
1161 1 : circpad_machine_remove_lower_token(mi,
1162 1 : circpad_histogram_bin_to_usec(mi, 3)+1);
1163 1 : circpad_machine_remove_lower_token(mi,
1164 1 : circpad_histogram_bin_to_usec(mi, 3)+1);
1165 : /* 3.c. No lower */
1166 1 : circpad_machine_remove_lower_token(mi,
1167 1 : circpad_histogram_bin_to_usec(mi, 3)+1);
1168 1 : tt_int_op(mi->histogram[2], OP_EQ, 0);
1169 : }
1170 :
1171 : /* 4. Test remove closest
1172 : * a. Closest lower
1173 : * b. Closest higher
1174 : * c. Closest 0
1175 : * d. Closest Infinity
1176 : */
1177 1 : circpad_machine_setup_tokens(mi);
1178 1 : tt_int_op(mi->histogram[2], OP_EQ, 2);
1179 1 : circpad_machine_remove_closest_token(mi,
1180 1 : circpad_histogram_bin_to_usec(mi, 2)+1, 0);
1181 1 : circpad_machine_remove_closest_token(mi,
1182 1 : circpad_histogram_bin_to_usec(mi, 2)+1, 0);
1183 1 : tt_int_op(mi->histogram[2], OP_EQ, 0);
1184 1 : tt_int_op(mi->histogram[3], OP_EQ, 2);
1185 1 : circpad_machine_remove_closest_token(mi,
1186 1 : circpad_histogram_bin_to_usec(mi, 2)+1, 0);
1187 1 : circpad_machine_remove_closest_token(mi,
1188 1 : circpad_histogram_bin_to_usec(mi, 2)+1, 0);
1189 1 : tt_int_op(mi->histogram[3], OP_EQ, 0);
1190 1 : tt_int_op(mi->histogram[0], OP_EQ, 1);
1191 1 : circpad_machine_remove_closest_token(mi,
1192 1 : circpad_histogram_bin_to_usec(mi, 2)+1, 0);
1193 1 : tt_int_op(mi->histogram[0], OP_EQ, 0);
1194 1 : tt_int_op(mi->histogram[4], OP_EQ, 2);
1195 1 : circpad_machine_remove_closest_token(mi,
1196 1 : circpad_histogram_bin_to_usec(mi, 2)+1, 0);
1197 1 : tt_int_op(mi->histogram[4], OP_EQ, 2);
1198 :
1199 : /* 5. Test remove closest usec
1200 : * a. Closest 0
1201 : * b. Closest lower (below midpoint)
1202 : * c. Closest higher (above midpoint)
1203 : * d. Closest Infinity
1204 : */
1205 1 : circpad_machine_setup_tokens(mi);
1206 :
1207 1 : tt_int_op(mi->histogram[0], OP_EQ, 1);
1208 1 : circpad_machine_remove_closest_token(mi,
1209 1 : circpad_histogram_bin_to_usec(mi, 0)/3, 1);
1210 1 : tt_int_op(mi->histogram[0], OP_EQ, 0);
1211 1 : tt_int_op(mi->histogram[2], OP_EQ, 2);
1212 1 : circpad_machine_remove_closest_token(mi,
1213 1 : circpad_histogram_bin_to_usec(mi, 0)/3, 1);
1214 1 : circpad_machine_remove_closest_token(mi,
1215 1 : circpad_histogram_bin_to_usec(mi, 0)/3, 1);
1216 1 : tt_int_op(mi->histogram[2], OP_EQ, 0);
1217 1 : tt_int_op(mi->histogram[3], OP_EQ, 2);
1218 1 : circpad_machine_remove_closest_token(mi,
1219 : circpad_histogram_bin_to_usec(mi, 4), 1);
1220 1 : circpad_machine_remove_closest_token(mi,
1221 : circpad_histogram_bin_to_usec(mi, 4), 1);
1222 1 : tt_int_op(mi->histogram[3], OP_EQ, 0);
1223 1 : tt_int_op(mi->histogram[4], OP_EQ, 2);
1224 1 : circpad_machine_remove_closest_token(mi,
1225 : circpad_histogram_bin_to_usec(mi, 4), 1);
1226 1 : circpad_machine_remove_closest_token(mi,
1227 : circpad_histogram_bin_to_usec(mi, 4), 1);
1228 1 : tt_int_op(mi->histogram[4], OP_EQ, 2);
1229 :
1230 : // XXX: Need more coverage of the actual usec branches
1231 :
1232 1 : done:
1233 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
1234 1 : monotime_disable_test_mocking();
1235 1 : tor_free(circ_client_machine.states);
1236 1 : testing_disable_reproducible_rng();
1237 1 : }
1238 :
1239 : void
1240 1 : test_circuitpadding_wronghop(void *arg)
1241 : {
1242 : /**
1243 : * Test plan:
1244 : * 1. Padding sent from hop 1 and 3 to client
1245 : * 2. Send negotiated from hop 1 and 3 to client
1246 : * 3. Garbled negotiated cell
1247 : * 4. Padding negotiate sent to client
1248 : * 5. Send negotiate stop command for unknown machine
1249 : * 6. Send negotiated to relay
1250 : * 7. Garbled padding negotiate cell
1251 : */
1252 1 : (void)arg;
1253 1 : uint32_t read_bw = 0, overhead_bw = 0;
1254 1 : cell_t cell;
1255 1 : signed_error_t ret;
1256 1 : origin_circuit_t *orig_client;
1257 1 : int64_t actual_mocked_monotime_start;
1258 :
1259 1 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
1260 :
1261 : /* Mock this function so that our cell counting tests don't get confused by
1262 : * padding that gets sent by scheduled timers. */
1263 1 : MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
1264 1 : testing_enable_reproducible_rng();
1265 :
1266 1 : client_side = TO_CIRCUIT(origin_circuit_new());
1267 1 : dummy_channel.cmux = circuitmux_alloc();
1268 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel,
1269 : &dummy_channel));
1270 1 : orig_client = TO_ORIGIN_CIRCUIT(client_side);
1271 :
1272 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
1273 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
1274 1 : nodes_init();
1275 :
1276 1 : monotime_init();
1277 1 : monotime_enable_test_mocking();
1278 1 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
1279 1 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
1280 1 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
1281 1 : curr_mocked_time = actual_mocked_monotime_start;
1282 :
1283 1 : timers_initialize();
1284 1 : circpad_machines_init();
1285 :
1286 1 : MOCK(node_get_by_id,
1287 : node_get_by_id_mock);
1288 :
1289 1 : MOCK(circuit_package_relay_cell,
1290 : circuit_package_relay_cell_mock);
1291 :
1292 : /* Build three hops */
1293 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1294 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1295 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1296 :
1297 : /* verify padding was negotiated */
1298 1 : tt_ptr_op(relay_side->padding_machine[0], OP_NE, NULL);
1299 1 : tt_ptr_op(relay_side->padding_info[0], OP_NE, NULL);
1300 :
1301 : /* verify echo was sent */
1302 1 : tt_int_op(n_relay_cells, OP_EQ, 1);
1303 1 : tt_int_op(n_client_cells, OP_EQ, 1);
1304 :
1305 1 : read_bw = orig_client->n_delivered_read_circ_bw;
1306 1 : overhead_bw = orig_client->n_overhead_read_circ_bw;
1307 :
1308 : /* 1. Test padding from first and third hop */
1309 1 : circpad_deliver_recognized_relay_cell_events(client_side,
1310 : RELAY_COMMAND_DROP,
1311 1 : TO_ORIGIN_CIRCUIT(client_side)->cpath);
1312 1 : tt_int_op(read_bw, OP_EQ,
1313 : orig_client->n_delivered_read_circ_bw);
1314 1 : tt_int_op(overhead_bw, OP_EQ,
1315 : orig_client->n_overhead_read_circ_bw);
1316 :
1317 2 : circpad_deliver_recognized_relay_cell_events(client_side,
1318 : RELAY_COMMAND_DROP,
1319 1 : TO_ORIGIN_CIRCUIT(client_side)->cpath->next->next);
1320 1 : tt_int_op(read_bw, OP_EQ,
1321 : orig_client->n_delivered_read_circ_bw);
1322 1 : tt_int_op(overhead_bw, OP_EQ,
1323 : orig_client->n_overhead_read_circ_bw);
1324 :
1325 2 : circpad_deliver_recognized_relay_cell_events(client_side,
1326 : RELAY_COMMAND_DROP,
1327 1 : TO_ORIGIN_CIRCUIT(client_side)->cpath->next);
1328 1 : tt_int_op(read_bw, OP_EQ,
1329 : orig_client->n_delivered_read_circ_bw);
1330 1 : tt_int_op(overhead_bw, OP_LT,
1331 : orig_client->n_overhead_read_circ_bw);
1332 :
1333 : /* 2. Test padding negotiated not handled from hops 1,3 */
1334 1 : ret = circpad_handle_padding_negotiated(client_side, &cell,
1335 1 : TO_ORIGIN_CIRCUIT(client_side)->cpath);
1336 1 : tt_int_op(ret, OP_EQ, -1);
1337 :
1338 3 : ret = circpad_handle_padding_negotiated(client_side, &cell,
1339 1 : TO_ORIGIN_CIRCUIT(client_side)->cpath->next->next);
1340 1 : tt_int_op(ret, OP_EQ, -1);
1341 :
1342 : /* 3. Garbled negotiated cell */
1343 1 : memset(&cell, 255, sizeof(cell));
1344 3 : ret = circpad_handle_padding_negotiated(client_side, &cell,
1345 1 : TO_ORIGIN_CIRCUIT(client_side)->cpath->next);
1346 1 : tt_int_op(ret, OP_EQ, -1);
1347 :
1348 : /* 4. Test that negotiate is dropped at origin */
1349 1 : read_bw = orig_client->n_delivered_read_circ_bw;
1350 1 : overhead_bw = orig_client->n_overhead_read_circ_bw;
1351 1 : relay_send_command_from_edge(0, relay_side,
1352 : RELAY_COMMAND_PADDING_NEGOTIATE,
1353 : (void*)cell.payload,
1354 : (size_t)3, NULL);
1355 1 : tt_int_op(read_bw, OP_EQ,
1356 : orig_client->n_delivered_read_circ_bw);
1357 1 : tt_int_op(overhead_bw, OP_EQ,
1358 : orig_client->n_overhead_read_circ_bw);
1359 :
1360 1 : tt_int_op(n_relay_cells, OP_EQ, 2);
1361 1 : tt_int_op(n_client_cells, OP_EQ, 1);
1362 :
1363 : /* 5. Test that asking to stop the wrong machine does nothing */
1364 1 : circpad_negotiate_padding(TO_ORIGIN_CIRCUIT(client_side),
1365 : 255, 2, CIRCPAD_COMMAND_STOP, 0);
1366 1 : tt_ptr_op(client_side->padding_machine[0], OP_NE, NULL);
1367 1 : tt_ptr_op(client_side->padding_info[0], OP_NE, NULL);
1368 1 : tt_ptr_op(relay_side->padding_machine[0], OP_NE, NULL);
1369 1 : tt_ptr_op(relay_side->padding_info[0], OP_NE, NULL);
1370 1 : tt_int_op(n_relay_cells, OP_EQ, 3);
1371 1 : tt_int_op(n_client_cells, OP_EQ, 2);
1372 :
1373 : /* 6. Sending negotiated command to relay does nothing */
1374 1 : ret = circpad_handle_padding_negotiated(relay_side, &cell, NULL);
1375 1 : tt_int_op(ret, OP_EQ, -1);
1376 :
1377 : /* 7. Test garbled negotiated cell (bad command 255) */
1378 1 : memset(&cell, 0, sizeof(cell));
1379 1 : ret = circpad_handle_padding_negotiate(relay_side, &cell);
1380 1 : tt_int_op(ret, OP_EQ, -1);
1381 1 : tt_int_op(n_client_cells, OP_EQ, 2);
1382 :
1383 : /* Test 2: Test no padding */
1384 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
1385 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
1386 :
1387 1 : client_side = TO_CIRCUIT(origin_circuit_new());
1388 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel,
1389 : &dummy_channel));
1390 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
1391 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
1392 :
1393 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1394 1 : simulate_single_hop_extend(client_side, relay_side, 0);
1395 :
1396 : /* verify no padding was negotiated */
1397 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
1398 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
1399 1 : tt_int_op(n_relay_cells, OP_EQ, 3);
1400 1 : tt_int_op(n_client_cells, OP_EQ, 2);
1401 :
1402 : /* verify no echo was sent */
1403 1 : tt_int_op(n_relay_cells, OP_EQ, 3);
1404 1 : tt_int_op(n_client_cells, OP_EQ, 2);
1405 :
1406 : /* Finish circuit */
1407 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1408 :
1409 : /* Spoof padding negotiated on circuit with no padding */
1410 1 : circpad_padding_negotiated(relay_side,
1411 : CIRCPAD_MACHINE_CIRC_SETUP,
1412 : CIRCPAD_COMMAND_START,
1413 : CIRCPAD_RESPONSE_OK, 0);
1414 :
1415 : /* verify no padding was negotiated */
1416 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
1417 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
1418 :
1419 1 : circpad_padding_negotiated(relay_side,
1420 : CIRCPAD_MACHINE_CIRC_SETUP,
1421 : CIRCPAD_COMMAND_START,
1422 : CIRCPAD_RESPONSE_ERR, 0);
1423 :
1424 : /* verify no padding was negotiated */
1425 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
1426 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
1427 :
1428 1 : done:
1429 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
1430 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
1431 1 : circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
1432 1 : circuitmux_free(dummy_channel.cmux);
1433 1 : monotime_disable_test_mocking();
1434 1 : UNMOCK(node_get_by_id);
1435 1 : UNMOCK(circuit_package_relay_cell);
1436 1 : UNMOCK(circuitmux_attach_circuit);
1437 1 : nodes_free();
1438 1 : testing_disable_reproducible_rng();
1439 1 : }
1440 :
1441 : void
1442 1 : test_circuitpadding_negotiation(void *arg)
1443 : {
1444 : /**
1445 : * Test plan:
1446 : * 1. Test circuit where padding is supported by middle
1447 : * a. Make sure padding negotiation is sent
1448 : * b. Test padding negotiation delivery and parsing
1449 : * 2. Test circuit where padding is unsupported by middle
1450 : * a. Make sure padding negotiation is not sent
1451 : * 3. Test failure to negotiate a machine due to desync.
1452 : */
1453 1 : int64_t actual_mocked_monotime_start;
1454 1 : (void)arg;
1455 :
1456 1 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
1457 :
1458 1 : client_side = TO_CIRCUIT(origin_circuit_new());
1459 1 : dummy_channel.cmux = circuitmux_alloc();
1460 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
1461 :
1462 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
1463 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
1464 1 : nodes_init();
1465 :
1466 1 : monotime_init();
1467 1 : monotime_enable_test_mocking();
1468 1 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
1469 1 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
1470 1 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
1471 1 : curr_mocked_time = actual_mocked_monotime_start;
1472 :
1473 1 : timers_initialize();
1474 1 : circpad_machines_init();
1475 :
1476 1 : MOCK(node_get_by_id,
1477 : node_get_by_id_mock);
1478 :
1479 1 : MOCK(circuit_package_relay_cell,
1480 : circuit_package_relay_cell_mock);
1481 :
1482 : /* Build two hops */
1483 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1484 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1485 :
1486 : /* verify padding was negotiated */
1487 1 : tt_ptr_op(relay_side->padding_machine[0], OP_NE, NULL);
1488 1 : tt_ptr_op(relay_side->padding_info[0], OP_NE, NULL);
1489 :
1490 : /* verify echo was sent */
1491 1 : tt_int_op(n_relay_cells, OP_EQ, 1);
1492 1 : tt_int_op(n_client_cells, OP_EQ, 1);
1493 :
1494 : /* Finish circuit */
1495 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1496 :
1497 : /* Test 2: Test no padding */
1498 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
1499 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
1500 :
1501 1 : client_side = TO_CIRCUIT(origin_circuit_new());
1502 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
1503 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
1504 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
1505 :
1506 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1507 1 : simulate_single_hop_extend(client_side, relay_side, 0);
1508 :
1509 : /* verify no padding was negotiated */
1510 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
1511 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
1512 1 : tt_int_op(n_relay_cells, OP_EQ, 1);
1513 1 : tt_int_op(n_client_cells, OP_EQ, 1);
1514 :
1515 : /* verify no echo was sent */
1516 1 : tt_int_op(n_relay_cells, OP_EQ, 1);
1517 1 : tt_int_op(n_client_cells, OP_EQ, 1);
1518 :
1519 : /* Finish circuit */
1520 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1521 :
1522 : /* Force negotiate padding. */
1523 1 : circpad_negotiate_padding(TO_ORIGIN_CIRCUIT(client_side),
1524 : CIRCPAD_MACHINE_CIRC_SETUP,
1525 : 2, CIRCPAD_COMMAND_START, 0);
1526 :
1527 : /* verify no padding was negotiated */
1528 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
1529 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
1530 :
1531 : /* verify no echo was sent */
1532 1 : tt_int_op(n_relay_cells, OP_EQ, 1);
1533 1 : tt_int_op(n_client_cells, OP_EQ, 1);
1534 :
1535 : /* 3. Test failure to negotiate a machine due to desync */
1536 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
1537 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
1538 :
1539 1 : client_side = TO_CIRCUIT(origin_circuit_new());
1540 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
1541 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
1542 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
1543 :
1544 4 : SMARTLIST_FOREACH(relay_padding_machines,
1545 : circpad_machine_spec_t *,
1546 : m, tor_free(m->states); tor_free(m));
1547 1 : smartlist_free(relay_padding_machines);
1548 1 : relay_padding_machines = smartlist_new();
1549 :
1550 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1551 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1552 :
1553 : /* verify echo was sent */
1554 1 : tt_int_op(n_client_cells, OP_EQ, 2);
1555 1 : tt_int_op(n_relay_cells, OP_EQ, 2);
1556 :
1557 : /* verify no padding was negotiated */
1558 1 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
1559 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
1560 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
1561 1 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
1562 :
1563 1 : done:
1564 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
1565 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
1566 1 : circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
1567 1 : circuitmux_free(dummy_channel.cmux);
1568 1 : monotime_disable_test_mocking();
1569 1 : UNMOCK(node_get_by_id);
1570 1 : UNMOCK(circuit_package_relay_cell);
1571 1 : UNMOCK(circuitmux_attach_circuit);
1572 1 : nodes_free();
1573 1 : }
1574 :
1575 : static void
1576 28 : simulate_single_hop_extend(circuit_t *client, circuit_t *mid_relay,
1577 : int padding)
1578 : {
1579 28 : char whatevs_key[CPATH_KEY_MATERIAL_LEN];
1580 28 : char digest[DIGEST_LEN];
1581 28 : tor_addr_t addr;
1582 :
1583 : // Pretend a non-padding cell was sent
1584 28 : circpad_cell_event_nonpadding_sent(client);
1585 :
1586 : // Receive extend cell at middle
1587 28 : circpad_cell_event_nonpadding_received(mid_relay);
1588 :
1589 : // Advance time a tiny bit so we can calculate an RTT
1590 28 : curr_mocked_time += 10 * TOR_NSEC_PER_MSEC;
1591 28 : monotime_coarse_set_mock_time_nsec(curr_mocked_time);
1592 28 : monotime_set_mock_time_nsec(curr_mocked_time);
1593 :
1594 : // Receive extended cell at middle
1595 28 : circpad_cell_event_nonpadding_sent(mid_relay);
1596 :
1597 : // Receive extended cell at first hop
1598 28 : circpad_cell_event_nonpadding_received(client);
1599 :
1600 : // Add a hop to cpath
1601 28 : crypt_path_t *hop = tor_malloc_zero(sizeof(crypt_path_t));
1602 28 : cpath_extend_linked_list(&TO_ORIGIN_CIRCUIT(client)->cpath, hop);
1603 :
1604 28 : hop->magic = CRYPT_PATH_MAGIC;
1605 28 : hop->state = CPATH_STATE_OPEN;
1606 :
1607 : // add an extend info to indicate if this node supports padding or not.
1608 : // (set the first byte of the digest for our mocked node_get_by_id)
1609 28 : digest[0] = padding;
1610 :
1611 30 : hop->extend_info = extend_info_new(
1612 : padding ? "padding" : "non-padding",
1613 : digest, NULL, NULL, NULL,
1614 : &addr, padding);
1615 :
1616 28 : cpath_init_circuit_crypto(hop, whatevs_key, sizeof(whatevs_key), 0, 0);
1617 :
1618 28 : hop->package_window = circuit_initial_package_window();
1619 28 : hop->deliver_window = CIRCWINDOW_START;
1620 :
1621 : // Signal that the hop was added
1622 28 : circpad_machine_event_circ_added_hop(TO_ORIGIN_CIRCUIT(client));
1623 28 : }
1624 :
1625 : static circpad_machine_spec_t *
1626 1 : helper_create_length_machine(void)
1627 : {
1628 1 : circpad_machine_spec_t *ret =
1629 1 : tor_malloc_zero(sizeof(circpad_machine_spec_t));
1630 :
1631 : /* Start, burst */
1632 1 : circpad_machine_states_init(ret, 2);
1633 :
1634 1 : ret->states[CIRCPAD_STATE_START].
1635 1 : next_state[CIRCPAD_EVENT_PADDING_SENT] = CIRCPAD_STATE_BURST;
1636 :
1637 1 : ret->states[CIRCPAD_STATE_BURST].
1638 1 : next_state[CIRCPAD_EVENT_PADDING_SENT] = CIRCPAD_STATE_BURST;
1639 :
1640 1 : ret->states[CIRCPAD_STATE_BURST].
1641 1 : next_state[CIRCPAD_EVENT_LENGTH_COUNT] = CIRCPAD_STATE_END;
1642 :
1643 1 : ret->states[CIRCPAD_STATE_BURST].
1644 1 : next_state[CIRCPAD_EVENT_BINS_EMPTY] = CIRCPAD_STATE_END;
1645 :
1646 : /* No token removal.. end via state_length only */
1647 1 : ret->states[CIRCPAD_STATE_BURST].token_removal =
1648 : CIRCPAD_TOKEN_REMOVAL_NONE;
1649 :
1650 : /* Let's have this one end after 12 packets */
1651 1 : ret->states[CIRCPAD_STATE_BURST].length_dist.type = CIRCPAD_DIST_UNIFORM;
1652 1 : ret->states[CIRCPAD_STATE_BURST].length_dist.param1 = 12;
1653 1 : ret->states[CIRCPAD_STATE_BURST].length_dist.param2 = 13;
1654 1 : ret->states[CIRCPAD_STATE_BURST].max_length = 12;
1655 :
1656 1 : ret->states[CIRCPAD_STATE_BURST].histogram_len = 4;
1657 :
1658 1 : ret->states[CIRCPAD_STATE_BURST].histogram_edges[0] = 0;
1659 1 : ret->states[CIRCPAD_STATE_BURST].histogram_edges[1] = 1;
1660 1 : ret->states[CIRCPAD_STATE_BURST].histogram_edges[2] = 1000000;
1661 1 : ret->states[CIRCPAD_STATE_BURST].histogram_edges[3] = 10000000;
1662 :
1663 1 : ret->states[CIRCPAD_STATE_BURST].histogram[0] = 0;
1664 1 : ret->states[CIRCPAD_STATE_BURST].histogram[1] = 0;
1665 1 : ret->states[CIRCPAD_STATE_BURST].histogram[2] = 6;
1666 :
1667 1 : ret->states[CIRCPAD_STATE_BURST].histogram_total_tokens = 6;
1668 1 : ret->states[CIRCPAD_STATE_BURST].use_rtt_estimate = 0;
1669 1 : ret->states[CIRCPAD_STATE_BURST].length_includes_nonpadding = 0;
1670 :
1671 1 : return ret;
1672 : }
1673 :
1674 : static circpad_machine_spec_t *
1675 8 : helper_create_conditional_machine(void)
1676 : {
1677 8 : circpad_machine_spec_t *ret =
1678 8 : tor_malloc_zero(sizeof(circpad_machine_spec_t));
1679 :
1680 : /* Start, burst */
1681 8 : circpad_machine_states_init(ret, 2);
1682 :
1683 8 : ret->states[CIRCPAD_STATE_START].
1684 8 : next_state[CIRCPAD_EVENT_PADDING_SENT] = CIRCPAD_STATE_BURST;
1685 :
1686 8 : ret->states[CIRCPAD_STATE_BURST].
1687 8 : next_state[CIRCPAD_EVENT_PADDING_SENT] = CIRCPAD_STATE_BURST;
1688 :
1689 8 : ret->states[CIRCPAD_STATE_BURST].
1690 8 : next_state[CIRCPAD_EVENT_LENGTH_COUNT] = CIRCPAD_STATE_END;
1691 :
1692 : /* Use EXACT removal strategy, otherwise setup_tokens() does not work */
1693 8 : ret->states[CIRCPAD_STATE_BURST].token_removal =
1694 : CIRCPAD_TOKEN_REMOVAL_EXACT;
1695 :
1696 8 : ret->states[CIRCPAD_STATE_BURST].histogram_len = 3;
1697 :
1698 8 : ret->states[CIRCPAD_STATE_BURST].histogram_edges[0] = 0;
1699 8 : ret->states[CIRCPAD_STATE_BURST].histogram_edges[1] = 1;
1700 8 : ret->states[CIRCPAD_STATE_BURST].histogram_edges[2] = 1000000;
1701 :
1702 8 : ret->states[CIRCPAD_STATE_BURST].histogram[0] = 6;
1703 8 : ret->states[CIRCPAD_STATE_BURST].histogram[1] = 0;
1704 8 : ret->states[CIRCPAD_STATE_BURST].histogram[2] = 0;
1705 :
1706 8 : ret->states[CIRCPAD_STATE_BURST].histogram_total_tokens = 6;
1707 8 : ret->states[CIRCPAD_STATE_BURST].use_rtt_estimate = 0;
1708 8 : ret->states[CIRCPAD_STATE_BURST].length_includes_nonpadding = 1;
1709 :
1710 8 : return ret;
1711 : }
1712 :
1713 : static void
1714 2 : helper_create_conditional_machines(void)
1715 : {
1716 2 : circpad_machine_spec_t *add = helper_create_conditional_machine();
1717 :
1718 2 : if (!origin_padding_machines)
1719 1 : origin_padding_machines = smartlist_new();
1720 2 : if (!relay_padding_machines)
1721 1 : relay_padding_machines = smartlist_new();
1722 :
1723 2 : add->machine_num = 2;
1724 2 : add->is_origin_side = 1;
1725 2 : add->should_negotiate_end = 1;
1726 2 : add->target_hopnum = 2;
1727 :
1728 : /* Let's have this one end after 4 packets */
1729 2 : add->states[CIRCPAD_STATE_BURST].length_dist.type = CIRCPAD_DIST_UNIFORM;
1730 2 : add->states[CIRCPAD_STATE_BURST].length_dist.param1 = 4;
1731 2 : add->states[CIRCPAD_STATE_BURST].length_dist.param2 = 4;
1732 2 : add->states[CIRCPAD_STATE_BURST].max_length = 4;
1733 :
1734 2 : add->conditions.requires_vanguards = 0;
1735 2 : add->conditions.min_hops = 2;
1736 2 : add->conditions.apply_state_mask = CIRCPAD_CIRC_BUILDING|
1737 : CIRCPAD_CIRC_NO_STREAMS|CIRCPAD_CIRC_HAS_RELAY_EARLY;
1738 2 : add->conditions.apply_purpose_mask = CIRCPAD_PURPOSE_ALL;
1739 2 : circpad_register_padding_machine(add, origin_padding_machines);
1740 :
1741 2 : add = helper_create_conditional_machine();
1742 2 : add->machine_num = 3;
1743 2 : add->is_origin_side = 1;
1744 2 : add->should_negotiate_end = 1;
1745 2 : add->target_hopnum = 2;
1746 :
1747 : /* Let's have this one end after 4 packets */
1748 2 : add->states[CIRCPAD_STATE_BURST].length_dist.type = CIRCPAD_DIST_UNIFORM;
1749 2 : add->states[CIRCPAD_STATE_BURST].length_dist.param1 = 4;
1750 2 : add->states[CIRCPAD_STATE_BURST].length_dist.param2 = 4;
1751 2 : add->states[CIRCPAD_STATE_BURST].max_length = 4;
1752 :
1753 2 : add->conditions.requires_vanguards = 1;
1754 2 : add->conditions.min_hops = 3;
1755 2 : add->conditions.apply_state_mask = CIRCPAD_CIRC_OPENED|
1756 : CIRCPAD_CIRC_STREAMS|CIRCPAD_CIRC_HAS_NO_RELAY_EARLY;
1757 2 : add->conditions.apply_purpose_mask = CIRCPAD_PURPOSE_ALL;
1758 2 : circpad_register_padding_machine(add, origin_padding_machines);
1759 :
1760 2 : add = helper_create_conditional_machine();
1761 2 : add->machine_num = 2;
1762 2 : circpad_register_padding_machine(add, relay_padding_machines);
1763 :
1764 2 : add = helper_create_conditional_machine();
1765 2 : add->machine_num = 3;
1766 2 : circpad_register_padding_machine(add, relay_padding_machines);
1767 2 : }
1768 :
1769 : void
1770 1 : test_circuitpadding_state_length(void *arg)
1771 : {
1772 : /**
1773 : * Test plan:
1774 : * * Explicitly test that with no token removal enabled, we hit
1775 : * the state length limit due to either padding, or non-padding.
1776 : * * Repeat test with an arbitrary token removal strategy, and
1777 : * verify that if we run out of tokens due to padding before we
1778 : * hit the state length, we still go to state end (all our
1779 : * token removal tests only test nonpadding token removal).
1780 : */
1781 1 : int64_t actual_mocked_monotime_start;
1782 1 : (void)arg;
1783 1 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
1784 1 : MOCK(circpad_send_command_to_hop, circpad_send_command_to_hop_mock);
1785 :
1786 1 : nodes_init();
1787 1 : dummy_channel.cmux = circuitmux_alloc();
1788 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel,
1789 : &dummy_channel));
1790 1 : client_side = TO_CIRCUIT(origin_circuit_new());
1791 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
1792 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
1793 :
1794 1 : monotime_init();
1795 1 : monotime_enable_test_mocking();
1796 1 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
1797 1 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
1798 1 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
1799 1 : curr_mocked_time = actual_mocked_monotime_start;
1800 :
1801 : /* This is needed so that we are not considered to be dormant */
1802 1 : note_user_activity(20);
1803 :
1804 1 : timers_initialize();
1805 2 : circpad_machine_spec_t *client_machine =
1806 1 : helper_create_length_machine();
1807 :
1808 1 : MOCK(circuit_package_relay_cell,
1809 : circuit_package_relay_cell_mock);
1810 1 : MOCK(node_get_by_id,
1811 : node_get_by_id_mock);
1812 :
1813 1 : client_side->padding_machine[0] = client_machine;
1814 2 : client_side->padding_info[0] =
1815 1 : circpad_circuit_machineinfo_new(client_side, 0);
1816 1 : circpad_machine_runtime_t *mi = client_side->padding_info[0];
1817 :
1818 1 : circpad_cell_event_padding_sent(client_side);
1819 1 : tt_i64_op(mi->state_length, OP_EQ, 12);
1820 1 : tt_ptr_op(mi->histogram, OP_EQ, NULL);
1821 :
1822 : /* Verify that non-padding does not change our state length */
1823 1 : circpad_cell_event_nonpadding_sent(client_side);
1824 1 : tt_i64_op(mi->state_length, OP_EQ, 12);
1825 :
1826 : /* verify that sending padding changes our state length */
1827 12 : for (uint64_t i = mi->state_length-1; i > 0; i--) {
1828 11 : circpad_send_padding_cell_for_callback(mi);
1829 11 : tt_i64_op(mi->state_length, OP_EQ, i);
1830 : }
1831 1 : circpad_send_padding_cell_for_callback(mi);
1832 :
1833 1 : tt_i64_op(mi->state_length, OP_EQ, -1);
1834 1 : tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END);
1835 :
1836 : /* Restart machine */
1837 1 : mi->current_state = CIRCPAD_STATE_START;
1838 :
1839 : /* Now, count nonpadding as part of the state length */
1840 1 : client_machine->states[CIRCPAD_STATE_BURST].length_includes_nonpadding = 1;
1841 :
1842 1 : circpad_cell_event_padding_sent(client_side);
1843 1 : tt_i64_op(mi->state_length, OP_EQ, 12);
1844 :
1845 : /* Verify that non-padding does change our state length now */
1846 12 : for (uint64_t i = mi->state_length-1; i > 0; i--) {
1847 11 : circpad_cell_event_nonpadding_sent(client_side);
1848 11 : tt_i64_op(mi->state_length, OP_EQ, i);
1849 : }
1850 :
1851 1 : circpad_cell_event_nonpadding_sent(client_side);
1852 1 : tt_i64_op(mi->state_length, OP_EQ, -1);
1853 1 : tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END);
1854 :
1855 : /* Now, just test token removal when we send padding */
1856 1 : client_machine->states[CIRCPAD_STATE_BURST].token_removal =
1857 : CIRCPAD_TOKEN_REMOVAL_EXACT;
1858 :
1859 : /* Restart machine */
1860 1 : mi->current_state = CIRCPAD_STATE_START;
1861 1 : circpad_cell_event_padding_sent(client_side);
1862 1 : tt_i64_op(mi->state_length, OP_EQ, 12);
1863 1 : tt_ptr_op(mi->histogram, OP_NE, NULL);
1864 1 : tt_int_op(mi->chosen_bin, OP_EQ, 2);
1865 :
1866 : /* verify that sending padding changes our state length and
1867 : * our histogram now */
1868 6 : for (uint32_t i = mi->histogram[2]-1; i > 0; i--) {
1869 5 : circpad_send_padding_cell_for_callback(mi);
1870 5 : tt_int_op(mi->chosen_bin, OP_EQ, 2);
1871 5 : tt_int_op(mi->histogram[2], OP_EQ, i);
1872 : }
1873 :
1874 1 : tt_i64_op(mi->state_length, OP_EQ, 7);
1875 1 : tt_int_op(mi->histogram[2], OP_EQ, 1);
1876 :
1877 1 : circpad_send_padding_cell_for_callback(mi);
1878 1 : tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END);
1879 :
1880 1 : done:
1881 1 : tor_free(client_machine->states);
1882 1 : tor_free(client_machine);
1883 :
1884 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
1885 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
1886 :
1887 1 : circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
1888 1 : circuitmux_free(dummy_channel.cmux);
1889 1 : timers_shutdown();
1890 1 : monotime_disable_test_mocking();
1891 1 : UNMOCK(circuit_package_relay_cell);
1892 1 : UNMOCK(circuitmux_attach_circuit);
1893 1 : UNMOCK(node_get_by_id);
1894 :
1895 1 : return;
1896 : }
1897 :
1898 : void
1899 1 : test_circuitpadding_conditions(void *arg)
1900 : {
1901 : /**
1902 : * Test plan:
1903 : * 0. Make a few origin and client machines with diff conditions
1904 : * * vanguards, purposes, has_opened circs, no relay early
1905 : * * Client side should_negotiate_end
1906 : * * Length limits
1907 : * 1. Test STATE_END transitions
1908 : * 2. Test new machine after end with same conditions
1909 : * 3. Test new machine due to changed conditions
1910 : * * Esp: built event, no relay early, no streams
1911 : * XXX: Diff test:
1912 : * 1. Test STATE_END with pending timers
1913 : * 2. Test marking a circuit before padding callback fires
1914 : * 3. Test freeing a circuit before padding callback fires
1915 : */
1916 1 : int64_t actual_mocked_monotime_start;
1917 1 : (void)arg;
1918 1 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
1919 1 : testing_enable_reproducible_rng();
1920 :
1921 1 : nodes_init();
1922 1 : dummy_channel.cmux = circuitmux_alloc();
1923 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel,
1924 : &dummy_channel));
1925 1 : client_side = TO_CIRCUIT(origin_circuit_new());
1926 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
1927 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
1928 :
1929 1 : monotime_init();
1930 1 : monotime_enable_test_mocking();
1931 1 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
1932 1 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
1933 1 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
1934 1 : curr_mocked_time = actual_mocked_monotime_start;
1935 :
1936 : /* This is needed so that we are not considered to be dormant */
1937 1 : note_user_activity(20);
1938 :
1939 1 : timers_initialize();
1940 1 : helper_create_conditional_machines();
1941 :
1942 1 : MOCK(circuit_package_relay_cell,
1943 : circuit_package_relay_cell_mock);
1944 1 : MOCK(node_get_by_id,
1945 : node_get_by_id_mock);
1946 :
1947 : /* Simulate extend. This should result in the original machine getting
1948 : * added, since the circuit is not built */
1949 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1950 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1951 :
1952 : /* Verify that machine #2 is added */
1953 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2);
1954 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2);
1955 :
1956 : /* Deliver a padding cell to the client, to trigger burst state */
1957 1 : circpad_cell_event_padding_sent(client_side);
1958 :
1959 : /* This should have trigger length shutdown condition on client.. */
1960 1 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
1961 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
1962 :
1963 : /* Verify machine is gone from both sides */
1964 1 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
1965 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
1966 :
1967 : /* Send another event.. verify machine gets re-added properly
1968 : * (test race with shutdown) */
1969 1 : simulate_single_hop_extend(client_side, relay_side, 1);
1970 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2);
1971 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2);
1972 :
1973 1 : TO_ORIGIN_CIRCUIT(client_side)->p_streams = 0;
1974 1 : circpad_machine_event_circ_has_no_streams(TO_ORIGIN_CIRCUIT(client_side));
1975 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2);
1976 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2);
1977 :
1978 : /* Now make the circuit opened and send built event */
1979 1 : TO_ORIGIN_CIRCUIT(client_side)->has_opened = 1;
1980 1 : circpad_machine_event_circ_built(TO_ORIGIN_CIRCUIT(client_side));
1981 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2);
1982 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2);
1983 :
1984 1 : TO_ORIGIN_CIRCUIT(client_side)->remaining_relay_early_cells = 0;
1985 1 : circpad_machine_event_circ_has_no_relay_early(
1986 1 : TO_ORIGIN_CIRCUIT(client_side));
1987 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2);
1988 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2);
1989 :
1990 1 : get_options_mutable()->HSLayer2Nodes = (void*)1;
1991 1 : TO_ORIGIN_CIRCUIT(client_side)->p_streams = (void*)1;
1992 1 : circpad_machine_event_circ_has_streams(TO_ORIGIN_CIRCUIT(client_side));
1993 :
1994 : /* Verify different machine is added */
1995 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 3);
1996 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 3);
1997 :
1998 : /* Hold off on negotiated */
1999 1 : deliver_negotiated = 0;
2000 :
2001 : /* Deliver a padding cell to the client, to trigger burst state */
2002 1 : circpad_cell_event_padding_sent(client_side);
2003 :
2004 : /* This should have trigger length shutdown condition on client
2005 : * but not the response for the padding machine */
2006 1 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
2007 1 : tt_ptr_op(client_side->padding_machine[0], OP_NE, NULL);
2008 :
2009 : /* Verify machine is gone from the relay (but negotiated not back yet */
2010 1 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
2011 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
2012 :
2013 : /* Add another hop and verify it's back */
2014 1 : simulate_single_hop_extend(client_side, relay_side, 1);
2015 :
2016 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 3);
2017 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 3);
2018 :
2019 1 : tt_ptr_op(client_side->padding_info[0], OP_NE, NULL);
2020 1 : tt_ptr_op(relay_side->padding_info[0], OP_NE, NULL);
2021 :
2022 1 : done:
2023 : /* XXX: Free everything */
2024 1 : testing_disable_reproducible_rng();
2025 1 : return;
2026 : }
2027 :
2028 : /** Disabled unstable test until #29298 is implemented (see #29122) */
2029 : #if 0
2030 : void
2031 : test_circuitpadding_circuitsetup_machine(void *arg)
2032 : {
2033 : int64_t actual_mocked_monotime_start;
2034 : /**
2035 : * Test case plan:
2036 : *
2037 : * 1. Simulate a normal circuit setup pattern
2038 : * a. Application traffic
2039 : *
2040 : * FIXME: This should focus more on exercising the machine
2041 : * features rather than actual traffic patterns. For example,
2042 : * test cancellation and bins empty/refill
2043 : */
2044 : (void)arg;
2045 :
2046 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
2047 :
2048 : dummy_channel.cmux = circuitmux_alloc();
2049 : client_side = TO_CIRCUIT(origin_circuit_new());
2050 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
2051 :
2052 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
2053 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2054 :
2055 : nodes_init();
2056 :
2057 : monotime_init();
2058 : monotime_enable_test_mocking();
2059 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
2060 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
2061 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
2062 : curr_mocked_time = actual_mocked_monotime_start;
2063 :
2064 : timers_initialize();
2065 : circpad_machines_init();
2066 :
2067 : MOCK(circuit_package_relay_cell,
2068 : circuit_package_relay_cell_mock);
2069 : MOCK(node_get_by_id,
2070 : node_get_by_id_mock);
2071 :
2072 : /* Test case #1: Build a 3 hop circuit, then wait and let pad */
2073 : simulate_single_hop_extend(client_side, relay_side, 1);
2074 : simulate_single_hop_extend(client_side, relay_side, 1);
2075 : simulate_single_hop_extend(client_side, relay_side, 1);
2076 :
2077 : tt_int_op(n_client_cells, OP_EQ, 1);
2078 : tt_int_op(n_relay_cells, OP_EQ, 1);
2079 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
2080 : CIRCPAD_STATE_BURST);
2081 : tt_int_op(relay_side->padding_info[0]->current_state, OP_EQ,
2082 : CIRCPAD_STATE_BURST);
2083 :
2084 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2085 : OP_NE, 0);
2086 : tt_int_op(relay_side->padding_info[0]->is_padding_timer_scheduled,
2087 : OP_EQ, 0);
2088 : timers_advance_and_run(2000);
2089 : tt_int_op(n_client_cells, OP_EQ, 2);
2090 : tt_int_op(n_relay_cells, OP_EQ, 1);
2091 :
2092 : tt_int_op(relay_side->padding_info[0]->current_state, OP_EQ,
2093 : CIRCPAD_STATE_GAP);
2094 :
2095 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2096 : OP_EQ, 0);
2097 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2098 : OP_NE, 0);
2099 : timers_advance_and_run(5000);
2100 : tt_int_op(n_client_cells, OP_EQ, 2);
2101 : tt_int_op(n_relay_cells, OP_EQ, 2);
2102 :
2103 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2104 : OP_NE, 0);
2105 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2106 : OP_EQ, 0);
2107 : timers_advance_and_run(2000);
2108 : tt_int_op(n_client_cells, OP_EQ, 3);
2109 : tt_int_op(n_relay_cells, OP_EQ, 2);
2110 :
2111 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2112 : OP_EQ, 0);
2113 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2114 : OP_NE, 0);
2115 : timers_advance_and_run(5000);
2116 : tt_int_op(n_client_cells, OP_EQ, 3);
2117 : tt_int_op(n_relay_cells, OP_EQ, 3);
2118 :
2119 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2120 : OP_NE, 0);
2121 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2122 : OP_EQ, 0);
2123 : timers_advance_and_run(2000);
2124 : tt_int_op(n_client_cells, OP_EQ, 4);
2125 : tt_int_op(n_relay_cells, OP_EQ, 3);
2126 :
2127 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2128 : OP_EQ, 0);
2129 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2130 : OP_NE, 0);
2131 : timers_advance_and_run(5000);
2132 : tt_int_op(n_client_cells, OP_EQ, 4);
2133 : tt_int_op(n_relay_cells, OP_EQ, 4);
2134 :
2135 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2136 : OP_NE, 0);
2137 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2138 : OP_EQ, 0);
2139 : timers_advance_and_run(2000);
2140 : tt_int_op(n_client_cells, OP_EQ, 5);
2141 : tt_int_op(n_relay_cells, OP_EQ, 4);
2142 :
2143 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2144 : OP_EQ, 0);
2145 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2146 : OP_NE, 0);
2147 : timers_advance_and_run(5000);
2148 : tt_int_op(n_client_cells, OP_EQ, 5);
2149 : tt_int_op(n_relay_cells, OP_EQ, 5);
2150 :
2151 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2152 : OP_NE, 0);
2153 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2154 : OP_EQ, 0);
2155 : timers_advance_and_run(2000);
2156 : tt_int_op(n_client_cells, OP_EQ, 6);
2157 : tt_int_op(n_relay_cells, OP_EQ, 5);
2158 :
2159 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2160 : OP_EQ, 0);
2161 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2162 : OP_NE, 0);
2163 : timers_advance_and_run(5000);
2164 : tt_int_op(n_client_cells, OP_EQ, 6);
2165 : tt_int_op(n_relay_cells, OP_EQ, 6);
2166 :
2167 : tt_int_op(client_side->padding_info[0]->current_state,
2168 : OP_EQ, CIRCPAD_STATE_END);
2169 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2170 : OP_EQ, 0);
2171 : tt_int_op(relay_side->padding_info[0]->current_state,
2172 : OP_EQ, CIRCPAD_STATE_GAP);
2173 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2174 : OP_EQ, 0);
2175 :
2176 : /* Verify we can't schedule padding in END state */
2177 : circpad_decision_t ret =
2178 : circpad_machine_schedule_padding(client_side->padding_info[0]);
2179 : tt_int_op(ret, OP_EQ, CIRCPAD_STATE_UNCHANGED);
2180 :
2181 : /* Simulate application traffic */
2182 : circpad_cell_event_nonpadding_sent(client_side);
2183 : circpad_deliver_unrecognized_cell_events(relay_side, CELL_DIRECTION_OUT);
2184 : circpad_deliver_unrecognized_cell_events(relay_side, CELL_DIRECTION_IN);
2185 : circpad_deliver_recognized_relay_cell_events(client_side, RELAY_COMMAND_DATA,
2186 : TO_ORIGIN_CIRCUIT(client_side)->cpath->next);
2187 :
2188 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
2189 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
2190 :
2191 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
2192 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
2193 : tt_int_op(n_client_cells, OP_EQ, 6);
2194 : tt_int_op(n_relay_cells, OP_EQ, 7);
2195 :
2196 : // Test timer cancellation
2197 : simulate_single_hop_extend(client_side, relay_side, 1);
2198 : simulate_single_hop_extend(client_side, relay_side, 1);
2199 : timers_advance_and_run(5000);
2200 : circpad_cell_event_padding_received(client_side);
2201 :
2202 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
2203 : CIRCPAD_STATE_BURST);
2204 : tt_int_op(relay_side->padding_info[0]->current_state, OP_EQ,
2205 : CIRCPAD_STATE_GAP);
2206 :
2207 : tt_int_op(n_client_cells, OP_EQ, 8);
2208 : tt_int_op(n_relay_cells, OP_EQ, 8);
2209 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2210 : OP_NE, 0);
2211 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2212 : OP_NE, 0);
2213 :
2214 : /* Test timer cancel due to state rules */
2215 : circpad_cell_event_nonpadding_sent(client_side);
2216 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2217 : OP_EQ, 0);
2218 : circpad_cell_event_padding_received(client_side);
2219 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2220 : OP_NE, 0);
2221 :
2222 : /* Simulate application traffic to cancel timer */
2223 : circpad_cell_event_nonpadding_sent(client_side);
2224 : circpad_deliver_unrecognized_cell_events(relay_side, CELL_DIRECTION_OUT);
2225 : circpad_deliver_unrecognized_cell_events(relay_side, CELL_DIRECTION_IN);
2226 : circpad_deliver_recognized_relay_cell_events(client_side, RELAY_COMMAND_DATA,
2227 : TO_ORIGIN_CIRCUIT(client_side)->cpath->next);
2228 :
2229 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
2230 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
2231 :
2232 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
2233 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
2234 :
2235 : /* No cells sent, except negotiate end from relay */
2236 : tt_int_op(n_client_cells, OP_EQ, 8);
2237 : tt_int_op(n_relay_cells, OP_EQ, 9);
2238 :
2239 : /* Test mark for close and free */
2240 : simulate_single_hop_extend(client_side, relay_side, 1);
2241 : simulate_single_hop_extend(client_side, relay_side, 1);
2242 : timers_advance_and_run(5000);
2243 : circpad_cell_event_padding_received(client_side);
2244 :
2245 : tt_int_op(n_client_cells, OP_EQ, 10);
2246 : tt_int_op(n_relay_cells, OP_EQ, 10);
2247 :
2248 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
2249 : CIRCPAD_STATE_BURST);
2250 : tt_int_op(relay_side->padding_info[0]->current_state, OP_EQ,
2251 : CIRCPAD_STATE_GAP);
2252 :
2253 : tt_u64_op(client_side->padding_info[0]->padding_scheduled_at_usec,
2254 : OP_NE, 0);
2255 : tt_u64_op(relay_side->padding_info[0]->padding_scheduled_at_usec,
2256 : OP_NE, 0);
2257 : circuit_mark_for_close(client_side, END_CIRC_REASON_FLAG_REMOTE);
2258 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
2259 : timers_advance_and_run(5000);
2260 :
2261 : /* No cells sent */
2262 : tt_int_op(n_client_cells, OP_EQ, 10);
2263 : tt_int_op(n_relay_cells, OP_EQ, 10);
2264 :
2265 : done:
2266 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
2267 :
2268 : circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
2269 : circuitmux_free(dummy_channel.cmux);
2270 : timers_shutdown();
2271 : monotime_disable_test_mocking();
2272 : UNMOCK(circuit_package_relay_cell);
2273 : UNMOCK(circuitmux_attach_circuit);
2274 :
2275 : return;
2276 : }
2277 : #endif /* 0 */
2278 :
2279 : /** Helper function: Initializes a padding machine where every state uses the
2280 : * uniform probability distribution. */
2281 : static void
2282 1 : helper_circpad_circ_distribution_machine_setup(int min, int max)
2283 : {
2284 1 : circpad_machine_states_init(&circ_client_machine, 7);
2285 :
2286 1 : circpad_state_t *zero_st = &circ_client_machine.states[0];
2287 1 : zero_st->next_state[CIRCPAD_EVENT_NONPADDING_RECV] = 1;
2288 1 : zero_st->iat_dist.type = CIRCPAD_DIST_UNIFORM;
2289 : /* param2 is upper bound, param1 is lower */
2290 1 : zero_st->iat_dist.param1 = min;
2291 1 : zero_st->iat_dist.param2 = max;
2292 1 : zero_st->dist_added_shift_usec = min;
2293 1 : zero_st->dist_max_sample_usec = max;
2294 :
2295 1 : circpad_state_t *first_st = &circ_client_machine.states[1];
2296 1 : first_st->next_state[CIRCPAD_EVENT_NONPADDING_RECV] = 2;
2297 1 : first_st->iat_dist.type = CIRCPAD_DIST_LOGISTIC;
2298 : /* param1 is Mu, param2 is sigma. */
2299 1 : first_st->iat_dist.param1 = 9;
2300 1 : first_st->iat_dist.param2 = 3;
2301 1 : first_st->dist_added_shift_usec = min;
2302 1 : first_st->dist_max_sample_usec = max;
2303 :
2304 1 : circpad_state_t *second_st = &circ_client_machine.states[2];
2305 1 : second_st->next_state[CIRCPAD_EVENT_NONPADDING_RECV] = 3;
2306 1 : second_st->iat_dist.type = CIRCPAD_DIST_LOG_LOGISTIC;
2307 : /* param1 is Alpha, param2 is 1.0/Beta */
2308 1 : second_st->iat_dist.param1 = 1;
2309 1 : second_st->iat_dist.param2 = 0.5;
2310 1 : second_st->dist_added_shift_usec = min;
2311 1 : second_st->dist_max_sample_usec = max;
2312 :
2313 1 : circpad_state_t *third_st = &circ_client_machine.states[3];
2314 1 : third_st->next_state[CIRCPAD_EVENT_NONPADDING_RECV] = 4;
2315 1 : third_st->iat_dist.type = CIRCPAD_DIST_GEOMETRIC;
2316 : /* param1 is 'p' (success probability) */
2317 1 : third_st->iat_dist.param1 = 0.2;
2318 1 : third_st->dist_added_shift_usec = min;
2319 1 : third_st->dist_max_sample_usec = max;
2320 :
2321 1 : circpad_state_t *fourth_st = &circ_client_machine.states[4];
2322 1 : fourth_st->next_state[CIRCPAD_EVENT_NONPADDING_RECV] = 5;
2323 1 : fourth_st->iat_dist.type = CIRCPAD_DIST_WEIBULL;
2324 : /* param1 is k, param2 is Lambda */
2325 1 : fourth_st->iat_dist.param1 = 1.5;
2326 1 : fourth_st->iat_dist.param2 = 1;
2327 1 : fourth_st->dist_added_shift_usec = min;
2328 1 : fourth_st->dist_max_sample_usec = max;
2329 :
2330 1 : circpad_state_t *fifth_st = &circ_client_machine.states[5];
2331 1 : fifth_st->next_state[CIRCPAD_EVENT_NONPADDING_RECV] = 6;
2332 1 : fifth_st->iat_dist.type = CIRCPAD_DIST_PARETO;
2333 : /* param1 is sigma, param2 is xi */
2334 1 : fifth_st->iat_dist.param1 = 1;
2335 1 : fifth_st->iat_dist.param2 = 5;
2336 1 : fifth_st->dist_added_shift_usec = min;
2337 1 : fifth_st->dist_max_sample_usec = max;
2338 1 : }
2339 :
2340 : /** Simple test that the padding delays sampled from a uniform distribution
2341 : * actually fail within the uniform distribution range. */
2342 : static void
2343 1 : test_circuitpadding_sample_distribution(void *arg)
2344 : {
2345 1 : circpad_machine_runtime_t *mi;
2346 1 : int n_samples;
2347 1 : int n_states;
2348 :
2349 1 : (void) arg;
2350 :
2351 : /* mock this function so that we dont actually schedule any padding */
2352 1 : MOCK(circpad_machine_schedule_padding,
2353 : circpad_machine_schedule_padding_mock);
2354 1 : testing_enable_reproducible_rng();
2355 :
2356 : /* Initialize a machine with multiple probability distributions */
2357 1 : circpad_machines_init();
2358 1 : helper_circpad_circ_distribution_machine_setup(0, 10);
2359 :
2360 : /* Initialize machine and circuits */
2361 1 : client_side = TO_CIRCUIT(origin_circuit_new());
2362 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2363 1 : client_side->padding_machine[0] = &circ_client_machine;
2364 2 : client_side->padding_info[0] =
2365 1 : circpad_circuit_machineinfo_new(client_side, 0);
2366 1 : mi = client_side->padding_info[0];
2367 :
2368 : /* For every state, sample a bunch of values from the distribution and ensure
2369 : * they fall within range. */
2370 7 : for (n_states = 0 ; n_states < 6; n_states++) {
2371 : /* Make sure we in the right state */
2372 6 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ, n_states);
2373 :
2374 606 : for (n_samples = 0; n_samples < 100; n_samples++) {
2375 600 : circpad_delay_t delay = circpad_machine_sample_delay(mi);
2376 600 : tt_int_op(delay, OP_GE, 0);
2377 600 : tt_int_op(delay, OP_LE, 10);
2378 : }
2379 :
2380 : /* send a non-padding cell to move to the next machine state */
2381 6 : circpad_cell_event_nonpadding_received(client_side);
2382 : }
2383 :
2384 1 : done:
2385 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
2386 1 : UNMOCK(circpad_machine_schedule_padding);
2387 1 : testing_disable_reproducible_rng();
2388 1 : }
2389 :
2390 : static circpad_decision_t
2391 131268 : circpad_machine_spec_transition_mock(circpad_machine_runtime_t *mi,
2392 : circpad_event_t event)
2393 : {
2394 131268 : (void) mi;
2395 131268 : (void) event;
2396 :
2397 131268 : return CIRCPAD_STATE_UNCHANGED;
2398 : }
2399 :
2400 : /* Test per-machine padding rate limits */
2401 : static void
2402 1 : test_circuitpadding_machine_rate_limiting(void *arg)
2403 : {
2404 1 : (void) arg;
2405 1 : bool retval;
2406 1 : circpad_machine_runtime_t *mi;
2407 1 : int i;
2408 :
2409 : /* Ignore machine transitions for the purposes of this function, we only
2410 : * really care about padding counts */
2411 1 : MOCK(circpad_machine_spec_transition, circpad_machine_spec_transition_mock);
2412 1 : MOCK(circpad_send_command_to_hop, circpad_send_command_to_hop_mock);
2413 1 : testing_enable_reproducible_rng();
2414 :
2415 : /* Setup machine and circuits */
2416 1 : client_side = TO_CIRCUIT(origin_circuit_new());
2417 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2418 1 : helper_create_basic_machine();
2419 1 : client_side->padding_machine[0] = &circ_client_machine;
2420 2 : client_side->padding_info[0] =
2421 1 : circpad_circuit_machineinfo_new(client_side, 0);
2422 1 : mi = client_side->padding_info[0];
2423 : /* Set up the machine info so that we can get through the basic functions */
2424 1 : mi->state_length = CIRCPAD_STATE_LENGTH_INFINITE;
2425 :
2426 : /* First we are going to test the per-machine rate limits */
2427 1 : circ_client_machine.max_padding_percent = 50;
2428 1 : circ_client_machine.allowed_padding_count = 100;
2429 :
2430 : /* Check padding limit, should be fine since we haven't sent anything yet. */
2431 1 : retval = circpad_machine_reached_padding_limit(mi);
2432 1 : tt_int_op(retval, OP_EQ, 0);
2433 :
2434 : /* Send 99 padding cells which is below circpad_global_allowed_cells=100, so
2435 : * the rate limit will not trigger */
2436 100 : for (i=0;i<99;i++) {
2437 99 : circpad_send_padding_cell_for_callback(mi);
2438 : }
2439 1 : retval = circpad_machine_reached_padding_limit(mi);
2440 1 : tt_int_op(retval, OP_EQ, 0);
2441 :
2442 : /* Now send another padding cell to pass circpad_global_allowed_cells=100,
2443 : and see that the limit will trigger */
2444 1 : circpad_send_padding_cell_for_callback(mi);
2445 1 : retval = circpad_machine_reached_padding_limit(mi);
2446 1 : tt_int_op(retval, OP_EQ, 1);
2447 :
2448 1 : retval = circpad_machine_schedule_padding(mi);
2449 1 : tt_int_op(retval, OP_EQ, CIRCPAD_STATE_UNCHANGED);
2450 :
2451 : /* Cover wrap */
2452 65437 : for (;i<UINT16_MAX;i++) {
2453 65436 : circpad_send_padding_cell_for_callback(mi);
2454 : }
2455 1 : tt_int_op(mi->padding_sent, OP_EQ, UINT16_MAX/2+1);
2456 :
2457 1 : tt_ptr_op(client_side->padding_info[0], OP_EQ, mi);
2458 65536 : for (i=0;i<UINT16_MAX;i++) {
2459 65535 : circpad_cell_event_nonpadding_sent(client_side);
2460 : }
2461 :
2462 1 : tt_int_op(mi->nonpadding_sent, OP_EQ, UINT16_MAX/2);
2463 1 : tt_int_op(mi->padding_sent, OP_EQ, UINT16_MAX/4+1);
2464 :
2465 1 : done:
2466 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
2467 1 : testing_disable_reproducible_rng();
2468 1 : }
2469 :
2470 : /* Test global padding rate limits */
2471 : static void
2472 1 : test_circuitpadding_global_rate_limiting(void *arg)
2473 : {
2474 1 : (void) arg;
2475 1 : bool retval;
2476 1 : circpad_machine_runtime_t *mi;
2477 1 : int i;
2478 1 : int64_t actual_mocked_monotime_start;
2479 :
2480 : /* Ignore machine transitions for the purposes of this function, we only
2481 : * really care about padding counts */
2482 1 : MOCK(circpad_machine_spec_transition, circpad_machine_spec_transition_mock);
2483 1 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
2484 1 : MOCK(circuit_package_relay_cell,
2485 : circuit_package_relay_cell_mock);
2486 1 : MOCK(monotime_absolute_usec, mock_monotime_absolute_usec);
2487 1 : testing_enable_reproducible_rng();
2488 :
2489 1 : monotime_init();
2490 1 : monotime_enable_test_mocking();
2491 1 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
2492 1 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
2493 1 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
2494 1 : curr_mocked_time = actual_mocked_monotime_start;
2495 1 : timers_initialize();
2496 :
2497 1 : client_side = TO_CIRCUIT(origin_circuit_new());
2498 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2499 1 : dummy_channel.cmux = circuitmux_alloc();
2500 :
2501 : /* Setup machine and circuits */
2502 1 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
2503 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
2504 1 : helper_create_basic_machine();
2505 1 : relay_side->padding_machine[0] = &circ_client_machine;
2506 2 : relay_side->padding_info[0] =
2507 1 : circpad_circuit_machineinfo_new(relay_side, 0);
2508 1 : mi = relay_side->padding_info[0];
2509 : /* Set up the machine info so that we can get through the basic functions */
2510 1 : mi->state_length = CIRCPAD_STATE_LENGTH_INFINITE;
2511 :
2512 1 : simulate_single_hop_extend(client_side, relay_side, 1);
2513 1 : simulate_single_hop_extend(client_side, relay_side, 1);
2514 :
2515 : /* Now test the global limits by setting up the consensus */
2516 1 : networkstatus_t vote1;
2517 1 : vote1.net_params = smartlist_new();
2518 1 : smartlist_split_string(vote1.net_params,
2519 : "circpad_global_allowed_cells=100 circpad_global_max_padding_pct=50",
2520 : NULL, 0, 0);
2521 : /* Register global limits with the padding subsystem */
2522 1 : circpad_new_consensus_params(&vote1);
2523 :
2524 : /* Check padding limit, should be fine since we haven't sent anything yet. */
2525 1 : retval = circpad_machine_reached_padding_limit(mi);
2526 1 : tt_int_op(retval, OP_EQ, 0);
2527 :
2528 : /* Send 99 padding cells which is below circpad_global_allowed_cells=100, so
2529 : * the rate limit will not trigger */
2530 100 : for (i=0;i<99;i++) {
2531 99 : circpad_send_padding_cell_for_callback(mi);
2532 : }
2533 1 : retval = circpad_machine_reached_padding_limit(mi);
2534 1 : tt_int_op(retval, OP_EQ, 0);
2535 :
2536 : /* Now send another padding cell to pass circpad_global_allowed_cells=100,
2537 : and see that the limit will trigger */
2538 1 : circpad_send_padding_cell_for_callback(mi);
2539 1 : retval = circpad_machine_reached_padding_limit(mi);
2540 1 : tt_int_op(retval, OP_EQ, 1);
2541 :
2542 1 : retval = circpad_machine_schedule_padding(mi);
2543 1 : tt_int_op(retval, OP_EQ, CIRCPAD_STATE_UNCHANGED);
2544 :
2545 : /* Now send 92 non-padding cells to get near the
2546 : * circpad_global_max_padding_pct=50 limit; in particular with 96 non-padding
2547 : * cells, the padding traffic is still 51% of total traffic so limit should
2548 : * trigger */
2549 93 : for (i=0;i<92;i++) {
2550 92 : circpad_cell_event_nonpadding_sent(relay_side);
2551 : }
2552 1 : retval = circpad_machine_reached_padding_limit(mi);
2553 1 : tt_int_op(retval, OP_EQ, 1);
2554 :
2555 : /* Send another non-padding cell to bring the padding traffic to 50% of total
2556 : * traffic and get past the limit */
2557 1 : circpad_cell_event_nonpadding_sent(relay_side);
2558 1 : retval = circpad_machine_reached_padding_limit(mi);
2559 1 : tt_int_op(retval, OP_EQ, 0);
2560 :
2561 1 : done:
2562 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
2563 1 : circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
2564 1 : circuitmux_free(dummy_channel.cmux);
2565 3 : SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp));
2566 1 : smartlist_free(vote1.net_params);
2567 1 : testing_disable_reproducible_rng();
2568 1 : }
2569 :
2570 : /* Test reduced and disabled padding */
2571 : static void
2572 1 : test_circuitpadding_reduce_disable(void *arg)
2573 : {
2574 1 : (void) arg;
2575 1 : int64_t actual_mocked_monotime_start;
2576 :
2577 1 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
2578 1 : testing_enable_reproducible_rng();
2579 :
2580 1 : nodes_init();
2581 1 : dummy_channel.cmux = circuitmux_alloc();
2582 1 : relay_side = (circuit_t *)new_fake_orcirc(&dummy_channel,
2583 : &dummy_channel);
2584 1 : client_side = (circuit_t *)origin_circuit_new();
2585 1 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
2586 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2587 :
2588 1 : circpad_machines_init();
2589 1 : helper_create_conditional_machines();
2590 :
2591 1 : monotime_init();
2592 1 : monotime_enable_test_mocking();
2593 1 : actual_mocked_monotime_start = MONOTIME_MOCK_START;
2594 1 : monotime_set_mock_time_nsec(actual_mocked_monotime_start);
2595 1 : monotime_coarse_set_mock_time_nsec(actual_mocked_monotime_start);
2596 1 : curr_mocked_time = actual_mocked_monotime_start;
2597 1 : timers_initialize();
2598 :
2599 : /* This is needed so that we are not considered to be dormant */
2600 1 : note_user_activity(20);
2601 :
2602 1 : MOCK(circuit_package_relay_cell,
2603 : circuit_package_relay_cell_mock);
2604 1 : MOCK(node_get_by_id,
2605 : node_get_by_id_mock);
2606 :
2607 : /* Simulate extend. This should result in the original machine getting
2608 : * added, since the circuit is not built */
2609 1 : simulate_single_hop_extend(client_side, relay_side, 1);
2610 1 : simulate_single_hop_extend(client_side, relay_side, 1);
2611 :
2612 : /* Verify that machine #2 is added */
2613 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2);
2614 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2);
2615 :
2616 : /* Deliver a padding cell to the client, to trigger burst state */
2617 1 : circpad_cell_event_padding_sent(client_side);
2618 :
2619 : /* This should have trigger length shutdown condition on client.. */
2620 1 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
2621 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
2622 :
2623 : /* Verify machine is gone from both sides */
2624 1 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
2625 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
2626 :
2627 : /* Now test the reduced padding machine by setting up the consensus */
2628 1 : networkstatus_t vote1;
2629 1 : vote1.net_params = smartlist_new();
2630 1 : smartlist_split_string(vote1.net_params,
2631 : "circpad_padding_reduced=1", NULL, 0, 0);
2632 :
2633 : /* Register reduced padding machine with the padding subsystem */
2634 1 : circpad_new_consensus_params(&vote1);
2635 :
2636 1 : simulate_single_hop_extend(client_side, relay_side, 1);
2637 :
2638 : /* Verify that machine #0 is added */
2639 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2);
2640 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2);
2641 :
2642 1 : tt_int_op(
2643 : circpad_machine_reached_padding_limit(client_side->padding_info[0]),
2644 : OP_EQ, 0);
2645 1 : tt_int_op(
2646 : circpad_machine_reached_padding_limit(relay_side->padding_info[0]),
2647 : OP_EQ, 0);
2648 :
2649 : /* Test that machines get torn down when padding is disabled */
2650 2 : SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp));
2651 1 : smartlist_free(vote1.net_params);
2652 1 : vote1.net_params = smartlist_new();
2653 1 : smartlist_split_string(vote1.net_params,
2654 : "circpad_padding_disabled=1", NULL, 0, 0);
2655 :
2656 : /* Register reduced padding machine with the padding subsystem */
2657 1 : circpad_new_consensus_params(&vote1);
2658 :
2659 1 : tt_int_op(
2660 : circpad_machine_schedule_padding(client_side->padding_info[0]),
2661 : OP_EQ, CIRCPAD_STATE_UNCHANGED);
2662 1 : tt_int_op(
2663 : circpad_machine_schedule_padding(relay_side->padding_info[0]),
2664 : OP_EQ, CIRCPAD_STATE_UNCHANGED);
2665 :
2666 : /* Signal that circuit is built: this event causes us to re-evaluate
2667 : * machine conditions (which don't apply because padding is disabled). */
2668 1 : circpad_machine_event_circ_built(TO_ORIGIN_CIRCUIT(client_side));
2669 :
2670 1 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
2671 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
2672 1 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
2673 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
2674 :
2675 2 : SMARTLIST_FOREACH(vote1.net_params, char *, cp, tor_free(cp));
2676 1 : smartlist_free(vote1.net_params);
2677 1 : vote1.net_params = NULL;
2678 1 : circpad_new_consensus_params(&vote1);
2679 :
2680 1 : get_options_mutable()->ReducedCircuitPadding = 1;
2681 :
2682 1 : simulate_single_hop_extend(client_side, relay_side, 1);
2683 :
2684 : /* Verify that machine #0 is added */
2685 1 : tt_int_op(client_side->padding_machine[0]->machine_num, OP_EQ, 2);
2686 1 : tt_int_op(relay_side->padding_machine[0]->machine_num, OP_EQ, 2);
2687 :
2688 1 : tt_int_op(
2689 : circpad_machine_reached_padding_limit(client_side->padding_info[0]),
2690 : OP_EQ, 0);
2691 1 : tt_int_op(
2692 : circpad_machine_reached_padding_limit(relay_side->padding_info[0]),
2693 : OP_EQ, 0);
2694 :
2695 1 : get_options_mutable()->CircuitPadding = 0;
2696 :
2697 1 : tt_int_op(
2698 : circpad_machine_schedule_padding(client_side->padding_info[0]),
2699 : OP_EQ, CIRCPAD_STATE_UNCHANGED);
2700 1 : tt_int_op(
2701 : circpad_machine_schedule_padding(relay_side->padding_info[0]),
2702 : OP_EQ, CIRCPAD_STATE_UNCHANGED);
2703 :
2704 : /* Signal that circuit is built: this event causes us to re-evaluate
2705 : * machine conditions (which don't apply because padding is disabled). */
2706 :
2707 1 : circpad_machine_event_circ_built(TO_ORIGIN_CIRCUIT(client_side));
2708 :
2709 1 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
2710 1 : tt_ptr_op(client_side->padding_machine[0], OP_EQ, NULL);
2711 1 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
2712 1 : tt_ptr_op(relay_side->padding_machine[0], OP_EQ, NULL);
2713 :
2714 1 : done:
2715 1 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
2716 1 : circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
2717 1 : circuitmux_free(dummy_channel.cmux);
2718 1 : testing_disable_reproducible_rng();
2719 1 : }
2720 :
2721 : /** Just a basic machine whose whole purpose is to reach the END state */
2722 : static void
2723 2 : helper_create_ender_machine(void)
2724 : {
2725 : /* Start, burst */
2726 2 : circpad_machine_states_init(&circ_client_machine, 2);
2727 :
2728 2 : circ_client_machine.states[CIRCPAD_STATE_START].
2729 2 : next_state[CIRCPAD_EVENT_NONPADDING_RECV] = CIRCPAD_STATE_END;
2730 :
2731 2 : circ_client_machine.conditions.apply_state_mask = CIRCPAD_STATE_ALL;
2732 2 : circ_client_machine.conditions.apply_purpose_mask = CIRCPAD_PURPOSE_ALL;
2733 2 : }
2734 :
2735 : static time_t mocked_timeofday;
2736 : /** Set timeval to a mock date and time. This is necessary
2737 : * to make tor_gettimeofday() mockable. */
2738 : static void
2739 8 : mock_tor_gettimeofday(struct timeval *timeval)
2740 : {
2741 8 : timeval->tv_sec = mocked_timeofday;
2742 8 : timeval->tv_usec = 0;
2743 8 : }
2744 :
2745 : /** Test manual managing of circuit lifetimes by the circuitpadding
2746 : * subsystem. In particular this test goes through all the cases of the
2747 : * circpad_marked_circuit_for_padding() function, via
2748 : * circuit_mark_for_close() as well as
2749 : * circuit_expire_old_circuits_clientside(). */
2750 : static void
2751 1 : test_circuitpadding_manage_circuit_lifetime(void *arg)
2752 : {
2753 1 : circpad_machine_runtime_t *mi;
2754 :
2755 1 : (void) arg;
2756 :
2757 1 : client_side = (circuit_t *)origin_circuit_new();
2758 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2759 1 : monotime_enable_test_mocking();
2760 1 : MOCK(tor_gettimeofday, mock_tor_gettimeofday);
2761 1 : mocked_timeofday = 23;
2762 :
2763 1 : helper_create_ender_machine();
2764 :
2765 : /* Enable manual circuit lifetime manage for this test */
2766 1 : circ_client_machine.manage_circ_lifetime = 1;
2767 :
2768 : /* Test setup */
2769 1 : client_side->padding_machine[0] = &circ_client_machine;
2770 2 : client_side->padding_info[0] =
2771 1 : circpad_circuit_machineinfo_new(client_side, 0);
2772 1 : mi = client_side->padding_info[0];
2773 :
2774 1 : tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_START);
2775 :
2776 : /* Check that the circuit is not marked for close */
2777 1 : tt_int_op(client_side->marked_for_close, OP_EQ, 0);
2778 1 : tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_GENERAL);
2779 :
2780 : /* Mark this circuit for close due to a remote reason */
2781 1 : circuit_mark_for_close(client_side,
2782 : END_CIRC_REASON_FLAG_REMOTE|END_CIRC_REASON_NONE);
2783 1 : tt_ptr_op(client_side->padding_info[0], OP_NE, NULL);
2784 1 : tt_int_op(client_side->marked_for_close, OP_NE, 0);
2785 1 : tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_GENERAL);
2786 1 : client_side->marked_for_close = 0;
2787 :
2788 : /* Mark this circuit for close due to a protocol issue */
2789 1 : circuit_mark_for_close(client_side, END_CIRC_REASON_TORPROTOCOL);
2790 1 : tt_int_op(client_side->marked_for_close, OP_NE, 0);
2791 1 : tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_GENERAL);
2792 1 : client_side->marked_for_close = 0;
2793 :
2794 : /* Mark a measurement circuit for close */
2795 1 : client_side->purpose = CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT;
2796 1 : circuit_mark_for_close(client_side, END_CIRC_REASON_NONE);
2797 1 : tt_int_op(client_side->marked_for_close, OP_NE, 0);
2798 1 : tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_MEASURE_TIMEOUT);
2799 1 : client_side->marked_for_close = 0;
2800 :
2801 : /* Mark a general circuit for close */
2802 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2803 1 : circuit_mark_for_close(client_side, END_CIRC_REASON_NONE);
2804 :
2805 : /* Check that this circuit is still not marked for close since we are
2806 : * managing the lifetime manually, but the circuit was tagged as such by the
2807 : * circpadding subsystem */
2808 1 : tt_int_op(client_side->marked_for_close, OP_EQ, 0);
2809 1 : tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_CIRCUIT_PADDING);
2810 :
2811 : /* We just tested case (1) from the comments of
2812 : * circpad_circuit_should_be_marked_for_close() */
2813 :
2814 : /* Transition the machine to the END state but did not delete its machine */
2815 1 : tt_ptr_op(client_side->padding_info[0], OP_NE, NULL);
2816 1 : circpad_cell_event_nonpadding_received(client_side);
2817 1 : tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END);
2818 :
2819 : /* We just tested case (3) from the comments of
2820 : * circpad_circuit_should_be_marked_for_close().
2821 : * Now let's go for case (2). */
2822 :
2823 : /* Reset the close mark */
2824 1 : client_side->marked_for_close = 0;
2825 :
2826 : /* Mark this circuit for close */
2827 1 : circuit_mark_for_close(client_side, 0);
2828 :
2829 : /* See that the circ got closed since we are already in END state */
2830 1 : tt_int_op(client_side->marked_for_close, OP_NE, 0);
2831 :
2832 : /* We just tested case (2). Now let's see that case (4) is unreachable as
2833 : that comment claims */
2834 :
2835 : /* First, reset all close marks and tags */
2836 1 : client_side->marked_for_close = 0;
2837 1 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2838 :
2839 : /* Now re-create the ender machine so that we can transition to END again */
2840 : /* Free up some stuff first */
2841 1 : circpad_circuit_free_all_machineinfos(client_side);
2842 1 : tor_free(circ_client_machine.states);
2843 1 : helper_create_ender_machine();
2844 :
2845 1 : client_side->padding_machine[0] = &circ_client_machine;
2846 2 : client_side->padding_info[0] =
2847 1 : circpad_circuit_machineinfo_new(client_side, 0);
2848 1 : mi = client_side->padding_info[0];
2849 :
2850 : /* Check we are in START. */
2851 1 : tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_START);
2852 :
2853 : /* Test that we don't expire this circuit yet */
2854 1 : client_side->timestamp_dirty = 0;
2855 1 : client_side->state = CIRCUIT_STATE_OPEN;
2856 1 : tor_gettimeofday(&client_side->timestamp_began);
2857 1 : TO_ORIGIN_CIRCUIT(client_side)->circuit_idle_timeout = 23;
2858 1 : mocked_timeofday += 24;
2859 1 : circuit_expire_old_circuits_clientside();
2860 1 : circuit_expire_old_circuits_clientside();
2861 1 : circuit_expire_old_circuits_clientside();
2862 1 : tt_int_op(client_side->timestamp_dirty, OP_NE, 0);
2863 1 : tt_int_op(client_side->marked_for_close, OP_EQ, 0);
2864 1 : tt_int_op(client_side->purpose, OP_EQ, CIRCUIT_PURPOSE_C_CIRCUIT_PADDING);
2865 :
2866 : /* Runaway circpad test: if the machine does not transition to end,
2867 : * test that after CIRCPAD_DELAY_MAX_SECS, we get marked anyway */
2868 2 : mocked_timeofday = client_side->timestamp_dirty
2869 1 : + get_options()->MaxCircuitDirtiness + 2;
2870 2 : client_side->padding_info[0]->last_cell_time_sec =
2871 1 : approx_time()-(CIRCPAD_DELAY_MAX_SECS+10);
2872 1 : circuit_expire_old_circuits_clientside();
2873 1 : tt_int_op(client_side->marked_for_close, OP_NE, 0);
2874 :
2875 : /* Test back to normal: if we had activity, we won't close */
2876 1 : client_side->padding_info[0]->last_cell_time_sec = approx_time();
2877 1 : client_side->marked_for_close = 0;
2878 1 : circuit_expire_old_circuits_clientside();
2879 1 : tt_int_op(client_side->marked_for_close, OP_EQ, 0);
2880 :
2881 : /* Transition to END, but before we're past the dirty timer */
2882 1 : mocked_timeofday = client_side->timestamp_dirty;
2883 1 : circpad_cell_event_nonpadding_received(client_side);
2884 1 : tt_int_op(mi->current_state, OP_EQ, CIRCPAD_STATE_END);
2885 :
2886 : /* Verify that the circuit was not closed. */
2887 1 : tt_int_op(client_side->marked_for_close, OP_EQ, 0);
2888 :
2889 : /* Now that we are in END state, we can be closed by expiry, but via
2890 : * the timestamp_dirty path, not the idle path. So first test not dirty
2891 : * enough. */
2892 1 : mocked_timeofday = client_side->timestamp_dirty;
2893 1 : circuit_expire_old_circuits_clientside();
2894 1 : tt_int_op(client_side->marked_for_close, OP_EQ, 0);
2895 2 : mocked_timeofday = client_side->timestamp_dirty
2896 1 : + get_options()->MaxCircuitDirtiness + 2;
2897 1 : circuit_expire_old_circuits_clientside();
2898 1 : tt_int_op(client_side->marked_for_close, OP_NE, 0);
2899 :
2900 1 : done:
2901 1 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
2902 1 : tor_free(circ_client_machine.states);
2903 1 : monotime_disable_test_mocking();
2904 1 : UNMOCK(tor_gettimeofday);
2905 1 : }
2906 :
2907 : /** Helper for the test_circuitpadding_hs_machines test:
2908 : *
2909 : * - Create a client and relay circuit.
2910 : * - Setup right circuit purpose and attach a machine to the client circuit.
2911 : * - Verify that state transitions work as intended and state length gets
2912 : * enforced.
2913 : *
2914 : * This function is able to do this test both for intro and rend circuits
2915 : * depending on the value of <b>test_intro_circs</b>.
2916 : */
2917 : static void
2918 2 : helper_test_hs_machines(bool test_intro_circs)
2919 : {
2920 : /* Setup the circuits */
2921 2 : origin_circuit_t *origin_client_side = origin_circuit_new();
2922 2 : client_side = TO_CIRCUIT(origin_client_side);
2923 2 : client_side->purpose = CIRCUIT_PURPOSE_C_GENERAL;
2924 :
2925 2 : dummy_channel.cmux = circuitmux_alloc();
2926 2 : relay_side = TO_CIRCUIT(new_fake_orcirc(&dummy_channel, &dummy_channel));
2927 2 : relay_side->purpose = CIRCUIT_PURPOSE_OR;
2928 :
2929 : /* extend the client circ to two hops */
2930 2 : simulate_single_hop_extend(client_side, relay_side, 1);
2931 2 : simulate_single_hop_extend(client_side, relay_side, 1);
2932 :
2933 : /* machines only apply on opened circuits */
2934 2 : origin_client_side->has_opened = 1;
2935 :
2936 : /************************************/
2937 :
2938 : /* Attaching the client machine now won't work here because of a wrong
2939 : * purpose */
2940 2 : tt_assert(!client_side->padding_machine[0]);
2941 2 : circpad_add_matching_machines(origin_client_side, origin_padding_machines);
2942 2 : tt_assert(!client_side->padding_machine[0]);
2943 :
2944 : /* Change the purpose, see the machine getting attached */
2945 2 : client_side->purpose = test_intro_circs ?
2946 : CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT : CIRCUIT_PURPOSE_C_REND_JOINED;
2947 2 : circpad_add_matching_machines(origin_client_side, origin_padding_machines);
2948 2 : tt_ptr_op(client_side->padding_info[0], OP_NE, NULL);
2949 2 : tt_ptr_op(client_side->padding_machine[0], OP_NE, NULL);
2950 :
2951 2 : tt_ptr_op(relay_side->padding_info[0], OP_NE, NULL);
2952 2 : tt_ptr_op(relay_side->padding_machine[0], OP_NE, NULL);
2953 :
2954 : /* Verify that the right machine is attached */
2955 3 : tt_str_op(client_side->padding_machine[0]->name, OP_EQ,
2956 : test_intro_circs ? "client_ip_circ" : "client_rp_circ");
2957 3 : tt_str_op(relay_side->padding_machine[0]->name, OP_EQ,
2958 : test_intro_circs ? "relay_ip_circ": "relay_rp_circ");
2959 :
2960 : /***********************************/
2961 :
2962 : /* Intro machines are at START state, but rend machines have already skipped
2963 : * to OBFUSCATE_CIRC_SETUP because of the sent PADDING_NEGOTIATE. */
2964 2 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
2965 : CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP);
2966 2 : tt_int_op(relay_side->padding_info[0]->current_state, OP_EQ,
2967 : CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP);
2968 :
2969 : /*Send non-padding to move the machines from START to OBFUSCATE_CIRC_SETUP */
2970 2 : circpad_cell_event_nonpadding_received(client_side);
2971 2 : circpad_cell_event_nonpadding_received(relay_side);
2972 2 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
2973 : CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP);
2974 2 : tt_int_op(relay_side->padding_info[0]->current_state, OP_EQ,
2975 : CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP);
2976 :
2977 : /* Check that the state lengths have been sampled and are within range */
2978 2 : circpad_machine_runtime_t *client_machine_runtime =
2979 2 : client_side->padding_info[0];
2980 2 : circpad_machine_runtime_t *relay_machine_runtime =
2981 2 : relay_side->padding_info[0];
2982 :
2983 2 : if (test_intro_circs) {
2984 : /* on the client side, we don't send any padding so
2985 : * state length is not set */
2986 1 : tt_i64_op(client_machine_runtime->state_length, OP_EQ, -1);
2987 : /* relay side has state limits. check them */
2988 1 : tt_i64_op(relay_machine_runtime->state_length, OP_GE,
2989 : INTRO_MACHINE_MINIMUM_PADDING);
2990 1 : tt_i64_op(relay_machine_runtime->state_length, OP_LT,
2991 : INTRO_MACHINE_MAXIMUM_PADDING);
2992 : } else {
2993 1 : tt_i64_op(client_machine_runtime->state_length, OP_EQ, 1);
2994 1 : tt_i64_op(relay_machine_runtime->state_length, OP_EQ, 1);
2995 : }
2996 :
2997 2 : if (test_intro_circs) {
2998 1 : int i;
2999 : /* Send state_length worth of padding from the relay and see that the
3000 : * client state goes to END */
3001 9 : for (i = (int) relay_machine_runtime->state_length ; i > 0 ; i--) {
3002 8 : circpad_send_padding_cell_for_callback(relay_machine_runtime);
3003 : }
3004 : /* See that the machine has been teared down after all the length has been
3005 : * exhausted (the padding info should now be null on both sides) */
3006 1 : tt_ptr_op(relay_side->padding_info[0], OP_EQ, NULL);
3007 1 : tt_ptr_op(client_side->padding_info[0], OP_EQ, NULL);
3008 : } else {
3009 1 : int i;
3010 : /* Send state_length worth of padding and see that the state goes to END */
3011 2 : for (i = (int) client_machine_runtime->state_length ; i > 0 ; i--) {
3012 1 : circpad_send_padding_cell_for_callback(client_machine_runtime);
3013 : }
3014 : /* See that the machine has been teared down after all the length has been
3015 : * exhausted. */
3016 1 : tt_int_op(client_side->padding_info[0]->current_state, OP_EQ,
3017 : CIRCPAD_STATE_END);
3018 : }
3019 :
3020 1 : done:
3021 2 : free_fake_orcirc(TO_OR_CIRCUIT(relay_side));
3022 2 : circuitmux_detach_all_circuits(dummy_channel.cmux, NULL);
3023 2 : circuitmux_free(dummy_channel.cmux);
3024 2 : free_fake_origin_circuit(TO_ORIGIN_CIRCUIT(client_side));
3025 2 : }
3026 :
3027 : /** Test that the HS circuit padding machines work as intended. */
3028 : static void
3029 1 : test_circuitpadding_hs_machines(void *arg)
3030 : {
3031 1 : (void)arg;
3032 :
3033 : /* Test logic:
3034 : *
3035 : * 1) Register the HS machines, which aim to hide the presence of
3036 : * onion service traffic on the client-side
3037 : *
3038 : * 2) Call helper_test_hs_machines() to perform tests for the intro circuit
3039 : * machines and for the rend circuit machines.
3040 : */
3041 :
3042 1 : MOCK(circuitmux_attach_circuit, circuitmux_attach_circuit_mock);
3043 1 : MOCK(circuit_package_relay_cell, circuit_package_relay_cell_mock);
3044 1 : MOCK(circuit_get_nth_node, circuit_get_nth_node_mock);
3045 1 : MOCK(circpad_machine_schedule_padding,circpad_machine_schedule_padding_mock);
3046 :
3047 1 : origin_padding_machines = smartlist_new();
3048 1 : relay_padding_machines = smartlist_new();
3049 :
3050 1 : nodes_init();
3051 :
3052 1 : monotime_init();
3053 1 : monotime_enable_test_mocking();
3054 1 : monotime_set_mock_time_nsec(1*TOR_NSEC_PER_USEC);
3055 1 : monotime_coarse_set_mock_time_nsec(1*TOR_NSEC_PER_USEC);
3056 1 : curr_mocked_time = 1*TOR_NSEC_PER_USEC;
3057 :
3058 1 : timers_initialize();
3059 :
3060 : /* This is needed so that we are not considered to be dormant */
3061 1 : note_user_activity(20);
3062 :
3063 : /************************************/
3064 :
3065 : /* Register the HS machines */
3066 1 : circpad_machine_client_hide_intro_circuits(origin_padding_machines);
3067 1 : circpad_machine_client_hide_rend_circuits(origin_padding_machines);
3068 1 : circpad_machine_relay_hide_intro_circuits(relay_padding_machines);
3069 1 : circpad_machine_relay_hide_rend_circuits(relay_padding_machines);
3070 :
3071 : /***********************************/
3072 :
3073 : /* Do the tests for the intro circuit machines */
3074 1 : helper_test_hs_machines(true);
3075 : /* Do the tests for the rend circuit machines */
3076 1 : helper_test_hs_machines(false);
3077 :
3078 1 : timers_shutdown();
3079 1 : monotime_disable_test_mocking();
3080 :
3081 3 : SMARTLIST_FOREACH_BEGIN(origin_padding_machines,
3082 : circpad_machine_spec_t *, m) {
3083 2 : machine_spec_free(m);
3084 2 : } SMARTLIST_FOREACH_END(m);
3085 :
3086 3 : SMARTLIST_FOREACH_BEGIN(relay_padding_machines,
3087 : circpad_machine_spec_t *, m) {
3088 2 : machine_spec_free(m);
3089 2 : } SMARTLIST_FOREACH_END(m);
3090 :
3091 1 : smartlist_free(origin_padding_machines);
3092 1 : smartlist_free(relay_padding_machines);
3093 :
3094 1 : UNMOCK(circuitmux_attach_circuit);
3095 1 : UNMOCK(circuit_package_relay_cell);
3096 1 : UNMOCK(circuit_get_nth_node);
3097 1 : UNMOCK(circpad_machine_schedule_padding);
3098 1 : }
3099 :
3100 : /** Test that we effectively ignore non-padding cells in padding circuits. */
3101 : static void
3102 1 : test_circuitpadding_ignore_non_padding_cells(void *arg)
3103 : {
3104 1 : int retval;
3105 1 : relay_header_t rh;
3106 :
3107 1 : (void) arg;
3108 :
3109 1 : client_side = (circuit_t *)origin_circuit_new();
3110 1 : client_side->purpose = CIRCUIT_PURPOSE_C_CIRCUIT_PADDING;
3111 :
3112 1 : rh.command = RELAY_COMMAND_BEGIN;
3113 :
3114 1 : setup_full_capture_of_logs(LOG_INFO);
3115 1 : retval = handle_relay_cell_command(NULL, client_side, NULL, NULL, &rh, 0);
3116 1 : tt_int_op(retval, OP_EQ, 0);
3117 1 : expect_log_msg_containing("Ignored cell");
3118 :
3119 1 : done:
3120 1 : ;
3121 1 : }
3122 :
3123 : #define TEST_CIRCUITPADDING(name, flags) \
3124 : { #name, test_##name, (flags), NULL, NULL }
3125 :
3126 : struct testcase_t circuitpadding_tests[] = {
3127 : TEST_CIRCUITPADDING(circuitpadding_tokens, TT_FORK),
3128 : TEST_CIRCUITPADDING(circuitpadding_state_length, TT_FORK),
3129 : TEST_CIRCUITPADDING(circuitpadding_negotiation, TT_FORK),
3130 : TEST_CIRCUITPADDING(circuitpadding_wronghop, TT_FORK),
3131 : /** Disabled unstable test until #29298 is implemented (see #29122) */
3132 : // TEST_CIRCUITPADDING(circuitpadding_circuitsetup_machine, TT_FORK),
3133 : TEST_CIRCUITPADDING(circuitpadding_conditions, TT_FORK),
3134 : TEST_CIRCUITPADDING(circuitpadding_rtt, TT_FORK),
3135 : TEST_CIRCUITPADDING(circuitpadding_sample_distribution, TT_FORK),
3136 : TEST_CIRCUITPADDING(circuitpadding_machine_rate_limiting, TT_FORK),
3137 : TEST_CIRCUITPADDING(circuitpadding_global_rate_limiting, TT_FORK),
3138 : TEST_CIRCUITPADDING(circuitpadding_reduce_disable, TT_FORK),
3139 : TEST_CIRCUITPADDING(circuitpadding_token_removal_lower, TT_FORK),
3140 : TEST_CIRCUITPADDING(circuitpadding_token_removal_higher, TT_FORK),
3141 : TEST_CIRCUITPADDING(circuitpadding_closest_token_removal, TT_FORK),
3142 : TEST_CIRCUITPADDING(circuitpadding_closest_token_removal_usec, TT_FORK),
3143 : TEST_CIRCUITPADDING(circuitpadding_token_removal_exact, TT_FORK),
3144 : TEST_CIRCUITPADDING(circuitpadding_manage_circuit_lifetime, TT_FORK),
3145 : TEST_CIRCUITPADDING(circuitpadding_hs_machines, TT_FORK),
3146 : TEST_CIRCUITPADDING(circuitpadding_ignore_non_padding_cells, TT_FORK),
3147 : END_OF_TESTCASES
3148 : };
|