diff --git a/matrix_sdk_crypto/src/identities/device.rs b/matrix_sdk_crypto/src/identities/device.rs index 2898f6e0..419ead58 100644 --- a/matrix_sdk_crypto/src/identities/device.rs +++ b/matrix_sdk_crypto/src/identities/device.rs @@ -34,7 +34,7 @@ use serde_json::{json, Value}; use tracing::warn; #[cfg(test)] -use crate::{Account, OlmMachine}; +use crate::{OlmMachine, ReadOnlyAccount}; use crate::{ error::{EventError, OlmError, OlmResult, SignatureError}, @@ -419,7 +419,7 @@ impl ReadOnlyDevice { } #[cfg(test)] - pub async fn from_account(account: &Account) -> ReadOnlyDevice { + pub async fn from_account(account: &ReadOnlyAccount) -> ReadOnlyDevice { let device_keys = account.device_keys().await; ReadOnlyDevice::try_from(&device_keys).unwrap() } diff --git a/matrix_sdk_crypto/src/identities/user.rs b/matrix_sdk_crypto/src/identities/user.rs index 469e83fd..ec9cb4f2 100644 --- a/matrix_sdk_crypto/src/identities/user.rs +++ b/matrix_sdk_crypto/src/identities/user.rs @@ -666,7 +666,7 @@ pub(crate) mod test { manager::test::{other_key_query, own_key_query}, Device, ReadOnlyDevice, }, - olm::Account, + olm::ReadOnlyAccount, store::{MemoryStore, Store}, verification::VerificationMachine, }; @@ -735,7 +735,7 @@ pub(crate) mod test { assert!(identity.is_device_signed(&second).is_ok()); let verification_machine = VerificationMachine::new( - Account::new(second.user_id(), second.device_id()), + ReadOnlyAccount::new(second.user_id(), second.device_id()), Store::new( Arc::new(second.user_id().clone()), Box::new(MemoryStore::new()), diff --git a/matrix_sdk_crypto/src/key_request.rs b/matrix_sdk_crypto/src/key_request.rs index 2d326279..842c6467 100644 --- a/matrix_sdk_crypto/src/key_request.rs +++ b/matrix_sdk_crypto/src/key_request.rs @@ -599,7 +599,7 @@ mod test { use crate::{ identities::{LocalTrust, ReadOnlyDevice}, - olm::Account, + olm::ReadOnlyAccount, store::{MemoryStore, Store}, }; @@ -625,12 +625,12 @@ mod test { room_id!("!test:example.org") } - fn account() -> Account { - Account::new(&alice_id(), &alice_device_id()) + fn account() -> ReadOnlyAccount { + ReadOnlyAccount::new(&alice_id(), &alice_device_id()) } - fn bob_account() -> Account { - Account::new(&bob_id(), &bob_device_id()) + fn bob_account() -> ReadOnlyAccount { + ReadOnlyAccount::new(&bob_id(), &bob_device_id()) } fn bob_machine() -> KeyRequestMachine { diff --git a/matrix_sdk_crypto/src/lib.rs b/matrix_sdk_crypto/src/lib.rs index 456306af..14886910 100644 --- a/matrix_sdk_crypto/src/lib.rs +++ b/matrix_sdk_crypto/src/lib.rs @@ -46,8 +46,8 @@ pub use identities::{ Device, LocalTrust, OwnUserIdentity, ReadOnlyDevice, UserDevices, UserIdentities, UserIdentity, }; pub use machine::OlmMachine; -pub(crate) use olm::Account; pub use olm::EncryptionSettings; +pub(crate) use olm::ReadOnlyAccount; pub use requests::{ IncomingResponse, KeysQueryRequest, OutgoingRequest, OutgoingRequests, ToDeviceRequest, }; diff --git a/matrix_sdk_crypto/src/machine.rs b/matrix_sdk_crypto/src/machine.rs index 47741239..d148b9d2 100644 --- a/matrix_sdk_crypto/src/machine.rs +++ b/matrix_sdk_crypto/src/machine.rs @@ -17,7 +17,6 @@ use std::path::Path; use std::{collections::BTreeMap, convert::TryInto, mem, sync::Arc, time::Duration}; use dashmap::DashMap; -use serde_json::Value; use tracing::{debug, error, info, instrument, trace, warn}; use matrix_sdk_common::{ @@ -52,7 +51,7 @@ use super::{ key_request::KeyRequestMachine, olm::{ Account, EncryptionSettings, ExportedRoomKey, GroupSessionKey, IdentityKeys, - InboundGroupSession, OlmMessage, OutboundGroupSession, + InboundGroupSession, OlmMessage, OutboundGroupSession, ReadOnlyAccount, }, requests::{IncomingResponse, OutgoingRequest, ToDeviceRequest}, store::{CryptoStore, MemoryStore, Result as StoreResult, Store}, @@ -113,7 +112,7 @@ impl OlmMachine { pub fn new(user_id: &UserId, device_id: &DeviceId) -> Self { let store: Box = Box::new(MemoryStore::new()); let device_id: DeviceIdBox = device_id.into(); - let account = Account::new(&user_id, &device_id); + let account = ReadOnlyAccount::new(&user_id, &device_id); OlmMachine::new_helper(user_id, device_id, store, account) } @@ -122,7 +121,7 @@ impl OlmMachine { user_id: &UserId, device_id: DeviceIdBox, store: Box, - account: Account, + account: ReadOnlyAccount, ) -> Self { let user_id = Arc::new(user_id.clone()); @@ -142,7 +141,10 @@ impl OlmMachine { OlmMachine { user_id, device_id, - account, + account: Account { + inner: account, + store: store.clone(), + }, store, outbound_group_sessions, verification_machine, @@ -182,7 +184,7 @@ impl OlmMachine { } None => { debug!("Creating a new account"); - Account::new(&user_id, &device_id) + ReadOnlyAccount::new(&user_id, &device_id) } }; @@ -326,7 +328,7 @@ impl OlmMachine { /// Get the underlying Olm account of the machine. #[cfg(test)] - pub(crate) fn account(&self) -> &Account { + pub(crate) fn account(&self) -> &ReadOnlyAccount { &self.account } @@ -341,26 +343,7 @@ impl OlmMachine { &self, response: &upload_keys::Response, ) -> OlmResult<()> { - if !self.account.shared() { - debug!("Marking account as shared"); - } - self.account.mark_as_shared(); - - let one_time_key_count = response - .one_time_key_counts - .get(&DeviceKeyAlgorithm::SignedCurve25519); - - let count: u64 = one_time_key_count.map_or(0, |c| (*c).into()); - debug!( - "Updated uploaded one-time key count {} -> {}, marking keys as published", - self.account.uploaded_key_count(), - count - ); - self.account.update_uploaded_key_count(count); - self.account.mark_keys_as_published().await; - self.store.save_account(self.account.clone()).await?; - - Ok(()) + self.account.receive_keys_upload_response(response).await } /// Get the a key claiming request for the user/device pairs that we are @@ -518,197 +501,6 @@ impl OlmMachine { Some(assign!(upload_keys::Request::new(), { device_keys, one_time_keys })) } - /// Try to decrypt an Olm message. - /// - /// This try to decrypt an Olm message using all the sessions we share - /// have with the given sender. - async fn try_decrypt_olm_message( - &self, - sender: &UserId, - sender_key: &str, - message: &OlmMessage, - ) -> OlmResult> { - let s = self.store.get_sessions(sender_key).await?; - - // We don't have any existing sessions, return early. - let sessions = if let Some(s) = s { - s - } else { - return Ok(None); - }; - - let mut session_to_save = None; - let mut plaintext = None; - - for session in &mut *sessions.lock().await { - let mut matches = false; - - // If this is a pre-key message check if it was encrypted for our - // session, if it wasn't decryption will fail so no need to try. - if let OlmMessage::PreKey(m) = &message { - matches = session.matches(sender_key, m.clone()).await?; - - if !matches { - continue; - } - } - - let ret = session.decrypt(message.clone()).await; - - if let Ok(p) = ret { - plaintext = Some(p); - session_to_save = Some(session.clone()); - - break; - } else { - // Decryption failed with a matching session, the session is - // likely wedged and needs to be rotated. - if matches { - warn!( - "Found a matching Olm session yet decryption failed - for sender {} and sender_key {}", - sender, sender_key - ); - return Err(OlmError::SessionWedged); - } - } - } - - if let Some(session) = session_to_save { - // Decryption was successful, save the new ratchet state of the - // session that was used to decrypt the message. - trace!("Saved the new session state for {}", sender); - self.store.save_sessions(&[session]).await?; - } - - Ok(plaintext) - } - - /// Decrypt an Olm message, creating a new Olm session if possible. - async fn decrypt_olm_message( - &self, - sender: &UserId, - sender_key: &str, - message: OlmMessage, - ) -> OlmResult<(Raw, String)> { - // First try to decrypt using an existing session. - let plaintext = if let Some(p) = self - .try_decrypt_olm_message(sender, sender_key, &message) - .await? - { - // Decryption succeeded, de-structure the plaintext out of the - // Option. - p - } else { - // Decryption failed with every known session, let's try to create a - // new session. - let mut session = match &message { - // A new session can only be created using a pre-key message, - // return with an error if it isn't one. - OlmMessage::Message(_) => { - warn!( - "Failed to decrypt a non-pre-key message with all - available sessions {} {}", - sender, sender_key - ); - return Err(OlmError::SessionWedged); - } - - OlmMessage::PreKey(m) => { - // Create the new session. - let session = match self - .account - .create_inbound_session(sender_key, m.clone()) - .await - { - Ok(s) => s, - Err(e) => { - warn!( - "Failed to create a new Olm session for {} {} - from a prekey message: {}", - sender, sender_key, e - ); - return Err(OlmError::SessionWedged); - } - }; - - // Save the account since we remove the one-time key that - // was used to create this session. - self.store.save_account(self.account.clone()).await?; - session - } - }; - - // Decrypt our message, this shouldn't fail since we're using a - // newly created Session. - let plaintext = session.decrypt(message).await?; - - // Save the new ratcheted state of the session. - self.store.save_sessions(&[session]).await?; - plaintext - }; - - trace!("Successfully decrypted a Olm message: {}", plaintext); - - self.parse_decrypted_to_device_event(sender, &plaintext) - } - - /// Parse a decrypted Olm message, check that the plaintext and encrypted - /// senders match and that the message was meant for us. - fn parse_decrypted_to_device_event( - &self, - sender: &UserId, - plaintext: &str, - ) -> OlmResult<(Raw, String)> { - // TODO make the errors a bit more specific. - let decrypted_json: Value = serde_json::from_str(&plaintext)?; - - let encrytped_sender = decrypted_json - .get("sender") - .cloned() - .ok_or_else(|| EventError::MissingField("sender".to_string()))?; - let encrytped_sender: UserId = serde_json::from_value(encrytped_sender)?; - let recipient = decrypted_json - .get("recipient") - .cloned() - .ok_or_else(|| EventError::MissingField("recipient".to_string()))?; - let recipient: UserId = serde_json::from_value(recipient)?; - - let recipient_keys: BTreeMap = serde_json::from_value( - decrypted_json - .get("recipient_keys") - .cloned() - .ok_or_else(|| EventError::MissingField("recipient_keys".to_string()))?, - )?; - let keys: BTreeMap = serde_json::from_value( - decrypted_json - .get("keys") - .cloned() - .ok_or_else(|| EventError::MissingField("keys".to_string()))?, - )?; - - if &recipient != self.user_id() || sender != &encrytped_sender { - return Err(EventError::MissmatchedSender.into()); - } - - if self.account.identity_keys().ed25519() - != recipient_keys - .get(&DeviceKeyAlgorithm::Ed25519) - .ok_or(EventError::MissingSigningKey)? - { - return Err(EventError::MissmatchedKeys.into()); - } - - let signing_key = keys - .get(&DeviceKeyAlgorithm::Ed25519) - .ok_or(EventError::MissingSigningKey)?; - - Ok(( - Raw::from(serde_json::from_value::(decrypted_json)?), - signing_key.to_owned(), - )) - } - /// Decrypt a to-device event. /// /// Returns a decrypted `ToDeviceEvent` if the decryption was successful, @@ -748,6 +540,7 @@ impl OlmMachine { // Decrypt the OlmMessage and get a Ruma event out of it. let (decrypted_event, signing_key) = self + .account .decrypt_olm_message(&event.sender, &content.sender_key, message) .await?; @@ -1070,11 +863,7 @@ impl OlmMachine { &self, key_count: &BTreeMap, ) -> StoreResult<()> { - let one_time_key_count = key_count.get(&DeviceKeyAlgorithm::SignedCurve25519); - - let count: u64 = one_time_key_count.map_or(0, |c| (*c).into()); - self.account.update_uploaded_key_count(count); - self.store.save_account(self.account.clone()).await + self.account.update_uploaded_key_count(key_count).await } /// Handle a sync response and update the internal state of the Olm machine. @@ -1496,7 +1285,7 @@ pub(crate) mod test { pub(crate) async fn get_prepared_machine() -> (OlmMachine, OneTimeKeys) { let machine = OlmMachine::new(&user_id(), &alice_device_id()); - machine.account.update_uploaded_key_count(0); + machine.account.inner.update_uploaded_key_count(0); let request = machine .keys_for_upload() .await @@ -1699,7 +1488,7 @@ pub(crate) mod test { #[tokio::test] async fn test_one_time_key_signing() { let machine = OlmMachine::new(&user_id(), &alice_device_id()); - machine.account.update_uploaded_key_count(49); + machine.account.inner.update_uploaded_key_count(49); let mut one_time_keys = machine.account.signed_one_time_keys().await.unwrap(); let identity_keys = machine.account.identity_keys(); @@ -1720,7 +1509,7 @@ pub(crate) mod test { #[tokio::test] async fn test_keys_for_upload() { let machine = OlmMachine::new(&user_id(), &alice_device_id()); - machine.account.update_uploaded_key_count(0); + machine.account.inner.update_uploaded_key_count(0); let identity_keys = machine.account.identity_keys(); let ed25519_key = identity_keys.ed25519(); diff --git a/matrix_sdk_crypto/src/olm/account.rs b/matrix_sdk_crypto/src/olm/account.rs index 3c39da04..23deef9e 100644 --- a/matrix_sdk_crypto/src/olm/account.rs +++ b/matrix_sdk_crypto/src/olm/account.rs @@ -12,51 +12,301 @@ // See the License for the specific language governing permissions and // limitations under the License. -#[cfg(test)] -use matrix_sdk_common::events::{room::encrypted::EncryptedEventContent, EventType}; +use serde::{Deserialize, Serialize}; +use serde_json::{json, Value}; use std::{ collections::BTreeMap, convert::{TryFrom, TryInto}, fmt, + ops::Deref, sync::{ atomic::{AtomicBool, AtomicI64, Ordering}, Arc, }, }; +use tracing::{debug, trace, warn}; +#[cfg(test)] +use matrix_sdk_common::events::{room::encrypted::EncryptedEventContent, EventType}; use matrix_sdk_common::{ - api::r0::keys::{OneTimeKey, SignedKey}, + api::r0::keys::{upload_keys, OneTimeKey, SignedKey}, encryption::DeviceKeys, + events::AnyToDeviceEvent, identifiers::{ DeviceId, DeviceIdBox, DeviceKeyAlgorithm, DeviceKeyId, EventEncryptionAlgorithm, RoomId, UserId, }, instant::Instant, + js_int::UInt, locks::Mutex, + Raw, }; use olm_rs::{ - account::{OlmAccount, OneTimeKeys}, + account::{IdentityKeys, OlmAccount, OneTimeKeys}, errors::{OlmAccountError, OlmSessionError}, + session::{OlmMessage, PreKeyMessage}, PicklingMode, }; -use serde::{Deserialize, Serialize}; -use serde_json::{json, Value}; -pub use olm_rs::{ - account::IdentityKeys, - session::{OlmMessage, PreKeyMessage}, - utility::OlmUtility, +use crate::{ + error::{EventError, OlmResult, SessionCreationError}, + identities::ReadOnlyDevice, + store::{Result as StoreResult, Store}, + OlmError, }; use super::{EncryptionSettings, InboundGroupSession, OutboundGroupSession, Session}; -use crate::{error::SessionCreationError, identities::ReadOnlyDevice}; + +#[derive(Clone)] +pub struct Account { + pub(crate) inner: ReadOnlyAccount, + pub(crate) store: Store, +} + +impl Deref for Account { + type Target = ReadOnlyAccount; + + fn deref(&self) -> &Self::Target { + &self.inner + } +} + +impl Account { + pub async fn update_uploaded_key_count( + &self, + key_count: &BTreeMap, + ) -> StoreResult<()> { + let one_time_key_count = key_count.get(&DeviceKeyAlgorithm::SignedCurve25519); + + let count: u64 = one_time_key_count.map_or(0, |c| (*c).into()); + self.inner.update_uploaded_key_count(count); + self.store.save_account(self.inner.clone()).await + } + + pub async fn receive_keys_upload_response( + &self, + response: &upload_keys::Response, + ) -> OlmResult<()> { + if !self.inner.shared() { + debug!("Marking account as shared"); + } + self.inner.mark_as_shared(); + + let one_time_key_count = response + .one_time_key_counts + .get(&DeviceKeyAlgorithm::SignedCurve25519); + + let count: u64 = one_time_key_count.map_or(0, |c| (*c).into()); + debug!( + "Updated uploaded one-time key count {} -> {}, marking keys as published", + self.inner.uploaded_key_count(), + count + ); + self.inner.update_uploaded_key_count(count); + self.inner.mark_keys_as_published().await; + self.store.save_account(self.inner.clone()).await?; + + Ok(()) + } + + /// Try to decrypt an Olm message. + /// + /// This try to decrypt an Olm message using all the sessions we share + /// have with the given sender. + async fn try_decrypt_olm_message( + &self, + sender: &UserId, + sender_key: &str, + message: &OlmMessage, + ) -> OlmResult> { + let s = self.store.get_sessions(sender_key).await?; + + // We don't have any existing sessions, return early. + let sessions = if let Some(s) = s { + s + } else { + return Ok(None); + }; + + let mut session_to_save = None; + let mut plaintext = None; + + for session in &mut *sessions.lock().await { + let mut matches = false; + + // If this is a pre-key message check if it was encrypted for our + // session, if it wasn't decryption will fail so no need to try. + if let OlmMessage::PreKey(m) = &message { + matches = session.matches(sender_key, m.clone()).await?; + + if !matches { + continue; + } + } + + let ret = session.decrypt(message.clone()).await; + + if let Ok(p) = ret { + plaintext = Some(p); + session_to_save = Some(session.clone()); + + break; + } else { + // Decryption failed with a matching session, the session is + // likely wedged and needs to be rotated. + if matches { + warn!( + "Found a matching Olm session yet decryption failed + for sender {} and sender_key {}", + sender, sender_key + ); + return Err(OlmError::SessionWedged); + } + } + } + + if let Some(session) = session_to_save { + // Decryption was successful, save the new ratchet state of the + // session that was used to decrypt the message. + trace!("Saved the new session state for {}", sender); + self.store.save_sessions(&[session]).await?; + } + + Ok(plaintext) + } + + /// Decrypt an Olm message, creating a new Olm session if possible. + pub async fn decrypt_olm_message( + &self, + sender: &UserId, + sender_key: &str, + message: OlmMessage, + ) -> OlmResult<(Raw, String)> { + // First try to decrypt using an existing session. + let plaintext = if let Some(p) = self + .try_decrypt_olm_message(sender, sender_key, &message) + .await? + { + // Decryption succeeded, de-structure the plaintext out of the + // Option. + p + } else { + // Decryption failed with every known session, let's try to create a + // new session. + let mut session = match &message { + // A new session can only be created using a pre-key message, + // return with an error if it isn't one. + OlmMessage::Message(_) => { + warn!( + "Failed to decrypt a non-pre-key message with all + available sessions {} {}", + sender, sender_key + ); + return Err(OlmError::SessionWedged); + } + + OlmMessage::PreKey(m) => { + // Create the new session. + let session = match self + .inner + .create_inbound_session(sender_key, m.clone()) + .await + { + Ok(s) => s, + Err(e) => { + warn!( + "Failed to create a new Olm session for {} {} + from a prekey message: {}", + sender, sender_key, e + ); + return Err(OlmError::SessionWedged); + } + }; + + // Save the account since we remove the one-time key that + // was used to create this session. + self.store.save_account(self.inner.clone()).await?; + session + } + }; + + // Decrypt our message, this shouldn't fail since we're using a + // newly created Session. + let plaintext = session.decrypt(message).await?; + + // Save the new ratcheted state of the session. + self.store.save_sessions(&[session]).await?; + plaintext + }; + + trace!("Successfully decrypted a Olm message: {}", plaintext); + + self.parse_decrypted_to_device_event(sender, &plaintext) + } + + /// Parse a decrypted Olm message, check that the plaintext and encrypted + /// senders match and that the message was meant for us. + fn parse_decrypted_to_device_event( + &self, + sender: &UserId, + plaintext: &str, + ) -> OlmResult<(Raw, String)> { + // TODO make the errors a bit more specific. + let decrypted_json: Value = serde_json::from_str(&plaintext)?; + + let encrytped_sender = decrypted_json + .get("sender") + .cloned() + .ok_or_else(|| EventError::MissingField("sender".to_string()))?; + let encrytped_sender: UserId = serde_json::from_value(encrytped_sender)?; + let recipient = decrypted_json + .get("recipient") + .cloned() + .ok_or_else(|| EventError::MissingField("recipient".to_string()))?; + let recipient: UserId = serde_json::from_value(recipient)?; + + let recipient_keys: BTreeMap = serde_json::from_value( + decrypted_json + .get("recipient_keys") + .cloned() + .ok_or_else(|| EventError::MissingField("recipient_keys".to_string()))?, + )?; + let keys: BTreeMap = serde_json::from_value( + decrypted_json + .get("keys") + .cloned() + .ok_or_else(|| EventError::MissingField("keys".to_string()))?, + )?; + + if &recipient != self.user_id() || sender != &encrytped_sender { + return Err(EventError::MissmatchedSender.into()); + } + + if self.inner.identity_keys().ed25519() + != recipient_keys + .get(&DeviceKeyAlgorithm::Ed25519) + .ok_or(EventError::MissingSigningKey)? + { + return Err(EventError::MissmatchedKeys.into()); + } + + let signing_key = keys + .get(&DeviceKeyAlgorithm::Ed25519) + .ok_or(EventError::MissingSigningKey)?; + + Ok(( + Raw::from(serde_json::from_value::(decrypted_json)?), + signing_key.to_owned(), + )) + } +} /// Account holding identity keys for which sessions can be created. /// /// An account is the central identity for encrypted communication between two /// devices. #[derive(Clone)] -pub struct Account { +pub struct ReadOnlyAccount { pub(crate) user_id: Arc, pub(crate) device_id: Arc>, inner: Arc>, @@ -106,7 +356,7 @@ pub struct PickledAccount { } #[cfg(not(tarpaulin_include))] -impl fmt::Debug for Account { +impl fmt::Debug for ReadOnlyAccount { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { f.debug_struct("Account") .field("identity_keys", self.identity_keys()) @@ -115,7 +365,7 @@ impl fmt::Debug for Account { } } -impl Account { +impl ReadOnlyAccount { const ALGORITHMS: &'static [&'static EventEncryptionAlgorithm] = &[ &EventEncryptionAlgorithm::OlmV1Curve25519AesSha2, &EventEncryptionAlgorithm::MegolmV1AesSha2, @@ -127,7 +377,7 @@ impl Account { let account = OlmAccount::new(); let identity_keys = account.parsed_identity_keys(); - Account { + Self { user_id: Arc::new(user_id.to_owned()), device_id: Arc::new(device_id.into()), inner: Arc::new(Mutex::new(account)), @@ -307,7 +557,7 @@ impl Account { let account = OlmAccount::unpickle(pickle.pickle.0, pickle_mode)?; let identity_keys = account.parsed_identity_keys(); - Ok(Account { + Ok(Self { user_id: Arc::new(pickle.user_id), device_id: Arc::new(pickle.device_id), inner: Arc::new(Mutex::new(account)), @@ -336,7 +586,7 @@ impl Account { let device_keys = json!({ "user_id": (*self.user_id).clone(), "device_id": (*self.device_id).clone(), - "algorithms": Account::ALGORITHMS, + "algorithms": Self::ALGORITHMS, "keys": keys, }); @@ -621,7 +871,7 @@ impl Account { } #[cfg(test)] - pub(crate) async fn create_session_for(&self, other: &Account) -> (Session, Session) { + pub(crate) async fn create_session_for(&self, other: &ReadOnlyAccount) -> (Session, Session) { other.generate_one_time_keys_helper(1).await; let one_time = other.signed_one_time_keys().await.unwrap(); @@ -676,7 +926,7 @@ impl Account { } } -impl PartialEq for Account { +impl PartialEq for ReadOnlyAccount { fn eq(&self, other: &Self) -> bool { self.identity_keys() == other.identity_keys() && self.shared() == other.shared() } diff --git a/matrix_sdk_crypto/src/olm/group_sessions/mod.rs b/matrix_sdk_crypto/src/olm/group_sessions/mod.rs index a30125d2..74acfbbf 100644 --- a/matrix_sdk_crypto/src/olm/group_sessions/mod.rs +++ b/matrix_sdk_crypto/src/olm/group_sessions/mod.rs @@ -135,7 +135,7 @@ mod test { }; use super::EncryptionSettings; - use crate::Account; + use crate::ReadOnlyAccount; #[tokio::test] #[cfg(not(target_os = "macos"))] @@ -145,7 +145,7 @@ mod test { ..Default::default() }; - let account = Account::new(&user_id!("@alice:example.org"), "DEVICEID".into()); + let account = ReadOnlyAccount::new(&user_id!("@alice:example.org"), "DEVICEID".into()); let (session, _) = account .create_group_session_pair(&room_id!("!test_room:example.org"), settings, [].iter()) .await diff --git a/matrix_sdk_crypto/src/olm/mod.rs b/matrix_sdk_crypto/src/olm/mod.rs index 7a48b9fd..dda23c76 100644 --- a/matrix_sdk_crypto/src/olm/mod.rs +++ b/matrix_sdk_crypto/src/olm/mod.rs @@ -22,20 +22,21 @@ mod group_sessions; mod session; mod utility; -pub use account::{Account, AccountPickle, IdentityKeys, PickledAccount}; +pub(crate) use account::Account; +pub use account::{AccountPickle, PickledAccount, ReadOnlyAccount}; pub use group_sessions::{ EncryptionSettings, ExportedRoomKey, InboundGroupSession, InboundGroupSessionPickle, PickledInboundGroupSession, }; pub(crate) use group_sessions::{GroupSessionKey, OutboundGroupSession}; -pub use olm_rs::PicklingMode; +pub use olm_rs::{account::IdentityKeys, PicklingMode}; pub(crate) use session::OlmMessage; pub use session::{PickledSession, Session, SessionPickle}; pub(crate) use utility::Utility; #[cfg(test)] pub(crate) mod test { - use crate::olm::{Account, InboundGroupSession, Session}; + use crate::olm::{InboundGroupSession, ReadOnlyAccount, Session}; use matrix_sdk_common::{ api::r0::keys::SignedKey, events::forwarded_room_key::ForwardedRoomKeyEventContent, @@ -60,9 +61,9 @@ pub(crate) mod test { "BOBDEVICE".into() } - pub(crate) async fn get_account_and_session() -> (Account, Session) { - let alice = Account::new(&alice_id(), &alice_device_id()); - let bob = Account::new(&bob_id(), &bob_device_id()); + pub(crate) async fn get_account_and_session() -> (ReadOnlyAccount, Session) { + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); + let bob = ReadOnlyAccount::new(&bob_id(), &bob_device_id()); bob.generate_one_time_keys_helper(1).await; let one_time_key = bob @@ -89,7 +90,7 @@ pub(crate) mod test { #[test] fn account_creation() { - let account = Account::new(&alice_id(), &alice_device_id()); + let account = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let identyty_keys = account.identity_keys(); assert!(!account.shared()); @@ -110,7 +111,7 @@ pub(crate) mod test { #[tokio::test] async fn one_time_keys_creation() { - let account = Account::new(&alice_id(), &alice_device_id()); + let account = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let one_time_keys = account.one_time_keys().await; assert!(one_time_keys.curve25519().is_empty()); @@ -137,8 +138,8 @@ pub(crate) mod test { #[tokio::test] async fn session_creation() { - let alice = Account::new(&alice_id(), &alice_device_id()); - let bob = Account::new(&bob_id(), &bob_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); + let bob = ReadOnlyAccount::new(&bob_id(), &bob_device_id()); let alice_keys = alice.identity_keys(); alice.generate_one_time_keys_helper(1).await; let one_time_keys = alice.one_time_keys().await; @@ -190,7 +191,7 @@ pub(crate) mod test { #[tokio::test] async fn group_session_creation() { - let alice = Account::new(&alice_id(), &alice_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let room_id = room_id!("!test:localhost"); let (outbound, _) = alice @@ -226,7 +227,7 @@ pub(crate) mod test { #[tokio::test] async fn group_session_export() { - let alice = Account::new(&alice_id(), &alice_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let room_id = room_id!("!test:localhost"); let (_, inbound) = alice diff --git a/matrix_sdk_crypto/src/store/memorystore.rs b/matrix_sdk_crypto/src/store/memorystore.rs index f8b4bbe6..d7f6a4da 100644 --- a/matrix_sdk_crypto/src/store/memorystore.rs +++ b/matrix_sdk_crypto/src/store/memorystore.rs @@ -23,7 +23,7 @@ use matrix_sdk_common_macros::async_trait; use super::{ caches::{DeviceStore, GroupSessionStore, ReadOnlyUserDevices, SessionStore}, - Account, CryptoStore, InboundGroupSession, Result, Session, + CryptoStore, InboundGroupSession, ReadOnlyAccount, Result, Session, }; use crate::identities::{ReadOnlyDevice, UserIdentities}; @@ -62,11 +62,11 @@ impl MemoryStore { #[async_trait] impl CryptoStore for MemoryStore { - async fn load_account(&self) -> Result> { + async fn load_account(&self) -> Result> { Ok(None) } - async fn save_account(&self, _: Account) -> Result<()> { + async fn save_account(&self, _: ReadOnlyAccount) -> Result<()> { Ok(()) } diff --git a/matrix_sdk_crypto/src/store/mod.rs b/matrix_sdk_crypto/src/store/mod.rs index 1e1d6cc4..6fc04bb4 100644 --- a/matrix_sdk_crypto/src/store/mod.rs +++ b/matrix_sdk_crypto/src/store/mod.rs @@ -72,7 +72,7 @@ use matrix_sdk_common_macros::send_sync; use super::{ identities::{OwnUserIdentity, ReadOnlyDevice, UserIdentities}, - olm::{Account, InboundGroupSession, Session}, + olm::{InboundGroupSession, ReadOnlyAccount, Session}, }; use crate::error::SessionUnpicklingError; @@ -216,14 +216,14 @@ pub enum CryptoStoreError { #[cfg_attr(not(target_arch = "wasm32"), send_sync)] pub trait CryptoStore: Debug { /// Load an account that was previously stored. - async fn load_account(&self) -> Result>; + async fn load_account(&self) -> Result>; /// Save the given account in the store. /// /// # Arguments /// /// * `account` - The account that should be stored. - async fn save_account(&self, account: Account) -> Result<()>; + async fn save_account(&self, account: ReadOnlyAccount) -> Result<()>; /// Save the given sessions in the store. /// diff --git a/matrix_sdk_crypto/src/store/sqlite.rs b/matrix_sdk_crypto/src/store/sqlite.rs index 42fd3550..17c525c2 100644 --- a/matrix_sdk_crypto/src/store/sqlite.rs +++ b/matrix_sdk_crypto/src/store/sqlite.rs @@ -41,9 +41,9 @@ use super::{ use crate::{ identities::{LocalTrust, OwnUserIdentity, ReadOnlyDevice, UserIdentities, UserIdentity}, olm::{ - Account, AccountPickle, IdentityKeys, InboundGroupSession, InboundGroupSessionPickle, - PickledAccount, PickledInboundGroupSession, PickledSession, PicklingMode, Session, - SessionPickle, + AccountPickle, IdentityKeys, InboundGroupSession, InboundGroupSessionPickle, + PickledAccount, PickledInboundGroupSession, PickledSession, PicklingMode, ReadOnlyAccount, + Session, SessionPickle, }, }; @@ -1167,7 +1167,7 @@ impl SqliteStore { #[async_trait] impl CryptoStore for SqliteStore { - async fn load_account(&self) -> Result> { + async fn load_account(&self) -> Result> { let mut connection = self.connection.lock().await; let row: Option<(i64, String, bool, i64)> = query_as( @@ -1188,7 +1188,7 @@ impl CryptoStore for SqliteStore { uploaded_signed_key_count: uploaded_key_count, }; - let account = Account::from_pickle(pickle, self.get_pickle_mode())?; + let account = ReadOnlyAccount::from_pickle(pickle, self.get_pickle_mode())?; *self.account_info.lock().unwrap() = Some(AccountInfo { account_id: id, @@ -1209,7 +1209,7 @@ impl CryptoStore for SqliteStore { Ok(result) } - async fn save_account(&self, account: Account) -> Result<()> { + async fn save_account(&self, account: ReadOnlyAccount) -> Result<()> { let pickle = account.pickle(self.get_pickle_mode()).await; let mut connection = self.connection.lock().await; @@ -1456,7 +1456,7 @@ mod test { device::test::get_device, user::test::{get_other_identity, get_own_identity}, }, - olm::{Account, GroupSessionKey, InboundGroupSession, Session}, + olm::{GroupSessionKey, InboundGroupSession, ReadOnlyAccount, Session}, }; use matrix_sdk_common::{ api::r0::keys::SignedKey, @@ -1506,7 +1506,7 @@ mod test { (store, tmpdir) } - async fn get_loaded_store() -> (Account, SqliteStore, tempfile::TempDir) { + async fn get_loaded_store() -> (ReadOnlyAccount, SqliteStore, tempfile::TempDir) { let (store, dir) = get_store(None).await; let account = get_account(); store @@ -1517,13 +1517,13 @@ mod test { (account, store, dir) } - fn get_account() -> Account { - Account::new(&alice_id(), &alice_device_id()) + fn get_account() -> ReadOnlyAccount { + ReadOnlyAccount::new(&alice_id(), &alice_device_id()) } - async fn get_account_and_session() -> (Account, Session) { - let alice = Account::new(&alice_id(), &alice_device_id()); - let bob = Account::new(&bob_id(), &bob_device_id()); + async fn get_account_and_session() -> (ReadOnlyAccount, Session) { + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); + let bob = ReadOnlyAccount::new(&bob_id(), &bob_device_id()); bob.generate_one_time_keys_helper(1).await; let one_time_key = bob @@ -1870,7 +1870,7 @@ mod test { .await .expect("Can't create store"); - let account = Account::new(&user_id, &device_id); + let account = ReadOnlyAccount::new(&user_id, &device_id); store .save_account(account.clone()) diff --git a/matrix_sdk_crypto/src/verification/machine.rs b/matrix_sdk_crypto/src/verification/machine.rs index 5c727de6..12ca4bc6 100644 --- a/matrix_sdk_crypto/src/verification/machine.rs +++ b/matrix_sdk_crypto/src/verification/machine.rs @@ -28,19 +28,19 @@ use super::sas::{content_to_request, Sas}; use crate::{ requests::{OutgoingRequest, ToDeviceRequest}, store::{CryptoStoreError, Store}, - Account, ReadOnlyDevice, + ReadOnlyAccount, ReadOnlyDevice, }; #[derive(Clone, Debug)] pub struct VerificationMachine { - account: Account, + account: ReadOnlyAccount, pub(crate) store: Store, verifications: Arc>, outgoing_to_device_messages: Arc>, } impl VerificationMachine { - pub(crate) fn new(account: Account, store: Store) -> Self { + pub(crate) fn new(account: ReadOnlyAccount, store: Store) -> Self { Self { account, store, @@ -235,7 +235,7 @@ mod test { requests::OutgoingRequests, store::{CryptoStore, MemoryStore, Store}, verification::test::{get_content_from_request, wrap_any_to_device_content}, - Account, ReadOnlyDevice, + ReadOnlyAccount, ReadOnlyDevice, }; fn alice_id() -> UserId { @@ -255,8 +255,8 @@ mod test { } async fn setup_verification_machine() -> (VerificationMachine, Sas) { - let alice = Account::new(&alice_id(), &alice_device_id()); - let bob = Account::new(&bob_id(), &bob_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); + let bob = ReadOnlyAccount::new(&bob_id(), &bob_device_id()); let store = MemoryStore::new(); let bob_store = Store::new(Arc::new(bob_id()), Box::new(MemoryStore::new())); @@ -285,7 +285,7 @@ mod test { #[test] fn create() { - let alice = Account::new(&alice_id(), &alice_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let user_id = Arc::new(alice_id()); let store = MemoryStore::new(); let _ = VerificationMachine::new(alice, Store::new(user_id, Box::new(store))); diff --git a/matrix_sdk_crypto/src/verification/sas/helpers.rs b/matrix_sdk_crypto/src/verification/sas/helpers.rs index d7abf88d..b58d744a 100644 --- a/matrix_sdk_crypto/src/verification/sas/helpers.rs +++ b/matrix_sdk_crypto/src/verification/sas/helpers.rs @@ -30,12 +30,12 @@ use matrix_sdk_common::{ use crate::{ identities::{ReadOnlyDevice, UserIdentities}, - Account, ToDeviceRequest, + ReadOnlyAccount, ToDeviceRequest, }; #[derive(Clone, Debug)] pub struct SasIds { - pub account: Account, + pub account: ReadOnlyAccount, pub other_device: ReadOnlyDevice, pub other_identity: Option, } diff --git a/matrix_sdk_crypto/src/verification/sas/mod.rs b/matrix_sdk_crypto/src/verification/sas/mod.rs index b79485d9..c52eff3f 100644 --- a/matrix_sdk_crypto/src/verification/sas/mod.rs +++ b/matrix_sdk_crypto/src/verification/sas/mod.rs @@ -35,7 +35,7 @@ use matrix_sdk_common::{ use crate::{ identities::{LocalTrust, ReadOnlyDevice, UserIdentities}, store::{CryptoStoreError, Store}, - Account, ToDeviceRequest, + ReadOnlyAccount, ToDeviceRequest, }; pub use helpers::content_to_request; @@ -48,7 +48,7 @@ use sas_state::{ pub struct Sas { inner: Arc>, store: Store, - account: Account, + account: ReadOnlyAccount, other_device: ReadOnlyDevice, other_identity: Option, flow_id: Arc, @@ -102,7 +102,7 @@ impl Sas { /// Returns the new `Sas` object and a `StartEventContent` that needs to be /// sent out through the server to the other device. pub(crate) fn start( - account: Account, + account: ReadOnlyAccount, other_device: ReadOnlyDevice, store: Store, other_identity: Option, @@ -137,7 +137,7 @@ impl Sas { /// * `event` - The m.key.verification.start event that was sent to us by /// the other side. pub(crate) fn from_start_event( - account: Account, + account: ReadOnlyAccount, other_device: ReadOnlyDevice, store: Store, event: &ToDeviceEvent, @@ -426,7 +426,7 @@ enum InnerSas { impl InnerSas { fn start( - account: Account, + account: ReadOnlyAccount, other_device: ReadOnlyDevice, other_identity: Option, ) -> (InnerSas, StartEventContent) { @@ -436,7 +436,7 @@ impl InnerSas { } fn from_start_event( - account: Account, + account: ReadOnlyAccount, other_device: ReadOnlyDevice, event: &ToDeviceEvent, other_identity: Option, @@ -656,7 +656,7 @@ mod test { use crate::{ store::{MemoryStore, Store}, verification::test::{get_content_from_request, wrap_any_to_device_content}, - Account, ReadOnlyDevice, + ReadOnlyAccount, ReadOnlyDevice, }; use super::{Accepted, Created, Sas, SasState, Started}; @@ -685,10 +685,10 @@ mod test { } async fn get_sas_pair() -> (SasState, SasState) { - let alice = Account::new(&alice_id(), &alice_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let alice_device = ReadOnlyDevice::from_account(&alice).await; - let bob = Account::new(&bob_id(), &bob_device_id()); + let bob = ReadOnlyAccount::new(&bob_id(), &bob_device_id()); let bob_device = ReadOnlyDevice::from_account(&bob).await; let alice_sas = SasState::::new(alice.clone(), bob_device, None); @@ -770,10 +770,10 @@ mod test { #[tokio::test] async fn sas_wrapper_full() { - let alice = Account::new(&alice_id(), &alice_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let alice_device = ReadOnlyDevice::from_account(&alice).await; - let bob = Account::new(&bob_id(), &bob_device_id()); + let bob = ReadOnlyAccount::new(&bob_id(), &bob_device_id()); let bob_device = ReadOnlyDevice::from_account(&bob).await; let alice_store = Store::new(Arc::new(alice_id()), Box::new(MemoryStore::new())); diff --git a/matrix_sdk_crypto/src/verification/sas/sas_state.rs b/matrix_sdk_crypto/src/verification/sas/sas_state.rs index 8d6ede7f..946e03a4 100644 --- a/matrix_sdk_crypto/src/verification/sas/sas_state.rs +++ b/matrix_sdk_crypto/src/verification/sas/sas_state.rs @@ -45,7 +45,7 @@ use super::helpers::{get_decimal, get_emoji, get_mac_content, receive_mac_event, use crate::{ identities::{ReadOnlyDevice, UserIdentities}, - Account, + ReadOnlyAccount, }; const KEY_AGREEMENT_PROTOCOLS: &[KeyAgreementProtocol] = @@ -290,7 +290,7 @@ impl SasState { /// /// * `other_device` - The other device which we are going to verify. pub fn new( - account: Account, + account: ReadOnlyAccount, other_device: ReadOnlyDevice, other_identity: Option, ) -> SasState { @@ -387,7 +387,7 @@ impl SasState { /// * `event` - The m.key.verification.start event that was sent to us by /// the other side. pub fn from_start_event( - account: Account, + account: ReadOnlyAccount, other_device: ReadOnlyDevice, event: &ToDeviceEvent, other_identity: Option, @@ -843,7 +843,7 @@ impl SasState { mod test { use std::convert::TryFrom; - use crate::{Account, ReadOnlyDevice}; + use crate::{ReadOnlyAccount, ReadOnlyDevice}; use matrix_sdk_common::{ events::{ key::verification::{ @@ -881,10 +881,10 @@ mod test { } async fn get_sas_pair() -> (SasState, SasState) { - let alice = Account::new(&alice_id(), &alice_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let alice_device = ReadOnlyDevice::from_account(&alice).await; - let bob = Account::new(&bob_id(), &bob_device_id()); + let bob = ReadOnlyAccount::new(&bob_id(), &bob_device_id()); let bob_device = ReadOnlyDevice::from_account(&bob).await; let alice_sas = SasState::::new(alice.clone(), bob_device, None); @@ -1038,10 +1038,10 @@ mod test { #[tokio::test] async fn sas_from_start_unknown_method() { - let alice = Account::new(&alice_id(), &alice_device_id()); + let alice = ReadOnlyAccount::new(&alice_id(), &alice_device_id()); let alice_device = ReadOnlyDevice::from_account(&alice).await; - let bob = Account::new(&bob_id(), &bob_device_id()); + let bob = ReadOnlyAccount::new(&bob_id(), &bob_device_id()); let bob_device = ReadOnlyDevice::from_account(&bob).await; let alice_sas = SasState::::new(alice.clone(), bob_device, None);