mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-06-18 05:08:30 -04:00
wip
This commit is contained in:
@@ -95,6 +95,7 @@ use crate::{
|
||||
AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
|
||||
UploadSigningKeysRequest,
|
||||
},
|
||||
room_history::RoomKeyBundle,
|
||||
EventEncryptionAlgorithm, ProcessedToDeviceEvent, Signatures,
|
||||
},
|
||||
utilities::timestamp_to_iso8601,
|
||||
@@ -968,6 +969,43 @@ impl OlmMachine {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Import the contents of a downloaded and decrypted [MSC4268] key bundle.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `bundle` - The decrypted and deserialized bundle itself.
|
||||
/// * `room_id` - The room that we expect this bundle to correspond to.
|
||||
/// * `sender_user` - The user that sent us the to-device message pointing
|
||||
/// to this data.
|
||||
/// * `sender_data` - Information on the sending device at the time we
|
||||
/// received that message.
|
||||
///
|
||||
/// [MSC4268]: https://github.com/matrix-org/matrix-spec-proposals/pull/4268
|
||||
#[instrument(skip(bundle))]
|
||||
pub async fn receive_room_key_bundle(
|
||||
&self,
|
||||
bundle: &RoomKeyBundle,
|
||||
room_id: &RoomId,
|
||||
sender_user: &UserId,
|
||||
sender_data: &SenderData,
|
||||
) -> OlmResult<()> {
|
||||
for key in bundle.room_keys.iter() {
|
||||
if key.room_id != room_id {
|
||||
warn!("Ignoring key for incorrect room {} in bundle", key.room_id);
|
||||
continue;
|
||||
}
|
||||
|
||||
let _session = match InboundGroupSession::try_from(key) {
|
||||
Ok(session) => session,
|
||||
Err(e) => {
|
||||
warn!("Ignoring key in bundle with import error: {}", e);
|
||||
continue;
|
||||
}
|
||||
};
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn add_withheld_info(&self, changes: &mut Changes, event: &RoomKeyWithheldEvent) {
|
||||
debug!(?event.content, "Processing `m.room_key.withheld` event");
|
||||
|
||||
|
||||
@@ -55,10 +55,10 @@ use crate::{
|
||||
room::encrypted::{EncryptedEvent, RoomEventEncryptionScheme},
|
||||
room_key,
|
||||
},
|
||||
room_history::HistoricRoomKey,
|
||||
serialize_curve_key, EventEncryptionAlgorithm, SigningKeys,
|
||||
},
|
||||
};
|
||||
|
||||
// TODO: add creation times to the inbound group sessions so we can export
|
||||
// sessions that were created between some time period, this should only be set
|
||||
// for non-imported sessions.
|
||||
@@ -672,6 +672,42 @@ fn default_algorithm() -> EventEncryptionAlgorithm {
|
||||
EventEncryptionAlgorithm::MegolmV1AesSha2
|
||||
}
|
||||
|
||||
impl TryFrom<&HistoricRoomKey> for InboundGroupSession {
|
||||
type Error = SessionCreationError;
|
||||
|
||||
fn try_from(key: &HistoricRoomKey) -> Result<Self, Self::Error> {
|
||||
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(),
|
||||
},
|
||||
sender_data: SenderData::default(),
|
||||
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;
|
||||
|
||||
|
||||
@@ -267,12 +267,24 @@ impl Room {
|
||||
false
|
||||
});
|
||||
|
||||
#[cfg(all(feature = "experimental-share-history-on-invite", feature = "e2e-encryption"))]
|
||||
let inviter = if prev_room_state == RoomState::Invited {
|
||||
self.invite_details().await?.inviter
|
||||
} else {
|
||||
None
|
||||
};
|
||||
|
||||
self.client.join_room_by_id(self.room_id()).await?;
|
||||
|
||||
if mark_as_direct {
|
||||
self.set_is_direct(true).await?;
|
||||
}
|
||||
|
||||
#[cfg(all(feature = "experimental-share-history-on-invite", feature = "e2e-encryption"))]
|
||||
if let Some(inviter) = inviter {
|
||||
shared_room_history::accept_key_bundle(&self, inviter.user_id()).await?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
||||
@@ -12,12 +12,16 @@
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::iter;
|
||||
use std::{iter, ops::Deref};
|
||||
|
||||
use ruma::OwnedUserId;
|
||||
use matrix_sdk_base::media::{MediaFormat, MediaRequestParameters};
|
||||
use ruma::{api::client::authenticated_media, events::room::MediaSource, OwnedUserId, UserId};
|
||||
use tracing::{info, instrument, warn};
|
||||
|
||||
use crate::{crypto::types::events::room_key_bundle::RoomKeyBundleContent, Error, Result, Room};
|
||||
use crate::{
|
||||
crypto::types::{events::room_key_bundle::RoomKeyBundleContent, room_history::RoomKeyBundle},
|
||||
Error, Result, Room,
|
||||
};
|
||||
|
||||
/// Share any shareable E2EE history in the given room with the given recipient,
|
||||
/// as per [MSC4268].
|
||||
@@ -85,3 +89,62 @@ pub async fn share_room_history(room: &Room, user_id: OwnedUserId) -> Result<()>
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Having accepted an invite for the given room from the given user, download a
|
||||
/// key bundle and import the room keys, as per [MSC4268].
|
||||
///
|
||||
/// [MSC4268]: https://github.com/matrix-org/matrix-spec-proposals/pull/4268
|
||||
#[instrument(skip(room), fields(room_id = ?room.room_id()))]
|
||||
pub async fn accept_key_bundle(room: &Room, user_id: &UserId) -> Result<()> {
|
||||
// TODO: retry this if it gets interrupted or it fails.
|
||||
// TODO: do this in the background.
|
||||
|
||||
let client = &room.client;
|
||||
let olm_machine = client.olm_machine().await;
|
||||
let Some(olm_machine) = olm_machine.deref() else {
|
||||
warn!("Not fetching room key bundle as the Olm machine is not available");
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let Some(bundle) =
|
||||
olm_machine.store().get_received_room_key_bundle_data(room.room_id(), user_id).await?
|
||||
else {
|
||||
// No bundle received (yet).
|
||||
// TODO: deal with the bundle arriving later (https://github.com/matrix-org/matrix-rust-sdk/issues/4926)
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
// TODO
|
||||
// olm_machine.store().clear_received_room_key_bundle_data(room.room_id(),
|
||||
// user_id).await?;
|
||||
|
||||
let bundle_content = client
|
||||
.media()
|
||||
.get_media_content(
|
||||
&MediaRequestParameters {
|
||||
source: MediaSource::Encrypted(Box::new(bundle.bundle_data.file)),
|
||||
format: MediaFormat::File,
|
||||
},
|
||||
false,
|
||||
)
|
||||
.await?;
|
||||
|
||||
let bundle_content: RoomKeyBundle = match serde_json::from_slice(&bundle_content) {
|
||||
Ok(bundle_content) => bundle_content,
|
||||
Err(err) => {
|
||||
warn!("Failed to deserialize room key bundle: {}", err);
|
||||
return Ok(());
|
||||
}
|
||||
};
|
||||
|
||||
olm_machine
|
||||
.receive_room_key_bundle(
|
||||
&bundle_content,
|
||||
room.room_id(),
|
||||
&bundle.sender_user,
|
||||
&bundle.sender_data,
|
||||
)
|
||||
.await?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user