crypto: Split out the Account into a read only portion and one with effects.
This commit is contained in:
parent
e1c220e2f7
commit
84066d4a76
15 changed files with 357 additions and 317 deletions
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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()),
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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<dyn CryptoStore> = 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<dyn CryptoStore>,
|
||||
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<Option<String>> {
|
||||
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<AnyToDeviceEvent>, 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<AnyToDeviceEvent>, 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<DeviceKeyAlgorithm, String> = serde_json::from_value(
|
||||
decrypted_json
|
||||
.get("recipient_keys")
|
||||
.cloned()
|
||||
.ok_or_else(|| EventError::MissingField("recipient_keys".to_string()))?,
|
||||
)?;
|
||||
let keys: BTreeMap<DeviceKeyAlgorithm, String> = 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::<AnyToDeviceEvent>(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<DeviceKeyAlgorithm, UInt>,
|
||||
) -> 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();
|
||||
|
|
|
@ -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<DeviceKeyAlgorithm, UInt>,
|
||||
) -> 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<Option<String>> {
|
||||
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<AnyToDeviceEvent>, 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<AnyToDeviceEvent>, 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<DeviceKeyAlgorithm, String> = serde_json::from_value(
|
||||
decrypted_json
|
||||
.get("recipient_keys")
|
||||
.cloned()
|
||||
.ok_or_else(|| EventError::MissingField("recipient_keys".to_string()))?,
|
||||
)?;
|
||||
let keys: BTreeMap<DeviceKeyAlgorithm, String> = 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::<AnyToDeviceEvent>(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<UserId>,
|
||||
pub(crate) device_id: Arc<Box<DeviceId>>,
|
||||
inner: Arc<Mutex<OlmAccount>>,
|
||||
|
@ -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()
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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<Option<Account>> {
|
||||
async fn load_account(&self) -> Result<Option<ReadOnlyAccount>> {
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
async fn save_account(&self, _: Account) -> Result<()> {
|
||||
async fn save_account(&self, _: ReadOnlyAccount) -> Result<()> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
|
|
|
@ -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<Option<Account>>;
|
||||
async fn load_account(&self) -> Result<Option<ReadOnlyAccount>>;
|
||||
|
||||
/// 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.
|
||||
///
|
||||
|
|
|
@ -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<Option<Account>> {
|
||||
async fn load_account(&self) -> Result<Option<ReadOnlyAccount>> {
|
||||
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())
|
||||
|
|
|
@ -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<DashMap<String, Sas>>,
|
||||
outgoing_to_device_messages: Arc<DashMap<Uuid, OutgoingRequest>>,
|
||||
}
|
||||
|
||||
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)));
|
||||
|
|
|
@ -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<UserIdentities>,
|
||||
}
|
||||
|
|
|
@ -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<Mutex<InnerSas>>,
|
||||
store: Store,
|
||||
account: Account,
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
flow_id: Arc<String>,
|
||||
|
@ -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<UserIdentities>,
|
||||
|
@ -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<StartEventContent>,
|
||||
|
@ -426,7 +426,7 @@ enum InnerSas {
|
|||
|
||||
impl InnerSas {
|
||||
fn start(
|
||||
account: Account,
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> (InnerSas, StartEventContent) {
|
||||
|
@ -436,7 +436,7 @@ impl InnerSas {
|
|||
}
|
||||
|
||||
fn from_start_event(
|
||||
account: Account,
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
event: &ToDeviceEvent<StartEventContent>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
|
@ -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<Created>, SasState<Started>) {
|
||||
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::<Created>::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()));
|
||||
|
|
|
@ -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<Created> {
|
|||
///
|
||||
/// * `other_device` - The other device which we are going to verify.
|
||||
pub fn new(
|
||||
account: Account,
|
||||
account: ReadOnlyAccount,
|
||||
other_device: ReadOnlyDevice,
|
||||
other_identity: Option<UserIdentities>,
|
||||
) -> SasState<Created> {
|
||||
|
@ -387,7 +387,7 @@ impl SasState<Started> {
|
|||
/// * `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<StartEventContent>,
|
||||
other_identity: Option<UserIdentities>,
|
||||
|
@ -843,7 +843,7 @@ impl SasState<Canceled> {
|
|||
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<Created>, SasState<Started>) {
|
||||
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::<Created>::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::<Created>::new(alice.clone(), bob_device, None);
|
||||
|
|
Loading…
Reference in a new issue