diff --git a/matrix_sdk_crypto/src/user_identity.rs b/matrix_sdk_crypto/src/user_identity.rs index 21bf3ee5..0ba74205 100644 --- a/matrix_sdk_crypto/src/user_identity.rs +++ b/matrix_sdk_crypto/src/user_identity.rs @@ -15,7 +15,10 @@ use std::{ collections::BTreeMap, convert::TryFrom, - sync::{atomic::AtomicBool, Arc}, + sync::{ + atomic::{AtomicBool, Ordering}, + Arc, + }, }; use serde_json::to_value; @@ -29,8 +32,10 @@ use crate::{error::SignatureError, verify_json, ReadOnlyDevice}; #[derive(Debug, Clone)] pub struct MasterPubkey(Arc); + #[derive(Debug, Clone)] pub struct SelfSigningPubkey(Arc); + #[derive(Debug, Clone)] pub struct UserSigningPubkey(Arc); @@ -182,6 +187,12 @@ impl UserIdentities { } } +impl PartialEq for UserIdentities { + fn eq(&self, other: &UserIdentities) -> bool { + self.user_id() == other.user_id() + } +} + #[derive(Debug, Clone)] pub struct UserIdentity { user_id: Arc, @@ -287,6 +298,14 @@ impl OwnUserIdentity { self.user_signing_key .verify_master_key(&identity.master_key) } + + pub fn mark_as_verified(&self) { + self.verified.store(true, Ordering::SeqCst) + } + + pub fn is_verified(&self) -> bool { + self.verified.load(Ordering::SeqCst) + } } #[cfg(test)] diff --git a/matrix_sdk_crypto/src/verification/sas/mod.rs b/matrix_sdk_crypto/src/verification/sas/mod.rs index 74a33e78..c3e49687 100644 --- a/matrix_sdk_crypto/src/verification/sas/mod.rs +++ b/matrix_sdk_crypto/src/verification/sas/mod.rs @@ -189,8 +189,15 @@ impl Sas { (content, guard.is_done()) }; - if done && !self.mark_device_as_verified().await? { - return Ok(self.cancel()); + if done { + // TODO move the logic that marks and stores the device into the + // else branch and only after the identity was verified as well. We + // dont' want to verify one without the other. + if !self.mark_device_as_verified().await? { + return Ok(self.cancel()); + } else { + self.mark_identity_as_verified().await?; + } } Ok(content.map(|c| { @@ -199,6 +206,61 @@ impl Sas { })) } + pub(crate) async fn mark_identity_as_verified(&self) -> Result { + // If there wasn't an identity available during the verification flow + // return early as there's nothing to do. + if self.other_identity.is_none() { + return Ok(false); + } + + let identity = self.store.get_user_identity(self.other_user_id()).await?; + + if let Some(identity) = identity { + if identity.master_key() == self.other_identity.as_ref().unwrap().master_key() { + if self + .verified_identities() + .map_or(false, |i| i.contains(&identity)) + { + trace!( + "Marking user identity of {} as verified.", + identity.user_id(), + ); + + match &identity { + UserIdentities::Own(i) => { + i.mark_as_verified(); + self.store.save_user_identities(&[identity]).await?; + } + // TODO if we have the private part of the user signing + // key we should sign and upload a signature for this + // identity. + _ => {} + } + + Ok(true) + } else { + info!( + "The interactive verification process didn't contain a \ + MAC for the user identity of {} {:?}", + identity.user_id(), + self.verified_identities(), + ); + + Ok(false) + } + } else { + Ok(false) + } + } else { + info!( + "The identity for {} was deleted while an interactive \ + verification was going on.", + self.other_user_id(), + ); + Ok(false) + } + } + pub(crate) async fn mark_device_as_verified(&self) -> Result { let device = self .store @@ -335,7 +397,6 @@ impl Sas { self.inner.lock().unwrap().verified_devices() } - #[allow(dead_code)] pub(crate) fn verified_identities(&self) -> Option>> { self.inner.lock().unwrap().verified_identities() }