tor  0.4.2.0-alpha-dev
circuitpadding_machines.c
Go to the documentation of this file.
1 /* Copyright (c) 2019 The Tor Project, Inc. */
2 /* See LICENSE for licensing information */
3 
48 #define CIRCUITPADDING_MACHINES_PRIVATE
49 
50 #include "core/or/or.h"
52 
54 
55 #include "core/or/circuitlist.h"
56 
58 #include "core/or/circuitpadding.h"
59 
64 void
66 {
67  circpad_machine_spec_t *client_machine
68  = tor_malloc_zero(sizeof(circpad_machine_spec_t));
69 
70  client_machine->name = "client_ip_circ";
71 
72  client_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
73  client_machine->target_hopnum = 2;
74 
75  /* This is a client machine */
76  client_machine->is_origin_side = 1;
77 
78  /* We only want to pad introduction circuits, and we want to start padding
79  * only after the INTRODUCE1 cell has been sent, so set the purposes
80  * appropriately.
81  *
82  * In particular we want introduction circuits to blend as much as possible
83  * with general circuits. Most general circuits have the following initial
84  * relay cell sequence (outgoing cells marked in [brackets]):
85  *
86  * [EXTEND2] -> EXTENDED2 -> [EXTEND2] -> EXTENDED2 -> [BEGIN] -> CONNECTED
87  * -> [DATA] -> [DATA] -> DATA -> DATA...(inbound data cells continue)
88  *
89  * Whereas normal introduction circuits usually look like:
90  *
91  * [EXTEND2] -> EXTENDED2 -> [EXTEND2] -> EXTENDED2 -> [EXTEND2] -> EXTENDED2
92  * -> [INTRO1] -> INTRODUCE_ACK
93  *
94  * This means that up to the sixth cell (first line of each sequence above),
95  * both general and intro circuits have identical cell sequences. After that
96  * we want to mimic the second line sequence of
97  * -> [DATA] -> [DATA] -> DATA -> DATA...(inbound data cells continue)
98  *
99  * We achieve this by starting padding INTRODUCE1 has been sent. With padding
100  * negotiation cells, in the common case of the second line looks like:
101  * -> [INTRO1] -> [PADDING_NEGOTIATE] -> PADDING_NEGOTIATED -> INTRO_ACK
102  *
103  * Then, the middle node will send between INTRO_MACHINE_MINIMUM_PADDING and
104  * INTRO_MACHINE_MAXIMUM_PADDING cells, to match the "...(inbound data cells
105  * continue)" portion of the trace (aka the rest of an HTTPS response body).
106  */
107  client_machine->conditions.purpose_mask =
111 
112  /* Keep the circuit alive even after the introduction has been finished,
113  * otherwise the short-term lifetime of the circuit will blow our cover */
114  client_machine->manage_circ_lifetime = 1;
115 
116  /* Set padding machine limits to help guard against excessive padding */
117  client_machine->allowed_padding_count = INTRO_MACHINE_MAXIMUM_PADDING;
118  client_machine->max_padding_percent = 1;
119 
120  /* Two states: START, OBFUSCATE_CIRC_SETUP (and END) */
121  circpad_machine_states_init(client_machine, 2);
122 
123  /* For the origin-side machine, we transition to OBFUSCATE_CIRC_SETUP after
124  * sending PADDING_NEGOTIATE, and we stay there (without sending any padding)
125  * until we receive a STOP from the other side. */
126  client_machine->states[CIRCPAD_STATE_START].
127  next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
128  CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP;
129 
130  /* origin-side machine has no event reactions while in
131  * CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP, so no more state transitions here. */
132 
133  /* The client side should never send padding, so it does not need
134  * to specify token removal, or a histogram definition or state lengths.
135  * That is all controlled by the middle node. */
136 
137  /* Register the machine */
138  client_machine->machine_num = smartlist_len(machines_sl);
139  circpad_register_padding_machine(client_machine, machines_sl);
140 
141  log_info(LD_CIRC,
142  "Registered client intro point hiding padding machine (%u)",
143  client_machine->machine_num);
144 }
145 
149 void
151 {
152  circpad_machine_spec_t *relay_machine
153  = tor_malloc_zero(sizeof(circpad_machine_spec_t));
154 
155  relay_machine->name = "relay_ip_circ";
156 
157  relay_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
158 
159  /* This is a relay-side machine */
160  relay_machine->is_origin_side = 0;
161 
162  /* We want to negotiate END from this side after all our padding is done, so
163  * that the origin-side machine goes into END state, and eventually closes
164  * the circuit. */
165  relay_machine->should_negotiate_end = 1;
166 
167  /* Set padding machine limits to help guard against excessive padding */
168  relay_machine->allowed_padding_count = INTRO_MACHINE_MAXIMUM_PADDING;
169  relay_machine->max_padding_percent = 1;
170 
171  /* Two states: START, OBFUSCATE_CIRC_SETUP (and END) */
172  circpad_machine_states_init(relay_machine, 2);
173 
174  /* For the relay-side machine, we want to transition
175  * START -> OBFUSCATE_CIRC_SETUP upon first non-padding
176  * cell sent (PADDING_NEGOTIATED in this case). */
177  relay_machine->states[CIRCPAD_STATE_START].
178  next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
179  CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP;
180 
181  /* For the relay-side, we want to transition from OBFUSCATE_CIRC_SETUP to END
182  * state when the length finishes. */
183  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
184  next_state[CIRCPAD_EVENT_LENGTH_COUNT] = CIRCPAD_STATE_END;
185 
186  /* Now let's define the OBF -> OBF transitions that maintain our padding
187  * flow:
188  *
189  * For the relay-side machine, we want to keep on sending padding bytes even
190  * when nothing else happens on this circuit. */
191  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
192  next_state[CIRCPAD_EVENT_PADDING_SENT] =
193  CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP;
194  /* For the relay-side machine, we need this transition so that we re-enter
195  the state, after PADDING_NEGOTIATED is sent. Otherwise, the remove token
196  function will disable the timer, and nothing will restart it since there
197  is no other motion on an intro circuit. */
198  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
199  next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
200  CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP;
201 
202  /* Token removal strategy for OBFUSCATE_CIRC_SETUP state: Don't
203  * remove any tokens.
204  *
205  * We rely on the state length sampling and not token removal, to avoid
206  * the mallocs required to copy the histograms for token removal,
207  * and to avoid monotime calls needed to determine histogram
208  * bins for token removal. */
209  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
210  token_removal = CIRCPAD_TOKEN_REMOVAL_NONE;
211 
212  /* Figure out the length of the OBFUSCATE_CIRC_SETUP state so that it's
213  * randomized. The relay side will send between INTRO_MACHINE_MINIMUM_PADDING
214  * and INTRO_MACHINE_MAXIMUM_PADDING padding cells towards the client. */
215  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
216  length_dist.type = CIRCPAD_DIST_UNIFORM;
217  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
218  length_dist.param1 = INTRO_MACHINE_MINIMUM_PADDING;
219  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
220  length_dist.param2 = INTRO_MACHINE_MAXIMUM_PADDING;
221 
222  /* Configure histogram */
223  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
224  histogram_len = 2;
225 
226  /* For the relay-side machine we want to batch padding instantly to pretend
227  * its an incoming directory download. So set the histogram edges tight:
228  * (1, 10ms, infinity). */
229  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
230  histogram_edges[0] = 1000;
231  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
232  histogram_edges[1] = 10000;
233 
234  /* We put all our tokens in bin 0, which means we want 100% probability
235  * for choosing a inter-packet delay of between 1000 and 10000 microseconds
236  * (1 to 10ms). Since we only have 1 bin, it doesn't matter how many tokens
237  * there are, 1000 out of 1000 is 100% */
238  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
239  histogram[0] = 1000;
240 
241  /* just one bin, so setup the total tokens */
242  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
243  histogram_total_tokens =
244  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].histogram[0];
245 
246  /* Register the machine */
247  relay_machine->machine_num = smartlist_len(machines_sl);
248  circpad_register_padding_machine(relay_machine, machines_sl);
249 
250  log_info(LD_CIRC,
251  "Registered relay intro circuit hiding padding machine (%u)",
252  relay_machine->machine_num);
253 }
254 
255 /************************** Rendezvous-circuit machine ***********************/
256 
259 void
261 {
262  circpad_machine_spec_t *client_machine
263  = tor_malloc_zero(sizeof(circpad_machine_spec_t));
264 
265  client_machine->name = "client_rp_circ";
266 
267  /* Only pad after the circuit has been built and pad to the middle */
268  client_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
269  client_machine->target_hopnum = 2;
270 
271  /* This is a client machine */
272  client_machine->is_origin_side = 1;
273 
274  /* We only want to pad rendezvous circuits, and we want to start padding only
275  * after the rendezvous circuit has been established.
276  *
277  * Following a similar argument as for intro circuits, we are aiming for
278  * padded rendezvous circuits to blend in with the initial cell sequence of
279  * general circuits which usually look like this:
280  *
281  * [EXTEND2] -> EXTENDED2 -> [EXTEND2] -> EXTENDED2 -> [BEGIN] -> CONNECTED
282  * -> [DATA] -> [DATA] -> DATA -> DATA...(incoming cells continue)
283  *
284  * Whereas normal rendezvous circuits usually look like:
285  *
286  * [EXTEND2] -> EXTENDED2 -> [EXTEND2] -> EXTENDED2 -> [EST_REND] -> REND_EST
287  * -> REND2 -> [BEGIN]
288  *
289  * This means that up to the sixth cell (in the first line), both general and
290  * rend circuits have identical cell sequences.
291  *
292  * After that we want to mimic a [DATA] -> [DATA] -> DATA -> DATA sequence.
293  *
294  * With padding negotiation right after the REND_ESTABLISHED, the sequence
295  * becomes:
296  *
297  * [EXTEND2] -> EXTENDED2 -> [EXTEND2] -> EXTENDED2 -> [EST_REND] -> REND_EST
298  * -> [PADDING_NEGOTIATE] -> [DROP] -> PADDING_NEGOTIATED -> DROP...
299  *
300  * After which normal application DATA cells continue on the circuit.
301  *
302  * Hence this way we make rendezvous circuits look like general circuits up
303  * till the end of the circuit setup. */
304  client_machine->conditions.purpose_mask =
308 
309  /* Set padding machine limits to help guard against excessive padding */
310  client_machine->allowed_padding_count = 1;
311  client_machine->max_padding_percent = 1;
312 
313  /* Two states: START, OBFUSCATE_CIRC_SETUP (and END) */
314  circpad_machine_states_init(client_machine, 2);
315 
316  /* START -> OBFUSCATE_CIRC_SETUP transition upon sending the first
317  * non-padding cell (which is PADDING_NEGOTIATE) */
318  client_machine->states[CIRCPAD_STATE_START].
319  next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
320  CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP;
321 
322  /* OBFUSCATE_CIRC_SETUP -> END transition when we send our first
323  * padding packet and/or hit the state length (the state length is 1). */
324  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
325  next_state[CIRCPAD_EVENT_PADDING_RECV] = CIRCPAD_STATE_END;
326  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
327  next_state[CIRCPAD_EVENT_LENGTH_COUNT] = CIRCPAD_STATE_END;
328 
329  /* Don't use a token removal strategy since we don't want to use monotime
330  * functions and we want to avoid mallocing histogram copies. We want
331  * this machine to be light. */
332  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
333  token_removal = CIRCPAD_TOKEN_REMOVAL_NONE;
334 
335  /* Instead, to control the volume of padding (we just want to send a single
336  * padding cell) we will use a static state length. We just want one token,
337  * since we want to make the following pattern:
338  * [PADDING_NEGOTIATE] -> [DROP] -> PADDING_NEGOTIATED -> DROP */
339  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
340  length_dist.type = CIRCPAD_DIST_UNIFORM;
341  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
342  length_dist.param1 = 1;
343  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
344  length_dist.param2 = 2; // rand(1,2) is always 1
345 
346  /* Histogram is: (0 msecs, 1 msec, infinity). We want this to be fast so
347  * that we send our outgoing [DROP] before the PADDING_NEGOTIATED comes
348  * back from the relay side. */
349  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
350  histogram_len = 2;
351  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
352  histogram_edges[0] = 0;
353  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
354  histogram_edges[1] = 1000;
355 
356  /* We want a 100% probability of choosing an inter-packet delay of
357  * between 0 and 1ms. Since we don't use token removal,
358  * the number of tokens does not matter. (And also, state_length
359  * governs how many packets we send). */
360  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
361  histogram[0] = 1;
362  client_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
363  histogram_total_tokens = 1;
364 
365  /* Register the machine */
366  client_machine->machine_num = smartlist_len(machines_sl);
367  circpad_register_padding_machine(client_machine, machines_sl);
368 
369  log_info(LD_CIRC,
370  "Registered client rendezvous circuit hiding padding machine (%u)",
371  client_machine->machine_num);
372 }
373 
378 void
380 {
381  circpad_machine_spec_t *relay_machine
382  = tor_malloc_zero(sizeof(circpad_machine_spec_t));
383 
384  relay_machine->name = "relay_rp_circ";
385 
386  /* Only pad after the circuit has been built and pad to the middle */
387  relay_machine->conditions.min_hops = 2;
388  relay_machine->conditions.state_mask = CIRCPAD_CIRC_OPENED;
389 
390  /* This is a relay-side machine */
391  relay_machine->is_origin_side = 0;
392 
393  /* Set padding machine limits to help guard against excessive padding */
394  relay_machine->allowed_padding_count = 1;
395  relay_machine->max_padding_percent = 1;
396 
397  /* Two states: START, OBFUSCATE_CIRC_SETUP (and END) */
398  circpad_machine_states_init(relay_machine, 2);
399 
400  /* START -> OBFUSCATE_CIRC_SETUP transition upon sending the first
401  * non-padding cell (which is PADDING_NEGOTIATED) */
402  relay_machine->states[CIRCPAD_STATE_START].
403  next_state[CIRCPAD_EVENT_NONPADDING_SENT] =
404  CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP;
405 
406  /* OBFUSCATE_CIRC_SETUP -> END transition when we send our first
407  * padding packet and/or hit the state length (the state length is 1). */
408  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
409  next_state[CIRCPAD_EVENT_PADDING_SENT] = CIRCPAD_STATE_END;
410  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
411  next_state[CIRCPAD_EVENT_LENGTH_COUNT] = CIRCPAD_STATE_END;
412 
413  /* Don't use a token removal strategy since we don't want to use monotime
414  * functions and we want to avoid mallocing histogram copies. We want
415  * this machine to be light. */
416  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
417  token_removal = CIRCPAD_TOKEN_REMOVAL_NONE;
418 
419  /* Instead, to control the volume of padding (we just want to send a single
420  * padding cell) we will use a static state length. We just want one token,
421  * since we want to make the following pattern:
422  * [PADDING_NEGOTIATE] -> [DROP] -> PADDING_NEGOTIATED -> DROP */
423  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
424  length_dist.type = CIRCPAD_DIST_UNIFORM;
425  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
426  length_dist.param1 = 1;
427  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
428  length_dist.param2 = 2; // rand(1,2) is always 1
429 
430  /* Histogram is: (0 msecs, 1 msec, infinity). We want this to be fast so
431  * that the outgoing DROP cell is sent immediately after the
432  * PADDING_NEGOTIATED. */
433  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
434  histogram_len = 2;
435  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
436  histogram_edges[0] = 0;
437  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
438  histogram_edges[1] = 1000;
439 
440  /* We want a 100% probability of choosing an inter-packet delay of
441  * between 0 and 1ms. Since we don't use token removal,
442  * the number of tokens does not matter. (And also, state_length
443  * governs how many packets we send). */
444  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
445  histogram[0] = 1;
446  relay_machine->states[CIRCPAD_STATE_OBFUSCATE_CIRC_SETUP].
447  histogram_total_tokens = 1;
448 
449  /* Register the machine */
450  relay_machine->machine_num = smartlist_len(machines_sl);
451  circpad_register_padding_machine(relay_machine, machines_sl);
452 
453  log_info(LD_CIRC,
454  "Registered relay rendezvous circuit hiding padding machine (%u)",
455  relay_machine->machine_num);
456 }
#define CIRCPAD_STATE_END
#define CIRCUIT_PURPOSE_C_REND_READY_INTRO_ACKED
Definition: circuitlist.h:87
Common functions for using (pseudo-)random number generators.
void circpad_machine_relay_hide_rend_circuits(smartlist_t *machines_sl)
circpad_state_t * states
void circpad_machine_client_hide_rend_circuits(smartlist_t *machines_sl)
#define CIRCUIT_PURPOSE_C_REND_READY
Definition: circuitlist.h:84
void circpad_machine_client_hide_intro_circuits(smartlist_t *machines_sl)
#define LD_CIRC
Definition: log.h:80
Header file for circuitpadding.c.
#define CIRCUIT_PURPOSE_C_INTRODUCE_ACKED
Definition: circuitlist.h:80
Master header file for Tor-specific functionality.
Header file for circuitpadding_machines.c.
Header file for circuitlist.c.
#define CIRCPAD_STATE_START
void circpad_machine_states_init(circpad_machine_spec_t *machine, circpad_statenum_t num_states)
void circpad_machine_relay_hide_intro_circuits(smartlist_t *machines_sl)
circpad_machine_conditions_t conditions
circpad_purpose_mask_t purpose_mask
circpad_hist_token_t histogram[CIRCPAD_MAX_HISTOGRAM_LEN]
circpad_circuit_state_t state_mask
#define CIRCUIT_PURPOSE_C_INTRODUCE_ACK_WAIT
Definition: circuitlist.h:77
#define CIRCUIT_PURPOSE_C_REND_JOINED
Definition: circuitlist.h:89
circpad_purpose_mask_t circpad_circ_purpose_to_mask(uint8_t circ_purpose)
circpad_machine_num_t machine_num
Header file for networkstatus.c.
#define CIRCUIT_PURPOSE_C_CIRCUIT_PADDING
Definition: circuitlist.h:96