@@ -57,7 +57,7 @@ use tracing::trace;
57
57
use tracing:: {
58
58
debug, error,
59
59
field:: { debug, display} ,
60
- info, instrument, warn, Span ,
60
+ info, instrument, trace , warn, Span ,
61
61
} ;
62
62
use vodozemac:: {
63
63
megolm:: { DecryptionError , SessionOrdering } ,
@@ -1834,52 +1834,85 @@ impl OlmMachine {
1834
1834
}
1835
1835
}
1836
1836
1837
- /// Check that the sender of a Megolm session satisfies the trust
1837
+ /// Check that a Megolm event satisfies the sender trust
1838
1838
/// requirement from the decryption settings.
1839
+ ///
1840
+ /// If the requirement is not satisfied, returns
1841
+ /// [`MegolmError::SenderIdentityNotTrusted`].
1839
1842
fn check_sender_trust_requirement (
1840
1843
& self ,
1841
1844
session : & InboundGroupSession ,
1842
1845
encryption_info : & EncryptionInfo ,
1843
1846
trust_requirement : & TrustRequirement ,
1844
1847
) -> MegolmResult < ( ) > {
1845
- /// Get the error from the encryption information.
1846
- fn encryption_info_to_error ( encryption_info : & EncryptionInfo ) -> MegolmResult < ( ) > {
1847
- // When this is called, the verification state *must* be unverified,
1848
- // otherwise the sender_data would have been SenderVerified
1849
- let VerificationState :: Unverified ( verification_level) =
1850
- & encryption_info. verification_state
1851
- else {
1852
- unreachable ! ( "inconsistent verification state" ) ;
1853
- } ;
1854
- Err ( MegolmError :: SenderIdentityNotTrusted ( verification_level. clone ( ) ) )
1855
- }
1848
+ trace ! (
1849
+ verification_state = ?encryption_info. verification_state,
1850
+ ?trust_requirement, "check_sender_trust_requirement" ,
1851
+ ) ;
1856
1852
1857
- match trust_requirement {
1858
- TrustRequirement :: Untrusted => Ok ( ( ) ) ,
1859
-
1860
- TrustRequirement :: CrossSignedOrLegacy => match & session. sender_data {
1861
- // Reject if the sender was previously verified, but changed
1862
- // their identity and is not verified any more.
1863
- SenderData :: VerificationViolation ( ..) => Err (
1864
- MegolmError :: SenderIdentityNotTrusted ( VerificationLevel :: VerificationViolation ) ,
1865
- ) ,
1866
- SenderData :: SenderUnverified ( ..) => Ok ( ( ) ) ,
1867
- SenderData :: SenderVerified ( ..) => Ok ( ( ) ) ,
1868
- SenderData :: DeviceInfo { legacy_session : true , .. } => Ok ( ( ) ) ,
1869
- SenderData :: UnknownDevice { legacy_session : true , .. } => Ok ( ( ) ) ,
1870
- _ => encryption_info_to_error ( encryption_info) ,
1871
- } ,
1853
+ // VerificationState::Verified is acceptable for all TrustRequirement levels, so
1854
+ // let's get that out of the way
1855
+ let verification_level = match & encryption_info. verification_state {
1856
+ VerificationState :: Verified => return Ok ( ( ) ) ,
1857
+ VerificationState :: Unverified ( verification_level) => verification_level,
1858
+ } ;
1859
+
1860
+ let ok = match trust_requirement {
1861
+ TrustRequirement :: Untrusted => true ,
1862
+
1863
+ TrustRequirement :: CrossSignedOrLegacy => {
1864
+ // `VerificationLevel::UnsignedDevice` and `VerificationLevel::None` correspond
1865
+ // to `SenderData::DeviceInfo` and `SenderData::UnknownDevice`
1866
+ // respectively, and those cases may be acceptable if the reason
1867
+ // for the lack of data is that the sessions were established
1868
+ // before we started collecting SenderData.
1869
+ let legacy_session = match session. sender_data {
1870
+ SenderData :: DeviceInfo { legacy_session, .. } => legacy_session,
1871
+ SenderData :: UnknownDevice { legacy_session, .. } => legacy_session,
1872
+ _ => false ,
1873
+ } ;
1872
1874
1873
- TrustRequirement :: CrossSigned => match & session. sender_data {
1874
- // Reject if the sender was previously verified, but changed
1875
- // their identity and is not verified any more.
1876
- SenderData :: VerificationViolation ( ..) => Err (
1877
- MegolmError :: SenderIdentityNotTrusted ( VerificationLevel :: VerificationViolation ) ,
1878
- ) ,
1879
- SenderData :: SenderUnverified ( ..) => Ok ( ( ) ) ,
1880
- SenderData :: SenderVerified ( ..) => Ok ( ( ) ) ,
1881
- _ => encryption_info_to_error ( encryption_info) ,
1875
+ // In the CrossSignedOrLegacy case the following rules apply:
1876
+ //
1877
+ // 1. Identities we have not yet verified can be decrypted regardless of the
1878
+ // legacy state of the session.
1879
+ // 2. Devices that aren't signed by the owning identity of the device can only
1880
+ // be decrypted if it's a legacy session.
1881
+ // 3. If we have no information about the device, we should only decrypt if it's
1882
+ // a legacy session.
1883
+ // 4. Anything else, should throw an error.
1884
+ match ( verification_level, legacy_session) {
1885
+ // Case 1
1886
+ ( VerificationLevel :: UnverifiedIdentity , _) => true ,
1887
+
1888
+ // Case 2
1889
+ ( VerificationLevel :: UnsignedDevice , true ) => true ,
1890
+
1891
+ // Case 3
1892
+ ( VerificationLevel :: None ( _) , true ) => true ,
1893
+
1894
+ // Case 4
1895
+ ( VerificationLevel :: VerificationViolation , _)
1896
+ | ( VerificationLevel :: UnsignedDevice , false )
1897
+ | ( VerificationLevel :: None ( _) , false ) => false ,
1898
+ }
1899
+ }
1900
+
1901
+ // If cross-signing of identities is required, the only acceptable unverified case
1902
+ // is when the identity is signed but not yet verified by us.
1903
+ TrustRequirement :: CrossSigned => match verification_level {
1904
+ VerificationLevel :: UnverifiedIdentity => true ,
1905
+
1906
+ VerificationLevel :: VerificationViolation
1907
+ | VerificationLevel :: UnsignedDevice
1908
+ | VerificationLevel :: None ( _) => false ,
1882
1909
} ,
1910
+ } ;
1911
+
1912
+ if ok {
1913
+ Ok ( ( ) )
1914
+ } else {
1915
+ Err ( MegolmError :: SenderIdentityNotTrusted ( verification_level. clone ( ) ) )
1883
1916
}
1884
1917
}
1885
1918
0 commit comments