Skip to content

Commit e8cf202

Browse files
committed
wip
1 parent f042084 commit e8cf202

File tree

4 files changed

+153
-4
lines changed

4 files changed

+153
-4
lines changed

crates/matrix-sdk-crypto/src/machine/mod.rs

+38
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,7 @@ use crate::{
9595
AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
9696
UploadSigningKeysRequest,
9797
},
98+
room_history::RoomKeyBundle,
9899
EventEncryptionAlgorithm, ProcessedToDeviceEvent, Signatures,
99100
},
100101
utilities::timestamp_to_iso8601,
@@ -968,6 +969,43 @@ impl OlmMachine {
968969
Ok(())
969970
}
970971

972+
/// Import the contents of a downloaded and decrypted [MSC4268] key bundle.
973+
///
974+
/// # Arguments
975+
///
976+
/// * `bundle` - The decrypted and deserialized bundle itself.
977+
/// * `room_id` - The room that we expect this bundle to correspond to.
978+
/// * `sender_user` - The user that sent us the to-device message pointing
979+
/// to this data.
980+
/// * `sender_data` - Information on the sending device at the time we
981+
/// received that message.
982+
///
983+
/// [MSC4268]: https://github.com/matrix-org/matrix-spec-proposals/pull/4268
984+
#[instrument(skip(bundle))]
985+
pub async fn receive_room_key_bundle(
986+
&self,
987+
bundle: &RoomKeyBundle,
988+
room_id: &RoomId,
989+
sender_user: &UserId,
990+
sender_data: &SenderData,
991+
) -> OlmResult<()> {
992+
for key in bundle.room_keys.iter() {
993+
if key.room_id != room_id {
994+
warn!("Ignoring key for incorrect room {} in bundle", key.room_id);
995+
continue;
996+
}
997+
998+
let _session = match InboundGroupSession::try_from(key) {
999+
Ok(session) => session,
1000+
Err(e) => {
1001+
warn!("Ignoring key in bundle with import error: {}", e);
1002+
continue;
1003+
}
1004+
};
1005+
}
1006+
Ok(())
1007+
}
1008+
9711009
fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
9721010
debug!(?event.content, "Processing `m.room_key.withheld` event");
9731011

crates/matrix-sdk-crypto/src/olm/group_sessions/inbound.rs

+37-1
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,10 @@ use crate::{
5555
room::encrypted::{EncryptedEvent, RoomEventEncryptionScheme},
5656
room_key,
5757
},
58+
room_history::HistoricRoomKey,
5859
serialize_curve_key, EventEncryptionAlgorithm, SigningKeys,
5960
},
6061
};
61-
6262
// TODO: add creation times to the inbound group sessions so we can export
6363
// sessions that were created between some time period, this should only be set
6464
// for non-imported sessions.
@@ -672,6 +672,42 @@ fn default_algorithm() -> EventEncryptionAlgorithm {
672672
EventEncryptionAlgorithm::MegolmV1AesSha2
673673
}
674674

675+
impl TryFrom<&HistoricRoomKey> for InboundGroupSession {
676+
type Error = SessionCreationError;
677+
678+
fn try_from(key: &HistoricRoomKey) -> Result<Self, Self::Error> {
679+
let HistoricRoomKey {
680+
algorithm,
681+
room_id,
682+
sender_key,
683+
session_id,
684+
session_key,
685+
sender_claimed_keys,
686+
} = key;
687+
688+
let config = OutboundGroupSession::session_config(algorithm)?;
689+
let session = InnerSession::import(session_key, config);
690+
let first_known_index = session.first_known_index();
691+
692+
Ok(InboundGroupSession {
693+
inner: Mutex::new(session).into(),
694+
session_id: session_id.to_owned().into(),
695+
creator_info: SessionCreatorInfo {
696+
curve25519_key: *sender_key,
697+
signing_keys: sender_claimed_keys.to_owned().into(),
698+
},
699+
sender_data: SenderData::default(),
700+
history_visibility: None.into(),
701+
first_known_index,
702+
room_id: room_id.to_owned(),
703+
imported: true,
704+
algorithm: algorithm.to_owned().into(),
705+
backed_up: AtomicBool::from(false).into(),
706+
shared_history: true,
707+
})
708+
}
709+
}
710+
675711
impl TryFrom<&ExportedRoomKey> for InboundGroupSession {
676712
type Error = SessionCreationError;
677713

crates/matrix-sdk/src/room/mod.rs

+12
Original file line numberDiff line numberDiff line change
@@ -267,12 +267,24 @@ impl Room {
267267
false
268268
});
269269

270+
#[cfg(all(feature = "experimental-share-history-on-invite", feature = "e2e-encryption"))]
271+
let inviter = if prev_room_state == RoomState::Invited {
272+
self.invite_details().await?.inviter
273+
} else {
274+
None
275+
};
276+
270277
self.client.join_room_by_id(self.room_id()).await?;
271278

272279
if mark_as_direct {
273280
self.set_is_direct(true).await?;
274281
}
275282

283+
#[cfg(all(feature = "experimental-share-history-on-invite", feature = "e2e-encryption"))]
284+
if let Some(inviter) = inviter {
285+
shared_room_history::accept_key_bundle(&self, inviter.user_id()).await?;
286+
}
287+
276288
Ok(())
277289
}
278290

crates/matrix-sdk/src/room/shared_room_history.rs

+66-3
Original file line numberDiff line numberDiff line change
@@ -12,12 +12,16 @@
1212
// See the License for the specific language governing permissions and
1313
// limitations under the License.
1414

15-
use std::iter;
15+
use std::{iter, ops::Deref};
1616

17-
use ruma::OwnedUserId;
17+
use matrix_sdk_base::media::{MediaFormat, MediaRequestParameters};
18+
use ruma::{api::client::authenticated_media, events::room::MediaSource, OwnedUserId, UserId};
1819
use tracing::{info, instrument, warn};
1920

20-
use crate::{crypto::types::events::room_key_bundle::RoomKeyBundleContent, Error, Result, Room};
21+
use crate::{
22+
crypto::types::{events::room_key_bundle::RoomKeyBundleContent, room_history::RoomKeyBundle},
23+
Error, Result, Room,
24+
};
2125

2226
/// Share any shareable E2EE history in the given room with the given recipient,
2327
/// as per [MSC4268].
@@ -85,3 +89,62 @@ pub async fn share_room_history(room: &Room, user_id: OwnedUserId) -> Result<()>
8589
}
8690
Ok(())
8791
}
92+
93+
/// Having accepted an invite for the given room from the given user, download a
94+
/// key bundle and import the room keys, as per [MSC4268].
95+
///
96+
/// [MSC4268]: https://github.com/matrix-org/matrix-spec-proposals/pull/4268
97+
#[instrument(skip(room), fields(room_id = ?room.room_id()))]
98+
pub async fn accept_key_bundle(room: &Room, user_id: &UserId) -> Result<()> {
99+
// TODO: retry this if it gets interrupted or it fails.
100+
// TODO: do this in the background.
101+
102+
let client = &room.client;
103+
let olm_machine = client.olm_machine().await;
104+
let Some(olm_machine) = olm_machine.deref() else {
105+
warn!("Not fetching room key bundle as the Olm machine is not available");
106+
return Ok(());
107+
};
108+
109+
let Some(bundle) =
110+
olm_machine.store().get_received_room_key_bundle_data(room.room_id(), user_id).await?
111+
else {
112+
// No bundle received (yet).
113+
// TODO: deal with the bundle arriving later (https://github.com/matrix-org/matrix-rust-sdk/issues/4926)
114+
return Ok(());
115+
};
116+
117+
// TODO
118+
// olm_machine.store().clear_received_room_key_bundle_data(room.room_id(),
119+
// user_id).await?;
120+
121+
let bundle_content = client
122+
.media()
123+
.get_media_content(
124+
&MediaRequestParameters {
125+
source: MediaSource::Encrypted(Box::new(bundle.bundle_data.file)),
126+
format: MediaFormat::File,
127+
},
128+
false,
129+
)
130+
.await?;
131+
132+
let bundle_content: RoomKeyBundle = match serde_json::from_slice(&bundle_content) {
133+
Ok(bundle_content) => bundle_content,
134+
Err(err) => {
135+
warn!("Failed to deserialize room key bundle: {}", err);
136+
return Ok(());
137+
}
138+
};
139+
140+
olm_machine
141+
.receive_room_key_bundle(
142+
&bundle_content,
143+
room.room_id(),
144+
&bundle.sender_user,
145+
&bundle.sender_data,
146+
)
147+
.await?;
148+
149+
Ok(())
150+
}

0 commit comments

Comments
 (0)