crypto: Add methods to request verification from users

master
Damir Jelić 2021-07-08 12:30:30 +02:00
parent db0843a47a
commit c5df7c5356
19 changed files with 455 additions and 222 deletions

View File

@ -39,11 +39,11 @@ use tracing::warn;
use super::{atomic_bool_deserializer, atomic_bool_serializer}; use super::{atomic_bool_deserializer, atomic_bool_serializer};
use crate::{ use crate::{
error::{EventError, OlmError, OlmResult, SignatureError}, error::{EventError, OlmError, OlmResult, SignatureError},
identities::{OwnUserIdentity, UserIdentities}, identities::{ReadOnlyOwnUserIdentity, ReadOnlyUserIdentities},
olm::{InboundGroupSession, PrivateCrossSigningIdentity, Session, Utility}, olm::{InboundGroupSession, PrivateCrossSigningIdentity, Session, Utility},
store::{Changes, CryptoStore, DeviceChanges, Result as StoreResult}, store::{Changes, CryptoStore, DeviceChanges, Result as StoreResult},
verification::VerificationMachine, verification::VerificationMachine,
OutgoingVerificationRequest, Sas, ToDeviceRequest, OutgoingVerificationRequest, Sas, ToDeviceRequest, VerificationRequest,
}; };
#[cfg(test)] #[cfg(test)]
use crate::{OlmMachine, ReadOnlyAccount}; use crate::{OlmMachine, ReadOnlyAccount};
@ -104,8 +104,8 @@ pub struct Device {
pub(crate) inner: ReadOnlyDevice, pub(crate) inner: ReadOnlyDevice,
pub(crate) private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>, pub(crate) private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
pub(crate) verification_machine: VerificationMachine, pub(crate) verification_machine: VerificationMachine,
pub(crate) own_identity: Option<OwnUserIdentity>, pub(crate) own_identity: Option<ReadOnlyOwnUserIdentity>,
pub(crate) device_owner_identity: Option<UserIdentities>, pub(crate) device_owner_identity: Option<ReadOnlyUserIdentities>,
} }
impl std::fmt::Debug for Device { impl std::fmt::Debug for Device {
@ -228,8 +228,8 @@ pub struct UserDevices {
pub(crate) inner: HashMap<DeviceIdBox, ReadOnlyDevice>, pub(crate) inner: HashMap<DeviceIdBox, ReadOnlyDevice>,
pub(crate) private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>, pub(crate) private_identity: Arc<Mutex<PrivateCrossSigningIdentity>>,
pub(crate) verification_machine: VerificationMachine, pub(crate) verification_machine: VerificationMachine,
pub(crate) own_identity: Option<OwnUserIdentity>, pub(crate) own_identity: Option<ReadOnlyOwnUserIdentity>,
pub(crate) device_owner_identity: Option<UserIdentities>, pub(crate) device_owner_identity: Option<ReadOnlyUserIdentities>,
} }
impl UserDevices { impl UserDevices {
@ -382,16 +382,16 @@ impl ReadOnlyDevice {
pub(crate) fn verified( pub(crate) fn verified(
&self, &self,
own_identity: &Option<OwnUserIdentity>, own_identity: &Option<ReadOnlyOwnUserIdentity>,
device_owner: &Option<UserIdentities>, device_owner: &Option<ReadOnlyUserIdentities>,
) -> bool { ) -> bool {
self.is_locally_trusted() || self.is_cross_signing_trusted(own_identity, device_owner) self.is_locally_trusted() || self.is_cross_signing_trusted(own_identity, device_owner)
} }
pub(crate) fn is_cross_signing_trusted( pub(crate) fn is_cross_signing_trusted(
&self, &self,
own_identity: &Option<OwnUserIdentity>, own_identity: &Option<ReadOnlyOwnUserIdentity>,
device_owner: &Option<UserIdentities>, device_owner: &Option<ReadOnlyUserIdentities>,
) -> bool { ) -> bool {
own_identity.as_ref().map_or(false, |own_identity| { own_identity.as_ref().map_or(false, |own_identity| {
// Our own identity needs to be marked as verified. // Our own identity needs to be marked as verified.
@ -401,14 +401,14 @@ impl ReadOnlyDevice {
.map(|device_identity| match device_identity { .map(|device_identity| match device_identity {
// If it's one of our own devices, just check that // If it's one of our own devices, just check that
// we signed the device. // we signed the device.
UserIdentities::Own(_) => { ReadOnlyUserIdentities::Own(_) => {
own_identity.is_device_signed(self).map_or(false, |_| true) own_identity.is_device_signed(self).map_or(false, |_| true)
} }
// If it's a device from someone else, first check // If it's a device from someone else, first check
// that our user has signed the other user and then // that our user has signed the other user and then
// check if the other user has signed this device. // check if the other user has signed this device.
UserIdentities::Other(device_identity) => { ReadOnlyUserIdentities::Other(device_identity) => {
own_identity.is_identity_signed(device_identity).map_or(false, |_| true) own_identity.is_identity_signed(device_identity).map_or(false, |_| true)
&& device_identity.is_device_signed(self).map_or(false, |_| true) && device_identity.is_device_signed(self).map_or(false, |_| true)
} }

View File

@ -29,8 +29,8 @@ use tracing::{trace, warn};
use crate::{ use crate::{
error::OlmResult, error::OlmResult,
identities::{ identities::{
MasterPubkey, OwnUserIdentity, ReadOnlyDevice, SelfSigningPubkey, UserIdentities, MasterPubkey, ReadOnlyDevice, ReadOnlyOwnUserIdentity, ReadOnlyUserIdentities,
UserIdentity, UserSigningPubkey, ReadOnlyUserIdentity, SelfSigningPubkey, UserSigningPubkey,
}, },
requests::KeysQueryRequest, requests::KeysQueryRequest,
store::{Changes, DeviceChanges, IdentityChanges, Result as StoreResult, Store}, store::{Changes, DeviceChanges, IdentityChanges, Result as StoreResult, Store},
@ -246,7 +246,7 @@ impl IdentityManager {
let result = if let Some(mut i) = self.store.get_user_identity(user_id).await? { let result = if let Some(mut i) = self.store.get_user_identity(user_id).await? {
match &mut i { match &mut i {
UserIdentities::Own(ref mut identity) => { ReadOnlyUserIdentities::Own(ref mut identity) => {
let user_signing = if let Some(s) = response.user_signing_keys.get(user_id) let user_signing = if let Some(s) = response.user_signing_keys.get(user_id)
{ {
UserSigningPubkey::from(s) UserSigningPubkey::from(s)
@ -261,7 +261,7 @@ impl IdentityManager {
identity.update(master_key, self_signing, user_signing).map(|_| (i, false)) identity.update(master_key, self_signing, user_signing).map(|_| (i, false))
} }
UserIdentities::Other(ref mut identity) => { ReadOnlyUserIdentities::Other(ref mut identity) => {
identity.update(master_key, self_signing).map(|_| (i, false)) identity.update(master_key, self_signing).map(|_| (i, false))
} }
} }
@ -280,8 +280,8 @@ impl IdentityManager {
continue; continue;
} }
OwnUserIdentity::new(master_key, self_signing, user_signing) ReadOnlyOwnUserIdentity::new(master_key, self_signing, user_signing)
.map(|i| (UserIdentities::Own(i), true)) .map(|i| (ReadOnlyUserIdentities::Own(i), true))
} else { } else {
warn!( warn!(
"User identity for our own user {} didn't contain a \ "User identity for our own user {} didn't contain a \
@ -294,8 +294,8 @@ impl IdentityManager {
warn!("User id mismatch in one of the cross signing keys for user {}", user_id); warn!("User id mismatch in one of the cross signing keys for user {}", user_id);
continue; continue;
} else { } else {
UserIdentity::new(master_key, self_signing) ReadOnlyUserIdentity::new(master_key, self_signing)
.map(|i| (UserIdentities::Other(i), true)) .map(|i| (ReadOnlyUserIdentities::Other(i), true))
}; };
match result { match result {

View File

@ -53,8 +53,8 @@ pub use device::{Device, LocalTrust, ReadOnlyDevice, UserDevices};
pub(crate) use manager::IdentityManager; pub(crate) use manager::IdentityManager;
use serde::{Deserialize, Deserializer, Serializer}; use serde::{Deserialize, Deserializer, Serializer};
pub use user::{ pub use user::{
MasterPubkey, OwnUserIdentity, SelfSigningPubkey, UserIdentities, UserIdentity, MasterPubkey, OwnUserIdentity, ReadOnlyOwnUserIdentity, ReadOnlyUserIdentities,
UserSigningPubkey, ReadOnlyUserIdentity, SelfSigningPubkey, UserIdentities, UserIdentity, UserSigningPubkey,
}; };
// These methods are only here because Serialize and Deserialize don't seem to // These methods are only here because Serialize and Deserialize don't seem to

View File

@ -15,6 +15,7 @@
use std::{ use std::{
collections::{btree_map::Iter, BTreeMap}, collections::{btree_map::Iter, BTreeMap},
convert::TryFrom, convert::TryFrom,
ops::Deref,
sync::{ sync::{
atomic::{AtomicBool, Ordering}, atomic::{AtomicBool, Ordering},
Arc, Arc,
@ -23,7 +24,10 @@ use std::{
use ruma::{ use ruma::{
encryption::{CrossSigningKey, KeyUsage}, encryption::{CrossSigningKey, KeyUsage},
DeviceKeyId, UserId, events::{
key::verification::VerificationMethod, room::message::KeyVerificationRequestEventContent,
},
DeviceKeyId, EventId, RoomId, UserId,
}; };
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use serde_json::to_value; use serde_json::to_value;
@ -31,7 +35,153 @@ use serde_json::to_value;
use super::{atomic_bool_deserializer, atomic_bool_serializer}; use super::{atomic_bool_deserializer, atomic_bool_serializer};
#[cfg(test)] #[cfg(test)]
use crate::olm::PrivateCrossSigningIdentity; use crate::olm::PrivateCrossSigningIdentity;
use crate::{error::SignatureError, olm::Utility, ReadOnlyDevice}; use crate::{
error::SignatureError, olm::Utility, verification::VerificationMachine, CryptoStoreError,
OutgoingVerificationRequest, ReadOnlyDevice, VerificationRequest,
};
/// Enum over the different user identity types we can have.
#[derive(Debug, Clone)]
pub enum UserIdentities {
/// Our own user identity.
Own(OwnUserIdentity),
/// An identity belonging to another user.
Other(UserIdentity),
}
impl UserIdentities {
/// Destructure the enum into an `OwnUserIdentity` if it's of the correct
/// type.
pub fn own(self) -> Option<OwnUserIdentity> {
match self {
Self::Own(i) => Some(i),
_ => None,
}
}
/// Destructure the enum into an `UserIdentity` if it's of the correct
/// type.
pub fn other(self) -> Option<UserIdentity> {
match self {
Self::Other(i) => Some(i),
_ => None,
}
}
}
impl From<OwnUserIdentity> for UserIdentities {
fn from(i: OwnUserIdentity) -> Self {
Self::Own(i)
}
}
impl From<UserIdentity> for UserIdentities {
fn from(i: UserIdentity) -> Self {
Self::Other(i)
}
}
/// Struct representing a cross signing identity of a user.
///
/// This is the user identity of a user that isn't our own. Other users will
/// only contain a master key and a self signing key, meaning that only device
/// signatures can be checked with this identity.
///
/// This struct wraps a read-only version of the struct and allows verifications
/// to be requested to verify our own device with the user identity.
#[derive(Debug, Clone)]
pub struct OwnUserIdentity {
pub(crate) inner: ReadOnlyOwnUserIdentity,
pub(crate) verification_machine: VerificationMachine,
}
impl Deref for OwnUserIdentity {
type Target = ReadOnlyOwnUserIdentity;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl OwnUserIdentity {
/// Send a verification request to our other devices.
pub async fn request_verification(
&self,
) -> Result<(VerificationRequest, OutgoingVerificationRequest), CryptoStoreError> {
self.verification_machine.request_self_verification(&self.inner, None).await
}
/// Send a verification request to our other devices while specifying our
/// supported methods.
///
/// # Arguments
///
/// * `methods` - The verification methods that we're supporting.
pub async fn request_verification_with_methods(
&self,
methods: Vec<VerificationMethod>,
) -> Result<(VerificationRequest, OutgoingVerificationRequest), CryptoStoreError> {
self.verification_machine.request_self_verification(&self.inner, Some(methods)).await
}
}
/// Struct representing a cross signing identity of a user.
///
/// This is the user identity of a user that isn't our own. Other users will
/// only contain a master key and a self signing key, meaning that only device
/// signatures can be checked with this identity.
///
/// This struct wraps a read-only version of the struct and allows verifications
/// to be requested to verify our own device with the user identity.
#[derive(Debug, Clone)]
pub struct UserIdentity {
pub(crate) inner: ReadOnlyUserIdentity,
pub(crate) verification_machine: VerificationMachine,
}
impl Deref for UserIdentity {
type Target = ReadOnlyUserIdentity;
fn deref(&self) -> &Self::Target {
&self.inner
}
}
impl UserIdentity {
/// Create a `VerificationRequest` object after the verification request
/// content has been sent out.
pub async fn request_verification(
&self,
room_id: &RoomId,
request_event_id: &EventId,
methods: Option<Vec<VerificationMethod>>,
) -> VerificationRequest {
self.verification_machine
.request_verification(&self.inner, room_id, request_event_id, methods)
.await
}
/// Send a verification request to the given user.
///
/// The returned content needs to be sent out into a DM room with the given
/// user.
///
/// After the content has been sent out a `VerificationRequest` can be
/// started with the [`request_verification`] method.
///
/// [`request_verification()`]: #method.request_verification
pub async fn verification_request_content(
&self,
methods: Option<Vec<VerificationMethod>>,
) -> KeyVerificationRequestEventContent {
VerificationRequest::request(
self.verification_machine.own_user_id(),
self.verification_machine.own_device_id(),
self.user_id(),
methods,
)
}
}
/// Wrapper for a cross signing key marking it as the master key. /// Wrapper for a cross signing key marking it as the master key.
/// ///
@ -358,47 +508,47 @@ impl<'a> IntoIterator for &'a SelfSigningPubkey {
/// Enum over the different user identity types we can have. /// Enum over the different user identity types we can have.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub enum UserIdentities { pub enum ReadOnlyUserIdentities {
/// Our own user identity. /// Our own user identity.
Own(OwnUserIdentity), Own(ReadOnlyOwnUserIdentity),
/// Identities of other users. /// Identities of other users.
Other(UserIdentity), Other(ReadOnlyUserIdentity),
} }
impl From<OwnUserIdentity> for UserIdentities { impl From<ReadOnlyOwnUserIdentity> for ReadOnlyUserIdentities {
fn from(identity: OwnUserIdentity) -> Self { fn from(identity: ReadOnlyOwnUserIdentity) -> Self {
UserIdentities::Own(identity) ReadOnlyUserIdentities::Own(identity)
} }
} }
impl From<UserIdentity> for UserIdentities { impl From<ReadOnlyUserIdentity> for ReadOnlyUserIdentities {
fn from(identity: UserIdentity) -> Self { fn from(identity: ReadOnlyUserIdentity) -> Self {
UserIdentities::Other(identity) ReadOnlyUserIdentities::Other(identity)
} }
} }
impl UserIdentities { impl ReadOnlyUserIdentities {
/// The unique user id of this identity. /// The unique user id of this identity.
pub fn user_id(&self) -> &UserId { pub fn user_id(&self) -> &UserId {
match self { match self {
UserIdentities::Own(i) => i.user_id(), ReadOnlyUserIdentities::Own(i) => i.user_id(),
UserIdentities::Other(i) => i.user_id(), ReadOnlyUserIdentities::Other(i) => i.user_id(),
} }
} }
/// Get the master key of the identity. /// Get the master key of the identity.
pub fn master_key(&self) -> &MasterPubkey { pub fn master_key(&self) -> &MasterPubkey {
match self { match self {
UserIdentities::Own(i) => i.master_key(), ReadOnlyUserIdentities::Own(i) => i.master_key(),
UserIdentities::Other(i) => i.master_key(), ReadOnlyUserIdentities::Other(i) => i.master_key(),
} }
} }
/// Get the self-signing key of the identity. /// Get the self-signing key of the identity.
pub fn self_signing_key(&self) -> &SelfSigningPubkey { pub fn self_signing_key(&self) -> &SelfSigningPubkey {
match self { match self {
UserIdentities::Own(i) => &i.self_signing_key, ReadOnlyUserIdentities::Own(i) => &i.self_signing_key,
UserIdentities::Other(i) => &i.self_signing_key, ReadOnlyUserIdentities::Other(i) => &i.self_signing_key,
} }
} }
@ -406,32 +556,32 @@ impl UserIdentities {
/// own user identity.. /// own user identity..
pub fn user_signing_key(&self) -> Option<&UserSigningPubkey> { pub fn user_signing_key(&self) -> Option<&UserSigningPubkey> {
match self { match self {
UserIdentities::Own(i) => Some(&i.user_signing_key), ReadOnlyUserIdentities::Own(i) => Some(&i.user_signing_key),
UserIdentities::Other(_) => None, ReadOnlyUserIdentities::Other(_) => None,
} }
} }
/// Destructure the enum into an `OwnUserIdentity` if it's of the correct /// Destructure the enum into an `ReadOnlyOwnUserIdentity` if it's of the
/// type. /// correct type.
pub fn own(&self) -> Option<&OwnUserIdentity> { pub fn own(&self) -> Option<&ReadOnlyOwnUserIdentity> {
match self { match self {
UserIdentities::Own(i) => Some(i), ReadOnlyUserIdentities::Own(i) => Some(i),
_ => None, _ => None,
} }
} }
/// Destructure the enum into an `UserIdentity` if it's of the correct /// Destructure the enum into an `UserIdentity` if it's of the correct
/// type. /// type.
pub fn other(&self) -> Option<&UserIdentity> { pub fn other(&self) -> Option<&ReadOnlyUserIdentity> {
match self { match self {
UserIdentities::Other(i) => Some(i), ReadOnlyUserIdentities::Other(i) => Some(i),
_ => None, _ => None,
} }
} }
} }
impl PartialEq for UserIdentities { impl PartialEq for ReadOnlyUserIdentities {
fn eq(&self, other: &UserIdentities) -> bool { fn eq(&self, other: &ReadOnlyUserIdentities) -> bool {
self.user_id() == other.user_id() self.user_id() == other.user_id()
} }
} }
@ -442,13 +592,13 @@ impl PartialEq for UserIdentities {
/// only contain a master key and a self signing key, meaning that only device /// only contain a master key and a self signing key, meaning that only device
/// signatures can be checked with this identity. /// signatures can be checked with this identity.
#[derive(Debug, Clone, Deserialize, Serialize)] #[derive(Debug, Clone, Deserialize, Serialize)]
pub struct UserIdentity { pub struct ReadOnlyUserIdentity {
user_id: Arc<UserId>, user_id: Arc<UserId>,
pub(crate) master_key: MasterPubkey, pub(crate) master_key: MasterPubkey,
self_signing_key: SelfSigningPubkey, self_signing_key: SelfSigningPubkey,
} }
impl UserIdentity { impl ReadOnlyUserIdentity {
/// Create a new user identity with the given master and self signing key. /// Create a new user identity with the given master and self signing key.
/// ///
/// # Arguments /// # Arguments
@ -543,7 +693,7 @@ impl UserIdentity {
/// This identity can verify other identities as well as devices belonging to /// This identity can verify other identities as well as devices belonging to
/// the identity. /// the identity.
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize)]
pub struct OwnUserIdentity { pub struct ReadOnlyOwnUserIdentity {
user_id: Arc<UserId>, user_id: Arc<UserId>,
master_key: MasterPubkey, master_key: MasterPubkey,
self_signing_key: SelfSigningPubkey, self_signing_key: SelfSigningPubkey,
@ -555,7 +705,7 @@ pub struct OwnUserIdentity {
verified: Arc<AtomicBool>, verified: Arc<AtomicBool>,
} }
impl OwnUserIdentity { impl ReadOnlyOwnUserIdentity {
/// Create a new own user identity with the given master, self signing, and /// Create a new own user identity with the given master, self signing, and
/// user signing key. /// user signing key.
/// ///
@ -615,7 +765,10 @@ impl OwnUserIdentity {
/// ///
/// Returns an empty result if the signature check succeeded, otherwise a /// Returns an empty result if the signature check succeeded, otherwise a
/// SignatureError indicating why the check failed. /// SignatureError indicating why the check failed.
pub fn is_identity_signed(&self, identity: &UserIdentity) -> Result<(), SignatureError> { pub fn is_identity_signed(
&self,
identity: &ReadOnlyUserIdentity,
) -> Result<(), SignatureError> {
self.user_signing_key.verify_master_key(&identity.master_key) self.user_signing_key.verify_master_key(&identity.master_key)
} }
@ -692,7 +845,7 @@ pub(crate) mod test {
use matrix_sdk_test::async_test; use matrix_sdk_test::async_test;
use ruma::{api::client::r0::keys::get_keys::Response as KeyQueryResponse, user_id}; use ruma::{api::client::r0::keys::get_keys::Response as KeyQueryResponse, user_id};
use super::{OwnUserIdentity, UserIdentities, UserIdentity}; use super::{ReadOnlyOwnUserIdentity, ReadOnlyUserIdentities, ReadOnlyUserIdentity};
use crate::{ use crate::{
identities::{ identities::{
manager::test::{other_key_query, own_key_query}, manager::test::{other_key_query, own_key_query},
@ -710,28 +863,29 @@ pub(crate) mod test {
(first, second) (first, second)
} }
fn own_identity(response: &KeyQueryResponse) -> OwnUserIdentity { fn own_identity(response: &KeyQueryResponse) -> ReadOnlyOwnUserIdentity {
let user_id = user_id!("@example:localhost"); let user_id = user_id!("@example:localhost");
let master_key = response.master_keys.get(&user_id).unwrap(); let master_key = response.master_keys.get(&user_id).unwrap();
let user_signing = response.user_signing_keys.get(&user_id).unwrap(); let user_signing = response.user_signing_keys.get(&user_id).unwrap();
let self_signing = response.self_signing_keys.get(&user_id).unwrap(); let self_signing = response.self_signing_keys.get(&user_id).unwrap();
OwnUserIdentity::new(master_key.into(), self_signing.into(), user_signing.into()).unwrap() ReadOnlyOwnUserIdentity::new(master_key.into(), self_signing.into(), user_signing.into())
.unwrap()
} }
pub(crate) fn get_own_identity() -> OwnUserIdentity { pub(crate) fn get_own_identity() -> ReadOnlyOwnUserIdentity {
own_identity(&own_key_query()) own_identity(&own_key_query())
} }
pub(crate) fn get_other_identity() -> UserIdentity { pub(crate) fn get_other_identity() -> ReadOnlyUserIdentity {
let user_id = user_id!("@example2:localhost"); let user_id = user_id!("@example2:localhost");
let response = other_key_query(); let response = other_key_query();
let master_key = response.master_keys.get(&user_id).unwrap(); let master_key = response.master_keys.get(&user_id).unwrap();
let self_signing = response.self_signing_keys.get(&user_id).unwrap(); let self_signing = response.self_signing_keys.get(&user_id).unwrap();
UserIdentity::new(master_key.into(), self_signing.into()).unwrap() ReadOnlyUserIdentity::new(master_key.into(), self_signing.into()).unwrap()
} }
#[test] #[test]
@ -743,7 +897,8 @@ pub(crate) mod test {
let user_signing = response.user_signing_keys.get(&user_id).unwrap(); let user_signing = response.user_signing_keys.get(&user_id).unwrap();
let self_signing = response.self_signing_keys.get(&user_id).unwrap(); let self_signing = response.self_signing_keys.get(&user_id).unwrap();
OwnUserIdentity::new(master_key.into(), self_signing.into(), user_signing.into()).unwrap(); ReadOnlyOwnUserIdentity::new(master_key.into(), self_signing.into(), user_signing.into())
.unwrap();
} }
#[test] #[test]
@ -773,7 +928,7 @@ pub(crate) mod test {
verification_machine: verification_machine.clone(), verification_machine: verification_machine.clone(),
private_identity: private_identity.clone(), private_identity: private_identity.clone(),
own_identity: Some(identity.clone()), own_identity: Some(identity.clone()),
device_owner_identity: Some(UserIdentities::Own(identity.clone())), device_owner_identity: Some(ReadOnlyUserIdentities::Own(identity.clone())),
}; };
let second = Device { let second = Device {
@ -781,7 +936,7 @@ pub(crate) mod test {
verification_machine, verification_machine,
private_identity, private_identity,
own_identity: Some(identity.clone()), own_identity: Some(identity.clone()),
device_owner_identity: Some(UserIdentities::Own(identity.clone())), device_owner_identity: Some(ReadOnlyUserIdentities::Own(identity.clone())),
}; };
assert!(!second.is_locally_trusted()); assert!(!second.is_locally_trusted());

View File

@ -45,7 +45,8 @@ pub use file_encryption::{
DecryptorError, EncryptionInfo, KeyExportError, DecryptorError, EncryptionInfo, KeyExportError,
}; };
pub use identities::{ pub use identities::{
Device, LocalTrust, OwnUserIdentity, ReadOnlyDevice, UserDevices, UserIdentities, UserIdentity, Device, LocalTrust, OwnUserIdentity, ReadOnlyDevice, ReadOnlyOwnUserIdentity,
ReadOnlyUserIdentities, ReadOnlyUserIdentity, UserDevices, UserIdentities, UserIdentity,
}; };
pub use machine::OlmMachine; pub use machine::OlmMachine;
pub use matrix_qrcode; pub use matrix_qrcode;

View File

@ -46,7 +46,7 @@ use tracing::{debug, error, info, trace, warn};
use crate::store::sled::SledStore; use crate::store::sled::SledStore;
use crate::{ use crate::{
error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult}, error::{EventError, MegolmError, MegolmResult, OlmError, OlmResult},
identities::{Device, IdentityManager, UserDevices}, identities::{user::UserIdentities, Device, IdentityManager, UserDevices},
key_request::KeyRequestMachine, key_request::KeyRequestMachine,
olm::{ olm::{
Account, EncryptionSettings, ExportedRoomKey, GroupSessionKey, IdentityKeys, Account, EncryptionSettings, ExportedRoomKey, GroupSessionKey, IdentityKeys,
@ -1052,6 +1052,18 @@ impl OlmMachine {
self.store.get_device(user_id, device_id).await self.store.get_device(user_id, device_id).await
} }
/// Get the cross signing user identity of a user.
///
/// # Arguments
///
/// * `user_id` - The unique id of the user that the identity belongs to
///
/// Returns a `UserIdentities` enum if one is found and the crypto store
/// didn't throw an error.
pub async fn get_identity(&self, user_id: &UserId) -> StoreResult<Option<UserIdentities>> {
self.store.get_identity(user_id).await
}
/// Get a map holding all the devices of an user. /// Get a map holding all the devices of an user.
/// ///
/// # Arguments /// # Arguments

View File

@ -34,7 +34,7 @@ use serde_json::Error as JsonError;
use crate::{ use crate::{
error::SignatureError, identities::MasterPubkey, requests::UploadSigningKeysRequest, error::SignatureError, identities::MasterPubkey, requests::UploadSigningKeysRequest,
OwnUserIdentity, ReadOnlyAccount, ReadOnlyDevice, UserIdentity, ReadOnlyAccount, ReadOnlyDevice, ReadOnlyOwnUserIdentity, ReadOnlyUserIdentity,
}; };
/// Private cross signing identity. /// Private cross signing identity.
@ -117,7 +117,9 @@ impl PrivateCrossSigningIdentity {
} }
} }
pub(crate) async fn to_public_identity(&self) -> Result<OwnUserIdentity, SignatureError> { pub(crate) async fn to_public_identity(
&self,
) -> Result<ReadOnlyOwnUserIdentity, SignatureError> {
let master = self let master = self
.master_key .master_key
.lock() .lock()
@ -142,7 +144,7 @@ impl PrivateCrossSigningIdentity {
.ok_or(SignatureError::MissingSigningKey)? .ok_or(SignatureError::MissingSigningKey)?
.public_key .public_key
.clone(); .clone();
let identity = OwnUserIdentity::new(master, self_signing, user_signing)?; let identity = ReadOnlyOwnUserIdentity::new(master, self_signing, user_signing)?;
identity.mark_as_verified(); identity.mark_as_verified();
Ok(identity) Ok(identity)
@ -151,7 +153,7 @@ impl PrivateCrossSigningIdentity {
/// Sign the given public user identity with this private identity. /// Sign the given public user identity with this private identity.
pub(crate) async fn sign_user( pub(crate) async fn sign_user(
&self, &self,
user_identity: &UserIdentity, user_identity: &ReadOnlyUserIdentity,
) -> Result<SignatureUploadRequest, SignatureError> { ) -> Result<SignatureUploadRequest, SignatureError> {
let signed_keys = self let signed_keys = self
.user_signing_key .user_signing_key
@ -407,7 +409,7 @@ mod test {
use super::{PrivateCrossSigningIdentity, Signing}; use super::{PrivateCrossSigningIdentity, Signing};
use crate::{ use crate::{
identities::{ReadOnlyDevice, UserIdentity}, identities::{ReadOnlyDevice, ReadOnlyUserIdentity},
olm::ReadOnlyAccount, olm::ReadOnlyAccount,
}; };
@ -518,7 +520,7 @@ mod test {
let bob_account = ReadOnlyAccount::new(&user_id!("@bob:localhost"), "DEVICEID".into()); let bob_account = ReadOnlyAccount::new(&user_id!("@bob:localhost"), "DEVICEID".into());
let (bob_private, _, _) = PrivateCrossSigningIdentity::new_with_account(&bob_account).await; let (bob_private, _, _) = PrivateCrossSigningIdentity::new_with_account(&bob_account).await;
let mut bob_public = UserIdentity::from_private(&bob_private).await; let mut bob_public = ReadOnlyUserIdentity::from_private(&bob_private).await;
let user_signing = identity.user_signing_key.lock().await; let user_signing = identity.user_signing_key.lock().await;
let user_signing = user_signing.as_ref().unwrap(); let user_signing = user_signing.as_ref().unwrap();

View File

@ -37,7 +37,7 @@ use crate::{
error::SignatureError, error::SignatureError,
identities::{MasterPubkey, SelfSigningPubkey, UserSigningPubkey}, identities::{MasterPubkey, SelfSigningPubkey, UserSigningPubkey},
utilities::{decode_url_safe as decode, encode_url_safe as encode, DecodeError}, utilities::{decode_url_safe as decode, encode_url_safe as encode, DecodeError},
UserIdentity, ReadOnlyUserIdentity,
}; };
const NONCE_SIZE: usize = 12; const NONCE_SIZE: usize = 12;
@ -186,7 +186,7 @@ impl UserSigning {
pub async fn sign_user( pub async fn sign_user(
&self, &self,
user: &UserIdentity, user: &ReadOnlyUserIdentity,
) -> Result<BTreeMap<UserId, BTreeMap<String, Value>>, SignatureError> { ) -> Result<BTreeMap<UserId, BTreeMap<String, Value>>, SignatureError> {
let user_master: &CrossSigningKey = user.master_key().as_ref(); let user_master: &CrossSigningKey = user.master_key().as_ref();
let signature = self.inner.sign_json(serde_json::to_value(user_master)?).await?; let signature = self.inner.sign_json(serde_json::to_value(user_master)?).await?;

View File

@ -26,7 +26,7 @@ use super::{
Changes, CryptoStore, InboundGroupSession, ReadOnlyAccount, Result, Session, Changes, CryptoStore, InboundGroupSession, ReadOnlyAccount, Result, Session,
}; };
use crate::{ use crate::{
identities::{ReadOnlyDevice, UserIdentities}, identities::{ReadOnlyDevice, ReadOnlyUserIdentities},
key_request::OutgoingKeyRequest, key_request::OutgoingKeyRequest,
olm::{OutboundGroupSession, PrivateCrossSigningIdentity}, olm::{OutboundGroupSession, PrivateCrossSigningIdentity},
}; };
@ -44,7 +44,7 @@ pub struct MemoryStore {
users_for_key_query: Arc<DashSet<UserId>>, users_for_key_query: Arc<DashSet<UserId>>,
olm_hashes: Arc<DashMap<String, DashSet<String>>>, olm_hashes: Arc<DashMap<String, DashSet<String>>>,
devices: DeviceStore, devices: DeviceStore,
identities: Arc<DashMap<UserId, UserIdentities>>, identities: Arc<DashMap<UserId, ReadOnlyUserIdentities>>,
outgoing_key_requests: Arc<DashMap<Uuid, OutgoingKeyRequest>>, outgoing_key_requests: Arc<DashMap<Uuid, OutgoingKeyRequest>>,
key_requests_by_info: Arc<DashMap<String, Uuid>>, key_requests_by_info: Arc<DashMap<String, Uuid>>,
} }
@ -215,7 +215,7 @@ impl CryptoStore for MemoryStore {
Ok(self.devices.user_devices(user_id)) Ok(self.devices.user_devices(user_id))
} }
async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentities>> { async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<ReadOnlyUserIdentities>> {
#[allow(clippy::map_clone)] #[allow(clippy::map_clone)]
Ok(self.identities.get(user_id).map(|i| i.clone())) Ok(self.identities.get(user_id).map(|i| i.clone()))
} }

View File

@ -66,7 +66,10 @@ use thiserror::Error;
pub use self::sled::SledStore; pub use self::sled::SledStore;
use crate::{ use crate::{
error::SessionUnpicklingError, error::SessionUnpicklingError,
identities::{Device, ReadOnlyDevice, UserDevices, UserIdentities}, identities::{
user::{OwnUserIdentity, UserIdentities, UserIdentity},
Device, ReadOnlyDevice, ReadOnlyUserIdentities, UserDevices,
},
key_request::OutgoingKeyRequest, key_request::OutgoingKeyRequest,
olm::{ olm::{
InboundGroupSession, OlmMessageHash, OutboundGroupSession, PrivateCrossSigningIdentity, InboundGroupSession, OlmMessageHash, OutboundGroupSession, PrivateCrossSigningIdentity,
@ -109,8 +112,8 @@ pub struct Changes {
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
#[allow(missing_docs)] #[allow(missing_docs)]
pub struct IdentityChanges { pub struct IdentityChanges {
pub new: Vec<UserIdentities>, pub new: Vec<ReadOnlyUserIdentities>,
pub changed: Vec<UserIdentities>, pub changed: Vec<ReadOnlyUserIdentities>,
} }
#[derive(Debug, Clone, Default)] #[derive(Debug, Clone, Default)]
@ -215,8 +218,8 @@ impl Store {
device_id: &DeviceId, device_id: &DeviceId,
) -> Result<Option<Device>> { ) -> Result<Option<Device>> {
let own_identity = let own_identity =
self.get_user_identity(&self.user_id).await?.map(|i| i.own().cloned()).flatten(); self.inner.get_user_identity(&self.user_id).await?.map(|i| i.own().cloned()).flatten();
let device_owner_identity = self.get_user_identity(user_id).await?; let device_owner_identity = self.inner.get_user_identity(user_id).await?;
Ok(self.inner.get_device(user_id, device_id).await?.map(|d| Device { Ok(self.inner.get_device(user_id, device_id).await?.map(|d| Device {
inner: d, inner: d,
@ -226,6 +229,20 @@ impl Store {
device_owner_identity, device_owner_identity,
})) }))
} }
pub async fn get_identity(&self, user_id: &UserId) -> Result<Option<UserIdentities>> {
Ok(self.inner.get_user_identity(user_id).await?.map(|i| match i {
ReadOnlyUserIdentities::Own(i) => OwnUserIdentity {
inner: i,
verification_machine: self.verification_machine.clone(),
}
.into(),
ReadOnlyUserIdentities::Other(i) => {
UserIdentity { inner: i, verification_machine: self.verification_machine.clone() }
.into()
}
}))
}
} }
impl Deref for Store { impl Deref for Store {
@ -388,7 +405,7 @@ pub trait CryptoStore: AsyncTraitDeps {
/// # Arguments /// # Arguments
/// ///
/// * `user_id` - The user for which we should get the identity. /// * `user_id` - The user for which we should get the identity.
async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentities>>; async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<ReadOnlyUserIdentities>>;
/// Check if a hash for an Olm message stored in the database. /// Check if a hash for an Olm message stored in the database.
async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool>; async fn is_message_known(&self, message_hash: &OlmMessageHash) -> Result<bool>;

View File

@ -35,7 +35,7 @@ use super::{
ReadOnlyAccount, Result, Session, ReadOnlyAccount, Result, Session,
}; };
use crate::{ use crate::{
identities::{ReadOnlyDevice, UserIdentities}, identities::{ReadOnlyDevice, ReadOnlyUserIdentities},
key_request::OutgoingKeyRequest, key_request::OutgoingKeyRequest,
olm::{OutboundGroupSession, PickledInboundGroupSession, PrivateCrossSigningIdentity}, olm::{OutboundGroupSession, PickledInboundGroupSession, PrivateCrossSigningIdentity},
}; };
@ -669,7 +669,7 @@ impl CryptoStore for SledStore {
.collect() .collect()
} }
async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<UserIdentities>> { async fn get_user_identity(&self, user_id: &UserId) -> Result<Option<ReadOnlyUserIdentities>> {
Ok(self Ok(self
.identities .identities
.get(user_id.encode())? .get(user_id.encode())?

View File

@ -20,9 +20,13 @@ use std::{
use dashmap::DashMap; use dashmap::DashMap;
use matrix_sdk_common::{locks::Mutex, uuid::Uuid}; use matrix_sdk_common::{locks::Mutex, uuid::Uuid};
use ruma::{ use ruma::{
events::{AnyToDeviceEvent, AnyToDeviceEventContent, ToDeviceEvent}, events::{
key::verification::VerificationMethod, AnyToDeviceEvent, AnyToDeviceEventContent,
ToDeviceEvent,
},
serde::Raw, serde::Raw,
DeviceId, MilliSecondsSinceUnixEpoch, UserId, to_device::DeviceIdOrAllDevices,
DeviceId, EventId, MilliSecondsSinceUnixEpoch, RoomId, UserId,
}; };
use tracing::{info, trace, warn}; use tracing::{info, trace, warn};
@ -37,8 +41,8 @@ use crate::{
olm::PrivateCrossSigningIdentity, olm::PrivateCrossSigningIdentity,
requests::OutgoingRequest, requests::OutgoingRequest,
store::{CryptoStore, CryptoStoreError}, store::{CryptoStore, CryptoStoreError},
OutgoingVerificationRequest, ReadOnlyAccount, ReadOnlyDevice, RoomMessageRequest, OutgoingVerificationRequest, ReadOnlyAccount, ReadOnlyDevice, ReadOnlyOwnUserIdentity,
ToDeviceRequest, ReadOnlyUserIdentity, RoomMessageRequest, ToDeviceRequest,
}; };
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -65,6 +69,69 @@ impl VerificationMachine {
} }
} }
pub(crate) fn own_user_id(&self) -> &UserId {
self.account.user_id()
}
pub(crate) fn own_device_id(&self) -> &DeviceId {
self.account.device_id()
}
pub(crate) async fn request_self_verification(
&self,
identity: &ReadOnlyOwnUserIdentity,
methods: Option<Vec<VerificationMethod>>,
) -> Result<(VerificationRequest, OutgoingVerificationRequest), CryptoStoreError> {
let flow_id = FlowId::from(Uuid::new_v4().to_string());
let verification = VerificationRequest::new(
self.verifications.clone(),
self.account.clone(),
self.private_identity.lock().await.clone(),
self.store.clone(),
flow_id,
identity.user_id(),
methods,
);
// TODO get all the device ids of the user instead of using AllDevices
// make sure to remember this so we can cancel once someone picks up
let request: OutgoingVerificationRequest = ToDeviceRequest::new(
identity.user_id(),
DeviceIdOrAllDevices::AllDevices,
AnyToDeviceEventContent::KeyVerificationRequest(verification.request_to_device()),
)
.into();
self.insert_request(verification.clone());
Ok((verification, request))
}
pub async fn request_verification(
&self,
identity: &ReadOnlyUserIdentity,
room_id: &RoomId,
request_event_id: &EventId,
methods: Option<Vec<VerificationMethod>>,
) -> VerificationRequest {
let flow_id = FlowId::InRoom(room_id.to_owned(), request_event_id.to_owned());
let request = VerificationRequest::new(
self.verifications.clone(),
self.account.clone(),
self.private_identity.lock().await.clone(),
self.store.clone(),
flow_id,
identity.user_id(),
methods,
);
self.insert_request(request.clone());
request
}
pub async fn start_sas( pub async fn start_sas(
&self, &self,
device: ReadOnlyDevice, device: ReadOnlyDevice,

View File

@ -44,7 +44,7 @@ use crate::{
error::SignatureError, error::SignatureError,
olm::PrivateCrossSigningIdentity, olm::PrivateCrossSigningIdentity,
store::{Changes, CryptoStore}, store::{Changes, CryptoStore},
CryptoStoreError, LocalTrust, ReadOnlyDevice, UserIdentities, CryptoStoreError, LocalTrust, ReadOnlyDevice, ReadOnlyUserIdentities,
}; };
/// An enum over the different verification types the SDK supports. /// An enum over the different verification types the SDK supports.
@ -144,7 +144,7 @@ impl From<QrVerification> for Verification {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct Done { pub struct Done {
verified_devices: Arc<[ReadOnlyDevice]>, verified_devices: Arc<[ReadOnlyDevice]>,
verified_master_keys: Arc<[UserIdentities]>, verified_master_keys: Arc<[ReadOnlyUserIdentities]>,
} }
impl Done { impl Done {
@ -277,7 +277,7 @@ pub struct IdentitiesBeingVerified {
private_identity: PrivateCrossSigningIdentity, private_identity: PrivateCrossSigningIdentity,
store: Arc<dyn CryptoStore>, store: Arc<dyn CryptoStore>,
device_being_verified: ReadOnlyDevice, device_being_verified: ReadOnlyDevice,
identity_being_verified: Option<UserIdentities>, identity_being_verified: Option<ReadOnlyUserIdentities>,
} }
impl IdentitiesBeingVerified { impl IdentitiesBeingVerified {
@ -308,7 +308,7 @@ impl IdentitiesBeingVerified {
pub async fn mark_as_done( pub async fn mark_as_done(
&self, &self,
verified_devices: Option<&[ReadOnlyDevice]>, verified_devices: Option<&[ReadOnlyDevice]>,
verified_identities: Option<&[UserIdentities]>, verified_identities: Option<&[ReadOnlyUserIdentities]>,
) -> Result<VerificationResult, CryptoStoreError> { ) -> Result<VerificationResult, CryptoStoreError> {
let device = self.mark_device_as_verified(verified_devices).await?; let device = self.mark_device_as_verified(verified_devices).await?;
let identity = self.mark_identity_as_verified(verified_identities).await?; let identity = self.mark_identity_as_verified(verified_identities).await?;
@ -415,8 +415,8 @@ impl IdentitiesBeingVerified {
async fn mark_identity_as_verified( async fn mark_identity_as_verified(
&self, &self,
verified_identities: Option<&[UserIdentities]>, verified_identities: Option<&[ReadOnlyUserIdentities]>,
) -> Result<Option<UserIdentities>, CryptoStoreError> { ) -> Result<Option<ReadOnlyUserIdentities>, CryptoStoreError> {
// If there wasn't an identity available during the verification flow // If there wasn't an identity available during the verification flow
// return early as there's nothing to do. // return early as there's nothing to do.
if self.identity_being_verified.is_none() { if self.identity_being_verified.is_none() {
@ -437,7 +437,7 @@ impl IdentitiesBeingVerified {
"Marking the user identity of as verified." "Marking the user identity of as verified."
); );
if let UserIdentities::Own(i) = &identity { if let ReadOnlyUserIdentities::Own(i) = &identity {
i.mark_as_verified(); i.mark_as_verified();
} }

View File

@ -45,8 +45,8 @@ use super::{
use crate::{ use crate::{
olm::{PrivateCrossSigningIdentity, ReadOnlyAccount}, olm::{PrivateCrossSigningIdentity, ReadOnlyAccount},
store::CryptoStore, store::CryptoStore,
CryptoStoreError, OutgoingVerificationRequest, ReadOnlyDevice, RoomMessageRequest, CryptoStoreError, OutgoingVerificationRequest, ReadOnlyDevice, ReadOnlyUserIdentities,
ToDeviceRequest, UserIdentities, RoomMessageRequest, ToDeviceRequest,
}; };
const SECRET_SIZE: usize = 16; const SECRET_SIZE: usize = 16;
@ -518,7 +518,7 @@ impl QrVerification {
ScanError::MissingDeviceKeys(other_user_id.clone(), other_device_id.clone()) ScanError::MissingDeviceKeys(other_user_id.clone(), other_device_id.clone())
})?; })?;
let check_master_key = |key, identity: &UserIdentities| { let check_master_key = |key, identity: &ReadOnlyUserIdentities| {
let master_key = identity.master_key().get_first_key().ok_or_else(|| { let master_key = identity.master_key().get_first_key().ok_or_else(|| {
ScanError::MissingCrossSigningIdentity(identity.user_id().clone()) ScanError::MissingCrossSigningIdentity(identity.user_id().clone())
})?; })?;
@ -719,7 +719,7 @@ impl QrState<Done> {
self.state.as_content(flow_id) self.state.as_content(flow_id)
} }
fn verified_identities(&self) -> (Arc<[ReadOnlyDevice]>, Arc<[UserIdentities]>) { fn verified_identities(&self) -> (Arc<[ReadOnlyDevice]>, Arc<[ReadOnlyUserIdentities]>) {
(self.state.verified_devices.clone(), self.state.verified_master_keys.clone()) (self.state.verified_devices.clone(), self.state.verified_master_keys.clone())
} }
} }
@ -729,7 +729,7 @@ impl QrState<Confirmed> {
self, self,
_: &DoneContent, _: &DoneContent,
verified_device: Option<&ReadOnlyDevice>, verified_device: Option<&ReadOnlyDevice>,
verified_identity: Option<&UserIdentities>, verified_identity: Option<&ReadOnlyUserIdentities>,
) -> QrState<Done> { ) -> QrState<Done> {
let devices: Vec<_> = verified_device.into_iter().cloned().collect(); let devices: Vec<_> = verified_device.into_iter().cloned().collect();
let identities: Vec<_> = verified_identity.into_iter().cloned().collect(); let identities: Vec<_> = verified_identity.into_iter().cloned().collect();
@ -768,7 +768,7 @@ impl QrState<Reciprocated> {
self, self,
_: &DoneContent, _: &DoneContent,
verified_device: Option<&ReadOnlyDevice>, verified_device: Option<&ReadOnlyDevice>,
verified_identity: Option<&UserIdentities>, verified_identity: Option<&ReadOnlyUserIdentities>,
) -> QrState<Done> { ) -> QrState<Done> {
let devices: Vec<_> = verified_device.into_iter().cloned().collect(); let devices: Vec<_> = verified_device.into_iter().cloned().collect();
let identities: Vec<_> = verified_identity.into_iter().cloned().collect(); let identities: Vec<_> = verified_identity.into_iter().cloned().collect();

View File

@ -12,8 +12,6 @@
// See the License for the specific language governing permissions and // See the License for the specific language governing permissions and
// limitations under the License. // limitations under the License.
#![allow(dead_code)]
use std::sync::{Arc, Mutex}; use std::sync::{Arc, Mutex};
use matrix_qrcode::QrVerificationData; use matrix_qrcode::QrVerificationData;
@ -31,7 +29,7 @@ use ruma::{
AnyMessageEventContent, AnyToDeviceEventContent, AnyMessageEventContent, AnyToDeviceEventContent,
}, },
to_device::DeviceIdOrAllDevices, to_device::DeviceIdOrAllDevices,
DeviceId, DeviceIdBox, DeviceKeyAlgorithm, EventId, MilliSecondsSinceUnixEpoch, RoomId, UserId, DeviceId, DeviceIdBox, DeviceKeyAlgorithm, MilliSecondsSinceUnixEpoch, RoomId, UserId,
}; };
use tracing::{info, trace, warn}; use tracing::{info, trace, warn};
@ -46,8 +44,8 @@ use super::{
use crate::{ use crate::{
olm::{PrivateCrossSigningIdentity, ReadOnlyAccount}, olm::{PrivateCrossSigningIdentity, ReadOnlyAccount},
store::CryptoStore, store::CryptoStore,
CryptoStoreError, OutgoingVerificationRequest, ReadOnlyDevice, RoomMessageRequest, Sas, CryptoStoreError, OutgoingVerificationRequest, ReadOnlyDevice, ReadOnlyUserIdentities,
ToDeviceRequest, UserIdentities, RoomMessageRequest, Sas, ToDeviceRequest,
}; };
const SUPPORTED_METHODS: &[VerificationMethod] = &[ const SUPPORTED_METHODS: &[VerificationMethod] = &[
@ -79,41 +77,10 @@ impl VerificationRequest {
account: ReadOnlyAccount, account: ReadOnlyAccount,
private_cross_signing_identity: PrivateCrossSigningIdentity, private_cross_signing_identity: PrivateCrossSigningIdentity,
store: Arc<dyn CryptoStore>, store: Arc<dyn CryptoStore>,
room_id: &RoomId, flow_id: FlowId,
event_id: &EventId,
other_user: &UserId, other_user: &UserId,
methods: Option<Vec<VerificationMethod>>,
) -> Self { ) -> Self {
let flow_id = (room_id.to_owned(), event_id.to_owned()).into();
let inner = Mutex::new(InnerRequest::Created(RequestState::new(
account.clone(),
private_cross_signing_identity,
cache.clone(),
store,
other_user,
&flow_id,
)))
.into();
Self {
account,
verification_cache: cache,
flow_id: flow_id.into(),
inner,
other_user_id: other_user.to_owned().into(),
we_started: true,
}
}
pub(crate) fn new_to_device(
cache: VerificationCache,
account: ReadOnlyAccount,
private_cross_signing_identity: PrivateCrossSigningIdentity,
store: Arc<dyn CryptoStore>,
other_user: &UserId,
) -> Self {
let flow_id = Uuid::new_v4().to_string().into();
let inner = Mutex::new(InnerRequest::Created(RequestState::new( let inner = Mutex::new(InnerRequest::Created(RequestState::new(
account.clone(), account.clone(),
private_cross_signing_identity, private_cross_signing_identity,
@ -121,6 +88,7 @@ impl VerificationRequest {
store, store,
other_user, other_user,
&flow_id, &flow_id,
methods,
))) )))
.into(); .into();
@ -138,11 +106,19 @@ impl VerificationRequest {
/// verification from the other side. This should be used only for /// verification from the other side. This should be used only for
/// self-verifications and it should be sent to the specific device that we /// self-verifications and it should be sent to the specific device that we
/// want to verify. /// want to verify.
pub fn request_to_device(&self) -> RequestToDeviceEventContent { pub(crate) fn request_to_device(&self) -> RequestToDeviceEventContent {
let inner = self.inner.lock().unwrap();
let methods = if let InnerRequest::Created(c) = &*inner {
c.state.our_methods.clone()
} else {
SUPPORTED_METHODS.to_vec()
};
RequestToDeviceEventContent::new( RequestToDeviceEventContent::new(
self.account.device_id().into(), self.account.device_id().into(),
self.flow_id().as_str().to_string(), self.flow_id().as_str().to_string(),
SUPPORTED_METHODS.to_vec(), methods,
MilliSecondsSinceUnixEpoch::now(), MilliSecondsSinceUnixEpoch::now(),
) )
} }
@ -155,6 +131,7 @@ impl VerificationRequest {
own_user_id: &UserId, own_user_id: &UserId,
own_device_id: &DeviceId, own_device_id: &DeviceId,
other_user_id: &UserId, other_user_id: &UserId,
methods: Option<Vec<VerificationMethod>>,
) -> KeyVerificationRequestEventContent { ) -> KeyVerificationRequestEventContent {
KeyVerificationRequestEventContent::new( KeyVerificationRequestEventContent::new(
format!( format!(
@ -163,7 +140,7 @@ impl VerificationRequest {
key verification to verify keys.", key verification to verify keys.",
own_user_id own_user_id
), ),
SUPPORTED_METHODS.to_vec(), methods.unwrap_or_else(|| SUPPORTED_METHODS.to_vec()),
own_device_id.into(), own_device_id.into(),
other_user_id.to_owned(), other_user_id.to_owned(),
) )
@ -376,6 +353,15 @@ impl VerificationRequest {
/// Cancel the verification request /// Cancel the verification request
pub fn cancel(&self) -> Option<OutgoingVerificationRequest> { pub fn cancel(&self) -> Option<OutgoingVerificationRequest> {
if let Some(verification) =
self.verification_cache.get(self.other_user(), self.flow_id().as_str())
{
match verification {
crate::Verification::SasV1(s) => s.cancel(),
crate::Verification::QrV1(q) => q.cancel(),
};
}
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
inner.cancel(true, &CancelCode::User); inner.cancel(true, &CancelCode::User);
@ -398,12 +384,20 @@ impl VerificationRequest {
pub(crate) fn receive_ready(&self, sender: &UserId, content: &ReadyContent) { pub(crate) fn receive_ready(&self, sender: &UserId, content: &ReadyContent) {
let mut inner = self.inner.lock().unwrap(); let mut inner = self.inner.lock().unwrap();
if let InnerRequest::Created(s) = &*inner { match &*inner {
if sender == self.own_user_id() && content.from_device() == self.account.device_id() { InnerRequest::Created(s) => {
*inner = InnerRequest::Passive(s.clone().into_passive(content))
} else {
*inner = InnerRequest::Ready(s.clone().into_ready(sender, content)); *inner = InnerRequest::Ready(s.clone().into_ready(sender, content));
} }
InnerRequest::Requested(s) => {
if sender == self.own_user_id() && content.from_device() != self.account.device_id()
{
*inner = InnerRequest::Passive(s.clone().into_passive(content))
}
}
InnerRequest::Ready(_)
| InnerRequest::Passive(_)
| InnerRequest::Done(_)
| InnerRequest::Cancelled(_) => {}
} }
} }
@ -512,17 +506,6 @@ impl InnerRequest {
} }
} }
fn other_user_id(&self) -> &UserId {
match self {
InnerRequest::Created(s) => &s.other_user_id,
InnerRequest::Requested(s) => &s.other_user_id,
InnerRequest::Ready(s) => &s.other_user_id,
InnerRequest::Passive(s) => &s.other_user_id,
InnerRequest::Done(s) => &s.other_user_id,
InnerRequest::Cancelled(s) => &s.other_user_id,
}
}
fn accept(&mut self, methods: Vec<VerificationMethod>) -> Option<OutgoingContent> { fn accept(&mut self, methods: Vec<VerificationMethod>) -> Option<OutgoingContent> {
if let InnerRequest::Requested(s) = self { if let InnerRequest::Requested(s) = self {
let (state, content) = s.clone().accept(methods); let (state, content) = s.clone().accept(methods);
@ -569,20 +552,6 @@ impl InnerRequest {
InnerRequest::Cancelled(_) => Ok(None), InnerRequest::Cancelled(_) => Ok(None),
} }
} }
fn to_started_sas(
&self,
content: &StartContent,
other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>,
we_started: bool,
) -> Result<Option<Sas>, OutgoingContent> {
if let InnerRequest::Ready(s) = self {
Ok(Some(s.to_started_sas(content, other_device, other_identity, we_started)?))
} else {
Ok(None)
}
}
} }
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
@ -638,30 +607,21 @@ impl RequestState<Created> {
store: Arc<dyn CryptoStore>, store: Arc<dyn CryptoStore>,
other_user_id: &UserId, other_user_id: &UserId,
flow_id: &FlowId, flow_id: &FlowId,
methods: Option<Vec<VerificationMethod>>,
) -> Self { ) -> Self {
let our_methods = methods.unwrap_or_else(|| SUPPORTED_METHODS.to_vec());
Self { Self {
account, account,
other_user_id: other_user_id.to_owned(), other_user_id: other_user_id.to_owned(),
private_cross_signing_identity: private_identity, private_cross_signing_identity: private_identity,
state: Created { our_methods: SUPPORTED_METHODS.to_vec() }, state: Created { our_methods },
verification_cache: cache, verification_cache: cache,
store, store,
flow_id: flow_id.to_owned().into(), flow_id: flow_id.to_owned().into(),
} }
} }
fn into_passive(self, content: &ReadyContent) -> RequestState<Passive> {
RequestState {
account: self.account,
flow_id: self.flow_id,
verification_cache: self.verification_cache,
private_cross_signing_identity: self.private_cross_signing_identity,
store: self.store,
other_user_id: self.other_user_id,
state: Passive { other_device_id: content.from_device().to_owned() },
}
}
fn into_ready(self, _sender: &UserId, content: &ReadyContent) -> RequestState<Ready> { fn into_ready(self, _sender: &UserId, content: &ReadyContent) -> RequestState<Ready> {
// TODO check the flow id, and that the methods match what we suggested. // TODO check the flow id, and that the methods match what we suggested.
RequestState { RequestState {
@ -720,6 +680,18 @@ impl RequestState<Requested> {
} }
} }
fn into_passive(self, content: &ReadyContent) -> RequestState<Passive> {
RequestState {
account: self.account,
flow_id: self.flow_id,
verification_cache: self.verification_cache,
private_cross_signing_identity: self.private_cross_signing_identity,
store: self.store,
other_user_id: self.other_user_id,
state: Passive { other_device_id: content.from_device().to_owned() },
}
}
fn accept(self, methods: Vec<VerificationMethod>) -> (RequestState<Ready>, OutgoingContent) { fn accept(self, methods: Vec<VerificationMethod>) -> (RequestState<Ready>, OutgoingContent) {
let state = RequestState { let state = RequestState {
account: self.account.clone(), account: self.account.clone(),
@ -776,7 +748,7 @@ impl RequestState<Ready> {
&self, &self,
content: &StartContent<'a>, content: &StartContent<'a>,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
we_started: bool, we_started: bool,
) -> Result<Sas, OutgoingContent> { ) -> Result<Sas, OutgoingContent> {
Sas::from_start_event( Sas::from_start_event(
@ -827,7 +799,7 @@ impl RequestState<Ready> {
let verification = if let Some(identity) = &identites.identity_being_verified { let verification = if let Some(identity) = &identites.identity_being_verified {
match &identity { match &identity {
UserIdentities::Own(i) => { ReadOnlyUserIdentities::Own(i) => {
if let Some(master_key) = i.master_key().get_first_key() { if let Some(master_key) = i.master_key().get_first_key() {
if identites.can_sign_devices().await { if identites.can_sign_devices().await {
if let Some(device_key) = if let Some(device_key) =
@ -870,7 +842,7 @@ impl RequestState<Ready> {
None None
} }
} }
UserIdentities::Other(i) => { ReadOnlyUserIdentities::Other(i) => {
if let Some(other_master) = i.master_key().get_first_key() { if let Some(other_master) = i.master_key().get_first_key() {
// TODO we can get the master key from the public // TODO we can get the master key from the public
// identity if we don't have the private one and we // identity if we don't have the private one and we
@ -1117,20 +1089,21 @@ mod test {
let bob_store: Box<dyn CryptoStore> = Box::new(MemoryStore::new()); let bob_store: Box<dyn CryptoStore> = Box::new(MemoryStore::new());
let bob_identity = PrivateCrossSigningIdentity::empty(alice_id()); let bob_identity = PrivateCrossSigningIdentity::empty(alice_id());
let content = VerificationRequest::request(bob.user_id(), bob.device_id(), &alice_id()); let content =
VerificationRequest::request(bob.user_id(), bob.device_id(), &alice_id(), None);
let flow_id = FlowId::InRoom(room_id, event_id);
let bob_request = VerificationRequest::new( let bob_request = VerificationRequest::new(
VerificationCache::new(), VerificationCache::new(),
bob, bob,
bob_identity, bob_identity,
bob_store.into(), bob_store.into(),
&room_id, flow_id.clone(),
&event_id,
&alice_id(), &alice_id(),
None,
); );
let flow_id = FlowId::from((room_id, event_id));
let alice_request = VerificationRequest::from_request( let alice_request = VerificationRequest::from_request(
VerificationCache::new(), VerificationCache::new(),
alice, alice,
@ -1174,20 +1147,20 @@ mod test {
changes.devices.new.push(alice_device.clone()); changes.devices.new.push(alice_device.clone());
bob_store.save_changes(changes).await.unwrap(); bob_store.save_changes(changes).await.unwrap();
let content = VerificationRequest::request(bob.user_id(), bob.device_id(), &alice_id()); let content =
VerificationRequest::request(bob.user_id(), bob.device_id(), &alice_id(), None);
let flow_id = FlowId::from((room_id, event_id));
let bob_request = VerificationRequest::new( let bob_request = VerificationRequest::new(
VerificationCache::new(), VerificationCache::new(),
bob, bob,
bob_identity, bob_identity,
bob_store.into(), bob_store.into(),
&room_id, flow_id.clone(),
&event_id,
&alice_id(), &alice_id(),
None,
); );
let flow_id = FlowId::from((room_id, event_id));
let alice_request = VerificationRequest::from_request( let alice_request = VerificationRequest::from_request(
VerificationCache::new(), VerificationCache::new(),
alice, alice,
@ -1240,12 +1213,16 @@ mod test {
changes.devices.new.push(alice_device.clone()); changes.devices.new.push(alice_device.clone());
bob_store.save_changes(changes).await.unwrap(); bob_store.save_changes(changes).await.unwrap();
let bob_request = VerificationRequest::new_to_device( let flow_id = FlowId::from("TEST_FLOW_ID".to_owned());
let bob_request = VerificationRequest::new(
VerificationCache::new(), VerificationCache::new(),
bob, bob,
bob_identity, bob_identity,
bob_store.into(), bob_store.into(),
flow_id,
&alice_id(), &alice_id(),
None,
); );
let content = bob_request.request_to_device(); let content = bob_request.request_to_device();

View File

@ -31,7 +31,7 @@ use tracing::{trace, warn};
use super::{FlowId, OutgoingContent}; use super::{FlowId, OutgoingContent};
use crate::{ use crate::{
identities::{ReadOnlyDevice, UserIdentities}, identities::{ReadOnlyDevice, ReadOnlyUserIdentities},
utilities::encode, utilities::encode,
verification::event_enums::{MacContent, StartContent}, verification::event_enums::{MacContent, StartContent},
ReadOnlyAccount, ReadOnlyAccount,
@ -41,7 +41,7 @@ use crate::{
pub struct SasIds { pub struct SasIds {
pub account: ReadOnlyAccount, pub account: ReadOnlyAccount,
pub other_device: ReadOnlyDevice, pub other_device: ReadOnlyDevice,
pub other_identity: Option<UserIdentities>, pub other_identity: Option<ReadOnlyUserIdentities>,
} }
/// Calculate the commitment for a accept event from the public key and the /// Calculate the commitment for a accept event from the public key and the
@ -182,7 +182,7 @@ pub fn receive_mac_event(
flow_id: &str, flow_id: &str,
sender: &UserId, sender: &UserId,
content: &MacContent, content: &MacContent,
) -> Result<(Vec<ReadOnlyDevice>, Vec<UserIdentities>), CancelCode> { ) -> Result<(Vec<ReadOnlyDevice>, Vec<ReadOnlyUserIdentities>), CancelCode> {
let mut verified_devices = Vec::new(); let mut verified_devices = Vec::new();
let mut verified_identities = Vec::new(); let mut verified_identities = Vec::new();

View File

@ -29,7 +29,7 @@ use super::{
FlowId, FlowId,
}; };
use crate::{ use crate::{
identities::{ReadOnlyDevice, UserIdentities}, identities::{ReadOnlyDevice, ReadOnlyUserIdentities},
verification::{ verification::{
event_enums::{AnyVerificationContent, OutgoingContent, OwnedAcceptContent, StartContent}, event_enums::{AnyVerificationContent, OutgoingContent, OwnedAcceptContent, StartContent},
Cancelled, Done, Cancelled, Done,
@ -55,7 +55,7 @@ impl InnerSas {
pub fn start( pub fn start(
account: ReadOnlyAccount, account: ReadOnlyAccount,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
transaction_id: Option<String>, transaction_id: Option<String>,
) -> (InnerSas, OutgoingContent) { ) -> (InnerSas, OutgoingContent) {
let sas = SasState::<Created>::new(account, other_device, other_identity, transaction_id); let sas = SasState::<Created>::new(account, other_device, other_identity, transaction_id);
@ -131,7 +131,7 @@ impl InnerSas {
room_id: RoomId, room_id: RoomId,
account: ReadOnlyAccount, account: ReadOnlyAccount,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
) -> (InnerSas, OutgoingContent) { ) -> (InnerSas, OutgoingContent) {
let sas = SasState::<Created>::new_in_room( let sas = SasState::<Created>::new_in_room(
room_id, room_id,
@ -149,7 +149,7 @@ impl InnerSas {
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
flow_id: FlowId, flow_id: FlowId,
content: &StartContent, content: &StartContent,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
started_from_request: bool, started_from_request: bool,
) -> Result<InnerSas, OutgoingContent> { ) -> Result<InnerSas, OutgoingContent> {
match SasState::<Started>::from_start_event( match SasState::<Started>::from_start_event(
@ -204,7 +204,9 @@ impl InnerSas {
InnerSas::WeAccepted(s) => s.cancel(cancelled_by_us, code), InnerSas::WeAccepted(s) => s.cancel(cancelled_by_us, code),
InnerSas::KeyReceived(s) => s.cancel(cancelled_by_us, code), InnerSas::KeyReceived(s) => s.cancel(cancelled_by_us, code),
InnerSas::MacReceived(s) => s.cancel(cancelled_by_us, code), InnerSas::MacReceived(s) => s.cancel(cancelled_by_us, code),
_ => return (self, None), InnerSas::Confirmed(s) => s.cancel(cancelled_by_us, code),
InnerSas::WaitingForDone(s) => s.cancel(cancelled_by_us, code),
InnerSas::Done(_) | InnerSas::Cancelled(_) => return (self, None),
}; };
let content = sas.as_content(); let content = sas.as_content();
@ -423,7 +425,7 @@ impl InnerSas {
} }
} }
pub fn verified_identities(&self) -> Option<Arc<[UserIdentities]>> { pub fn verified_identities(&self) -> Option<Arc<[ReadOnlyUserIdentities]>> {
if let InnerSas::Done(s) = self { if let InnerSas::Done(s) = self {
Some(s.verified_identities()) Some(s.verified_identities())
} else { } else {

View File

@ -41,7 +41,7 @@ use super::{
FlowId, IdentitiesBeingVerified, VerificationResult, FlowId, IdentitiesBeingVerified, VerificationResult,
}; };
use crate::{ use crate::{
identities::{ReadOnlyDevice, UserIdentities}, identities::{ReadOnlyDevice, ReadOnlyUserIdentities},
olm::PrivateCrossSigningIdentity, olm::PrivateCrossSigningIdentity,
requests::{OutgoingVerificationRequest, RoomMessageRequest}, requests::{OutgoingVerificationRequest, RoomMessageRequest},
store::{CryptoStore, CryptoStoreError}, store::{CryptoStore, CryptoStoreError},
@ -151,7 +151,7 @@ impl Sas {
private_identity: PrivateCrossSigningIdentity, private_identity: PrivateCrossSigningIdentity,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
store: Arc<dyn CryptoStore>, store: Arc<dyn CryptoStore>,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
we_started: bool, we_started: bool,
) -> Sas { ) -> Sas {
let flow_id = inner_sas.verification_flow_id(); let flow_id = inner_sas.verification_flow_id();
@ -187,7 +187,7 @@ impl Sas {
private_identity: PrivateCrossSigningIdentity, private_identity: PrivateCrossSigningIdentity,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
store: Arc<dyn CryptoStore>, store: Arc<dyn CryptoStore>,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
transaction_id: Option<String>, transaction_id: Option<String>,
we_started: bool, we_started: bool,
) -> (Sas, OutgoingContent) { ) -> (Sas, OutgoingContent) {
@ -230,7 +230,7 @@ impl Sas {
private_identity: PrivateCrossSigningIdentity, private_identity: PrivateCrossSigningIdentity,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
store: Arc<dyn CryptoStore>, store: Arc<dyn CryptoStore>,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
we_started: bool, we_started: bool,
) -> (Sas, OutgoingContent) { ) -> (Sas, OutgoingContent) {
let (inner, content) = InnerSas::start_in_room( let (inner, content) = InnerSas::start_in_room(
@ -273,7 +273,7 @@ impl Sas {
account: ReadOnlyAccount, account: ReadOnlyAccount,
private_identity: PrivateCrossSigningIdentity, private_identity: PrivateCrossSigningIdentity,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
started_from_request: bool, started_from_request: bool,
we_started: bool, we_started: bool,
) -> Result<Sas, OutgoingContent> { ) -> Result<Sas, OutgoingContent> {
@ -503,7 +503,7 @@ impl Sas {
self.inner.lock().unwrap().verified_devices() self.inner.lock().unwrap().verified_devices()
} }
pub(crate) fn verified_identities(&self) -> Option<Arc<[UserIdentities]>> { pub(crate) fn verified_identities(&self) -> Option<Arc<[ReadOnlyUserIdentities]>> {
self.inner.lock().unwrap().verified_identities() self.inner.lock().unwrap().verified_identities()
} }

View File

@ -52,7 +52,7 @@ use super::{
OutgoingContent, OutgoingContent,
}; };
use crate::{ use crate::{
identities::{ReadOnlyDevice, UserIdentities}, identities::{ReadOnlyDevice, ReadOnlyUserIdentities},
verification::{ verification::{
event_enums::{ event_enums::{
AcceptContent, DoneContent, KeyContent, MacContent, OwnedAcceptContent, AcceptContent, DoneContent, KeyContent, MacContent, OwnedAcceptContent,
@ -277,7 +277,7 @@ pub struct MacReceived {
we_started: bool, we_started: bool,
their_pubkey: String, their_pubkey: String,
verified_devices: Arc<[ReadOnlyDevice]>, verified_devices: Arc<[ReadOnlyDevice]>,
verified_master_keys: Arc<[UserIdentities]>, verified_master_keys: Arc<[ReadOnlyUserIdentities]>,
pub accepted_protocols: Arc<AcceptedProtocols>, pub accepted_protocols: Arc<AcceptedProtocols>,
} }
@ -287,7 +287,7 @@ pub struct MacReceived {
#[derive(Clone, Debug)] #[derive(Clone, Debug)]
pub struct WaitingForDone { pub struct WaitingForDone {
verified_devices: Arc<[ReadOnlyDevice]>, verified_devices: Arc<[ReadOnlyDevice]>,
verified_master_keys: Arc<[UserIdentities]>, verified_master_keys: Arc<[ReadOnlyUserIdentities]>,
} }
impl<S: Clone> SasState<S> { impl<S: Clone> SasState<S> {
@ -362,7 +362,7 @@ impl SasState<Created> {
pub fn new( pub fn new(
account: ReadOnlyAccount, account: ReadOnlyAccount,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
transaction_id: Option<String>, transaction_id: Option<String>,
) -> SasState<Created> { ) -> SasState<Created> {
let started_from_request = transaction_id.is_some(); let started_from_request = transaction_id.is_some();
@ -388,7 +388,7 @@ impl SasState<Created> {
event_id: EventId, event_id: EventId,
account: ReadOnlyAccount, account: ReadOnlyAccount,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
) -> SasState<Created> { ) -> SasState<Created> {
let flow_id = FlowId::InRoom(room_id, event_id); let flow_id = FlowId::InRoom(room_id, event_id);
Self::new_helper(flow_id, account, other_device, other_identity, false) Self::new_helper(flow_id, account, other_device, other_identity, false)
@ -398,7 +398,7 @@ impl SasState<Created> {
flow_id: FlowId, flow_id: FlowId,
account: ReadOnlyAccount, account: ReadOnlyAccount,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
started_from_request: bool, started_from_request: bool,
) -> SasState<Created> { ) -> SasState<Created> {
SasState { SasState {
@ -497,7 +497,7 @@ impl SasState<Started> {
pub fn from_start_event( pub fn from_start_event(
account: ReadOnlyAccount, account: ReadOnlyAccount,
other_device: ReadOnlyDevice, other_device: ReadOnlyDevice,
other_identity: Option<UserIdentities>, other_identity: Option<ReadOnlyUserIdentities>,
flow_id: FlowId, flow_id: FlowId,
content: &StartContent, content: &StartContent,
started_from_request: bool, started_from_request: bool,
@ -1096,7 +1096,7 @@ impl SasState<Done> {
} }
/// Get the list of verified identities. /// Get the list of verified identities.
pub fn verified_identities(&self) -> Arc<[UserIdentities]> { pub fn verified_identities(&self) -> Arc<[ReadOnlyUserIdentities]> {
self.state.verified_master_keys.clone() self.state.verified_master_keys.clone()
} }
} }