<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.

