From ddf8577c84e961d93de5dc370bb19e242a312951 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Wed, 3 Aug 2022 15:05:35 +0200 Subject: [PATCH] refactor(crypto): Start using our own event types when we encrypt --- .../src/gossiping/machine.rs | 22 +++++++------- .../src/identities/device.rs | 17 +++++++---- crates/matrix-sdk-crypto/src/machine.rs | 7 ++--- crates/matrix-sdk-crypto/src/olm/account.rs | 8 +++-- .../src/olm/group_sessions/outbound.rs | 29 ++++++++++--------- crates/matrix-sdk-crypto/src/olm/session.rs | 13 +++------ .../src/session_manager/group_sessions.rs | 18 +++++++----- .../src/session_manager/sessions.rs | 6 ++-- .../src/types/events/room_key.rs | 7 +++++ .../src/types/events/secret_send.rs | 11 +++++-- 10 files changed, 79 insertions(+), 59 deletions(-) diff --git a/crates/matrix-sdk-crypto/src/gossiping/machine.rs b/crates/matrix-sdk-crypto/src/gossiping/machine.rs index 25729cd7b82..098a8d64b18 100644 --- a/crates/matrix-sdk-crypto/src/gossiping/machine.rs +++ b/crates/matrix-sdk-crypto/src/gossiping/machine.rs @@ -28,13 +28,9 @@ use ruma::{ events::{ forwarded_room_key::{ToDeviceForwardedRoomKeyEvent, ToDeviceForwardedRoomKeyEventContent}, room_key_request::{Action, RequestedKeyInfo, ToDeviceRoomKeyRequestEvent}, - secret::{ - request::{ - RequestAction, SecretName, ToDeviceSecretRequestEvent as SecretRequestEvent, - }, - send::ToDeviceSecretSendEventContent as SecretSendEventContent, + secret::request::{ + RequestAction, SecretName, ToDeviceSecretRequestEvent as SecretRequestEvent, }, - AnyToDeviceEventContent, }, DeviceId, DeviceKeyAlgorithm, EventEncryptionAlgorithm, OwnedDeviceId, OwnedTransactionId, OwnedUserId, RoomId, TransactionId, UserId, @@ -49,7 +45,10 @@ use crate::{ requests::{OutgoingRequest, ToDeviceRequest}, session_manager::GroupSessionCache, store::{Changes, CryptoStoreError, SecretImportError, Store}, - types::events::{secret_send::SecretSendEvent, EventType}, + types::events::{ + secret_send::{SecretSendContent, SecretSendEvent}, + EventType, + }, Device, }; @@ -238,7 +237,7 @@ impl GossipMachine { }; let content = if let Some(secret) = self.store.export_secret(secret_name).await { - SecretSendEventContent::new(event.content.request_id.to_owned(), secret) + SecretSendContent::new(event.content.request_id.to_owned(), secret) } else { info!(?secret_name, "Can't serve a secret request, secret isn't found"); return Ok(None); @@ -428,10 +427,11 @@ impl GossipMachine { async fn share_secret( &self, device: &Device, - content: SecretSendEventContent, + content: SecretSendContent, ) -> OlmResult { - let (used_session, content) = - device.encrypt(AnyToDeviceEventContent::SecretSend(content)).await?; + let event_type = content.event_type(); + let content = serde_json::to_value(content)?; + let (used_session, content) = device.encrypt(event_type, content).await?; let request = ToDeviceRequest::new( device.user_id(), diff --git a/crates/matrix-sdk-crypto/src/identities/device.rs b/crates/matrix-sdk-crypto/src/identities/device.rs index 83920a54e10..aae701d3d02 100644 --- a/crates/matrix-sdk-crypto/src/identities/device.rs +++ b/crates/matrix-sdk-crypto/src/identities/device.rs @@ -28,13 +28,14 @@ use ruma::{ api::client::keys::upload_signatures::v3::Request as SignatureUploadRequest, events::{ forwarded_room_key::ToDeviceForwardedRoomKeyEventContent, - key::verification::VerificationMethod, AnyToDeviceEventContent, + key::verification::VerificationMethod, }, serde::Raw, DeviceId, DeviceKeyAlgorithm, DeviceKeyId, EventEncryptionAlgorithm, OwnedDeviceId, OwnedDeviceKeyId, UserId, }; use serde::{Deserialize, Deserializer, Serialize, Serializer}; +use serde_json::Value; use tracing::warn; use vodozemac::{Curve25519PublicKey, Ed25519PublicKey}; @@ -257,9 +258,10 @@ impl Device { /// * `content` - The content of the event that should be encrypted. pub(crate) async fn encrypt( &self, - content: AnyToDeviceEventContent, + event_type: &str, + content: Value, ) -> OlmResult<(Session, Raw)> { - self.inner.encrypt(self.verification_machine.store.inner(), content).await + self.inner.encrypt(self.verification_machine.store.inner(), event_type, content).await } /// Encrypt the given inbound group session as a forwarded room key for this @@ -288,7 +290,9 @@ impl Device { ); }; - self.encrypt(AnyToDeviceEventContent::ForwardedRoomKey(content)).await + let content = serde_json::to_value(content)?; + + self.encrypt("m.forwarded_room_key", content).await } } @@ -514,7 +518,8 @@ impl ReadOnlyDevice { pub(crate) async fn encrypt( &self, store: &dyn CryptoStore, - content: AnyToDeviceEventContent, + event_type: &str, + content: Value, ) -> OlmResult<(Session, Raw)> { let sender_key = if let Some(k) = self.curve25519_key() { k @@ -548,7 +553,7 @@ impl ReadOnlyDevice { return Err(OlmError::MissingSession); }; - let message = session.encrypt(self, content).await?; + let message = session.encrypt(self, event_type, content).await?; Ok((session, message)) } diff --git a/crates/matrix-sdk-crypto/src/machine.rs b/crates/matrix-sdk-crypto/src/machine.rs index cac08f24696..075a35419e3 100644 --- a/crates/matrix-sdk-crypto/src/machine.rs +++ b/crates/matrix-sdk-crypto/src/machine.rs @@ -1589,8 +1589,7 @@ pub(crate) mod tests { message::{MessageType, RoomMessageEventContent}, }, AnyMessageLikeEvent, AnyMessageLikeEventContent, AnyRoomEvent, AnyToDeviceEvent, - AnyToDeviceEventContent, MessageLikeEvent, MessageLikeUnsigned, - OriginalMessageLikeEvent, + MessageLikeEvent, MessageLikeUnsigned, OriginalMessageLikeEvent, }, room_id, serde::Raw, @@ -1717,7 +1716,7 @@ pub(crate) mod tests { alice.get_device(&bob.user_id, &bob.device_id, None).await.unwrap().unwrap(); let (session, content) = bob_device - .encrypt(AnyToDeviceEventContent::Dummy(ToDeviceDummyEventContent::new())) + .encrypt("m.dummy", serde_json::to_value(ToDeviceDummyEventContent::new()).unwrap()) .await .unwrap(); alice.store.save_sessions(&[session]).await.unwrap(); @@ -1945,7 +1944,7 @@ pub(crate) mod tests { let event = ToDeviceEvent { sender: alice.user_id().to_owned(), content: bob_device - .encrypt(AnyToDeviceEventContent::Dummy(ToDeviceDummyEventContent::new())) + .encrypt("m.dummy", serde_json::to_value(ToDeviceDummyEventContent::new()).unwrap()) .await .unwrap() .1 diff --git a/crates/matrix-sdk-crypto/src/olm/account.rs b/crates/matrix-sdk-crypto/src/olm/account.rs index 7f3a1ead4cf..bfb4a1b3e43 100644 --- a/crates/matrix-sdk-crypto/src/olm/account.rs +++ b/crates/matrix-sdk-crypto/src/olm/account.rs @@ -1094,7 +1094,7 @@ impl ReadOnlyAccount { #[allow(dead_code)] /// Testing only helper to create a session for the given Account pub async fn create_session_for(&self, other: &ReadOnlyAccount) -> (Session, Session) { - use ruma::events::{dummy::ToDeviceDummyEventContent, AnyToDeviceEventContent}; + use ruma::events::dummy::ToDeviceDummyEventContent; other.generate_one_time_keys_helper(1).await; let one_time = other.signed_one_time_keys().await; @@ -1107,7 +1107,11 @@ impl ReadOnlyAccount { other.mark_keys_as_published().await; let message = our_session - .encrypt(&device, AnyToDeviceEventContent::Dummy(ToDeviceDummyEventContent::new())) + .encrypt( + &device, + "m.dummy", + serde_json::to_value(ToDeviceDummyEventContent::new()).unwrap(), + ) .await .unwrap() .deserialize() diff --git a/crates/matrix-sdk-crypto/src/olm/group_sessions/outbound.rs b/crates/matrix-sdk-crypto/src/olm/group_sessions/outbound.rs index 5ac3af7abd5..076bde33171 100644 --- a/crates/matrix-sdk-crypto/src/olm/group_sessions/outbound.rs +++ b/crates/matrix-sdk-crypto/src/olm/group_sessions/outbound.rs @@ -26,11 +26,7 @@ use std::{ use dashmap::DashMap; use matrix_sdk_common::locks::Mutex; use ruma::{ - events::{ - room::{encryption::RoomEncryptionEventContent, history_visibility::HistoryVisibility}, - room_key::ToDeviceRoomKeyEventContent, - AnyToDeviceEventContent, - }, + events::room::{encryption::RoomEncryptionEventContent, history_visibility::HistoryVisibility}, serde::Raw, DeviceId, EventEncryptionAlgorithm, OwnedDeviceId, OwnedTransactionId, OwnedUserId, RoomId, SecondsSinceUnixEpoch, TransactionId, UserId, @@ -46,8 +42,11 @@ pub use vodozemac::{ }; use crate::{ - types::events::room::encrypted::{ - MegolmV1AesSha2Content, RoomEncryptedEventContent, RoomEventEncryptionScheme, + types::events::{ + room::encrypted::{ + MegolmV1AesSha2Content, RoomEncryptedEventContent, RoomEventEncryptionScheme, + }, + room_key::{MegolmV1AesSha2Content as MegolmV1AesSha2RoomKeyContent, RoomKeyContent}, }, Device, ToDeviceRequest, }; @@ -374,15 +373,17 @@ impl OutboundGroupSession { session.message_index() } - pub(crate) async fn as_content(&self) -> AnyToDeviceEventContent { + pub(crate) async fn as_content(&self) -> RoomKeyContent { let session_key = self.session_key().await; - AnyToDeviceEventContent::RoomKey(ToDeviceRoomKeyEventContent::new( - EventEncryptionAlgorithm::MegolmV1AesSha2, - self.room_id().to_owned(), - self.session_id().to_owned(), - session_key.to_base64(), - )) + RoomKeyContent::MegolmV1AesSha2( + MegolmV1AesSha2RoomKeyContent::new( + self.room_id().to_owned(), + self.session_id().to_owned(), + session_key, + ) + .into(), + ) } /// Has or will the session be shared with the given user/device pair. diff --git a/crates/matrix-sdk-crypto/src/olm/session.rs b/crates/matrix-sdk-crypto/src/olm/session.rs index ae4d63bf29e..c887beb5887 100644 --- a/crates/matrix-sdk-crypto/src/olm/session.rs +++ b/crates/matrix-sdk-crypto/src/olm/session.rs @@ -15,13 +15,9 @@ use std::{fmt, sync::Arc}; use matrix_sdk_common::locks::Mutex; -use ruma::{ - events::{AnyToDeviceEventContent, EventContent}, - serde::Raw, - DeviceId, SecondsSinceUnixEpoch, UserId, -}; +use ruma::{serde::Raw, DeviceId, SecondsSinceUnixEpoch, UserId}; use serde::{Deserialize, Serialize}; -use serde_json::json; +use serde_json::{json, Value}; use vodozemac::{ olm::{DecryptionError, OlmMessage, Session as InnerSession, SessionPickle}, Curve25519PublicKey, @@ -117,13 +113,12 @@ impl Session { pub async fn encrypt( &mut self, recipient_device: &ReadOnlyDevice, - content: AnyToDeviceEventContent, + event_type: &str, + content: Value, ) -> OlmResult> { let recipient_signing_key = recipient_device.ed25519_key().ok_or(EventError::MissingSigningKey)?; - let event_type = content.event_type(); - let payload = json!({ "sender": self.user_id.as_str(), "sender_device": self.device_id.as_ref(), diff --git a/crates/matrix-sdk-crypto/src/session_manager/group_sessions.rs b/crates/matrix-sdk-crypto/src/session_manager/group_sessions.rs index be1483bc557..c23e9df610e 100644 --- a/crates/matrix-sdk-crypto/src/session_manager/group_sessions.rs +++ b/crates/matrix-sdk-crypto/src/session_manager/group_sessions.rs @@ -35,7 +35,7 @@ use crate::{ error::{EventError, MegolmResult, OlmResult}, olm::{Account, InboundGroupSession, OutboundGroupSession, Session, ShareInfo, ShareState}, store::{Changes, Result as StoreResult, Store}, - types::events::room::encrypted::RoomEncryptedEventContent, + types::events::{room::encrypted::RoomEncryptedEventContent, EventType}, Device, EncryptionSettings, OlmError, ToDeviceRequest, }; @@ -216,7 +216,7 @@ impl GroupSessionManager { /// Encrypt the given content for the given devices and create a to-device /// requests that sends the encrypted content to them. async fn encrypt_session_for( - content: AnyToDeviceEventContent, + content: OutboundGroupSession, devices: Vec, message_index: u32, ) -> OlmResult<( @@ -237,11 +237,16 @@ impl GroupSessionManager { let mut changed_sessions = Vec::new(); let mut share_infos = BTreeMap::new(); - let encrypt = |device: Device, content: AnyToDeviceEventContent| async move { + let encrypt = |device: Device, session: OutboundGroupSession| async move { let mut message = BTreeMap::new(); let mut share_info = BTreeMap::new(); - let encrypted = device.encrypt(content.clone()).await; + let content = session.as_content().await; + let event_type = content.event_type(); + let content = + serde_json::to_value(content).expect("We can always serialize our own room key"); + + let encrypted = device.encrypt(event_type, content).await; let used_session = match encrypted { Ok((session, encrypted)) => { @@ -409,13 +414,12 @@ impl GroupSessionManager { pub async fn encrypt_request( chunk: Vec, - content: AnyToDeviceEventContent, outbound: OutboundGroupSession, message_index: u32, being_shared: Arc>, ) -> OlmResult> { let (id, request, share_infos, used_sessions) = - Self::encrypt_session_for(content.clone(), chunk, message_index).await?; + Self::encrypt_session_for(outbound.clone(), chunk, message_index).await?; if !request.messages.is_empty() { outbound.add_request(id.clone(), request.into(), share_infos); @@ -499,7 +503,6 @@ impl GroupSessionManager { }) .collect(); - let key_content = outbound.as_content().await; let message_index = outbound.message_index().await; // If we have some recipients, log them here. @@ -531,7 +534,6 @@ impl GroupSessionManager { .map(|chunk| { spawn(Self::encrypt_request( chunk.to_vec(), - key_content.clone(), outbound.clone(), message_index, self.sessions.sessions_being_shared.clone(), diff --git a/crates/matrix-sdk-crypto/src/session_manager/sessions.rs b/crates/matrix-sdk-crypto/src/session_manager/sessions.rs index 87360f33838..6ba67302dab 100644 --- a/crates/matrix-sdk-crypto/src/session_manager/sessions.rs +++ b/crates/matrix-sdk-crypto/src/session_manager/sessions.rs @@ -24,7 +24,7 @@ use ruma::{ Request as KeysClaimRequest, Response as KeysClaimResponse, }, assign, - events::{dummy::ToDeviceDummyEventContent, AnyToDeviceEventContent}, + events::dummy::ToDeviceDummyEventContent, DeviceId, DeviceKeyAlgorithm, EventEncryptionAlgorithm, OwnedDeviceId, OwnedTransactionId, OwnedUserId, SecondsSinceUnixEpoch, TransactionId, UserId, }; @@ -140,8 +140,8 @@ impl SessionManager { async fn check_if_unwedged(&self, user_id: &UserId, device_id: &DeviceId) -> OlmResult<()> { if self.wedged_devices.get(user_id).and_then(|d| d.remove(device_id)).is_some() { if let Some(device) = self.store.get_device(user_id, device_id).await? { - let content = AnyToDeviceEventContent::Dummy(ToDeviceDummyEventContent::new()); - let (_, content) = device.encrypt(content).await?; + let content = serde_json::to_value(ToDeviceDummyEventContent::new())?; + let (_, content) = device.encrypt("m.dummy", content).await?; let request = ToDeviceRequest::new( device.user_id(), diff --git a/crates/matrix-sdk-crypto/src/types/events/room_key.rs b/crates/matrix-sdk-crypto/src/types/events/room_key.rs index 4be9b1d38cc..0c8ec4f894e 100644 --- a/crates/matrix-sdk-crypto/src/types/events/room_key.rs +++ b/crates/matrix-sdk-crypto/src/types/events/room_key.rs @@ -110,6 +110,13 @@ pub struct MegolmV1AesSha2Content { other: BTreeMap, } +impl MegolmV1AesSha2Content { + /// Create a new `m.megolm.v1.aes-sha2` `m.room_key` content. + pub fn new(room_id: OwnedRoomId, session_id: String, session_key: SessionKey) -> Self { + Self { room_id, session_id, session_key, other: Default::default() } + } +} + impl std::fmt::Debug for MegolmV1AesSha2Content { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("MegolmV1AesSha2Content") diff --git a/crates/matrix-sdk-crypto/src/types/events/secret_send.rs b/crates/matrix-sdk-crypto/src/types/events/secret_send.rs index 649c9655e3c..9ae69441025 100644 --- a/crates/matrix-sdk-crypto/src/types/events/secret_send.rs +++ b/crates/matrix-sdk-crypto/src/types/events/secret_send.rs @@ -16,7 +16,7 @@ use std::collections::BTreeMap; -use ruma::events::secret::request::SecretName; +use ruma::{events::secret::request::SecretName, OwnedTransactionId}; use serde::{Deserialize, Serialize}; use serde_json::Value; use zeroize::Zeroize; @@ -34,7 +34,7 @@ pub type SecretSendEvent = ToDeviceEvent; #[derive(Serialize, Deserialize)] pub struct SecretSendContent { /// The ID of the request that this a response to. - pub request_id: String, + pub request_id: OwnedTransactionId, /// The contents of the secret. pub secret: String, /// The name of the secret, typically not part of the event but can be @@ -47,6 +47,13 @@ pub struct SecretSendContent { other: BTreeMap, } +impl SecretSendContent { + /// Create a new `m.secret.send` content. + pub fn new(request_id: OwnedTransactionId, secret: String) -> Self { + Self { request_id, secret, secret_name: None, other: Default::default() } + } +} + impl Zeroize for SecretSendContent { fn zeroize(&mut self) { self.secret.zeroize();