diff --git a/bindings/matrix-sdk-crypto-ffi/src/error.rs b/bindings/matrix-sdk-crypto-ffi/src/error.rs index 784b459ccc7..273e059002b 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/error.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/error.rs @@ -61,4 +61,6 @@ pub enum DecryptionError { Identifier(#[from] IdParseError), #[error(transparent)] Megolm(#[from] MegolmError), + #[error(transparent)] + Store(#[from] InnerStoreError), } diff --git a/bindings/matrix-sdk-crypto-ffi/src/machine.rs b/bindings/matrix-sdk-crypto-ffi/src/machine.rs index d75413169e5..38656bbcd5d 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/machine.rs +++ b/bindings/matrix-sdk-crypto-ffi/src/machine.rs @@ -34,7 +34,10 @@ use ruma::{ }, IncomingResponse, }, - events::{key::verification::VerificationMethod, AnySyncMessageLikeEvent}, + events::{ + key::verification::VerificationMethod, room::message::MessageType, AnyMessageLikeEvent, + AnySyncMessageLikeEvent, AnyTimelineEvent, MessageLikeEvent, + }, serde::Raw, DeviceKeyAlgorithm, EventId, OwnedTransactionId, OwnedUserId, RoomId, UserId, }; @@ -635,6 +638,7 @@ impl OlmMachine { &self, event: &str, room_id: &str, + handle_verification_events: bool, ) -> Result { // Element Android wants only the content and the type and will create a // decrypted event with those two itself, this struct makes sure we @@ -652,6 +656,25 @@ impl OlmMachine { let decrypted = self.runtime.block_on(self.inner.decrypt_room_event(&event, &room_id))?; + if handle_verification_events { + if let Ok(AnyTimelineEvent::MessageLike(e)) = decrypted.event.deserialize() { + match &e { + AnyMessageLikeEvent::RoomMessage(MessageLikeEvent::Original( + original_event, + )) => { + if let MessageType::VerificationRequest(_) = &original_event.content.msgtype + { + self.runtime.block_on(self.inner.receive_verification_event(&e))?; + } + } + _ if e.event_type().to_string().starts_with("m.key.verification") => { + self.runtime.block_on(self.inner.receive_verification_event(&e))?; + } + _ => (), + } + } + } + let encryption_info = decrypted.encryption_info.expect("Decrypted event didn't contain any encryption info"); @@ -810,19 +833,30 @@ impl OlmMachine { /// This method can be used to pass verification events that are happening /// in unencrypted rooms to the `OlmMachine`. /// - /// **Note**: This does not need to be called for encrypted events since - /// those will get passed to the `OlmMachine` during decryption. + /// **Note**: This has been deprecated. pub fn receive_unencrypted_verification_event( &self, event: &str, room_id: &str, + ) -> Result<(), CryptoStoreError> { + self.receive_verification_event(event, room_id) + } + + /// Receive a verification event. + /// + /// This method can be used to pass verification events that are happening + /// in rooms to the `OlmMachine`. The event should be in the decrypted form. + pub fn receive_verification_event( + &self, + event: &str, + room_id: &str, ) -> Result<(), CryptoStoreError> { let room_id = RoomId::parse(room_id)?; let event: AnySyncMessageLikeEvent = serde_json::from_str(event)?; let event = event.into_full_event(room_id); - self.runtime.block_on(self.inner.receive_unencrypted_verification_event(&event))?; + self.runtime.block_on(self.inner.receive_verification_event(&event))?; Ok(()) } diff --git a/bindings/matrix-sdk-crypto-ffi/src/olm.udl b/bindings/matrix-sdk-crypto-ffi/src/olm.udl index 372d1d5c925..67f52fec936 100644 --- a/bindings/matrix-sdk-crypto-ffi/src/olm.udl +++ b/bindings/matrix-sdk-crypto-ffi/src/olm.udl @@ -59,6 +59,7 @@ enum DecryptionError { "Identifier", "Serialization", "Megolm", + "Store", }; dictionary DeviceLists { @@ -365,7 +366,7 @@ interface OlmMachine { ); [Throws=DecryptionError] - DecryptedEvent decrypt_room_event([ByRef] string event, [ByRef] string room_id); + DecryptedEvent decrypt_room_event([ByRef] string event, [ByRef] string room_id, boolean handle_verificaton_events); [Throws=CryptoStoreError] string encrypt([ByRef] string room_id, [ByRef] string event_type, [ByRef] string content); @@ -396,6 +397,8 @@ interface OlmMachine { [Throws=CryptoStoreError] void receive_unencrypted_verification_event([ByRef] string event, [ByRef] string room_id); + [Throws=CryptoStoreError] + void receive_verification_event([ByRef] string event, [ByRef] string room_id); sequence get_verification_requests([ByRef] string user_id); VerificationRequest? get_verification_request([ByRef] string user_id, [ByRef] string flow_id); Verification? get_verification([ByRef] string user_id, [ByRef] string flow_id); diff --git a/bindings/matrix-sdk-crypto-js/src/machine.rs b/bindings/matrix-sdk-crypto-js/src/machine.rs index 7d00cf179f4..eeedc75141a 100644 --- a/bindings/matrix-sdk-crypto-js/src/machine.rs +++ b/bindings/matrix-sdk-crypto-js/src/machine.rs @@ -633,24 +633,17 @@ impl OlmMachine { .collect() } - /// Receive an unencrypted verification event. + /// Receive a verification event. /// - /// This method can be used to pass verification events that are - /// happening in unencrypted rooms to the `OlmMachine`. - /// - /// Note: This does not need to be called for encrypted events - /// since those will get passed to the `OlmMachine` during - /// decryption. - #[wasm_bindgen(js_name = "receiveUnencryptedVerificationEvent")] - pub fn receive_unencrypted_verification_event(&self, event: &str) -> Result { + /// This method can be used to pass verification events that are happening + /// in rooms to the `OlmMachine`. The event should be in the decrypted form. + #[wasm_bindgen(js_name = "receiveVerificationEvent")] + pub fn receive_verification_event(&self, event: &str) -> Result { let event: ruma::events::AnyMessageLikeEvent = serde_json::from_str(event)?; let me = self.inner.clone(); Ok(future_to_promise(async move { - Ok(me - .receive_unencrypted_verification_event(&event) - .await - .map(|_| JsValue::UNDEFINED)?) + Ok(me.receive_verification_event(&event).await.map(|_| JsValue::UNDEFINED)?) })) } diff --git a/crates/matrix-sdk-base/src/client.rs b/crates/matrix-sdk-base/src/client.rs index 0b321a5b4ab..0caf92fafa9 100644 --- a/crates/matrix-sdk-base/src/client.rs +++ b/crates/matrix-sdk-base/src/client.rs @@ -31,7 +31,10 @@ use matrix_sdk_crypto::{ use once_cell::sync::OnceCell; #[cfg(feature = "e2e-encryption")] use ruma::events::{ - room::{history_visibility::HistoryVisibility, redaction::SyncRoomRedactionEvent}, + room::{ + history_visibility::HistoryVisibility, message::MessageType, + redaction::SyncRoomRedactionEvent, + }, AnySyncMessageLikeEvent, SyncMessageLikeEvent, }; use ruma::{ @@ -240,21 +243,49 @@ impl BaseClient { } #[cfg(feature = "e2e-encryption")] - async fn handle_unencrypted_verification_event( + async fn handle_verification_event( &self, event: &AnySyncMessageLikeEvent, room_id: &RoomId, ) -> Result<()> { if let Some(olm) = self.olm_machine() { - olm.receive_unencrypted_verification_event( - &event.clone().into_full_event(room_id.to_owned()), - ) - .await?; + olm.receive_verification_event(&event.clone().into_full_event(room_id.to_owned())) + .await?; } Ok(()) } + #[cfg(feature = "e2e-encryption")] + async fn decrypt_sync_room_event( + &self, + event: &Raw, + room_id: &RoomId, + ) -> Result> { + let Some(olm) = self.olm_machine() else { return Ok(None) }; + + let event = olm.decrypt_room_event(event.cast_ref(), room_id).await.unwrap(); + let event: SyncTimelineEvent = event.into(); + + if let Ok(AnySyncTimelineEvent::MessageLike(e)) = event.event.deserialize() { + match &e { + AnySyncMessageLikeEvent::RoomMessage(SyncMessageLikeEvent::Original( + original_event, + )) => { + if let MessageType::VerificationRequest(_) = &original_event.content.msgtype { + self.handle_verification_event(&e, room_id).await?; + } + } + _ if e.event_type().to_string().starts_with("m.key.verification") => { + self.handle_verification_event(&e, room_id).await?; + } + _ => (), + } + } + + Ok(Some(event)) + } + #[allow(clippy::too_many_arguments)] pub(crate) async fn handle_timeline( &self, @@ -338,13 +369,10 @@ impl BaseClient { AnySyncMessageLikeEvent::RoomEncrypted( SyncMessageLikeEvent::Original(_), ) => { - if let Some(olm) = self.olm_machine() { - if let Ok(decrypted) = olm - .decrypt_room_event(event.event.cast_ref(), room_id) - .await - { - event = decrypted.into(); - } + if let Ok(Some(e)) = + self.decrypt_sync_room_event(&event.event, room_id).await + { + event = e; } } AnySyncMessageLikeEvent::RoomMessage( @@ -353,12 +381,12 @@ impl BaseClient { ruma::events::room::message::MessageType::VerificationRequest( _, ) => { - self.handle_unencrypted_verification_event(e, room_id).await?; + self.handle_verification_event(e, room_id).await?; } _ => (), }, _ if e.event_type().to_string().starts_with("m.key.verification") => { - self.handle_unencrypted_verification_event(e, room_id).await?; + self.handle_verification_event(e, room_id).await?; } _ => (), }, diff --git a/crates/matrix-sdk-crypto/src/machine.rs b/crates/matrix-sdk-crypto/src/machine.rs index 87d513536aa..946b5dcd380 100644 --- a/crates/matrix-sdk-crypto/src/machine.rs +++ b/crates/matrix-sdk-crypto/src/machine.rs @@ -35,15 +35,14 @@ use ruma::{ }, assign, events::{ - secret::request::SecretName, AnyMessageLikeEvent, AnyTimelineEvent, AnyToDeviceEvent, - MessageLikeEventContent, + secret::request::SecretName, AnyMessageLikeEvent, AnyToDeviceEvent, MessageLikeEventContent, }, serde::Raw, DeviceId, DeviceKeyAlgorithm, OwnedDeviceId, OwnedDeviceKeyId, OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UInt, UserId, }; use serde_json::{value::to_raw_value, Value}; -use tracing::{debug, error, field::debug, info, instrument, trace, warn}; +use tracing::{debug, error, field::debug, info, instrument, warn}; use vodozemac::{ megolm::{DecryptionError, SessionOrdering}, Curve25519PublicKey, Ed25519Signature, @@ -731,6 +730,7 @@ impl OlmMachine { /// /// **Note**: This does not need to be called for encrypted events since /// those will get passed to the `OlmMachine` during decryption. + #[deprecated(note = "Use OlmMachine::receive_verification_event instead", since = "0.7.0")] pub async fn receive_unencrypted_verification_event( &self, event: &AnyMessageLikeEvent, @@ -738,6 +738,14 @@ impl OlmMachine { self.verification_machine.receive_any_event(event).await } + /// Receive a verification event. + /// + /// in rooms to the `OlmMachine`. The event should be in the decrypted form. + /// in rooms to the `OlmMachine`. + pub async fn receive_verification_event(&self, event: &AnyMessageLikeEvent) -> StoreResult<()> { + self.verification_machine.receive_any_event(event).await + } + /// Receive and properly handle a decrypted to-device event. /// /// # Arguments @@ -1127,22 +1135,6 @@ impl OlmMachine { // TODO: check the message index. let (decrypted_event, _) = session.decrypt(event).await?; - - match decrypted_event.deserialize() { - Ok(e) => { - // TODO: log the event type once `AnyTimelineEvent` has the - // method as well - trace!("Successfully decrypted a room event"); - - if let AnyTimelineEvent::MessageLike(e) = e { - self.verification_machine.receive_any_event(&e).await?; - } - } - Err(e) => { - warn!("Event was successfully decrypted but has an invalid format: {e}"); - } - } - let encryption_info = self.get_encryption_info(&session, &event.sender).await?; Ok(TimelineEvent { encryption_info: Some(encryption_info), event: decrypted_event })