Skip to content
Snippets Groups Projects
Transport-Key-Agreement-Client.md 5.11 KiB
Newer Older
# Transport Key Agreement Client

The transport key agreement client is a [BSP client](/protocols/BSP.md) that establishes keys for newly added transports.

The client establishes transport keys with each contact for any transports that were added more recently than the contact was added.

A key agreement session may be started between two peers, X and Y, in the following cases:

1. Neither of the peers supported the transport when they added each other as contacts. In this case, each peer will send a key message when it adds support for the transport. If a peer receives a key message for a transport it doesn't support, it will defer handling the message until it supports the transport. The session will complete when both peers support the transport.
2. X did not support the transport when the peers added each other as contacts, but Y did. In this case, when X later adds support for the transport, X will start a key agreement session. Although Y already has keys for the transport, it will complete the session in order to establish a new set of keys that X also possesses.

### Identifier

The client's identifier is `org.briarproject.bramble.transport.agreement`. The major version is 0.

### Groups

The client uses a separate BSP group for communicating with each contact. The [group descriptor](/protocols/BSP.md#23-groups) is a [BDF list](/BDF.md) containing the unique IDs of the contacts' identities, sorted in ascending order as byte strings.

### Message types

The protocol uses two message types.

**0: KEY** - The message body is a BDF list with three elements: `messageType` (int), `transportId` (string), and `publicKey` (raw). `publicKey` is an X25519 public key.

**1: ACTIVATE** - The message body is a BDF list with three elements: `messageType` (int), `transportId` (string), and `previousMessageId` (unique ID). `previousMessageId` is the ID of the sender's key message in this session, which is a dependency.

### Validity policy

* A key message is valid if it is well-formed and the public key is valid, i.e. the X25519 raw shared secret is not all zeroes.
* An activate message is valid if it is well-formed and its dependency is a valid incoming key message with the same transport ID.

### Storage policy

* A key message for an unknown transport is deferred.
* All other messages are stored.

### Sharing policy

* All local messages are shared.

### Security properties

Confidentiality, integrity and authenticity are provided by the transport security layer ([BTP](/protocols/BTP.md)). Messages are repudiable, but this is not a security goal and may change in future versions of the client.

### State machine

![key-agreement-client](/assets/clients/Transport-Key-Agreement-Client/key-agreement-client.png)

[key-agreement-client.odg](/assets/clients/Transport-Key-Agreement-Client/key-agreement-client.odg)

The `ACTIVATED` state lets us know that we already completed a session, so that we don't create a new session if we receive another key message from the contact. Otherwise a malicious contact could cause us to create an unlimited number of key sets and run out of memory.

### Key management

For each session, each peer generates an ephemeral X25519 key pair. The public key is sent in the peer's key message and the private key is stored until the peer receives the other peer's key message. Each peer then uses its own private key and the other peer's public key to derive the [root key](/protocols/BTP.md#2-key-management-protocol) for a set of rotation mode transport keys.

Each peer stores the transport keys, starts rotating them, and deletes its own private key before sending its activate message. A peer does not start using the new transport keys until it either receives the other peer's activate message or receives a BTP stream from the other peer that uses the new keys.

#### Roles

The peers assign themselves the roles of Alice and Bob by comparing their ephemeral public keys as byte strings. The peer whose ephemeral public key comes first is Alice, the other is Bob.

#### Notation

* || denotes concatenation

* Double quotes denote an ASCII string

* len(x) denotes the length of x in bytes

* int\_n(x) denotes x represented as an unsigned, big-endian, n-bit integer

#### Cryptographic primitives

The protocol uses two primitives:

1. **A cryptographic hash function**, H(m). In the current version of the protocol this is BLAKE2b.

2. **A key agreement function**, DH(pri, pub), where pri is one party's private key and pub is the other party's public key. In the current version of the protocol this is X25519.

We use H(m) to define a multi-argument hash function:

* HASH(x\_1, ..., x\_n) = H(int\_32(len(x\_1)) || x\_1 || ... || int\_32(len(x\_n)) || x\_n)

#### Key derivation

Alice calculates the raw shared secret as follows:

* raw = DH(pri\_a, pub\_b)

Bob calculates the raw shared secret as follows:

* raw = DH(pri\_b, pub\_a)

(*Note:* If a peer calculates an X25519 raw shared secret that is all zeroes, the peer must reject the incoming key message and not continue with the session.)

Both peers then derive the root key as follows:

* root\_key = HASH("org.briarproject.bramble.transport.agreement/ROOT\_KEY", raw, pub\_a, pub_b)