diff --git a/crates/matrix-sdk-crypto/src/identities/device.rs b/crates/matrix-sdk-crypto/src/identities/device.rs index 3ba6ac0f2..b336559f6 100644 --- a/crates/matrix-sdk-crypto/src/identities/device.rs +++ b/crates/matrix-sdk-crypto/src/identities/device.rs @@ -160,10 +160,82 @@ impl Device { /// can be confirmed as the creator and owner of the `m.room_key`. pub fn is_owner_of_session(&self, session: &InboundGroupSession) -> Result { if session.has_been_imported() { + // An imported room key means that we did not receive the room key as a + // `m.room_key` event when the room key was initially exchanged. + // + // This could mean a couple of things: + // 1. We received the room key as a `m.forwarded_room_key`. + // 2. We imported the room key through a file export. + // 3. We imported the room key through a backup. + // + // To be certain that a `Device` is the owner of a room key we need to have a + // proof that the `Curve25519` key of this `Device` was used to + // initially exchange the room key. This proof is provided by the Olm decryption + // step, see below for further clarification. + // + // Each of the above room key methods that receive room keys do not contain this + // proof and we received only a claim that the room key is tied to a + // `Curve25519` key. + // + // Since there's no way to verify that the claim is true, we say that we don't + // know that the room key belongs to this device. Ok(false) } else if let Some(key) = session.signing_keys.get(&DeviceKeyAlgorithm::Ed25519).and_then(|k| k.ed25519()) { + // Room keys are received as an `m.room.encrypted` event using the `m.olm` + // algorithm. Upon decryption of the `m.room.encrypted` event, the + // decrypted content will contain also a `Ed25519` public key[1]. + // + // The inclusion of this key means that the `Curve25519` key of the `Device` and + // Olm `Session`, established using the DH authentication of the + // double ratchet, binds the `Ed25519` key of the `Device` + // + // On the other hand, the `Ed25519` key is binding the `Curve25519` key + // using a signature which is uploaded to the server as + // `device_keys` and downloaded by us using a `/keys/query` request. + // + // A `Device` is considered to be the owner of a room key iff: + // 1. The `Curve25519` key that was used to establish the Olm `Session` + // that was used to decrypt the event is binding the `Ed25519`key + // of this `Device`. + // 2. The `Ed25519` key of this device has signed a `device_keys` object + // that contains the `Curve25519` key from step 1. + // + // We don't need to check the signature of the `Device` here, since we don't + // accept a `Device` unless it has a valid `Ed25519` signature. + // + // We do check that the `Curve25519` that was used to decrypt the event carrying + // the `m.room_key` and the `Ed25519` key that was part of the + // decrypted content matches the keys found in this `Device`. + // + // ```text + // ┌───────────────────────┐ + // │ EncryptedToDeviceEvent│ + // └───────────────────────┘ + // │ + // ┌──────────────────────────────────┐ │ + // │ Device │ ▼ + // ├──────────────────────────────────┤ ┌──────────────────┐ + // │ Device Keys │ │ Session │ + // ├────────────────┬─────────────────┤ ├──────────────────┤ + // │ Ed25519 Key │ Curve25519 Key │◄──────►│ Curve25519 Key │ + // └────────────────┴─────────────────┘ └──────────────────┘ + // ▲ │ + // │ │ + // │ │ Decrypt + // │ │ + // │ ▼ + // │ ┌───────────────────────┐ + // │ │ DecryptedOlmV1Event │ + // │ ├───────────────────────┤ + // │ │ keys │ + // │ ├───────────────────────┤ + // └────────────────────────────────►│ Ed25519 Key │ + // └───────────────────────┘ + // ``` + // + // [1]: https://spec.matrix.org/v1.5/client-server-api/#molmv1curve25519-aes-sha2 let ed25519_comparison = self.ed25519_key().map(|k| k == key); let curve25519_comparison = self.curve25519_key().map(|k| k == session.sender_key);