Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
f14ecc9
feat(crypto): Add `EncryptionInfo` to `Decrypted` to-device variant
BillCarsonFr May 22, 2025
0c4a895
fixup: coverage, test deserialize new format
BillCarsonFr May 22, 2025
c4cbcf9
feat(crypto): Support EncryptionInfo for olm encrypted via event handler
BillCarsonFr May 26, 2025
fc4a97e
Merge branch 'main' into valere/crypto/receive_encrypted_to_device
BillCarsonFr Jun 5, 2025
125aec6
refactor: Move ProcessedToDeviceEvent to common crate
BillCarsonFr Jun 5, 2025
d9137e9
fixup: when not(e2e-encryption) ignore encrypted to-device processing
BillCarsonFr Jun 5, 2025
53aeeb7
fixup: Test wrongly expecting encrypted to-device
BillCarsonFr Jun 5, 2025
290f963
fixup: flag dependent imports
BillCarsonFr Jun 5, 2025
10a9688
Merge branch 'main' into valere/crypto/receive_encrypted_to_device
BillCarsonFr Jun 5, 2025
7dd01ee
fixup: merge error in crypto changelog added a double entry
BillCarsonFr Jun 5, 2025
566d935
Merge branch 'main' into valere/crypto/receive_encrypted_to_device
BillCarsonFr Jun 6, 2025
041e50d
review: Improve test, better var names
BillCarsonFr Jun 6, 2025
27bc725
update changelog
BillCarsonFr Jun 6, 2025
d705261
Merge branch 'main' into valere/crypto/receive_encrypted_to_device
BillCarsonFr Jun 6, 2025
7639807
review: Better mapping to ProcessedToDeviceEvent when no e2e
BillCarsonFr Jun 12, 2025
3eaaa30
review: avoid cloning for dbg format of ProcessedToDeviceEvent list
BillCarsonFr Jun 12, 2025
f8a157f
review: fix olm -> Olm typo
BillCarsonFr Jun 12, 2025
2e2970c
review: clarify doc
BillCarsonFr Jun 12, 2025
0ff9c99
Merge branch 'main' into valere/crypto/receive_encrypted_to_device
BillCarsonFr Jun 12, 2025
d92eceb
fixup! changelog merge problem
BillCarsonFr Jun 13, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 17 additions & 2 deletions crates/matrix-sdk-base/src/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -496,7 +496,7 @@ impl BaseClient {
#[cfg(feature = "e2e-encryption")]
let to_device = {
let processors::e2ee::to_device::Output {
decrypted_to_device_events: to_device,
processed_to_device_events: to_device,
room_key_updates,
} = processors::e2ee::to_device::from_sync_v2(&response, olm_machine.as_ref()).await?;

Expand All @@ -519,7 +519,22 @@ impl BaseClient {
};

#[cfg(not(feature = "e2e-encryption"))]
let to_device = response.to_device.events;
let to_device = response
.to_device
.events
.into_iter()
.map(|raw| {
if let Ok(Some(event_type)) = raw.get_field::<String>("type") {
if event_type == "m.room.encrypted" {
matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent::UnableToDecrypt(raw)
} else {
matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent::PlainText(raw)
}
} else {
matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent::Invalid(raw) // Exclude events with no type
}
})
.collect();

let mut ambiguity_cache = AmbiguityCache::new(self.state_store.inner.clone());

Expand Down
14 changes: 14 additions & 0 deletions crates/matrix-sdk-base/src/debug.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
use std::fmt;

pub use matrix_sdk_common::debug::*;
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
use ruma::{
api::client::sync::sync_events::v3::{InvitedRoom, KnockedRoom},
serde::Raw,
Expand All @@ -35,6 +36,19 @@ impl<T> fmt::Debug for DebugListOfRawEventsNoId<'_, T> {
}
}

/// A wrapper around a slice of `ProcessedToDeviceEvent` events that implements
/// `Debug` in a way that only prints the event type of each item.
pub struct DebugListOfProcessedToDeviceEvents<'a>(pub &'a [ProcessedToDeviceEvent]);

#[cfg(not(tarpaulin_include))]
impl fmt::Debug for DebugListOfProcessedToDeviceEvents<'_> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut list = f.debug_list();
list.entries(self.0.iter().map(|e| DebugRawEventNoId(e.as_raw())));
list.finish()
}
}

/// A wrapper around an invited room as found in `/sync` responses that
/// implements `Debug` in a way that only prints the event ID and event type for
/// the raw events contained in `invite_state`.
Expand Down
34 changes: 21 additions & 13 deletions crates/matrix-sdk-base/src/response_processors/e2ee/to_device.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@

use std::collections::BTreeMap;

use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
use matrix_sdk_crypto::{store::types::RoomKeyInfo, EncryptionSyncChanges, OlmMachine};
use ruma::{
api::client::sync::sync_events::{v3, v5, DeviceLists},
Expand Down Expand Up @@ -93,28 +94,35 @@ async fn process(
let (events, room_key_updates) =
olm_machine.receive_sync_changes(encryption_sync_changes).await?;

let events = events
.iter()
// TODO: There is loss of information here, after calling `to_raw` it is not
// possible to make the difference between a successfully decrypted event and a plain
// text event. This information needs to be propagated to top layer at some point if
// clients relies on custom encrypted to device events.
.map(|p| p.to_raw())
.collect();

Output { decrypted_to_device_events: events, room_key_updates: Some(room_key_updates) }
Output { processed_to_device_events: events, room_key_updates: Some(room_key_updates) }
} else {
// If we have no `OlmMachine`, just return the events that were passed in.
// If we have no `OlmMachine`, just return the clear events that were passed in.
// The encrypted ones are dropped as they are un-usable.
// This should not happen unless we forget to set things up by calling
// `Self::activate()`.
Output {
decrypted_to_device_events: encryption_sync_changes.to_device_events,
processed_to_device_events: encryption_sync_changes
.to_device_events
.into_iter()
.map(|raw| {
if let Ok(Some(event_type)) = raw.get_field::<String>("type") {
if event_type == "m.room.encrypted" {
ProcessedToDeviceEvent::UnableToDecrypt(raw)
} else {
ProcessedToDeviceEvent::PlainText(raw)
}
} else {
// Exclude events with no type
ProcessedToDeviceEvent::Invalid(raw)
}
})
.collect(),
room_key_updates: None,
}
})
}

pub struct Output {
pub decrypted_to_device_events: Vec<Raw<AnyToDeviceEvent>>,
pub processed_to_device_events: Vec<ProcessedToDeviceEvent>,
pub room_key_updates: Option<Vec<RoomKeyInfo>>,
}
10 changes: 5 additions & 5 deletions crates/matrix-sdk-base/src/sliding_sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,10 +14,10 @@

//! Extend `BaseClient` with capabilities to handle MSC4186.

#[cfg(feature = "e2e-encryption")]
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
use matrix_sdk_common::deserialized_responses::TimelineEvent;
use ruma::{api::client::sync::sync_events::v5 as http, OwnedRoomId};
#[cfg(feature = "e2e-encryption")]
use ruma::{events::AnyToDeviceEvent, serde::Raw};
use tracing::{instrument, trace};

use super::BaseClient;
Expand All @@ -44,7 +44,7 @@ impl BaseClient {
&self,
to_device: Option<&http::response::ToDevice>,
e2ee: &http::response::E2EE,
) -> Result<Option<Vec<Raw<AnyToDeviceEvent>>>> {
) -> Result<Option<Vec<ProcessedToDeviceEvent>>> {
if to_device.is_none() && e2ee.is_empty() {
return Ok(None);
}
Expand All @@ -62,7 +62,7 @@ impl BaseClient {

let mut context = processors::Context::default();

let processors::e2ee::to_device::Output { decrypted_to_device_events, room_key_updates } =
let processors::e2ee::to_device::Output { processed_to_device_events, room_key_updates } =
processors::e2ee::to_device::from_msc4186(to_device, e2ee, olm_machine.as_ref())
.await?;

Expand All @@ -89,7 +89,7 @@ impl BaseClient {
)
.await?;

Ok(Some(decrypted_to_device_events))
Ok(Some(processed_to_device_events))
}

/// Process a response from a sliding sync call.
Expand Down
16 changes: 11 additions & 5 deletions crates/matrix-sdk-base/src/sync.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,18 @@

use std::{collections::BTreeMap, fmt};

use matrix_sdk_common::{debug::DebugRawEvent, deserialized_responses::TimelineEvent};
use matrix_sdk_common::{
debug::DebugRawEvent,
deserialized_responses::{ProcessedToDeviceEvent, TimelineEvent},
};
pub use ruma::api::client::sync::sync_events::v3::{
InvitedRoom as InvitedRoomUpdate, KnockedRoom as KnockedRoomUpdate,
};
use ruma::{
api::client::sync::sync_events::UnreadNotificationsCount as RumaUnreadNotificationsCount,
events::{
presence::PresenceEvent, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent,
AnySyncEphemeralRoomEvent, AnySyncStateEvent, AnyToDeviceEvent,
AnySyncEphemeralRoomEvent, AnySyncStateEvent,
},
push::Action,
serde::Raw,
Expand All @@ -33,7 +36,10 @@ use ruma::{
use serde::{Deserialize, Serialize};

use crate::{
debug::{DebugInvitedRoom, DebugKnockedRoom, DebugListOfRawEvents, DebugListOfRawEventsNoId},
debug::{
DebugInvitedRoom, DebugKnockedRoom, DebugListOfProcessedToDeviceEvents,
DebugListOfRawEvents, DebugListOfRawEventsNoId,
},
deserialized_responses::{AmbiguityChange, RawAnySyncOrStrippedTimelineEvent},
};

Expand All @@ -50,7 +56,7 @@ pub struct SyncResponse {
/// The global private data created by this user.
pub account_data: Vec<Raw<AnyGlobalAccountDataEvent>>,
/// Messages sent directly between devices.
pub to_device: Vec<Raw<AnyToDeviceEvent>>,
pub to_device: Vec<ProcessedToDeviceEvent>,
/// New notifications per room.
pub notifications: BTreeMap<OwnedRoomId, Vec<Notification>>,
}
Expand All @@ -61,7 +67,7 @@ impl fmt::Debug for SyncResponse {
f.debug_struct("SyncResponse")
.field("rooms", &self.rooms)
.field("account_data", &DebugListOfRawEventsNoId(&self.account_data))
.field("to_device", &DebugListOfRawEventsNoId(&self.to_device))
.field("to_device", &DebugListOfProcessedToDeviceEvents(&self.to_device))
.field("notifications", &self.notifications)
.finish_non_exhaustive()
}
Expand Down
49 changes: 48 additions & 1 deletion crates/matrix-sdk-common/src/deserialized_responses.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ use std::{collections::BTreeMap, fmt, sync::Arc};
#[cfg(doc)]
use ruma::events::AnyTimelineEvent;
use ruma::{
events::{AnyMessageLikeEvent, AnySyncTimelineEvent},
events::{AnyMessageLikeEvent, AnySyncTimelineEvent, AnyToDeviceEvent},
push::Action,
serde::{
AsRefStr, AsStrAsRefStr, DebugAsRefStr, DeserializeFromCowStr, FromString, JsonObject, Raw,
Expand Down Expand Up @@ -1165,6 +1165,53 @@ impl From<SyncTimelineEventDeserializationHelperV0> for TimelineEvent {
}
}

/// Represents a to-device event after it has been processed by the Olm machine.
#[derive(Clone, Debug)]
pub enum ProcessedToDeviceEvent {
/// A successfully-decrypted encrypted event.
/// Contains the raw decrypted event and encryption info
Decrypted {
/// The raw decrypted event
raw: Raw<AnyToDeviceEvent>,
/// The Olm encryption info
encryption_info: EncryptionInfo,
},

/// An encrypted event which could not be decrypted.
UnableToDecrypt(Raw<AnyToDeviceEvent>),

/// An unencrypted event.
PlainText(Raw<AnyToDeviceEvent>),

/// An invalid to device event that was ignored because it is missing some
/// required information to be processed (like no event `type` for
/// example)
Invalid(Raw<AnyToDeviceEvent>),
}

impl ProcessedToDeviceEvent {
/// Converts a ProcessedToDeviceEvent to the `Raw<AnyToDeviceEvent>` it
/// encapsulates
pub fn to_raw(&self) -> Raw<AnyToDeviceEvent> {
match self {
ProcessedToDeviceEvent::Decrypted { raw, .. } => raw.clone(),
ProcessedToDeviceEvent::UnableToDecrypt(event) => event.clone(),
ProcessedToDeviceEvent::PlainText(event) => event.clone(),
ProcessedToDeviceEvent::Invalid(event) => event.clone(),
}
}

/// Gets the raw to-device event.
pub fn as_raw(&self) -> &Raw<AnyToDeviceEvent> {
match self {
ProcessedToDeviceEvent::Decrypted { raw, .. } => raw,
ProcessedToDeviceEvent::UnableToDecrypt(event) => event,
ProcessedToDeviceEvent::PlainText(event) => event,
ProcessedToDeviceEvent::Invalid(event) => event,
}
}
}

#[cfg(test)]
mod tests {
use std::{collections::BTreeMap, sync::Arc};
Expand Down
8 changes: 4 additions & 4 deletions crates/matrix-sdk-crypto/src/machine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,9 +23,9 @@ use itertools::Itertools;
use matrix_sdk_common::deserialized_responses::WithheldCode;
use matrix_sdk_common::{
deserialized_responses::{
AlgorithmInfo, DecryptedRoomEvent, DeviceLinkProblem, EncryptionInfo, UnableToDecryptInfo,
UnableToDecryptReason, UnsignedDecryptionResult, UnsignedEventLocation, VerificationLevel,
VerificationState,
AlgorithmInfo, DecryptedRoomEvent, DeviceLinkProblem, EncryptionInfo,
ProcessedToDeviceEvent, UnableToDecryptInfo, UnableToDecryptReason,
UnsignedDecryptionResult, UnsignedEventLocation, VerificationLevel, VerificationState,
},
locks::RwLock as StdRwLock,
BoxFuture,
Expand Down Expand Up @@ -101,7 +101,7 @@ use crate::{
AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
UploadSigningKeysRequest,
},
EventEncryptionAlgorithm, ProcessedToDeviceEvent, Signatures,
EventEncryptionAlgorithm, Signatures,
},
utilities::timestamp_to_iso8601,
verification::{Verification, VerificationMachine, VerificationRequest},
Expand Down
3 changes: 2 additions & 1 deletion crates/matrix-sdk-crypto/src/machine/test_helpers.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use std::{collections::BTreeMap, ops::Deref, sync::Arc};

use as_variant::as_variant;
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
use matrix_sdk_test::{ruma_response_from_json, test_json};
use ruma::{
api::client::keys::{
Expand All @@ -42,7 +43,7 @@ use crate::{
types::{
events::ToDeviceEvent,
requests::{AnyOutgoingRequest, ToDeviceRequest},
DeviceKeys, ProcessedToDeviceEvent,
DeviceKeys,
},
utilities::json_convert,
verification::VerificationMachine,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ use std::{fmt::Debug, iter, pin::Pin};
use assert_matches::assert_matches;
use futures_core::Stream;
use futures_util::{FutureExt, StreamExt};
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
use matrix_sdk_test::async_test;
use ruma::{room_id, user_id, RoomId, TransactionId, UserId};
use serde::Serialize;
Expand All @@ -33,10 +34,7 @@ use crate::{
},
olm::{InboundGroupSession, SenderData},
store::types::RoomKeyInfo,
types::{
events::{room::encrypted::ToDeviceEncryptedEventContent, EventType, ToDeviceEvent},
ProcessedToDeviceEvent,
},
types::events::{room::encrypted::ToDeviceEncryptedEventContent, EventType, ToDeviceEvent},
DeviceData, EncryptionSettings, EncryptionSyncChanges, OlmMachine, Session,
};

Expand Down
7 changes: 4 additions & 3 deletions crates/matrix-sdk-crypto/src/machine/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,8 +19,9 @@ use futures_util::{pin_mut, FutureExt, StreamExt};
use itertools::Itertools;
use matrix_sdk_common::{
deserialized_responses::{
AlgorithmInfo, UnableToDecryptInfo, UnableToDecryptReason, UnsignedDecryptionResult,
UnsignedEventLocation, VerificationLevel, VerificationState, WithheldCode,
AlgorithmInfo, ProcessedToDeviceEvent, UnableToDecryptInfo, UnableToDecryptReason,
UnsignedDecryptionResult, UnsignedEventLocation, VerificationLevel, VerificationState,
WithheldCode,
},
executor::spawn,
};
Expand Down Expand Up @@ -73,7 +74,7 @@ use crate::{
ToDeviceEvent,
},
requests::{AnyOutgoingRequest, ToDeviceRequest},
DeviceKeys, ProcessedToDeviceEvent, SignedKey, SigningKeys,
DeviceKeys, SignedKey, SigningKeys,
},
utilities::json_convert,
verification::tests::bob_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ use std::{
};

use assert_matches2::assert_let;
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
use matrix_sdk_test::async_test;
use ruma::{
device_id,
Expand All @@ -38,7 +39,7 @@ use crate::{
},
olm::utility::SignJson,
store::types::Changes,
types::{events::ToDeviceEvent, DeviceKeys, ProcessedToDeviceEvent},
types::{events::ToDeviceEvent, DeviceKeys},
DeviceData, OlmMachine,
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
use assert_matches2::{assert_let, assert_matches};
use insta::assert_json_snapshot;
use matrix_sdk_common::deserialized_responses::{
AlgorithmInfo, VerificationLevel, VerificationState,
AlgorithmInfo, ProcessedToDeviceEvent, VerificationLevel, VerificationState,
};
use matrix_sdk_test::async_test;
use ruma::{events::AnyToDeviceEvent, serde::Raw, to_device::DeviceIdOrAllDevices};
Expand All @@ -33,7 +33,6 @@ use crate::{
types::{
events::{ToDeviceCustomEvent, ToDeviceEvent},
requests::ToDeviceRequest,
ProcessedToDeviceEvent,
},
utilities::json_convert,
verification::tests::bob_id,
Expand Down
Loading
Loading