tor  master
Data Structures | Macros | Typedefs | Functions
onion.c File Reference

Functions to queue create cells, wrap the various onionskin types, and parse and create the CREATE cell and its allies. More...

#include "or.h"
#include "circuitbuild.h"
#include "circuitlist.h"
#include "config.h"
#include "cpuworker.h"
#include "crypto_util.h"
#include "networkstatus.h"
#include "onion.h"
#include "onion_fast.h"
#include "onion_ntor.h"
#include "onion_tap.h"
#include "relay.h"
#include "rephist.h"
#include "router.h"
#include "ed25519_cert.h"
Include dependency graph for onion.c:

Data Structures

struct  onion_queue_t
 

Macros

#define ONIONQUEUE_WAIT_CUTOFF   5
 
#define WARN_TOO_MANY_CIRC_CREATIONS_INTERVAL   (60)
 
#define DEFAULT_NUM_NTORS_PER_TAP   10
 
#define MIN_NUM_NTORS_PER_TAP   1
 
#define MAX_NUM_NTORS_PER_TAP   100000
 
#define MAX_KEYS_TMP_LEN   128
 
#define NTOR_CREATE_MAGIC   "ntorNTORntorNTOR"
 

Typedefs

typedef struct onion_queue_t onion_queue_t
 

Functions

int onion_pending_add (or_circuit_t *circ, create_cell_t *onionskin)
 
or_circuit_tonion_next_task (create_cell_t **onionskin_out)
 
int onion_num_pending (uint16_t handshake_type)
 
void onion_pending_remove (or_circuit_t *circ)
 
void clear_pending_onions (void)
 
server_onion_keys_tserver_onion_keys_new (void)
 
void server_onion_keys_free_ (server_onion_keys_t *keys)
 
void onion_handshake_state_release (onion_handshake_state_t *state)
 
int onion_skin_create (int type, const extend_info_t *node, onion_handshake_state_t *state_out, uint8_t *onion_skin_out)
 
int onion_skin_server_handshake (int type, const uint8_t *onion_skin, size_t onionskin_len, const server_onion_keys_t *keys, uint8_t *reply_out, uint8_t *keys_out, size_t keys_out_len, uint8_t *rend_nonce_out)
 
int onion_skin_client_handshake (int type, const onion_handshake_state_t *handshake_state, const uint8_t *reply, size_t reply_len, uint8_t *keys_out, size_t keys_out_len, uint8_t *rend_authenticator_out, const char **msg_out)
 
void create_cell_init (create_cell_t *cell_out, uint8_t cell_type, uint16_t handshake_type, uint16_t handshake_len, const uint8_t *onionskin)
 
int create_cell_parse (create_cell_t *cell_out, const cell_t *cell_in)
 
int created_cell_parse (created_cell_t *cell_out, const cell_t *cell_in)
 
int extend_cell_parse (extend_cell_t *cell_out, const uint8_t command, const uint8_t *payload, size_t payload_length)
 
int extended_cell_parse (extended_cell_t *cell_out, const uint8_t command, const uint8_t *payload, size_t payload_len)
 
int create_cell_format (cell_t *cell_out, const create_cell_t *cell_in)
 
int create_cell_format_relayed (cell_t *cell_out, const create_cell_t *cell_in)
 
int created_cell_format (cell_t *cell_out, const created_cell_t *cell_in)
 
int extend_cell_format (uint8_t *command_out, uint16_t *len_out, uint8_t *payload_out, const extend_cell_t *cell_in)
 
int extended_cell_format (uint8_t *command_out, uint16_t *len_out, uint8_t *payload_out, const extended_cell_t *cell_in)
 

Detailed Description

Functions to queue create cells, wrap the various onionskin types, and parse and create the CREATE cell and its allies.

This module has a few functions, all related to the CREATE/CREATED handshake that we use on links in order to create a circuit, and the related EXTEND/EXTENDED handshake that we use over circuits in order to extend them an additional hop.

In this module, we provide a set of abstractions to create a uniform interface over the three circuit extension handshakes that Tor has used over the years (TAP, CREATE_FAST, and ntor). These handshakes are implemented in onion_tap.c, onion_fast.c, and onion_ntor.c respectively.

All[*] of these handshakes follow a similar pattern: a client, knowing some key from the relay it wants to extend through, generates the first part of a handshake. A relay receives that handshake, and sends a reply. Once the client handles the reply, it knows that it is talking to the right relay, and it shares some freshly negotiated key material with that relay.

We sometimes call the client's part of the handshake an "onionskin". We do this because historically, Onion Routing used a multi-layer structure called an "onion" to construct circuits. Each layer of the onion contained key material chosen by the client, the identity of the next relay in the circuit, and a smaller onion, encrypted with the key of the next relay. When we changed Tor to use a telescoping circuit extension design, it corresponded to sending each layer of the onion separately – as a series of onionskins.

Clients invoke these functions when creating or extending a circuit, from circuitbuild.c.

Relays invoke these functions when they receive a CREATE or EXTEND cell in command.c or relay.c, in order to queue the pending request. They also invoke them from cpuworker.c, which handles dispatching onionskin requests to different worker threads.


This module also handles:

[*] The CREATE_FAST handshake is weaker than described here; see onion_fast.c for more information.

Macro Definition Documentation

◆ NTOR_CREATE_MAGIC

#define NTOR_CREATE_MAGIC   "ntorNTORntorNTOR"

Magic string which, in a CREATE or EXTEND cell, indicates that a seeming TAP payload is really an ntor payload. We'd do away with this if every relay supported EXTEND2, but we want to be able to extend from A to B with ntor even when A doesn't understand EXTEND2 and so can't generate a CREATE2 cell.

◆ ONIONQUEUE_WAIT_CUTOFF

#define ONIONQUEUE_WAIT_CUTOFF   5

5 seconds on the onion queue til we just send back a destroy

Typedef Documentation

◆ onion_queue_t

typedef struct onion_queue_t onion_queue_t

Type for a linked list of circuits that are waiting for a free CPU worker to process a waiting onion handshake.

Function Documentation

◆ clear_pending_onions()

void clear_pending_onions ( void  )

Remove all circuits from the pending list. Called from tor_free_all.

◆ create_cell_init()

void create_cell_init ( create_cell_t cell_out,
uint8_t  cell_type,
uint16_t  handshake_type,
uint16_t  handshake_len,
const uint8_t *  onionskin 
)

Write the various parameters into the create cell. Separate from create_cell_parse() to make unit testing easier.

◆ create_cell_parse()

int create_cell_parse ( create_cell_t cell_out,
const cell_t cell_in 
)

Parse a CREATE, CREATE_FAST, or CREATE2 cell from cell_in into cell_out. Return 0 on success, -1 on failure. (We reject some syntactically valid CREATE2 cells that we can't generate or react to.)

◆ created_cell_format()

int created_cell_format ( cell_t cell_out,
const created_cell_t cell_in 
)

Fill cell_out with a correctly formatted version of the CREATED{,_FAST,2} cell in cell_in. Return 0 on success, -1 on failure.

◆ created_cell_parse()

int created_cell_parse ( created_cell_t cell_out,
const cell_t cell_in 
)

Parse a CREATED, CREATED_FAST, or CREATED2 cell from cell_in into cell_out. Return 0 on success, -1 on failure.

◆ extend_cell_format()

int extend_cell_format ( uint8_t *  command_out,
uint16_t *  len_out,
uint8_t *  payload_out,
const extend_cell_t cell_in 
)

Format the EXTEND{,2} cell in cell_in, storing its relay payload in payload_out, the number of bytes used in *len_out, and the relay command in *command_out. The payload_out must have RELAY_PAYLOAD_SIZE bytes available. Return 0 on success, -1 on failure.

◆ extend_cell_parse()

int extend_cell_parse ( extend_cell_t cell_out,
const uint8_t  command,
const uint8_t *  payload,
size_t  payload_length 
)

Parse an EXTEND or EXTEND2 cell (according to command) from the payload_length bytes of payload into cell_out. Return 0 on success, -1 on failure.

◆ extended_cell_format()

int extended_cell_format ( uint8_t *  command_out,
uint16_t *  len_out,
uint8_t *  payload_out,
const extended_cell_t cell_in 
)

Format the EXTENDED{,2} cell in cell_in, storing its relay payload in payload_out, the number of bytes used in *len_out, and the relay command in *command_out. The payload_out must have RELAY_PAYLOAD_SIZE bytes available. Return 0 on success, -1 on failure.

◆ extended_cell_parse()

int extended_cell_parse ( extended_cell_t cell_out,
const uint8_t  command,
const uint8_t *  payload,
size_t  payload_len 
)

Parse an EXTENDED or EXTENDED2 cell (according to command) from the payload_length bytes of payload into cell_out. Return 0 on success, -1 on failure.

◆ onion_handshake_state_release()

void onion_handshake_state_release ( onion_handshake_state_t state)

Release whatever storage is held in state, depending on its type, and clear its pointer.

◆ onion_next_task()

or_circuit_t* onion_next_task ( create_cell_t **  onionskin_out)

Remove the highest priority item from ol_list[] and return it, or return NULL if the lists are empty.

◆ onion_num_pending()

int onion_num_pending ( uint16_t  handshake_type)

Return the number of handshake_type-style create requests pending.

◆ onion_pending_add()

int onion_pending_add ( or_circuit_t circ,
create_cell_t onionskin 
)

Add circ to the end of ol_list and return 0, except if ol_list is too long, in which case do nothing and return -1.

◆ onion_pending_remove()

void onion_pending_remove ( or_circuit_t circ)

Go through ol_list, find the onion_queue_t element which points to circ, remove and free that element. Leave circ itself alone.

◆ onion_skin_client_handshake()

int onion_skin_client_handshake ( int  type,
const onion_handshake_state_t handshake_state,
const uint8_t *  reply,
size_t  reply_len,
uint8_t *  keys_out,
size_t  keys_out_len,
uint8_t *  rend_authenticator_out,
const char **  msg_out 
)

Perform the final (client-side) step of a circuit-creation handshake of type type, using our state in handshake_state and the server's response in reply. On success, generate keys_out_len bytes worth of key material in keys_out_len, set rend_authenticator_out to the "KH" field that can be used to establish introduction points at this hop, and return 0. On failure, return -1, and set *msg_out to an error message if this is worth complaining to the user about.

◆ onion_skin_create()

int onion_skin_create ( int  type,
const extend_info_t node,
onion_handshake_state_t state_out,
uint8_t *  onion_skin_out 
)

Perform the first step of a circuit-creation handshake of type type (one of ONION_HANDSHAKE_TYPE_*): generate the initial "onion skin" in onion_skin_out, and store any state information in state_out. Return -1 on failure, and the length of the onionskin on acceptance.

◆ onion_skin_server_handshake()

int onion_skin_server_handshake ( int  type,
const uint8_t *  onion_skin,
size_t  onionskin_len,
const server_onion_keys_t keys,
uint8_t *  reply_out,
uint8_t *  keys_out,
size_t  keys_out_len,
uint8_t *  rend_nonce_out 
)

Perform the second (server-side) step of a circuit-creation handshake of type type, responding to the client request in onion_skin using the keys in keys. On success, write our response into reply_out, generate keys_out_len bytes worth of key material in keys_out_len, a hidden service nonce to rend_nonce_out, and return the length of the reply. On failure, return -1.

◆ server_onion_keys_free_()

void server_onion_keys_free_ ( server_onion_keys_t keys)

Release all storage held in keys.

◆ server_onion_keys_new()

server_onion_keys_t* server_onion_keys_new ( void  )

Return a new server_onion_keys_t object with all of the keys and other info we might need to do onion handshakes. (We make a copy of our keys for each cpuworker to avoid race conditions with the main thread, and to avoid locking)