diff --git a/matrix_sdk_crypto/src/machine.rs b/matrix_sdk_crypto/src/machine.rs index cb364fd9..27a8f757 100644 --- a/matrix_sdk_crypto/src/machine.rs +++ b/matrix_sdk_crypto/src/machine.rs @@ -32,13 +32,10 @@ use super::{device::Device, store::Result as StoreResult, CryptoStore}; use matrix_sdk_common::api; use matrix_sdk_common::events::{ - forwarded_room_key::ForwardedRoomKeyEventContent, - room::encrypted::{CiphertextInfo, EncryptedEventContent, OlmV1Curve25519AesSha2Content}, - room::message::MessageEventContent, - room_key::RoomKeyEventContent, - room_key_request::RoomKeyRequestEventContent, - Algorithm, AnySyncRoomEvent, AnyToDeviceEvent, EventJson, EventType, SyncMessageEvent, - ToDeviceEvent, + forwarded_room_key::ForwardedRoomKeyEventContent, room::encrypted::EncryptedEventContent, + room::message::MessageEventContent, room_key::RoomKeyEventContent, + room_key_request::RoomKeyRequestEventContent, Algorithm, AnySyncRoomEvent, AnyToDeviceEvent, + EventJson, EventType, SyncMessageEvent, ToDeviceEvent, }; use matrix_sdk_common::identifiers::{DeviceId, RoomId, UserId}; use matrix_sdk_common::uuid::Uuid; @@ -50,7 +47,7 @@ use api::r0::{ to_device::{send_event_to_device::Request as ToDeviceRequest, DeviceIdOrAllDevices}, }; -use serde_json::{json, Value}; +use serde_json::Value; use tracing::{debug, error, info, instrument, trace, warn}; /// A map from the algorithm and device id to a one-time key. @@ -807,52 +804,12 @@ impl OlmMachine { event_type: EventType, content: Value, ) -> OlmResult { - let identity_keys = self.account.identity_keys(); - - // TODO most of this could go into the session, the session already - // stores the curve key of the device, if we also store the ed25519 key - // with the session we'll only need to pass in the account to the - // session and all of this can live in the session. - - let recipient_signing_key = recipient_device - .get_key(KeyAlgorithm::Ed25519) - .ok_or(EventError::MissingSigningKey)?; - let recipient_sender_key = recipient_device - .get_key(KeyAlgorithm::Curve25519) - .ok_or(EventError::MissingSigningKey)?; - - let payload = json!({ - "sender": self.user_id, - "sender_device": self.device_id, - "keys": { - "ed25519": identity_keys.ed25519(), - }, - "recipient": recipient_device.user_id(), - "recipient_keys": { - "ed25519": recipient_signing_key, - }, - "type": event_type, - "content": content, - }); - - let plaintext = cjson::to_string(&payload) - .unwrap_or_else(|_| panic!(format!("Can't serialize {} to canonical JSON", payload))); - - let ciphertext = session.encrypt(&plaintext).await.to_tuple(); - - let message_type: usize = ciphertext.0.into(); - - let ciphertext = CiphertextInfo::new(ciphertext.1, (message_type as u32).into()); - - let mut content = BTreeMap::new(); - - content.insert(recipient_sender_key.to_owned(), ciphertext); - + let message = session + .encrypt(self.account.clone(), recipient_device, event_type, content) + .await; self.store.save_sessions(&[session]).await?; - Ok(EncryptedEventContent::OlmV1Curve25519AesSha2( - OlmV1Curve25519AesSha2Content::new(content, identity_keys.curve25519().to_owned()), - )) + message } /// Should the client share a group session for the given room. diff --git a/matrix_sdk_crypto/src/olm/account.rs b/matrix_sdk_crypto/src/olm/account.rs index 9178e4de..4cff7467 100644 --- a/matrix_sdk_crypto/src/olm/account.rs +++ b/matrix_sdk_crypto/src/olm/account.rs @@ -49,8 +49,8 @@ use super::{InboundGroupSession, OutboundGroupSession, Session}; /// devices. #[derive(Clone)] pub struct Account { - user_id: Arc, - device_id: Arc>, + pub(crate) user_id: Arc, + pub(crate) device_id: Arc>, inner: Arc>, identity_keys: Arc, shared: Arc, diff --git a/matrix_sdk_crypto/src/olm/mod.rs b/matrix_sdk_crypto/src/olm/mod.rs index 39157d87..e6e31c3f 100644 --- a/matrix_sdk_crypto/src/olm/mod.rs +++ b/matrix_sdk_crypto/src/olm/mod.rs @@ -149,7 +149,7 @@ pub(crate) mod test { let plaintext = "Hello world"; - let message = bob_session.encrypt(plaintext).await; + let message = bob_session.encrypt_helper(plaintext).await; let prekey_message = match message.clone() { OlmMessage::PreKey(m) => m, diff --git a/matrix_sdk_crypto/src/olm/session.rs b/matrix_sdk_crypto/src/olm/session.rs index 7438cbf5..fff93eab 100644 --- a/matrix_sdk_crypto/src/olm/session.rs +++ b/matrix_sdk_crypto/src/olm/session.rs @@ -12,22 +12,35 @@ // See the License for the specific language governing permissions and // limitations under the License. -use matrix_sdk_common::instant::Instant; +use std::collections::BTreeMap; use std::fmt; use std::sync::Arc; -use matrix_sdk_common::locks::Mutex; - -pub use olm_rs::account::IdentityKeys; use olm_rs::errors::OlmSessionError; use olm_rs::session::OlmSession; use olm_rs::PicklingMode; +use serde_json::{json, Value}; + pub use olm_rs::{ session::{OlmMessage, PreKeyMessage}, utility::OlmUtility, }; +use super::Account; +use crate::error::{EventError, OlmResult}; +use crate::Device; + +use matrix_sdk_common::{ + api::r0::keys::KeyAlgorithm, + events::{ + room::encrypted::{CiphertextInfo, EncryptedEventContent, OlmV1Curve25519AesSha2Content}, + EventType, + }, + instant::Instant, + locks::Mutex, +}; + /// Cryptographic session that enables secure communication between two /// `Account`s #[derive(Clone)] @@ -71,12 +84,61 @@ impl Session { /// # Arguments /// /// * `plaintext` - The plaintext that should be encrypted. - pub async fn encrypt(&mut self, plaintext: &str) -> OlmMessage { + pub(crate) async fn encrypt_helper(&mut self, plaintext: &str) -> OlmMessage { let message = self.inner.lock().await.encrypt(plaintext); self.last_use_time = Arc::new(Instant::now()); message } + /// Encrypt the given event content content as an m.room.encrypted event + /// content. + pub async fn encrypt( + &mut self, + account: Account, + recipient_device: &Device, + event_type: EventType, + content: Value, + ) -> OlmResult { + let recipient_signing_key = recipient_device + .get_key(KeyAlgorithm::Ed25519) + .ok_or(EventError::MissingSigningKey)?; + let recipient_sender_key = recipient_device + .get_key(KeyAlgorithm::Curve25519) + .ok_or(EventError::MissingSigningKey)?; + + let payload = json!({ + "sender": account.user_id.to_string(), + "sender_device": account.device_id.as_ref(), + "keys": { + "ed25519": account.identity_keys().ed25519(), + }, + "recipient": recipient_device.user_id(), + "recipient_keys": { + "ed25519": recipient_signing_key, + }, + "type": event_type, + "content": content, + }); + + let plaintext = cjson::to_string(&payload) + .unwrap_or_else(|_| panic!(format!("Can't serialize {} to canonical JSON", payload))); + + let ciphertext = self.encrypt_helper(&plaintext).await.to_tuple(); + + let message_type = ciphertext.0; + let ciphertext = CiphertextInfo::new(ciphertext.1, (message_type as u32).into()); + + let mut content = BTreeMap::new(); + content.insert(recipient_sender_key.to_owned(), ciphertext); + + Ok(EncryptedEventContent::OlmV1Curve25519AesSha2( + OlmV1Curve25519AesSha2Content::new( + content, + account.identity_keys().curve25519().to_owned(), + ), + )) + } + /// Check if a pre-key Olm message was encrypted for this session. /// /// Returns true if it matches, false if not and a OlmSessionError if there