diff --git a/protocols/BTP.md b/protocols/BTP.md index c7062884bc9435b8e8a670125b44d3fb547bdabe..31347cc96d6fc7b1d277e681fe884f7c748388d6 100644 --- a/protocols/BTP.md +++ b/protocols/BTP.md @@ -1,4 +1,4 @@ -# Bramble Transport Protocol, version 2 +# Bramble Transport Protocol, version 4 ## 1 Introduction @@ -12,49 +12,47 @@ BTP can operate over any transport that can deliver a stream of bytes from one d The BTP wire protocol includes optional padding and does not use any timeouts, handshakes or plaintext headers. This makes BTP compatible with traffic analysis prevention techniques such as traffic morphing, with the goal of making it difficult to distinguish BTP from other protocols. -BTP does not attempt to conceal the identities of the communicating parties or the fact that they are communicating - in other words, it does not provide anonymity, unlinkability or unobservability. If such properties are required, BTP can use anonymity systems such as Tor and Mixminion as underlying transports. +BTP does not attempt to conceal the identities of the communicating parties or the fact that they are communicating - in other words, it does not provide anonymity, unlinkability or unobservability. If such properties are required, BTP can use an anonymity system such as Tor as the underlying transport. -Forward secrecy is achieved by establishing an initial shared secret between each pair of endpoint devices and using a one-way key derivation function to generate a series of temporary keys from the shared secret. Once both devices have erased a given key, it cannot be re-derived if the devices are later compromised. A protocol for establishing the shared secret is described in other work. +Forward secrecy is achieved by establishing an initial root key between pair of endpoint devices and using a one-way key derivation function to derive a series of temporary keys from the root key. Once both endpoints have deleted a given key, it cannot be re-derived if the endpoints are later compromised. ### 1.1 Motivation -The primary motivation for BTP's design is to provide a building block for censorship-resistant communication systems, given powerful adversaries such as governments who can compromise the availability and/or privacy of centralised servers. +The primary motivation for BTP's design is to provide a versatile building block for censorship-resistant communication systems. BTP is therefore designed to be used across a diverse mixture of transports, both online and offline, with varying properties. The transports are not given access to unencrypted or unauthenticated data; nor are they required to ensure the confidentiality, integrity, authenticity or forward secrecy of the data they carry. BTP is responsible for providing those properties. -BTP is therefore designed to be used across a diverse mixture of transports, both online and offline, with varying properties. The transports are not given access to unencrypted or unauthenticated data; nor are they required to ensure the confidentiality, integrity, authenticity or forward secrecy of the data they carry. BTP is responsible for providing those properties. - -BTP is unusual in that it provides forward secrecy without ongoing two-way communication, and also has features that can make it non-trivial for an adversary to detect when BTP is in use. It can be used even on transports with very high latency, such as disks sent through the mail. +BTP is unusual in that it provides forward secrecy even for transports where one of the endpoints can only send and the other can only receive. It can be used on transports with very high latency, such as disks sent through the mail. ### 1.2 Design Requirements - **Flexibility** - BTP should be able to operate over a wide range of underlying transports with bandwidths varying from kilobits to gigabits per second, and with latencies varying from milliseconds to days. + The protocol should be able to operate over a wide range of underlying transports with bandwidths varying from kilobits to gigabits per second, and with latencies varying from milliseconds to days. - **Layering** - BTP should treat each underlying transport connection as a unidirectional or bidirectional sequence of bytes with a simple socket-like interface (open, read/write, close). Likewise, BTP should provide a similar interface to higher protocol layers. + The protocol should treat each underlying transport connection as a unidirectional or bidirectional sequence of bytes with a simple socket-like interface (open, read/write, close). Likewise, the protocol should provide a similar interface to higher protocol layers. - **Concealability** - BTP should not reveal any plaintext fields that would make it easily distinguishable from other protocols. It should be compatible with techniques such as traffic morphing that are designed to resist traffic analysis and traffic classification. + The protocol should not reveal any plaintext fields that would make it easily distinguishable from other protocols. It should be compatible with techniques such as traffic morphing that are designed to resist traffic analysis and traffic classification. - **Confidentiality** - The adversary should not be able to learn what data is being transported across a BTP stream. + The adversary should not be able to learn what data is being transported by the protocol. - **Integrity** - The adversary should not be able to cause either endpoint of a BTP stream to read data from the BTP layer that differs from the data written to the BTP layer by the other endpoint. If the adversary truncates a BTP stream, the receiving endpoint should be able to detect that this has happened. + The adversary should not be able to cause either endpoint to read data from the BTP layer that differs from the data written to the BTP layer by the other endpoint. If the adversary truncates the data, the receiving endpoint should be able to detect that this has happened. - **Authenticity** - The adversary should not be able to cause either endpoint of a BTP stream to accept data from any third party as though it came from the other endpoint. + The adversary should not be able to cause either endpoint to accept data from any third party as though it came from the other endpoint. - **Forward Secrecy** - The adversary should not be able to learn what data was transported across a BTP stream if, at some later time, the adversary compromises one or both of the endpoint devices. + The adversary should not be able to learn what data was transported by the protocol if, at some later time, the adversary compromises one or both of the endpoint devices. -BTP is not required to conceal the identities of the communicating parties or the fact that they are communicating. +The protocol is not required to conceal the identities of the communicating parties or the fact that they are communicating. ### 1.3 Adversary Model @@ -66,67 +64,55 @@ BTP is intended to be used in systems that resist surveillance and censorship by - The adversary has a limited ability to compromise endpoint devices. If a device is compromised, the adversary can access any information held in the device's volatile memory or persistent storage. -- The adversary cannot break standard cryptographic primitives such as block ciphers and message authentication codes. +- The adversary cannot break standard cryptographic primitives such as ciphers and message authentication codes. ### 1.4 Underlying Transports -BTP can operate over any transport that can deliver a unidirectional or bidirectional sequence of bytes from one device to another on a best-effort basis. We refer to this sequence of bytes as a **connection**. If the connection is unidirectional, BTP uses it to carry an encrypted and authenticated sequence of bytes, which we refer to as a **stream**. If the connection is bidirectional, BTP uses it to carry two separate streams, one in each direction. +BTP can operate over any transport that can deliver a unidirectional or bidirectional sequence of bytes from one device to another on a best-effort basis. We refer to this sequence of bytes as a **connection**. If the connection is unidirectional then BTP uses it to carry an encrypted and authenticated sequence of bytes, which we refer to as a **stream**. If the connection is bidirectional then BTP uses it to carry two separate streams, one in each direction. -Transports must ensure that bytes within a given connection arrive in the correct order. If the bytes within a connection are reordered, none of BTP's security properties are lost, but it will reject the stream or streams carried by the connection. +Transports must ensure that the bytes within a given connection arrive in the correct order. If the bytes within a connection are reordered then none of BTP's security properties are lost, but it will reject the stream or streams carried by the connection. Transport connections themselves may be reordered. There is no requirement that all connections reach the intended recipient. -If a transport imposes a maximum connection length, such as the storage capacity of a disk, BTP passes this restriction on to higher protocol layers; it does not fragment a stream across multiple connections. BTP cannot use transport connections with less capacity than the minimum length of a stream. (*Note:* In the current version of the protocol, the minimum length of a stream is 100 bytes.) - -The use of BTP over a datagram-oriented transport such as UDP (which does not have a concept of connections) would require the use of an intermediate connection-oriented protocol such as UDT. - -### 1.5 Initial state - -Before two devices can communicate using BTP they must establish the following initial state: - -- An agreement as to which device plays the role of **Alice** and which plays the role of **Bob** - -- A shared secret KEY\_LEN bytes long, **S** +If one endpoint of a connection starts writing to the transport at time T0 and the other endpoint starts reading from the transport at time T1, we call T1 - T0 the **latency** of the connection. For a bidirectional connection we define the latency of the connection to be the maximum latency in either direction. -- A timestamp in seconds since the Unix epoch, **T** +If a transport imposes a maximum connection length, such as the storage capacity of a disk, BTP passes this restriction on to higher protocol layers by limiting the stream length; it does not fragment a stream across multiple connections. BTP cannot use transport connections with less capacity than the minimum length of a stream. (*Note:* In the current version of the protocol, the minimum length of a stream is 118 bytes.) -- The maximum expected difference between the devices' clocks in seconds, **D** +Using BTP over a datagram-oriented transport such as UDP (which does not have a concept of connections) would require the use of an intermediate connection-oriented protocol such as UDT to provide an ordered sequence of bytes in each direction. -- The maximum expected latency of the transport in seconds, **L** +### 1.5 Prerequisites -The establishment of the initial state is not addressed by BTP itself. BTP is designed to be used with a separate key agreement protocol that securely establishes the initial state. +Before two endpoints can communicate using BTP they must agree on the following properties: -##### Roles of the two parties +- **Roles of the two endpoints** -The roles of Alice and Bob are identical except for some key derivation constants. It does not matter which device plays which role, as long as one is Alice and the other Bob. + The endpoints must agree which of them will play the role of **Alice** and which the role of **Bob**. The roles are identical except for some key derivation constants. It does not matter which endpoint plays which role, as long as one is Alice and the other Bob. -##### Shared secret +- **Maximum clock difference** -The shared secret must have KEY\_LEN * 8 bits of entropy. BTP does not place any restrictions on the method used to establish the shared secret, except that it must not be possible to re-derive the secret from any information retained by the parties after the secret has been erased. If Alice and Bob wish to communicate across more than one transport, they must establish a separate shared secret for each transport to ensure they do not reuse keys. + The endpoints must agree on the maximum expected difference between their clocks, **D**. This value may be hard-coded. The current version of BTP assumes D = 86,400 seconds (24 hours). This is to accommodate mobile devices, which often have inaccurate clocks. -##### Timestamp +- **Maximum latency** -T must be in the past according to both devices' clocks. T may be hard-coded or negotiated by the key agreement protocol. + The endpoints must agree on the maximum expected latency, **L**, of each transport they wish to use. This value may be hard-coded. For any given transport we can choose some maximum latency L such that the latency of any connection is unlikely to exceed L under normal conditions. For example, we might choose one minute as the maximum latency for TCP, or two weeks as the maximum latency for disks sent through the mail. If a connection exceeds the maximum latency, none of BTP's security properties are lost but it may reject the stream or streams carried by the connection. -##### Maximum clock difference +### 1.6 Notation -D may be hard-coded. The current version of BTP assumes D = 86,400 (24 hours). This is to accommodate mobile devices, which often have inaccurate clocks. +- || denotes concatenation -##### Maximum latency +- Double quotes denote an ASCII string -Alice and Bob must agree on a maximum latency for each transport they wish to use. If one endpoint of a connection starts writing to the transport at time T0 and the other endpoint starts reading from the transport at time T1, we call T1 - T0 the latency of the connection. For any given transport we can choose some maximum latency, L , such that the latency of any connection is unlikely to exceed L under normal conditions. For example, we might choose one minute as the maximum latency for TCP, or two weeks as the maximum latency for disks sent through the mail. +- len(x) denotes the length of x in bytes -If a connection exceeds the maximum latency, none of BTP's security properties are lost but it may reject the stream or streams carried by the connection. +- int_n(x) denotes x represented as a big-endian n-bit integer -### 1.6 Cryptographic Primitives - -**Notation:** || denotes concatenation, double quotes denote an ASCII string, int(x) denotes x represented as a 64-bit integer, and len(x) denotes the length of x in bytes, represented as a 32-bit integer. All integers in BTP are big-endian. +### 1.7 Cryptographic Primitives BTP uses three cryptographic primitives: 1. **A pseudo-random function**, PRF(k, m) - The output of PRF(k, m) is PRF\_LEN bytes. (*Note:* The current version of BTP uses keyed BLAKE2s as the pseudo-random function, giving PRF\_LEN = 32.) + The output of PRF(k, m) is PRF\_LEN bytes. (*Note:* The current version of BTP uses keyed BLAKE2b with a 32-byte output length as the pseudo-random function, giving PRF\_LEN = 32.) 2. **An authenticated cipher**, ENC(k, n, m) and DEC(k, n, m), where n is a nonce @@ -134,141 +120,183 @@ BTP uses three cryptographic primitives: 3. **A random number generator**, R(n), with an output length of n bytes - R(n) must be either a true random number generator or a cryptographically secure pseudo-random number generator. + R(n) must be either an unbiased true random number generator or a cryptographically secure pseudo-random number generator. ## 2 Key Management Protocol -### 2.1 Key Derivation Function +BTP uses a time-based key management protocol to derive a series of **temporary keys** from an initial **root key**. The root key must be KEY\_LEN bytes long and contain KEY\_LEN * 8 bits of entropy. + +### 2.1 Key Management Modes + +BTP has two key management modes, which are suitable for different purposes. + +**Dynamic mode** provides forward secrecy for the data being transported, but requires the endpoints to delete the root key, and any information that could be used to re-derive it, before the temporary keys are used. Dynamic mode requires the endpoints to agree on a timestamp, **T**, which must be in the past according to both endpoints' clocks. + +**Static mode** does not provide forward secrecy for the data being transported, but allows the endpoints to retain the root key or information that could be used to re-derive it. Static mode does not require a timestamp. -BTP uses a **key derivation function** to derive encryption and authentication keys from the shared secret S. Forward secrecy relies on the one-way nature of the key derivation function. +These modes are intended to be complementary. Static mode can be used to bootstrap dynamic mode by transporting the messages of a key agreement protocol that establishes a root key and timestamp for dynamic mode. + +The establishment of root keys and timestamps is not handled by BTP itself. BTP is designed to be used with a separate key agreement protocol that securely establishes the initial state. + +If two endpoints wish to communicate across more than one transport, they must establish a separate root key for each transport to ensure they do not reuse keys. + +### 2.2 Key Derivation Function + +BTP uses a **key derivation function** to derive temporary keys from the root key. The key derivation function is based on PRF(k, m): -- KDF(k, x\_1, ..., x\_n) = PRF(k, len(x\_1) || x\_1 || ... || len(x\_n) || x\_n) +- KDF(k, x\_1, ..., x\_n) = PRF(k, int\_32(len(x\_1)) || x\_1 || ... || int\_32(len(x\_n)) || x\_n) + +### 2.3 Time Periods + +For each transport, BTP divides time into numbered periods, where period zero starts at the Unix epoch. A different set of temporary keys is used for each period. -### 2.2 Initial Keys +The length of each period is R = D + L seconds, where D is the maximum expected difference between the endpoints' clocks and L is the maximum expected latency of the transport. Recall that the endpoints must agree on the values of D and L, which may be hard-coded. -Each endpoint derives four initial keys from S. Alice derives her initial keys as follows: +This ensures that if the sender starts sending a stream in period P0 according to the sender's clock, and if D and L are not exceeded, then the recipient will start receiving the stream in period P1 according to the recipient's clock, where abs(P1 - P0) <= 1. In other words, the recipient only needs to retain the temporary keys for the previous, current and next periods. -- outgoing\_tag\_key := KDF(S, "ALICE\_TAG\_KEY") +### 2.4 Key Derivation for Dynamic Mode -- outgoing\_header\_key := KDF(S, "ALICE\_HEADER\_KEY") +In dynamic mode, BTP achieves forward secrecy by periodically rotating and deleting the temporary keys. The key derivation function is deterministic, so endpoints that start from the same root key and timestamp T will derive the same temporary keys for each time period. Forward secrecy relies on the one-way nature of the key derivation function: the keys of an earlier period cannot be re-derived from those of a later period. -- incoming\_tag\_key := KDF(S, "BOB\_TAG\_KEY") +##### Initial Keys -- incoming\_header\_key := KDF(S, "BOB\_HEADER\_KEY") +Each endpoint derives four initial keys from the root key. Alice derives her initial keys as follows: + +- outgoing\_tag\_key := KDF(root\_key, "ALICE\_TAG\_KEY") + +- outgoing\_header\_key := KDF(root\_key, "ALICE\_HEADER\_KEY") + +- incoming\_tag\_key := KDF(root\_key, "BOB\_TAG\_KEY") + +- incoming\_header\_key := KDF(root\_key, "BOB\_HEADER\_KEY") Bob derives his initial keys as follows: -- outgoing\_tag\_key := KDF(S, "BOB\_TAG\_KEY") +- outgoing\_tag\_key := KDF(root\_key, "BOB\_TAG\_KEY") -- outgoing\_header\_key := KDF(S, "BOB\_HEADER\_KEY") +- outgoing\_header\_key := KDF(root\_key, "BOB\_HEADER\_KEY") -- incoming\_tag\_key := KDF(S, "ALICE\_TAG\_KEY") +- incoming\_tag\_key := KDF(root\_key, "ALICE\_TAG\_KEY") -- incoming\_header\_key := KDF(S, "ALICE\_HEADER\_KEY") +- incoming\_header\_key := KDF(root\_key, "ALICE\_HEADER\_KEY") -Thus Alice's outgoing keys are Bob's incoming keys and vice versa. Both devices must then erase the shared secret S. +Thus Alice's outgoing keys are Bob's incoming keys and vice versa. -### 2.3 Rotation and Retention Periods +After deriving the initial keys, both endpoints must delete the root key. -BTP achieves forward secrecy by rotating keys periodically. The key rotation function is deterministic, so devices that start from the same S and T will have matching keys in each rotation period. +The initial keys are used as the temporary keys for the period preceding the period containing the timestamp T. -The length of each rotation period is R = D + L seconds. Rotation periods are aligned with the Unix epoch. +The purpose of the timestamp is to save the cost of rotating keys from period zero to the current period. If it is not possible or convenient to agree a timestamp T along with the root key then T can be hard-coded to some value that is certain to be in the past according to both endpoints' clocks, at the cost of some extra key rotations. -If the sender starts sending a stream at time t according to the sender's clock, the recipient may start receiving the stream at any time between t - D and t + D + L according to the recipient's clock. Therefore each device must retain the incoming keys for the previous, current and next rotation periods, along with the outgoing keys for the current rotation period. +##### Key Rotation -The initial keys derived from S are used as the keys for the rotation period that precedes the period containing the timestamp T. +The temporary keys for each time period P are derived from the previous period's keys as follows: -The keys for the i<sup>th</sup> rotation period are derived from the previous period's keys as follows: +- outgoing\_tag\_key := KDF(outgoing\_tag\_key, "ROTATE", int\_64(P)) -- outgoing\_tag\_key := KDF(outgoing\_tag\_key, "ROTATE", int(i)) +- outgoing\_header\_key := KDF(outgoing\_header\_key, "ROTATE", int\_64(P)) -- outgoing\_header\_key := KDF(outgoing\_header\_key, "ROTATE", int(i)) +- incoming\_tag\_key := KDF(incoming\_tag\_key, "ROTATE", int\_64(P)) -- incoming\_tag\_key := KDF(incoming\_tag\_key, "ROTATE", int(i)) +- incoming\_header\_key := KDF(incoming\_header\_key, "ROTATE", int\_64(P)) -- incoming\_header\_key := KDF(incoming\_header\_key, "ROTATE", int(i)) +To ensure forward secrecy, keys must be deleted when they are no longer needed. The outgoing keys for period P must be deleted at the end of period P, while the incoming keys for period P must be deleted at the end of period P + 1. -Keys must be erased when they are no longer needed , to ensure forward secrecy. +### 2.5 Key Derivation for Static Mode -## 3 Wire Protocol +In static mode, BTP does not provide forward secrecy. The temporary keys for any period can be derived from the root key, which is retained by the endpoints. -A stream consists of three parts: a **tag**, a **stream header**, and one or more **frames**. +Alice derives her temporary keys for each time period P as follows: -### 3.1 Tags +- outgoing\_tag\_key := KDF(root\_key, "ALICE\_STATIC\_TAG\_KEY", int\_64(P)) -Each stream starts with a pseudo-random tag TAG\_LEN bytes long. (*Note:* In the current version of the protocol, TAG\_LEN = 16.) The recipient calculates the same tag in advance and uses it to recognise which sender the stream comes from and which incoming header key should be used for the stream. +- outgoing\_header\_key := KDF(root\_key, "ALICE\_STATIC\_HEADER\_KEY", int\_64(P)) -The tag for the i<sup>th</sup> stream from a given sender to a given recipient in a given rotation period is the first TAG\_LEN bytes of PRF(k, int(i)), where k is the sender's outgoing tag key (which is also the recipient's incoming tag key). For simplicity we require that TAG\_LEN ≤ PRF\_LEN. Streams are counted from zero in each rotation period. +- incoming\_tag\_key := KDF(root\_key, "BOB\_STATIC\_TAG\_KEY", int\_64(P)) -### 3.2 Stream Headers +- incoming\_header\_key := KDF(root\_key, "BOB\_STATIC\_HEADER\_KEY", int\_64(P)) -The pseudo-random tag is followed by the stream header, which consists of a true random **initialisation vector (IV)** followed by a symmetric **ephemeral cipher key.** The IV is IV\_LEN bytes long, where IV\_LEN = NONCE\_LEN - 8. +Bob derives his temporary keys as follows: -The ephemeral cipher key is encrypted and authenticated with the sender's outgoing header key, using a nonce consisting of the stream number as a 64-bit integer followed by the IV. The ephemeral cipher key is used for encrypting and authenticating the rest of the stream. +- outgoing\_tag\_key := KDF(root\_key, "BOB\_STATIC\_TAG\_KEY", int\_64(P)) -The stream header is IV\_LEN + KEY\_LEN + AUTH\_LEN bytes long. +- outgoing\_header\_key := KDF(root\_key, "BOB\_STATIC\_HEADER\_KEY", int\_64(P)) -The stream header is composed as follows: +- incoming\_tag\_key := KDF(root\_key, "ALICE\_STATIC\_TAG\_KEY", int\_64(P)) -- stream\_iv = R(IV\_LEN) +- incoming\_header\_key := KDF(root\_key, "ALICE\_STATIC\_HEADER\_KEY", int\_64(P)) -- stream\_header\_nonce = int(stream\_number) || stream\_iv +Thus Alice's outgoing keys are Bob's incoming keys and vice versa. -- stream\_header = stream\_iv || ENC(outgoing\_header\_key, stream\_header\_nonce, ephemeral\_cipher\_key) +The outgoing keys for period P can be deleted at the end of period P, and the incoming keys for period P can be deleted at the end of period P + 1, but this is not required for security. -The random IV ensures that if a stream number is accidentally reused, the nonces will be different. IV\_LEN must be large enough to ensure that two random IVs are different with high probability. (*Note:* In the current version of the protocol, IV\_LEN = 16.) +## 3 Wire Protocol -### 3.3 Frames +A stream consists of three parts: a **pseudo-random tag**, a **stream header**, and one or more **frames**. -The remainder of the stream consists of one or more frames. Each frame has a fixed-length **frame header** and a variable-length **frame body** that may contain data and/or padding. The frames in each stream are numbered from zero. A stream may not contain more than 2<sup>63</sup> frames. +### 3.1 Tags -##### Frame header +Each stream starts with a pseudo-random tag TAG\_LEN bytes long. (*Note:* In the current version of the protocol, TAG\_LEN = 16.) The recipient calculates the same tag in advance and uses it to recognise which sender the stream comes from and which incoming header key should be used for the stream. -The plaintext frame header is four bytes long, with the following format: +The tag for the i<sup>th</sup> stream from a given sender to a given recipient in a given time period is the first TAG\_LEN bytes of PRF(k, int\_16(PROTOCOL\_VERSION) || int\_64(i)), where k is the sender's outgoing tag key (which is also the recipient's incoming tag key) and PROTOCOL\_VERSION is 4 for the current version of BTP. Streams are counted from zero in each time period. -- Bit 0: Final frame flag, set to one if this is the last frame in the stream +### 3.2 Stream Headers -- Bits 1-15: Length of the data in bytes as a 15-bit integer +The pseudo-random tag is followed by the stream header, which is composed as follows: -- Bit 16: Zero +- nonce = R(NONCE\_LEN) -- Bits 17-31: Length of the padding in bytes as a 15-bit integer +- stream\_header\_plaintext = int\_16(PROTOCOL\_VERSION) || int\_64(stream\_number) || ephemeral\_cipher\_key -The final frame flag allows the recipient to detect the end of the stream without reading to EOF, which is not possible for all transports on all platforms. +- stream\_header = nonce || ENC(outgoing\_header\_key, nonce, stream\_header\_plaintext) -##### Frame body +The stream header is NONCE\_LEN + 2 + 8 + KEY\_LEN + AUTH\_LEN = 82 bytes long. The header contains an **ephemeral cipher key** that is used for encrypting and authenticating the rest of the stream. -The plaintext frame body contains data and/or padding. The total length of the data and padding must be less than 2<sup>15</sup> bytes. +The random nonce ensures that even if a stream number is accidentally reused, the combination of header key and nonce will be unique, which is a security requirement of many ciphers. -##### Encryption and authentication +### 3.3 Frames -The header and body of each frame are encrypted and authenticated separately using the ephemeral cipher key and deterministic nonces. The nonces are not sent. +The remainder of the stream consists of one or more frames. Each frame has a fixed-length **frame header** and a variable-length **frame body** that may contain data and/or padding. The total length of the data and padding must be less than 2<sup>15</sup> bytes. -The nonce for the frame header is NONCE\_LEN bytes long, with the following format: +The frames in each stream are numbered from zero. A stream must not contain more than 2<sup>63</sup> frames. -- Bit 0: Header flag, set to one +##### Frame Header -- Bits 1-63: Frame number as a 63-bit integer +The plaintext frame header is four bytes long, with the following format (where bit zero is the most significant): -- Remaining bits: Zero +- Bit 0: Final frame flag, set to one if this is the last frame in the stream + +- Bits 0 - 15: int\_16(len(data)) + +- Bits 16 - 31: int\_16(len(padding)) + +The final frame flag overlaps with the most significant bit of the data length, which is unused because the data must be less than 2<sup>15</sup> bytes long. -The nonce for the frame body is NONCE\_LEN bytes long, with the following format: +The final frame flag allows the recipient to detect the end of the stream without reading to EOF, which is not possible for all transports on all platforms. + +##### Encryption and Authentication + +The header and body of each frame are encrypted and authenticated separately using the ephemeral cipher key and deterministic nonces. The nonces are not sent over the wire. -- Bit 0: Header flag, set to zero +Each nonce is NONCE\_LEN bytes long, with the following format (where bit zero is the most significant): -- Bits 1-63: Frame number as a 63-bit integer +- Bit 0: Header flag, set to one for the frame header or zero for the frame body + +- Bits 0 - 63: int\_64(frame\_number) - Remaining bits: Zero +The header flag overlaps with the most significant bit of the frame number, which is unused because a stream must not contain more than 2<sup>63</sup> frames. + The encrypted and authenticated frame header is 4 + AUTH\_LEN bytes long, while the encrypted and authenticated frame body is AUTH\_LEN bytes longer than the data and padding. ## 4 Reordering Windows -BTP uses **reordering windows** to allow endpoints to recognise streams that are received out of order due to reordering and/or loss of connections by the underlying transport. Each endpoint maintains reordering windows for the previous, current and next rotation periods. The windows are used to recognise incoming streams by their tags. +BTP uses **reordering windows** to allow endpoints to recognise streams that are received out of order due to reordering or loss of connections by the underlying transport. Each endpoint maintains reordering windows for the previous, current and next time periods. The windows are used to recognise incoming streams by their tags. -Each window contains **W** tags, each of which is marked as *seen* or *unseen*. W is an implementation parameter. Maintaining larger windows makes it possible to tolerate more reordering and/or loss by the transport, at the cost of storing more tags. (*Note:* In the current implementation of the protocol, W = 32.) +Each window contains **W** tags, each of which is marked as *seen* or *unseen*. W is an implementation parameter. Maintaining larger windows makes it possible to tolerate more reordering or loss by the transport, at the cost of storing more tags. (*Note:* In the current implementation of the protocol, W = 32.) When a previously unseen tag is marked as seen, the window slides according to the following rules: @@ -278,6 +306,6 @@ When a previously unseen tag is marked as seen, the window slides according to t If the window slides past a tag that has not been seen, the recipient can no longer recognise the corresponding stream. -To avoid reusing tags, which would allow the adversary to distinguish BTP traffic from random, the sender must persistently store the number of streams sent to the recipient in the current rotation period. +To avoid reusing tags, which would allow the adversary to distinguish BTP traffic from random, the sender must persistently store the number of streams sent to the recipient in the current time period. -To avoid accepting replayed streams, the recipient must persistently store the reordering windows for the previous, current and next rotation periods. +To avoid accepting replayed streams, the recipient must persistently store the reordering windows for the previous, current and next time periods.