diff options
Diffstat (limited to 'spec/tor-spec')
-rw-r--r-- | spec/tor-spec/cell-packet-format.md | 196 | ||||
-rw-r--r-- | spec/tor-spec/channels.md | 91 | ||||
-rw-r--r-- | spec/tor-spec/circuit-management.md | 6 | ||||
-rw-r--r-- | spec/tor-spec/closing-streams.md | 100 | ||||
-rw-r--r-- | spec/tor-spec/create-created-cells.md | 620 | ||||
-rw-r--r-- | spec/tor-spec/creating-circuits.md | 102 | ||||
-rw-r--r-- | spec/tor-spec/flow-control.md | 199 | ||||
-rw-r--r-- | spec/tor-spec/index.md | 12 | ||||
-rw-r--r-- | spec/tor-spec/negotiating-channels.md | 516 | ||||
-rw-r--r-- | spec/tor-spec/obsolete-channels.md | 269 | ||||
-rw-r--r-- | spec/tor-spec/opening-streams.md | 141 | ||||
-rw-r--r-- | spec/tor-spec/preliminaries.md | 142 | ||||
-rw-r--r-- | spec/tor-spec/relay-cells.md | 219 | ||||
-rw-r--r-- | spec/tor-spec/relay-early.md | 20 | ||||
-rw-r--r-- | spec/tor-spec/relay-keys.md | 175 | ||||
-rw-r--r-- | spec/tor-spec/remote-hostname-lookup.md | 43 | ||||
-rw-r--r-- | spec/tor-spec/routing-relay-cells.md | 99 | ||||
-rw-r--r-- | spec/tor-spec/setting-circuit-keys.md | 62 | ||||
-rw-r--r-- | spec/tor-spec/streams.md | 7 | ||||
-rw-r--r-- | spec/tor-spec/subprotocol-versioning.md | 321 | ||||
-rw-r--r-- | spec/tor-spec/tearing-down-circuits.md | 108 |
21 files changed, 3448 insertions, 0 deletions
diff --git a/spec/tor-spec/cell-packet-format.md b/spec/tor-spec/cell-packet-format.md new file mode 100644 index 0000000..cfc7f36 --- /dev/null +++ b/spec/tor-spec/cell-packet-format.md @@ -0,0 +1,196 @@ +<a id="tor-spec.txt-3"></a> + +# Cells (messages on channels) {#cell-packet-format} + +The basic unit of communication on a Tor channel is a "cell". + +Once a TLS connection is established, +the two parties send cells to each other. +Cells are sent serially, one after another. + +Cells may be sent embedded in TLS records of any size, +or divided across TLS records, +but the framing of TLS records MUST NOT leak information +about the type or contents of the cells. + +Most cells are of fixed length, +with the actual length depending +on the negotiated link protocol on the channel. +Below we designate the negotiated protocol as `v`. + +As an exception, [`VERSIONS` cells] are always sent with `v = 0`, +since no version has yet been negotiated. + +<span id="fixed-length-cell">A fixed-length cell has this format:</span> + +| Field | Size in bytes | Notes | +|-----------|-------------------|-------| +| `CircID` | [`CIRCID_LEN(v)`] | | +| `Command` | 1 | | +| `Body` | [`CELL_BODY_LEN`] | Padded to fit | + +The value of `CIRCID_LEN` depends on the negotiated link protocol. + +Some cells have variable length; +the length of these cells is encoded in their header. + +A variable-length cell has this format: + +| Field | Size in bytes | Notes | +|-----------|-----------------|-------| +| `CircID` | `CIRCID_LEN(v)` | | +| `Command` | 1 | | +| `Length` | 2 | A big-endian integer | +| `Body` | `Length` | | + +[`CIRCID_LEN(v)`]: ./preliminaries.md#msg-len +[`CELL_BODY_LEN`]: ./preliminaries.md#msg-len +[`VERSIONS` cells]: ./negotiating-channels.md#VERSIONS-cells + +Fixed-length and variable-length cells are distinguished +based on the value of their Command field: + +- Command 7 (`VERSIONS`) is variable-length. +- Every other command less than 128 denotes a fixed-length cell. +- Every command greater than or equal to 128 denotes + a variable-length cell. + +> Historical note: +> +> On version 1 connections, all cells were fixed-length. +> +> On version 2 connections, +> only the `VERSIONS` command was variable-length, +> and all others were fixed-length. +> +> These link protocols are obsolete, +> and implementations SHOULD NOT support them. + +## Interpreting the fields: CircID {#circid} + +The `CircID` field determines which [circuit](./circuit-management.md), +if any, the cell is associated with. +If the cell is not associated with any circuit, +its `CircID` is set to 0. + +> Note that a CircID is a channel-local identifier. +> +> A single multi-hop circuit +> will have a different CircID +> on every channel that is used to transmit its data. + +## Interpreting the fields: Command {#command} + +The `Command` field of a fixed-length cell +holds one of the following values: + +| Value |C|P| Identifier | Description | +|-------|-|-|---------------------|--------------------------------------- | +| 0 |N| | `PADDING` | [Link Padding][PADDING] | +| 1 |Y| | `CREATE` | [Create circuit][CREATE] (deprecated) | +| 2 |Y| | `CREATED` | [Acknowledge CREATE][CREATED] (deprecated) | +| 3 |Y| | `RELAY` | [End-to-end data][RELAY] | +| 4 |Y| | `DESTROY` | [Destroy circuit][DESTROY] | +| 5 |Y| | `CREATE_FAST` | [Create circuit, no public key][CREATE_FAST] | +| 6 |Y| | `CREATED_FAST` | [Acknowledge CREATE_FAST][CREATED_FAST] | +| 8 |N| | `NETINFO` | [Time and address info][NETINFO] | +| 9 |Y| | `RELAY_EARLY` | [End-to-end data; limited][RELAY_EARLY] | +| 10 |Y| | `CREATE2` | [Create circuit][CREATE2] | +| 11 |Y| | `CREATED2` | [Acknowledge CREATED2][CREATED2] | +| 12 |Y|5| `PADDING_NEGOTIATE` | [Padding negotiation][PADDING_NEGOTIATE] | + + +[PADDING]: ./flow-control.md#link-padding +[CREATE]: ./create-created-cells.md#CREATE +[CREATED]: ./create-created-cells.md#CREATE +[RELAY]: ./routing-relay-cells.md#routing-relay-cells +[DESTROY]: ./tearing-down-circuits.md#tearing-down-circuits +[CREATE_FAST]: ./create-created-cells.md#create_fast +[CREATED_FAST]: ./create-created-cells.md#create_fast +[NETINFO]: ./negotiating-channels.md#NETINFO-cells +[RELAY_EARLY]: ./relay-early.md#handling-relay-early-cells +[CREATE2]: ./create-created-cells.md#CREATE +[CREATED2]: ./create-created-cells.md#CREATE +[PADDING_NEGOTIATE]: ./flow-control.md#link-padding + +The variable-length `Command` values are: + +| Value |C|P| Identifier | Description | +|-------|-|-|------------------|----------------------------------------| +| 7 |N| | `VERSIONS` | [Negotiate link protocol][VERSIONS] | +| 128 |N| | `VPADDING` | [Variable-length padding][VPADDING] | +| 129 |N| | `CERTS` | [Certificates][CERTS] | +| 130 |N| | `AUTH_CHALLENGE` | [Challenge value][AUTH_CHALLENGE] | +| 131 |N| | `AUTHENTICATE` | [Authenticate initiator][AUTHENTICATE] | +| 132 |N|n/a| `AUTHORIZE` | (Reserved) | + +[VERSIONS]: ./negotiating-channels.md#VERSIONS-cells +[VPADDING]: ./flow-control.md#link-padding +[CERTS]: ./negotiating-channels.md#CERTS-cells +[AUTH_CHALLENGE]: ./negotiating-channels.md#AUTH-CHALLENGE-cells +[AUTHENTICATE]: ./negotiating-channels.md#AUTHENTICATE-cells + +In the tables above, +**C**=Y indicates that a command must have a nonzero CircId, and +**C**=N indicates that a command must have a zero CircId. +Where given, **P** is the first link protocol version +to support a command. +Commands with no value given for **P** +are supported at least in link protocols 3 and above. + +No other command values are allowed. +Implementations SHOULD NOT send undefined command values. +Upon receiving an unrecognized command, +an implementation MAY silently drop the cell +and MAY terminate the channel with an error. + +> Extensibility note: +> +> When we add new cell command types, +> we define a new link protocol version +> to indicate support for that command. +> +> Therefore, implementations can now safely assume +> that other correct implementations +> will never send them an unrecognized cell command. +> +> Historically, before the link protocol was not versioned, +> implementations would drop cells with unrecognized commands, +> under the assumption that the command was sent +> by a more up-to-date version of Tor. + +## Interpreting the fields: Cell Body {#body} + +<!-- deprecated target --><a id="payload"></a> + +The interpretation of a cell's Body depends on the cell's command. +see the links in the command descriptions above +for more information on each command. + +## Padding fixed-length cell bodies {#body-padding} + +<!-- deprecated target --><a id="payload-padding"></a> + +Often, the amount of information to be sent +in a fixed-length cell +is less than [`CELL_BODY_LEN`] bytes. +When this happens, +the sender MUST fill the unused part of the cell's body +with zero-valued bytes. + +Recipients MUST ignore padding bytes. + +> [RELAY] and [RELAY_EARLY] cells' bodies +> contain encrypted data, +> and are always full +> from the point of the view of the channel layer. +> +> The _plaintext_ of these cells' contents may be padded; +> this uses a [different mechanism](./relay-cells.md#relay-cell-padding) +> and does not interact with cell body padding. + +Variable-length cells never have extra space, +so there is no need to pad their bodies. +Unless otherwise specified, +variable-length cells have no padding. + diff --git a/spec/tor-spec/channels.md b/spec/tor-spec/channels.md new file mode 100644 index 0000000..652b931 --- /dev/null +++ b/spec/tor-spec/channels.md @@ -0,0 +1,91 @@ +<a id="tor-spec.txt-2"></a> + +# Channels {#channels} + +A channel is a direct encrypted connection +between two Tor relays, +or between a client and a relay. + +Channels are implemented as +[TLS](https://www.rfc-editor.org/rfc/rfc8446) sessions over TCP. + +Clients and relays may both open new channels; +only a relay may be the recipient of a channel. + +> Historical note: +> in some older documentation, +> channels were sometimes called "connections". +> This proved to be confusing, +> and we are trying not to use the term. + +As part of establishing a channel, +the responding relay will always prove cryptographic ownership +of one or more [**relay identities**](./relay-keys.md), +using a [handshake](./negotiating-channels.md) +that combines TLS facilities +and a series of Tor cells. + +<span id="does-initiator-authenticate"> +As part of this handshake, +the initiator MAY also prove cryptographic ownership +of its own relay identities, +if it has any: +public relays SHOULD prove their identities when they initiate a channel, +whereas clients and bridges SHOULD NOT do so. +</span> + +Parties should usually reuse an existing channel +rather than opening new a channel to the same relay. +There are exceptions here; +we discuss them more below. <!-- TODO: add anchor link --> + +To open a channel, +a client or relay must know the IP address and port +of the target relay. +(This is sometimes called +the "OR address" or "OR port" for the relay.) +In most cases, the participant will also know +one or more expected identities for the target relay, +and will reject the channel +if the target relay cannot cryptographically prove +ownership of those identities. + +> (When initiating a connection, if a reasonably live consensus is +> available, then the expected identity key is taken from that +> consensus. But when initiating a connection otherwise, the expected +> identity key is the one given in the hard-coded authority or +> fallback list. Finally, when creating a connection because of an +> EXTEND/EXTEND2 message, the expected identity key is the one given in +> the message.) + +<!-- TODO: Integrate that paragraph better, or put it in a better place. --> + +Opening a channel is multi-step process: + +1. The initiator opens + a new TLS session with certain properties, + and the responding relay checks and enforces those properties. +2. Both parties + exchange cells over this TLS session + in order to establish their identity or identities. +3. Both parties verify that the identities that they received + are the ones that they expected. + (If any expected key is missing or not as expected, + the party MUST close the connection.) + +Once this is done, the channel is Open, +and regular cells can be exchanged. + +## Channel lifetime + +Channels are not permanent. +Either side MAY close a channel if there are no circuits running on it +and an amount of time (KeepalivePeriod, defaults to 5 minutes) +has passed since the last time any traffic was transmitted over it. +Clients SHOULD +also hold a TLS connection with no circuits open, if it is likely that a +circuit will be built soon using that connection. + +<!-- TODO: Give a forward-reference to explain predicted circuits + and how we decide that a channel is "likely" to be used. --> + diff --git a/spec/tor-spec/circuit-management.md b/spec/tor-spec/circuit-management.md new file mode 100644 index 0000000..d7691a3 --- /dev/null +++ b/spec/tor-spec/circuit-management.md @@ -0,0 +1,6 @@ +<a id="tor-spec.txt-5"></a> + +# Circuit management{#circuit-management} + +This section describes how circuits are created, and how they operate +once they are constructed. diff --git a/spec/tor-spec/closing-streams.md b/spec/tor-spec/closing-streams.md new file mode 100644 index 0000000..1d65b6d --- /dev/null +++ b/spec/tor-spec/closing-streams.md @@ -0,0 +1,100 @@ +<a id="tor-spec.txt-6.3"></a> + +# Closing streams{#closing-streams} + +When an anonymized TCP connection is closed, or an edge node +encounters error on any stream, it sends a 'RELAY_END' message along the +circuit (if possible) and closes the TCP connection immediately. If +an edge node receives a 'RELAY_END' message for any stream, it closes +the TCP connection completely, and sends nothing more along the +circuit for that stream. + +The body of a RELAY_END message begins with a single 'reason' byte to +describe why the stream is closing. For some reasons, it contains +additional data (depending on the reason.) The values are: + +```text + 1 -- REASON_MISC (catch-all for unlisted reasons) + 2 -- REASON_RESOLVEFAILED (couldn't look up hostname) + 3 -- REASON_CONNECTREFUSED (remote host refused connection) [*] + 4 -- REASON_EXITPOLICY (OR refuses to connect to host or port) + 5 -- REASON_DESTROY (Circuit is being destroyed) + 6 -- REASON_DONE (Anonymized TCP connection was closed) + 7 -- REASON_TIMEOUT (Connection timed out, or OR timed out + while connecting) + 8 -- REASON_NOROUTE (Routing error while attempting to + contact destination) + 9 -- REASON_HIBERNATING (OR is temporarily hibernating) + 10 -- REASON_INTERNAL (Internal error at the OR) + 11 -- REASON_RESOURCELIMIT (OR has no resources to fulfill request) + 12 -- REASON_CONNRESET (Connection was unexpectedly reset) + 13 -- REASON_TORPROTOCOL (Sent when closing connection because of + Tor protocol violations.) + 14 -- REASON_NOTDIRECTORY (Client sent RELAY_BEGIN_DIR to a + non-directory relay.) + + [*] Older versions of Tor also send this reason when connections are + reset. +``` + +OPs and ORs MUST accept reasons not on the above list, since future +versions of Tor may provide more fine-grained reasons. + +For most reasons, the format of RELAY_END is: + +Reason \[1 byte\] + +For REASON_EXITPOLICY, the format of RELAY_END is: + +```text + Reason [1 byte] + IPv4 or IPv6 address [4 bytes or 16 bytes] + TTL [4 bytes] +``` + +(If the TTL is absent, it should be treated as if it were 0xffffffff. +If the address is absent or is the wrong length, the RELAY_END message +should be processed anyway.) + +Tors SHOULD NOT send any reason except REASON_MISC for a stream that they +have originated. + +Implementations SHOULD accept empty RELAY_END messages, and treat them +as if they specified REASON_MISC. + +Upon receiving a RELAY_END message, the recipient may be sure that no further +messages will arrive on that stream, and can treat such messages as a protocol +violation. + +After sending a RELAY_END message, the sender needs to give the recipient +time to receive that message. In the meantime, the sender SHOULD remember +how many messages of which types (CONNECTED, SENDME, DATA) it would have +accepted on that stream, and SHOULD kill the circuit if it receives more +than permitted. + +--- \[The rest of this section describes unimplemented functionality.\] + +Because TCP connections can be half-open, we follow an equivalent +to TCP's FIN/FIN-ACK/ACK protocol to close streams. + +An exit (or onion service) connection can have a TCP stream in one of +three states: 'OPEN', 'DONE_PACKAGING', and 'DONE_DELIVERING'. For the +purposes of modeling transitions, we treat 'CLOSED' as a fourth state, +although connections in this state are not, in fact, tracked by the +onion router. + +A stream begins in the 'OPEN' state. Upon receiving a 'FIN' from +the corresponding TCP connection, the edge node sends a 'RELAY_FIN' +message along the circuit and changes its state to 'DONE_PACKAGING'. +Upon receiving a 'RELAY_FIN' message, an edge node sends a 'FIN' to +the corresponding TCP connection (e.g., by calling +shutdown(SHUT_WR)) and changing its state to 'DONE_DELIVERING'. + +When a stream in already in 'DONE_DELIVERING' receives a 'FIN', it +also sends a 'RELAY_FIN' along the circuit, and changes its state +to 'CLOSED'. When a stream already in 'DONE_PACKAGING' receives a +'RELAY_FIN' message, it sends a 'FIN' and changes its state to +'CLOSED'. + +If an edge node encounters an error on any stream, it sends a +'RELAY_END' message (if possible) and closes the stream immediately. diff --git a/spec/tor-spec/create-created-cells.md b/spec/tor-spec/create-created-cells.md new file mode 100644 index 0000000..3208909 --- /dev/null +++ b/spec/tor-spec/create-created-cells.md @@ -0,0 +1,620 @@ +<a id="tor-spec.txt-5.1"></a> + +# CREATE and CREATED cells{#CREATE} + +Users set up circuits incrementally, one hop at a time. To create a +new circuit, OPs send a CREATE/CREATE2 cell to the first node, with +the first half of an authenticated handshake; that node responds with +a CREATED/CREATED2 cell with the second half of the handshake. To +extend a circuit past the first hop, the OP sends an EXTEND/EXTEND2 +relay message (see [EXTEND and EXTENDED messages](#EXTEND) which instructs the last +node in the circuit to send a CREATE/CREATE2 cell to extend the circuit. + +There are two kinds of CREATE and CREATED cells: The older +"CREATE/CREATED" format, and the newer "CREATE2/CREATED2" format. The +newer format is extensible by design; the older one is not. + +A CREATE2 cell contains: + +| Field | Description | Size | +| ----- | ----------- | ---- | +| `HTYPE` | Client Handshake Type | 2 bytes | +| `HLEN` | Client Handshake Data Len | 2 bytes | +| `HDATA` | Client Handshake Data | `HLEN` bytes | + +A CREATED2 cell contains: + +| Field | Description | Size | +| ----- | ----------- | ---- | +| `HLEN` | Server Handshake Data Len | 2 bytes | +| `HDATA` | Server Handshake Data | `HLEN` bytes | + + +Recognized HTYPEs (handshake types) are: + +| Value | Description | +| ----- | ----------- | +| 0x0000 | TAP -- the original Tor handshake; see [The "TAP" handshake](#TAP) | +| 0x0001 | reserved | +| 0x0002 | ntor -- the ntor+curve25519+sha256 handshake; see [The "ntor" handshake](#ntor) | +| 0x0003 | ntor-v3 -- ntor extended with extra data; see [The "ntor-v3" handshake](#ntor-v3) | + +The format of a CREATE cell is one of the following: + +| Field | Description | Size | +| ----- | ----------- | ---- | +| `HDATA` | Client Handshake Data | `TAP_C_HANDSHAKE_LEN` bytes | + +or + +| Field | Description | Size | +| ----- | ----------- | ---- | +| `HTAG` | Client Handshake Type Tag | 16 bytes | +| `HDATA` | Client Handshake Data | `TAP_C_HANDSHAKE_LEN`-16 bytes | + +The first format is equivalent to a CREATE2 cell with HTYPE of 'tap' +and length of `TAP_C_HANDSHAKE_LEN`. The second format is a way to +encapsulate new handshake types into the old CREATE cell format for +migration. See ["EXTEND and EXTENDED messages"](#EXTEND) below. Recognized HTAG values are: + +| Value | Description | +| ----- | ----------- | +| 'ntorNTORntorNTOR' | ntor | + +The format of a CREATED cell is: + +| Field | Description | Size | +| ----- | ----------- | ---- | +| `HDATA` | Server Handshake Data | `TAP_S_HANDSHAKE_LEN` bytes | + +(It's equivalent to a CREATED2 cell with length of `TAP_S_HANDSHAKE_LEN`.) + +As usual with DH, `x` and `y` MUST be generated randomly. + +In general, clients SHOULD use CREATE whenever they are using the TAP +handshake, and CREATE2 otherwise. Clients SHOULD NOT send the +second format of CREATE cells (the one with the handshake type tag) +to a server directly. + +Servers always reply to a successful CREATE with a CREATED, and to a +successful CREATE2 with a CREATED2. On failure, a server sends a +DESTROY cell to tear down the circuit. + +\[CREATE2 is handled by Tor 0.2.4.7-alpha and later.\] + +<a id="tor-spec.txt-5.1.1"></a> + +## Choosing circuit IDs in create cells {#choosing-circid} + +The CircID for a CREATE/CREATE2 cell is a nonzero integer, selected +by the node (OP or OR) that sends the CREATE/CREATED2 cell. +Depending on the link protocol version, there are certain rules for +choosing the value of CircID which MUST be obeyed, as implementations +MAY decide to refuse in case of a violation. In link protocol 3 or +lower, CircIDs are 2 bytes long; in protocol 4 or higher, CircIDs are +4 bytes long. + +In link protocol version 3 or lower, the nodes choose from only one +half of the possible values based on the ORs' public identity keys, +in order to avoid collisions. If the sending node has a lower key, +it chooses a CircID with an MSB of 0; otherwise, it chooses a CircID +with an MSB of 1. (Public keys are compared numerically by modulus.) +A client with no public key MAY choose any CircID it wishes, since +clients never need to process CREATE/CREATE2 cells. + +In link protocol version 4 or higher, whichever node initiated the +connection MUST set its MSB to 1, and whichever node didn't initiate +the connection MUST set its MSB to 0. + +The CircID value 0 is specifically reserved for cells that do not +belong to any circuit: CircID 0 MUST not be used for circuits. No +other CircID value, including 0x8000 or 0x80000000, is reserved. + +Existing Tor implementations choose their CircID values at random from +among the available unused values. To avoid distinguishability, new +implementations should do the same. Implementations MAY give up and stop +attempting to build new circuits on a channel, if a certain number of +randomly chosen CircID values are all in use (today's Tor stops after 64). + +<a id="tor-spec.txt-5.1.2"></a> + +## EXTEND and EXTENDED messagess {#EXTEND} + +To extend an existing circuit, the client sends an EXTEND or EXTEND2 +message, in a RELAY_EARLY cell, to the last node in the circuit. + +The body of an EXTEND2 message contains: + +| Field | Description | Size | +| ----- | ----------- | ---- | +| `NSPEC` | Number of link specifiers | 1 byte +| `NSPEC` times: | +| - `LSTYPE` | Link specifier type | 1 byte +| - `LSLEN` | Link specifier length | 1 byte +| - `LSPEC` | Link specifier | LSLEN bytes +| `HTYPE` | Client Handshake Type | 2 bytes +| `HLEN` | Client Handshake Data Len | 2 bytes +| `HDATA` | Client Handshake Data | HLEN bytes + +Link specifiers describe the next node in the circuit and how to +connect to it. Recognized specifiers are: + +| Value | Description +| ----- | ----------- +| \[00\] | TLS-over-TCP, IPv4 address. A four-byte IPv4 address plus two-byte ORPort. +| \[01\] | TLS-over-TCP, IPv6 address. A sixteen-byte IPv6 address plus two-byte ORPort. +| \[02\] | Legacy identity. A 20-byte SHA1 identity fingerprint. At most one may be listed. +| \[03\] | Ed25519 identity. A 32-byte Ed25519 identity fingerprint. At most one may be listed. + +Nodes MUST ignore unrecognized specifiers, and MUST accept multiple +instances of specifiers other than 'legacy identity' and +'Ed25519 identity'. (Nodes SHOULD reject link specifier lists +that include multiple instances of either one of those specifiers.) + +For purposes of indistinguishability, implementations SHOULD send +these link specifiers, if using them, in this order: \[00\], \[02\], \[03\], +\[01\]. + +The body for an EXTEND relay message consists of: + +| Field | Size +| ----- | ---- +| Address | 4 bytes +| Port | 2 bytes +| Onion skin | `TAP_C_HANDSHAKE_LEN` bytes +| Identity fingerprint | `HASH_LEN` bytes + +The "legacy identity" and "identity fingerprint" fields are the +SHA1 hash of the PKCS#1 ASN1 encoding of the next onion router's +identity (signing) key. (See ["Preliminaries » Ciphers"](./preliminaries.md#ciphers)) +The "Ed25519 identity" +field is the Ed25519 identity key of the target node. Including +this key information allows the extending OR verify that it is +indeed connected to the correct target OR, and prevents certain +man-in-the-middle attacks. + +Extending ORs MUST check _all_ provided identity keys (if they +recognize the format), and and MUST NOT extend the circuit if the +target OR did not prove its ownership of any such identity key. +If only one identity key is provided, but the extending OR knows +the other (from directory information), then the OR SHOULD also +enforce the key in the directory. + +If an extending OR has a channel with a given Ed25519 ID and RSA +identity, and receives a request for that Ed25519 ID and a +different RSA identity, it SHOULD NOT attempt to make another +connection: it should just fail and DESTROY the circuit. + +The client MAY include multiple IPv4 or IPv6 link specifiers in an +EXTEND message; current OR implementations only consider the first +of each type. + +After checking relay identities, extending ORs generate a +CREATE/CREATE2 cell from the contents of the EXTEND/EXTEND2 message. +See [Creating circuits](./creating-circuits.md#creating-circuits) +for details. + +The body of an EXTENDED message is the same as the body of a +CREATED cell. + +The body of an EXTENDED2 message is the same as the body of a +CREATED2 cell. + +\[Support for EXTEND2/EXTENDED2 was added in Tor 0.2.4.8-alpha.\] + +Clients SHOULD use the EXTEND format whenever sending a TAP +handshake, and MUST use it whenever the EXTEND message will be handled +by a node running a version of Tor too old to support EXTEND2. In +other cases, clients SHOULD use EXTEND2. + +When generating an EXTEND2 message, clients SHOULD include the target's +Ed25519 identity whenever the target has one, and whenever the +target supports LinkAuth subprotocol version "3". (See [LinkAuth](./subprotocol-versioning.md#link-auth)). + +When encoding a non-TAP handshake in an EXTEND message, clients SHOULD +use the format with 'client handshake type tag'. + +<a id="tor-spec.txt-5.1.3"></a> + +## The "TAP" handshake {#TAP} + +This handshake uses Diffie-Hellman in Z<sub>p</sub> and RSA to compute a set of +shared keys which the client knows are shared only with a particular +server, and the server knows are shared with whomever sent the +original handshake (or with nobody at all). It's not very fast and +not very good. (See Goldberg's "On the Security of the Tor +Authentication Protocol".) + +Define `TAP_C_HANDSHAKE_LEN` as `DH_LEN+KEY_LEN+KP_PAD_LEN`. +Define `TAP_S_HANDSHAKE_LEN` as `DH_LEN+HASH_LEN`. + +The body for a CREATE cell is an 'onion skin', which consists of +the first step of the DH handshake data (also known as `g^x`). This +value is encrypted using the "legacy hybrid encryption" algorithm +(see ["Preliminaries » A bad hybrid encryption algorithm..."](./preliminaries.md#legacy-hybrid-encryption)) +to the server's onion key, giving a client handshake: + +| Field | Size +| ----- | ---- +| KP-encrypted: +| - Padding | `KP_PAD_LEN` bytes +| - Symmetric key | `KEY_LEN` bytes +| - First part of `g^x` | `KP_ENC_LEN-KP_PAD_LEN-KEY_LEN` bytes +| Symmetrically encrypted +| - Second part of `g^x` | `DH_LEN-(KP_ENC_LEN-KP_PAD_LEN-KEY_LEN)` bytes + +The body for a CREATED cell, or the body for an +EXTENDED relay message, contains: + +| Field | Size +| ----- | ---- +| DH data (`g^y`) | `DH_LEN` bytes +| Derivative key data (`KH`) | `HASH_LEN` bytes (see ["Setting Circuit Keys"](./setting-circuit-keys.md)) + + +Once the handshake between the OP and an OR is completed, both can +now calculate `g^xy` with ordinary DH. Before computing `g^xy`, both parties +MUST verify that the received `g^x` or `g^y` value is not degenerate; +that is, it must be strictly greater than `1` and strictly less than `p-1` +where `p` is the DH modulus. Implementations MUST NOT complete a handshake +with degenerate keys. Implementations MUST NOT discard other "weak" +`g^x` values. + +(Discarding degenerate keys is critical for security; if bad keys +are not discarded, an attacker can substitute the OR's CREATED +cell's `g^y` with `0` or `1`, thus creating a known `g^xy` and impersonating +the OR. Discarding other keys may allow attacks to learn bits of +the private key.) + +Once both parties have `g^xy`, they derive their shared circuit keys +and 'derivative key data' value via the +[KDF-TOR function](./setting-circuit-keys.md#kdf-tor). + +<a id="tor-spec.txt-5.1.4"></a> + +## The "ntor" handshake {#ntor} + +This handshake uses a set of DH handshakes to compute a set of +shared keys which the client knows are shared only with a particular +server, and the server knows are shared with whomever sent the +original handshake (or with nobody at all). Here we use the +"curve25519" group and representation as specified in "Curve25519: +new Diffie-Hellman speed records" by D. J. Bernstein. + +\[The ntor handshake was added in Tor 0.2.4.8-alpha.\] + +In this section, define: + +```text +H(x,t) as HMAC_SHA256 with message x and key t. +H_LENGTH = 32. +ID_LENGTH = 20. +G_LENGTH = 32 +PROTOID = "ntor-curve25519-sha256-1" +t_mac = PROTOID | ":mac" +t_key = PROTOID | ":key_extract" +t_verify = PROTOID | ":verify" +G = The preferred base point for curve25519 ([9]) +KEYGEN() = The curve25519 key generation algorithm, returning + a private/public keypair. +m_expand = PROTOID | ":key_expand" +KEYID(A) = A +EXP(a, b) = The ECDH algorithm for establishing a shared secret. +``` + +To perform the handshake, the client needs to know an identity key +digest for the server, and an ntor onion key (a curve25519 public +key) for that server. Call the ntor onion key `B`. The client +generates a temporary keypair: + +```text +x,X = KEYGEN() +``` + +and generates a client-side handshake with contents: + +| Field | Value | Size +| ----- | ----- | ---- +| `NODEID` | Server identity digest | `ID_LENGTH` bytes +| `KEYID` | KEYID(B) | `H_LENGTH` bytes +| `CLIENT_KP` | X | `G_LENGTH` bytes + +The server generates a keypair of `y,Y = KEYGEN()`, and uses its ntor +private key `b` to compute: + +```text +secret_input = EXP(X,y) | EXP(X,b) | ID | B | X | Y | PROTOID +KEY_SEED = H(secret_input, t_key) +verify = H(secret_input, t_verify) +auth_input = verify | ID | B | Y | X | PROTOID | "Server" +``` + +The server's handshake reply is: + +| Field | Value | Size +| ----- | ----- | ---- +| `SERVER_KP` | `Y` | `G_LENGTH` bytes +| `AUTH` | `H(auth_input, t_mac)` | `H_LENGTH` bytes + +The client then checks `Y` is in G<sup>*</sup> \[see NOTE below\], and computes + +```text +secret_input = EXP(Y,x) | EXP(B,x) | ID | B | X | Y | PROTOID +KEY_SEED = H(secret_input, t_key) +verify = H(secret_input, t_verify) +auth_input = verify | ID | B | Y | X | PROTOID | "Server" +``` + +The client verifies that `AUTH == H(auth_input, t_mac)`. + +Both parties check that none of the `EXP()` operations produced the +point at infinity. \[NOTE: This is an adequate replacement for +checking `Y` for group membership, if the group is curve25519.\] + +Both parties now have a shared value for `KEY_SEED`. They expand this +into the keys needed for the Tor relay protocol, using the KDF +described in ["KDF-RFC5869"](./setting-circuit-keys.md#kdf-rfc5869) +and the tag `m_expand`. + +<a id="tor-spec.txt-5.1.4.1"></a> + +### The "ntor-v3" handshake {#ntor-v3} + +This handshake extends the ntor handshake to include support +for extra data transmitted as part of the handshake. Both +the client and the server can transmit extra data; in both cases, +the extra data is encrypted, but only server data receives +forward secrecy. + +To advertise support for this handshake, servers advertise the +"Relay=4" subprotocol version. To select it, clients use the +'ntor-v3' HTYPE value in their CREATE2 cells. + +In this handshake, we define: + +```text +PROTOID = "ntor3-curve25519-sha3_256-1" +t_msgkdf = PROTOID | ":kdf_phase1" +t_msgmac = PROTOID | ":msg_mac" +t_key_seed = PROTOID | ":key_seed" +t_verify = PROTOID | ":verify" +t_final = PROTOID | ":kdf_final" +t_auth = PROTOID | ":auth_final" + +`ENCAP(s)` -- an encapsulation function. We define this +as `htonll(len(s)) | s`. (Note that `len(ENCAP(s)) = len(s) + 8`). + +`PARTITION(s, n1, n2, n3, ...)` -- a function that partitions a +bytestring `s` into chunks of length `n1`, `n2`, `n3`, and so +on. Extra data is put into a final chunk. If `s` is not long +enough, the function fails. + +H(s, t) = SHA3_256(ENCAP(t) | s) +MAC(k, msg, t) = SHA3_256(ENCAP(t) | ENCAP(k) | s) +KDF(s, t) = SHAKE_256(ENCAP(t) | s) +ENC(k, m) = AES_256_CTR(k, m) + +EXP(pk,sk), KEYGEN: defined as in curve25519 + +DIGEST_LEN = MAC_LEN = MAC_KEY_LEN = ENC_KEY_LEN = PUB_KEY_LEN = 32 + +ID_LEN = 32 (representing an ed25519 identity key) + +For any tag "t_foo": + H_foo(s) = H(s, t_foo) + MAC_foo(k, msg) = MAC(k, msg, t_foo) + KDF_foo(s) = KDF(s, t_foo) +``` + +Other notation is as in the [ntor description above](#ntor). + +The client begins by knowing: + +```text +B, ID -- The curve25519 onion key and Ed25519 ID of the server that it + wants to use. +CM -- A message it wants to send as part of its handshake. +VER -- An optional shared verification string: +``` + +The client computes: + +```text +x,X = KEYGEN() +Bx = EXP(B,x) +secret_input_phase1 = Bx | ID | X | B | PROTOID | ENCAP(VER) +phase1_keys = KDF_msgkdf(secret_input_phase1) +(ENC_K1, MAC_K1) = PARTITION(phase1_keys, ENC_KEY_LEN, MAC_KEY_LEN) +encrypted_msg = ENC(ENC_K1, CM) +msg_mac = MAC_msgmac(MAC_K1, ID | B | X | encrypted_msg) +``` + + The client then sends, as its CREATE handshake: + +| Field | Value | Size +| ----- | ----- | ---- +| `NODEID` | `ID` | `ID_LEN` bytes +| `KEYID` | `B` | `PUB_KEY_LEN` bytes +| `CLIENT_PK` | `X` | `PUB_KEY_LEN` bytes +| `MSG` | `encrypted_msg` | `len(CM)` bytes +| `MAC` | `msg_mac` | `MAC_LEN` bytes + +The client remembers `x`, `X`, `B`, `ID`, `Bx`, and `msg_mac`. + +When the server receives this handshake, it checks whether `NODEID` is as +expected, and looks up the `(b,B)` keypair corresponding to `KEYID`. If the +keypair is missing or the `NODEID` is wrong, the handshake fails. + +Now the relay uses `X=CLIENT_PK` to compute: + +```text +Xb = EXP(X,b) +secret_input_phase1 = Xb | ID | X | B | PROTOID | ENCAP(VER) +phase1_keys = KDF_msgkdf(secret_input_phase1) +(ENC_K1, MAC_K1) = PARTITION(phase1_keys, ENC_KEY_LEN, MAC_KEY_LEN) + +expected_mac = MAC_msgmac(MAC_K1, ID | B | X | MSG) +``` + +If `expected_mac` is not `MAC`, the handshake fails. Otherwise +the relay computes `CM` as: + +```text +CM = DEC(MSG, ENC_K1) +``` + +The relay then checks whether `CM` is well-formed, and in response +composes `SM`, the reply that it wants to send as part of the +handshake. It then generates a new ephemeral keypair: + +```text +y,Y = KEYGEN() +``` + +and computes the rest of the handshake: + +```text +Xy = EXP(X,y) +secret_input = Xy | Xb | ID | B | X | Y | PROTOID | ENCAP(VER) +ntor_key_seed = H_key_seed(secret_input) +verify = H_verify(secret_input) + +RAW_KEYSTREAM = KDF_final(ntor_key_seed) +(ENC_KEY, KEYSTREAM) = PARTITION(RAW_KEYSTREAM, ENC_KEY_LKEN, ...) + +encrypted_msg = ENC(ENC_KEY, SM) + +auth_input = verify | ID | B | Y | X | MAC | ENCAP(encrypted_msg) | + PROTOID | "Server" +AUTH = H_auth(auth_input) +``` + +The relay then sends as its CREATED handshake: + +| Field | Value | Size +| ----- | ----- | ---- +| `Y` | `Y` | `PUB_KEY_LEN` bytes +| `AUTH` | `AUTH` | `DIGEST_LEN` bytes +| `MSG` | `encrypted_msg` | `len(SM)` bytes, up to end of the message + +Upon receiving this handshake, the client computes: + +```text +Yx = EXP(Y, x) +secret_input = Yx | Bx | ID | B | X | Y | PROTOID | ENCAP(VER) +ntor_key_seed = H_key_seed(secret_input) +verify = H_verify(secret_input) + +auth_input = verify | ID | B | Y | X | MAC | ENCAP(MSG) | + PROTOID | "Server" +AUTH_expected = H_auth(auth_input) +``` + +If `AUTH_expected` is equal to `AUTH`, then the handshake has +succeeded. The client can then calculate: + +```text +RAW_KEYSTREAM = KDF_final(ntor_key_seed) +(ENC_KEY, KEYSTREAM) = PARTITION(RAW_KEYSTREAM, ENC_KEY_LKEN, ...) + +SM = DEC(ENC_KEY, MSG) +``` + +SM is the message from the relay, and the client uses KEYSTREAM to +generate the shared secrets for the newly created circuit. + +Now both parties share the same KEYSTREAM, and can use it to generate +their circuit keys. + +<a id="tor-spec.txt-5.1.5"></a> + +## CREATE_FAST/CREATED_FAST cells {#create_fast} + +When creating a one-hop circuit, the OP has already +established the OR's identity and negotiated a secret key using TLS. +Because of this, it is not necessary for the OP to perform the +public key operations to create a circuit. +In this case, the OP MAY send a CREATE_FAST cell instead of a CREATE cell. +The OR responds with a CREATED_FAST cell, and the circuit is +created. + +A CREATE_FAST cell contains: + +| Field | Size +| ----- | ---- +| Key material (`X`) | `HASH_LEN` bytes + +A CREATED_FAST cell contains: + +| Field | Size +| ----- | ---- +| Key material (`Y`) | `HASH_LEN` bytes +| Derivative key data | `HASH_LEN` bytes (See [KDF-TOR](./setting-circuit-keys.md#kdf-tor)) + +The values of `X` and `Y` must be generated randomly. + +Once both parties have `X` and `Y`, they derive their shared circuit keys +and 'derivative key data' value via the [KDF-TOR function](./setting-circuit-keys.md#kdf-tor). + +Parties SHOULD NOT use CREATE_FAST except for creating one-hop circuits. + +<a id="tor-spec.txt-5.1.6"></a> + +## Additional data in CREATE/CREATED cells {#additional-data} + +Some handshakes (currently ntor-v3 defined above) allow the client or the +relay to send additional data as part of the handshake. When used in a +CREATE/CREATED handshake, this additional data must have the following +format: + +| Field | Size +| ----- | ---- +| `N_EXTENSIONS` | one byte +| `N_EXTENSIONS` times: | +| - `EXT_FIELD_TYPE` | one byte +| - `EXT_FIELD_LEN` | one byte +| - `EXT_FIELD` | `EXT_FIELD_LEN` bytes + +(`EXT_FIELD_LEN` may be zero, in which case `EXT_FIELD` is absent.) + +All parties MUST reject messages that are not well-formed per the +rules above. + +We do not specify specific TYPE semantics here; we leave those for +other proposals and specifications. + +Parties MUST ignore extensions with `EXT_FIELD_TYPE` bodies they do not +recognize. + +Unless otherwise specified in the documentation for an extension type: + * Each extension type SHOULD be sent only once in a message. + * Parties MUST ignore any occurrences all occurrences of an extension + with a given type after the first such occurrence. + * Extensions SHOULD be sent in numerically ascending order by type. + +(The above extension sorting and multiplicity rules are only defaults; +they may be overridden in the description of individual extensions.) + +Currently supported extensions are: + + * 1 -- `CC_FIELD_REQUEST` \[Client to server\] + + Contains an empty body. Signifies that the client + wants to use the extended congestion control described + in [proposal 324]. + + * 2 -- `CC_FIELD_RESPONSE` \[Server to client\] + + Indicates that the relay will use the congestion control + of [proposal 324], as requested by the client. One byte + in length: + + `sendme_inc [1 byte]` + + * 3 -- Subprotocol Request \[Client to Server\] + + (RESERVED) Tells the endpoint what protocol version to use on the + circuit ([proposal 346]). + +[proposal 324]: ../proposals/324-rtt-congestion-control.txt +[proposal 346]: ../proposals/346-protovers-again.md diff --git a/spec/tor-spec/creating-circuits.md b/spec/tor-spec/creating-circuits.md new file mode 100644 index 0000000..deb6b83 --- /dev/null +++ b/spec/tor-spec/creating-circuits.md @@ -0,0 +1,102 @@ +<a id="tor-spec.txt-5.3"></a> + +# Creating circuits{#creating-circuits} + +When creating a circuit through the network, the circuit creator +(OP) performs the following steps: + +1. Choose an onion router as an end node (R_N): + * N MAY be 1 for non-anonymous directory mirror, introduction point, + or service rendezvous connections. + * N SHOULD be 3 or more for anonymous connections. + Some end nodes accept streams (see ["Opening streams"](./opening-streams.md)), + others are introduction or rendezvous points (see the [Rendezvous Spec](../rend-spec/index.md)). + +2. Choose a chain of (N-1) onion routers (R_1...R_N-1) to constitute + the path, such that no router appears in the path twice. + +3. If not already connected to the first router in the chain, + open a new connection to that router. + +4. Choose a circID not already in use on the connection with the + first router in the chain; send a CREATE/CREATE2 cell along + the connection, to be received by the first onion router. + +5. Wait until a CREATED/CREATED2 cell is received; finish the + handshake and extract the forward key Kf_1 and the backward + key Kb_1. + +6. For each subsequent onion router R (R_2 through R_N), extend + the circuit to R. + +To extend the circuit by a single onion router R_M, the OP performs +these steps: + +1. Create an onion skin, encrypted to R_M's public onion key. + +2. Send the onion skin in a relay EXTEND/EXTEND2 message along + the circuit (see + ["EXTEND and EXTENDED messages"](./create-created-cells.md#EXTEND) + and ["Routing relay cells"](./routing-relay-cells.md#routing-relay-cells)). + +3. When a relay EXTENDED/EXTENDED2 message is received, verify KH, + and calculate the shared keys. The circuit is now extended. + +When an onion router receives an EXTEND relay message, it sends a CREATE +cell to the next onion router, with the enclosed onion skin as its +body. + +When an onion router receives an EXTEND2 relay message, it sends a CREATE2 +cell to the next onion router, with the enclosed HLEN, HTYPE, and HDATA +as its body. The initiating onion router chooses some circID not yet +used on the connection between the two onion routers. (But see section +["Choosing circuit IDs in create cells"](./create-created-cells.md#choosing-circid)) + +As special cases, if the EXTEND/EXTEND2 message includes a legacy identity, or +identity fingerprint of all zeroes, or asks to extend back to the relay +that sent the extend cell, the circuit will fail and be torn down. + +Ed25519 identity keys are not required in EXTEND2 messages, so all zero +keys SHOULD be accepted. If the extending relay knows the ed25519 key from +the consensus, it SHOULD also check that key. (See +[EXTEND and EXTENDED message](./create-created-cells.md#EXTEND)) + +If an EXTEND2 message contains the ed25519 key of the relay that sent the +EXTEND2 message, the circuit will fail and be torn down. + +When an onion router receives a CREATE/CREATE2 cell, if it already has a +circuit on the given connection with the given circID, it drops the +cell. Otherwise, after receiving the CREATE/CREATE2 cell, it completes +the specified handshake, and replies with a CREATED/CREATED2 cell. + +Upon receiving a CREATED/CREATED2 cell, an onion router packs its body +into an [EXTENDED/EXTENDED2](./create-created-cells.md#EXTEND) relay message, and sends +that message up the circuit. Upon receiving the EXTENDED/EXTENDED2 relay +message, the OP can retrieve the handshake material. + +(As an optimization, OR implementations may delay processing onions +until a break in traffic allows time to do so without harming +network latency too greatly.) + +<a id="tor-spec.txt-5.3.1"></a> + +## Canonical connections{#canonical-connections} + +It is possible for an attacker to launch a man-in-the-middle attack +against a connection by telling OR Alice to extend to OR Bob at some +address X controlled by the attacker. The attacker cannot read the +encrypted traffic, but the attacker is now in a position to count all +bytes sent between Alice and Bob (assuming Alice was not already +connected to Bob.) + +To prevent this, when an OR gets an extend request, it SHOULD use an +existing OR connection if the ID matches, and ANY of the following +conditions hold: + + - The IP matches the requested IP. + - The OR knows that the IP of the connection it's using is canonical + because it was listed in the NETINFO cell. + +ORs SHOULD NOT check the IPs that are listed in the server descriptor. +Trusting server IPs makes it easier to covertly impersonate a relay, after +stealing its keys. diff --git a/spec/tor-spec/flow-control.md b/spec/tor-spec/flow-control.md new file mode 100644 index 0000000..9ecc5da --- /dev/null +++ b/spec/tor-spec/flow-control.md @@ -0,0 +1,199 @@ +<a id="tor-spec.txt-7"></a> + +# Flow control{#flow-control} + +<a id="tor-spec.txt-7.1"></a> + +## Link throttling + +Each client or relay should do appropriate bandwidth throttling to +keep its user happy. + +Communicants rely on TCP's default flow control to push back when they +stop reading. + +The mainline Tor implementation uses token buckets (one for reads, +one for writes) for the rate limiting. + +Since 0.2.0.x, Tor has let the user specify an additional pair of +token buckets for "relayed" traffic, so people can deploy a Tor relay +with strict rate limiting, but also use the same Tor as a client. To +avoid partitioning concerns we combine both classes of traffic over a +given OR connection, and keep track of the last time we read or wrote +a high-priority (non-relayed) cell. If it's been less than N seconds +(currently N=30), we give the whole connection high priority, else we +give the whole connection low priority. We also give low priority +to reads and writes for connections that are serving directory +information. See [proposal 111] for details. + +[proposal 111]: ../proposals/111-local-traffic-priority.txt + +<a id="tor-spec.txt-7.2"></a> + +## Link padding{#link-padding} + +Link padding can be created by sending PADDING or VPADDING cells +along the connection; relay messages of type "DROP" can be used for +long-range padding. The bodies of PADDING cells, VPADDING cells, or DROP +message are filled with padding bytes. +See [Cell Packet format](./cell-packet-format.md#cell-packet-format). + +If the link protocol is version 5 or higher, link level padding is +enabled as per padding-spec.txt. On these connections, clients may +negotiate the use of padding with a PADDING_NEGOTIATE command +whose format is as follows: + +```text + Version [1 byte] + Command [1 byte] + ito_low_ms [2 bytes] + ito_high_ms [2 bytes] +``` + +Currently, only version 0 of this cell is defined. In it, the command +field is either 1 (stop padding) or 2 (start padding). For the start +padding command, a pair of timeout values specifying a low and a high +range bounds for randomized padding timeouts may be specified as unsigned +integer values in milliseconds. The ito_low_ms field should not be lower +than the current consensus parameter value for nf_ito_low (default: +1500). The ito_high_ms field should not be lower than ito_low_ms. +(If any party receives an out-of-range value, they clamp it so +that it is in-range.) + +For the stop padding command, the timeout fields should be sent as +zero (to avoid client distinguishability) and ignored by the recipient. + +For more details on padding behavior, see padding-spec.txt. + +<a id="tor-spec.txt-7.3"></a> + +## Circuit-level flow control + +To control a circuit's bandwidth usage, each OR keeps track of two +'windows', consisting of how many DATA-bearing relay cells it is allowed to +originate or willing to consume. + +(For the purposes of flow control, +we call a relay cell "DATA-bearing" +if it holds a DATA relay message. +Note that this design does _not_ limit relay cells that don't contain +a DATA message; +this limitation may be addressed in the future.) + +These two windows are respectively named: the package window (packaged for +transmission) and the deliver window (delivered for local streams). + +Because of our leaky-pipe topology, every relay on the circuit has a pair +of windows, and the OP has a pair of windows for every relay on the +circuit. +These windows apply only to _originated_ and _consumed_ cells. +They do not, however, apply to _relayed_ cells, +and a relay +that is never used for streams will never decrement its windows or cause the +client to decrement a window. + +Each 'window' value is initially set based on the consensus parameter +'circwindow' in the directory (see dir-spec.txt), or to 1000 +DATA-bearing relay cells if +no 'circwindow' value is given. In each direction, cells that are not +RELAY_DATA cells do not affect the window. + +An OR or OP (depending on the stream direction) sends a RELAY_SENDME message +to indicate that it is willing to receive more DATA-bearing cells when its deliver +window goes down below a full increment (100). For example, if the window +started at 1000, it should send a RELAY_SENDME when it reaches 900. + +When an OR or OP receives a RELAY_SENDME, it increments its package window +by a value of 100 (circuit window increment) and proceeds to sending the +remaining DATA-bearing cells. + +If a package window reaches 0, the OR or OP stops reading from TCP +connections for all streams on the corresponding circuit, and sends no more +DATA-bearing cells until receiving a RELAY_SENDME message. + +If a deliver window goes below 0, the circuit should be torn down. + +Starting with tor-0.4.1.1-alpha, authenticated SENDMEs are supported +(version 1, see below). This means that both the OR and OP need to remember +the rolling digest of the relay cell that precedes (triggers) a RELAY_SENDME. +This can be known if the package window gets to a multiple of the circuit +window increment (100). + +When the RELAY_SENDME version 1 arrives, it will contain a digest that MUST +match the one remembered. This represents a proof that the end point of the +circuit saw the sent relay cells. On failure to match, the circuit should be torn +down. + +To ensure unpredictability, random bytes should be added to at least one +RELAY_DATA cell within one increment window. In other word, +at every 100 data-bearing cells (increment), +random bytes should be introduced in at least one cell. + +<a id="tor-spec.txt-7.3.1"></a> + +### SENDME Message Format + +A circuit-level RELAY_SENDME message always has its StreamID=0. + +An OR or OP must obey these two consensus parameters in order to know which +version to emit and accept. + +```text + 'sendme_emit_min_version': Minimum version to emit. + 'sendme_accept_min_version': Minimum version to accept. +``` + +If a RELAY_SENDME version is received that is below the minimum accepted +version, the circuit should be closed. + +The body of a RELAY_SENDME message contains the following: + +```text + VERSION [1 byte] + DATA_LEN [2 bytes] + DATA [DATA_LEN bytes] +``` + +The VERSION tells us what is expected in the DATA section of length +DATA_LEN and how to handle it. The recognized values are: + +0x00: The rest of the message should be ignored. + +0x01: Authenticated SENDME. The DATA section MUST contain: + +DIGEST \[20 bytes\] + +```text + If the DATA_LEN value is less than 20 bytes, the message should be + dropped and the circuit closed. If the value is more than 20 bytes, + then the first 20 bytes should be read to get the DIGEST value. + + The DIGEST is the rolling digest value from the DATA-bearing relay cell that + immediately preceded (triggered) this RELAY_SENDME. This value is + matched on the other side from the previous cell sent that the OR/OP + must remember. + + (Note that if the digest in use has an output length greater than 20 + bytes—as is the case for the hop of an onion service rendezvous + circuit created by the hs_ntor handshake—we truncate the digest + to 20 bytes here.) +``` + +If the VERSION is unrecognized or below the minimum accepted version (taken +from the consensus), the circuit should be torn down. + +<a id="tor-spec.txt-7.4"></a> + +## Stream-level flow control + +Edge nodes use RELAY_SENDME messages to implement end-to-end flow +control for individual connections across circuits. Similarly to +circuit-level flow control, edge nodes begin with a window of +DATA-bearing cells +(500) per stream, and increment the window by a fixed value (50) +upon receiving a RELAY_SENDME message. Edge nodes initiate RELAY_SENDME +messages when both a) the window is \<= 450, and b) there are less than +ten cells' worth of data remaining to be flushed at that edge. + +Stream-level RELAY_SENDME messages are distinguished by having nonzero +StreamID. They are still empty; the body still SHOULD be ignored. diff --git a/spec/tor-spec/index.md b/spec/tor-spec/index.md new file mode 100644 index 0000000..219ea1d --- /dev/null +++ b/spec/tor-spec/index.md @@ -0,0 +1,12 @@ +# Tor Protocol Specification + +Note: This document aims to specify Tor as currently implemented, though it +may take it a little time to become fully up to date. Future versions of Tor +may implement improved protocols, and compatibility is not guaranteed. +We may or may not remove compatibility notes for other obsolete versions of +Tor as they become obsolete. + +This specification is not a design document; most design criteria +are not examined. For more information on why Tor acts as it does, +see tor-design.pdf. + diff --git a/spec/tor-spec/negotiating-channels.md b/spec/tor-spec/negotiating-channels.md new file mode 100644 index 0000000..571a1be --- /dev/null +++ b/spec/tor-spec/negotiating-channels.md @@ -0,0 +1,516 @@ +<a id="tor-spec.txt-4"></a> + +# Negotiating and initializing channels {#negotiating} + +Here we describe the primary TLS behavior +used by Tor relays and clients to create a new channel. +There are older versions of these handshakes, +which we describe in [another section](./obsolete-channels.md). + +In brief: + - The initiator starts the handshake + by [opening a TLS connection](#tls). + - Both parties send a [VERSIONS](#VERSIONS-cells) + to negotiate the protocol version to use. + - The responder sends a + [CERTS cell](#CERTS-cells) to give the + initiator the certificates it needs to learn the responder's + identity, an [AUTH_CHALLENGE cell](#AUTH-CHALLENGE-cells) + that the initiator must include + as part of its answer if it chooses to authenticate, and a + [NETINFO cell](#NETINFO-cells) + to establish clock skew and IP addresses. + - The initiator checks whether the CERTS cell is correct, + and decides whether to authenticate. + - If the initiator + [is not authenticating itself](./channels.md#does-initiator-authenticate), + it sends a [NETINFO cell](#NETINFO-cells). + - If the initiator + [is authenticating itself](./channels.md#does-initiator-authenticate), + it sends a [CERTS cell](#CERTS-cells), + an [AUTHENTICATE cell](#AUTHENTICATE-cells), + a [NETINFO cell](#NETINFO-cells). + +When this handshake is in use, +the first cell must be VERSIONS, VPADDING, or AUTHORIZE, +and no other cell type is allowed to intervene besides those specified, +except for VPADDING cells. + +(The AUTHORIZE cell type is reserved for future use +by scanning-resistance designs. +It is not specified here.) + +```mermaid +sequenceDiagram + Initiator --> Responder: TLS Handshake + + Note over Initiator,Responder: The rest is encrypted + + Initiator ->> Responder: VERSIONS + Responder ->> Initiator: VERSIONS, CERTS, AUTH_CHALLENGE, NETINFO + + opt if the initiator is authenticating + Initiator ->> Responder: CERTS, AUTHENTICATE + end + + Initiator ->> Responder: NETINFO +``` + + + +## The TLS handshake {#tls} + +<span id="in-protocol">The +initiator must send a ciphersuite list containing +at least one ciphersuite other than +[those listed in the obsolete v1 handshake](./obsolete-channels.md#v1-ciphersuite-list). +</span> + +> This is trivially achieved +> by using any modern TLS implementation, +> and most implementations will not need to worry about it. +> +> This requirement distinguishes the current protocol +> (sometimes called the "in-protocol" or "v3" handshake) +> from the obsolete v1 protocol. + +<a id="tor-spec.txt-2.2"></a> + +### TLS security considerations + +(Standard TLS security guarantees apply; +this is not a comprehensive guide.) + +Implementations SHOULD NOT allow TLS session resumption -- it can +exacerbate some attacks (e.g. the "Triple Handshake" attack from +Feb 2013), and it plays havoc with forward secrecy guarantees. + +Implementations SHOULD NOT allow TLS compression -- although we don't +know a way to apply a CRIME-style attack to current Tor directly, +it's a waste of resources. + +<a id="tor-spec.txt-4.1"></a> + +## Negotiating versions with VERSIONS cells {#VERSIONS-cells} + +There are multiple instances of the Tor channel protocol. + +Once the TLS handshake is complete, +both parties send a VERSIONS cell +to negotiate which one they will use. + +The body in a VERSIONS cell is a series of big-endian two-byte +integers. +Both parties MUST select as the link protocol version the +highest number contained both in the VERSIONS cell they sent and in the +VERSIONS cell they received. +If they have no such version in common, +they cannot communicate and MUST close the connection. +Either party MUST +close the connection if the VERSIONS cell is not well-formed (for example, +if the body contains an odd number of bytes). + +Any VERSIONS cells sent after the first VERSIONS cell MUST be ignored. +(To be interpreted correctly, later VERSIONS cells MUST have a CIRCID_LEN +matching the version negotiated with the first VERSIONS cell.) + +> (The +> [obsolete v1 channel protocol](./obsolete-channels.md#v1-handshake) +> does note VERSIONS cells. +> Implementations MUST NOT list version 1 in their VERSIONS cells. +> The +> [obsolete v2 channel protocol](./obsolete-channels.md#v2-handshake) +> can only be used after renegotiation; +> implementations MUST NOT list version 2 in their VERSIONS cells +> unless they have renegotiated the TLS session.) + +The currently specified [Link](./subprotocol-versioning.md#link) protocols are: + +| Version | Description +| ------- | ----------- +| 1 | (Obsolete) The ["certs up front"](./obsolete-channels.md#v1-handshake) handshake. +| 2 | (Obsolete) Uses the [renegotiation-based handshake](./obsolete-channels.md#v2-handshake). Introduces variable-length cells. +| 3 | Uses the [current ("in-protocol") handshake](#in-protocol). Must always be advertised. +| 4 | Increases circuit ID width to 4 bytes. +| 5 | Adds support for [link padding](../padding-spec) and negotiation. + + +<a id="tor-spec.txt-4.2"></a> + +## CERTS cells {#CERTS-cells} + +The CERTS cell describes the keys +that a Tor instance is claiming to have, +and provides certificates to authenticate that those keys +belong, ultimately, to one or more +[identity keys](./relay-keys.md#identity). + +CERTS is a variable-length cell. Its body format is: + +| Field | Size | Description | +| ----- | ---- | ------------------------------ | +| N | 1 | Number of certificates in cell | +| N times: | | | +| - CertType | 1 | Type of certificate | +| - CertLen | 2 | Length of "Certificate" field | +| - Certificate | CertLen | Encoded certificate | + +Any extra octets at the end of a CERTS cell MUST be ignored. + +The CertType field determines +the format of the certificate, +and the roles of its keys within the Tor protcol. +Recognized values are defined in +["Certificate types (CERT_TYPE field)"](../cert-spec.md#list-cert-types). + +A CERTS cell MUST have no more than one certificate of any CertType. + +### Authenticating the responder from its CERTS {#auth-responder} + +The responder's CERTS cell is as follows: + +- The CERTS cell contains exactly one CertType 4 Ed25519 + `IDENTITY_V_SIGNING_CERT`. + - This cert must be self-signed; + the signing key must be included in a + ["signed-with-ed25519-key" extension](../cert-spec.md#signed-with-ed25519) + extension. + This signing key is `KP_relayid_ed`. + The subject key is `KP_relaysign_ed`. +- The CERTS cell contains exactly one CertType 5 Ed25519 + `SIGNING_V_TLS_CERT` certificate. + - This cert must be signed with `KP_relaysign_ed`. + Its subject must be the SHA-256 digest + of the TLS certificate + that was presented curing the TLS handshake. +- All of the certs above must be correctly signed, and not expired. + +The initiator must check all of the above. +If this is successful +the initiator knows that the responder +has the identity `KP_relayid_ed`. + +> The responder's CERTS cell is meant to prove +> that the responder posses one or more +> [relay identities](./relay-keys.md#identity). +> It does this by containing certificate chains +> from each relay identity key +> to the TLS certificate presented during the TLS handshake. + +> The responder's ownership of that TLS certificate +> was already proven during the TLS hadnshake itself. + +### Validating an initiator's CERTS {#validate-initiator-certs} + +When required +by [other parts of this specification](./channels.md#does-initiator-authenticate); +to prove its identity, +the initiator must provide a CERTS cell. + +> Recall that +> [not all initiators authenticate themselves](./channels.md#does-initiator-authenticate); +> bridges and clients do not prove their identity. + +The initiator's CERTS cell must conform to the rules +for the responder's CERTS cell (see above, +exchanging "initiator" and "responder") +except that: + +**Instead** of containg a `SIGNING_V_TLS_CERT`, + +- The CERTS cell contains exactly one CertType 6 + `SIGNING_V_LINK_AUTH` certificate. + - This certificate must be signed with `KP_relayid_ed`. + (Its subject key is deemed to be `KP_link_ed`.) +- All of the certs above must be correctly signed, and not expired. + +The responder must check all of the CERTS cell's properties +(as stated here, and in the previous section). +If this is successful +**and** +the initiator later sends a valid +[AUTHENTICATE cell](#AUTHENTICATE-cells), +then the initiator has ownership of the presented `KP_relayid_ed`. + +> Note that +> the CERTS cell is _not_ yet sufficent to authenticate the channel, +> until AUTHENTICATE is received: +> unlike the responder, +> the initiator is not required to present a TLS certificate +> during the TLS handshake. +> Therefore, the initiator has +> no meaningful `SIGNING_V_TLS_CERT` certificate. +> +> Therefore, instead, the initiator's CERTS cell +> proves a chain from the initiator's relay identities +> to a "link authentication" key. +> This key is later used to sign an "authentication challenge", +> and bind it to the channel. + +### Authenticating an RSA identity (#auth-RSA) + +After processing a CERTS cell +to find the other party's +`KP_relayid_ed` Ed25519 identity key, +a Tor instance MAY *additionally* check the CERTS cell +to find the other party's +`KP_relayid_rsa` legacy RSA identity key. + +A party with a given `KP_relayid_ed` identity key +also has a given `KP_relayid_rsa` legacy identity key +when all of the following are true. +(A party MUST NOT conclude that an RSA identity key +is associated with a channel +without checking these properties.) + +- The CERTS cell contains exactly one CertType 2 + `RSA_ID_X509` certificate. + - This must be a self-signed certificate containing a 1024-bit RSA key; + that key's exponent must be 65537. + That key is `KP_relayid_rsa`. +- The CERTS cell contains exactly one CertType 7 + `RSA_ID_V_IDENTITY` certificate. + - This certificate must be signed with `KP_relayid_rsa`. + - This certificate's subject key must be the same + as an already-authenticated `KP_relayid_ed`. +- All of the certs above must be correctly signed, + not expired, + and not before their `validAfter` dates. + +If the above tests all pass, +then any relay which can prove it has the the identity `KP_relayid_ed` +also has the legacy identity `KP_relayid_rsa`. + + +<a id="tor-spec.txt-4.3"></a> + +## AUTH_CHALLENGE cells{#AUTH-CHALLENGE-cells} + +An AUTH_CHALLENGE cell is a variable-length cell with the following +fields: + +| Field | Size +| ----- | ---- +| Challenge | 32 octets +| N_Methods | 2 octets +| Methods | 2 * N_Methods octets + +It is sent from the responder to the initiator. +Initiators MUST ignore unexpected bytes at the end of the cell. +Responders MUST generate every challenge independently. + +The Challenge field is +a [randomly generated](./preliminaries.md#random-values) +binary string that the initiator must sign (a hash of) +as part of their [AUTHENTICATE cell](#AUTHENTICATE-cells). + +The Methods are a list of authentication methods +that the responder will accept. +These methods are defined: + +| Type | Method | +| --------- | ------ | +| `[00 01]` | [RSA-SHA256-TLSSecret] (Obsolete) | +| `[00 02]` | (Historical, never implemented) | +| `[00 03]` | [Ed25519-SHA256-RFC5705] | + + +[RSA-SHA256-TLSSecret]: ./obsolete-channels.md#RSA-SHA256-TLSSecret +[Ed25519-SHA256-RFC5705]: #Ed25519-SHA256-RFC5705 + +<a id="tor-spec.txt-4.4"></a> + +## AUTHENTICATE cells{#AUTHENTICATE-cells} + +To authenticate, an initiator MUST +it respond to the AUTH_CHALLENGE cell +with a CERTS cell and an AUTHENTICATE cell. + +> Recall that initiators are +> [not always required to authenticate](./channels.md#does-initiator-authenticate). +> +> ([As discussed above](#validate-initiator-certs), +> the initiator's CERTS cell differs slightly +> from what a responder would send.) + +An AUTHENTICATE cell contains the following: + +| Field | Size +| ----- | ---- +| AuthType | 2 +| AuthLen | 2 +| Authentication | AuthLen + +Responders MUST ignore extra bytes at the end of an AUTHENTICATE +cell. + +The `AuthType` value corresponds to one of the +authentication methods. +The initiator MUST NOT send an AUTHENTICATE cell +whose AuthType was not contained +in the responder's AUTH_CHALLENGE. + +An initiator MUST NOT send an AUTHENTICATE +cell before it has verified the certificates +presented in the responder's CERTS cell, +and authenticated the responder. + +<a id="tor-spec.txt-4.4.2"></a> + +### Link authentication type 3: Ed25519-SHA256-RFC5705 {#Ed25519-SHA256-RFC5705} + +If AuthType is `[00 03]`, +meaning "Ed25519-SHA256-RFC5705", +the Authentication field of the AUTHENTICATE cell is as follows + +Modified values and new fields below are marked with asterisks. + +| Field | Size | Summary | +| --------- | ---- | ----------- | +| `TYPE` | 8 | The nonterminated string `AUTH0003` | +| `CID` | 32 | `SHA256(KP_relayid_rsa)` for initiator | +| `SID` | 32 | `SHA256(KP_relayid_rsa)` for responder | +| `CID_ED` | 32 | `KP_relayid_ed` for initiator | +| `SID_ED` | 32 | `KP_relayid_ed` for responder | +| `SLOG` | 32 | Responder log digest, SHA256 | +| `CLOG` | 32 | Initiator log digest, SHA256 | +| `SCERT` | 32 | SHA256 of responder's TLS certificate | +| `TLSSECRETS`|32 | RFC5705 information | +| `RAND` | 24 | [Random bytes] | +| `SIG` | 64 | Ed25519 signature | + + +- The `TYPE` string distinguishes this authentication document from others. + It must be the nonterminated 8-byte string `AUTH0003`. +- For `CID` and `SID`, the SHA256 digest of an RSA key + is computed as the SHA256 digest of its asn.1 encoding. +- The `SLOG` field is computed + as the SHA256 digest + of all bytes sent within the TLS channel up to and including + the AUTH_CHALLENGE cell. + - This includes the VERSIONS cell, + the CERTS cell, + the AUTH_CHALLENGE cell, + and any padding cells. +- The `CLOG` field is computed + as the SHA256 digest + of all bytes sent within the TLS channel up to but not including + the AUTHENTICATE cell. + - This includes the VERSIONS cell, + the CERTS cell, and any padding cells. +- The `SCERT` field holds the SHA256 digest + of the X.509 certificate presented by the responder + as part of the TLS negotiation. +- The `TLSSECRETS` field is computed + as the output of a Keying Material Exporter function + on the TLS section. + - The parameters for this exporter are: + - Label string: "EXPORTER FOR TOR TLS CLIENT BINDING AUTH0003" + - Context value: The initiator's `KP_relayid_ed`. + - Length: 32. + - For keying material exporters on TLS 1.3, + see [RFC 8446 Section 7.5]. + - For keying material exporters on older TLS versions, + see [RFC5705]. +- The `RAND` field is a uniform squence of [Random bytes]. +- The `SIG` field is an Ed25519 signature + of all earlier members in the Authentication + (from `TYPE` through `RAND`) + using `KS_link_ed`. + + +[Random bytes]: ./preliminaries.md#random-values +[RFC 8446 Section 7.5]: https://datatracker.ietf.org/doc/html/rfc8446#section-7.5 +[RFC5705]: https://datatracker.ietf.org/doc/html/rfc5705. + + +To check an AUTHENTICATE cell, +a responder checks that all fields from TYPE through TLSSECRETS +contain their unique correct values as described above, +and then verifies the signature. +The responder MUST ignore any extra bytes in the signed data after +the RAND field. + +<!-- TODO: We should consider removing that last sentence. --> + +<a id="tor-spec.txt-4.5"></a> + +## NETINFO cells {#NETINFO-cells} + +To finish the handshake, +each party sends the other +a NETINFO cell. + +A NETINFO cell's body is: + +| Field | Description | Size +| ----- | ----------- | ---- +| TIME | Timestamp | 4 bytes +| OTHERADDR: | Other party's address | +| - ATYPE | Address type | 1 byte +| - ALEN | Address length | 1 byte +| - AVAL | Address value | ALEN bytes +| NMYADDR | Number of this party's addresses | 1 byte +| NMYADDR times: | | +| - ATYPE | Address type | 1 byte +| - ALEN | Address length | 1 byte +| - AVAL | Address value | ALEN bytes + +Recognized address types (ATYPE) are: + +| ATYPE | Description +| ----- | ----------- +| 0x04 | IPv4 +| 0x06 | IPv6 + +Implementations SHOULD ignore addresses with unrecognized types. + +ALEN MUST be 4 when ATYPE is 0x04 (IPv4) +and 16 when ATYPE is 0x06 (IPv6). +If the ALEN value is wrong for the given ATYPE value, then +the provided address should be ignored. + +The `OTHERADDR` field SHOULD be set to the actual IP address +observed for the other party. + +> (This is typically the address passed to `connect()` +> when acting as the channel initiator, +> or the address received from `accept()` +> when acting as the channel responder.) + +In the `ATYPE`/`ALEN`/`AVAL` fields, +relays SHOULD send the addresses that they have advertised +in their router descriptors. +Bridges and clients SHOULD send none of their own addresses. + +For the `TIME` field, +relays send a (big-endian) integer +holding the number of seconds since the Unix epoch. +Clients SHOULD send `[00 00 00 00]` as their timestamp, +to avoid fingerprinting. + +> See [proposal 338](../proposals/338-netinfo-y2038.md) +> for a proposal to extend the timestamp to 8 bytes. + +Implementations MUST ignore unexpected bytes at the end of the NETINFO cell. + +### Using information from NETINFO cells {#using-netinfo} + +Implementations MAY use the timestamp value to help decide if their +clocks are skewed. + +Initiators MAY use "other OR's address" field +to help learn which address their connections may be originating from, +if they do not know it; +and to learn whether the peer will treat the current connection as +canonical. +(See [Canonical connections](./creating-circuits.md#canonical-connections)) + +Implementations SHOULD NOT trust these values unconditionally, +especially when they come from non-authorities, +since the other party can lie about the time +or the IP addresses it sees. + +Initiators SHOULD use "this OR's address" to make sure +that they have connected to another OR at its +[canonical address](./creating-circuits.md#canonical-connections). diff --git a/spec/tor-spec/obsolete-channels.md b/spec/tor-spec/obsolete-channels.md new file mode 100644 index 0000000..0bd47f8 --- /dev/null +++ b/spec/tor-spec/obsolete-channels.md @@ -0,0 +1,269 @@ +# Obsolete channel handshakes + +These handshake variants are no longer in use. +Channel initiators MUST NOT send them. +Relays MAY detect and reject them. + +> If you are experienced with TLS, +> you will find some aspects of this handshake +> strange or obfuscated. +> Several historical factors led to its current state. +> +> First, before the development of +> [pluggable transports](../pt-spec/), +> Tor tried to avoid censorship by mimicking the behavior +> of a web client negotiating HTTPS with a web server. +> If we wanted a secure option that was not in common use, +> we had to hide our use of that option. +> +> Second, prior to the introduction of +> [TLS 1.3](https://datatracker.ietf.org/doc/html/rfc8446), +> many more aspects of the handshake +> (such as the number and nature of certificates sent by each party) +> were sent in the clear, +> and were easy to distinguish. +> +> Third, prior to the introduction of TLS 1.3, +> there was no good encrypted signalling mechanism +> that a client could use to declare +> how it wanted the rest of the TLS handshake to proceed. +> Thus, we wound up using the client's list +> of supported ciphersuites +> to send a signal about which variation of the handshake is in use. + + +### Version 1, or "certificates up front" {#v1-handshake} + +With this obsolete handshake, +the responding relay proves ownership of an RSA identity (`KP_relayid_rsa`), +and the initiator also proves ownership of an RSA identity. + +(If the initiator does not have an RSA identity to prove, +it invents one and throws it away afterwards.) + +To select this handshake, +the initiator starts a TLS handshake +containing no ciphersuites other than these: + +<a id="v1-ciphersuite-list"></a> +```text + TLS_DHE_RSA_WITH_AES_256_CBC_SHA + TLS_DHE_RSA_WITH_AES_128_CBC_SHA + SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA +``` + +> Note that because of this list, +> it is impossible to use this obsolete handshake +> with TLS 1.3. + + +As part of the TLS handshake, +the initiator sends a two-certificate chain, +consisting of an X.509 certificate +for its short-term connection public key (`KP_legacy_conn_tls`) +signed by `KP_relayid_rsa`, and +a second self-signed X.509 certificate containing `KP_relayid_rsa`. +The responder sends a similar +certificate chain. + +Once the TLS handshake is done, +both parties validate each other's certificate chains. +If they are valid, +then the connection is Open, +and both parties may start exchanging [cells](./cell-packet-format.md). + +## Version 2, or "renegotiation" {#v2-handshake} + +In "renegotiation" (a.k.a. "the v2 handshake"), +the connection initiator selects at least one ciphersuite +not in the [list above](#v1-ciphersuite-list). +The initiator sends no certificates, and +the responder sends a single connection certificate in return. + +(If the responder sends a certificate chain, +the initiator assumes that it only knows about the v1 handshake.) + +Once this initial TLS handshake is complete, +the initiator renegotiates the session. +During the renegotiation, +each party sends a two-certificate chain +as in the ["certificates up front"](#v1-handshake) handshake above. + +When this handshake is used, +both parties immediately +send a VERSIONS cell, and after negotiating a link +protocol version (which will be 2), each sends a NETINFO cell +to confirm their addresses and timestamps. +At that point, the channel is Open. +No other intervening cell types are allowed. + +## Indicating support for the in-protocol handshake + +When the in-protocol handshake was new, +we placed a set of constraints on the certificate that the responder would send +to indicate that it supported the v3 handshake. + +Specifically, if at least one of these properties +was true of the responders's certificate, +the initiator could be sure that the responder supported +the in-protocol handshake: + +- The certificate is self-signed +- Some component other than "commonName" is set in the subject or + issuer DN of the certificate. +- The commonName of the subject or issuer of the certificate ends + with a suffix other than ".net". +- The certificate's public key modulus is longer than 1024 bits. + +Otherwise, the initiator would assume +that only the v2 protocol was in use. + +## Fixed ciphersuite list {#fixed-cipehrsuite-list} + +For a long time, clients would advertise +a certain "fixed ciphersuite list" +regardless of whether they actually supported those ciphers. + +That list is: + +```text + TLS1_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + TLS1_ECDHE_RSA_WITH_AES_256_CBC_SHA + TLS1_DHE_RSA_WITH_AES_256_SHA + TLS1_DHE_DSS_WITH_AES_256_SHA + TLS1_ECDH_RSA_WITH_AES_256_CBC_SHA + TLS1_ECDH_ECDSA_WITH_AES_256_CBC_SHA + TLS1_RSA_WITH_AES_256_SHA + TLS1_ECDHE_ECDSA_WITH_RC4_128_SHA + TLS1_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + TLS1_ECDHE_RSA_WITH_RC4_128_SHA + TLS1_ECDHE_RSA_WITH_AES_128_CBC_SHA + TLS1_DHE_RSA_WITH_AES_128_SHA + TLS1_DHE_DSS_WITH_AES_128_SHA + TLS1_ECDH_RSA_WITH_RC4_128_SHA + TLS1_ECDH_RSA_WITH_AES_128_CBC_SHA + TLS1_ECDH_ECDSA_WITH_RC4_128_SHA + TLS1_ECDH_ECDSA_WITH_AES_128_CBC_SHA + SSL3_RSA_RC4_128_MD5 + SSL3_RSA_RC4_128_SHA + TLS1_RSA_WITH_AES_128_SHA + TLS1_ECDHE_ECDSA_WITH_DES_192_CBC3_SHA + TLS1_ECDHE_RSA_WITH_DES_192_CBC3_SHA + SSL3_EDH_RSA_DES_192_CBC3_SHA + SSL3_EDH_DSS_DES_192_CBC3_SHA + TLS1_ECDH_RSA_WITH_DES_192_CBC3_SHA + TLS1_ECDH_ECDSA_WITH_DES_192_CBC3_SHA + SSL3_RSA_FIPS_WITH_3DES_EDE_CBC_SHA + SSL3_RSA_DES_192_CBC3_SHA + [*] The "extended renegotiation is supported" ciphersuite, 0x00ff, is + not counted when checking the list of ciphersuites. +``` + +When encountering this list, +a responder would not select any ciphersuites +besides the mandatory-to-implement +TLS_DHE_RSA_WITH_AES_256_CBC_SHA, TLS_DHE_RSA_WITH_AES_128_CBC_SHA, +and SSL_DHE_RSA_WITH_3DES_EDE_CBC_SHA. + +Clients no longer report ciphers that they do not support. + + +## Legacy CERTS authentication: Responder has RSA Identity only {#certs-responder-legacy} + +A Tor relay that has only an RSA identity key (`KP_relayid_rsa`) +and not an Ed25519 identity key (`KP_relayid_ed`) +will present a different set of certificates in its CERTS cell. + +(Relays like this are no longer supported; +all relays must now have Ed25519 identities.) + +To authenticate a responder as having only an RSA identity, +the initiator would verify the following: + +- The CERTS cell contains exactly one CertType 2 `RSA_ID_X509` certificate. + - This must be a self-signed certificate containing a 1024-bit RSA key; + that key's exponent must be 65537. + That key is `KP_relayid_rsa`. +- The CERTS cell contains exactly one CertType 1 `TLS_LINK_X509` certificate. + - It must be signed with `KP_relayid_rsa`. + - Its subject key must be the same + as `KP_legacy_conn_tls` + (the key used to negotiate the TLS connection). +- All of the certs above must be correctly signed, + not expired, + and not before their `validAfter` dates. + +### Legacy CERTS authentication: Initiator has RSA Identity only {#certs-initiator-legacy} + + +As discussed in +["Validating an initiator's CERTS"](./negotiating-channels.md#validate-initiator-certs), +the initiator of the v3 handshake does not present a TLS certificate. + +Therefore, to process an initiator's CERTS cell, +the responder would have to procede as for a responder's certificates, +[as described above](#certs-responder-legacy), +except that **instead** of checking for a `TLS_LINK_X509` certificate, +it would need to verify that: + +- The CERTS cell contains exactly one CertType 3 + `LINK_AUTH_X509` certificate. + - This certificate must be signed with `KP_relayid_rsa`. + Its subject key is deemed to be `KP_legacy_linkauth_rsa`. +- All of the certs above must be correctly signed, + not expired, + and not before their `validAfter` dates. + + +<a id="tor-spec.txt-4.4.1"></a> + +## Link authentication type 1: RSA-SHA256-TLSSecret {#RSA-SHA256-TLSSecret} + +This is an obsolete authentication method +used before RFC5705 support was ubiquitous. +It is nearly the same as +[Ed25519-SHA256-RFC5705](./negotiating-channels.md#Ed25519-SHA256-RFC5705), +but lacks support for Ed25519, +and does not use keying material exporters +(which were not widely supported at the time it as used. + +If AuthType is `[00 01]` (meaning "RSA-SHA256-TLSSecret"), +then the authentication field of the AUTHENTICATE +cell contains the following: + +| Field | Size | Description | +| --------- | ---- | ----------- | +| `TYPE` | 8 | The nonterminated string `AUTH0001` | +| `CID` | 32 | `SHA256(KP_relayid_rsa)` for initiator | +| `SID` | 32 | `SHA256(KP_relayid_rsa)` for responder | +| `SLOG` | 32 | SHA256 of responder transcript | +| `CLOG` | 32 | SHA256 of initiator transcript | +| `SCERT` | 32 | SHA256 of responder's TLS certificate | +| `TLSSECRETS`|32 | An ad-hoc HMAC output | +| `RAND` | 24 | [Random bytes] | +| `SIG` | Variable | RSA signature | + + +Notes are as for [Ed25519-SHA256-RFC5705], +except as follows: + + +- The `TLSSECRETS` fields holds a SHA256 HMAC, + using the TLS master secret as the secret key, + of the following concatenated fields: + - `client_random`, as sent in the TLS Client Hello + - `server_random`, as sent in the TLS Server Hello + - the NUL terminated ASCII string: + `"Tor V3 handshake TLS cross-certification"` +* The `SIG` fields holds an RSA signature of a SHA256 hash + of all the previous fields + (that is, `TYPE` through `RAND`), + using the initiator's `KS_legacy_linkauth_rsa`. + This field extends through the end of the AUTHENTICATE cell. + +[Random bytes]: ./preliminaries.md#random-values +[Ed25519-SHA256-RFC5705]: ./negotiating-channels.md#Ed25519-SHA256-RFC5705 + +Responders MUST NOT accept this AuthType if the initiator has +claimed to have an Ed25519 identity. + diff --git a/spec/tor-spec/opening-streams.md b/spec/tor-spec/opening-streams.md new file mode 100644 index 0000000..81e1616 --- /dev/null +++ b/spec/tor-spec/opening-streams.md @@ -0,0 +1,141 @@ +<a id="tor-spec.txt-6.2"></a> + +# Opening streams and transmitting data + +## Opening a new stream: The begin/connected handshake {#opening} + +To open a new anonymized TCP connection, the OP chooses an open +circuit to an exit that may be able to connect to the destination +address, selects an arbitrary StreamID not yet used on that circuit, +and constructs a RELAY_BEGIN message with a body encoding the address +and port of the destination host. The body format is: + +```text + ADDRPORT [nul-terminated string] + FLAGS [4 bytes, optional] + + ADDRPORT is made of ADDRESS | ':' | PORT | [00] +``` + +where ADDRESS can be a DNS hostname, or an IPv4 address in +dotted-quad format, or an IPv6 address surrounded by square brackets; +and where PORT is a decimal integer between 1 and 65535, inclusive. + +The ADDRPORT string SHOULD be sent in lower case, to avoid +fingerprinting. Implementations MUST accept strings in any case. + +The FLAGS value has one or more of the following bits set, where +"bit 1" is the LSB of the 32-bit value, and "bit 32" is the MSB. +(Remember that +[all integers in Tor are big-endian](../intro/conventions.md), +so +the MSB of a 4-byte value is the MSB of the first byte, and the LSB +of a 4-byte value is the LSB of its last byte.) + +If FLAGS is absent, its value is 0. Whenever 0 would be sent for +FLAGS, FLAGS is omitted from the message body. + +```text + bit meaning + 1 -- IPv6 okay. We support learning about IPv6 addresses and + connecting to IPv6 addresses. + 2 -- IPv4 not okay. We don't want to learn about IPv4 addresses + or connect to them. + 3 -- IPv6 preferred. If there are both IPv4 and IPv6 addresses, + we want to connect to the IPv6 one. (By default, we connect + to the IPv4 address.) + 4..32 -- Reserved. Current clients MUST NOT set these. Servers + MUST ignore them. +``` + +Upon receiving this message, the exit node resolves the address as +necessary, and opens a new TCP connection to the target port. If the +address cannot be resolved, or a connection can't be established, the +exit node replies with a RELAY_END message. (See +["Closing streams"](./closing-streams.md#closing-streams).) +Otherwise, the exit node replies with a RELAY_CONNECTED message, whose +body is in one of the following formats: + +```text + The IPv4 address to which the connection was made [4 octets] + A number of seconds (TTL) for which the address may be cached [4 octets] + + or + + Four zero-valued octets [4 octets] + An address type (6) [1 octet] + The IPv6 address to which the connection was made [16 octets] + A number of seconds (TTL) for which the address may be cached [4 octets] +``` + +Implementations MUST accept either of these formats, +and MUST also accept an empty RELAY_CONNECTED message body. + +Implmentations MAY ignore the address value, +and MAY choose not to cache it. +If an implementation chooses to cache the address, +it SHOULD NOT reuse that address with any other circuit. + +> The reason not to cache an address +> is that the exit might have lied about the actual address of the host, +> or might have given us a unique address to identify us in the future. + +\[Tor exit nodes before 0.1.2.0 set the TTL field to a fixed value. Later +versions set the TTL to the last value seen from a DNS server, and expire +their own cached entries after a fixed interval. This prevents certain +attacks.\] + +## Transmitting data {#transmitting} + +Once a connection has been established, the OP and exit node +package stream data in RELAY_DATA message, and upon receiving such +messages, echo their contents to the corresponding TCP stream. + +If the exit node does not support optimistic data (i.e. its +version number is before 0.2.3.1-alpha), then the OP MUST wait +for a RELAY_CONNECTED message before sending any data. If the exit +node supports optimistic data (i.e. its version number is +0.2.3.1-alpha or later), then the OP MAY send RELAY_DATA messages +immediately after sending the RELAY_BEGIN message (and before +receiving either a RELAY_CONNECTED or RELAY_END message). + +RELAY_DATA messages sent to unrecognized streams are dropped. If +the exit node supports optimistic data, then RELAY_DATA messages it +receives on streams which have seen RELAY_BEGIN but have not yet +been replied to with a RELAY_CONNECTED or RELAY_END are queued. +If the stream creation succeeds with a RELAY_CONNECTED, the queue +is processed immediately afterwards; if the stream creation fails +with a RELAY_END, the contents of the queue are deleted. + +Relay RELAY_DROP messages are long-range dummies; upon receiving such +a message, the OR or OP must drop it. + +<a id="tor-spec.txt-6.2.1"></a> + +## Opening a directory stream + +If a Tor relay is a directory server, it should respond to a +RELAY_BEGIN_DIR message as if it had received a BEGIN message requesting a +connection to its directory port. RELAY_BEGIN_DIR message ignore exit +policy, since the stream is local to the Tor process. + +Directory servers may be: + +- authoritative directories (RELAY_BEGIN_DIR, usually non-anonymous), +- bridge authoritative directories (RELAY_BEGIN_DIR, anonymous), +- directory mirrors (RELAY_BEGIN_DIR, usually non-anonymous), +- onion service directories (RELAY_BEGIN_DIR, anonymous). + +If the Tor relay is not running a directory service, it should respond +with a REASON_NOTDIRECTORY RELAY_END message. + +Clients MUST generate a empty body for RELAY_BEGIN_DIR message; +relays MUST ignore the the body of a RELAY_BEGIN_DIR message. + +In response to a RELAY_BEGIN_DIR message, relays respond either with a +RELAY_CONNECTED message on success, or a RELAY_END message on failure. +They MUST send a RELAY_CONNECTED message with an empty body; +clients MUST ignore the body. + +\[RELAY_BEGIN_DIR was not supported before Tor 0.1.2.2-alpha; clients +SHOULD NOT send it to routers running earlier versions of Tor.\] diff --git a/spec/tor-spec/preliminaries.md b/spec/tor-spec/preliminaries.md new file mode 100644 index 0000000..15cacf3 --- /dev/null +++ b/spec/tor-spec/preliminaries.md @@ -0,0 +1,142 @@ +<a id="tor-spec.txt-0"></a> + +# Preliminaries + +<a id="tor-spec.txt-0.1"></a> + +## Notation and encoding{#notation-and-encoding} + +```text + KP -- a public key for an asymmetric cipher. + KS -- a private key for an asymmetric cipher. + K -- a key for a symmetric cipher. + N -- a "nonce", a random value, usually deterministically chosen + from other inputs using hashing. +``` + +H(m) -- a cryptographic hash of m. + +## Security parameters + +Tor uses a stream cipher, a public-key cipher, the Diffie-Hellman +protocol, and a hash function. + +KEY_LEN -- the length of the stream cipher's key, in bytes. + +```text + KP_ENC_LEN -- the length of a public-key encrypted message, in bytes. + KP_PAD_LEN -- the number of bytes added in padding for public-key + encryption, in bytes. (The largest number of bytes that can be encrypted + in a single public-key operation is therefore KP_ENC_LEN-KP_PAD_LEN.) + + DH_LEN -- the number of bytes used to represent a member of the + Diffie-Hellman group. + DH_SEC_LEN -- the number of bytes used in a Diffie-Hellman private key (x). + + HASH_LEN -- the length of the hash function's output, in bytes. + +``` + +## Message lengths {#msg-len} + +Some message lengths are fixed in the Tor protocol. +We give them here. +Some of these message lengths depend +on the version of the Tor link protocol in use: +for these, the link protocol is denoted in this table with `v`. + +| Name | Length in bytes | Meaning | +| ---- | --------------- | ------- | +| `CELL_BODY_LEN` | 509 | The body length for a [fixed-length cell](./cell-packet-format.md#fixed-length-cell). | +| `CIRCID_LEN(v)`, `v` < 4 | 2 | The length of a [circuit ID](./cell-packet-format.md#circid) | +| `CIRCID_LEN(v)`, `v` ≥ 4 | 4 | | +| `CELL_LEN(v)`, `v` < 4 | 512 | The length of a [fixed-length cell](./cell-packet-format.md). | +| `CELL_LEN(v)`, `v` ≥ 4 | 514 | | + +Note that for all `v`, `CELL_LEN(v) = 1 + CIRCID_LEN(v) + CELL_BODY_LEN`. + +> Formerly `CELL_BODY_LEN` was called sometimes called `PAYLOAD_LEN`. + +<a id="tor-spec.txt-0.3"></a> + +## Ciphers{#ciphers} + +These are the ciphers we use _unless otherwise specified_. Several of +them are deprecated for new use. + +For a stream cipher, unless otherwise specified, we use 128-bit AES in +counter mode, with an IV of all 0 bytes. (We also require AES256.) + +For a public-key cipher, unless otherwise specified, we use RSA with +1024-bit keys and a fixed exponent of 65537. We use OAEP-MGF1 +padding, with SHA-1 as its digest function. We leave the optional +"Label" parameter unset. (For OAEP padding, see +ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf) + +We also use the Curve25519 group and the Ed25519 signature format in +several places. + +For Diffie-Hellman, unless otherwise specified, we use a generator +(g) of 2. For the modulus (p), we use the 1024-bit safe prime from +rfc2409 section 6.2 whose hex representation is: + +```text + "FFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E08" + "8A67CC74020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B" + "302B0A6DF25F14374FE1356D6D51C245E485B576625E7EC6F44C42E9" + "A637ED6B0BFF5CB6F406B7EDEE386BFB5A899FA5AE9F24117C4B1FE6" + "49286651ECE65381FFFFFFFFFFFFFFFF" +``` + +As an optimization, implementations SHOULD choose DH private keys (x) of +320 bits. Implementations that do this MUST never use any DH key more +than once. +\[May other implementations reuse their DH keys?? -RD\] +\[Probably not. Conceivably, you could get away with changing DH keys once +per second, but there are too many oddball attacks for me to be +comfortable that this is safe. -NM\] + +For a hash function, unless otherwise specified, we use SHA-1. + +KEY_LEN=16. +DH_LEN=128; DH_SEC_LEN=40. +KP_ENC_LEN=128; KP_PAD_LEN=42. +HASH_LEN=20. + +We also use SHA256 and SHA3-256 in some places. + +When we refer to "the hash of a public key", unless otherwise +specified, we mean the SHA-1 hash of the DER encoding of an ASN.1 RSA +public key (as specified in PKCS.1). + +<span id="random-values"> +All "random" values MUST be generated with a cryptographically +strong pseudorandom number generator seeded from a strong entropy +source, unless otherwise noted. +All "random" values MUST selected uniformly at random from the +universe of possible values, unless otherwise noted. +</span> + +<a id="tor-spec.txt-0.4"></a> + +## A bad hybrid encryption algorithm, for legacy purposes {#legacy-hybrid-encryption} + +Some specifications will refer to the "legacy hybrid encryption" of a +byte sequence M with a public key KP. It is computed as follows: + +```text + 1. If the length of M is no more than KP_ENC_LEN-KP_PAD_LEN, + pad and encrypt M with KP. + 2. Otherwise, generate a KEY_LEN byte random key K. + Let M1 = the first KP_ENC_LEN-KP_PAD_LEN-KEY_LEN bytes of M, + and let M2 = the rest of M. + Pad and encrypt K|M1 with KP. Encrypt M2 with our stream cipher, + using the key K. Concatenate these encrypted values. +``` + +Note that this "hybrid encryption" approach does not prevent +an attacker from adding or removing bytes to the end of M. It also +allows attackers to modify the bytes not covered by the OAEP -- +see Goldberg's PET2006 paper for details. Do not use it as the basis +for new protocols! Also note that as used in Tor's protocols, case 1 +never occurs. diff --git a/spec/tor-spec/relay-cells.md b/spec/tor-spec/relay-cells.md new file mode 100644 index 0000000..f1f7997 --- /dev/null +++ b/spec/tor-spec/relay-cells.md @@ -0,0 +1,219 @@ +<a id="tor-spec.txt-6.1"></a> + +# Relay cells {#relay-cells} + +Within a circuit, the OP and the end node use the contents of +relay cells to tunnel end-to-end commands and TCP connections +("Streams") across circuits. End-to-end commands can be initiated +by either edge; streams are initiated by the OP. + +End nodes that accept streams may be: + +- exit relays (RELAY_BEGIN, anonymous), +- directory servers (RELAY_BEGIN_DIR, anonymous or non-anonymous), +- onion services (RELAY_BEGIN, anonymous via a rendezvous point). + +The body of each unencrypted relay cell consists of an +enveloped relay message, encoded as follows: + +| Field | Size +| ----- | ---- +| Relay command | 1 byte +| 'Recognized' | 2 bytes +| StreamID | 2 bytes +| Digest | 4 bytes +| Length | 2 bytes +| Data | Length bytes +| Padding | CELL_BODY_LEN - 11 - Length bytes + +> TODO: When we implement [prop340](../proposals/340-packed-and-fragmented.md), +> we should clarify which parts of the above are about +> the relay cell, and which are the enveloped message. + +The relay commands are: + +| Command | Identifier | Type | Description +| ------- | ---------- | ---- | ----------- +| <th>Core protocol</th> +| 1 | [BEGIN] | **F** | Open a stream +| 2 | [DATA] | **F**/**B** | Transmit data +| 3 | [END] | **F**/**B** | Close a stream +| 4 | [CONNECTED] | **B** | Stream has successfully opened +| 5 | [SENDME] | **F**/**B**, **C?** | Acknowledge traffic +| 6 | [EXTEND] | **F**, **C** | Extend a circuit with TAP (obsolete) +| 7 | [EXTENDED] | **B**, **C** | Finish extending a circuit with TAP (obsolete) +| 8 | [TRUNCATE] | **F**, **C** | Remove nodes from a circuit (unused) +| 9 | [TRUNCATED] | **B**, **C** | Report circuit truncation (unused) +| 10 | [DROP] | **F**/**B**, **C** | Long-range padding +| 11 | [RESOLVE] | **F** | Hostname lookup +| 12 | [RESOLVED] | **B** | Hostname lookup reply +| 13 | [BEGIN_DIR] | **F** | Open stream to directory cache +| 14 | [EXTEND2] | **F**, **C** | Extend a circuit +| 15 | [EXTENDED2] | **B**, **C** | Finish extending a circuit +| 16..18 | Reserved | | For UDP; see [prop339]. +| <th>Conflux</th> +| 19 | [CONFLUX_LINK][prop329] | **F**, **C** | Link circuits into a bundle +| 20 | [CONFLUX_LINKED][prop329] | **B**, **C** | Acknowledge link request +| 21 | [CONFLUX_LINKED_ACK][prop329] | **F**, **C** | Acknowledge CONFLUX_LINKED message (for timing) +| 22 | [CONFLUX_SWITCH][prop329] | **F**/**B**, **C** | Switch between circuits in a bundle +| <th>Onion services</th> +| 32 | [ESTABLISH_INTRO] | **F**, **C** | Create introduction point +| 33 | [ESTABLISH_RENDEZVOUS] | **F**, **C** | Create rendezvous point +| 34 | [INTRODUCE1] | **F**, **C** | Introduction request (to intro point) +| 35 | [INTRODUCE2] | **B**, **C** | Introduction request (to service) +| 36 | [RENDEZVOUS1] | **F**, **C** | Rendezvous request (to rendezvous point) +| 37 | [RENDEZVOUS2] | **B**, **C** | Rendezvous request (to client) +| 38 | [INTRO_ESTABLISHED] | **B**, **C** | Acknowledge ESTABLISH_INTRO +| 39 | [RENDEZVOUS_ESTABLISHED] | **B**, **C** | Acknowledge ESTABLISH_RENDEZVOUS +| 40 | [INTRODUCE_ACK] | **B**, **C** | Acknowledge INTRODUCE1 +| <th>Circuit padding</th> +| 41 | [PADDING_NEGOTIATE][circ-padding] | **F**, **C** | Negotiate circuit padding +| 42 | [PADDING_NEGOTIATED][circ-padding] | **B**, **C** | Negotiate circuit padding +| <th>Flow control</th> +| 43 | [XON][prop324] | **F**/**B** | Stream-level flow control +| 44 | [XOFF][prop324] | **F**/**B** | Stream-level flow control + +[prop324]: ../proposals/324-rtt-congestion-control.txt +[prop329]: ../proposals/329-traffic-splitting.md +[prop339]: ../proposals/339-udp-over-tor.md +[circ-padding]: ../padding-spec/circuit-level-padding.md#circuit-level-padding +[BEGIN]: ./opening-streams.md#opening +[CONNECTED]: ./opening-streams.md#opening +[DATA]: ./opening-streams.md#transmitting +[DROP]: ./opening-streams.md#transmitting +[BEGIN_DIR]: ./opening-streams.md#opening-a-directory-stream +[END]: ./closing-streams.md#closing-streams +[RESOLVE]: ./remote-hostname-lookup.md +[RESOLVED]: ./remote-hostname-lookup.md +[EXTEND]: ./create-created-cells.md#EXTEND +[EXTEND2]: ./create-created-cells.md#EXTEND +[EXTENDED]: ./create-created-cells.md#EXTEND +[EXTENDED2]: ./create-created-cells.md#EXTEND +[TRUNCATE]: ./tearing-down-circuits.md +[TRUNCATED]: ./tearing-down-circuits.md +[SENDME]: ./flow-control.md#sendme-message-format +[ESTABLISH_INTRO]: ../rend-spec/introduction-protocol.md#EST_INTRO +[INTRO_ESTABLISHED]: ../rend-spec/introduction-protocol.md#INTRO_ESTABLISHED +[INTRODUCE1]: ../rend-spec/introduction-protocol.md#SEND_INTRO1 +[INTRODUCE2]: ../rend-spec/introduction-protocol.md#PROCESS_INTRO2 +[INTRODUCE_ACK]: ../rend-spec/introduction-protocol.md#SEND_INTRO1 +[ESTABLISH_RENDEZVOUS]: ../rend-spec/rendezvous-protocol.md#EST_REND_POINT +[RENDEZVOUS_ESTABLISHED]: ../rend-spec/rendezvous-protocol.md#EST_REND_POINT +[RENDEZVOUS1]: ../rend-spec/rendezvous-protocol.md#JOIN_REND +[RENDEZVOUS2]: ../rend-spec/rendezvous-protocol.md#JOIN_REND + +- **F** (Forward): Must only be sent by the originator of the circuit. +- **B** (Backward): Must only be sent by other nodes in the circuit + back towards the originator. +- **F**/**B** (Forward or backward): May be sent in either direction. +- **C**: (Control) must have a zero-valued stream ID. + (Other commands must have a nonzero stream ID.) + +The 'recognized' field is used as a simple indication that the cell +is still encrypted. It is an optimization to avoid calculating +expensive digests for every cell. When sending cells, the unencrypted +'recognized' MUST be set to zero. + +When receiving and decrypting cells the 'recognized' will always be +zero if we're the endpoint that the cell is destined for. For cells +that we should relay, the 'recognized' field will usually be nonzero, +but will accidentally be zero with P=2^-16. + +When handling a relay cell, if the 'recognized' in field in a +decrypted relay cell is zero, the 'digest' field is computed as +the first four bytes of the running digest of all the bytes that have +been destined for this hop of the circuit or originated from this hop +of the circuit, seeded from Df or Db respectively (obtained in +[Setting circuit keys](./setting-circuit-keys.md#setting-circuit-keys)), +and including this relay cell's entire body +(taken with the digest field set to zero). Note that these digests +_do_ include the padding bytes at the end of the cell, not only those up +to "Len". If the digest is correct, the cell is considered "recognized" +for the purposes of decryption (see +[Routing relay cells](./routing-relay-cells.md#routing-relay-cells)). + +(The digest does not include any bytes from relay cells that do +not start or end at this hop of the circuit. That is, it does not +include forwarded data. Therefore if 'recognized' is zero but the +digest does not match, the running digest at that node should +not be updated, and the cell should be forwarded on.) + +All relay messages pertaining to the same tunneled stream have the same +stream ID. StreamIDs are chosen arbitrarily by the OP. No stream +may have a StreamID of zero. Rather, relay messages that affect the +entire circuit rather than a particular stream use a StreamID of zero +-- they are marked in the table above as "**C**" ([control") style +cells. (Sendme cells are marked as "sometimes control" because they +can include a StreamID or not depending on their purpose -- see +[Flow control](./flow-control.md#flow-control).) + +The 'Length' field of a relay cell contains the number of bytes in +the relay cell's body which contain the body of the message. +The remainder of +the unencrypted relay cell's body is padded with padding bytes. +Implementations +handle padding bytes of unencrypted relay cells as they do padding +bytes for other cell types; see [Cell Packet format](./cell-packet-format.md#cell-packet-format). + +<span id="relay-cell-padding">The +'Padding' field is used to make relay cell contents unpredictable, to +avoid certain attacks (see +[proposal 289](../proposals/289-authenticated-sendmes.txt) +for rationale). Implementations +SHOULD fill this field with four zero-valued bytes, followed by as many +random bytes as will fit. (If there are fewer than 4 bytes for padding, +then they should all be filled with zero.</span> + +Implementations MUST NOT rely on the contents of the 'Padding' field. + +If the relay cell is recognized but the relay command is not +understood, the cell must be dropped and ignored. Its contents +still count with respect to the digests and flow control windows, though. + +<a id="tor-spec.txt-6.1.1"></a> + +## Calculating the 'Digest' field {#digest-field} + +The 'Digest' field itself serves the purpose to check if a cell has been +fully decrypted, that is, all onion layers have been removed. Having a +single field, namely 'Recognized' is not sufficient, as outlined above. + +When ENCRYPTING a relay cell, an implementation does the following: + +```text +# Encode the cell in binary (recognized and digest set to zero) +tmp = cmd + [0, 0] + stream_id + [0, 0, 0, 0] + length + data + padding + +# Update the digest with the encoded data +digest_state = hash_update(digest_state, tmp) +digest = hash_calculate(digest_state) + +# The encoded data is the same as above with the digest field not being +# zero anymore +encoded = cmd + [0, 0] + stream_id + digest[0..4] + length + data + + padding + +# Now we can encrypt the cell by adding the onion layers ... +``` + + When DECRYPTING a relay cell, an implementation does the following: + +```text +decrypted = decrypt(cell) + +# Replace the digest field in decrypted by zeros +tmp = decrypted[0..5] + [0, 0, 0, 0] + decrypted[9..] + +# Update the digest field with the decrypted data and its digest field +# set to zero +digest_state = hash_update(digest_state, tmp) +digest = hash_calculate(digest_state) + +if digest[0..4] == decrypted[5..9] + # The cell has been fully decrypted ... +``` + +The caveat itself is that only the binary data with the digest bytes set to +zero are being taken into account when calculating the running digest. The +final plain-text cells (with the digest field set to its actual value) are +not taken into the running digest. diff --git a/spec/tor-spec/relay-early.md b/spec/tor-spec/relay-early.md new file mode 100644 index 0000000..fd7dbf4 --- /dev/null +++ b/spec/tor-spec/relay-early.md @@ -0,0 +1,20 @@ +<a id="tor-spec.txt-5.6"></a> + +# Handling RELAY_EARLY cells{#handling-relay-early-cells} + +A RELAY_EARLY cell is designed to limit the length any circuit can reach. +When an OR receives a RELAY_EARLY cell, and the next node in the circuit +is speaking v2 of the link protocol or later, the OR relays the cell as a +RELAY_EARLY cell. Otherwise, older Tors will relay it as a RELAY cell. + +If a node ever receives more than 8 RELAY_EARLY cells on a given +outbound circuit, it SHOULD close the circuit. If it receives any +inbound RELAY_EARLY cells, it MUST close the circuit immediately. + +When speaking v2 of the link protocol or later, clients MUST only send +EXTEND/EXTEND2 message inside RELAY_EARLY cells. Clients SHOULD send the first +~8 relay cells that are not targeted at the first hop of any circuit as +RELAY_EARLY cells too, in order to partially conceal the circuit length. + +\[Starting with Tor 0.2.3.11-alpha, relays should reject any +EXTEND/EXTEND2 cell not received in a RELAY_EARLY cell.\] diff --git a/spec/tor-spec/relay-keys.md b/spec/tor-spec/relay-keys.md new file mode 100644 index 0000000..25ac3ed --- /dev/null +++ b/spec/tor-spec/relay-keys.md @@ -0,0 +1,175 @@ +<a id="tor-spec.txt-1.1"></a> + +# Relay keys and identities + +Every Tor relay has multiple public/private keypairs, +with different lifetimes and purposes. +We explain them here. + +Each key here has an English name +(like "Ed25519 identity key") +and an unambiguous identifier +(like `KP_relayid_ed`). + +In an identifier, +a `KP_` prefix denotes a public key, +and a `KS_` prefix denotes the corresponding secret key. + +> For historical reasons or reasons of space, +> you will sometimes encounter +> multiple English names for the same key, +> or shortened versions of that name. +> The identifier for a key, however, +> should always be unique and unambiguous. + +For security reasons, **all keys MUST be distinct**: +the same key or keypair should never be used +for separate roles within the Tor protocol suite, +unless specifically stated. +For example, +a relay's identity key `KP_relayid_ed` +MUST NOT also be used +as its medium-term signing key `KP_relaysign_ed`. + +## Identity keys {#identity} + +An **identity key** is a long-lived key +that uniquely identifies a relay. +Two relays with the same set of identity keys +are considered to be the same; +any relay that changes its identity key +is considered to have become a different relay. + +An identity keypair's lifetime +is the same as the lifetime of the relay. + +Two identity keys are currently defined: + +- <span id="relayid_ed">`KP_relayid_ed`, `KS_relayid_ed`:</span> + An "ed25519 identity key", + also sometimes called a "master identity key". + + This is an Ed25519 key. + This key never expires. + It is used for only one purpose: + signing the `KP_relaysign_ed` key, + which is used to sign + other important keys and objects. + +- <span id="relayid_rsa">`KP_relayid_rsa`, `KS_relayid_rsa`:</span> + A _legacy_ "RSA identity key". + + This is an RSA key. + It never expires. + It is always 1024 bits long, + and (as discussed [above](./preliminaries.md#ciphers)) + its exponent must be 65537. + It is used to sign directory documents and certificates. + +Note that because the legacy RSA identity key is so short, +it should not be assumed secure against an attacker. +It exists for legacy purposes only. +When authenticating a relay, +a failure to prove an expected RSA identity +is sufficient evidence of a _failure_ to authenticate, +but a successful proof of an RSA identity is not sufficient +to establish a relay's identity. +Parties SHOULD NOT use the RSA identity on its own. + +We write `KP_relayid` to refer to a key which is either +`KP_relayid_rsa` or `KP_relayid_ed`. + +## Online signing keys {#online-signing} + +Since Tor's design tries to support +keeping the high-value Ed25519 relay identity key offline, +we need a corresponding key that can be used for online signing: + +- <span id="relaysign_ed">`KP_relaysign_ed`, `KS_relaysign_ed`:</span> + A medium-term Ed25519 "signing" key. + This key is signed by the identity key `KP_relayid_ed`, + and must be kept online. + A new one should be generated periodically. + It signs nearly everything else, + including directory objects, + and certificates for other keys. + +When this key is generated, +it needs to be signed with the `KP_relayid_ed` key, +producing a [certificate of type `IDENTITY_V_SIGNING`](../cert-spec.md). +The `KP_relayid_ed` key is not used for anything else. + + +## Circuit extension keys + +Each relay has one or more **circuit extension keys** +(also called "onion keys"). +When [creating](./create-created-cells.md) +or [extending](./create-created-cells.md#EXTEND) +a circuit, +a client uses this key to perform +a [one-way authenticated key exchange][cacr2011-goldberg] +with the target relay. +If the recipient does not have the correct private key, +the handshake will fail. + +[cacr2011-goldberg]: https://cacr.uwaterloo.ca/techreports/2011/cacr2011-11.pdf + +Circuit extension keys have moderate lifetimes, +on the order of weeks. +They are published as part of the directory protocol, +and relays SHOULD accept handshakes for a while +after publishing any new key. +(The exact durations for these are set via +[a set of network parameters](../param-spec.md#onion-key-rotation-days).) + +There are two current kinds of circuit extension keys: + +- <span id="ntor">`KP_ntor`, `KS_ntor`</span>: + A curve25519 key + used for the [`ntor`](./create-created-cells.md#ntor) + and [`ntorv3`](./create-created-cells.md#ntor-v3) + circuit extension handshakes. + +- <span id="onion_tap">`KP_onion_tap`, `KS_onion_tap`</span>: + A 1024 bit RSA key + used for the obsolete [`TAP`](./create-created-cells.md#ntor) + circuit extension handshake. + + +## Channel authentication {#auth} + +There are other keys that relays use to authenticate +as part of their [channel negotiation handshakes](./channels.md). + +These keys are authenticated with other, longer lived keys. +Relays MAY rotate them as often as they like, +and SHOULD rotate them frequently—typically, at least once a day. + +- <span id="link_ed">`KP_link_ed`, `KS_link_ed`</span>. + A short-term Ed25519 "link authentication" key, used to authenticate + the link handshake: see + ["Negotiating and initializing channels"](./negotiating-channels.md#negotiating). + This key is signed by the "signing" key, and should be regenerated frequently. + +### Legacy channel authentication {#auth-legacy} + +These key types were used in +[older versions](./obsolete-channels.md) +of the channel negotiation handshakes. + +- <span id="legacy_linkauth_rsa">`KP_legacy_linkauth_rsa`, `KS_legacy_linkauth_rsa`</span>: + A 1024-bit RSA key, used to authenticate the link handshake. + (No longer used in modern Tor.) + It played a role similar to `KP_link_ed`. + + +As a convenience, to describe legacy versions of the link handshake, +we give a name to the public key used for the TLS handshake itself: + +- <span id="legacy_conn_tls">`KP_legacy_conn_tls`, `KS_legacy_conn_tls`</span>: + A short term key used to for TLS connections. + (No longer used in modern Tor.) + This was another name for the server's TLS key, + which at the time was required to be an RSA key. + It was used in some legacy handshake versions. diff --git a/spec/tor-spec/remote-hostname-lookup.md b/spec/tor-spec/remote-hostname-lookup.md new file mode 100644 index 0000000..2793411 --- /dev/null +++ b/spec/tor-spec/remote-hostname-lookup.md @@ -0,0 +1,43 @@ +<a id="tor-spec.txt-6.4"></a> + +# Remote hostname lookup + +To find the address associated with a hostname, the OP sends a +RELAY_RESOLVE message containing the hostname to be resolved with a NUL +terminating byte. (For a reverse lookup, the OP sends a RELAY_RESOLVE +message containing an in-addr.arpa address.) The OR replies with a +RELAY_RESOLVED message containing any number of answers. Each answer is +of the form: + +```text + Type (1 octet) + Length (1 octet) + Value (variable-width) + TTL (4 octets) + "Length" is the length of the Value field. + "Type" is one of: + + 0x00 -- Hostname + 0x04 -- IPv4 address + 0x06 -- IPv6 address + 0xF0 -- Error, transient + 0xF1 -- Error, nontransient + + If any answer has a type of 'Error', then no other answer may be + given. + + The 'Value' field encodes the answer: + IP addresses are given in network order. + Hostnames are given in standard DNS order ("www.example.com") + and not NUL-terminated. + The content of Errors is currently ignored. Relays currently + set it to the string "Error resolving hostname" with no + terminating NUL. Implementations MUST ignore this value. + + For backward compatibility, if there are any IPv4 answers, one of those + must be given as the first answer. + + The RELAY_RESOLVE messge must use a nonzero, distinct streamID; the + corresponding RELAY_RESOLVED message must use the same streamID. No stream + is actually created by the OR when resolving the name. +``` diff --git a/spec/tor-spec/routing-relay-cells.md b/spec/tor-spec/routing-relay-cells.md new file mode 100644 index 0000000..66d5625 --- /dev/null +++ b/spec/tor-spec/routing-relay-cells.md @@ -0,0 +1,99 @@ +<a id="tor-spec.txt-5.5"></a> + +# Routing relay cells{#routing-relay-cells} + +<a id="tor-spec.txt-5.5.1"></a> + +## Circuit ID Checks + +When a node wants to send a RELAY or RELAY_EARLY cell, it checks the cell's +circID and determines whether the corresponding circuit along that +connection is still open. If not, the node drops the cell. + +When a node receives a RELAY or RELAY_EARLY cell, it checks the cell's +circID and determines whether it has a corresponding circuit along +that connection. If not, the node drops the cell. + +> Here and elsewhere, we refer to RELAY and RELAY_EARLY cells +> collectively as "relay cells". + +<a id="tor-spec.txt-5.5.2"></a> + +## Forward Direction + +The forward direction is the direction that CREATE/CREATE2 cells +are sent. + +<a id="tor-spec.txt-5.5.2.1"></a> + +### Routing from the Origin + +When a relay cell is sent from an OP, the OP encrypts the cell's body +with the stream cipher as follows: + +```text +OP sends relay cell: + For I=N...1, where N is the destination node: + Encrypt with Kf_I. + Transmit the encrypted cell to node 1. +``` + +<a id="tor-spec.txt-5.5.2.2"></a> + +### Relaying Forward at Onion Routers + +When a forward relay cell is received by an OR, it decrypts the cell's body +with the stream cipher, as follows: + +```text +'Forward' relay cell: + Use Kf as key; decrypt. +``` + +The OR then decides whether it recognizes the relay cell, by +inspecting the cell as described in [Relay cells](./relay-cells.md#relay-cells). If the OR +recognizes the cell, it processes the contents of the relay cell. +Otherwise, it passes the decrypted relay cell along the circuit if +the circuit continues. If the OR at the end of the circuit +encounters an unrecognized relay cell, an error has occurred: the OR +sends a DESTROY cell to tear down the circuit. + +For more information, see +[Application connections and stream management](./streams.md#application-connections-and-stream-management). + +<a id="tor-spec.txt-5.5.3"></a> + +## Backward Direction + +The backward direction is the opposite direction from +CREATE/CREATE2 cells. + +<a id="tor-spec.txt-5.5.3.1"></a> + +### Relaying Backward at Onion Routers + +When a backward relay cell is received by an OR, it encrypts the cell's body +with the stream cipher, as follows: + +```text +'Backward' relay cell: + Use Kb as key; encrypt. +``` + +<a id="tor-spec.txt-5.5.3"></a> + +## Routing to the Origin + +When a relay cell arrives at an OP, the OP decrypts the cell's body +with the stream cipher as follows: + +```text +OP receives relay cell from node 1: + For I=1...N, where N is the final node on the circuit: + Decrypt with Kb_I. + If the cell is recognized (see [1]), then: + The sending node is I. + Stop and process the cell. +``` + +\[1\]: ["Relay cells"](./relay-cells.md#relay-cells) diff --git a/spec/tor-spec/setting-circuit-keys.md b/spec/tor-spec/setting-circuit-keys.md new file mode 100644 index 0000000..200862f --- /dev/null +++ b/spec/tor-spec/setting-circuit-keys.md @@ -0,0 +1,62 @@ +<a id="tor-spec.txt-5.2"></a> + +# Setting circuit keys{#setting-circuit-keys} + +<a id="tor-spec.txt-5.2.1"></a> + +## KDF-TOR{#kdf-tor} + +This key derivation function is used by the TAP and CREATE_FAST +handshakes, and in the current hidden service protocol. It shouldn't +be used for new functionality. + +If the TAP handshake is used to extend a circuit, both parties +base their key material on K0=g^xy, represented as a big-endian unsigned +integer. + +If CREATE_FAST is used, both parties base their key material on +K0=X|Y. + +From the base key material K0, they compute KEY_LEN*2+HASH_LEN*3 bytes of +derivative key data as + +K = H(K0 | \[00\]) | H(K0 | \[01\]) | H(K0 | \[02\]) | ... + +The first HASH_LEN bytes of K form KH; the next HASH_LEN form the forward +digest Df; the next HASH_LEN 41-60 form the backward digest Db; the next +KEY_LEN 61-76 form Kf, and the final KEY_LEN form Kb. Excess bytes from K +are discarded. + +KH is used in the handshake response to demonstrate knowledge of the +computed shared key. Df is used to seed the integrity-checking hash +for the stream of data going from the OP to the OR, and Db seeds the +integrity-checking hash for the data stream from the OR to the OP. Kf +is used to encrypt the stream of data going from the OP to the OR, and +Kb is used to encrypt the stream of data going from the OR to the OP. + +<a id="tor-spec.txt-5.2.2"></a> + +## KDF-RFC5869{#kdf-rfc5869} + +For newer KDF needs, Tor uses the key derivation function HKDF from +RFC5869, instantiated with SHA256. (This is due to a construction +from Krawczyk.) The generated key material is: + +K = K_1 | K_2 | K_3 | ... + +```text + Where H(x,t) is HMAC_SHA256 with value x and key t + and K_1 = H(m_expand | INT8(1) , KEY_SEED ) + and K_(i+1) = H(K_i | m_expand | INT8(i+1) , KEY_SEED ) + and m_expand is an arbitrarily chosen value, + and INT8(i) is a octet with the value "i". +``` + +In RFC5869's vocabulary, this is HKDF-SHA256 with info == m_expand, +salt == t_key, and IKM == secret_input. + +When used in the ntor handshake, the first HASH_LEN bytes form the +forward digest Df; the next HASH_LEN form the backward digest Db; the +next KEY_LEN form Kf, the next KEY_LEN form Kb, and the final +DIGEST_LEN bytes are taken as a nonce to use in the place of KH in the +hidden service protocol. Excess bytes from K are discarded. diff --git a/spec/tor-spec/streams.md b/spec/tor-spec/streams.md new file mode 100644 index 0000000..4d96048 --- /dev/null +++ b/spec/tor-spec/streams.md @@ -0,0 +1,7 @@ +<a id="tor-spec.txt-6"></a> + +# Application connections and stream management{#application-connections-and-stream-management} + +This section describes how clients use relay messages to communicate with +exit nodes, and how use this communication channel to send and receive +application data. diff --git a/spec/tor-spec/subprotocol-versioning.md b/spec/tor-spec/subprotocol-versioning.md new file mode 100644 index 0000000..5f43c71 --- /dev/null +++ b/spec/tor-spec/subprotocol-versioning.md @@ -0,0 +1,321 @@ +<a id="tor-spec.txt-9"></a> + +# Subprotocol versioning + +This section specifies the Tor subprotocol versioning. They are broken down +into different types with their current version numbers. Any new version +number should be added to this section. + +The dir-spec.txt details how those versions are encoded. See the +"proto"/"pr" line in a descriptor and the "recommended-relay-protocols", +"required-relay-protocols", "recommended-client-protocols" and +"required-client-protocols" lines in the vote/consensus format. + +Here are the rules a relay and client should follow when encountering a +protocol list in the consensus: + + - When a relay lacks a protocol listed in recommended-relay-protocols, + it should warn its operator that the relay is obsolete. + + - When a relay lacks a protocol listed in required-relay-protocols, it + should warn its operator as above. If the consensus is newer than the + date when the software was released or scheduled for release, it must + not attempt to join the network. + + - When a client lacks a protocol listed in recommended-client-protocols, + it should warn the user that the client is obsolete. + + - When a client lacks a protocol listed in required-client-protocols, + it should warn the user as above. If the consensus is newer than the + date when the software was released, it must not connect to the + network. This implements a "safe forward shutdown" mechanism for + zombie clients. + + - If a client or relay has a cached consensus telling it that a given + protocol is required, and it does not implement that protocol, it + SHOULD NOT try to fetch a newer consensus. + +Software release dates SHOULD be automatically updated as part of the +release process, to prevent forgetting to move them forward. Software +release dates MAY be manually adjusted by maintainers if necessary. + +Starting in version 0.2.9.4-alpha, the initial required protocols for +clients that we will Recommend and Require are: + +```text +Cons=1-2 Desc=1-2 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=4 +LinkAuth=1 Microdesc=1-2 Relay=2 +``` + +For relays we will Require: + +```text +Cons=1 Desc=1 DirCache=1 HSDir=1 HSIntro=3 HSRend=1 Link=3-4 +LinkAuth=1 Microdesc=1 Relay=1-2 +``` + +For relays, we will additionally Recommend all protocols which we +recommend for clients. + +<a id="tor-spec.txt-9.1"></a> + +## "Link" + +The "link" protocols are those used by clients and relays to initiate and +receive OR connections and to handle cells on OR connections. The "link" +protocol versions correspond 1:1 to those versions. + +Two Tor instances can make a connection to each other only if they have at +least one link protocol in common. + +The current "link" versions are: "1" through "5". See +[Negotiating versions with VERSIONS cells](./negotiating-channels.md#VERSIONS-cells) for more +information. All current Tor versions support "1-3"; versions from +0.2.4.11-alpha and on support "1-4"; versions from 0.3.1.1-alpha and on +support "1-5". Eventually we will drop "1" and "2". + +<a id="tor-spec.txt-9.2"></a> + +## "LinkAuth" {#link-auth} + +LinkAuth protocols correspond to varieties of AUTHENTICATE cells used for +the v3+ link protocols. + +Current versions are: + + * "1" is the RSA link authentication described in [Link authentication type 1: RSA-SHA256-TLSSecret](./obsolete-channels.md#RSA-SHA256-TLSSecret). + + * "2" is unused, and reserved by [proposal 244]. + + * "3" is the ed25519 link authentication described in [Link authentication type 3: Ed25519-SHA256-RFC5705](./negotiating-channels.md#Ed25519-SHA256-RFC5705). + +<a id="tor-spec.txt-9.3"></a> + +## "Relay" + +The "relay" protocols are those used to handle CREATE/CREATE2 +cells, and those that handle the various relay messages received +after a CREATE/CREATE2 cell. (Except, relay cells used to manage +introduction and rendezvous points are managed with the "HSIntro" +and "HSRend" protocols respectively.) + +Current versions are as follows. + + * "1" -- supports the TAP key exchange, with all features in Tor 0.2.3. + Support for CREATE and CREATED and CREATE_FAST and CREATED_FAST + and EXTEND and EXTENDED. + + * "2" -- supports the ntor key exchange, and all features in Tor + 0.2.4.19. Includes support for CREATE2 and CREATED2 and + EXTEND2 and EXTENDED2. + + Relay=2 has limited IPv6 support: + + * Clients might not include IPv6 ORPorts in EXTEND2 messages. + * Relays (and bridges) might not initiate IPv6 connections in + response to EXTEND2 messages containing IPv6 ORPorts, even if they + are configured with an IPv6 ORPort. + + However, relays support accepting inbound connections to their IPv6 + ORPorts. And they might extend circuits via authenticated IPv6 + connections to other relays. + + * "3" -- relays support extending over IPv6 connections in response to an + EXTEND2 message containing an IPv6 ORPort. + + Bridges might not extend over IPv6, because they try to imitate + client behaviour. + + A successful IPv6 extend requires: + * Relay subprotocol version 3 (or later) on the extending relay, + * an IPv6 ORPort on the extending relay, + * an IPv6 ORPort for the accepting relay in the EXTEND2 message, and + * an IPv6 ORPort on the accepting relay. + (Because different tor instances can have different views of the + network, these checks should be done when the path is selected. + Extending relays should only check local IPv6 information, before + attempting the extend.) + + When relays receive an EXTEND2 message containing both an IPv4 and an + IPv6 ORPort, and there is no existing authenticated connection with + the target relay, the extending relay may choose between IPv4 and + IPv6 at random. The extending relay might not try the other address, + if the first connection fails. + + As is the case with other subprotocol versions, tor advertises, + recommends, or requires support for this protocol version, regardless + of its current configuration. + + In particular: + * relays without an IPv6 ORPort, and + * tor instances that are not relays, + have the following behaviour, regardless of their configuration: + * advertise support for "Relay=3" in their descriptor + (if they are a relay, bridge, or directory authority), and + * react to consensuses recommending or requiring support for + "Relay=3". + + This subprotocol version is described in + [proposal 311], and implemented in Tor 0.4.5.1-alpha. + + * "4" -- support the ntorv3 (version 3) key exchange and all features in + 0.4.7.3-alpha. This adds a new CREATE2 cell type. See [proposal 332] + and [The "ntor-v3" handshake](./create-created-cells.md#ntor-v3) for more details. + + * "5" -- \[RESERVED\] support the ntorv3 subprotocol request extension + ([proposal 346]) + allowing a client to request what features to be used on a circuit. + +<a id="tor-spec.txt-9.4"></a> + +## "HSIntro" {#HSIntro} + +The "HSIntro" protocol handles introduction points. + + * "3" -- supports authentication as of [proposal 121] in Tor 0.2.1.6-alpha. + + * "4" -- support ed25519 authentication keys which is defined by the HS v3 + protocol as part of [proposal 224] in Tor 0.3.0.4-alpha. + + * "5" -- support ESTABLISH_INTRO message DoS parameters extension for onion + service version 3 only in Tor 0.4.2.1-alpha. + +<a id="tor-spec.txt-9.5"></a> + +## "HSRend" + +The "HSRend" protocol handles rendezvous points. + + * "1" -- supports all features in Tor 0.0.6. + + * "2" -- supports RENDEZVOUS2 messages of arbitrary length as long as they + have 20 bytes of cookie in Tor 0.2.9.1-alpha. + +<a id="tor-spec.txt-9.6"></a> + +## "HSDir" + +The "HSDir" protocols are the set of hidden service document types that can +be uploaded to, understood by, and downloaded from a tor relay, and the set +of URLs available to fetch them. + + * "1" -- supports all features in Tor 0.2.0.10-alpha. + + * "2" -- support ed25519 blinded keys request which is defined by the HS v3 + protocol as part of [proposal 224] in Tor 0.3.0.4-alpha. + +<a id="tor-spec.txt-9.7"></a> + +## "DirCache" + +The "DirCache" protocols are the set of documents available for download +from a directory cache via BEGIN_DIR, and the set of URLs available to +fetch them. (This excludes URLs for hidden service objects.) + + * "1" -- supports all features in Tor 0.2.4.19. + + * "2" -- adds support for consensus diffs in Tor 0.3.1.1-alpha. + +<a id="tor-spec.txt-9.8"></a> + +## "Desc" + +Describes features present or absent in descriptors. + +Most features in descriptors don't require a "Desc" update -- only those +that need to someday be required. For example, someday clients will need +to understand ed25519 identities. + + * "1" -- supports all features in Tor 0.2.4.19. + + * "2" -- cross-signing with onion-keys, signing with ed25519 +identities. + +<a id="tor-spec.txt-9.9"></a> + +## "Microdesc" + +Describes features present or absent in microdescriptors. + +Most features in descriptors don't require a "MicroDesc" update -- only +those that need to someday be required. These correspond more or less with +consensus methods. + + * "1" -- consensus methods 9 through 20. + + * "2" -- consensus method 21 (adds ed25519 keys to microdescs). + +<a id="tor-spec.txt-9.10"></a> + +## "Cons" + +Describes features present or absent in consensus documents. + +Most features in consensus documents don't require a "Cons" update -- only +those that need to someday be required. + +These correspond more or less with consensus methods. + + * "1" -- consensus methods 9 through 20. + + * "2" -- consensus method 21 (adds ed25519 keys to microdescs). + +<a id="tor-spec.txt-9.11"></a> + +## "Padding" + +Describes the padding capabilities of the relay. + + * "1" -- \[DEFUNCT\] Relay supports circuit-level padding. This version MUST NOT + be used as it was also enabled in relays that don't actually support + circuit-level padding. Advertised by Tor versions from + tor-0.4.0.1-alpha and only up to and including tor-0.4.1.4-rc. + + * "2" -- Relay supports the HS circuit setup padding machines ([proposal 302]). + Advertised by Tor versions from tor-0.4.1.5 and onwards. + +<a id="tor-spec.txt-9.12"></a> + +## "FlowCtrl" + +Describes the flow control protocol at the circuit and stream level. If +there is no FlowCtrl advertised, tor supports the unauthenticated flow +control features (version 0). + + * "1" -- supports authenticated circuit level SENDMEs as of [proposal 289] in + Tor 0.4.1.1-alpha. + + * "2" -- supports congestion control by the Exits which implies a new SENDME + format and algorithm. See [proposal 324] for more details. Advertised + in tor 0.4.7.3-alpha. + +## "Conflux" + +Describes the communications mechanisms used to bundle circuits together, +in order to split traffic across multiple paths. + +> TODO: This is not yet described here. For details see +> [proposal 329]. + +<a id="tor-spec.txt-9.13"></a> + +## "Datagram" + +Describes the UDP protocol capabilities of a relay. + + * "1" -- \[RESERVED\] supports UDP by an Exit as in the relay command + CONNECT_UDP, CONNECTED_UDP and DATAGRAM. See [proposal 339] for more details. + (Not yet advertised, reserved) + +[proposal 121]: ../proposals/121-hidden-service-authentication.txt +[proposal 224]: ../proposals/224-rend-spec-ng.txt +[proposal 244]: ../proposals/244-use-rfc5705-for-tls-binding.txt +[proposal 289]: ../proposals/289-authenticated-sendmes.txt +[proposal 302]: ../proposals/302-padding-machines-for-onion-clients.txt +[proposal 311]: ../proposals/311-relay-ipv6-reachability.txt +[proposal 324]: ../proposals/324-rtt-congestion-control.txt +[proposal 329]: ../proposals/329-traffic-splitting.txt +[proposal 332]: ../proposals/332-ntor-v3-with-extra-data.md +[proposal 339]: ../proposals/339-udp-over-tor.md +[proposal 346]: ../proposals/346-protovers-again.md + diff --git a/spec/tor-spec/tearing-down-circuits.md b/spec/tor-spec/tearing-down-circuits.md new file mode 100644 index 0000000..3fde693 --- /dev/null +++ b/spec/tor-spec/tearing-down-circuits.md @@ -0,0 +1,108 @@ +<a id="tor-spec.txt-5.4"></a> + +# Tearing down circuits{#tearing-down-circuits} + +Circuits are torn down when an unrecoverable error occurs along +the circuit, or when all streams on a circuit are closed and the +circuit's intended lifetime is over. + +ORs SHOULD also tear down circuits which attempt to create: + +- streams with RELAY_BEGIN, or +- rendezvous points with ESTABLISH_RENDEZVOUS, + ending at the first hop. Letting Tor be used as a single hop proxy makes + exit and rendezvous nodes a more attractive target for compromise. + +ORs MAY use multiple methods to check if they are the first hop: + +```text + * If an OR sees a circuit created with CREATE_FAST, the OR is sure to be + the first hop of a circuit. + * If an OR is the responder, and the initiator: + * did not authenticate the link, or + * authenticated with a key that is not in the consensus, + then the OR is probably the first hop of a circuit (or the second hop of + a circuit via a bridge relay). + + Circuits may be torn down either completely or hop-by-hop. +``` + +To tear down a circuit completely, an OR or OP sends a DESTROY +cell to the adjacent nodes on that circuit, using the appropriate +direction's circID. + +Upon receiving an outgoing DESTROY cell, an OR frees resources +associated with the corresponding circuit. If it's not the end of +the circuit, it sends a DESTROY cell for that circuit to the next OR +in the circuit. If the node is the end of the circuit, then it tears +down any associated edge connections (see +[Calculating the 'Digest' field](./relay-cells.md#digest-field)). + +After a DESTROY cell has been processed, an OR ignores all data or +DESTROY cells for the corresponding circuit. + +To tear down part of a circuit, the OP may send a RELAY_TRUNCATE message +signaling a given OR (Stream ID zero). That OR sends a DESTROY +cell to the next node in the circuit, and replies to the OP with a +RELAY_TRUNCATED message. + +\[Note: If an OR receives a TRUNCATE message and it has any relay cells +still queued on the circuit for the next node it will drop them +without sending them. This is not considered conformant behavior, +but it probably won't get fixed until a later version of Tor. Thus, +clients SHOULD NOT send a TRUNCATE message to a node running any current +version of Tor if a) they have sent relay cells through that node, +and b) they aren't sure whether those cells have been sent on yet.\] + +```text + When an unrecoverable error occurs along one a circuit, the nodes + must report it as follows: + * If possible, send a DESTROY cell to ORs _away_ from the client. + * If possible, send *either* a DESTROY cell towards the client, or + a RELAY_TRUNCATED cell towards the client. +``` + +Current versions of Tor do not reuse truncated RELAY_TRUNCATED +circuits: An OP, upon receiving a RELAY_TRUNCATED, will send +forward a DESTROY cell in order to entirely tear down the circuit. +Because of this, we recommend that relays should send DESTROY +towards the client, not RELAY_TRUNCATED. + +```text + NOTE: + In tor versions before 0.4.5.13, 0.4.6.11 and 0.4.7.9, relays would + handle an inbound DESTROY by sending the client a RELAY_TRUNCATED + message. Beginning with those versions, relays now propagate + DESTROY cells in either direction, in order to tell every + intermediary ORs to stop queuing data on the circuit. The earlier + behavior created queuing pressure on the intermediary ORs. +``` + +The body of a DESTROY cell or RELAY_TRUNCATED message contains a single +octet, describing the reason that the circuit was +closed. RELAY_TRUNCATED message, and DESTROY cells sent \_towards the +client, should contain the actual reason from the list of error codes +below. Reasons in DESTROY cell SHOULD NOT be propagated downward or +upward, due to potential side channel risk: An OR receiving a DESTROY +command should use the DESTROYED reason for its next cell. An OP +should always use the NONE reason for its own DESTROY cells. + +The error codes are: + +```text + 0 -- NONE (No reason given.) + 1 -- PROTOCOL (Tor protocol violation.) + 2 -- INTERNAL (Internal error.) + 3 -- REQUESTED (A client sent a TRUNCATE command.) + 4 -- HIBERNATING (Not currently operating; trying to save bandwidth.) + 5 -- RESOURCELIMIT (Out of memory, sockets, or circuit IDs.) + 6 -- CONNECTFAILED (Unable to reach relay.) + 7 -- OR_IDENTITY (Connected to relay, but its OR identity was not + as expected.) + 8 -- CHANNEL_CLOSED (The OR connection that was carrying this circuit + died.) + 9 -- FINISHED (The circuit has expired for being dirty or old.) + 10 -- TIMEOUT (Circuit construction took too long) + 11 -- DESTROYED (The circuit was destroyed w/o client TRUNCATE) + 12 -- NOSUCHSERVICE (Request for unknown hidden service) +``` |