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:
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
Reference in New Issue
Block a user