From f753d478fa1e3b3f10b555724a48678fc57f5e7b Mon Sep 17 00:00:00 2001 From: Richard van der Hoff Date: Tue, 9 Dec 2025 14:05:19 +0000 Subject: [PATCH 1/5] feat: Add `forwarder_data` to `InboundGroupSession` and pickle. - Introduces `forwarder_data` to IGS and its pickled form, and a helper method to import them from `HistoricRoomKey`s. Issue: https://github.com/matrix-org/matrix-rust-sdk/issues/5109 Signed-off-by: Skye Elliot --- bindings/matrix-sdk-crypto-ffi/src/lib.rs | 1 + .../tests/decryption_verification_state.rs | 2 + crates/matrix-sdk-crypto/src/olm/account.rs | 1 + .../src/olm/group_sessions/inbound.rs | 84 ++++++++++++++ .../olm/group_sessions/sender_data_finder.rs | 1 + .../src/store/integration_tests.rs | 1 + .../src/store/memorystore.rs | 2 + crates/matrix-sdk-crypto/src/store/mod.rs | 109 +++++++++++------- .../src/crypto_store/migrations/mod.rs | 3 + .../src/crypto_store/mod.rs | 1 + .../tests/integration/encryption/backups.rs | 1 + 11 files changed, 165 insertions(+), 41 deletions(-) diff --git a/bindings/matrix-sdk-crypto-ffi/src/lib.rs b/bindings/matrix-sdk-crypto-ffi/src/lib.rs index 255f69d78..a8223e53e 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/lib.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/lib.rs @@ -506,6 +506,7 @@ fn collect_sessions( }) .collect::>()?, sender_data: SenderData::legacy(), + forwarder_data: None, room_id: RoomId::parse(session.room_id)?, imported: session.imported, backed_up: session.backed_up, diff --git a/crates/matrix-sdk-crypto/src/machine/tests/decryption_verification_state.rs b/crates/matrix-sdk-crypto/src/machine/tests/decryption_verification_state.rs index 0574d395d..bd678419e 100644 --- a/crates/matrix-sdk-crypto/src/machine/tests/decryption_verification_state.rs +++ b/crates/matrix-sdk-crypto/src/machine/tests/decryption_verification_state.rs @@ -450,6 +450,7 @@ async fn test_verification_states_multiple_device() { fake_room_id, &olm, SenderData::unknown(), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, false, @@ -468,6 +469,7 @@ async fn test_verification_states_multiple_device() { fake_room_id, &olm, SenderData::unknown(), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, false, diff --git a/crates/matrix-sdk-crypto/src/olm/account.rs b/crates/matrix-sdk-crypto/src/olm/account.rs index 290539785..30edc4fea 100644 --- a/crates/matrix-sdk-crypto/src/olm/account.rs +++ b/crates/matrix-sdk-crypto/src/olm/account.rs @@ -234,6 +234,7 @@ impl StaticAccountData { room_id, &outbound.session_key().await, own_sender_data, + None, algorithm, Some(visibility), shared_history, diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs index 9fba02ab2..b65896fd2 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs @@ -187,6 +187,11 @@ pub struct InboundGroupSession { /// key. pub sender_data: SenderData, + /// If this session was shared-on-invite as part of an MSC4268 key bundle, + /// information about the user who forwarded us the session information. + /// This is distinct from [`InboundGroupSession::sender_data`]. + pub forwarder_data: Option, + /// The Room this GroupSession belongs to pub room_id: OwnedRoomId, @@ -240,6 +245,10 @@ impl InboundGroupSession { /// * `sender_data` - Information about the sender of the to-device message /// that established this session. /// + /// * `forwarder_data` - If present, indicates this session was received via + /// an MSC4268 room key bundle, and provides information about the + /// forwarder of this bundle. + /// /// * `encryption_algorithm` - The [`EventEncryptionAlgorithm`] that should /// be used when messages are being decrypted. The method will return an /// [`SessionCreationError::Algorithm`] error if an algorithm we do not @@ -263,6 +272,7 @@ impl InboundGroupSession { room_id: &RoomId, session_key: &SessionKey, sender_data: SenderData, + forwarder_data: Option, encryption_algorithm: EventEncryptionAlgorithm, history_visibility: Option, shared_history: bool, @@ -286,6 +296,7 @@ impl InboundGroupSession { signing_keys: keys.into(), }, sender_data, + forwarder_data, room_id: room_id.into(), imported: false, algorithm: encryption_algorithm.into(), @@ -325,6 +336,7 @@ impl InboundGroupSession { room_id, session_key, SenderData::unknown(), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, *shared_history, @@ -380,6 +392,7 @@ impl InboundGroupSession { sender_key: self.creator_info.curve25519_key, signing_key: (*self.creator_info.signing_keys).clone(), sender_data: self.sender_data.clone(), + forwarder_data: self.forwarder_data.clone(), room_id: self.room_id().to_owned(), imported: self.imported, backed_up: self.backed_up(), @@ -459,6 +472,7 @@ impl InboundGroupSession { sender_key, signing_key, sender_data, + forwarder_data, room_id, imported, backed_up, @@ -479,6 +493,7 @@ impl InboundGroupSession { signing_keys: signing_key.into(), }, sender_data, + forwarder_data, history_visibility: history_visibility.into(), first_known_index, room_id, @@ -691,6 +706,9 @@ pub struct PickledInboundGroupSession { /// Information on the device/sender who sent us this session #[serde(default)] pub sender_data: SenderData, + /// Information on the device/sender who forwarded us this session + #[serde(default)] + pub forwarder_data: Option, /// The id of the room that the session is used in. pub room_id: OwnedRoomId, /// Flag remembering if the session was directly sent to us by the sender @@ -717,6 +735,67 @@ fn default_algorithm() -> EventEncryptionAlgorithm { EventEncryptionAlgorithm::MegolmV1AesSha2 } +impl HistoricRoomKey { + /// Converts a `HistoricRoomKey` into an `InboundGroupSession`. + /// + /// This method takes the current `HistoricRoomKey` instance and attempts to + /// create an `InboundGroupSession` from it. The `forwarder_data` parameter + /// provides information about the user or device that forwarded the session + /// information. This is distinct from the original sender of the session. + /// + /// # Arguments + /// + /// * `forwarder_data` - A reference to a `SenderData` object containing + /// information about the forwarder of the session. + /// + /// # Returns + /// + /// Returns a `Result` containing the newly created `InboundGroupSession` on + /// success, or a `SessionCreationError` if the conversion fails. + /// + /// # Errors + /// + /// This method will return a `SessionCreationError` if the session + /// configuration for the given algorithm cannot be determined. + pub fn try_into_inbound_group_session( + &self, + forwarder_data: &SenderData, + ) -> Result { + let HistoricRoomKey { + algorithm, + room_id, + sender_key, + session_id, + session_key, + sender_claimed_keys, + } = self; + + let config = OutboundGroupSession::session_config(algorithm)?; + let session = InnerSession::import(session_key, config); + let first_known_index = session.first_known_index(); + + Ok(InboundGroupSession { + inner: Mutex::new(session).into(), + session_id: session_id.to_owned().into(), + creator_info: SessionCreatorInfo { + curve25519_key: *sender_key, + signing_keys: sender_claimed_keys.to_owned().into(), + }, + // TODO: How do we remember that this is a historic room key and events decrypted using + // this room key should always show some form of warning. + sender_data: SenderData::default(), + forwarder_data: Some(forwarder_data.clone()), + history_visibility: None.into(), + first_known_index, + room_id: room_id.to_owned(), + imported: true, + algorithm: algorithm.to_owned().into(), + backed_up: AtomicBool::from(false).into(), + shared_history: true, + }) + } +} + impl TryFrom<&HistoricRoomKey> for InboundGroupSession { type Error = SessionCreationError; @@ -744,6 +823,7 @@ impl TryFrom<&HistoricRoomKey> for InboundGroupSession { // TODO: How do we remember that this is a historic room key and events decrypted using // this room key should always show some form of warning. sender_data: SenderData::default(), + forwarder_data: None, history_visibility: None.into(), first_known_index, room_id: room_id.to_owned(), @@ -784,6 +864,7 @@ impl TryFrom<&ExportedRoomKey> for InboundGroupSession { // TODO: In future, exported keys should contain sender data that we can use here. // See https://github.com/matrix-org/matrix-rust-sdk/issues/3548 sender_data: SenderData::default(), + forwarder_data: None, history_visibility: None.into(), first_known_index, room_id: room_id.to_owned(), @@ -815,6 +896,7 @@ impl From<&ForwardedMegolmV1AesSha2Content> for InboundGroupSession { // In future, exported keys should contain sender data that we can use here. // See https://github.com/matrix-org/matrix-rust-sdk/issues/3548 sender_data: SenderData::default(), + forwarder_data: None, history_visibility: None.into(), first_known_index, room_id: value.room_id.to_owned(), @@ -842,6 +924,7 @@ impl From<&ForwardedMegolmV2AesSha2Content> for InboundGroupSession { // In future, exported keys should contain sender data that we can use here. // See https://github.com/matrix-org/matrix-rust-sdk/issues/3548 sender_data: SenderData::default(), + forwarder_data: None, history_visibility: None.into(), first_known_index, room_id: value.room_id.to_owned(), @@ -982,6 +1065,7 @@ mod tests { room_id!("!test:localhost"), &create_session_key(), SenderData::unknown(), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, Some(HistoryVisibility::Shared), false, diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/sender_data_finder.rs b/crates/matrix-sdk-crypto/src/olm/group_sessions/sender_data_finder.rs index e00f458c0..c60b76671 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/sender_data_finder.rs +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/sender_data_finder.rs @@ -826,6 +826,7 @@ mod tests { room_id, &session_key, SenderData::unknown(), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, false, diff --git a/crates/matrix-sdk-crypto/src/store/integration_tests.rs b/crates/matrix-sdk-crypto/src/store/integration_tests.rs index 3dcafb523..3f9b032f5 100644 --- a/crates/matrix-sdk-crypto/src/store/integration_tests.rs +++ b/crates/matrix-sdk-crypto/src/store/integration_tests.rs @@ -1430,6 +1430,7 @@ macro_rules! cryptostore_integration_tests { room_id!("!r:s.co"), &session_key, sender_data, + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, false, diff --git a/crates/matrix-sdk-crypto/src/store/memorystore.rs b/crates/matrix-sdk-crypto/src/store/memorystore.rs index fcd6c2294..7230f96ae 100644 --- a/crates/matrix-sdk-crypto/src/store/memorystore.rs +++ b/crates/matrix-sdk-crypto/src/store/memorystore.rs @@ -847,6 +847,7 @@ mod tests { room_id, &outbound.session_key().await, SenderData::unknown(), + None, outbound.settings().algorithm.to_owned(), None, false, @@ -1245,6 +1246,7 @@ mod tests { room_id, &outbound.session_key().await, SenderData::unknown(), + None, outbound.settings().algorithm.to_owned(), None, false, diff --git a/crates/matrix-sdk-crypto/src/store/mod.rs b/crates/matrix-sdk-crypto/src/store/mod.rs index add3c682f..00262eeb9 100644 --- a/crates/matrix-sdk-crypto/src/store/mod.rs +++ b/crates/matrix-sdk-crypto/src/store/mod.rs @@ -1445,6 +1445,8 @@ impl Store { /// * `from_backup_version` - If the keys came from key backup, the key /// backup version. This will cause the keys to be marked as already /// backed up, and therefore not requiring another backup. + /// * `forwarder_data` - If the sessions were received as part of an MSC4268 + /// key bundle, the information about the user who sent us the bundle. /// * `progress_listener` - Callback which will be called after each key is /// processed. Called with arguments `(processed, total)` where /// `processed` is the number of keys processed so far, and `total` is the @@ -1455,7 +1457,22 @@ impl Store { from_backup_version: Option<&str>, progress_listener: impl Fn(usize, usize), ) -> Result { - let exported_keys: Vec<&ExportedRoomKey> = exported_keys.iter().collect(); + let exported_keys: Vec<_> = exported_keys + .iter() + .filter_map(|key| { + key.try_into() + .map_err(|e| { + warn!( + sender_key = key.sender_key().to_base64(), + room_id = ?key.room_id(), + session_id = key.session_id(), + error = ?e, + "Couldn't import a room key from a file export." + ); + }) + .ok() + }) + .collect(); self.import_sessions_impl(exported_keys, from_backup_version, progress_listener).await } @@ -1493,57 +1510,43 @@ impl Store { self.import_room_keys(exported_keys, None, progress_listener).await } - async fn import_sessions_impl( + async fn import_sessions_impl( &self, - room_keys: Vec, + sessions: Vec, from_backup_version: Option<&str>, progress_listener: impl Fn(usize, usize), - ) -> Result - where - T: TryInto + RoomKeyExport + Copy, - T::Error: Debug, - { - let mut sessions = Vec::new(); + ) -> Result { + let mut imported_sessions = Vec::new(); - let total_count = room_keys.len(); + let total_count = sessions.len(); let mut keys = BTreeMap::new(); - for (i, key) in room_keys.into_iter().enumerate() { - match key.try_into() { - Ok(session) => { - // Only import the session if we didn't have this session or - // if it's a better version of the same session. - if let Some(merged) = self.merge_received_group_session(session).await? { - if from_backup_version.is_some() { - merged.mark_as_backed_up(); - } - - keys.entry(merged.room_id().to_owned()) - .or_insert_with(BTreeMap::new) - .entry(merged.sender_key().to_base64()) - .or_insert_with(BTreeSet::new) - .insert(merged.session_id().to_owned()); - - sessions.push(merged); - } - } - Err(e) => { - warn!( - sender_key = key.sender_key().to_base64(), - room_id = ?key.room_id(), - session_id = key.session_id(), - error = ?e, - "Couldn't import a room key from a file export." - ); + for (i, session) in sessions.into_iter().enumerate() { + // Only import the session if we didn't have this session or + // if it's a better version of the same session. + if let Some(merged) = self.merge_received_group_session(session).await? { + if from_backup_version.is_some() { + merged.mark_as_backed_up(); } + + keys.entry(merged.room_id().to_owned()) + .or_insert_with(BTreeMap::new) + .entry(merged.sender_key().to_base64()) + .or_insert_with(BTreeSet::new) + .insert(merged.session_id().to_owned()); + + imported_sessions.push(merged); } progress_listener(i, total_count); } - let imported_count = sessions.len(); + let imported_count = imported_sessions.len(); - self.inner.store.save_inbound_group_sessions(sessions, from_backup_version).await?; + self.inner + .store + .save_inbound_group_sessions(imported_sessions, from_backup_version) + .await?; info!(total_count, imported_count, room_keys = ?keys, "Successfully imported room keys"); @@ -1706,6 +1709,9 @@ impl Store { tracing::Span::current().record("sender_data", tracing::field::debug(&sender_data)); + // The sender's device must be either `SenderData::SenderUnverified` (i.e., + // TOFU-trusted) or `SenderData::SenderVerified` (i.e., fully verified + // via user verification and cross-signing). if matches!( &sender_data, SenderData::UnknownDevice { .. } @@ -1718,7 +1724,8 @@ impl Store { return Ok(()); } - self.import_room_key_bundle_sessions(bundle_info, &bundle, progress_listener).await?; + self.import_room_key_bundle_sessions(bundle_info, &bundle, &sender_data, progress_listener) + .await?; self.import_room_key_bundle_withheld_info(bundle_info, &bundle).await?; Ok(()) @@ -1728,6 +1735,7 @@ impl Store { &self, bundle_info: &StoredRoomKeyBundleData, bundle: &RoomKeyBundle, + forwarder_data: &SenderData, progress_listener: impl Fn(usize, usize), ) -> Result<(), CryptoStoreError> { let (good, bad): (Vec<_>, Vec<_>) = bundle.room_keys.iter().partition_map(|key| { @@ -1768,7 +1776,24 @@ impl Store { ); } - self.import_sessions_impl(good, None, progress_listener).await?; + let keys = good + .iter() + .filter_map(|key| { + key.try_into_inbound_group_session(forwarder_data) + .map_err(|e| { + warn!( + sender_key = ?key.sender_key().to_base64(), + room_id = ?key.room_id(), + session_id = key.session_id(), + error = ?e, + "Couldn't import a room key from a key bundle." + ); + }) + .ok() + }) + .collect(); + + self.import_sessions_impl(keys, None, progress_listener).await?; } } @@ -1985,6 +2010,7 @@ mod tests { BTreeMap::new(), crate::types::Signatures::new(), )), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, Some(ruma::events::room::history_visibility::HistoryVisibility::Shared), true, @@ -2430,6 +2456,7 @@ mod tests { room_id, session_key, SenderData::unknown(), + None, #[cfg(not(feature = "experimental-algorithms"))] EventEncryptionAlgorithm::MegolmV1AesSha2, #[cfg(feature = "experimental-algorithms")] diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs index ae8624353..6ed4f1783 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/migrations/mod.rs @@ -524,6 +524,7 @@ mod tests { &room_id, session_key, SenderData::unknown(), + None, encryption_algorithm, history_visibility, false, @@ -683,6 +684,7 @@ mod tests { ) .unwrap(), SenderData::legacy(), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, false, @@ -703,6 +705,7 @@ mod tests { ) .unwrap(), SenderData::legacy(), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, false, diff --git a/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs b/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs index efe745cce..2fbe6f33f 100644 --- a/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs +++ b/crates/matrix-sdk-indexeddb/src/crypto_store/mod.rs @@ -2067,6 +2067,7 @@ mod unit_tests { ) .unwrap(), sender_data, + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, false, diff --git a/crates/matrix-sdk/tests/integration/encryption/backups.rs b/crates/matrix-sdk/tests/integration/encryption/backups.rs index ca56b5862..245cfb71d 100644 --- a/crates/matrix-sdk/tests/integration/encryption/backups.rs +++ b/crates/matrix-sdk/tests/integration/encryption/backups.rs @@ -1540,6 +1540,7 @@ async fn inbound_session_from_outbound_session( room_id, &outbound_group_session.session_key().await, SenderData::unknown(), + None, EventEncryptionAlgorithm::MegolmV1AesSha2, None, false, From 809643a159f7d6cc91152a4d4422fca1011c50ce Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Wed, 10 Dec 2025 13:45:17 +0000 Subject: [PATCH 2/5] tests(crypto): Doctests, update snapshots to include `forwarder_data`. --- .../src/olm/group_sessions/inbound.rs | 19 +++++++++++++------ ...on__test_pickle_snapshot__regression.snap} | 1 + crates/matrix-sdk-crypto/src/store/mod.rs | 11 +++++++++++ 3 files changed, 25 insertions(+), 6 deletions(-) rename crates/matrix-sdk-crypto/src/olm/group_sessions/snapshots/{matrix_sdk_crypto__olm__group_sessions__inbound__tests__pickle_snapshot.snap => InboundGroupSession__test_pickle_snapshot__regression.snap} (96%) diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs index b65896fd2..1968b8ccc 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs @@ -954,7 +954,7 @@ impl TryFrom<&DecryptedForwardedRoomKeyEvent> for InboundGroupSession { #[cfg(test)] mod tests { use assert_matches2::assert_let; - use insta::assert_json_snapshot; + use insta::{assert_json_snapshot, with_settings}; use matrix_sdk_test::async_test; use ruma::{ DeviceId, UserId, device_id, events::room::history_visibility::HistoryVisibility, @@ -989,11 +989,17 @@ mod tests { let pickle = session.pickle().await; - assert_json_snapshot!(pickle, { - ".pickle.initial_ratchet.inner" => "[ratchet]", - ".pickle.signing_key" => "[signing_key]", - ".sender_key" => "[sender_key]", - ".signing_key.ed25519" => "[ed25519_key]", + with_settings!({prepend_module_to_snapshot => false}, { + assert_json_snapshot!( + "InboundGroupSession__test_pickle_snapshot__regression", + pickle, + { + ".pickle.initial_ratchet.inner" => "[ratchet]", + ".pickle.signing_key" => "[signing_key]", + ".sender_key" => "[sender_key]", + ".signing_key.ed25519" => "[ed25519_key]", + } + ); }); } @@ -1112,6 +1118,7 @@ mod tests { "legacy_session":false } }, + "forwarder_data":null, "room_id":"!test:localhost", "imported":false, "backed_up":false, diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/snapshots/matrix_sdk_crypto__olm__group_sessions__inbound__tests__pickle_snapshot.snap b/crates/matrix-sdk-crypto/src/olm/group_sessions/snapshots/InboundGroupSession__test_pickle_snapshot__regression.snap similarity index 96% rename from crates/matrix-sdk-crypto/src/olm/group_sessions/snapshots/matrix_sdk_crypto__olm__group_sessions__inbound__tests__pickle_snapshot.snap rename to crates/matrix-sdk-crypto/src/olm/group_sessions/snapshots/InboundGroupSession__test_pickle_snapshot__regression.snap index 8b69cf401..3ca8da7da 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/snapshots/matrix_sdk_crypto__olm__group_sessions__inbound__tests__pickle_snapshot.snap +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/snapshots/InboundGroupSession__test_pickle_snapshot__regression.snap @@ -23,6 +23,7 @@ expression: pickle "legacy_session": false } }, + "forwarder_data": null, "room_id": "!test:localhost", "imported": false, "backed_up": false, diff --git a/crates/matrix-sdk-crypto/src/store/mod.rs b/crates/matrix-sdk-crypto/src/store/mod.rs index 00262eeb9..b13b03fcc 100644 --- a/crates/matrix-sdk-crypto/src/store/mod.rs +++ b/crates/matrix-sdk-crypto/src/store/mod.rs @@ -2369,6 +2369,17 @@ mod tests { assert_eq!(imported_sessions.len(), 1); assert_eq!(imported_sessions[0].room_id(), room_id); + // The session forwarder data should be set correctly. + assert_eq!( + imported_sessions[0] + .forwarder_data + .as_ref() + .expect("Session should contain forwarder data.") + .user_id() + .expect("Forwarder data should contain user ID."), + alice.user_id() + ); + assert_matches!( bob.store() .get_withheld_info(room_id, sessions[1].session_id()) From 85f07b10ad012625397ca29d45564ed392641b60 Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Wed, 17 Dec 2025 12:30:29 +0000 Subject: [PATCH 3/5] chore: Remove unused `TryFrom<&HistoricRoomKey>` implementation. --- .../src/olm/group_sessions/inbound.rs | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs index 1968b8ccc..b664c26ce 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs @@ -796,45 +796,6 @@ impl HistoricRoomKey { } } -impl TryFrom<&HistoricRoomKey> for InboundGroupSession { - type Error = SessionCreationError; - - fn try_from(key: &HistoricRoomKey) -> Result { - let HistoricRoomKey { - algorithm, - room_id, - sender_key, - session_id, - session_key, - sender_claimed_keys, - } = key; - - let config = OutboundGroupSession::session_config(algorithm)?; - let session = InnerSession::import(session_key, config); - let first_known_index = session.first_known_index(); - - Ok(InboundGroupSession { - inner: Mutex::new(session).into(), - session_id: session_id.to_owned().into(), - creator_info: SessionCreatorInfo { - curve25519_key: *sender_key, - signing_keys: sender_claimed_keys.to_owned().into(), - }, - // TODO: How do we remember that this is a historic room key and events decrypted using - // this room key should always show some form of warning. - sender_data: SenderData::default(), - forwarder_data: None, - history_visibility: None.into(), - first_known_index, - room_id: room_id.to_owned(), - imported: true, - algorithm: algorithm.to_owned().into(), - backed_up: AtomicBool::from(false).into(), - shared_history: true, - }) - } -} - impl TryFrom<&ExportedRoomKey> for InboundGroupSession { type Error = SessionCreationError; From f94ce7e91c9b390572573511e68c0830fb70ff3c Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Wed, 17 Dec 2025 16:43:54 +0000 Subject: [PATCH 4/5] docs: Improve doc comments, linkify MSC4268. --- .../src/olm/group_sessions/inbound.rs | 10 +++++++--- crates/matrix-sdk-crypto/src/store/mod.rs | 2 -- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs index b664c26ce..82a7bd8d9 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs @@ -187,9 +187,11 @@ pub struct InboundGroupSession { /// key. pub sender_data: SenderData, - /// If this session was shared-on-invite as part of an MSC4268 key bundle, + /// If this session was shared-on-invite as part of an [MSC4268] key bundle, /// information about the user who forwarded us the session information. /// This is distinct from [`InboundGroupSession::sender_data`]. + /// + /// [MSC4268]: https://github.com/matrix-org/matrix-spec-proposals/pull/4268 pub forwarder_data: Option, /// The Room this GroupSession belongs to @@ -246,7 +248,7 @@ impl InboundGroupSession { /// that established this session. /// /// * `forwarder_data` - If present, indicates this session was received via - /// an MSC4268 room key bundle, and provides information about the + /// an [MSC4268] room key bundle, and provides information about the /// forwarder of this bundle. /// /// * `encryption_algorithm` - The [`EventEncryptionAlgorithm`] that should @@ -265,6 +267,7 @@ impl InboundGroupSession { /// history visibility of the room. /// /// [MSC3061]: https://github.com/matrix-org/matrix-spec-proposals/pull/3061 + /// [MSC4268]: https://github.com/matrix-org/matrix-spec-proposals/pull/4268 #[allow(clippy::too_many_arguments)] pub fn new( sender_key: Curve25519PublicKey, @@ -741,7 +744,8 @@ impl HistoricRoomKey { /// This method takes the current `HistoricRoomKey` instance and attempts to /// create an `InboundGroupSession` from it. The `forwarder_data` parameter /// provides information about the user or device that forwarded the session - /// information. This is distinct from the original sender of the session. + /// information. This is normally distinct from the original sender of the + /// session. /// /// # Arguments /// diff --git a/crates/matrix-sdk-crypto/src/store/mod.rs b/crates/matrix-sdk-crypto/src/store/mod.rs index b13b03fcc..da268c90e 100644 --- a/crates/matrix-sdk-crypto/src/store/mod.rs +++ b/crates/matrix-sdk-crypto/src/store/mod.rs @@ -1445,8 +1445,6 @@ impl Store { /// * `from_backup_version` - If the keys came from key backup, the key /// backup version. This will cause the keys to be marked as already /// backed up, and therefore not requiring another backup. - /// * `forwarder_data` - If the sessions were received as part of an MSC4268 - /// key bundle, the information about the user who sent us the bundle. /// * `progress_listener` - Callback which will be called after each key is /// processed. Called with arguments `(processed, total)` where /// `processed` is the number of keys processed so far, and `total` is the From 0e568a4ee6bbd8f5c4ee4f13cf6bd6f29538a1c9 Mon Sep 17 00:00:00 2001 From: Skye Elliot Date: Wed, 17 Dec 2025 16:50:59 +0000 Subject: [PATCH 5/5] refactor: Use `impl Iterator` as param. --- crates/matrix-sdk-crypto/src/store/mod.rs | 61 +++++++++++------------ 1 file changed, 28 insertions(+), 33 deletions(-) diff --git a/crates/matrix-sdk-crypto/src/store/mod.rs b/crates/matrix-sdk-crypto/src/store/mod.rs index da268c90e..96d2c47ec 100644 --- a/crates/matrix-sdk-crypto/src/store/mod.rs +++ b/crates/matrix-sdk-crypto/src/store/mod.rs @@ -1455,22 +1455,19 @@ impl Store { from_backup_version: Option<&str>, progress_listener: impl Fn(usize, usize), ) -> Result { - let exported_keys: Vec<_> = exported_keys - .iter() - .filter_map(|key| { - key.try_into() - .map_err(|e| { - warn!( - sender_key = key.sender_key().to_base64(), - room_id = ?key.room_id(), - session_id = key.session_id(), - error = ?e, - "Couldn't import a room key from a file export." - ); - }) - .ok() - }) - .collect(); + let exported_keys = exported_keys.iter().filter_map(|key| { + key.try_into() + .map_err(|e| { + warn!( + sender_key = key.sender_key().to_base64(), + room_id = ?key.room_id(), + session_id = key.session_id(), + error = ?e, + "Couldn't import a room key from a file export." + ); + }) + .ok() + }); self.import_sessions_impl(exported_keys, from_backup_version, progress_listener).await } @@ -1510,10 +1507,11 @@ impl Store { async fn import_sessions_impl( &self, - sessions: Vec, + sessions: impl Iterator, from_backup_version: Option<&str>, progress_listener: impl Fn(usize, usize), ) -> Result { + let sessions: Vec<_> = sessions.collect(); let mut imported_sessions = Vec::new(); let total_count = sessions.len(); @@ -1774,22 +1772,19 @@ impl Store { ); } - let keys = good - .iter() - .filter_map(|key| { - key.try_into_inbound_group_session(forwarder_data) - .map_err(|e| { - warn!( - sender_key = ?key.sender_key().to_base64(), - room_id = ?key.room_id(), - session_id = key.session_id(), - error = ?e, - "Couldn't import a room key from a key bundle." - ); - }) - .ok() - }) - .collect(); + let keys = good.iter().filter_map(|key| { + key.try_into_inbound_group_session(forwarder_data) + .map_err(|e| { + warn!( + sender_key = ?key.sender_key().to_base64(), + room_id = ?key.room_id(), + session_id = key.session_id(), + error = ?e, + "Couldn't import a room key from a key bundle." + ); + }) + .ok() + }); self.import_sessions_impl(keys, None, progress_listener).await?; }