@@ -1541,13 +1541,17 @@ impl Account {
1541
1541
1542
1542
/// Look up the [`Device`] that sent us a successfully-decrypted event.
1543
1543
///
1544
- /// Also validates the `sender_device_keys` field, if present.
1544
+ /// We first look for the sender device in our store; if it is found then we
1545
+ /// return that (having checked that the keys match). If the device is
1546
+ /// not found in the store, we return the details
1547
+ /// from `sender_device_keys`, if present. If the device is not in the
1548
+ /// store, and the event lacks `sender_device_keys`, an error is returned.
1549
+ ///
1550
+ /// Also validates the `sender_device_keys` field, if present, regardless of
1551
+ /// whether it is used.
1545
1552
///
1546
1553
/// `m.room_key` events are special-cased and return `None`: we look up
1547
1554
/// their devices later on.
1548
- ///
1549
- /// For other events, we look up the device in the store, and return the
1550
- /// details.
1551
1555
async fn get_event_sender_device (
1552
1556
store : & Store ,
1553
1557
sender_key : Curve25519PublicKey ,
@@ -1557,7 +1561,7 @@ impl Account {
1557
1561
// WARN: If you move or modify this check, ensure that the code below is still
1558
1562
// valid. The processing of the historic room key bundle depends on this being
1559
1563
// here.
1560
- Self :: check_sender_device_keys ( event, sender_key) ?;
1564
+ let sender_device_keys = Self :: check_sender_device_keys ( event, sender_key) ?;
1561
1565
if let AnyDecryptedOlmEvent :: RoomKey ( _) = event {
1562
1566
// If this event is an `m.room_key` event, defer the check for
1563
1567
// the Ed25519 key of the sender until we decrypt room events.
@@ -1569,23 +1573,41 @@ impl Account {
1569
1573
// MSC4268 requires room key bundle events to have a `sender_device_keys` field.
1570
1574
// Enforce that now.
1571
1575
if let AnyDecryptedOlmEvent :: RoomKeyBundle ( _) = event {
1572
- event . sender_device_keys ( ) . ok_or ( EventError :: MissingSigningKey ) . inspect_err ( |_| {
1576
+ sender_device_keys. ok_or ( EventError :: MissingSigningKey ) . inspect_err ( |_| {
1573
1577
warn ! ( "The room key bundle was missing the sender device keys in the event" )
1574
1578
} ) ?;
1575
1579
}
1576
1580
1577
- let device = store
1578
- . get_device_from_curve_key ( event. sender ( ) , sender_key)
1579
- . await ?
1580
- . ok_or ( EventError :: MissingSigningKey ) ?;
1581
+ // For event types other than `m.room_key`, we need to look up the device in the
1582
+ // database irrespective of whether the `sender_device_keys` field is
1583
+ // present in the event, because it may have been marked as "locally
1584
+ // trusted" in the database.
1585
+ let store_device = store. get_device_from_curve_key ( event. sender ( ) , sender_key) . await ?;
1586
+
1587
+ match ( store_device, sender_device_keys) {
1588
+ // If the device is in the database, it had better have an Ed25519 key which
1589
+ // matches that in the event.
1590
+ ( Some ( device) , _) => {
1591
+ let key = device. ed25519_key ( ) . ok_or ( EventError :: MissingSigningKey ) ?;
1592
+ if key != event. keys ( ) . ed25519 {
1593
+ return Err ( EventError :: MismatchedKeys (
1594
+ key. into ( ) ,
1595
+ event. keys ( ) . ed25519 . into ( ) ,
1596
+ )
1597
+ . into ( ) ) ;
1598
+ }
1599
+ Ok ( Some ( device) )
1600
+ }
1581
1601
1582
- let key = device. ed25519_key ( ) . ok_or ( EventError :: MissingSigningKey ) ?;
1602
+ ( None , Some ( sender_device_keys) ) => {
1603
+ // We have already validated the signature on `sender_device_keys`, so this
1604
+ // try_into cannot fail.
1605
+ let sender_device_data = sender_device_keys. try_into ( ) . unwrap ( ) ;
1606
+ Ok ( Some ( store. wrap_device_data ( sender_device_data) . await ?) )
1607
+ }
1583
1608
1584
- if key != event. keys ( ) . ed25519 {
1585
- return Err ( EventError :: MismatchedKeys ( key. into ( ) , event. keys ( ) . ed25519 . into ( ) ) . into ( ) ) ;
1609
+ ( None , None ) => Err ( OlmError :: EventError ( EventError :: MissingSigningKey ) ) ,
1586
1610
}
1587
-
1588
- Ok ( Some ( device) )
1589
1611
}
1590
1612
1591
1613
/// Return true if:
@@ -1733,13 +1755,18 @@ impl Account {
1733
1755
/// * `sender_key` - The Curve25519 key that the sender used to establish
1734
1756
/// the Olm session that was used to decrypt the event.
1735
1757
///
1758
+ /// # Returns
1759
+ ///
1760
+ /// A reference to the `sender_device_keys` in the event, if it exists and
1761
+ /// is valid.
1762
+ ///
1736
1763
/// [MSC4147]: https://github.com/matrix-org/matrix-spec-proposals/pull/4147
1737
1764
fn check_sender_device_keys (
1738
1765
event : & AnyDecryptedOlmEvent ,
1739
1766
sender_key : Curve25519PublicKey ,
1740
- ) -> OlmResult < ( ) > {
1767
+ ) -> OlmResult < Option < & DeviceKeys > > {
1741
1768
let Some ( sender_device_keys) = event. sender_device_keys ( ) else {
1742
- return Ok ( ( ) ) ;
1769
+ return Ok ( None ) ;
1743
1770
} ;
1744
1771
1745
1772
// Check the signature within the device_keys structure
@@ -1774,7 +1801,7 @@ impl Account {
1774
1801
return Err ( OlmError :: EventError ( EventError :: InvalidSenderDeviceKeys ) ) ;
1775
1802
}
1776
1803
1777
- Ok ( ( ) )
1804
+ Ok ( Some ( sender_device_keys ) )
1778
1805
}
1779
1806
1780
1807
/// Internal use only.
0 commit comments