You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
matrix-spec-proposals/proposals/3834-tofu.md

7.2 KiB

MSC3834: Opportunistic user key pinning (TOFU)

In the Matrix spec at present, there are no real provisions for properly authenticating devices belonging to other users, aside from the fairly rare cases where users actually take the time to verify each other out-of-band. Most clients encourage users to cross-sign their own devices, but this has little practical value for most users in the ecosystem at present, unless you're willing to verify all of your contacts or trust the user keys reported by homeservers.

The goal of this proposal is to establish a TOFU-style mechanism where users' signing keys are pinned when they're first encountered; internally, this will look similar to user verification, but will require no action on either user's part, and correspondingly will not be considered as high a level of trust. Nevertheless, this at least raises the bar for Mallory-in-the-middle attacks by malicious homeservers, as they can no longer quietly falsify signing keys for users who are already in contact with each other.

Proposal

This proposal adds a fourth ed25519 keypair to a user's set of cross-signing keys: the TOFU Signing Key (TSK), identified by m.cross_signing.tofu_signing. This key will be uploaded and stored alongside the MSK, SSK, and USK; it will be published to the keys/device_signing/upload using the new optional field tofu_signing_key.

Whenever a user Alice and a user Bob are in a room together for the first time, Alice's device will automatically and silently cross-sign Bob's MSK using her TSK. This effectively pins Bob's MSK; in future interactions, Alice will be able to check that any device of Bob's is signed by Bob's SSK which is signed by the pinned MSK, confirming that the device really does belong to Bob as long as that very first interaction wasn't tampered with. If Alice's device later observes an MSK for Bob that differs from the one signed by her TSK, the device may warn Alice that Bob's key has changed, and could potentially refuse to share keys with devices that aren't signed under the original SSK/MSK until Alice chooses to accept the new key.

After a device signs one or several new MSKs with the TSK (on joining a new room, or observing a new member join a room), it should upload these new signatures to the homeserver via the keys/signatures/upload API endpoint. However, it is important to ensure that the homeserver cannot perform a denial-of-service attack on key pinning by simply dropping TOFU signatures. For this reason, a user's devices should periodically ask each other to confirm a hash of the complete set of all cross-signing signatures created by that user. At any point, a device may send any or all of the user's other devices an encrypted to-device message, with event type m.signatures_hash_request and no fields. When the device receives the message, it should reply with an encrypted to-device message with event type m.signatures_hash and one field sha256. This field contains a SHA256 hash of the canonical JSON encoding of the complete set of cross-signing signatures known to that device, in the format for uploading to keys/signatures/upload, excluding any unsigned fields - that is, a map from user ID, to key ID, to a signed JSON object for that key.

Potential issues

If a client does choose to warn users every time a pinned MSK changes, users in many large rooms could be overwhelmed with warnings from random people losing their devices and performing key resets. There are several things clients can do to alleviate this. First, rather than popping up a warning immediately in a toast or dialog as soon as a key changes, clients should only warn the user when they actually open one of the rooms where the changed key is present. In addition, users should be given the option to automatically accept all future key changes in a particular room, and the option to accept all key changes globally if that's in line with the user's threat model. Clients could still display a small state-event-like message in room timelines notifying the user of a key change, or could simply accept all key changes silently.

Security considerations

In the malicious homeserver scenario that this proposal aims to mitigate, the homeserver could attempt to simply exclude TSK signatures from its responses to key queries, preventing the propagation of pinned keys between devices, and possibly even causing a device to lose track of pinned keys over time. To prevent this, it's important that clients maintain a persistent record of TSK signatures without relying on the homeserver to store that information. Signatures must never be removed from this record, even if they aren't present in homeserver responses. However, if multiple valid signatures for the same key from the same TSK have been created due to race conditions, only the signature whose base64 representation comes first lexicographically should be kept.

When devices ask each other to confirm the hash of the set of cross-signing signatures, they may not receive a response; this could be because the other device is offline, it could be because the device is using an older version of the spec and doesn't understand the request, or it could be because the homeserver is performing a denial-of-service attack. If a device doesn't get a response, and does see other activity from the other device, it could possibly eventually display a warning encouraging the user to upgrade their other device. If the device observes too many missing key indices in its to-device Olm session, however, that may be a sign that the homeserver is dropping messages.

Unstable prefix

This proposal does not add any new API endpoints, but does add some new fields and message types to existing data structures. These field names and message types will be prefixed with org.matrix.msc3834.v1. Test implementations can identify the TSK as org.matrix.msc3834.v1.cross_signing.tofu_signing, use the optional field org.matrix.msc3834.v1.tofu_signing_key for the keys/device_signing/upload endpoint, and use the message types org.matrix.msc3834.v1.signatures_hash_request and org.matrix.msc3834.v1.signatures_hash for exchanging hashes of the set of cross-signing signatures.

Migration notes

When a device with this functionality first comes online, if the user doesn't already have a TSK and if the device possesses the private MSK, it should create a new TSK, sign it with the MSK, and publish it to keys/device_signing/upload. This endpoint requires authentication, and therefore the user may need to be prompted for a password when they open their upgraded client. If the user already has server-side secret storage set up, the device should also store the private TSK encrypted in secret storage.

If the user does already have a TSK, devices should obtain the private key either from secret storage or by requesting the secret from other devices. In the event of a race condition where multiple devices have upgraded and created TSKs, the TSK whose base64 representation comes first lexicographically will take precedence. Once other devices have received the private key for the winning TSK, they should use it to re-sign and re-submit any TOFU signatures they've already created, and replace any signatures by the old TSK in their persistent records.