aboutsummaryrefslogtreecommitdiff
path: root/spec/tor-spec
diff options
context:
space:
mode:
Diffstat (limited to 'spec/tor-spec')
-rw-r--r--spec/tor-spec/cell-packet-format.md196
-rw-r--r--spec/tor-spec/channels.md91
-rw-r--r--spec/tor-spec/circuit-management.md6
-rw-r--r--spec/tor-spec/closing-streams.md100
-rw-r--r--spec/tor-spec/create-created-cells.md620
-rw-r--r--spec/tor-spec/creating-circuits.md102
-rw-r--r--spec/tor-spec/flow-control.md199
-rw-r--r--spec/tor-spec/index.md12
-rw-r--r--spec/tor-spec/negotiating-channels.md516
-rw-r--r--spec/tor-spec/obsolete-channels.md269
-rw-r--r--spec/tor-spec/opening-streams.md141
-rw-r--r--spec/tor-spec/preliminaries.md142
-rw-r--r--spec/tor-spec/relay-cells.md219
-rw-r--r--spec/tor-spec/relay-early.md20
-rw-r--r--spec/tor-spec/relay-keys.md175
-rw-r--r--spec/tor-spec/remote-hostname-lookup.md43
-rw-r--r--spec/tor-spec/routing-relay-cells.md99
-rw-r--r--spec/tor-spec/setting-circuit-keys.md62
-rw-r--r--spec/tor-spec/streams.md7
-rw-r--r--spec/tor-spec/subprotocol-versioning.md321
-rw-r--r--spec/tor-spec/tearing-down-circuits.md108
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)
+```