mirror of
https://github.com/matrix-org/matrix-rust-sdk.git
synced 2026-05-08 07:56:55 -04:00
crypto: Add variants for plain text and encrypted to-device events
fixup: post rebase
This commit is contained in:
@@ -554,8 +554,10 @@ impl OlmMachine {
|
||||
}),
|
||||
)?;
|
||||
|
||||
let to_device_events =
|
||||
to_device_events.into_iter().map(|event| event.json().get().to_owned()).collect();
|
||||
let to_device_events = to_device_events
|
||||
.into_iter()
|
||||
.map(|event| event.to_raw().json().get().to_owned())
|
||||
.collect();
|
||||
let room_key_infos = room_key_infos.into_iter().map(|info| info.into()).collect();
|
||||
|
||||
Ok(SyncChangesResult { to_device_events, room_key_infos })
|
||||
@@ -930,6 +932,8 @@ impl OlmMachine {
|
||||
},
|
||||
}
|
||||
}
|
||||
// Should not happen
|
||||
_ => panic!("Unsupported algorithm in room"),
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -99,6 +99,15 @@ async fn process(
|
||||
let (events, room_key_updates) =
|
||||
olm_machine.receive_sync_changes(encryption_sync_changes).await?;
|
||||
|
||||
let events = events
|
||||
.iter()
|
||||
// XXX 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) }
|
||||
} else {
|
||||
// If we have no `OlmMachine`, just return the events that were passed in.
|
||||
|
||||
@@ -17,7 +17,7 @@ use std::{collections::BTreeMap, fmt};
|
||||
#[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,
|
||||
@@ -282,6 +282,11 @@ pub enum AlgorithmInfo {
|
||||
/// key.
|
||||
sender_claimed_keys: BTreeMap<DeviceKeyAlgorithm, String>,
|
||||
},
|
||||
|
||||
OlmV1Curve25519AesSha2 {
|
||||
// The sender key of the device that encrypted the message
|
||||
curve25519_key: String,
|
||||
},
|
||||
}
|
||||
|
||||
/// Struct containing information on how an event was decrypted.
|
||||
@@ -615,6 +620,40 @@ impl fmt::Debug for DecryptedRoomEvent {
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, Serialize, Deserialize)]
|
||||
pub enum ProcessedToDeviceEvent {
|
||||
/// A successfully-decrypted encrypted event.
|
||||
Decrypted {
|
||||
/// The decrypted to device event
|
||||
decrypted_event: Raw<AnyToDeviceEvent>,
|
||||
/// Sender encryption information
|
||||
encryption_info: EncryptionInfo,
|
||||
},
|
||||
|
||||
/// An encrypted event which could not be decrypted.
|
||||
UnableToDecrypt {
|
||||
/// The `m.room.encrypted` to device event.
|
||||
event: Raw<AnyToDeviceEvent>,
|
||||
},
|
||||
|
||||
/// An unencrypted event.
|
||||
PlainText(Raw<AnyToDeviceEvent>),
|
||||
|
||||
/// An invalid to device event that was ignored
|
||||
NotProcessed(Raw<AnyToDeviceEvent>),
|
||||
}
|
||||
|
||||
impl ProcessedToDeviceEvent {
|
||||
pub fn to_raw(&self) -> Raw<AnyToDeviceEvent> {
|
||||
match self {
|
||||
ProcessedToDeviceEvent::Decrypted { decrypted_event, .. } => decrypted_event.clone(),
|
||||
ProcessedToDeviceEvent::UnableToDecrypt { event } => event.clone(),
|
||||
ProcessedToDeviceEvent::PlainText(event) => event.clone(),
|
||||
ProcessedToDeviceEvent::NotProcessed(event) => event.clone(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The location of an event bundled in an `unsigned` object.
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
|
||||
pub enum UnsignedEventLocation {
|
||||
|
||||
@@ -20,6 +20,12 @@ All notable changes to this project will be documented in this file.
|
||||
|
||||
### Features
|
||||
|
||||
- [**breaking**] `OlmMachine.receive_sync_changes` returns now a list of `ProcessedToDeviceEvent`
|
||||
instead of a list of `Raw<AnyToDeviceEvent>`. With variants like `Decrypted`|`UnableToDecrypt`|`PlainText`|`NotProcessed`.
|
||||
This allows for example to make the difference between an event sent in clear and an event successfully decrypted.
|
||||
A `ProcessedToDeviceEvent::Decrypted` now contains the `encryption_info` and `verification_state` of the event.
|
||||
For quick compatibility a helper `ProcessedToDeviceEvent::to_raw` allows to map back to the previous behaviour.
|
||||
|
||||
- [**breaking**] Add support for the shared history flag defined in
|
||||
[MSC3061](https://github.com/matrix-org/matrix-spec-proposals/pull/3061).
|
||||
The shared history flag is now respected when room keys are received as an
|
||||
|
||||
@@ -21,9 +21,9 @@ use std::{
|
||||
use itertools::Itertools;
|
||||
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,
|
||||
@@ -1286,7 +1286,7 @@ impl OlmMachine {
|
||||
transaction: &mut StoreTransaction,
|
||||
changes: &mut Changes,
|
||||
mut raw_event: Raw<AnyToDeviceEvent>,
|
||||
) -> Option<Raw<AnyToDeviceEvent>> {
|
||||
) -> Option<ProcessedToDeviceEvent> {
|
||||
Self::record_message_id(&raw_event);
|
||||
|
||||
let event: ToDeviceEvents = match raw_event.deserialize_as() {
|
||||
@@ -1294,8 +1294,7 @@ impl OlmMachine {
|
||||
Err(e) => {
|
||||
// Skip invalid events.
|
||||
warn!("Received an invalid to-device event: {e}");
|
||||
|
||||
return Some(raw_event);
|
||||
return Some(ProcessedToDeviceEvent::NotProcessed(raw_event));
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1320,7 +1319,7 @@ impl OlmMachine {
|
||||
}
|
||||
}
|
||||
|
||||
return Some(raw_event);
|
||||
return Some(ProcessedToDeviceEvent::UnableToDecrypt { event: raw_event });
|
||||
}
|
||||
};
|
||||
|
||||
@@ -1372,12 +1371,75 @@ impl OlmMachine {
|
||||
raw_event = decrypted.result.raw_event;
|
||||
}
|
||||
}
|
||||
|
||||
let encryption_info =
|
||||
self.get_olm_encryption_info(&e.sender, decrypted.result.sender_key).await;
|
||||
|
||||
Some(ProcessedToDeviceEvent::Decrypted {
|
||||
decrypted_event: raw_event,
|
||||
encryption_info,
|
||||
})
|
||||
}
|
||||
|
||||
e => self.handle_to_device_event(changes, &e).await,
|
||||
e => {
|
||||
self.handle_to_device_event(changes, &e).await;
|
||||
Some(ProcessedToDeviceEvent::PlainText(raw_event))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Some(raw_event)
|
||||
/// Get the sender information for a successfully decrypted olm message.
|
||||
///
|
||||
/// # Arguments
|
||||
///
|
||||
/// * `sender` - The claimed user_id retrieved from the event.
|
||||
///
|
||||
/// * `sender_key` - The `Curve25519PublicKey` linked to the olm session
|
||||
/// that decrypted the message.
|
||||
///
|
||||
/// # Returns
|
||||
///
|
||||
/// A [`EncryptionInfo`] struct.
|
||||
async fn get_olm_encryption_info(
|
||||
&self,
|
||||
sender: &UserId,
|
||||
sender_key: Curve25519PublicKey,
|
||||
) -> EncryptionInfo {
|
||||
let device =
|
||||
self.store().get_device_from_curve_key(sender, sender_key).await.unwrap_or(None);
|
||||
|
||||
let state = if let Some(device) = &device {
|
||||
if device.is_cross_signed_by_owner() {
|
||||
if device.is_device_owner_verified() {
|
||||
VerificationState::Verified
|
||||
} else {
|
||||
let identity = device
|
||||
.device_owner_identity
|
||||
.as_ref()
|
||||
.expect("This device is cross-signed, so the identity exists");
|
||||
if identity.was_previously_verified() {
|
||||
VerificationState::Unverified(VerificationLevel::VerificationViolation)
|
||||
} else {
|
||||
VerificationState::Unverified(VerificationLevel::UnverifiedIdentity)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
VerificationState::Unverified(VerificationLevel::UnsignedDevice)
|
||||
}
|
||||
} else {
|
||||
VerificationState::Unverified(VerificationLevel::None(DeviceLinkProblem::MissingDevice))
|
||||
};
|
||||
|
||||
EncryptionInfo {
|
||||
sender: sender.to_owned(),
|
||||
sender_device: device.map(|d| d.device_id().to_owned()),
|
||||
algorithm_info: AlgorithmInfo::OlmV1Curve25519AesSha2 {
|
||||
curve25519_key: sender_key.to_base64(),
|
||||
},
|
||||
verification_state: state,
|
||||
// Only relevant for megolm
|
||||
session_id: None,
|
||||
}
|
||||
}
|
||||
|
||||
/// Decide whether a decrypted to-device event was sent from a dehydrated
|
||||
@@ -1435,7 +1497,7 @@ impl OlmMachine {
|
||||
pub async fn receive_sync_changes(
|
||||
&self,
|
||||
sync_changes: EncryptionSyncChanges<'_>,
|
||||
) -> OlmResult<(Vec<Raw<AnyToDeviceEvent>>, Vec<RoomKeyInfo>)> {
|
||||
) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
|
||||
let mut store_transaction = self.inner.store.transaction().await;
|
||||
|
||||
let (events, changes) =
|
||||
@@ -1464,10 +1526,18 @@ impl OlmMachine {
|
||||
&self,
|
||||
transaction: &mut StoreTransaction,
|
||||
sync_changes: EncryptionSyncChanges<'_>,
|
||||
) -> OlmResult<(Vec<Raw<AnyToDeviceEvent>>, Changes)> {
|
||||
) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Changes)> {
|
||||
// Remove verification objects that have expired or are done.
|
||||
let mut events = self.inner.verification_machine.garbage_collect();
|
||||
|
||||
let mut events: Vec<ProcessedToDeviceEvent> = self
|
||||
.inner
|
||||
.verification_machine
|
||||
.garbage_collect()
|
||||
.iter()
|
||||
// These are `fake` to device events just serving as local echo
|
||||
// in order for own client to react quickly to cancelled transaction.
|
||||
// Just use PlainText for that.
|
||||
.map(|e| ProcessedToDeviceEvent::PlainText(e.clone()))
|
||||
.collect();
|
||||
// The account is automatically saved by the store transaction created by the
|
||||
// caller.
|
||||
let mut changes = Default::default();
|
||||
|
||||
@@ -17,8 +17,9 @@ 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::{events::AnyToDeviceEvent, room_id, serde::Raw, user_id, RoomId, TransactionId, UserId};
|
||||
use ruma::{room_id, user_id, RoomId, TransactionId, UserId};
|
||||
use serde::Serialize;
|
||||
use serde_json::json;
|
||||
use tokio_stream::wrappers::errors::BroadcastStreamRecvError;
|
||||
@@ -286,7 +287,7 @@ async fn create_and_share_session_without_sender_data(
|
||||
pub async fn receive_to_device_event<C>(
|
||||
machine: &OlmMachine,
|
||||
event: &ToDeviceEvent<C>,
|
||||
) -> (Vec<Raw<AnyToDeviceEvent>>, Vec<RoomKeyInfo>)
|
||||
) -> (Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)
|
||||
where
|
||||
C: EventType + Serialize + Debug,
|
||||
{
|
||||
|
||||
@@ -18,8 +18,9 @@ use assert_matches2::{assert_let, assert_matches};
|
||||
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,
|
||||
};
|
||||
use matrix_sdk_test::{async_test, message_like_event_content, ruma_response_from_json, test_json};
|
||||
use ruma::{
|
||||
@@ -397,7 +398,7 @@ async fn test_room_key_sharing() {
|
||||
let (decrypted, room_key_updates) =
|
||||
send_room_key_to_device(&alice, &bob, room_id).await.unwrap();
|
||||
|
||||
let event = decrypted[0].deserialize().unwrap();
|
||||
let event = decrypted[0].to_raw().deserialize().unwrap();
|
||||
|
||||
if let AnyToDeviceEvent::RoomKey(event) = event {
|
||||
assert_eq!(&event.sender, alice.user_id());
|
||||
@@ -489,7 +490,7 @@ async fn send_room_key_to_device(
|
||||
sender: &OlmMachine,
|
||||
receiver: &OlmMachine,
|
||||
room_id: &RoomId,
|
||||
) -> OlmResult<(Vec<Raw<AnyToDeviceEvent>>, Vec<RoomKeyInfo>)> {
|
||||
) -> OlmResult<(Vec<ProcessedToDeviceEvent>, Vec<RoomKeyInfo>)> {
|
||||
let to_device_requests = sender
|
||||
.share_room_key(room_id, iter::once(receiver.user_id()), EncryptionSettings::default())
|
||||
.await
|
||||
|
||||
@@ -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,
|
||||
@@ -292,7 +293,11 @@ async fn test_decrypt_to_device_message_with_unsigned_sender_keys() {
|
||||
// Bob receives the to-device message
|
||||
let (to_device_events, _) = receive_to_device_event(&bob, &event).await;
|
||||
|
||||
let event = to_device_events.first().expect("Bob did not get a to-device event").clone();
|
||||
|
||||
// The to-device event should remain decrypted.
|
||||
let event = to_device_events.first().expect("Bob did not get a to-device event");
|
||||
let ProcessedToDeviceEvent::UnableToDecrypt { event } = event else {
|
||||
panic!("Should refuse to decrypt")
|
||||
};
|
||||
assert_eq!(event.get_field("type").unwrap(), Some("m.room.encrypted"));
|
||||
}
|
||||
|
||||
@@ -13,8 +13,11 @@
|
||||
// limitations under the License.
|
||||
|
||||
use assert_matches2::assert_matches;
|
||||
use matrix_sdk_common::deserialized_responses::{
|
||||
AlgorithmInfo, ProcessedToDeviceEvent, VerificationLevel, VerificationState,
|
||||
};
|
||||
use matrix_sdk_test::async_test;
|
||||
use ruma::to_device::DeviceIdOrAllDevices;
|
||||
use ruma::{events::AnyToDeviceEvent, serde::Raw, to_device::DeviceIdOrAllDevices};
|
||||
use serde_json::{json, value::to_raw_value};
|
||||
|
||||
use crate::{
|
||||
@@ -22,7 +25,10 @@ use crate::{
|
||||
test_helpers::{get_machine_pair, get_machine_pair_with_session},
|
||||
tests,
|
||||
},
|
||||
types::{events::ToDeviceEvent, requests::ToDeviceRequest},
|
||||
types::{
|
||||
events::{ToDeviceCustomEvent, ToDeviceEvent},
|
||||
requests::ToDeviceRequest,
|
||||
},
|
||||
utilities::json_convert,
|
||||
EncryptionSyncChanges, OlmError,
|
||||
};
|
||||
@@ -81,12 +87,15 @@ async fn test_send_encrypted_to_device() {
|
||||
let (decrypted, _) = bob.receive_sync_changes(sync_changes).await.unwrap();
|
||||
|
||||
assert_eq!(1, decrypted.len());
|
||||
|
||||
let decrypted_event = decrypted[0].deserialize().unwrap();
|
||||
let processed_event = &decrypted[0];
|
||||
let ProcessedToDeviceEvent::Decrypted { decrypted_event, .. } = processed_event else {
|
||||
panic!("Unexpected variant");
|
||||
};
|
||||
let decrypted_event = decrypted_event.deserialize().unwrap();
|
||||
|
||||
assert_eq!(decrypted_event.event_type().to_string(), custom_event_type.to_owned());
|
||||
|
||||
let decrypted_value = to_raw_value(&decrypted[0]).unwrap();
|
||||
let decrypted_value = to_raw_value(&decrypted[0].to_raw()).unwrap();
|
||||
let decrypted_value = serde_json::to_value(decrypted_value).unwrap();
|
||||
|
||||
assert_eq!(
|
||||
@@ -100,6 +109,142 @@ async fn test_send_encrypted_to_device() {
|
||||
);
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_processed_to_device_variants() {
|
||||
let (alice, bob) =
|
||||
get_machine_pair_with_session(tests::alice_id(), tests::user_id(), false).await;
|
||||
|
||||
let custom_event_type = "m.new_device";
|
||||
|
||||
let custom_content = json!({
|
||||
"device_id": "XYZABCDE",
|
||||
"rooms": ["!726s6s6q:example.com"]
|
||||
});
|
||||
|
||||
let device = alice.get_device(bob.user_id(), bob.device_id(), None).await.unwrap().unwrap();
|
||||
let raw_encrypted = device
|
||||
.encrypt_event_raw(custom_event_type, &custom_content)
|
||||
.await
|
||||
.expect("Should have encryted the content");
|
||||
|
||||
let request = ToDeviceRequest::new(
|
||||
bob.user_id(),
|
||||
DeviceIdOrAllDevices::DeviceId(tests::bob_device_id().to_owned()),
|
||||
"m.room.encrypted",
|
||||
raw_encrypted.cast(),
|
||||
);
|
||||
|
||||
let encrypted_event = ToDeviceEvent::new(
|
||||
alice.user_id().to_owned(),
|
||||
tests::to_device_requests_to_content(vec![request.clone().into()]),
|
||||
);
|
||||
|
||||
let custom_event = json!({
|
||||
"sender": "@alice:example.com",
|
||||
"type": "m.new_device",
|
||||
"content": {
|
||||
"device_id": "XYZABCDE",
|
||||
"rooms": ["!726s6s6q:example.com"]
|
||||
}
|
||||
});
|
||||
let clear_event = serde_json::from_value::<ToDeviceCustomEvent>(custom_event.clone()).unwrap();
|
||||
|
||||
let encrypted_event = json_convert(&encrypted_event).unwrap();
|
||||
let clear_event = json_convert(&clear_event).unwrap();
|
||||
|
||||
let malformed_event_no_type = json!({
|
||||
"sender": "@alice:example.com",
|
||||
"content": {
|
||||
"device_id": "XYZABCDE",
|
||||
"rooms": ["!726s6s6q:example.com"]
|
||||
}
|
||||
});
|
||||
let malformed_event: Raw<AnyToDeviceEvent> =
|
||||
serde_json::from_value(malformed_event_no_type).unwrap();
|
||||
|
||||
let alice_curve = alice
|
||||
.get_device(alice.user_id(), alice.device_id(), None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.curve25519_key()
|
||||
.unwrap();
|
||||
let bob_curve = bob
|
||||
.get_device(bob.user_id(), bob.device_id(), None)
|
||||
.await
|
||||
.unwrap()
|
||||
.unwrap()
|
||||
.curve25519_key()
|
||||
.unwrap();
|
||||
|
||||
// let's add a UTD event
|
||||
let utd_event = json!({
|
||||
"content": {
|
||||
"algorithm": "m.olm.v1.curve25519-aes-sha2",
|
||||
"ciphertext": {
|
||||
bob_curve.to_base64(): {
|
||||
// this payload is just captured from a sync of some other element web with other users
|
||||
"body": "Awogjvpx458CGhuo77HX/+tp1sxgRoCi7iAlzMvfrpbWoREQAiKACysX/p+ojr5QitCi9WRXNyamW2v2LTvoyWKtVaA2oHnYGR5s5RYhDfnIgh5MMSqqKlAbfqLvrbLovTYcKagCBbFnbA43f6zYM44buGgy8q70hMVH5WP6aK1E9Z3DVZ+8PnXQGpsrxvz2IsL6w0Nzl/qUyBEQFcgkjoDPawbsZRCllMgq2LQUyqlun6IgDTCozqsfxhDWpdfYGde4z16m34Ang7f5pH+BmPrFs6E1AO5+UbhhhS6NwWlfEtA6/9yfMxWLz1d2OrLh+QG7lYFAU9/CzIoPxaHKKr4JxgL9CjsmUPyDymWOWHP0jLi1NwpOv6hGpx0FgM7jJIMk6gWGgC5rEgEeTIwdrJh3F9OKTNSva5hvD9LomGk6tZgzQG6oap1e3wiOUyTt6S7BlyMppIu3RlIiNihZ9e17JEGiGDXOXzMJ6ISAgvGVgTP7+EvyEt2Wt4du7uBo/UvljRvVNu3I8tfItizPAOlvz460+aBDxk+sflJWt7OnhiyPnOCfopb+1RzqKVCnnPyVaP2f4BPf8qpn/f5YZk+5jJgBrGPiHzzmb3sQ5pC470s6+U3MpVFlFTG/xPBtMRMwPsbKoHfnRPqIqGu5dQ1Sw7T6taDXWjP450TvjxgHK5t2z1rLA2SXzAB1P8xbi6YXqQwxL6PvMNHn/TM0jiIQHYuqg5/RKLyhHybfP8JAjgNBw9z16wfKR/YoYFr7c+S4McQaMNa8v2SxGzhpCC3duAoK2qCWLEkYRO5cMCsGm/9bf8Q+//OykygBU/hdkT1eHUbexgALPLdfhzduutU7pbChg4T7SH7euh/3NLmS/SQvkmPfm3ckbh/Vlcj9CsXws/7MX/VJbhpbyzgBNtMnbG6tAeAofMa6Go/yMgiNBZIhLpAm31iUbUhaGm2IIlF/lsmSYEiBPoSVfFU44tetX2I/PBDGiBlzyU+yC2TOEBwMGxBE3WHbIe5/7sKW8xJF9t+HBfxIyW1QRtY3EKdEcuVOTyMxYzq3L5OKOOtPDHObYiiXg00mAgdQqgfkEAIfoRCOa2NYfTedwwo0S77eQ1sPvW5Hhf+Cm+bLibkWzaYHEZF+vyE9/Tn0tZGtH07RXfUyhp1vtTH49OBZHGkb/r+L8OjYJTST1dDCGqeGXO3uwYjoWHXtezLVHYgL+UOwcLJfMF5s9DQiqcfYXzp2kEWGsaetBFXcUWqq4RMHqlr6QfbxyuYLlQzc/AYA/MrT3J6nDpNLcvozH3RcIs8NcKcjdtjvgL0QGThy3RcecJQEDx3STrkkePL3dlyFCtVsmtQ0vjBBCxUgdySfxiobGGnpezZYi7q+Xz61GOZ9QqYmkcZOPzfNWeqtmzB7gqlH1gkFsK2yMAzKq2XCDFHvA7YAT3yMGiY06FcQ+2jyg7Bk2Q+AvjTG8hlPlmt6BZfW5cz1qx1apQn1qHXHrgfWcI52rApYQlNPOU1Uc8kZ8Ee6XUhhXBGY1rvZiKjKFG0PPuS8xo4/P7/u+gH5gItmEVDFL6giYPFsPpqAQkUN7hFoGiVZEjO4PwrLOmydsEcNOfACqrnUs08FQtvPg0sjHnxh6nh6FUQv93ukKl6+c9d+pCsN2xukrQ7Dog3nrjFZ6PrS5J0k9rDAOwTB55sfGXPZ2rATOK1WS4XcpsCtqwnYm4sGNc8ALMQkQ97zCnw8TcQwLvdUMlfbqQ5ykDQpQD68fITEDDHmBAeTCjpC713E6AhvOMwTJvjhd7hSkeOTRTmn9zXIVGNo1jSr8u0xO9uLGeWsV0+UlRLgp7/nsgfermjwNN8wj6MW3DHGS8UzzYfe9TGCeywqqIUTqgfXY48leGgB7twh4cl4jcOQniLATTvigIAQIvq/Uv8L45BGnkpKTdQ5F73gehXdVA",
|
||||
"type": 1
|
||||
}
|
||||
},
|
||||
"org.matrix.msgid": "93ee0170aa7740d0ac9ee137e820302d",
|
||||
"sender_key": alice_curve.to_base64(),
|
||||
},
|
||||
"type": "m.room.encrypted",
|
||||
"sender": "@alice:example.org",
|
||||
});
|
||||
|
||||
let utd_event: Raw<AnyToDeviceEvent> = serde_json::from_value(utd_event).unwrap();
|
||||
|
||||
let sync_changes = EncryptionSyncChanges {
|
||||
to_device_events: vec![encrypted_event, clear_event, malformed_event, utd_event],
|
||||
changed_devices: &Default::default(),
|
||||
one_time_keys_counts: &Default::default(),
|
||||
unused_fallback_keys: None,
|
||||
next_batch_token: None,
|
||||
};
|
||||
|
||||
let (processed, _) = bob.receive_sync_changes(sync_changes).await.unwrap();
|
||||
|
||||
assert_eq!(4, processed.len());
|
||||
|
||||
let processed_event = &processed[0];
|
||||
let ProcessedToDeviceEvent::Decrypted { encryption_info, .. } = processed_event else {
|
||||
panic!("Unexpected variant");
|
||||
};
|
||||
|
||||
assert_eq!(alice.user_id().to_owned(), encryption_info.sender);
|
||||
assert_eq!(Some(alice.device_id().to_owned()), encryption_info.sender_device);
|
||||
|
||||
let AlgorithmInfo::OlmV1Curve25519AesSha2 { curve25519_key } = &encryption_info.algorithm_info
|
||||
else {
|
||||
panic!("Unexpected algorithm info");
|
||||
};
|
||||
assert_eq!(curve25519_key.to_owned(), alice_curve.to_base64());
|
||||
|
||||
assert_eq!(encryption_info.session_id, None);
|
||||
assert_eq!(
|
||||
encryption_info.verification_state,
|
||||
VerificationState::Unverified(VerificationLevel::UnsignedDevice)
|
||||
);
|
||||
|
||||
let processed_event = &processed[1];
|
||||
let ProcessedToDeviceEvent::PlainText(_) = processed_event else {
|
||||
panic!("Unexpected variant");
|
||||
};
|
||||
|
||||
let processed_event = &processed[2];
|
||||
let ProcessedToDeviceEvent::NotProcessed(_) = processed_event else {
|
||||
panic!("Unexpected variant");
|
||||
};
|
||||
|
||||
let processed_event = &processed[3];
|
||||
let ProcessedToDeviceEvent::UnableToDecrypt { .. } = processed_event else {
|
||||
panic!("Unexpected variant");
|
||||
};
|
||||
}
|
||||
|
||||
#[async_test]
|
||||
async fn test_send_encrypted_to_device_no_session() {
|
||||
let (alice, bob, _) = get_machine_pair(tests::alice_id(), tests::user_id(), false).await;
|
||||
|
||||
@@ -1031,7 +1031,7 @@ mod tests {
|
||||
};
|
||||
|
||||
use assert_matches2::assert_let;
|
||||
use matrix_sdk_common::deserialized_responses::WithheldCode;
|
||||
use matrix_sdk_common::deserialized_responses::{ProcessedToDeviceEvent, WithheldCode};
|
||||
use matrix_sdk_test::{async_test, ruma_response_from_json};
|
||||
use ruma::{
|
||||
api::client::{
|
||||
@@ -1822,8 +1822,12 @@ mod tests {
|
||||
let (decrypted, _) = bob.receive_sync_changes(sync_changes).await.unwrap();
|
||||
assert_eq!(1, decrypted.len());
|
||||
use crate::types::events::EventType;
|
||||
assert_let!(
|
||||
ProcessedToDeviceEvent::Decrypted { decrypted_event, .. } =
|
||||
decrypted.first().unwrap().clone()
|
||||
);
|
||||
assert_eq!(
|
||||
decrypted[0].get_field::<String>("type").unwrap().unwrap(),
|
||||
decrypted_event.get_field::<String>("type").unwrap().unwrap(),
|
||||
RoomKeyBundleContent::EVENT_TYPE,
|
||||
);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user