@@ -845,9 +845,17 @@ impl OlmMachine {
845
845
846
846
/// Decrypt and handle a to-device event.
847
847
///
848
- /// If decryption (or checking the sender device) fails, returns
848
+ /// If decryption (or checking the sender device) fails, returns an
849
849
/// `Err(DecryptToDeviceError::OlmError)`.
850
850
///
851
+ /// If we are in strict "exclude insecure devices" mode and the sender
852
+ /// device is not verified, and the decrypted event type is not on the
853
+ /// allow list, returns `Err(DecryptToDeviceError::UnverifiedSender)`
854
+ ///
855
+ /// (The allow list of types that are processed even if the sender is
856
+ /// unverified is: `m.room_key`, `m.room_key.withheld`,
857
+ /// `m.room_key_request`, `m.secret.request` and `m.key.verification.*`.)
858
+ ///
851
859
/// If the sender device is dehydrated, does no handling and immediately
852
860
/// returns `Err(DecryptToDeviceError::FromDehydratedDevice)`.
853
861
///
@@ -862,12 +870,16 @@ impl OlmMachine {
862
870
transaction : & mut StoreTransaction ,
863
871
event : & EncryptedToDeviceEvent ,
864
872
changes : & mut Changes ,
865
- _decryption_settings : & DecryptionSettings ,
873
+ decryption_settings : & DecryptionSettings ,
866
874
) -> Result < OlmDecryptionInfo , DecryptToDeviceError > {
867
875
// Decrypt the event
868
- let mut decrypted =
876
+ let decrypted =
869
877
transaction. account ( ) . await ?. decrypt_to_device_event ( & self . inner . store , event) . await ?;
870
878
879
+ let mut decrypted = self
880
+ . check_to_device_is_from_verified_device_or_allowed_type ( decryption_settings, decrypted)
881
+ . await ?;
882
+
871
883
// Return early if the sending device is decrypted
872
884
self . check_to_device_event_is_not_from_dehydrated_device ( & decrypted, & event. sender ) . await ?;
873
885
@@ -1324,7 +1336,10 @@ impl OlmMachine {
1324
1336
1325
1337
match event {
1326
1338
// These are handled here because we accept them either plaintext or
1327
- // encrypted
1339
+ // encrypted.
1340
+ //
1341
+ // Note: this list should match the allowed types in
1342
+ // check_to_device_is_from_verified_device_or_allowed_type
1328
1343
RoomKeyRequest ( e) => self . inner . key_request_machine . receive_incoming_key_request ( e) ,
1329
1344
SecretRequest ( e) => self . inner . key_request_machine . receive_incoming_secret_request ( e) ,
1330
1345
RoomKeyWithheld ( e) => self . add_withheld_info ( changes, e) ,
@@ -1426,8 +1441,14 @@ impl OlmMachine {
1426
1441
///
1427
1442
/// Return the same event, decrypted if possible.
1428
1443
///
1429
- /// If we can identify that this to-device event came from a dehydrated
1430
- /// device, this method does not process it, and returns `None`.
1444
+ /// If we are in strict "exclude insecure devices" mode and the sender
1445
+ /// device is not verified, and the decrypted event type is not on the
1446
+ /// allow list, or if this event comes from a dehydrated device, this method
1447
+ /// does not process it, and returns `None`.
1448
+ ///
1449
+ /// (The allow list of types that are processed even if the sender is
1450
+ /// unverified is: `m.room_key`, `m.room_key.withheld`,
1451
+ /// `m.room_key_request`, `m.secret.request` and `m.key.verification.*`.)
1431
1452
async fn receive_encrypted_to_device_event (
1432
1453
& self ,
1433
1454
transaction : & mut StoreTransaction ,
@@ -1456,6 +1477,12 @@ impl OlmMachine {
1456
1477
return Some ( ProcessedToDeviceEvent :: UnableToDecrypt ( raw_event) ) ;
1457
1478
}
1458
1479
Err ( DecryptToDeviceError :: FromDehydratedDevice ) => return None ,
1480
+ Err ( DecryptToDeviceError :: UnverifiedSender ( olm_decryption_info) ) => {
1481
+ return Some ( ProcessedToDeviceEvent :: UnverifiedSender {
1482
+ raw : olm_decryption_info. result . raw_event ,
1483
+ encryption_info : olm_decryption_info. result . encryption_info ,
1484
+ } )
1485
+ }
1459
1486
} ;
1460
1487
1461
1488
// New sessions modify the account so we need to save that
@@ -1493,6 +1520,66 @@ impl OlmMachine {
1493
1520
} )
1494
1521
}
1495
1522
1523
+ async fn check_to_device_is_from_verified_device_or_allowed_type (
1524
+ & self ,
1525
+ decryption_settings : & DecryptionSettings ,
1526
+ decrypted : OlmDecryptionInfo ,
1527
+ ) -> Result < OlmDecryptionInfo , DecryptToDeviceError > {
1528
+ let event_type = decrypted. result . event . event_type ( ) ;
1529
+
1530
+ // If we're in "exclude insecure devices" mode, we prevent most
1531
+ // to-device events with unverified senders from being allowed
1532
+ // through here, but there are some exceptions:
1533
+ //
1534
+ // * m.room_key - we hold on to these until later, so if the sender becomes
1535
+ // verified later we can still use the key.
1536
+ //
1537
+ // * m.room_key_request, m.room_key.withheld, m.key.verification.*,
1538
+ // m.secret.request - these are allowed as plaintext events, so we also allow
1539
+ // them encrypted from insecure devices. Note: the list of allowed types here
1540
+ // should match with what is allowed in handle_to_device_event.
1541
+ match event_type {
1542
+ "m.room_key"
1543
+ | "m.room_key.withheld"
1544
+ | "m.room_key_request"
1545
+ | "m.secret.request"
1546
+ | "m.key.verification.key"
1547
+ | "m.key.verification.mac"
1548
+ | "m.key.verification.done"
1549
+ | "m.key.verification.ready"
1550
+ | "m.key.verification.start"
1551
+ | "m.key.verification.accept"
1552
+ | "m.key.verification.cancel"
1553
+ | "m.key.verification.request" => {
1554
+ // This is one of the exception types - we allow it even if the sender device is
1555
+ // not verified.
1556
+ Ok ( decrypted)
1557
+ }
1558
+ _ => {
1559
+ // This is not an exception type - check for "exclude insecure devices" mode,
1560
+ // and whether the sender is verified.
1561
+
1562
+ let exclude_unverified_devices = match decryption_settings
1563
+ . sender_device_trust_requirement
1564
+ {
1565
+ TrustRequirement :: Untrusted => false ,
1566
+ TrustRequirement :: CrossSignedOrLegacy | TrustRequirement :: CrossSigned => true ,
1567
+ } ;
1568
+
1569
+ if exclude_unverified_devices
1570
+ && sending_device_is_unverified ( & decrypted. result . encryption_info )
1571
+ {
1572
+ // Refuse to decrypt - the sender is unverified
1573
+ Err ( DecryptToDeviceError :: UnverifiedSender ( decrypted) )
1574
+ } else {
1575
+ // Either we're not excluding insecure devices, or the sender is verified, so
1576
+ // allow decryption to continue.
1577
+ Ok ( decrypted)
1578
+ }
1579
+ }
1580
+ }
1581
+ }
1582
+
1496
1583
/// Return an error if the supplied to-device event was sent from a
1497
1584
/// dehydrated device.
1498
1585
async fn check_to_device_event_is_not_from_dehydrated_device (
@@ -1594,6 +1681,15 @@ impl OlmMachine {
1594
1681
/// If any of the to-device events in the supplied changes were sent from
1595
1682
/// dehydrated devices, these are not processed, and are omitted from
1596
1683
/// the returned list, as per MSC3814.
1684
+ ///
1685
+ /// If we are in strict "exclude insecure devices" mode and the sender
1686
+ /// device of any event is not verified, and the decrypted event type is not
1687
+ /// on the allow list, these events are not processed and are omitted from
1688
+ /// the returned list.
1689
+ ///
1690
+ /// (The allow list of types that are processed even if the sender is
1691
+ /// unverified is: `m.room_key`, `m.room_key.withheld`,
1692
+ /// `m.room_key_request`, `m.secret.request` and `m.key.verification.*`.)
1597
1693
pub ( crate ) async fn preprocess_sync_changes (
1598
1694
& self ,
1599
1695
transaction : & mut StoreTransaction ,
@@ -2842,6 +2938,28 @@ impl OlmMachine {
2842
2938
}
2843
2939
}
2844
2940
2941
+ fn sending_device_is_unverified ( encryption_info : & EncryptionInfo ) -> bool {
2942
+ if let VerificationState :: Unverified ( level) = & encryption_info. verification_state {
2943
+ // Sender is not fully verified
2944
+ match level {
2945
+ VerificationLevel :: UnverifiedIdentity => {
2946
+ // The user's identity is only pinned: fine
2947
+ false
2948
+ }
2949
+ VerificationLevel :: VerificationViolation
2950
+ | VerificationLevel :: UnsignedDevice
2951
+ | VerificationLevel :: None ( _)
2952
+ | VerificationLevel :: MismatchedSender => {
2953
+ // The device is not verified or the user is in verification violation: not fine
2954
+ true
2955
+ }
2956
+ }
2957
+ } else {
2958
+ // Verified sender: fine
2959
+ false
2960
+ }
2961
+ }
2962
+
2845
2963
fn sender_data_to_verification_state (
2846
2964
sender_data : SenderData ,
2847
2965
session_has_been_imported : bool ,
@@ -2960,14 +3078,27 @@ fn megolm_error_to_utd_info(
2960
3078
Ok ( UnableToDecryptInfo { session_id, reason } )
2961
3079
}
2962
3080
2963
- /// An error that can occur during [`OlmMachine::decrypt_to_device_event`] -
2964
- /// either because decryption failed, or because the sender device was a
2965
- /// dehydrated device, which should never send any to-device messages.
3081
+ /// An error that can occur during [`OlmMachine::decrypt_to_device_event`]:
3082
+ ///
3083
+ /// * because decryption failed, or
3084
+ ///
3085
+ /// * because the sender device was not verified when we are in strict "exclude
3086
+ /// insecure devices" mode, or
3087
+ ///
3088
+ /// * because the sender device was a dehydrated device, which should never send
3089
+ /// any to-device messages.
2966
3090
#[ derive( Debug , thiserror:: Error ) ]
2967
3091
pub ( crate ) enum DecryptToDeviceError {
2968
3092
#[ error( "An Olm error occurred meaning we failed to decrypt the event" ) ]
2969
3093
OlmError ( #[ from] OlmError ) ,
2970
3094
3095
+ #[ error(
3096
+ "We were able to decrypt the event, but the sender device was not \
3097
+ verified, and we have 'exclude insecure devices' enabled, so we \
3098
+ choose not to use this event."
3099
+ ) ]
3100
+ UnverifiedSender ( OlmDecryptionInfo ) ,
3101
+
2971
3102
#[ error( "The event was sent from a dehydrated device" ) ]
2972
3103
FromDehydratedDevice ,
2973
3104
}
@@ -2988,6 +3119,9 @@ impl From<DecryptToDeviceError> for OlmError {
2988
3119
DecryptToDeviceError :: FromDehydratedDevice => {
2989
3120
panic ! ( "Expected an OlmError but found FromDehydratedDevice" )
2990
3121
}
3122
+ DecryptToDeviceError :: UnverifiedSender ( _) => {
3123
+ panic ! ( "Expected and OlmError but found UnverifiedSender" )
3124
+ }
2991
3125
}
2992
3126
}
2993
3127
}
0 commit comments