# MSC4081: Eagerly sharing fallback keys with federated servers
*Abstract: This MSC aims to increase the robustness of the Olm session setup protocol over federation.
With this MSC, transient network failures over federation will not cause undecryptable messages due to
@ -10,69 +10,141 @@ only be used once. However, this presents several problems:
- what happens when the device does not upload more keys and the uploaded keys are all used up? (key exhaustion)
- what happens if the OTK cannot be claimed due to transient network failures.
[MSC2732](https://github.com/matrix-org/matrix-spec-proposals/pull/2732) introduced the concept of "fallback keys"
which can be claimed when OTKs are exhausted. Fallback keys provide weaker security properties than one-time keys,
specifically impacting forward secrecy, which protects past sessions against future compromises of keys or passwords.
The risk is that if the private part of the fallback key is exposed, an attacker may use the key to decrypt earlier
sessions. This can be mitigated by cycling the fallback key (and hence deleting the private key) once it has been
"used", with some lag time to account for slow networks.
[MSC2732](https://github.com/matrix-org/matrix-spec-proposals/pull/2732) introduced the concept of "fallback keys"
which can be claimed when OTKs are exhausted. Fallback keys provide weaker security properties than one-time keys,
specifically impacting forward secrecy, which protects past sessions against future compromises of keys or
passwords. The risk is that if the private part of the fallback key is exposed, an attacker may use the key to
decrypt earlier sessions. This can be mitigated by creating a new fallback key as soon as the old one has been used
(and hence later deleting the private key, with some lag time to account for slow networks).
For reference, https://crypto.stackexchange.com/a/52825 is a good explanation of why OTKs are preferable
to fallback keys, where they are available. (The question is about Signal rather than Olm, however the principles
are much the same. Signal uses the terms "prekey" to refer to "fallback key" and "one-time prekey" to refer to
OTK.)
## Proposal
Currently, fallback keys are _only_ claimed on key exhaustion, not due to transient network failures. This MSC
Currently, fallback keys are _only_used on key exhaustion, not due to transient network failures. This MSC
proposes to change the semantics to allow fallback keys to be returned by the `/keys/claim` endpoint if the server
the target device is on is unreachable. In order for servers to return fallback keys during the network failure,
the fallback keys must be cached _in advance_ on the claiming user's homeserver. This MSC proposes adding a new
key `fallback_keys` to the [`m.device_list_update` EDU](https://spec.matrix.org/v1.9/server-server-api/#definition-mdevice_list_update). This MSC proposes changing the spec wording (bold is new):
the fallback keys must be cached _in advance_ on the claiming user's homeserver.
| `device_keys` | `DeviceKeys` | Identity keys for the device. May be absent if no new identity keys are required.
| `fallback_keys` | `OneTimeKeys` | The public key which should be used if the device’s one-time keys are exhausted, **or if the user's homeserver is unreachable**. [etc]
| `one_time_keys` | `OneTimeKeys` | One-time public keys for “pre-key” messages. The names of the properties should be in the format <algorithm>:<key_id>. The format of the key is determined by the key algorithm. May be absent if no new one-time keys are required.
| **`eager_share_fallback_keys`** | **`boolean`** | **Whether the `fallback_keys` should immediately be sent to other homeservers which have a user which share a room with this user. Omitting this property is the same as setting it to `false`.
### Extend `m.device_list_update` EDU
This MSC proposes adding a new key `fallback_keys` to the [`m.device_list_update`
EDU](https://spec.matrix.org/v1.9/server-server-api/#definition-mdevice_list_update). We change the spec wording as
follows:
> Servers must send `m.device_list_update` EDUs to all the servers who share a room with a given local user, and
> must be sent whenever that user’s device list changes (i.e. for new or deleted devices, when that user joins a
> room which contains servers which are not already receiving updates for that user’s device list, or changes in
> device information such as the device’s human-readable name **or fallback key**).
> device information such as the device’s human-readable name **or, if the client has opted into eager sharing of
> fallback keys, the fallback keys**).
The following key/values are added to the `DeviceKeys` object definition (bold is new):
A new property `fallback_keys` is added to the body of the `m.device_list_update` EDU, as shown below (bold is new):
| algorithms | [string] | Required: The encryption algorithms supported by this device. |
| device_id | string | Required: The ID of the device these keys belong to. Must match the device ID used when logging in. |
| keys | {string: string} | Required: Public identity keys. The names of the properties should be in the format <algorithm>:<device_id>. The keys themselves should be encoded as specified by the key algorithm. |
| signatures | Signatures | Required: Signatures for the device key object. A map from user ID, to a map from <algorithm>:<device_id> to the signature. The signature is calculated using the process described at Signing JSON. |
| user_id | string | Required: The ID of the user the device belongs to. Must match the user ID used when logging in. |
| **fallback_key** | **{string: KeyObject}** | **The fallback key for this device, if set. The format of this object is identical to the /keys/claim response for a single device. This replaces any previously sent fallback key.** |
| `deleted` | `boolean` | True if the server is announcing that this device has been deleted.
| `device_display_name` | `string` | The public human-readable name of this device. Will be absent if the device has no name.
| `device_id` | `string` | Required: The ID of the device whose details are changing.
| `keys` | `DeviceKeys` | The updated identity keys (if any) for this device. May be absent if the device has no E2E keys defined.
| `prev_id` | `[integer]` | The `stream_ids` of any prior `m.device_list_update` EDUs sent for this user which have not been referred to already in an EDU’s `prev_id` field. If the receiving server does not recognise any of the `prev_ids`, it means an EDU has been lost and the server should query a snapshot of the device list via `/user/keys/query` in order to correctly interpret future `m.device_list_update` EDUs. May be missing or empty for the first EDU in a sequence.
| `stream_id` | `integer` | Required: An ID sent by the server for this update, unique for a given `user_id`. Used to identify any gaps in the sequence of m.device_list_update EDUs broadcast by a server.
| `user_id` | `string` | Required: The user ID who owns this device.
| **`fallback_keys`** | **`{string: KeyObject}`** | **The fallback keys for this device, if set, and if the client has opted in to eager sharing. This is the same as the most recent `fallback_keys` uploaded by this device via [`POST /_matrix/client/v3/keys/upload`](https://spec.matrix.org/v1.9/client-server-api/#post_matrixclientv3keysupload).**