crypto: If our own identity passed a SAS flow, mark it as verified.

master
Damir Jelić 2020-08-19 14:34:18 +02:00
parent 3990e50ca6
commit 317a141e07
2 changed files with 84 additions and 4 deletions

View File

@ -15,7 +15,10 @@
use std::{ use std::{
collections::BTreeMap, collections::BTreeMap,
convert::TryFrom, convert::TryFrom,
sync::{atomic::AtomicBool, Arc}, sync::{
atomic::{AtomicBool, Ordering},
Arc,
},
}; };
use serde_json::to_value; use serde_json::to_value;
@ -29,8 +32,10 @@ use crate::{error::SignatureError, verify_json, ReadOnlyDevice};
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct MasterPubkey(Arc<CrossSigningKey>); pub struct MasterPubkey(Arc<CrossSigningKey>);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct SelfSigningPubkey(Arc<CrossSigningKey>); pub struct SelfSigningPubkey(Arc<CrossSigningKey>);
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct UserSigningPubkey(Arc<CrossSigningKey>); pub struct UserSigningPubkey(Arc<CrossSigningKey>);
@ -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)] #[derive(Debug, Clone)]
pub struct UserIdentity { pub struct UserIdentity {
user_id: Arc<UserId>, user_id: Arc<UserId>,
@ -287,6 +298,14 @@ impl OwnUserIdentity {
self.user_signing_key self.user_signing_key
.verify_master_key(&identity.master_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)] #[cfg(test)]

View File

@ -189,8 +189,15 @@ impl Sas {
(content, guard.is_done()) (content, guard.is_done())
}; };
if done && !self.mark_device_as_verified().await? { 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()); return Ok(self.cancel());
} else {
self.mark_identity_as_verified().await?;
}
} }
Ok(content.map(|c| { Ok(content.map(|c| {
@ -199,6 +206,61 @@ impl Sas {
})) }))
} }
pub(crate) async fn mark_identity_as_verified(&self) -> Result<bool, CryptoStoreError> {
// 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<bool, CryptoStoreError> { pub(crate) async fn mark_device_as_verified(&self) -> Result<bool, CryptoStoreError> {
let device = self let device = self
.store .store
@ -335,7 +397,6 @@ impl Sas {
self.inner.lock().unwrap().verified_devices() self.inner.lock().unwrap().verified_devices()
} }
#[allow(dead_code)]
pub(crate) fn verified_identities(&self) -> Option<Arc<Vec<UserIdentities>>> { pub(crate) fn verified_identities(&self) -> Option<Arc<Vec<UserIdentities>>> {
self.inner.lock().unwrap().verified_identities() self.inner.lock().unwrap().verified_identities()
} }