Skip to content

Commit 7126fc8

Browse files
authored
feat(crypto): Emmit EncryptionInfo with event handlers for to-device messages as well
1 parent f4e612c commit 7126fc8

File tree

21 files changed

+378
-111
lines changed

21 files changed

+378
-111
lines changed

crates/matrix-sdk-base/src/client.rs

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -496,7 +496,7 @@ impl BaseClient {
496496
#[cfg(feature = "e2e-encryption")]
497497
let to_device = {
498498
let processors::e2ee::to_device::Output {
499-
decrypted_to_device_events: to_device,
499+
processed_to_device_events: to_device,
500500
room_key_updates,
501501
} = processors::e2ee::to_device::from_sync_v2(&response, olm_machine.as_ref()).await?;
502502

@@ -519,7 +519,22 @@ impl BaseClient {
519519
};
520520

521521
#[cfg(not(feature = "e2e-encryption"))]
522-
let to_device = response.to_device.events;
522+
let to_device = response
523+
.to_device
524+
.events
525+
.into_iter()
526+
.map(|raw| {
527+
if let Ok(Some(event_type)) = raw.get_field::<String>("type") {
528+
if event_type == "m.room.encrypted" {
529+
matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent::UnableToDecrypt(raw)
530+
} else {
531+
matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent::PlainText(raw)
532+
}
533+
} else {
534+
matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent::Invalid(raw) // Exclude events with no type
535+
}
536+
})
537+
.collect();
523538

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

crates/matrix-sdk-base/src/debug.rs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
use std::fmt;
1818

1919
pub use matrix_sdk_common::debug::*;
20+
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
2021
use ruma::{
2122
api::client::sync::sync_events::v3::{InvitedRoom, KnockedRoom},
2223
serde::Raw,
@@ -35,6 +36,19 @@ impl<T> fmt::Debug for DebugListOfRawEventsNoId<'_, T> {
3536
}
3637
}
3738

39+
/// A wrapper around a slice of `ProcessedToDeviceEvent` events that implements
40+
/// `Debug` in a way that only prints the event type of each item.
41+
pub struct DebugListOfProcessedToDeviceEvents<'a>(pub &'a [ProcessedToDeviceEvent]);
42+
43+
#[cfg(not(tarpaulin_include))]
44+
impl fmt::Debug for DebugListOfProcessedToDeviceEvents<'_> {
45+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46+
let mut list = f.debug_list();
47+
list.entries(self.0.iter().map(|e| DebugRawEventNoId(e.as_raw())));
48+
list.finish()
49+
}
50+
}
51+
3852
/// A wrapper around an invited room as found in `/sync` responses that
3953
/// implements `Debug` in a way that only prints the event ID and event type for
4054
/// the raw events contained in `invite_state`.

crates/matrix-sdk-base/src/response_processors/e2ee/to_device.rs

Lines changed: 21 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
use std::collections::BTreeMap;
1616

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

96-
let events = events
97-
.iter()
98-
// TODO: There is loss of information here, after calling `to_raw` it is not
99-
// possible to make the difference between a successfully decrypted event and a plain
100-
// text event. This information needs to be propagated to top layer at some point if
101-
// clients relies on custom encrypted to device events.
102-
.map(|p| p.to_raw())
103-
.collect();
104-
105-
Output { decrypted_to_device_events: events, room_key_updates: Some(room_key_updates) }
97+
Output { processed_to_device_events: events, room_key_updates: Some(room_key_updates) }
10698
} else {
107-
// If we have no `OlmMachine`, just return the events that were passed in.
99+
// If we have no `OlmMachine`, just return the clear events that were passed in.
100+
// The encrypted ones are dropped as they are un-usable.
108101
// This should not happen unless we forget to set things up by calling
109102
// `Self::activate()`.
110103
Output {
111-
decrypted_to_device_events: encryption_sync_changes.to_device_events,
104+
processed_to_device_events: encryption_sync_changes
105+
.to_device_events
106+
.into_iter()
107+
.map(|raw| {
108+
if let Ok(Some(event_type)) = raw.get_field::<String>("type") {
109+
if event_type == "m.room.encrypted" {
110+
ProcessedToDeviceEvent::UnableToDecrypt(raw)
111+
} else {
112+
ProcessedToDeviceEvent::PlainText(raw)
113+
}
114+
} else {
115+
// Exclude events with no type
116+
ProcessedToDeviceEvent::Invalid(raw)
117+
}
118+
})
119+
.collect(),
112120
room_key_updates: None,
113121
}
114122
})
115123
}
116124

117125
pub struct Output {
118-
pub decrypted_to_device_events: Vec<Raw<AnyToDeviceEvent>>,
126+
pub processed_to_device_events: Vec<ProcessedToDeviceEvent>,
119127
pub room_key_updates: Option<Vec<RoomKeyInfo>>,
120128
}

crates/matrix-sdk-base/src/sliding_sync.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414

1515
//! Extend `BaseClient` with capabilities to handle MSC4186.
1616
17+
#[cfg(feature = "e2e-encryption")]
18+
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
1719
use matrix_sdk_common::deserialized_responses::TimelineEvent;
1820
use ruma::{api::client::sync::sync_events::v5 as http, OwnedRoomId};
19-
#[cfg(feature = "e2e-encryption")]
20-
use ruma::{events::AnyToDeviceEvent, serde::Raw};
2121
use tracing::{instrument, trace};
2222

2323
use super::BaseClient;
@@ -44,7 +44,7 @@ impl BaseClient {
4444
&self,
4545
to_device: Option<&http::response::ToDevice>,
4646
e2ee: &http::response::E2EE,
47-
) -> Result<Option<Vec<Raw<AnyToDeviceEvent>>>> {
47+
) -> Result<Option<Vec<ProcessedToDeviceEvent>>> {
4848
if to_device.is_none() && e2ee.is_empty() {
4949
return Ok(None);
5050
}
@@ -62,7 +62,7 @@ impl BaseClient {
6262

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

65-
let processors::e2ee::to_device::Output { decrypted_to_device_events, room_key_updates } =
65+
let processors::e2ee::to_device::Output { processed_to_device_events, room_key_updates } =
6666
processors::e2ee::to_device::from_msc4186(to_device, e2ee, olm_machine.as_ref())
6767
.await?;
6868

@@ -89,7 +89,7 @@ impl BaseClient {
8989
)
9090
.await?;
9191

92-
Ok(Some(decrypted_to_device_events))
92+
Ok(Some(processed_to_device_events))
9393
}
9494

9595
/// Process a response from a sliding sync call.

crates/matrix-sdk-base/src/sync.rs

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,15 +16,18 @@
1616
1717
use std::{collections::BTreeMap, fmt};
1818

19-
use matrix_sdk_common::{debug::DebugRawEvent, deserialized_responses::TimelineEvent};
19+
use matrix_sdk_common::{
20+
debug::DebugRawEvent,
21+
deserialized_responses::{ProcessedToDeviceEvent, TimelineEvent},
22+
};
2023
pub use ruma::api::client::sync::sync_events::v3::{
2124
InvitedRoom as InvitedRoomUpdate, KnockedRoom as KnockedRoomUpdate,
2225
};
2326
use ruma::{
2427
api::client::sync::sync_events::UnreadNotificationsCount as RumaUnreadNotificationsCount,
2528
events::{
2629
presence::PresenceEvent, AnyGlobalAccountDataEvent, AnyRoomAccountDataEvent,
27-
AnySyncEphemeralRoomEvent, AnySyncStateEvent, AnyToDeviceEvent,
30+
AnySyncEphemeralRoomEvent, AnySyncStateEvent,
2831
},
2932
push::Action,
3033
serde::Raw,
@@ -33,7 +36,10 @@ use ruma::{
3336
use serde::{Deserialize, Serialize};
3437

3538
use crate::{
36-
debug::{DebugInvitedRoom, DebugKnockedRoom, DebugListOfRawEvents, DebugListOfRawEventsNoId},
39+
debug::{
40+
DebugInvitedRoom, DebugKnockedRoom, DebugListOfProcessedToDeviceEvents,
41+
DebugListOfRawEvents, DebugListOfRawEventsNoId,
42+
},
3743
deserialized_responses::{AmbiguityChange, RawAnySyncOrStrippedTimelineEvent},
3844
};
3945

@@ -50,7 +56,7 @@ pub struct SyncResponse {
5056
/// The global private data created by this user.
5157
pub account_data: Vec<Raw<AnyGlobalAccountDataEvent>>,
5258
/// Messages sent directly between devices.
53-
pub to_device: Vec<Raw<AnyToDeviceEvent>>,
59+
pub to_device: Vec<ProcessedToDeviceEvent>,
5460
/// New notifications per room.
5561
pub notifications: BTreeMap<OwnedRoomId, Vec<Notification>>,
5662
}
@@ -61,7 +67,7 @@ impl fmt::Debug for SyncResponse {
6167
f.debug_struct("SyncResponse")
6268
.field("rooms", &self.rooms)
6369
.field("account_data", &DebugListOfRawEventsNoId(&self.account_data))
64-
.field("to_device", &DebugListOfRawEventsNoId(&self.to_device))
70+
.field("to_device", &DebugListOfProcessedToDeviceEvents(&self.to_device))
6571
.field("notifications", &self.notifications)
6672
.finish_non_exhaustive()
6773
}

crates/matrix-sdk-common/src/deserialized_responses.rs

Lines changed: 48 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use std::{collections::BTreeMap, fmt, sync::Arc};
1717
#[cfg(doc)]
1818
use ruma::events::AnyTimelineEvent;
1919
use ruma::{
20-
events::{AnyMessageLikeEvent, AnySyncTimelineEvent},
20+
events::{AnyMessageLikeEvent, AnySyncTimelineEvent, AnyToDeviceEvent},
2121
push::Action,
2222
serde::{
2323
AsRefStr, AsStrAsRefStr, DebugAsRefStr, DeserializeFromCowStr, FromString, JsonObject, Raw,
@@ -1165,6 +1165,53 @@ impl From<SyncTimelineEventDeserializationHelperV0> for TimelineEvent {
11651165
}
11661166
}
11671167

1168+
/// Represents a to-device event after it has been processed by the Olm machine.
1169+
#[derive(Clone, Debug)]
1170+
pub enum ProcessedToDeviceEvent {
1171+
/// A successfully-decrypted encrypted event.
1172+
/// Contains the raw decrypted event and encryption info
1173+
Decrypted {
1174+
/// The raw decrypted event
1175+
raw: Raw<AnyToDeviceEvent>,
1176+
/// The Olm encryption info
1177+
encryption_info: EncryptionInfo,
1178+
},
1179+
1180+
/// An encrypted event which could not be decrypted.
1181+
UnableToDecrypt(Raw<AnyToDeviceEvent>),
1182+
1183+
/// An unencrypted event.
1184+
PlainText(Raw<AnyToDeviceEvent>),
1185+
1186+
/// An invalid to device event that was ignored because it is missing some
1187+
/// required information to be processed (like no event `type` for
1188+
/// example)
1189+
Invalid(Raw<AnyToDeviceEvent>),
1190+
}
1191+
1192+
impl ProcessedToDeviceEvent {
1193+
/// Converts a ProcessedToDeviceEvent to the `Raw<AnyToDeviceEvent>` it
1194+
/// encapsulates
1195+
pub fn to_raw(&self) -> Raw<AnyToDeviceEvent> {
1196+
match self {
1197+
ProcessedToDeviceEvent::Decrypted { raw, .. } => raw.clone(),
1198+
ProcessedToDeviceEvent::UnableToDecrypt(event) => event.clone(),
1199+
ProcessedToDeviceEvent::PlainText(event) => event.clone(),
1200+
ProcessedToDeviceEvent::Invalid(event) => event.clone(),
1201+
}
1202+
}
1203+
1204+
/// Gets the raw to-device event.
1205+
pub fn as_raw(&self) -> &Raw<AnyToDeviceEvent> {
1206+
match self {
1207+
ProcessedToDeviceEvent::Decrypted { raw, .. } => raw,
1208+
ProcessedToDeviceEvent::UnableToDecrypt(event) => event,
1209+
ProcessedToDeviceEvent::PlainText(event) => event,
1210+
ProcessedToDeviceEvent::Invalid(event) => event,
1211+
}
1212+
}
1213+
}
1214+
11681215
#[cfg(test)]
11691216
mod tests {
11701217
use std::{collections::BTreeMap, sync::Arc};

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

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ use itertools::Itertools;
2323
use matrix_sdk_common::deserialized_responses::WithheldCode;
2424
use matrix_sdk_common::{
2525
deserialized_responses::{
26-
AlgorithmInfo, DecryptedRoomEvent, DeviceLinkProblem, EncryptionInfo, UnableToDecryptInfo,
27-
UnableToDecryptReason, UnsignedDecryptionResult, UnsignedEventLocation, VerificationLevel,
28-
VerificationState,
26+
AlgorithmInfo, DecryptedRoomEvent, DeviceLinkProblem, EncryptionInfo,
27+
ProcessedToDeviceEvent, UnableToDecryptInfo, UnableToDecryptReason,
28+
UnsignedDecryptionResult, UnsignedEventLocation, VerificationLevel, VerificationState,
2929
},
3030
locks::RwLock as StdRwLock,
3131
BoxFuture,
@@ -101,7 +101,7 @@ use crate::{
101101
AnyIncomingResponse, KeysQueryRequest, OutgoingRequest, ToDeviceRequest,
102102
UploadSigningKeysRequest,
103103
},
104-
EventEncryptionAlgorithm, ProcessedToDeviceEvent, Signatures,
104+
EventEncryptionAlgorithm, Signatures,
105105
},
106106
utilities::timestamp_to_iso8601,
107107
verification::{Verification, VerificationMachine, VerificationRequest},

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
use std::{collections::BTreeMap, ops::Deref, sync::Arc};
1919

2020
use as_variant::as_variant;
21+
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
2122
use matrix_sdk_test::{ruma_response_from_json, test_json};
2223
use ruma::{
2324
api::client::keys::{
@@ -42,7 +43,7 @@ use crate::{
4243
types::{
4344
events::ToDeviceEvent,
4445
requests::{AnyOutgoingRequest, ToDeviceRequest},
45-
DeviceKeys, ProcessedToDeviceEvent,
46+
DeviceKeys,
4647
},
4748
utilities::json_convert,
4849
verification::VerificationMachine,

crates/matrix-sdk-crypto/src/machine/tests/megolm_sender_data.rs

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@ use std::{fmt::Debug, iter, pin::Pin};
1717
use assert_matches::assert_matches;
1818
use futures_core::Stream;
1919
use futures_util::{FutureExt, StreamExt};
20+
use matrix_sdk_common::deserialized_responses::ProcessedToDeviceEvent;
2021
use matrix_sdk_test::async_test;
2122
use ruma::{room_id, user_id, RoomId, TransactionId, UserId};
2223
use serde::Serialize;
@@ -33,10 +34,7 @@ use crate::{
3334
},
3435
olm::{InboundGroupSession, SenderData},
3536
store::types::RoomKeyInfo,
36-
types::{
37-
events::{room::encrypted::ToDeviceEncryptedEventContent, EventType, ToDeviceEvent},
38-
ProcessedToDeviceEvent,
39-
},
37+
types::events::{room::encrypted::ToDeviceEncryptedEventContent, EventType, ToDeviceEvent},
4038
DeviceData, EncryptionSettings, EncryptionSyncChanges, OlmMachine, Session,
4139
};
4240

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

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,9 @@ use futures_util::{pin_mut, FutureExt, StreamExt};
1919
use itertools::Itertools;
2020
use matrix_sdk_common::{
2121
deserialized_responses::{
22-
AlgorithmInfo, UnableToDecryptInfo, UnableToDecryptReason, UnsignedDecryptionResult,
23-
UnsignedEventLocation, VerificationLevel, VerificationState, WithheldCode,
22+
AlgorithmInfo, ProcessedToDeviceEvent, UnableToDecryptInfo, UnableToDecryptReason,
23+
UnsignedDecryptionResult, UnsignedEventLocation, VerificationLevel, VerificationState,
24+
WithheldCode,
2425
},
2526
executor::spawn,
2627
};
@@ -73,7 +74,7 @@ use crate::{
7374
ToDeviceEvent,
7475
},
7576
requests::{AnyOutgoingRequest, ToDeviceRequest},
76-
DeviceKeys, ProcessedToDeviceEvent, SignedKey, SigningKeys,
77+
DeviceKeys, SignedKey, SigningKeys,
7778
},
7879
utilities::json_convert,
7980
verification::tests::bob_id,

0 commit comments

Comments
 (0)