aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--proposals/000-index.txt2
-rw-r--r--proposals/339-udp-over-tor.md2
-rw-r--r--proposals/340-packed-and-fragmented.md111
-rw-r--r--proposals/346-protovers-again.md5
-rw-r--r--proposals/349-command-state-validation.md666
-rw-r--r--proposals/BY_INDEX.md1
-rw-r--r--proposals/BY_STATUS.md1
-rw-r--r--proposals/SUMMARY.md1
-rw-r--r--spec/control-spec/replies.md8
-rw-r--r--spec/glossary.md13
-rw-r--r--spec/hspow-spec/v1-equix.md4
-rw-r--r--spec/padding-spec/circuit-level-padding.md2
-rw-r--r--spec/rend-spec/hsdesc-encrypt.md16
-rw-r--r--spec/rend-spec/introduction-protocol.md131
-rw-r--r--spec/rend-spec/protocol-overview.md13
-rw-r--r--spec/rend-spec/rendezvous-protocol.md4
-rw-r--r--spec/tor-spec/cell-packet-format.md26
-rw-r--r--spec/tor-spec/closing-streams.md2
-rw-r--r--spec/tor-spec/create-created-cells.md16
-rw-r--r--spec/tor-spec/creating-circuits.md6
-rw-r--r--spec/tor-spec/flow-control.md8
-rw-r--r--spec/tor-spec/negotiating-channels.md8
-rw-r--r--spec/tor-spec/opening-streams.md18
-rw-r--r--spec/tor-spec/preliminaries.md6
-rw-r--r--spec/tor-spec/relay-cells.md118
-rw-r--r--spec/tor-spec/routing-relay-cells.md14
-rw-r--r--spec/tor-spec/tearing-down-circuits.md2
27 files changed, 982 insertions, 222 deletions
diff --git a/proposals/000-index.txt b/proposals/000-index.txt
index 8c9668f..7e37484 100644
--- a/proposals/000-index.txt
+++ b/proposals/000-index.txt
@@ -270,6 +270,7 @@ Proposals by number:
346 Clarifying and extending the use of protocol versioning [OPEN]
347 Domain separation for certificate signing keys [OPEN]
348 UDP Application Support in Tor [OPEN]
+349 Client-Side Command Acceptance Validation [DRAFT]
Proposals by status:
@@ -279,6 +280,7 @@ Proposals by status:
316 FlashFlow: A Secure Speed Test for Tor (Parent Proposal)
331 Res tokens: Anonymous Credentials for Onion Service DoS Resilience
342 Decoupling hs_interval and SRV lifetime
+ 349 Client-Side Command Acceptance Validation
NEEDS-REVISION:
212 Increase Acceptable Consensus Age [for 0.2.4.x+]
219 Support for full DNS and DNSSEC resolution in Tor [for 0.2.5.x]
diff --git a/proposals/339-udp-over-tor.md b/proposals/339-udp-over-tor.md
index 12de0c6..e5235d1 100644
--- a/proposals/339-udp-over-tor.md
+++ b/proposals/339-udp-over-tor.md
@@ -11,7 +11,7 @@ Status: Accepted
Tor currently only supports delivering two kinds of traffic to the
internet: TCP data streams, and a certain limited subset of DNS
requests. This proposal describes a plan to extend the Tor protocol so
-that exit relays can also relay UDP traffic to the network?.
+that exit relays can also relay UDP traffic to the network.
Why would we want to do this? There are important protocols that use
UDP, and in order to support users that rely on these protocols, we'll
diff --git a/proposals/340-packed-and-fragmented.md b/proposals/340-packed-and-fragmented.md
index da0cbdb..2407f99 100644
--- a/proposals/340-packed-and-fragmented.md
+++ b/proposals/340-packed-and-fragmented.md
@@ -22,6 +22,9 @@ between messages and cells, for two reasons:
(notably `SENDME`, `XON`, `XOFF`, and several types from
[proposal 329](./329-traffic-splitting.txt)) are much smaller than
the relay cell size, and could be sent comparatively often.
+ We also want to be able to *hide* the transmission of small control messages
+ by packing them into what would have been the padding of other messages,
+ making them effectively invisible to a network traffic observer.
In this proposal, we describe a way to decouple relay cells from relay
messages. Relay messages can now be packed into multiple cells or split
@@ -65,7 +68,7 @@ If we are lucky, we won't have to build this encryption at all, and we
can just move to some version of GCM-UIV or other RPRP that reserves 16
bytes for an authentication tag or similar cryptographic object.
-The `body` MUST contain exactly 493 bytes as cells have a fixed size.
+The `body` MUST contain exactly 493 bytes as relay cells have a fixed size.
## New relay message packing
@@ -94,14 +97,16 @@ The following message types take required stream IDs: `BEGIN`, `DATA`, `END`,
The following message types from proposal 339 (UDP) take required stream IDs:
`CONNECT_UDP`, `CONNECTED_UDP` and `DATAGRAM`.
-No other message types take stream IDs. The `stream_id` field, when present,
-MUST NOT be zero.
+No other current message types take stream IDs. The `stream_id` field, when
+present, MUST NOT be zero.
Messages can be split across relay cells; multiple messages can occur in
a single relay cell. We enforce the following rules:
* Headers may not be split across cells.
* If a 0 byte follows a message body, there are no more messages.
+ * A message body is permitted to end at exactly the end of a relay cell,
+ without a 0 byte afterwards.
* A relay cell may not be "empty": it must have at least some part of
some message.
@@ -116,40 +121,41 @@ Receivers MUST validate that the cell `header` and the `message header` are
well-formed and have valid lengths while handling the cell in which the header
is encoded. If any of them is invalid, the circuit MUST be destroyed.
-An unrecognized `command` is considered invalid and thus MUST result in the
-circuit being immediately destroyed.
+A message header with an unrecognized `command` is considered invalid and thus
+MUST result in the circuit being immediately destroyed (without waiting for the
+rest of the relay message to arrive, in the case of a fragmented message).
-## Negotiation (OBSOLETE)
+## New subprotocol `RelayCell`
-> We do not want to do it this way. Instead, we want to use the system
-> described in the forthcoming proposal, "xxx-protovers-again.md".
+We introduce a new subprotocol `RelayCell` to specify the relay cell ABI. The
+new format specified in this proposal, supporting packing and fragmentation,
+corresponds to `RelayCell` version 1. The ABI prior to this proposal is
+`RelayCell` version 0.
-This message format requires a new `Relay` subprotocol version to indicate
-support. If a client wants to indicate support for this format, it sends the
-following extension as part of its `ntor3` handshake:
+All clients and relays implicitly support `RelayCell` version 0.
- EXT_FIELD_TYPE:
+> XXX: Do we want to consider some migration path for eventually removing
+> support for `RelayCell` version 0? e.g. maybe this should be something like
+> "Support for any of `Relay` versions 1-5 imply support for `RelayCell`
+> version 0"?
- [03] -- Packed and Fragmented Cell Request
+We reserve the protocol ID 13 for binary encoding of this subprotocol with
+respect to [proposal 346][prop346] and [proposal 323][prop323].
-This field is zero payload length. Its presence signifies that the client
-wants to use packed and fragmented cells on the circuit.
+To use `RelayCell` version 1 or greater with a given relay on a given circuit,
+the client negotiates it using an `ntor_v3` extension, as per [proposal
+346][prop346]. This implies that the relay must advertise support for `Relay`
+version 5 (`ntor_v3` circuit extensions) as well as the target `RelayCell`
+version (1 for the format introduced in this proposal).
-The Exit side ntorv3 response payload is encoded as:
-
- EXT_FIELD_TYPE:
-
- [04] -- Packed and Fragmented Cell Response
-
-Again, the extension presence indicates to the client that the Exit has
-acknowledged the feature and is ready to use it. If the extension is not
-present, the client MUST not use the packed and fragmented feature even though
-the Exit has advertised the correct protover.
-
-The client MUST reject the handshake and thus close the circuit if:
-
- - The response extension is seen for a non-ntorv3 handshake.
- - The response extension is seen but no request was made initially.
+Circuits using mixed `RelayCell` versions are permitted. e.g. we anticipate
+some of the use-cases for packing and fragmentation to only need the exit-relay
+to support it. Not requiring `RelayCell=1` for other relays in the circuit
+provides a larger pool of candidate relays. While an intermediate relay using a
+different `RelayCell` version than the destination relay of a given relay cell
+will look at the wrong bytes for the `recognized` and `digest` fields, they
+will reach the correct conclusion that the cell is not intended for them and
+pass it to the next hop in the circuit.
## Migration
@@ -181,6 +187,23 @@ there is, then it adds a DATA message to the end of the current cell,
with as much data as possible. Otherwise, the client sends the cell
with no packed data.
+> XXX: This isn't quite right. What was actually implemented in tor, and
+> what we want in arti, is to defer sending some "control" messages like
+> confluence switch and (non-first) xon, until they can be invisibly packed
+> into a cell for a DATA message.
+>
+> dgoulet: Could you update this section with the concrete details, and exactly
+> what property we're trying to achieve? e.g.:
+>
+> If we have data to send, but the corresponding DATA messages don't leave
+> enough room to pack in the deferred control message(s), what do we do? If we
+> continue deferring could we end up deferring forever if the application
+> always writes in chunks that happen to align this way?
+>
+> Since cells containing any part of a DATA message is subject to congestion
+> windows, does that mean if our congestion window is empty we can't send these
+> control messages either (until the window becomes non-empty)?
+
## Onion services
Negotiating this for onion services will happen in a separate proposal;
@@ -259,7 +282,7 @@ follows:
accommodates most reasonable MTU choices)
Any increase in maximum length for any other message type requires a new
-Relay subprotocol version. (For example, if we later want to allow
+`RelayCell` subprotocol version. (For example, if we later want to allow
EXTEND2 messages to be 2000 bytes long, we need to add a new proposal
saying so, and reserving a new subprotocol version.)
@@ -288,7 +311,27 @@ Here is an example of the simplest case: one message, sent in one relay cell:
random [464 bytes]
```
-Total of 514 bytes which is the absolute maximum cell size.
+Total of 514 bytes which is the absolute maximum relay cell size.
+
+A message whose body ends at exactly the end of a relay cell has no
+corresponding end-of-messages marker.
+
+```
+ Cell 1:
+ header:
+ circid .. [4 bytes]
+ command RELAY [1 byte]
+ relay cell header:
+ recognized 0 [2 bytes]
+ digest (...) [14 bytes]
+ message header:
+ command DATA [1 byte]
+ length 488 [2 bytes]
+ message routing header:
+ stream_id 42 [2 bytes]
+ message body:
+ (data) [488 bytes]
+```
Here's an example with fragmentation only: a large EXTEND2 message split
across two relay cells.
@@ -320,7 +363,6 @@ across two relay cells.
0 [1 byte]
padding up to end of cell:
random [182 bytes]
-
```
Each cells are 514 bytes for a message body totalling 800 bytes.
@@ -428,3 +470,6 @@ what parties need to accept.)
padding up to end of cell:
random [241 bytes]
```
+
+[prop323]: ./323-walking-onions-full.md "Specification for Walking Onions"
+[prop346]: ./346-protovers-again.md "Clarifying and extending the use of protocol versioning"
diff --git a/proposals/346-protovers-again.md b/proposals/346-protovers-again.md
index a18e238..a5c7e24 100644
--- a/proposals/346-protovers-again.md
+++ b/proposals/346-protovers-again.md
@@ -93,7 +93,8 @@ ordered in the same way as in tor-spec.
| Padding | 10 |
| FlowCtrl | 11 |
| Conflux | 12 |
-| Datagram | 13 |
+| RelayCell| 13 |
+| Datagram | TBD|
> Note: This is the same encoding used in [walking onions proposal][prop323].
> It takes its order from the ordering of protocol versions in
@@ -172,7 +173,7 @@ Currently specified subprotocol versions which can be negotiated using
this extension are:
* FlowCtrl=2 (congestion control)
- * Packed-and-fragmented support (proposal 340)
+ * RelayCell=1 (proposal 340)
The availability of the `subproto_request` extension itself
will be indicated by a new Relay=X flag. When used, it will supplant
diff --git a/proposals/349-command-state-validation.md b/proposals/349-command-state-validation.md
new file mode 100644
index 0000000..47598e6
--- /dev/null
+++ b/proposals/349-command-state-validation.md
@@ -0,0 +1,666 @@
+```
+Filename: 349-command-state-validation.md
+Title: Client-Side Command Acceptance Validation
+Author: Mike Perry
+Created: 2023-08-17
+Status: Draft
+```
+
+# Introduction
+
+The ability of relays to inject end-to-end relay cells that are ignored by
+clients allows malicious relays to create a covert channel to verify that they
+are present in multiple positions of a path. This covert channel allows a
+Guard to deanonymize 100% of its traffic, or just all the traffic of a
+particular client IP address.
+
+This attack was first documented in [DROPMARK]. Proposal 344 describes the
+severity of this attack, and how this kind of end-to-end covert channel leads
+to full deanonymization, in a reliable way, in practice. (Recall that dropped
+cell attacks are most severe when an adversary can inject arbitrary end-to-end
+data patterns at times when the circuit is known to be idle, before it is used
+for traffic; injection at this point enables path bias attacks which can
+ensure that only malicious Guard+Exit relays are present in all circuits used
+by a particular target client IP address. For further details, see Proposal
+344.)
+
+This proposal is targeting arti-client, not C-Tor. This proposal is specific
+to client-side checks of relay cells and relay messages. Its primary change to
+behavior is the definition of state machines that enforce what relay message
+commands are acceptable on a given circuit, and when.
+
+By applying and enforcing these state machine rules, we prevent the end-to-end
+transmission of arbitrary amounts of data, and ensure that predictable periods
+of the protocol are happening as expected, and not filled with side channel
+packet patterns.
+
+
+
+## Overview of dropped cell types
+
+Dropped cells are cells that a relay can inject that end up ignored and
+discarded by a Tor client.
+
+These include:
+ 1. Unparsable cells
+ 2. invalid relay commands
+ 3. Unrecognized cells (ie: wrong source hop, or decrypt failures)
+ 4. unsupported (or consensus-disabled) relay commands or extensions
+ 5. out-of-context relay commands
+ 6. duplicate relay commands
+ 7. relay commands that hit any error codepaths
+ 8. relay commands for an invalid or already-closed stream ID
+ 9. semantically void relay cells (incl relay data len == 0, or PING)
+ 10. onion descriptor-appended junk
+
+Items 1-4 and 8 are handled by the existing relay command parsers in arti. In
+these cases, arti closes the circuit already.
+
+> XXX: Arti's relay parser is lazy; see https://gitlab.torproject.org/tpo/core/arti/-/merge_requests/1978
+> Does this mean that individual components need to properly propagate error
+> information in order for circuits to get closed, when a command does not
+> parse?
+
+The state machines of this proposal handle 5-7 in a rigorous way. (In many
+cases of out-of-context relay cells, arti already closes the circuit;
+our goal here is to centralize this validation so that we can ensure that
+it is not possible for any relay commands to omit checks or allow unbounded
+activity.)
+
+> XXX: Does arti allow extra onion-descriptor junk to be appended after the
+> descriptor signature? C-Tor does...
+
+
+# Architectural Patterns and Behavior
+
+Ideally, the handling of invalid protocol behavior should be centralized,
+so that validation can happen in one easy-to-audit place, rather than spread
+across the codebase (as it currently is with C-Tor).
+
+For some narrow cases of invalid protocol activity, this is trivial. The relay
+command acceptance is centralized in arti, which allows arti to immediately
+reject unknown or disabled relay commands. This kind of validation is
+necessary, but not sufficient, in order to prevent dropped cell vectors.
+
+Things quickly get complicated when handling parsable relay cells sent during
+an inappropriate time, or other activity such as duplicate relay commands,
+semantically void cells, or commands that would hit an error condition, or
+lazy parsing failure, deep in the code and be silently accepted without
+closing the circuit.
+
+To handle such cases, we propose adding a relay command message state machine
+pattern. Each relay protocol, when it becomes active on a circuit, must
+register a state machine that handles validating its messages.
+
+Because multiple relay protocols can be active at a time, multiple validation
+state machines can be attached to a circuit. This also allows protocols to
+create their own validation without needing to modify the entire validation
+process. Relay messages that are not accepted by any active protocol
+validation handler MUST result in circuit close.
+
+
+## Architectural Patterns
+
+In order to handle these cases, we rely on some architectural patterns:
+ 1. No relay message command may be sent to the client unless it is unless
+ explicitly allowed by the specification, advertised as supported, and
+ negotiated on a particular channel or circuit. (Prop#346)
+ 2. Any relay commands or extension fields not successfully negotiated
+ on a circuit are invalid. This includes cells from intermediate hops,
+ which must also negotiate their use (example: padding machine
+ negotiation to middles).
+ 3. By following the above principles, state machines can be developed
+ that govern when a relay command is acceptable. This covers the
+ majority of protocol activity. See Section 3.
+ 4. For some commands, additional checks must be performed by using
+ context of the protocol itself.
+
+The following relay commands require additional module state to enforce
+limitations, beyond what is known by a state machine, for #4:
+ - RELAY_COMMAND_SENDME
+ - Requires checking that the auth digest hash is accurate
+ - RELAY_COMMAND_XOFF and RELAY_COMMAND_XON
+ - Context and rate limiting is stream-dependent
+ - Packing enforcement via prop#340 is context-dependent
+ - RELAY_COMMAND_CONFLUX_SWITCH
+ - Packing enforcement via prop#340 is context-dependent
+ - RELAY_COMMAND_DROP:
+ - This can only be accepted from a hop if there is a padding
+ machine at that hop.
+ - RELAY_COMMAND_INTRODUCE2
+ - Requires inspecting replay cache (however, circuits should not get
+ closed because replays can come from the client)
+
+## Behavior
+
+When an invalid relay cell or relay message is encountered, the corresponding
+circuit should be immediately closed.
+
+Initially, this can be accomplished by sending a DESTROY cell to the Guard
+relay.
+
+Additionally, when closing circuits in this way, clients must take care not to
+allow cases of adversarially-induced infinite circuit creation in non-onion
+service protocols that are not protected by Vanguards/Vanguards-lite, by
+limiting the number of retries they perform. (One such example of this is a
+malicious conflux exit that repeatedly kills only one leg by injecting dropped
+cells to close the circuit.)
+
+While we also specify some cases where the channel to the Guard should be
+closed, this is not necessary in the general case.
+
+> XXX: I can't think of any issues severe enough to actually warrant the
+> following, but Florentin pointed it out as a possibility: A malicious Guard
+> may withhold the DESTROY, and still allow full identifier transmission before
+> the circuit is closed. While this does not directly allow full deanonymization
+> because the client won't actually use the circuit, it may still be enough to
+> make the vector useful for other attacks. For completeness against this
+> vector, we may want to consider sending a new RELAY_DESTROY command to the
+> middle node, such that it has responsibility for tearing down a circuit by
+> sending its own DESTROYS in both directions, and then have the client send its
+> own DESTROY if the client does not get a DESTROY from the Guard.
+> >>> See torspec#220: https://gitlab.torproject.org/tpo/core/torspec/-/issues/220
+
+
+
+# State machine descriptions
+
+These state machines apply only at the client. (There is no information leak
+from extra cells in the protocol on the relay side, so we will not be specifying
+relay-side enforcement, or implementing it for C-Tor.)
+
+There are multiple state machines, describing particular circuit purposes
+and/or components of the Tor relay protocol.
+
+Each state machine has a "Trigger", and a "Message Scope". The "Trigger" is
+the condition, relay command, or action that causes the state machine to get
+added to a circuit's command state validator set. The Message Scope is where the state
+machine applies: to specific a hop number, stream ID, or both.
+
+A circuit can have multiple state machines attached at one time.
+ * If no state machine accepts a relay command, then the circuit MUST be
+ closed.
+ * When we say "receive X" we mean "receive a _valid_ cell of
+ type X". If the cell is invalid, we MUST kill the circuit
+
+## Relay message handlers
+
+The state machines process enveloped relay message commands. Ie, with respect
+to prop#340, they operate on the message bodies, with associated stream ID.
+
+With respect to Proposal #340, the calls to state machine validation would go
+after converting cells to messages, but before parsing the message body
+itself, to still minimize exposure of the parser attack surfaces.
+
+> XXX: Again, some validation will require early parsing, not lazy parsing
+
+There are multiple relay message handlers that can be registered with each
+circuit ID, for a specific hop on that circuit ID, depending on the protocols
+that are in use on that circuit with that hop, as well as the streams to that
+hop.
+
+Each handler has a Message Scope, that acts as a filter such that only relay
+command messages from this scope are processed by that handler.
+
+If a message is not accepted by any active handler, the circuit MUST be
+closed.
+
+
+### Base Handler
+
+Purpose: This handler validates commands for circuit construction and
+circuit-level SENDME activity.
+
+Trigger: Creation of a circuit; ntor handhshake success for a hop
+
+Message Scope: The circuit ID and hop number must match for this handler to
+apply. (Because of leaky pipes, each hop of the circuit has a base handler
+added when that hop completes an ntor handshake and is added to the circuit.)
+
+```text
+START:
+ Upon sending EXTEND:
+ Enter EXTEND_SENT.
+
+ Receive SENDME:
+ Ensure expected auth digest matches; close circuit otherwise
+ No transition.
+
+EXTEND_SENT:
+ Receiving EXTENDED:
+ Enter START.
+
+ Receive SENDME:
+ Ensure expected auth digest matches; close circuit otherwise
+ No transition.
+```
+
+### Client Introducing Handler
+
+Purpose: Circuits used by clients to connect to a service introduction point
+have this handler attached.
+
+Trigger: Usage of a circuit for client introduction
+
+Message Scope: Circuit ID and hop number must match
+
+```text
+CLIENT_INTRO_START:
+ Upon sending INTRODUCE1:
+ Enter CLIENT_INTRO_WAIT
+
+CLIENT_INTRO_WAIT
+ Receieve INTRODUCE_ACK:
+ Accept
+ Transition to CLIENT_INTRO_END
+
+CLIENT_INTRO_END:
+ No transitions possible
+ - XXX: Enforce that no new handlers can be added? We may still have padding
+ handlers though.
+```
+
+
+### Service Introduce Handler
+
+Purpose: Service-side onion service introduction circuits have this handler
+attached.
+
+Trigger: Onion service establishing an introduction point circuit
+
+Message Scope: Circuit ID and hop number must match
+
+```text
+SERVICE_INTRO_START:
+ Upon sending ESTABLISH_INTRO:
+ Enter SERVICE_INTRO_ESTABLISH
+
+SERVICE_INTRO_ESTABLISH:
+ Receiving INTRO_ESTABLISHED:
+ Enter SERVICE_INTRO_ESTABLISHED
+
+SERVICE_INTRO_ESTABLISHED:
+ Receiving INTRODUCE2
+ Accept
+```
+
+
+### Client Rendezvous Handler
+
+Purpose: Circuits used by clients to build a rendezvous point have this handler
+attached.
+
+Trigger: Client rendezvous initiation
+
+Message Scope: Circuit ID and hop number must match
+
+```text
+CLIENT_REND_START:
+ Upon Sending RENDEZVOUS1:
+ Enter CLIENT_REND_WAIT
+
+CLIENT_REND_WAIT:
+ Receive RENDEZVOUS2:
+ Enter CLIENT_REND_ESTABLISHED
+
+CLIENT_REND_ESTABLISHED:
+ Remain in this state; launch TCP, UDP, or Conflux handlers for streams
+```
+
+
+### Service Rendezvous Handler
+
+Purpose: Circuits used by services to connect to a rendezvous point have this
+handler attached.
+
+Trigger: Incoming introduce cell/service rend initiation
+
+Message Scope: Circuit ID and hop number must match
+
+```text
+SERVICE_REND_START:
+ Upon sending ESTABLISH_RENDEZVOUS:
+ Enter SERVICE_REND_WAIT
+
+SERVICE_REND_WAIT:
+ Receive RENDEZVOUS_ESTABLISHED:
+ Enter SERVICE_REND_ESTABLISHED
+
+SERVICE_REND_ESTABLISHED:
+ Remain in this state; launch TCP, UDP, or Conflux handlers for streams
+```
+
+
+### CircPad Handler
+
+Purpose: Circuit-level padding is negotiated with a particular hop in the
+circuit; when it is negotiated, we need to allow padding cells from that hop.
+
+Trigger: Negotiation of a circuit padding machine
+
+Message Scope: Circuit ID and hop must match; padding machine must be active
+
+```text
+PADDING_START:
+ Upon sending PADDING_NEGOTIATE:
+ Enter PADDING_NEGOTIATING
+
+PADDING_NEGOTIATING:
+ Receiving PADDING_NEGOTIATED:
+ Enter PADDING_ACTIVE
+
+PADDING_ACTIVE:
+ Receiving DROP:
+ Accept (if from correct hop)
+ - XXX: We could perform more sophisticated rate limiting accounting here
+ too?
+```
+
+### Resolve Stream Handler
+
+Purpose: This handler is created on circuits when a resolve happens.
+
+Trigger: RESOLVE message
+
+Message Scope: Circuit ID, stream ID, and hop number must all match
+
+```text
+RESOLVE_START:
+ Send a RESOLVE message:
+ Enter RESOLVE_SENT
+
+RESOLVE_SENT:
+ Receive a RESOLVED or an END:
+ Enter RESOLVE_START.
+```
+
+
+### TCP Stream handler
+
+Purpose: This handler is created when the client creates a new stream ID, using either
+BEGIN or BEGIN_DIR.
+
+Trigger: New AP or DirConn stream
+
+Message Scope: Circuit ID, stream ID, and hop number must all match; stream ID
+must be open or half-open (half-open is END_SENT).
+
+```text
+TCP_STREAM_START:
+ Send a BEGIN or BEGIN_DIR message:
+ Enter BEGIN_SENT.
+
+BEGIN_SENT:
+ Receive an END:
+ Enter TCP_STREAM_START.
+ Receive a CONNECTED:
+ Enter STREAM_OPEN.
+
+STREAM_OPEN:
+ Receive DATA:
+ Verify length is > 0
+ XXX: Handle [HSDIRINFLATION] here?
+ Process.
+
+ Receive XOFF:
+ Enter STREAM_XOFF
+
+ Send END:
+ Enter END_SENT.
+
+ Receive END:
+ Enter TCP_STREAM_START
+
+STREAM_XOFF:
+ Receive DATA:
+ Verify length is > 0
+ XXX: Handle [HSDIRINFLATION] here?
+ Process.
+
+ Send END:
+ Enter END_SENT.
+
+ Receive XON:
+ Enter STREAM_XON
+
+ Receive END:
+ Enter TCP_STREAM_START
+
+STREAM_XON:
+ Receive DATA:
+ Verify length is > 0
+ XXX: Handle [HSDIRINFLATION] here?
+ Process.
+
+ Receive XOFF:
+ If prop#340 is enabled, verify packed with SENDME
+ Enter STREAM_XOFF
+
+ Receive XON:
+ If prop#340 is enabled, verify packed with SENDME
+ Verify rate has changed
+
+ Send END:
+ Enter END_SENT.
+
+ Receive END:
+ Enter TCP_STREAM_START
+
+END_SENT:
+ Same as STREAM_OPEN, except do not actually deliver data.
+ Only remain in this state for one RTT_max, or until END_ACK.
+```
+
+
+### Conflux Handler
+
+Purpose: Circuits that are a part of a conflux set have a conflux handler, associated
+with the last hop.
+
+Trigger: Creation of a conflux set
+
+Message Scope: Circuit ID and hop number must match
+ - XXX: Linked circuits must accept stream ids from either circuit for other
+ handlers :/
+
+```text
+CONFLUX_START: (all conflux leg circuits start here)
+ Upon sending CONFLUX_LINK:
+ Enter CONFLUX_LINKING
+
+CONFLUX_LINKING:
+ Receiving CONFLUX_LINKED:
+ Send CONFLUX_LINKED_ACK
+ Enter CONFLUX_LINKED
+
+CONFLUX_LINKED:
+ Receiving CONFLUX_SWITCH:
+ If prop#340 is negotiated, ensure packed with a DATA cell
+```
+
+
+### UDP Stream Handler
+
+Purpose: Circuits that are using prop#339
+
+Trigger: UDP stream creation
+
+Message Scope: Circuit ID, hop number, and stream-id must match
+
+```text
+UDP_STREAM_START:
+ If no other udp streams used on circuit:
+ Send CONNECT_UDP for any stream, enter UDP_CONNECTING
+ else:
+ Immediately enter UDP_CONNECTING
+ (CONNECTED_UDP MAY arrive without a CONNECT_UDP, after the first UDP
+ stream on a circuit is established)
+
+UDP_CONNECTING:
+ Upon receipt of CONNECTED_UDP, enter UDP_CONNECTED
+
+UDP_CONNECTED:
+ Receive DATAGRAM:
+ Verify length > 0
+ Verify Prop#344 NAT rules are obeyed, including srcport and stream limits
+ Process.
+
+ Send END:
+ Enter UDP_END_SENT
+
+UDP_END_SENT:
+ Same as UDP_CONNECTED, except do not actually deliver data.
+ Only remain in this state for one RTT_max, or until END_ACK,
+ then transition to UDP_STREAM_START.
+```
+
+
+# HSDIR Inflation { #HSDIRINFLATION }
+
+XXX: This can be folded into the state machines and/or rend-spec.. The state
+machines should actually be able to handle this, once they are ready for it.
+
+One of the most common questions about dropped cells is "what about data cells
+with a 1 byte payload?". As Prop#344 makes clear, this is not a dropped cell
+attack, but is instead an instance of an Active Traffic Manipulation Covert
+Channel, described in Section 1.3.2. The lower severity of active traffic
+manipulation is due to the fact that it cannot be used to deanonymize 100% of
+a target client's circuits, where as the combination of path bias and
+pre-usage dropped cells can.
+
+However, there is one case where one can construct a potent attack from this
+Active Traffic Manipulation: by making use of onion service circuits being
+built on demand by an application. Further, because the onion service
+handshake is uniquely fingerprintable (see Section 1.2.1 of Prop#344), it is
+possible to use this vector in this specific case to encode an identifier in
+the timing and traffic patterns of the onion service descriptor download,
+similar to how the CMU attack operated, and use both the onion service
+fingerprint and descriptor traffic pattern to transmit the fact that a
+particular onion service was visited, to the Guard or possibly even a local
+network observer.
+
+A normal hidden service descriptor occupies only ~10 cells (with a hard max of
+30KB, or ~60 cells). This is not enough to reliably encode the full address of
+the onion service in a timing-based covert channel.
+
+However, there are two ways to cause this descriptor download to transmit
+enough data to encode such a covert channel, and replicate the CMU attack
+using timing information of this data.
+
+First, the actual descriptor payload can be spread across many DATA cells that
+are filled only partially with data (which does not happen if the HSDIR is
+honest and well-behaved, because it always has the full descriptor on hand).
+
+Second, in C-tor, additional junk can be appended at the end of a onion service
+descriptor document that does not count against the 30KB maximum, which the
+client will happily download and then ignore.
+
+Neither of these things are necessary to preserve, and neither can happen in
+normal operation. They can either be addressed directly by checks on
+HSDIR-based RELAY_COMMAND_DATA lengths and descriptor parsing, or by simply
+enforcing that circuits used to fetch service descriptors can *only* receive
+as many bytes as the maximum descriptor size, before being closed.
+
+XXX: Consider RELAY_COMMAND_END_ACK also..
+ - https://gitlab.torproject.org/tpo/core/torspec/-/issues/196
+
+XXX: Tickets to grovel through for other stuff:
+https://gitlab.torproject.org/tpo/core/torspec/-/issues/38
+https://gitlab.torproject.org/tpo/core/torspec/-/issues/39
+https://gitlab.torproject.org/tpo/core/arti/-/issues/525
+
+
+# Command Allowlist enumeration { #CTORALLOWLIST }
+
+XXX: We are planning to remove this section after we finish the state
+machines; keeping it for reference until then for cross-checking.
+
+Formerly, in C-Tor, we took the approach of performing a series of checks for
+each message command, ad-hoc. Here's those rules, for spot-checking that the
+above state machines cover them.
+
+All relay commands are rejected by clients and serviced unless a rule says
+they are OK.
+
+Here's a list of those rules, by relay command:
+
+ - RELAY_COMMAND_DATA 2
+ - This command MUST only arrive for valid open or half-open stream ID
+ - This command MUST have data length > 0
+ - On HSDIR circuits, ONLY ONE command is allowed to have a non-full
+ payload (the last command). See Section 4.
+
+ - RELAY_COMMAND_END 3
+ - This command MUST only arrive ONCE for each valid open or half-open
+ stream ID
+
+ - RELAY_COMMAND_CONNECTED 4
+ - This command MUST ONLY be accepted ONCE by clients if they sent a BEGIN
+ or BEGIN_DIR
+ - The stream ID MUST match the stream ID from BEGIN (or BEGIN_DIR)
+
+ - RELAY_COMMAND_DROP 10
+ - This command is accepted by clients from any hop that they
+ have negotiated an active circuit padding machine with
+
+ - RELAY_COMMAND_CONFLUX_LINKED 20
+ - Ensure that a LINK cell was sent to the hop that sent this
+ - Ensure that no previous LINKED cell has arrived on this circuit
+
+ - RELAY_COMMAND_CONFLUX_SWITCH 22
+ - Ensure that conflux is enabled and linked
+ - If Prop#340 is in use, this cell MUST be packed with a valid
+ multiplexed RELAY_COMMAND_DATA cell.
+
+ - RELAY_COMMAND_INTRODUCE2 35
+ - Services MUST check:
+ - The intro is for a valid service identity and auth
+ - The command has a valid sub-credential
+ - The command is not a replay (possibly not close circuit?)
+
+ - RELAY_COMMAND_RENDEZVOUS2 37
+ - This command MUST ONLY arrive ONCE in response to a sent REND1 cell,
+ on the appropriate circuit
+ - The ntor handshake must succeed with MAC validation
+
+ - RELAY_COMMAND_INTRO_ESTABLISHED 38
+ - Services MUST check:
+ - This cell MUST ONLY come ONCE in response to
+ RELAY_COMMAND_ESTABLISH_INTRO, for the appropriate service identity
+
+ - RELAY_COMMAND_RENDEZVOUS_ESTABLISHED 39
+ - This command MUST ONLY be accepted ONCE in response to
+ RELAY_COMMAND_ESTABLISH_RENDEZVOUS
+
+ - RELAY_COMMAND_INTRODUCE_ACK 40
+ - This command MUST ONLY be accepted ONCE by clients, in response to
+ RELAY_COMMAND_INTRODUCE1
+
+ - RELAY_COMMAND_PADDING_NEGOTIATED 42
+ - This command MUST ONLY be accepted by clients in response to
+ PADDING_NEGOTIATE
+
+ - RELAY_COMMAND_XOFF 43
+ - Ensure that congestion control is enabled and negotiated
+ - Ensure that the stream id is either opened or half-open
+ - Ensure that the stream id is in "XON" state
+
+ - RELAY_COMMAND_XON 44
+ - Ensure that congestion control is enabled and negotiated
+ - Ensure that the stream id is either opened or half-open
+ - Enforce always packing this to a SENDME with Prop#340?
+
+ - RELAY_COMMAND_CONNECTED_UDP
+ - The stream id in this command MUST match that from
+ RELAY_COMMAND_CONNECT_UDP
+ - This command is only accepted once per UDP stream id
+
+ - RELAY_COMMAND_DATAGRAM
+ - This command MUST only arrive for valid open or half-open stream ID
+ - This command MUST have data length > 0
+
+
+
+References:
+
+[DROPMARK]: https://petsymposium.org/2018/files/papers/issue2/popets-2018-0011.pdf
diff --git a/proposals/BY_INDEX.md b/proposals/BY_INDEX.md
index a8f1ac4..96e52b0 100644
--- a/proposals/BY_INDEX.md
+++ b/proposals/BY_INDEX.md
@@ -266,4 +266,5 @@ Below are a list of proposals sorted by their proposal number. See
* [`346-protovers-again.md`](/proposals/346-protovers-again.md): Clarifying and extending the use of protocol versioning \[OPEN\]
* [`347-domain-separation.md`](/proposals/347-domain-separation.md): Domain separation for certificate signing keys \[OPEN\]
* [`348-udp-app-support.md`](/proposals/348-udp-app-support.md): UDP Application Support in Tor \[OPEN\]
+* [`349-command-state-validation.md`](/proposals/349-command-state-validation.md): Client-Side Command Acceptance Validation \[DRAFT\]
diff --git a/proposals/BY_STATUS.md b/proposals/BY_STATUS.md
index 0c265c2..84345ac 100644
--- a/proposals/BY_STATUS.md
+++ b/proposals/BY_STATUS.md
@@ -103,6 +103,7 @@ discussion.
* [`316-flashflow.md`](/proposals/316-flashflow.md): FlashFlow: A Secure Speed Test for Tor (Parent Proposal)
* [`331-res-tokens-for-anti-dos.md`](/proposals/331-res-tokens-for-anti-dos.md): Res tokens: Anonymous Credentials for Onion Service DoS Resilience
* [`342-decouple-hs-interval.md`](/proposals/342-decouple-hs-interval.md): Decoupling hs_interval and SRV lifetime
+* [`349-command-state-validation.md`](/proposals/349-command-state-validation.md): Client-Side Command Acceptance Validation
## NEEDS-REVISION proposals: ideas that we can't implement as-is
diff --git a/proposals/SUMMARY.md b/proposals/SUMMARY.md
index df02273..09e1270 100644
--- a/proposals/SUMMARY.md
+++ b/proposals/SUMMARY.md
@@ -259,6 +259,7 @@
- [`346-protovers-again`](./346-protovers-again.md): Clarifying and extending the use of protocol versioning (OPEN)
- [`347-domain-separation`](./347-domain-separation.md): Domain separation for certificate signing keys (OPEN)
- [`348-udp-app-support`](./348-udp-app-support.md): UDP Application Support in Tor (OPEN)
+ - [`349-command-state-validation`](./349-command-state-validation.md): Client-Side Command Acceptance Validation (DRAFT)
diff --git a/spec/control-spec/replies.md b/spec/control-spec/replies.md
index 6fce9b1..ed76cbd 100644
--- a/spec/control-spec/replies.md
+++ b/spec/control-spec/replies.md
@@ -1445,9 +1445,11 @@ dropped cells, and ignored cells (such as padding cells). These
values include the relay headers, but not circuit headers.
Circuit data that has been validated and processed by Tor is further
-broken down into two categories: delivered payloads and overhead.
-DeliveredBytesRead and DeliveredBytesWritten are the total relay cell
-payloads transmitted since the last CIRC_BW event, not counting relay
+broken down into two categories: delivered relay message bodies,
+and overhead.
+DeliveredBytesRead and DeliveredBytesWritten are the total
+length of the relay message bodies
+transmitted since the last CIRC_BW event, not counting relay
cell headers or circuit headers. OverheadBytesRead and
OverheadBytesWritten are the extra unused bytes at the end of each
cell in order for it to be the fixed CELL_LEN bytes long.
diff --git a/spec/glossary.md b/spec/glossary.md
index aa68699..5f45f7f 100644
--- a/spec/glossary.md
+++ b/spec/glossary.md
@@ -199,14 +199,19 @@ CREATED cell: Second part of a handshake, sent by the responder.
EXTEND message: (also known as a RELAY_EXTEND message) First part of a
handshake, tunneled through an existing circuit. The last relay
-in the circuit so far will decrypt this cell and send the
-payload in a CREATED cell to the chosen next hop relay.
+in the circuit so far will process this message by
+decoding it,
+and sending the appropriate handshake
+in a CREATED cell to the client's chosen next-hop relay.
EXTENDED cell: (also known as a RELAY_EXTENDED message) Second part
of a handshake, tunneled through an existing circuit. The last
relay in the circuit so far receives the CREATED cell from the
-new last hop relay and encrypts the payload in an EXTENDED message
-to tunnel back to the client.
+new last-hop relay,
+encodes that cell's body in in an EXTENDED message,
+and uses a RELAY cell to deliver the message back to the client.
+Upon receiving the EXTENDED message,
+the client's circuit is one hop longer.
Onion skin: The body of a CREATE/CREATE2 cell or an EXTEND/EXTEND2 message.
It contains the first part of the TAP or ntor key establishment
diff --git a/spec/hspow-spec/v1-equix.md b/spec/hspow-spec/v1-equix.md
index 025af48..f49086a 100644
--- a/spec/hspow-spec/v1-equix.md
+++ b/spec/hspow-spec/v1-equix.md
@@ -1,4 +1,4 @@
-# Onion service proof-of-work: Version 1, Equi-X and Blake2b
+# Onion service proof-of-work: Scheme v1, Equi-X and Blake2b
## Implementations {#implementations}
@@ -82,7 +82,7 @@ Thus the effort is communicated explicitly in our protocol, and it forms part of
## Parameter descriptor {#parameter-descriptor}
This whole protocol starts with the service encoding its parameters in a `pow-params` line within the 'encrypted' (inner) part of the v3 descriptor. The [second layer plaintext format](../rend-spec/hsdesc-encrypt.md#second-layer-plaintext) describes it canonically. The parameters offered are:
-- `type`, always `v1` for the algorithm described here
+- `scheme`, always `v1` for the algorithm described here
- `seed-b64`, a periodically updated 32-byte random seed, base64 encoded
- `suggested-effort`, the latest output from the [service-side effort controller](./common-protocol.md#service-effort)
- `expiration-time`, a timestamp when we plan to replace the seed.
diff --git a/spec/padding-spec/circuit-level-padding.md b/spec/padding-spec/circuit-level-padding.md
index 85f9137..66caa2f 100644
--- a/spec/padding-spec/circuit-level-padding.md
+++ b/spec/padding-spec/circuit-level-padding.md
@@ -69,7 +69,7 @@ the circuit. It is used to disambiguate shutdown requests.
When a relay receives a PADDING_NEGOTIATE message, it checks that it supports
the requested machine, and sends a PADDING_NEGOTIATED message, which is formatted
-in the data payload of a relay cell with command number 42 (see tor-spec.txt
+in the body of a relay message with command number 42 (see tor-spec.txt
section 6.1), as follows:
```text
diff --git a/spec/rend-spec/hsdesc-encrypt.md b/spec/rend-spec/hsdesc-encrypt.md
index 3e91172..3d2117e 100644
--- a/spec/rend-spec/hsdesc-encrypt.md
+++ b/spec/rend-spec/hsdesc-encrypt.md
@@ -252,21 +252,25 @@ list of intro points etc. The plaintext has the following format:
```
```text
- "pow-params" SP type SP seed-b64 SP suggested-effort
+ "pow-params" SP scheme SP seed-b64 SP suggested-effort
SP expiration-time NL
- [At most once per "type"]
-
If present, this line provides parameters for an optional proof-of-work
client puzzle. A client that supports an offered scheme can include a
corresponding solution in its introduction request to improve priority
in the service's processing queue.
- Only version 1 is currently defined.
- Other versions may have a different format.
+ Only scheme `v1` is currently defined.
+ It may appear only once.
+
+ Unknown schemes found in a descriptor must be completely ignored:
+ future schemes might have a different format (in the parts of the
+ Item after the "scheme"; this could even include an Object); and
+ future schemes might allow repetition, and might appear in any order.
+
Introduced in tor-0.4.8.1-alpha.
- type: The type of PoW system used. We call the one specified here "v1".
+ scheme: The PoW system used. We call the one specified here "v1".
seed-b64: A random seed that should be used as the input to the PoW
hash function. Should be 32 random bytes encoded in base64
diff --git a/spec/rend-spec/introduction-protocol.md b/spec/rend-spec/introduction-protocol.md
index cb7debf..43c5638 100644
--- a/spec/rend-spec/introduction-protocol.md
+++ b/spec/rend-spec/introduction-protocol.md
@@ -185,7 +185,7 @@ and the introduction point should ignore the other parameter.
If the burst is lower than the rate,
the introduction point SHOULD ignore the extension.
-> Using this extension extends the payload of the ESTABLISH_INTRO message by 19
+> Using this extension extends the body of the ESTABLISH_INTRO message by 19
> bytes bringing it from 134 bytes to 155 bytes.
When this extension is not _sent_,
@@ -219,7 +219,7 @@ In this older protocol, an ESTABLISH_INTRO message contains:
KEY_LEN [2 bytes]
KEY [KEY_LEN bytes]
HANDSHAKE_AUTH [20 bytes]
- SIG [variable, up to end of relay payload]
+ SIG [variable, up to end of relay message body]
The KEY_LEN variable determines the length of the KEY field.
```
@@ -313,7 +313,7 @@ should be of the form:
EXT_FIELD_TYPE [1 byte]
EXT_FIELD_LEN [1 byte]
EXT_FIELD [EXT_FIELD_LEN bytes]
- ENCRYPTED [Up to end of relay payload]
+ ENCRYPTED [Up to end of relay message body]
```
The `ENCRYPTED` field is described in the \[PROCESS_INTRO2\] section.
@@ -341,51 +341,6 @@ client.)
The same rules for multiplicity, ordering, and handling unknown types
apply to the extension fields here as described \[EST_INTRO\] above.
-#### Proof-of-work extension to INTRODUCE1 {#INTRO1_POW_EXT}
-
-This extension can be used to optionally attach a proof of work to the introduction request.
-The proof must be calculated using unique parameters appropriate for this specific service.
-An acceptable proof will raise the priority of this introduction request according to the proof's verified computational effort.
-
-This is for the [proof-of-work DoS mitigation](../dos-spec/overview.md#hs-intro-pow), described in depth by the [Proof of Work for onion service introduction](../hspow-spec/index.md) specification.
-
-If used, it needs to be encoded within the N_EXTENSIONS field of the
-ESTABLISH_INTRO message defined in the previous section. The content is
-defined as follows:
-
-EXT_FIELD_TYPE:
-
-\[02\] -- `PROOF_OF_WORK`
-
-```text
-The EXT_FIELD content format is:
-
- POW_VERSION [1 byte]
- POW_NONCE [16 bytes]
- POW_EFFORT [4 bytes]
- POW_SEED [4 bytes]
- POW_SOLUTION [16 bytes]
-
-where:
-
-POW_VERSION is 1 for the protocol specified here
-POW_NONCE is the nonce value chosen by the client's solver
-POW_EFFORT is the effort value chosen by the client,
- as a 32-bit integer in network byte order
-POW_SEED identifies which seed was in use, by its first 4 bytes
-POW_SOLUTION is a matching proof computed by the client's solver
-```
-
-Only version 1 is currently defined.
-Other versions may have a different format.
-A correctly functioning client only submits solutions with a version and seed which were advertised by the server and have not yet expired.
-An extension with an unknown version or expired seed is suspicious and SHOULD result in introduction failure.
-
-This will increase the INTRODUCE1 payload size by 43 bytes since the extension type and length is 2 extra bytes, the N_EXTENSIONS field is always present and currently set to 0 and the EXT_FIELD is 41 bytes.
-According to ticket #33650, INTRODUCE1 messages currently have more than 200 bytes available.
-
-Introduced in tor-0.4.8.1-alpha.
-
<a id="rend-spec-v3.txt-3.2.2"></a>
### INTRODUCE_ACK message format. {#INTRO_ACK}
@@ -508,10 +463,22 @@ will have:
The same rules for multiplicity, ordering, and handling unknown types
apply to the extension fields here as described \[EST_INTRO\] above.
-### INTRODUCE1 Extensions
+### INTRODUCE1/INTRODUCE2 Extensions
The following sections details the currently supported or reserved extensions
-of an `INTRODUCE1` message.
+of an `INTRODUCE1`/`INTRODUCE2` message.
+
+Note that there are two sets of extensions in `INTRODUCE1`/`INTRODUCE2`:
+one in the top-level, unencrypted portion,
+and one within the plaintext of ENCRYPTED
+(ie, after RENDEZVOUS_COOKIE and before ONION_KEY_TYPE.
+
+The sets of extensions allowed in each part of the message are disjoint:
+each extension is valid in only *one* of the two places.
+
+Nevertheless, for historical reasons,
+both kinds of extension are listed in this section,
+and they use nonoverlapping values of `EXT_FIELD_TYPE`.
#### Congestion Control
@@ -522,51 +489,59 @@ configured with congestion control.
\[01\] -- Congestion Control Request.
-This field is has zero payload length. Its presence signifies that the client
+This field is has zero body length. Its presence signifies that the client
wants to use congestion control. The client MUST NOT set this field, or use
ntorv3, if the service did not list "2" in the `FlowCtrl` line in the
descriptor. The client SHOULD NOT provide this field if the consensus parameter
'cc_alg' is 0.
-The service MUST ignore any unknown fields.
+This appears in the ENCRYPTED section of the INTRODUCE1/INTRODUCE2 message.
-#### Proof-of-Work (PoW)
+#### Proof-of-Work (PoW) {#INTRO1_POW_EXT}
-This is used to send the work done by the client to the service.
+This extension can be used to optionally attach a proof of work to the introduction request.
+The proof must be calculated using unique parameters appropriate for this specific service.
+An acceptable proof will raise the priority of this introduction request according to the proof's verified computational effort.
- EXT_FIELD_TYPE:
+This is for the [proof-of-work DoS mitigation](../dos-spec/overview.md#hs-intro-pow), described in depth by the [Proof of Work for onion service introduction](../hspow-spec/index.md) specification.
- \[02\] -- Proof Of Work.
+This appears in the ENCRYPTED section of the INTRODUCE1/INTRODUCE2 message.
- EXT_FIELD content format is:
+The content is defined as follows:
- POW_VERSION [1 byte]
- POW_NONCE [16 bytes]
- POW_EFFORT [4 bytes]
- POW_SEED [4 bytes]
- POW_SOLUTION [16 bytes]
+EXT_FIELD_TYPE:
- where:
+\[02\] -- `PROOF_OF_WORK`
- POW_VERSION is 1 for the protocol specified in this proposal
- POW_NONCE is the nonce 'N' from the section above
- POW_EFFORT is the 32-bit integer effort value, in network byte order
- POW_SEED is the first 4 bytes of the seed used
+```text
+The EXT_FIELD content format is:
+ POW_SCHEME [1 byte]
+ POW_NONCE [16 bytes]
+ POW_EFFORT [4 bytes]
+ POW_SEED [4 bytes]
+ POW_SOLUTION [16 bytes]
+
+where:
-When a service receives an INTRODUCE1 with the extension, it should check its
-configuration on whether proof-of-work is enabled on the service. If it's not
-enabled, the extension SHOULD be ignored. If enabled, even if the suggested
-effort is currently zero, the service follows the procedure detailed in
-prop327.
+POW_SCHEME is 1 for the `v1` protocol specified here
+POW_NONCE is the nonce value chosen by the client's solver
+POW_EFFORT is the effort value chosen by the client,
+ as a 32-bit integer in network byte order
+POW_SEED identifies which seed was in use, by its first 4 bytes
+POW_SOLUTION is a matching proof computed by the client's solver
+```
-If the service requires the PROOF_OF_WORK extension but received an INTRODUCE1
-message without any embedded proof-of-work, the service SHOULD consider this message
-as a zero-effort introduction for the purposes of the priority queue (see
-section \[INTRO_QUEUE\] of prop327).
+Only SCHEME 1, `v1`, is currently defined.
+Other schemes may have a different format,
+after the POW_SCHEME byte.
+A correctly functioning client only submits solutions with a scheme and seed which were advertised by the server
+(using a "pow-params" Item in the
+[HS descriptor](hsdesc-encrypt.md#second-layer-plaintext))
+and have not yet expired.
+An extension with an unknown scheme or expired seed is suspicious and SHOULD result in introduction failure.
-(TODO: We should have a proof-of-work.md to fold in prop327. For now, just
-point to the proposal.)
+Introduced in tor-0.4.8.1-alpha.
#### Subprotocol Request
diff --git a/spec/rend-spec/protocol-overview.md b/spec/rend-spec/protocol-overview.md
index a50b3d1..9f7c96f 100644
--- a/spec/rend-spec/protocol-overview.md
+++ b/spec/rend-spec/protocol-overview.md
@@ -40,9 +40,16 @@ circuits, and the cryptographic handshake gives the two parties a
shared key and proves to the client that it is indeed talking to the
hidden service.
-Once the two circuits are joined, the client can use Tor RELAY cells
-to deliver relay messages
-to the server. RELAY_BEGIN messages open streams to an external process
+Once the two circuits are joined, the client can use Tor relay cells
+to deliver relay messages to the server:
+Whenever the rendezvous point receives as relay cell from one of
+the circuits, it transmits it to the other.
+(It accepts both RELAY and RELAY_EARLY cells,
+and retransmits them all as RELAY cells.)
+
+The two parties use these relay messages to implement Tor's
+usual application stream protocol:
+RELAY_BEGIN messages open streams to an external process
or processes configured by the server; RELAY_DATA messages are used to
communicate data on those streams, and so forth.
diff --git a/spec/rend-spec/rendezvous-protocol.md b/spec/rend-spec/rendezvous-protocol.md
index 2b14934..0f6d4e9 100644
--- a/spec/rend-spec/rendezvous-protocol.md
+++ b/spec/rend-spec/rendezvous-protocol.md
@@ -127,8 +127,8 @@ The behavior of ESTABLISH_RENDEZVOUS is unchanged from older versions
of this protocol, except that relays should now ignore unexpected
bytes at the end.
-Old versions of Tor required that RENDEZVOUS message payloads be exactly
-168 bytes long. All shorter rendezvous payloads should be padded to
+Old versions of Tor required that RENDEZVOUS message bodies be exactly
+168 bytes long. All shorter rendezvous bodies should be padded to
this length with random bytes, to make them difficult to distinguish from
older protocols at the rendezvous point.
diff --git a/spec/tor-spec/cell-packet-format.md b/spec/tor-spec/cell-packet-format.md
index 8f2174d..cfc7f36 100644
--- a/spec/tor-spec/cell-packet-format.md
+++ b/spec/tor-spec/cell-packet-format.md
@@ -27,7 +27,7 @@ since no version has yet been negotiated.
|-----------|-------------------|-------|
| `CircID` | [`CIRCID_LEN(v)`] | |
| `Command` | 1 | |
-| `Payload` | [`PAYLOAD_LEN`] | Padded to fit |
+| `Body` | [`CELL_BODY_LEN`] | Padded to fit |
The value of `CIRCID_LEN` depends on the negotiated link protocol.
@@ -41,10 +41,10 @@ A variable-length cell has this format:
| `CircID` | `CIRCID_LEN(v)` | |
| `Command` | 1 | |
| `Length` | 2 | A big-endian integer |
-| `Payload` | `Length` | |
+| `Body` | `Length` | |
[`CIRCID_LEN(v)`]: ./preliminaries.md#msg-len
-[`PAYLOAD_LEN`]: ./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
@@ -159,34 +159,38 @@ and MAY terminate the channel with an error.
> under the assumption that the command was sent
> by a more up-to-date version of Tor.
-## Interpreting the fields: Payload {#payload}
+## Interpreting the fields: Cell Body {#body}
-The interpretation of Payload depends on the cell's command.
+<!-- 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 payloads {#payload-padding}
+## 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 [`PAYLOAD_LEN`] bytes.
+is less than [`CELL_BODY_LEN`] bytes.
When this happens,
-the sender MUST fill the unused part of the payload
+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] cell payloads
+> [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 channel payload padding.
+> and does not interact with cell body padding.
Variable-length cells never have extra space,
-so there is no need to pad their payloads.
+so there is no need to pad their bodies.
Unless otherwise specified,
variable-length cells have no padding.
diff --git a/spec/tor-spec/closing-streams.md b/spec/tor-spec/closing-streams.md
index 6bbcaeb..1d65b6d 100644
--- a/spec/tor-spec/closing-streams.md
+++ b/spec/tor-spec/closing-streams.md
@@ -9,7 +9,7 @@ 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 payload of a RELAY_END message begins with a single 'reason' byte to
+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:
diff --git a/spec/tor-spec/create-created-cells.md b/spec/tor-spec/create-created-cells.md
index a9b7a12..3208909 100644
--- a/spec/tor-spec/create-created-cells.md
+++ b/spec/tor-spec/create-created-cells.md
@@ -123,7 +123,7 @@ randomly chosen CircID values are all in use (today's Tor stops after 64).
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.
-An EXTEND2 message's relay payload contains:
+The body of an EXTEND2 message contains:
| Field | Description | Size |
| ----- | ----------- | ---- |
@@ -155,7 +155,7 @@ For purposes of indistinguishability, implementations SHOULD send
these link specifiers, if using them, in this order: \[00\], \[02\], \[03\],
\[01\].
-The relay payload for an EXTEND relay message consists of:
+The body for an EXTEND relay message consists of:
| Field | Size
| ----- | ----
@@ -194,10 +194,10 @@ CREATE/CREATE2 cell from the contents of the EXTEND/EXTEND2 message.
See [Creating circuits](./creating-circuits.md#creating-circuits)
for details.
-The payload of an EXTENDED message is the same as the payload of a
+The body of an EXTENDED message is the same as the body of a
CREATED cell.
-The payload of an EXTENDED2 message is the same as the payload of a
+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.\]
@@ -228,7 +228,7 @@ 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 payload for a CREATE cell is an 'onion skin', which consists of
+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))
@@ -243,8 +243,8 @@ to the server's onion key, giving a client handshake:
| Symmetrically encrypted
| - Second part of `g^x` | `DH_LEN-(KP_ENC_LEN-KP_PAD_LEN-KEY_LEN)` bytes
-The payload for a CREATED cell, or the relay payload for an
-EXTENDED message, contains:
+The body for a CREATED cell, or the body for an
+EXTENDED relay message, contains:
| Field | Size
| ----- | ----
@@ -599,7 +599,7 @@ Currently supported extensions are:
* 1 -- `CC_FIELD_REQUEST` \[Client to server\]
- Contains an empty payload. Signifies that the client
+ Contains an empty body. Signifies that the client
wants to use the extended congestion control described
in [proposal 324].
diff --git a/spec/tor-spec/creating-circuits.md b/spec/tor-spec/creating-circuits.md
index 10e23b4..deb6b83 100644
--- a/spec/tor-spec/creating-circuits.md
+++ b/spec/tor-spec/creating-circuits.md
@@ -44,11 +44,11 @@ these steps:
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
-payload.
+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 payload. The initiating onion router chooses some circID not yet
+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))
@@ -69,7 +69,7 @@ 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 it payload
+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.
diff --git a/spec/tor-spec/flow-control.md b/spec/tor-spec/flow-control.md
index 8c3bcce..9ecc5da 100644
--- a/spec/tor-spec/flow-control.md
+++ b/spec/tor-spec/flow-control.md
@@ -34,7 +34,7 @@ information. See [proposal 111] for details.
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 payloads of PADDING cells, VPADDING cells, or DROP
+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).
@@ -146,7 +146,7 @@ version to emit and accept.
If a RELAY_SENDME version is received that is below the minimum accepted
version, the circuit should be closed.
-The RELAY_SENDME payload contains the following:
+The body of a RELAY_SENDME message contains the following:
```text
VERSION [1 byte]
@@ -157,7 +157,7 @@ The RELAY_SENDME payload contains the following:
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 payload should be ignored.
+0x00: The rest of the message should be ignored.
0x01: Authenticated SENDME. The DATA section MUST contain:
@@ -193,7 +193,7 @@ 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 cell payloads remaining to be flushed at that edge.
+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/negotiating-channels.md b/spec/tor-spec/negotiating-channels.md
index 4c1ae1c..571a1be 100644
--- a/spec/tor-spec/negotiating-channels.md
+++ b/spec/tor-spec/negotiating-channels.md
@@ -99,7 +99,7 @@ Once the TLS handshake is complete,
both parties send a VERSIONS cell
to negotiate which one they will use.
-The payload in a VERSIONS cell is a series of big-endian two-byte
+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
@@ -108,7 +108,7 @@ 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 payload contains an odd number of bytes).
+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
@@ -145,7 +145,7 @@ 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 payload format is:
+CERTS is a variable-length cell. Its body format is:
| Field | Size | Description |
| ----- | ---- | ------------------------------ |
@@ -441,7 +441,7 @@ To finish the handshake,
each party sends the other
a NETINFO cell.
-The cell's payload is:
+A NETINFO cell's body is:
| Field | Description | Size
| ----- | ----------- | ----
diff --git a/spec/tor-spec/opening-streams.md b/spec/tor-spec/opening-streams.md
index 8e63a62..81e1616 100644
--- a/spec/tor-spec/opening-streams.md
+++ b/spec/tor-spec/opening-streams.md
@@ -7,8 +7,8 @@
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 payload encoding the address
-and port of the destination host. The payload format is:
+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]
@@ -33,7 +33,7 @@ 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 payload.
+FLAGS, FLAGS is omitted from the message body.
```text
bit meaning
@@ -54,7 +54,7 @@ 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
-payload is in one of the following formats:
+body is in one of the following formats:
```text
The IPv4 address to which the connection was made [4 octets]
@@ -129,13 +129,13 @@ Directory servers may be:
If the Tor relay is not running a directory service, it should respond
with a REASON_NOTDIRECTORY RELAY_END message.
-Clients MUST generate an all-zero payload for RELAY_BEGIN_DIR message,
-and relays MUST ignore the payload.
+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 all-zero payload, and clients MUST ignore
-the payload.
+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
index e69d47e..15cacf3 100644
--- a/spec/tor-spec/preliminaries.md
+++ b/spec/tor-spec/preliminaries.md
@@ -47,13 +47,15 @@ for these, the link protocol is denoted in this table with `v`.
| Name | Length in bytes | Meaning |
| ---- | --------------- | ------- |
-| `PAYLOAD_LEN` | 509 | The longest payload for a [fixed-length cell](./cell-packet-format.md#fixed-length-cell). |
+| `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) + PAYLOAD_LEN`.
+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>
diff --git a/spec/tor-spec/relay-cells.md b/spec/tor-spec/relay-cells.md
index 346899b..f1f7997 100644
--- a/spec/tor-spec/relay-cells.md
+++ b/spec/tor-spec/relay-cells.md
@@ -13,7 +13,7 @@ End nodes that accept streams may be:
- directory servers (RELAY_BEGIN_DIR, anonymous or non-anonymous),
- onion services (RELAY_BEGIN, anonymous via a rendezvous point).
-The payload of each unencrypted relay cell consists of an
+The body of each unencrypted relay cell consists of an
enveloped relay message, encoded as follows:
| Field | Size
@@ -24,7 +24,7 @@ enveloped relay message, encoded as follows:
| Digest | 4 bytes
| Length | 2 bytes
| Data | Length bytes
-| Padding | PAYLOAD_LEN - 11 - 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
@@ -32,40 +32,82 @@ enveloped relay message, encoded as follows:
The relay commands are:
-| Command | Identifier | Direction | Control?
-| ------- | ---------- | --------- | --------
-| 1 | RELAY_BEGIN | forward |
-| 2 | RELAY_DATA | forward or backward |
-| 3 | RELAY_END | forward or backward |
-| 4 | RELAY_CONNECTED | backward |
-| 5 | RELAY_SENDME | forward or backward | sometimes control
-| 6 | RELAY_EXTEND | forward | control
-| 7 | RELAY_EXTENDED | backward | control
-| 8 | RELAY_TRUNCATE | forward | control
-| 9 | RELAY_TRUNCATED | backward | control
-| 10 | RELAY_DROP | forward or backward | control
-| 11 | RELAY_RESOLVE | forward |
-| 12 | RELAY_RESOLVED | backward |
-| 13 | RELAY_BEGIN_DIR | forward |
-| 14 | RELAY_EXTEND2 | forward | control
-| 15 | RELAY_EXTENDED2 | backward | control
-| 16..18 | Reserved for UDP; Not yet in use, see [prop339].
-| 19..22 | Reserved for Conflux, see [prop329].
-| 32..40 | Used for hidden services; see the [rendezvous spec].
-| 41..42 | Used for circuit padding; see ["Circuit-level padding"] in the padding spec.
-| 43 | XON (See Sec 4 of [prop324]) | forward or backward |
-| 44 | XOFF (See Sec 4 of [prop324]) | forward or backward |
+| 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
-[rendezvous spec]: ../rend-spec/index.md
-["Circuit-level padding"]: ../padding-spec/circuit-level-padding.md#circuit-level-padding
-
-Commands labelled as "forward" must only be sent by the originator
-of the circuit. Commands labelled as "backward" must only be sent by
-other nodes in the circuit back to the originator. Commands marked
-as either can be sent either by the originator or other nodes.
+[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
@@ -78,12 +120,12 @@ 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 payload is zero, the 'digest' field is computed as
+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 payload
+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"
@@ -100,14 +142,16 @@ 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 "\[control\]" style
+-- 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 payload which contain real payload data. The remainder of
-the unencrypted payload is padded with padding bytes. Implementations
+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).
diff --git a/spec/tor-spec/routing-relay-cells.md b/spec/tor-spec/routing-relay-cells.md
index a9e3c49..66d5625 100644
--- a/spec/tor-spec/routing-relay-cells.md
+++ b/spec/tor-spec/routing-relay-cells.md
@@ -28,7 +28,7 @@ are sent.
### Routing from the Origin
-When a relay cell is sent from an OP, the OP encrypts the payload
+When a relay cell is sent from an OP, the OP encrypts the cell's body
with the stream cipher as follows:
```text
@@ -42,7 +42,7 @@ OP sends relay cell:
### Relaying Forward at Onion Routers
-When a forward relay cell is received by an OR, it decrypts the payload
+When a forward relay cell is received by an OR, it decrypts the cell's body
with the stream cipher, as follows:
```text
@@ -51,7 +51,7 @@ with the stream cipher, as follows:
```
The OR then decides whether it recognizes the relay cell, by
-inspecting the payload as described in [Relay cells](./relay-cells.md#relay-cells). If the OR
+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
@@ -72,7 +72,7 @@ CREATE/CREATE2 cells.
### Relaying Backward at Onion Routers
-When a backward relay cell is received by an OR, it encrypts the payload
+When a backward relay cell is received by an OR, it encrypts the cell's body
with the stream cipher, as follows:
```text
@@ -84,16 +84,16 @@ with the stream cipher, as follows:
## Routing to the Origin
-When a relay cell arrives at an OP, the OP decrypts the payload
+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 payload is recognized (see [1]), then:
+ If the cell is recognized (see [1]), then:
The sending node is I.
- Stop and process the payload.
+ Stop and process the cell.
```
\[1\]: ["Relay cells"](./relay-cells.md#relay-cells)
diff --git a/spec/tor-spec/tearing-down-circuits.md b/spec/tor-spec/tearing-down-circuits.md
index fadd1fc..3fde693 100644
--- a/spec/tor-spec/tearing-down-circuits.md
+++ b/spec/tor-spec/tearing-down-circuits.md
@@ -78,7 +78,7 @@ towards the client, not RELAY_TRUNCATED.
behavior created queuing pressure on the intermediary ORs.
```
-The payload of a DESTROY cell or RELAY_TRUNCATED message contains a single
+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