feat(crypto): Request the recovery key when we request secrets

This commit is contained in:
Damir Jelić
2021-11-04 14:26:49 +01:00
parent 656edce75a
commit 2db52eed7c
4 changed files with 44 additions and 28 deletions

View File

@@ -143,7 +143,7 @@ impl RecoveryKey {
Self { key, version: None }
}
pub fn from_base64(key: String) -> Result<Self, DecodeError> {
pub fn from_base64(key: &str) -> Result<Self, DecodeError> {
let decoded = Zeroizing::new(crate::utilities::decode(key)?);
if decoded.len() != Self::KEY_SIZE {

View File

@@ -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!(

View File

@@ -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");
}

View File

@@ -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<GossipRequest> {
let secrets = self.private_identity.get_missing_secrets().await;
GossipMachine::request_missing_secrets(self.user_id(), secrets)
async fn request_missing_secrets(&self) -> Result<Vec<GossipRequest>, 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(