diff --git a/crates/matrix-sdk-crypto/src/identities/device.rs b/crates/matrix-sdk-crypto/src/identities/device.rs index af2937058..b017d1537 100644 --- a/crates/matrix-sdk-crypto/src/identities/device.rs +++ b/crates/matrix-sdk-crypto/src/identities/device.rs @@ -47,7 +47,7 @@ use crate::{ forwarded_room_key::ForwardedRoomKeyContent, room::encrypted::ToDeviceEncryptedEventContent, EventType, }, - DeviceKey, DeviceKeys, Signatures, SignedKey, + DeviceKey, DeviceKeys, Signatures, SignedKey, SigningKey, }, verification::VerificationMachine, OutgoingVerificationRequest, ReadOnlyAccount, Sas, ToDeviceRequest, VerificationRequest, @@ -141,6 +141,35 @@ impl Device { } } + /// Is this our own device. + pub fn is_our_own_device(&self) -> bool { + let own_ed25519_key = self.verification_machine.store.account.identity_keys().ed25519; + let own_curve25519_key = self.verification_machine.store.account.identity_keys().curve25519; + + self.user_id() == self.verification_machine.own_user_id() + && self.device_id() == self.verification_machine.own_device_id() + && self.ed25519_key().map(|k| k == own_ed25519_key).unwrap_or(false) + && self.curve25519_key().map(|k| k == own_curve25519_key).unwrap_or(false) + } + + /// Does the given `InboundGroupSession` belong to this device. + /// + /// An `InboundGroupSession` is exchanged between devices as an Olm + /// encrypted `m.room_key` event. This method determines if this `Device` + /// can be confirmed as the creator and owner of the `m.room_key`. + pub fn is_owner_of_session(&self, session: &InboundGroupSession) -> bool { + if session.has_been_imported() { + false + } else if let Some(SigningKey::Ed25519(key)) = + session.signing_keys.get(&DeviceKeyAlgorithm::Ed25519) + { + self.ed25519_key().map(|k| k == *key).unwrap_or(false) + && self.curve25519_key().map(|k| k == session.sender_key).unwrap_or(false) + } else { + false + } + } + /// Request an interacitve verification with this `Device` /// /// Returns a `VerificationRequest` object and a to-device request that diff --git a/crates/matrix-sdk-crypto/src/machine.rs b/crates/matrix-sdk-crypto/src/machine.rs index 1d27ecc72..bff468eb2 100644 --- a/crates/matrix-sdk-crypto/src/machine.rs +++ b/crates/matrix-sdk-crypto/src/machine.rs @@ -1002,27 +1002,52 @@ impl OlmMachine { .await?) } + async fn get_verification_state( + &self, + session: &InboundGroupSession, + sender: &UserId, + device_id: &DeviceId, + ) -> StoreResult { + Ok( + // First find the device from the Curve25519 key that was recorded + // when we decrypted the room_key. + if let Some(device) = self + .get_device(sender, device_id, None) + .await? + .filter(|d| d.curve25519_key().map(|k| k == session.sender_key()).unwrap_or(false)) + { + // If the `Device` is confirmed to be the owner of the + // `InboundGroupSession` we will consider the room key, and by + // extension any events that are encrypted using this room key, + // to be trusted if: + // a) This is our own device + // b) The device itself is considered to be trusted + if device.is_owner_of_session(session) + && (device.is_our_own_device() || device.verified()) + { + VerificationState::Trusted + } else { + VerificationState::Untrusted + } + } else { + // We didn't find a device, no way to know if we should trust + // the `InboundGroupSession` or not. + VerificationState::UnknownDevice + }, + ) + } + + /// Get the `EncryptionInfo` of an `InboundGroupSession`. + /// + /// This determines if the events that a given `InboundGroupSession` + /// decrypts are considered to be trusted. async fn get_encryption_info( &self, session: &InboundGroupSession, sender: &UserId, device_id: &DeviceId, ) -> StoreResult { - let verification_state = if let Some(device) = self - .get_device(sender, device_id, None) - .await? - .filter(|d| d.curve25519_key().map(|k| k == session.sender_key()).unwrap_or(false)) - { - if (self.user_id() == device.user_id() && self.device_id() == device.device_id()) - || device.verified() - { - VerificationState::Trusted - } else { - VerificationState::Untrusted - } - } else { - VerificationState::UnknownDevice - }; + let verification_state = self.get_verification_state(session, sender, device_id).await?; let sender = sender.to_owned(); let device_id = device_id.to_owned(); diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs index ac5cbd849..778969b6d 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs @@ -327,6 +327,12 @@ impl InboundGroupSession { self.first_known_index } + /// Has the session been imported from a file, or backup, or has it been + /// directly received as an `m.room_key` event. + pub fn has_been_imported(&self) -> bool { + self.imported + } + /// Check if the `InboundGroupSession` is better than the given other /// `InboundGroupSession` pub async fn compare(&self, other: &InboundGroupSession) -> SessionOrdering {