fix(crypto): Improve the code checking if a decrypted event is trusted

This now takes into account if the room key was imported, i.e. received
as a forward. We also do the check of the Ed25519 key now.
This commit is contained in:
Damir Jelić
2022-08-15 09:54:52 +02:00
parent 27d4228269
commit a4af5bf4e1
3 changed files with 76 additions and 16 deletions
@@ -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
+40 -15
View File
@@ -1002,27 +1002,52 @@ impl OlmMachine {
.await?)
}
async fn get_verification_state(
&self,
session: &InboundGroupSession,
sender: &UserId,
device_id: &DeviceId,
) -> StoreResult<VerificationState> {
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<EncryptionInfo> {
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();
@@ -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 {