Skip to content

Commit 2a4b503

Browse files
committed
crypto: rewrite check_sender_trust_requirement to use VerficationState
There are two reasons for this. Firstly. we've already done a bunch of work to map `SenderData` into a `VerificationState`, and the decision tree from `VerificationState` to allow/reject is simpler than going from `SenderData`, even if we have to fudge it a bit to get the "legacy" flag. (Note that it allows us to get rid of an `unreachable!` panic.) Secondly, `VerficationState` represents the state of an *event*, whereas `SenderData` is about the session as a whole. A session can be fine, whilst event (claiming to be) encrypted with it can be suspect. What we want here is to check a specific message. Currently, this doesn't make any functional difference, but conceptually it's cleaner to check the `VerificationState`.
1 parent c0e45a2 commit 2a4b503

File tree

1 file changed

+47
-37
lines changed
  • crates/matrix-sdk-crypto/src/machine

1 file changed

+47
-37
lines changed

crates/matrix-sdk-crypto/src/machine/mod.rs

Lines changed: 47 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,7 @@ use tokio::sync::Mutex;
5353
use tracing::{
5454
debug, error,
5555
field::{debug, display},
56-
info, instrument, warn, Span,
56+
info, instrument, trace, warn, Span,
5757
};
5858
use vodozemac::{
5959
megolm::{DecryptionError, SessionOrdering},
@@ -1786,52 +1786,62 @@ impl OlmMachine {
17861786
}
17871787
}
17881788

1789-
/// Check that the sender of a Megolm session satisfies the trust
1789+
/// Check that a Megolm event satisfies the sender trust
17901790
/// requirement from the decryption settings.
1791+
///
1792+
/// If the requirement is not satisfied, returns
1793+
/// [`MegolmError::SenderIdentityNotTrusted`].
17911794
fn check_sender_trust_requirement(
17921795
&self,
17931796
session: &InboundGroupSession,
17941797
encryption_info: &EncryptionInfo,
17951798
trust_requirement: &TrustRequirement,
17961799
) -> MegolmResult<()> {
1797-
/// Get the error from the encryption information.
1798-
fn encryption_info_to_error(encryption_info: &EncryptionInfo) -> MegolmResult<()> {
1799-
// When this is called, the verification state *must* be unverified,
1800-
// otherwise the sender_data would have been SenderVerified
1801-
let VerificationState::Unverified(verification_level) =
1802-
&encryption_info.verification_state
1803-
else {
1804-
unreachable!("inconsistent verification state");
1805-
};
1806-
Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
1807-
}
1800+
trace!(
1801+
verification_state = ?encryption_info.verification_state,
1802+
?trust_requirement, "check_sender_trust_requirement",
1803+
);
18081804

1809-
match trust_requirement {
1810-
TrustRequirement::Untrusted => Ok(()),
1811-
1812-
TrustRequirement::CrossSignedOrLegacy => match &session.sender_data {
1813-
// Reject if the sender was previously verified, but changed
1814-
// their identity and is not verified any more.
1815-
SenderData::VerificationViolation(..) => Err(
1816-
MegolmError::SenderIdentityNotTrusted(VerificationLevel::VerificationViolation),
1817-
),
1818-
SenderData::SenderUnverified(..) => Ok(()),
1819-
SenderData::SenderVerified(..) => Ok(()),
1820-
SenderData::DeviceInfo { legacy_session: true, .. } => Ok(()),
1821-
SenderData::UnknownDevice { legacy_session: true, .. } => Ok(()),
1822-
_ => encryption_info_to_error(encryption_info),
1823-
},
1805+
// VerificationState::Verified is acceptable for all TrustRequirement levels, so
1806+
// let's get that out of the way
1807+
let verification_level = match &encryption_info.verification_state {
1808+
VerificationState::Verified => return Ok(()),
1809+
VerificationState::Unverified(verification_level) => verification_level,
1810+
};
1811+
1812+
let ok = match trust_requirement {
1813+
TrustRequirement::Untrusted => true,
1814+
1815+
TrustRequirement::CrossSignedOrLegacy => {
1816+
// `VerificationLevel::UnsignedDevice` and `VerificationLevel::None` correspond
1817+
// to `SenderData::DeviceInfo` and `SenderData::UnknownDevice`
1818+
// respectively, and those cases may be acceptable if the reason
1819+
// for the lack of data is that the sessions were established
1820+
// before we started collecting SenderData.
1821+
let legacy_session = match &session.sender_data {
1822+
SenderData::DeviceInfo { legacy_session, .. } => legacy_session,
1823+
SenderData::UnknownDevice { legacy_session, .. } => legacy_session,
1824+
_ => &false,
1825+
};
1826+
1827+
match (verification_level, legacy_session) {
1828+
(VerificationLevel::UnverifiedIdentity, _) => true,
1829+
(VerificationLevel::UnsignedDevice, true) => true,
1830+
(VerificationLevel::None(_), true) => true,
1831+
_ => false,
1832+
}
1833+
}
18241834

1825-
TrustRequirement::CrossSigned => match &session.sender_data {
1826-
// Reject if the sender was previously verified, but changed
1827-
// their identity and is not verified any more.
1828-
SenderData::VerificationViolation(..) => Err(
1829-
MegolmError::SenderIdentityNotTrusted(VerificationLevel::VerificationViolation),
1830-
),
1831-
SenderData::SenderUnverified(..) => Ok(()),
1832-
SenderData::SenderVerified(..) => Ok(()),
1833-
_ => encryption_info_to_error(encryption_info),
1835+
TrustRequirement::CrossSigned => match verification_level {
1836+
VerificationLevel::UnverifiedIdentity => true,
1837+
_ => false,
18341838
},
1839+
};
1840+
1841+
if ok {
1842+
Ok(())
1843+
} else {
1844+
Err(MegolmError::SenderIdentityNotTrusted(verification_level.clone()))
18351845
}
18361846
}
18371847

0 commit comments

Comments
 (0)