fix: avoid blocking on expensive pgp operations

This commit is contained in:
dignifiedquire
2020-05-25 00:17:01 +02:00
parent 477e689c74
commit 2adeadfd73
9 changed files with 241 additions and 217 deletions

View File

@@ -87,30 +87,30 @@ impl EncryptHelper {
/// Tries to encrypt the passed in `mail`.
pub async fn encrypt(
&mut self,
self,
context: &Context,
min_verified: PeerstateVerifiedStatus,
mail_to_encrypt: lettre_email::PartBuilder,
peerstates: &[(Option<Peerstate<'_>>, &str)],
peerstates: Vec<(Option<Peerstate<'_>>, &str)>,
) -> Result<String> {
let mut keyring = Keyring::default();
for (peerstate, addr) in peerstates
.iter()
.filter_map(|(state, addr)| state.as_ref().map(|s| (s, addr)))
.into_iter()
.filter_map(|(state, addr)| state.map(|s| (s, addr)))
{
let key = peerstate.peek_key(min_verified).ok_or_else(|| {
let key = peerstate.take_key(min_verified).ok_or_else(|| {
format_err!("proper enc-key for {} missing, cannot encrypt", addr)
})?;
keyring.add_ref(key);
keyring.add(key);
}
let public_key = Key::from(self.public_key.clone());
keyring.add_ref(&public_key);
let public_key = Key::from(self.public_key);
keyring.add(public_key);
let sign_key = Key::from(SignedSecretKey::load_self(context).await?);
let raw_message = mail_to_encrypt.build().as_string().into_bytes();
let ctext = pgp::pk_encrypt(&raw_message, &keyring, Some(&sign_key))?;
let ctext = pgp::pk_encrypt(&raw_message, keyring, Some(sign_key)).await?;
Ok(ctext)
}
@@ -151,39 +151,38 @@ pub async fn try_decrypt(
}
/* possibly perform decryption */
let mut private_keyring = Keyring::default();
let mut public_keyring_for_validate = Keyring::default();
let mut out_mail = None;
let mut signatures = HashSet::default();
let self_addr = context.get_config(Config::ConfiguredAddr).await;
if let Some(self_addr) = self_addr {
if private_keyring
.load_self_private_for_decrypting(context, self_addr, &context.sql)
.await
if let Ok(private_keyring) =
Keyring::load_self_private_for_decrypting(context, self_addr).await
{
if peerstate.as_ref().map(|p| p.last_seen).unwrap_or_else(|| 0) == 0 {
peerstate = Peerstate::from_addr(&context, &from).await;
}
if let Some(ref peerstate) = peerstate {
if let Some(peerstate) = peerstate {
if peerstate.degrade_event.is_some() {
handle_degrade_event(context, &peerstate).await?;
}
if let Some(ref key) = peerstate.gossip_key {
public_keyring_for_validate.add_ref(key);
if let Some(key) = peerstate.gossip_key {
public_keyring_for_validate.add(key);
}
if let Some(ref key) = peerstate.public_key {
public_keyring_for_validate.add_ref(key);
if let Some(key) = peerstate.public_key {
public_keyring_for_validate.add(key);
}
}
out_mail = decrypt_if_autocrypt_message(
context,
mail,
&private_keyring,
&public_keyring_for_validate,
private_keyring,
public_keyring_for_validate,
&mut signatures,
)?;
)
.await?;
}
}
Ok((out_mail, signatures))
@@ -216,11 +215,11 @@ fn get_autocrypt_mime<'a, 'b>(mail: &'a ParsedMail<'b>) -> Result<&'a ParsedMail
Ok(&mail.subparts[1])
}
fn decrypt_if_autocrypt_message<'a>(
async fn decrypt_if_autocrypt_message<'a>(
context: &Context,
mail: &ParsedMail<'a>,
private_keyring: &Keyring,
public_keyring_for_validate: &Keyring,
private_keyring: Keyring,
public_keyring_for_validate: Keyring,
ret_valid_signatures: &mut HashSet<String>,
) -> Result<Option<Vec<u8>>> {
// The returned bool is true if we detected an Autocrypt-encrypted
@@ -240,20 +239,19 @@ fn decrypt_if_autocrypt_message<'a>(
info!(context, "Detected Autocrypt-mime message");
decrypt_part(
context,
encrypted_data_part,
private_keyring,
public_keyring_for_validate,
ret_valid_signatures,
)
.await
}
/// Returns Ok(None) if nothing encrypted was found.
fn decrypt_part(
_context: &Context,
async fn decrypt_part(
mail: &ParsedMail<'_>,
private_keyring: &Keyring,
public_keyring_for_validate: &Keyring,
private_keyring: Keyring,
public_keyring_for_validate: Keyring,
ret_valid_signatures: &mut HashSet<String>,
) -> Result<Option<Vec<u8>>> {
let data = mail.get_body_raw()?;
@@ -263,11 +261,12 @@ fn decrypt_part(
ensure!(ret_valid_signatures.is_empty(), "corrupt signatures");
let plain = pgp::pk_decrypt(
&data,
&private_keyring,
&public_keyring_for_validate,
data,
private_keyring,
public_keyring_for_validate,
Some(ret_valid_signatures),
)?;
)
.await?;
ensure!(!ret_valid_signatures.is_empty(), "no valid signatures");
return Ok(Some(plain));