Tor 0.4.9.0-alpha-dev
Macros | Functions | Variables
circuitpadding.c File Reference

Circuit-level padding implementation. More...

#include <math.h>
#include "lib/math/fp.h"
#include "lib/math/prob_distr.h"
#include "core/or/or.h"
#include "core/or/circuitpadding.h"
#include "core/or/circuitpadding_machines.h"
#include "core/or/circuitlist.h"
#include "core/or/circuituse.h"
#include "core/mainloop/netstatus.h"
#include "core/or/relay.h"
#include "feature/stats/rephist.h"
#include "feature/nodelist/networkstatus.h"
#include "core/or/channel.h"
#include "lib/time/compat_time.h"
#include "lib/defs/time.h"
#include "lib/crypt_ops/crypto_rand.h"
#include "core/or/crypt_path_st.h"
#include "core/or/circuit_st.h"
#include "core/or/origin_circuit_st.h"
#include "core/or/or_circuit_st.h"
#include "feature/nodelist/routerstatus_st.h"
#include "feature/nodelist/node_st.h"
#include "core/or/cell_st.h"
#include "core/or/extend_info_st.h"
#include "core/crypto/relay_crypto.h"
#include "feature/nodelist/nodelist.h"
#include "src/core/or/conflux_util.h"
#include "app/config/config.h"

Go to the source code of this file.

Macros

#define CIRCUITPADDING_PRIVATE
 
#define FOR_EACH_CIRCUIT_MACHINE_BEGIN(loop_var)
 
#define FOR_EACH_CIRCUIT_MACHINE_END   } STMT_END ;
 
#define FOR_EACH_ACTIVE_CIRCUIT_MACHINE_BEGIN(loop_var, circ)
 
#define FOR_EACH_ACTIVE_CIRCUIT_MACHINE_END   } STMT_END ;
 
#define ENSURE_BIN_CAPACITY(bin_index)
 

Functions

static circpad_circuit_state_t circpad_circuit_state (origin_circuit_t *circ)
 
static void circpad_setup_machine_on_circ (circuit_t *on_circ, const circpad_machine_spec_t *machine)
 
static double circpad_distribution_sample (circpad_distribution_t dist)
 
static void circpad_machine_update_state_length_for_nonpadding (circpad_machine_runtime_t *mi)
 
static void circpad_circuit_machineinfo_free_idx (circuit_t *circ, int idx)
 
int circpad_marked_circuit_for_padding (circuit_t *circ, int reason)
 
static int free_circ_machineinfos_with_machine_num (circuit_t *circ, int machine_num, uint32_t machine_ctr)
 
void circpad_circuit_free_all_machineinfos (circuit_t *circ)
 
STATIC circpad_machine_runtime_tcircpad_circuit_machineinfo_new (circuit_t *on_circ, int machine_index)
 
STATIC const circpad_state_tcircpad_machine_current_state (const circpad_machine_runtime_t *mi)
 
STATIC circpad_delay_t circpad_histogram_bin_to_usec (const circpad_machine_runtime_t *mi, circpad_hist_index_t bin)
 
STATIC circpad_delay_t histogram_get_bin_upper_bound (const circpad_machine_runtime_t *mi, circpad_hist_index_t bin)
 
static circpad_delay_t circpad_get_histogram_bin_midpoint (const circpad_machine_runtime_t *mi, int bin_index)
 
STATIC circpad_hist_index_t circpad_histogram_usec_to_bin (const circpad_machine_runtime_t *mi, circpad_delay_t usec)
 
static int circpad_is_token_removal_supported (circpad_machine_runtime_t *mi)
 
STATIC void circpad_machine_setup_tokens (circpad_machine_runtime_t *mi)
 
static void circpad_choose_state_length (circpad_machine_runtime_t *mi)
 
static circpad_delay_t circpad_distribution_sample_iat_delay (const circpad_state_t *state, circpad_delay_t delay_shift)
 
STATIC circpad_delay_t circpad_machine_sample_delay (circpad_machine_runtime_t *mi)
 
static circpad_hist_index_t circpad_machine_first_higher_index (const circpad_machine_runtime_t *mi, circpad_delay_t target_bin_usec)
 
static circpad_hist_index_t circpad_machine_first_lower_index (const circpad_machine_runtime_t *mi, circpad_delay_t target_bin_usec)
 
STATIC void circpad_machine_remove_higher_token (circpad_machine_runtime_t *mi, circpad_delay_t target_bin_usec)
 
STATIC void circpad_machine_remove_lower_token (circpad_machine_runtime_t *mi, circpad_delay_t target_bin_usec)
 
STATIC void circpad_machine_remove_closest_token (circpad_machine_runtime_t *mi, circpad_delay_t target_bin_usec, bool use_usec)
 
static void circpad_machine_remove_exact (circpad_machine_runtime_t *mi, circpad_delay_t target_bin_usec)
 
static circpad_decision_t check_machine_token_supply (circpad_machine_runtime_t *mi)
 
static void circpad_machine_count_padding_sent (circpad_machine_runtime_t *mi)
 
static void circpad_machine_count_nonpadding_sent (circpad_machine_runtime_t *mi)
 
STATIC void circpad_machine_remove_token (circpad_machine_runtime_t *mi)
 
STATIC signed_error_t circpad_send_command_to_hop (origin_circuit_t *circ, uint8_t hopnum, uint8_t relay_command, const uint8_t *payload, ssize_t payload_len)
 
circpad_decision_t circpad_send_padding_cell_for_callback (circpad_machine_runtime_t *mi)
 
static void circpad_send_padding_callback (tor_timer_t *timer, void *args, const struct monotime_t *time)
 
void circpad_new_consensus_params (const networkstatus_t *ns)
 
static bool circpad_is_padding_allowed (void)
 
STATIC bool circpad_machine_reached_padding_limit (circpad_machine_runtime_t *mi)
 
circpad_decision_t circpad_machine_schedule_padding (circpad_machine_runtime_t *mi)
 
static void circpad_machine_spec_transitioned_to_end (circpad_machine_runtime_t *mi)
 
circpad_decision_t circpad_machine_spec_transition (circpad_machine_runtime_t *mi, circpad_event_t event)
 
static void circpad_estimate_circ_rtt_on_received (circuit_t *circ, circpad_machine_runtime_t *mi)
 
static void circpad_estimate_circ_rtt_on_send (circuit_t *circ, circpad_machine_runtime_t *mi)
 
void circpad_cell_event_nonpadding_sent (circuit_t *on_circ)
 
int circpad_check_received_cell (cell_t *cell, circuit_t *circ, crypt_path_t *layer_hint, const relay_header_t *rh)
 
void circpad_cell_event_nonpadding_received (circuit_t *on_circ)
 
void circpad_cell_event_padding_sent (circuit_t *on_circ)
 
void circpad_cell_event_padding_received (circuit_t *on_circ)
 
circpad_decision_t circpad_internal_event_infinity (circpad_machine_runtime_t *mi)
 
circpad_decision_t circpad_internal_event_bins_empty (circpad_machine_runtime_t *mi)
 
circpad_decision_t circpad_internal_event_state_length_up (circpad_machine_runtime_t *mi)
 
static bool circpad_machine_conditions_apply (origin_circuit_t *circ, const circpad_machine_spec_t *machine)
 
static bool circpad_machine_conditions_keep (origin_circuit_t *circ, const circpad_machine_spec_t *machine)
 
circpad_purpose_mask_t circpad_circ_purpose_to_mask (uint8_t circ_purpose)
 
static void circpad_shutdown_old_machines (origin_circuit_t *on_circ)
 
STATIC void circpad_add_matching_machines (origin_circuit_t *on_circ, smartlist_t *machines_sl)
 
void circpad_machine_event_circ_added_hop (origin_circuit_t *on_circ)
 
void circpad_machine_event_circ_built (origin_circuit_t *circ)
 
void circpad_machine_event_circ_purpose_changed (origin_circuit_t *circ)
 
void circpad_machine_event_circ_has_no_relay_early (origin_circuit_t *circ)
 
void circpad_machine_event_circ_has_streams (origin_circuit_t *circ)
 
void circpad_machine_event_circ_has_no_streams (origin_circuit_t *circ)
 
bool circpad_padding_is_from_expected_hop (circuit_t *circ, crypt_path_t *from_hop)
 
void circpad_deliver_unrecognized_cell_events (circuit_t *circ, cell_direction_t dir)
 
void circpad_deliver_recognized_relay_cell_events (circuit_t *circ, uint8_t relay_command, crypt_path_t *layer_hint)
 
void circpad_deliver_sent_relay_cell_events (circuit_t *circ, uint8_t relay_command)
 
void circpad_machine_states_init (circpad_machine_spec_t *machine, circpad_statenum_t num_states)
 
static bool padding_machine_state_is_valid (const circpad_state_t *state)
 
static bool padding_machine_is_valid (const circpad_machine_spec_t *machine)
 
void circpad_register_padding_machine (circpad_machine_spec_t *machine, smartlist_t *machine_list)
 
void circpad_machines_init (void)
 
void circpad_machines_free (void)
 
static bool circpad_node_supports_padding (const node_t *node)
 
STATIC const node_tcircuit_get_nth_node (origin_circuit_t *circ, int hop)
 
static bool circpad_circuit_supports_padding (origin_circuit_t *circ, int target_hopnum)
 
signed_error_t circpad_negotiate_padding (origin_circuit_t *circ, circpad_machine_num_t machine, uint8_t target_hopnum, uint8_t command, uint32_t machine_ctr)
 
bool circpad_padding_negotiated (circuit_t *circ, circpad_machine_num_t machine, uint8_t command, uint8_t response, uint32_t machine_ctr)
 
signed_error_t circpad_handle_padding_negotiate (circuit_t *circ, cell_t *cell)
 
signed_error_t circpad_handle_padding_negotiated (circuit_t *circ, cell_t *cell, crypt_path_t *layer_hint)
 
STATIC void machine_spec_free_ (circpad_machine_spec_t *m)
 
void circpad_free_all (void)
 

Variables

static uint8_t circpad_padding_disabled
 
static uint8_t circpad_padding_reduced
 
static uint8_t circpad_global_max_padding_percent
 
static uint16_t circpad_global_allowed_cells
 
static uint16_t circpad_max_circ_queued_cells
 
static uint64_t circpad_global_padding_sent
 
static uint64_t circpad_global_nonpadding_sent
 
STATIC smartlist_torigin_padding_machines = NULL
 
STATIC smartlist_trelay_padding_machines = NULL
 

Detailed Description

Circuit-level padding implementation.

This file implements Tor proposal 254 "Padding Negotiation" which is heavily inspired by the paper "Toward an Efficient Website Fingerprinting Defense" by M. Juarez, M. Imani, M. Perry, C. Diaz, M. Wright.

In particular the code in this file describes mechanisms for clients to negotiate various types of circuit-level padding from relays.

Each padding type is described by a state machine (circpad_machine_spec_t), which is also referred as a "padding machine" in this file. Currently, these state machines are hardcoded in the source code (e.g. see circpad_machines_init()), but in the future we will be able to serialize them in the torrc or the consensus.

As specified by prop#254, clients can negotiate padding with relays by using PADDING_NEGOTIATE cells. After successful padding negotiation, padding machines are assigned to the circuit in their mutable form as a circpad_machine_runtime_t.

Each state of a padding state machine can be either:

Padding machines start from the START state and finish with the END state. They can transition between states using the events in circpad_event_t.

When a padding machine reaches the END state, it gets wiped from the circuit so that other padding machines can take over if needed (see circpad_machine_spec_transitioned_to_end()).

General notes:

All used machines should be heap allocated and placed into origin_padding_machines/relay_padding_machines so that they get correctly cleaned up by the circpad_free_all() function.

Definition in file circuitpadding.c.

Macro Definition Documentation

◆ CIRCUITPADDING_PRIVATE

#define CIRCUITPADDING_PRIVATE

Definition at line 49 of file circuitpadding.c.

◆ ENSURE_BIN_CAPACITY

#define ENSURE_BIN_CAPACITY (   bin_index)
Value:
if (BUG(mi->histogram[bin_index] == 0)) { \
return; \
}

Definition at line 865 of file circuitpadding.c.

◆ FOR_EACH_ACTIVE_CIRCUIT_MACHINE_BEGIN

#define FOR_EACH_ACTIVE_CIRCUIT_MACHINE_BEGIN (   loop_var,
  circ 
)
Value:
if (!(circ)->padding_info[loop_var]) \
continue;
#define FOR_EACH_CIRCUIT_MACHINE_BEGIN(loop_var)

Loop over the current active padding state machines using loop_var as the loop variable. If a machine is not active, skip it.

Definition at line 131 of file circuitpadding.c.

◆ FOR_EACH_ACTIVE_CIRCUIT_MACHINE_END

#define FOR_EACH_ACTIVE_CIRCUIT_MACHINE_END   } STMT_END ;

Definition at line 135 of file circuitpadding.c.

◆ FOR_EACH_CIRCUIT_MACHINE_BEGIN

#define FOR_EACH_CIRCUIT_MACHINE_BEGIN (   loop_var)
Value:
STMT_BEGIN \
for (int loop_var = 0; loop_var < CIRCPAD_MAX_MACHINES; loop_var++) {
#define CIRCPAD_MAX_MACHINES
Definition: circuit_st.h:28

Loop over the current padding state machines using loop_var as the loop variable.

Definition at line 124 of file circuitpadding.c.

◆ FOR_EACH_CIRCUIT_MACHINE_END

#define FOR_EACH_CIRCUIT_MACHINE_END   } STMT_END ;

Definition at line 127 of file circuitpadding.c.

Function Documentation

◆ check_machine_token_supply()

static circpad_decision_t check_machine_token_supply ( circpad_machine_runtime_t mi)
static

Check our state's cell limit count and tokens.

Returns 1 if either limits are hit and we decide to change states, otherwise returns 0.

Definition at line 982 of file circuitpadding.c.

Referenced by circpad_cell_event_padding_sent().

◆ circpad_add_matching_machines()

STATIC void circpad_add_matching_machines ( origin_circuit_t on_circ,
smartlist_t machines_sl 
)

Negotiate new machines that would apply to this circuit, given the machines inside machines_sl.

This function checks to see if we have any free machine indexes, and for each free machine index, it initializes the most recently added origin-side padding machine that matches the target machine index and circuit conditions, and negotiates it with the appropriate middle relay.

Definition at line 2175 of file circuitpadding.c.

Referenced by circpad_machine_event_circ_added_hop(), circpad_machine_event_circ_built(), circpad_machine_event_circ_has_no_relay_early(), circpad_machine_event_circ_has_no_streams(), circpad_machine_event_circ_has_streams(), and circpad_machine_event_circ_purpose_changed().

◆ circpad_cell_event_nonpadding_received()

void circpad_cell_event_nonpadding_received ( circuit_t on_circ)

A "non-padding" cell has been received by this endpoint. React according to any padding state machines on the circuit.

For origin circuits, this means we read a cell from the network. For middle relay circuits, this means we received a cell from the origin.

Definition at line 1908 of file circuitpadding.c.

Referenced by circpad_deliver_unrecognized_cell_events().

◆ circpad_cell_event_nonpadding_sent()

void circpad_cell_event_nonpadding_sent ( circuit_t on_circ)

A "non-padding" cell has been sent from this endpoint. React according to any padding state machines on the circuit.

For origin circuits, this means we sent a cell into the network. For middle relay circuits, this means we sent a cell towards the origin.

Definition at line 1818 of file circuitpadding.c.

Referenced by circpad_deliver_unrecognized_cell_events().

◆ circpad_cell_event_padding_received()

void circpad_cell_event_padding_received ( circuit_t on_circ)

A padding cell has been received by this endpoint. React according to any padding state machines on the circuit.

For origin circuits, this means we read a cell from the network. For middle relay circuits, this means we received a cell from the origin.

Definition at line 1955 of file circuitpadding.c.

◆ circpad_cell_event_padding_sent()

void circpad_cell_event_padding_sent ( circuit_t on_circ)

A padding cell has been sent from this endpoint. React according to any padding state machines on the circuit.

For origin circuits, this means we sent a cell into the network. For middle relay circuits, this means we sent a cell towards the origin.

Definition at line 1929 of file circuitpadding.c.

◆ circpad_check_received_cell()

int circpad_check_received_cell ( cell_t cell,
circuit_t circ,
crypt_path_t layer_hint,
const relay_header_t rh 
)

Check if this cell or circuit are related to circuit padding and handle them if so. Return 0 if the cell was handled in this subsystem and does not need any other consideration, otherwise return 1.

Definition at line 1849 of file circuitpadding.c.

◆ circpad_choose_state_length()

static void circpad_choose_state_length ( circpad_machine_runtime_t mi)
static

Choose a length for this state (in cells), if specified.

Definition at line 535 of file circuitpadding.c.

◆ circpad_circ_purpose_to_mask()

circpad_purpose_mask_t circpad_circ_purpose_to_mask ( uint8_t  circ_purpose)

Convert a normal circuit purpose into a bitmask that we can use for determining matching circuits.

Definition at line 2117 of file circuitpadding.c.

Referenced by circpad_machine_conditions_keep().

◆ circpad_circuit_free_all_machineinfos()

void circpad_circuit_free_all_machineinfos ( circuit_t circ)

Free all padding machines and mutable info associated with circuit

Definition at line 309 of file circuitpadding.c.

◆ circpad_circuit_machineinfo_free_idx()

static void circpad_circuit_machineinfo_free_idx ( circuit_t circ,
int  idx 
)
static

Free the machineinfo at an index

Definition at line 142 of file circuitpadding.c.

Referenced by circpad_circuit_free_all_machineinfos(), circpad_machine_spec_transitioned_to_end(), and circpad_shutdown_old_machines().

◆ circpad_circuit_machineinfo_new()

STATIC circpad_machine_runtime_t * circpad_circuit_machineinfo_new ( circuit_t on_circ,
int  machine_index 
)

Allocate a new mutable machineinfo structure.

Definition at line 320 of file circuitpadding.c.

◆ circpad_circuit_state()

static circpad_circuit_state_t circpad_circuit_state ( origin_circuit_t circ)
inlinestatic

Returns a minimized representation of the circuit state.

The padding code only cares if the circuit is building, opened, used for streams, and/or still has relay early cells. This returns a bitmask of all state properties that apply to this circuit.

Definition at line 2089 of file circuitpadding.c.

Referenced by circpad_machine_conditions_keep().

◆ circpad_circuit_supports_padding()

static bool circpad_circuit_supports_padding ( origin_circuit_t circ,
int  target_hopnum 
)
static

Return true if a particular circuit supports padding at the desired hop.

Definition at line 2861 of file circuitpadding.c.

◆ circpad_deliver_recognized_relay_cell_events()

void circpad_deliver_recognized_relay_cell_events ( circuit_t circ,
uint8_t  relay_command,
crypt_path_t layer_hint 
)

Deliver circpad events for "recognized" relay cells.

Recognized cells are destined for this hop, either client or middle. Check if this is a padding cell or not, and send the appropriate received event.

Definition at line 2402 of file circuitpadding.c.

Referenced by connection_edge_process_ordered_relay_cell().

◆ circpad_deliver_sent_relay_cell_events()

void circpad_deliver_sent_relay_cell_events ( circuit_t circ,
uint8_t  relay_command 
)

Deliver circpad events for relay cells sent from us.

If this is a padding cell, update our padding stats and deliver the event. Otherwise just deliver the event.

Definition at line 2439 of file circuitpadding.c.

◆ circpad_deliver_unrecognized_cell_events()

void circpad_deliver_unrecognized_cell_events ( circuit_t circ,
cell_direction_t  dir 
)

Deliver circpad events for an "unrecognized cell".

Unrecognized cells are sent to relays and are forwarded onto the next hop of their circuits. Unrecognized cells are by definition not padding. We need to tell relay-side state machines that a non-padding cell was sent or received, depending on the direction, so they can update their histograms and decide to pad or not.

Definition at line 2374 of file circuitpadding.c.

◆ circpad_distribution_sample()

static double circpad_distribution_sample ( circpad_distribution_t  dist)
static

Sample a value from the specified probability distribution.

Uses functions from src/lib/math/prob_distr.c .

Definition at line 695 of file circuitpadding.c.

Referenced by circpad_distribution_sample_iat_delay().

◆ circpad_distribution_sample_iat_delay()

static circpad_delay_t circpad_distribution_sample_iat_delay ( const circpad_state_t state,
circpad_delay_t  delay_shift 
)
static

Sample a value from our iat_dist, and clamp it safely to circpad_delay_t.

Before returning, add delay_shift (can be zero) to the sampled value.

Definition at line 567 of file circuitpadding.c.

◆ circpad_estimate_circ_rtt_on_received()

static void circpad_estimate_circ_rtt_on_received ( circuit_t circ,
circpad_machine_runtime_t mi 
)
static

Estimate the circuit RTT from the current middle hop out to the end of the circuit.

We estimate RTT by calculating the time between "receive" and "send" at a middle hop. This is because we "receive" a cell from the origin, and then relay it towards the exit before a response comes back. It is that response time from the exit side that we want to measure, so that we can make use of it for synthetic response delays.

Definition at line 1691 of file circuitpadding.c.

Referenced by circpad_cell_event_nonpadding_received().

◆ circpad_estimate_circ_rtt_on_send()

static void circpad_estimate_circ_rtt_on_send ( circuit_t circ,
circpad_machine_runtime_t mi 
)
static

Handles the "send" side of RTT calculation at middle nodes.

This function calculates the RTT from the middle to the end of the circuit by subtracting the last received cell timestamp from the current time. It allows back-to-back cells until the circuit is opened, to allow for var cell handshakes. XXX: Check our var cell plans to make sure this will work.

Definition at line 1757 of file circuitpadding.c.

◆ circpad_free_all()

void circpad_free_all ( void  )

Free all memory allocated by the circuitpadding subsystem.

Definition at line 3130 of file circuitpadding.c.

◆ circpad_get_histogram_bin_midpoint()

static circpad_delay_t circpad_get_histogram_bin_midpoint ( const circpad_machine_runtime_t mi,
int  bin_index 
)
static

Return the midpoint of the histogram bin bin_index.

Definition at line 406 of file circuitpadding.c.

◆ circpad_handle_padding_negotiate()

signed_error_t circpad_handle_padding_negotiate ( circuit_t circ,
cell_t cell 
)

Parse and react to a padding_negotiate cell.

This is called at the middle node upon receipt of the client's choice of state machine, so that it can use the requested state machine index, if it is available.

Returns -1 on error, 0 on success.

Definition at line 2972 of file circuitpadding.c.

◆ circpad_handle_padding_negotiated()

signed_error_t circpad_handle_padding_negotiated ( circuit_t circ,
cell_t cell,
crypt_path_t layer_hint 
)

Parse and react to a padding_negotiated cell.

This is called at the origin upon receipt of the middle's response to our choice of state machine.

Returns -1 on error, 0 on success.

Definition at line 3060 of file circuitpadding.c.

◆ circpad_histogram_bin_to_usec()

STATIC circpad_delay_t circpad_histogram_bin_to_usec ( const circpad_machine_runtime_t mi,
circpad_hist_index_t  bin 
)

Get the lower bound of a histogram bin.

You can obtain the upper bound using histogram_get_bin_upper_bound().

This function can also be called with 'bin' set to a value equal or greater than histogram_len in which case the infinity bin is chosen and CIRCPAD_DELAY_INFINITE is returned.

Definition at line 367 of file circuitpadding.c.

Referenced by circpad_get_histogram_bin_midpoint(), circpad_machine_first_lower_index(), and histogram_get_bin_upper_bound().

◆ circpad_histogram_usec_to_bin()

STATIC circpad_hist_index_t circpad_histogram_usec_to_bin ( const circpad_machine_runtime_t mi,
circpad_delay_t  usec 
)

Return the bin that contains the usec argument. "Contains" is defined as us in [lower, upper).

This function will never return the infinity bin (histogram_len-1), in order to simplify the rest of the code, so if a usec is provided that falls above the highest non-infinity bin, that bin index will be returned.

Definition at line 424 of file circuitpadding.c.

Referenced by circpad_machine_first_higher_index(), circpad_machine_first_lower_index(), circpad_machine_remove_closest_token(), and circpad_machine_remove_exact().

◆ circpad_internal_event_bins_empty()

circpad_decision_t circpad_internal_event_bins_empty ( circpad_machine_runtime_t mi)

All of the bins of our current state's histogram's are empty.

Check to see if this means transition to another state, and if not, refill the tokens.

Return 1 if we decide to transition, 0 otherwise.

Definition at line 1989 of file circuitpadding.c.

Referenced by check_machine_token_supply().

◆ circpad_internal_event_infinity()

circpad_decision_t circpad_internal_event_infinity ( circpad_machine_runtime_t mi)

An "infinite" delay has ben chosen from one of our histograms.

"Infinite" delays mean don't send padding – but they can also mean transition to another state depending on the state machine definitions. Check the rules and react accordingly.

Return 1 if we decide to transition, 0 otherwise.

Definition at line 1975 of file circuitpadding.c.

◆ circpad_internal_event_state_length_up()

circpad_decision_t circpad_internal_event_state_length_up ( circpad_machine_runtime_t mi)

This state has used up its cell count. Emit the event and see if we transition.

Return 1 if we decide to transition, 0 otherwise.

Definition at line 2008 of file circuitpadding.c.

◆ circpad_is_padding_allowed()

static bool circpad_is_padding_allowed ( void  )
static

Return true if padding is allowed by torrc and consensus.

Definition at line 1350 of file circuitpadding.c.

Referenced by circpad_machine_schedule_padding().

◆ circpad_is_token_removal_supported()

static int circpad_is_token_removal_supported ( circpad_machine_runtime_t mi)
inlinestatic

Return true if the machine supports token removal.

Token removal is equivalent to having a mutable histogram in the circpad_machine_runtime_t mutable info. So while we're at it, let's assert that everything is consistent between the mutable runtime and the readonly machine spec.

Definition at line 467 of file circuitpadding.c.

Referenced by check_machine_token_supply().

◆ circpad_machine_conditions_apply()

static bool circpad_machine_conditions_apply ( origin_circuit_t circ,
const circpad_machine_spec_t machine 
)
inlinestatic

Returns true if the circuit matches the conditions.

Definition at line 2017 of file circuitpadding.c.

Referenced by circpad_add_matching_machines(), and circpad_shutdown_old_machines().

◆ circpad_machine_conditions_keep()

static bool circpad_machine_conditions_keep ( origin_circuit_t circ,
const circpad_machine_spec_t machine 
)
inlinestatic

Check to see if any of the keep conditions still apply to this circuit.

These conditions keep the machines active if they match, but do not cause new machines to start up.

Definition at line 2066 of file circuitpadding.c.

Referenced by circpad_shutdown_old_machines().

◆ circpad_machine_count_nonpadding_sent()

static void circpad_machine_count_nonpadding_sent ( circpad_machine_runtime_t mi)
inlinestatic

Count a nonpadding packet as being sent.

This function updates our overhead accounting variables, as well as decrements the state limit packet counter, if the latter was flagged as applying to non-padding as well.

Definition at line 1059 of file circuitpadding.c.

◆ circpad_machine_count_padding_sent()

static void circpad_machine_count_padding_sent ( circpad_machine_runtime_t mi)
inlinestatic

Count that a padding packet was sent.

This updates our state length count, our machine rate limit counts, and if token removal is used, decrements the histogram.

Definition at line 1018 of file circuitpadding.c.

◆ circpad_machine_current_state()

STATIC const circpad_state_t * circpad_machine_current_state ( const circpad_machine_runtime_t mi)

Return the circpad_state_t for the current state based on the mutable info.

This function returns NULL when the machine is in the end state or in an invalid state.

Definition at line 340 of file circuitpadding.c.

Referenced by circpad_choose_state_length(), circpad_histogram_bin_to_usec(), circpad_histogram_usec_to_bin(), circpad_machine_remove_token(), circpad_machine_sample_delay(), circpad_machine_setup_tokens(), and circpad_machine_spec_transition().

◆ circpad_machine_event_circ_added_hop()

void circpad_machine_event_circ_added_hop ( origin_circuit_t on_circ)

Event that tells us we added a hop to an origin circuit.

This event is used to decide if we should create a padding machine on a circuit.

Definition at line 2251 of file circuitpadding.c.

◆ circpad_machine_event_circ_built()

void circpad_machine_event_circ_built ( origin_circuit_t circ)

Event that tells us that an origin circuit is now built.

Shut down any machines that only applied to un-built circuits. Activate any new ones.

Definition at line 2265 of file circuitpadding.c.

◆ circpad_machine_event_circ_has_no_relay_early()

void circpad_machine_event_circ_has_no_relay_early ( origin_circuit_t circ)

Event that tells us that an origin circuit is out of RELAY_EARLY cells.

Shut down any machines that only applied to RELAY_EARLY circuits. Activate any new ones.

Definition at line 2292 of file circuitpadding.c.

◆ circpad_machine_event_circ_has_no_streams()

void circpad_machine_event_circ_has_no_streams ( origin_circuit_t circ)

Streams detached event.

Called from circuit_detach_stream()

Shut down any machines that only applied to machines without streams. Activate any new ones.

Definition at line 2322 of file circuitpadding.c.

◆ circpad_machine_event_circ_has_streams()

void circpad_machine_event_circ_has_streams ( origin_circuit_t circ)

Streams attached event.

Called from link_apconn_to_circ() and handle_hs_exit_conn()

Shut down any machines that only applied to machines without streams. Activate any new ones.

Definition at line 2307 of file circuitpadding.c.

◆ circpad_machine_event_circ_purpose_changed()

void circpad_machine_event_circ_purpose_changed ( origin_circuit_t circ)

Circpad purpose changed event.

Shut down any machines that don't apply to our circ purpose. Activate any new ones that do.

Definition at line 2278 of file circuitpadding.c.

◆ circpad_machine_first_higher_index()

static circpad_hist_index_t circpad_machine_first_higher_index ( const circpad_machine_runtime_t mi,
circpad_delay_t  target_bin_usec 
)
static

Find the index of the first bin whose upper bound is greater than the target, and that has tokens remaining.

Used for histograms with token removal.

Definition at line 780 of file circuitpadding.c.

Referenced by circpad_machine_remove_closest_token(), and circpad_machine_remove_higher_token().

◆ circpad_machine_first_lower_index()

static circpad_hist_index_t circpad_machine_first_lower_index ( const circpad_machine_runtime_t mi,
circpad_delay_t  target_bin_usec 
)
static

Find the index of the first bin whose lower bound is lower or equal to target_bin_usec, and that still has tokens remaining.

Used for histograms with token removal.

Definition at line 804 of file circuitpadding.c.

Referenced by circpad_machine_remove_closest_token(), and circpad_machine_remove_lower_token().

◆ circpad_machine_reached_padding_limit()

STATIC bool circpad_machine_reached_padding_limit ( circpad_machine_runtime_t mi)

Check this machine against its padding limits, as well as global consensus limits.

We have two limits: a percent and a cell count. The cell count limit must be reached before the percent is enforced (this is to optionally allow very light padding of things like circuit setup while there is no other traffic on the circuit).

TODO: Don't apply limits to machines form torrc.

Returns 1 if limits are set and we've hit them. Otherwise returns 0.

Definition at line 1378 of file circuitpadding.c.

◆ circpad_machine_remove_closest_token()

STATIC void circpad_machine_remove_closest_token ( circpad_machine_runtime_t mi,
circpad_delay_t  target_bin_usec,
bool  use_usec 
)

Remove a token from the closest non-empty bin to the target.

If use_usec is true, measure "closest" in terms of the next closest bin midpoint.

If it is false, use bin index distance only.

Used for histograms with token removal.

Definition at line 881 of file circuitpadding.c.

◆ circpad_machine_remove_exact()

static void circpad_machine_remove_exact ( circpad_machine_runtime_t mi,
circpad_delay_t  target_bin_usec 
)
static

Remove a token from the exact bin corresponding to the target.

If it is empty, do nothing.

Used for histograms with token removal.

Definition at line 965 of file circuitpadding.c.

◆ circpad_machine_remove_higher_token()

STATIC void circpad_machine_remove_higher_token ( circpad_machine_runtime_t mi,
circpad_delay_t  target_bin_usec 
)

Remove a token from the first non-empty bin whose upper bound is greater than the target.

Used for histograms with token removal.

Definition at line 827 of file circuitpadding.c.

◆ circpad_machine_remove_lower_token()

STATIC void circpad_machine_remove_lower_token ( circpad_machine_runtime_t mi,
circpad_delay_t  target_bin_usec 
)

Remove a token from the first non-empty bin whose upper bound is lower than the target.

Used for histograms with token removal.

Definition at line 850 of file circuitpadding.c.

◆ circpad_machine_remove_token()

STATIC void circpad_machine_remove_token ( circpad_machine_runtime_t mi)

When a non-padding packet arrives, remove a token from the bin corresponding to the delta since last sent packet. If that bin is empty, choose a token based on the specified removal strategy in the state machine.

Definition at line 1114 of file circuitpadding.c.

Referenced by circpad_machine_count_nonpadding_sent().

◆ circpad_machine_sample_delay()

STATIC circpad_delay_t circpad_machine_sample_delay ( circpad_machine_runtime_t mi)

Sample an expected time-until-next-packet delay from the histogram or probability distribution.

A bin of the histogram is chosen with probability proportional to the number of tokens in each bin, and then a time value is chosen uniformly from that bin's [start,end) time range.

Definition at line 596 of file circuitpadding.c.

◆ circpad_machine_schedule_padding()

circpad_decision_t circpad_machine_schedule_padding ( circpad_machine_runtime_t mi)

Schedule the next padding time according to the machineinfo on a circuit.

The histograms represent inter-packet-delay. Whenever you get an packet event you should be scheduling your next timer (after cancelling any old ones and updating tokens accordingly).

Returns 1 if we decide to transition states (due to infinity bin), 0 otherwise.

Definition at line 1426 of file circuitpadding.c.

◆ circpad_machine_setup_tokens()

STATIC void circpad_machine_setup_tokens ( circpad_machine_runtime_t mi)

This function frees any token bins allocated from a previous state

Called after a state transition, or if the bins are empty.

Definition at line 500 of file circuitpadding.c.

◆ circpad_machine_spec_transition()

circpad_decision_t circpad_machine_spec_transition ( circpad_machine_runtime_t mi,
circpad_event_t  event 
)

Generic state transition function for padding state machines.

Given an event and our mutable machine info, decide if/how to transition to a different state, and perform actions accordingly.

Returns 1 if we transition states, 0 otherwise.

Definition at line 1611 of file circuitpadding.c.

Referenced by circpad_cell_event_nonpadding_received(), circpad_cell_event_padding_received(), circpad_internal_event_bins_empty(), circpad_internal_event_infinity(), and circpad_internal_event_state_length_up().

◆ circpad_machine_spec_transitioned_to_end()

static void circpad_machine_spec_transitioned_to_end ( circpad_machine_runtime_t mi)
static

If the machine transitioned to the END state, we need to check to see if it wants us to shut it down immediately. If it does, then we need to send the appropriate negotiation commands depending on which side it is.

After this function is called, mi may point to freed memory. Do not access it.

Definition at line 1551 of file circuitpadding.c.

◆ circpad_machine_states_init()

void circpad_machine_states_init ( circpad_machine_spec_t machine,
circpad_statenum_t  num_states 
)

Initialize the states array for a circpad machine.

Definition at line 2466 of file circuitpadding.c.

◆ circpad_machine_update_state_length_for_nonpadding()

static void circpad_machine_update_state_length_for_nonpadding ( circpad_machine_runtime_t mi)
inlinestatic

Decrement the state length counter for a non-padding packet.

Only updates the state length if we're using that feature, we have a state, and the machine wants to count non-padding packets towards the state length.

Definition at line 1085 of file circuitpadding.c.

Referenced by circpad_machine_count_nonpadding_sent().

◆ circpad_machines_free()

void circpad_machines_free ( void  )

Free our padding machines

Definition at line 2805 of file circuitpadding.c.

◆ circpad_machines_init()

void circpad_machines_init ( void  )

Initialize all of our padding machines.

This is called at startup. It sets up some global machines, and then loads some from torrc, and from the tor consensus.

Definition at line 2778 of file circuitpadding.c.

◆ circpad_marked_circuit_for_padding()

int circpad_marked_circuit_for_padding ( circuit_t circ,
int  reason 
)

Return true if circpad has decided to hold the circuit open for additional padding. This function is used to take and retain ownership of certain types of circuits that have padding machines on them, that have been passed to circuit_mark_for_close().

circuit_mark_for_close() calls this function to ask circpad if any padding machines want to keep the circuit open longer to pad.

Any non-measurement circuit that was closed for a normal, non-error reason code may be held open for up to CIRCPAD_DELAY_INFINITE microseconds between network-driven cell events.

After CIRCPAD_DELAY_INFINITE microseconds of silence on a circuit, this function will no longer hold it open (it will return 0 regardless of what the machines ask for, and thus circuit_expire_old_circuits_clientside() will close the circuit after roughly 1.25hr of idle time, maximum, regardless of the padding machine state.

Definition at line 176 of file circuitpadding.c.

◆ circpad_negotiate_padding()

signed_error_t circpad_negotiate_padding ( origin_circuit_t circ,
circpad_machine_num_t  machine,
uint8_t  target_hopnum,
uint8_t  command,
uint32_t  machine_ctr 
)

Try to negotiate padding.

Returns -1 on error, 0 on success.

Definition at line 2879 of file circuitpadding.c.

Referenced by circpad_machine_spec_transitioned_to_end(), and circpad_shutdown_old_machines().

◆ circpad_new_consensus_params()

void circpad_new_consensus_params ( const networkstatus_t ns)

Cache our consensus parameters upon consensus update.

Definition at line 1323 of file circuitpadding.c.

◆ circpad_node_supports_padding()

static bool circpad_node_supports_padding ( const node_t node)
static

Check the Protover info to see if a node supports padding.

Definition at line 2826 of file circuitpadding.c.

Referenced by circpad_circuit_supports_padding().

◆ circpad_padding_is_from_expected_hop()

bool circpad_padding_is_from_expected_hop ( circuit_t circ,
crypt_path_t from_hop 
)

Verify that padding is coming from the expected hop.

Returns true if from_hop matches the target hop from one of our padding machines.

Returns false if we're not an origin circuit, or if from_hop does not match one of the padding machines.

Definition at line 2338 of file circuitpadding.c.

◆ circpad_padding_negotiated()

bool circpad_padding_negotiated ( circuit_t circ,
circpad_machine_num_t  machine,
uint8_t  command,
uint8_t  response,
uint32_t  machine_ctr 
)

Try to negotiate padding.

Returns 1 if successful (or already set up), 0 otherwise.

Definition at line 2927 of file circuitpadding.c.

Referenced by circpad_machine_spec_transitioned_to_end().

◆ circpad_register_padding_machine()

void circpad_register_padding_machine ( circpad_machine_spec_t machine,
smartlist_t machine_list 
)

Definition at line 2598 of file circuitpadding.c.

◆ circpad_send_command_to_hop()

STATIC signed_error_t circpad_send_command_to_hop ( origin_circuit_t circ,
uint8_t  hopnum,
uint8_t  relay_command,
const uint8_t *  payload,
ssize_t  payload_len 
)

Send a relay command with a relay cell payload on a circuit to the particular hopnum.

Hopnum starts at 1 (1=guard, 2=middle, 3=exit, etc).

Payload may be null.

Returns negative on error, 0 on success.

Definition at line 1189 of file circuitpadding.c.

◆ circpad_send_padding_callback()

static void circpad_send_padding_callback ( tor_timer_t *  timer,
void *  args,
const struct monotime_t time 
)
static

Tor-timer compatible callback that tells us to send a padding cell.

Timers are associated with circpad_machine_runtime_t's. When the machineinfo is freed on a circuit, the timers are cancelled. Since the lifetime of machineinfo is always longer than the timers, handles are not needed.

Definition at line 1299 of file circuitpadding.c.

◆ circpad_send_padding_cell_for_callback()

circpad_decision_t circpad_send_padding_cell_for_callback ( circpad_machine_runtime_t mi)

Callback helper to send a padding cell.

This helper is called after our histogram-sampled delay period passes without another packet being sent first. If a packet is sent before this callback happens, it is canceled. So when we're called here, send padding right away.

If sending this padding cell forced us to transition states return CIRCPAD_STATE_CHANGED. Otherwise return CIRCPAD_STATE_UNCHANGED.

Definition at line 1229 of file circuitpadding.c.

◆ circpad_setup_machine_on_circ()

static void circpad_setup_machine_on_circ ( circuit_t on_circ,
const circpad_machine_spec_t machine 
)
static

Definition at line 2486 of file circuitpadding.c.

◆ circpad_shutdown_old_machines()

static void circpad_shutdown_old_machines ( origin_circuit_t on_circ)
static

◆ circuit_get_nth_node()

STATIC const node_t * circuit_get_nth_node ( origin_circuit_t circ,
int  hop 
)

Get a node_t for the nth hop in our circuit, starting from 1.

Returns node_t from the consensus for that hop, if it is opened. Otherwise returns NULL.

Definition at line 2846 of file circuitpadding.c.

Referenced by circpad_circuit_supports_padding().

◆ free_circ_machineinfos_with_machine_num()

static int free_circ_machineinfos_with_machine_num ( circuit_t circ,
int  machine_num,
uint32_t  machine_ctr 
)
static

Free all the machineinfos in circ that match machine_num.

If machine_ctr is non-zero, also make sure it matches the padding_info's machine counter before freeing.

Returns true if any machineinfos with that number were freed. False otherwise.

Definition at line 280 of file circuitpadding.c.

◆ histogram_get_bin_upper_bound()

STATIC circpad_delay_t histogram_get_bin_upper_bound ( const circpad_machine_runtime_t mi,
circpad_hist_index_t  bin 
)

Like circpad_histogram_bin_to_usec() but return the upper bound of bin. (The upper bound is included in the bin.)

Definition at line 398 of file circuitpadding.c.

Referenced by circpad_get_histogram_bin_midpoint(), and circpad_machine_first_higher_index().

◆ machine_spec_free_()

STATIC void machine_spec_free_ ( circpad_machine_spec_t m)

Free memory allocated by this machine spec.

Definition at line 3120 of file circuitpadding.c.

◆ padding_machine_is_valid()

static bool padding_machine_is_valid ( const circpad_machine_spec_t machine)
static

Basic validation of padding machine

Definition at line 2581 of file circuitpadding.c.

◆ padding_machine_state_is_valid()

static bool padding_machine_state_is_valid ( const circpad_state_t state)
static

Validate a single state of a padding machine

Definition at line 2536 of file circuitpadding.c.

Referenced by padding_machine_is_valid().

Variable Documentation

◆ circpad_global_allowed_cells

uint16_t circpad_global_allowed_cells
static

Definition at line 98 of file circuitpadding.c.

◆ circpad_global_max_padding_percent

uint8_t circpad_global_max_padding_percent
static

Definition at line 97 of file circuitpadding.c.

◆ circpad_global_nonpadding_sent

uint64_t circpad_global_nonpadding_sent
static

Definition at line 103 of file circuitpadding.c.

◆ circpad_global_padding_sent

uint64_t circpad_global_padding_sent
static

Global cell counts, for rate limiting

Definition at line 102 of file circuitpadding.c.

◆ circpad_max_circ_queued_cells

uint16_t circpad_max_circ_queued_cells
static

Definition at line 99 of file circuitpadding.c.

◆ circpad_padding_disabled

uint8_t circpad_padding_disabled
static

Cached consensus params

Definition at line 95 of file circuitpadding.c.

Referenced by circpad_is_padding_allowed(), circpad_machine_conditions_apply(), and circpad_new_consensus_params().

◆ circpad_padding_reduced

uint8_t circpad_padding_reduced
static

Definition at line 96 of file circuitpadding.c.

◆ origin_padding_machines

STATIC smartlist_t* origin_padding_machines = NULL

This is the list of circpad_machine_spec_t's parsed from consensus and torrc that have origin_side == 1 (ie: are for client side).

The machines in this smartlist are considered immutable and they are used as-is by circuits so they should not change or get deallocated in Tor's runtime and as long as circuits are alive.

Definition at line 111 of file circuitpadding.c.

Referenced by circpad_free_all(), circpad_machine_event_circ_added_hop(), circpad_machine_event_circ_built(), circpad_machine_event_circ_has_no_relay_early(), circpad_machine_event_circ_has_no_streams(), circpad_machine_event_circ_has_streams(), circpad_machine_event_circ_purpose_changed(), and circpad_machines_free().

◆ relay_padding_machines

STATIC smartlist_t* relay_padding_machines = NULL

This is the list of circpad_machine_spec_t's parsed from consensus and torrc that have origin_side == 0 (ie: are for relay side).

The machines in this smartlist are considered immutable and they are used as-is by circuits so they should not change or get deallocated in Tor's runtime and as long as circuits are alive.

Definition at line 119 of file circuitpadding.c.