From 2db52eed7cfcd8345e4683ba2fcf56323450c3f0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Damir=20Jeli=C4=87?= Date: Thu, 4 Nov 2021 14:26:49 +0100 Subject: [PATCH] feat(crypto): Request the recovery key when we request secrets --- .../src/backups/keys/recovery.rs | 2 +- .../src/gossiping/machine.rs | 48 ++++++++++--------- crates/matrix-sdk-crypto/src/store/mod.rs | 7 ++- .../matrix-sdk-crypto/src/verification/mod.rs | 15 ++++-- 4 files changed, 44 insertions(+), 28 deletions(-) diff --git a/crates/matrix-sdk-crypto/src/backups/keys/recovery.rs b/crates/matrix-sdk-crypto/src/backups/keys/recovery.rs index fdfffc85c..2594c5577 100644 --- a/crates/matrix-sdk-crypto/src/backups/keys/recovery.rs +++ b/crates/matrix-sdk-crypto/src/backups/keys/recovery.rs @@ -143,7 +143,7 @@ impl RecoveryKey { Self { key, version: None } } - pub fn from_base64(key: String) -> Result { + pub fn from_base64(key: &str) -> Result { let decoded = Zeroizing::new(crate::utilities::decode(key)?); if decoded.len() != Self::KEY_SIZE { diff --git a/crates/matrix-sdk-crypto/src/gossiping/machine.rs b/crates/matrix-sdk-crypto/src/gossiping/machine.rs index 18c6dbc59..552c93461 100644 --- a/crates/matrix-sdk-crypto/src/gossiping/machine.rs +++ b/crates/matrix-sdk-crypto/src/gossiping/machine.rs @@ -770,6 +770,8 @@ impl GossipMachine { return Ok(None); }; + let secret = std::mem::take(&mut event.content.secret); + if let Some(request) = self.store.get_outgoing_secret_requests(request_id).await? { match &request.info { SecretInfo::KeyRequest(_) => { @@ -791,30 +793,32 @@ impl GossipMachine { self.store.get_device_from_curve_key(&event.sender, sender_key).await? { if device.verified() { - match self - .store - .import_secret( - secret_name, - std::mem::take(&mut event.content.secret), - ) - .await - { - Ok(_) => self.mark_as_done(request).await?, - Err(e) => { - // If this is a store error propagate it up - // the call stack. - if let SecretImportError::Store(e) = e { - return Err(e); - } else { - // Otherwise warn that there was - // something wrong with the secret. - warn!( - secret_name = secret_name.as_ref(), - error =? e, - "Error while importing a secret" - ) + if secret_name != &SecretName::RecoveryKey { + match self.store.import_secret(secret_name, secret).await { + Ok(_) => self.mark_as_done(request).await?, + Err(e) => { + // If this is a store error propagate it up + // the call stack. + if let SecretImportError::Store(e) = e { + return Err(e); + } else { + // Otherwise warn that there was + // something wrong with the secret. + warn!( + secret_name = secret_name.as_ref(), + error =? e, + "Error while importing a secret" + ) + } } } + } else { + // Skip importing the recovery key here since + // we'll want to check if the public key matches + // to the latest version on the server. We + // instead leave the key in the event and let + // the user import it later. + event.content.secret = secret; } } else { warn!( diff --git a/crates/matrix-sdk-crypto/src/store/mod.rs b/crates/matrix-sdk-crypto/src/store/mod.rs index be317dd21..9f5ea3366 100644 --- a/crates/matrix-sdk-crypto/src/store/mod.rs +++ b/crates/matrix-sdk-crypto/src/store/mod.rs @@ -514,7 +514,12 @@ impl Store { self.save_changes(changes).await?; } } - SecretName::RecoveryKey => (), + SecretName::RecoveryKey => { + // We don't import the recovery key here since we'll want to + // check if the public key matches to the latest version on the + // server. We instead leave the key in the event and let the + // user import it later. + } name => { warn!(secret =? name, "Tried to import an unknown secret"); } diff --git a/crates/matrix-sdk-crypto/src/verification/mod.rs b/crates/matrix-sdk-crypto/src/verification/mod.rs index 0dc8f3887..087e8dd70 100644 --- a/crates/matrix-sdk-crypto/src/verification/mod.rs +++ b/crates/matrix-sdk-crypto/src/verification/mod.rs @@ -42,6 +42,7 @@ use ruma::{ done::{KeyVerificationDoneEventContent, ToDeviceKeyVerificationDoneEventContent}, Relation, }, + secret::request::SecretName, AnyMessageEventContent, AnyToDeviceEventContent, }, DeviceId, DeviceIdBox, DeviceKeyId, EventId, RoomId, UserId, @@ -535,7 +536,7 @@ impl IdentitiesBeingVerified { }; if should_request_secrets { - let secret_requests = self.request_missing_secrets().await; + let secret_requests = self.request_missing_secrets().await?; changes.key_requests = secret_requests; } @@ -547,9 +548,15 @@ impl IdentitiesBeingVerified { .unwrap_or(VerificationResult::Ok)) } - async fn request_missing_secrets(&self) -> Vec { - let secrets = self.private_identity.get_missing_secrets().await; - GossipMachine::request_missing_secrets(self.user_id(), secrets) + async fn request_missing_secrets(&self) -> Result, CryptoStoreError> { + let mut secrets = self.private_identity.get_missing_secrets().await; + + #[cfg(feature = "backups_v1")] + if self.store.inner.load_backup_keys().await?.recovery_key.is_none() { + secrets.push(SecretName::RecoveryKey); + } + + Ok(GossipMachine::request_missing_secrets(self.user_id(), secrets)) } async fn mark_identity_as_verified(