Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mark as verified if our own device matches keys #1348

Merged
merged 4 commits into from
Jan 17, 2023
Merged
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
88 changes: 67 additions & 21 deletions crates/matrix-sdk-crypto/src/identities/manager.rs
Original file line number Diff line number Diff line change
Expand Up @@ -532,6 +532,15 @@ impl IdentityManager {
if result.any_cleared() {
changed_identity = Some((*private_identity).clone());
info!(cleared = ?result, "Removed some or all of our private cross signing keys");
} else if new && private_identity.has_master_key().await {
poljar marked this conversation as resolved.
Show resolved Hide resolved
poljar marked this conversation as resolved.
Show resolved Hide resolved
// If the master key didn't rotate above (`clear_if_differs`),
// then this means that the public part and the private parts of
// the master key match. We previously did a signature check, so
// this means that the private part of the master key has signed
// the identity. We can safely mark the public part of the
// identity as verified.
identity.mark_as_verified();
trace!("Marked our own identity as verified");
poljar marked this conversation as resolved.
Show resolved Hide resolved
}
}

Expand Down Expand Up @@ -665,7 +674,9 @@ pub(crate) mod testing {
machine::testing::response_from_file,
olm::{PrivateCrossSigningIdentity, ReadOnlyAccount},
store::{CryptoStore, MemoryStore, Store},
types::DeviceKeys,
verification::VerificationMachine,
UploadSigningKeysRequest,
};

pub fn user_id() -> &'static UserId {
Expand All @@ -680,8 +691,9 @@ pub(crate) mod testing {
device_id!("WSKKLTJZCL")
}

pub(crate) fn manager() -> IdentityManager {
let identity = Arc::new(Mutex::new(PrivateCrossSigningIdentity::empty(user_id())));
pub(crate) async fn manager() -> IdentityManager {
let identity = PrivateCrossSigningIdentity::new(user_id().into()).await;
let identity = Arc::new(Mutex::new(identity));
let user_id = Arc::from(user_id());
let account = ReadOnlyAccount::new(&user_id, device_id());
let store: Arc<dyn CryptoStore> = Arc::new(MemoryStore::new());
Expand Down Expand Up @@ -850,6 +862,33 @@ pub(crate) mod testing {
KeyQueryResponse::try_from_http_response(data)
.expect("Can't parse the keys upload response")
}

pub fn key_query(
identity: UploadSigningKeysRequest,
device_keys: DeviceKeys,
) -> KeyQueryResponse {
let json = json!({
"device_keys": {
"@example:localhost": {
device_keys.device_id.to_string(): device_keys
}
},
"failures": {},
"master_keys": {
"@example:localhost": identity.master_key
},
"self_signing_keys": {
"@example:localhost": identity.self_signing_key
},
"user_signing_keys": {
"@example:localhost": identity.user_signing_key
},
}
);

KeyQueryResponse::try_from_http_response(response_from_file(&json))
.expect("Can't parse the keys upload response")
}
}

#[cfg(test)]
Expand All @@ -863,7 +902,7 @@ pub(crate) mod tests {
};
use serde_json::json;

use super::testing::{manager, other_key_query, other_user_id};
use super::testing::{device_id, key_query, manager, other_key_query, other_user_id, user_id};

fn key_query_without_failures() -> KeysQueryResponse {
let response = json!({
Expand Down Expand Up @@ -896,13 +935,13 @@ pub(crate) mod tests {

#[async_test]
async fn test_manager_creation() {
let manager = manager();
let manager = manager().await;
assert!(manager.store.tracked_users().is_empty())
}

#[async_test]
async fn test_manager_key_query_response() {
let manager = manager();
let manager = manager().await;
let other_user = other_user_id();
let devices = manager.store.get_user_devices(other_user).await.unwrap();
assert_eq!(devices.devices().count(), 0);
Expand Down Expand Up @@ -932,31 +971,38 @@ pub(crate) mod tests {

#[async_test]
async fn test_manager_own_key_query_response() {
let manager = manager();
let other_user = other_user_id();
let devices = manager.store.get_user_devices(other_user).await.unwrap();
let manager = manager().await;
let our_user = user_id();
let devices = manager.store.get_user_devices(our_user).await.unwrap();
assert_eq!(devices.devices().count(), 0);

manager.receive_keys_query_response(&other_key_query()).await.unwrap();
let private_identity = manager.store.private_identity();
let private_identity = private_identity.lock().await;
let identity_request = private_identity.as_upload_request().await;
drop(private_identity);

let devices = manager.store.get_user_devices(other_user).await.unwrap();
assert_eq!(devices.devices().count(), 1);

let device = manager
.store
.get_readonly_device(other_user, device_id!("SKISMLNIMH"))
let device_keys = manager.store.account().device_keys().await;
manager
.receive_keys_query_response(&key_query(identity_request, device_keys))
.await
.unwrap()
.unwrap();
let identity = manager.store.get_user_identity(other_user).await.unwrap().unwrap();
let identity = identity.other().unwrap();

identity.is_device_signed(&device).unwrap();
let identity = manager.store.get_user_identity(our_user).await.unwrap().unwrap();
let identity = identity.own().unwrap();
assert!(identity.is_verified());

let devices = manager.store.get_user_devices(our_user).await.unwrap();
assert_eq!(devices.devices().count(), 1);

let device =
manager.store.get_readonly_device(our_user, device_id!(device_id())).await.unwrap();

assert!(device.is_some());
}

#[async_test]
async fn no_tracked_users_key_query_request() {
let manager = manager();
let manager = manager().await;

assert!(manager.store.tracked_users().is_empty(), "No users are initially tracked");

Expand All @@ -971,7 +1017,7 @@ pub(crate) mod tests {

#[async_test]
async fn failure_handling() {
let manager = manager();
let manager = manager().await;
let alice = user_id!("@alice:example.org");

assert!(manager.store.tracked_users().is_empty(), "No users are initially tracked");
Expand Down