@@ -1630,20 +1630,72 @@ impl OlmMachine {
16301630 self . inner . key_request_machine . request_key ( room_id, & event) . await
16311631 }
16321632
1633- /// Find whether the supplied session is verified, and provide
1634- /// explanation of what is missing/wrong if not.
1633+ /// Find whether an event decrypted via the supplied session is verified,
1634+ /// and provide explanation of what is missing/wrong if not.
1635+ ///
1636+ /// Stores the updated [`SenderData`] for the session in the store
1637+ /// if we find an updated value for it.
1638+ ///
1639+ /// # Arguments
1640+ ///
1641+ /// * `session` - The inbound Megolm session that was used to decrypt the
1642+ /// event.
1643+ /// * `sender` - The `sender` of that event (as claimed by the envelope of
1644+ /// the event).
1645+ async fn get_room_event_verification_state (
1646+ & self ,
1647+ session : & InboundGroupSession ,
1648+ sender : & UserId ,
1649+ ) -> MegolmResult < ( VerificationState , Option < OwnedDeviceId > ) > {
1650+ let sender_data = self . get_or_update_sender_data ( session, sender) . await ?;
1651+
1652+ // If the user ID in the sender data doesn't match that in the event envelope,
1653+ // this event is not from who it appears to be from.
1654+ //
1655+ // If `sender_data.user_id()` returns `None`, that means we don't have any
1656+ // information about the owner of the session (i.e. we have
1657+ // `SenderData::UnknownDevice`); in that case we fall through to the
1658+ // logic in `sender_data_to_verification_state` which will pick an appropriate
1659+ // `DeviceLinkProblem` for `VerificationLevel::None`.
1660+ let ( verification_state, device_id) = match sender_data. user_id ( ) {
1661+ Some ( i) if i != sender => {
1662+ // For backwards compatibility, we treat this the same as "Unknown device".
1663+ // TODO: use a dedicated VerificationLevel here.
1664+ (
1665+ VerificationState :: Unverified ( VerificationLevel :: None (
1666+ DeviceLinkProblem :: MissingDevice ,
1667+ ) ) ,
1668+ None ,
1669+ )
1670+ }
1671+
1672+ Some ( _) | None => {
1673+ sender_data_to_verification_state ( sender_data, session. has_been_imported ( ) )
1674+ }
1675+ } ;
1676+
1677+ Ok ( ( verification_state, device_id) )
1678+ }
1679+
1680+ /// Get an up-to-date [`SenderData`] for the given session, suitable for
1681+ /// determining if messages decrypted using that session are verified.
16351682 ///
16361683 /// Checks both the stored verification state of the session and a
16371684 /// recalculated verification state based on our current knowledge, and
16381685 /// returns the more trusted of the two.
16391686 ///
1640- /// Store the updated [`SenderData`] for this session in the store
1687+ /// Stores the updated [`SenderData`] for the session in the store
16411688 /// if we find an updated value for it.
1642- async fn get_or_update_verification_state (
1689+ ///
1690+ /// # Arguments
1691+ ///
1692+ /// * `session` - The Megolm session that was used to decrypt the event.
1693+ /// * `sender` - The claimed sender of that event.
1694+ async fn get_or_update_sender_data (
16431695 & self ,
16441696 session : & InboundGroupSession ,
16451697 sender : & UserId ,
1646- ) -> MegolmResult < ( VerificationState , Option < OwnedDeviceId > ) > {
1698+ ) -> MegolmResult < SenderData > {
16471699 /// Whether we should recalculate the Megolm sender's data, given the
16481700 /// current sender data. We only want to recalculate if it might
16491701 /// increase trust and allow us to decrypt messages that we
@@ -1664,7 +1716,24 @@ impl OlmMachine {
16641716 }
16651717
16661718 let sender_data = if should_recalculate_sender_data ( & session. sender_data ) {
1667- // The session is not sure of the sender yet. Calculate it.
1719+ // The session is not sure of the sender yet. Try to find a matching device
1720+ // belonging to the claimed sender of the recently-received event.
1721+ //
1722+ // It's worth noting that this could in theory result in unintuitive changes,
1723+ // like a session which initially appears to belong to Alice turning into a
1724+ // session which belongs to Bob [1]. This could mean that a session initially
1725+ // successfully decrypts events from Alice, but then stops decrypting those same
1726+ // events once we get an update.
1727+ //
1728+ // That's ok though: if we get good evidence that the session belongs to Bob,
1729+ // it's correct to update the session even if we previously had weak
1730+ // evidence it belonged to Alice.
1731+ //
1732+ // [1] For example: maybe Alice and Bob both publish devices with the *same*
1733+ // keys (presumably because they are colluding). Initially we think
1734+ // the session belongs to Alice, but then we do a device lookup for
1735+ // Bob, we find a matching device with a cross-signature, so prefer
1736+ // that.
16681737 let calculated_sender_data = SenderDataFinder :: find_using_curve_key (
16691738 self . store ( ) ,
16701739 session. sender_key ( ) ,
@@ -1690,7 +1759,7 @@ impl OlmMachine {
16901759 session. sender_data . clone ( )
16911760 } ;
16921761
1693- Ok ( sender_data_to_verification_state ( sender_data, session . has_been_imported ( ) ) )
1762+ Ok ( sender_data)
16941763 }
16951764
16961765 /// Request missing local secrets from our devices (cross signing private
@@ -1763,7 +1832,7 @@ impl OlmMachine {
17631832 sender : & UserId ,
17641833 ) -> MegolmResult < Arc < EncryptionInfo > > {
17651834 let ( verification_state, device_id) =
1766- self . get_or_update_verification_state ( session, sender) . await ?;
1835+ self . get_room_event_verification_state ( session, sender) . await ?;
17671836
17681837 let sender = sender. to_owned ( ) ;
17691838
@@ -2216,7 +2285,7 @@ impl OlmMachine {
22162285 self . get_session_encryption_info ( room_id, content. session_id ( ) , & event. sender ) . await
22172286 }
22182287
2219- /// Get encryption info for a megolm session.
2288+ /// Get encryption info for an event decrypted with a megolm session.
22202289 ///
22212290 /// This recalculates the [`EncryptionInfo`] data that is returned by
22222291 /// [`OlmMachine::decrypt_room_event`], based on the current
@@ -2228,7 +2297,8 @@ impl OlmMachine {
22282297 ///
22292298 /// * `room_id` - The ID of the room where the session is being used.
22302299 /// * `session_id` - The ID of the session to get information for.
2231- /// * `sender` - The user ID of the sender who created this session.
2300+ /// * `sender` - The (claimed) sender of the event where the session was
2301+ /// used.
22322302 pub async fn get_session_encryption_info (
22332303 & self ,
22342304 room_id : & RoomId ,
0 commit comments