diff --git a/src/e2ee.rs b/src/e2ee.rs index d5ad5a8b1..b776cb717 100644 --- a/src/e2ee.rs +++ b/src/e2ee.rs @@ -2,7 +2,7 @@ use std::collections::HashSet; -use anyhow::{bail, ensure, format_err, Result}; +use anyhow::{bail, format_err, Result}; use mailparse::ParsedMail; use num_traits::FromPrimitive; @@ -179,7 +179,6 @@ pub async fn try_decrypt( // Possibly perform decryption let private_keyring: Keyring = Keyring::new_self(context).await?; let mut public_keyring_for_validate: Keyring = Keyring::new(); - let mut signatures = HashSet::default(); if let Some(ref mut peerstate) = peerstate { peerstate @@ -192,14 +191,17 @@ pub async fn try_decrypt( } } - let out_mail = decrypt_if_autocrypt_message( + let (out_mail, signatures) = match decrypt_if_autocrypt_message( context, mail, private_keyring, public_keyring_for_validate, - &mut signatures, ) - .await?; + .await? + { + Some((out_mail, signatures)) => (Some(out_mail), signatures), + None => (None, Default::default()), + }; if let Some(mut peerstate) = peerstate { // If message is not encrypted and it is not a read receipt, degrade encryption. @@ -275,8 +277,7 @@ async fn decrypt_if_autocrypt_message( mail: &ParsedMail<'_>, private_keyring: Keyring, public_keyring_for_validate: Keyring, - ret_valid_signatures: &mut HashSet, -) -> Result>> { +) -> Result, HashSet)>> { let encrypted_data_part = match get_autocrypt_mime(mail).or_else(|| get_mixed_up_mime(mail)) { None => { // not an autocrypt mime message, abort and ignore @@ -290,7 +291,6 @@ async fn decrypt_if_autocrypt_message( encrypted_data_part, private_keyring, public_keyring_for_validate, - ret_valid_signatures, ) .await } @@ -300,26 +300,17 @@ async fn decrypt_part( mail: &ParsedMail<'_>, private_keyring: Keyring, public_keyring_for_validate: Keyring, - ret_valid_signatures: &mut HashSet, -) -> Result>> { +) -> Result, HashSet)>> { let data = mail.get_body_raw()?; if has_decrypted_pgp_armor(&data) { - // we should only have one decryption happening - ensure!(ret_valid_signatures.is_empty(), "corrupt signatures"); - - let plain = pgp::pk_decrypt( - data, - private_keyring, - public_keyring_for_validate, - Some(ret_valid_signatures), - ) - .await?; + let (plain, ret_valid_signatures) = + pgp::pk_decrypt(data, private_keyring, public_keyring_for_validate).await?; // If the message was wrongly or not signed, still return the plain text. // The caller has to check the signatures then. - return Ok(Some(plain)); + return Ok(Some((plain, ret_valid_signatures))); } Ok(None) diff --git a/src/pgp.rs b/src/pgp.rs index 820dff34a..c5ac98862 100644 --- a/src/pgp.rs +++ b/src/pgp.rs @@ -277,7 +277,7 @@ pub async fn pk_encrypt( /// Receiver private keys are provided in /// `private_keys_for_decryption`. /// -/// If `ret_signature_fingerprints` is not `None`, stores fingerprints +/// Returns decrypted message and fingerprints /// of all keys from the `public_keys_for_validation` keyring that /// have valid signatures there. #[allow(clippy::implicit_hasher)] @@ -285,8 +285,9 @@ pub async fn pk_decrypt( ctext: Vec, private_keys_for_decryption: Keyring, public_keys_for_validation: Keyring, - ret_signature_fingerprints: Option<&mut HashSet>, -) -> Result> { +) -> Result<(Vec, HashSet)> { + let mut ret_signature_fingerprints: HashSet = Default::default(); + let msgs = async_std::task::spawn_blocking(move || { let cursor = Cursor::new(ctext); let (msg, _) = Message::from_armor_single(cursor)?; @@ -308,28 +309,26 @@ pub async fn pk_decrypt( None => bail!("The decrypted message is empty"), }; - if let Some(ret_signature_fingerprints) = ret_signature_fingerprints { - if !public_keys_for_validation.is_empty() { - let fingerprints = async_std::task::spawn_blocking(move || { - let pkeys = public_keys_for_validation.keys(); + if !public_keys_for_validation.is_empty() { + let fingerprints = async_std::task::spawn_blocking(move || { + let pkeys = public_keys_for_validation.keys(); - let mut fingerprints: Vec = Vec::new(); - if let signed_msg @ pgp::composed::Message::Signed { .. } = msg { - for pkey in pkeys { - if signed_msg.verify(&pkey.primary_key).is_ok() { - let fp = DcKey::fingerprint(pkey); - fingerprints.push(fp); - } + let mut fingerprints: Vec = Vec::new(); + if let signed_msg @ pgp::composed::Message::Signed { .. } = msg { + for pkey in pkeys { + if signed_msg.verify(&pkey.primary_key).is_ok() { + let fp = DcKey::fingerprint(pkey); + fingerprints.push(fp); } } - fingerprints - }) - .await; + } + fingerprints + }) + .await; - ret_signature_fingerprints.extend(fingerprints); - } + ret_signature_fingerprints.extend(fingerprints); } - Ok(content) + Ok((content, ret_signature_fingerprints)) } else { bail!("No valid messages found"); } @@ -492,12 +491,10 @@ mod tests { decrypt_keyring.add(KEYS.alice_secret.clone()); let mut sig_check_keyring: Keyring = Keyring::new(); sig_check_keyring.add(KEYS.alice_public.clone()); - let mut valid_signatures: HashSet = Default::default(); - let plain = pk_decrypt( + let (plain, valid_signatures) = pk_decrypt( CTEXT_SIGNED.as_bytes().to_vec(), decrypt_keyring, - sig_check_keyring, - Some(&mut valid_signatures), + sig_check_keyring ) .await .map_err(|err| println!("{:?}", err)) @@ -510,12 +507,10 @@ mod tests { decrypt_keyring.add(KEYS.bob_secret.clone()); let mut sig_check_keyring = Keyring::new(); sig_check_keyring.add(KEYS.alice_public.clone()); - let mut valid_signatures: HashSet = Default::default(); - let plain = pk_decrypt( + let (plain, valid_signatures) = pk_decrypt( CTEXT_SIGNED.as_bytes().to_vec(), decrypt_keyring, - sig_check_keyring, - Some(&mut valid_signatures), + sig_check_keyring ) .await .map_err(|err| println!("{:?}", err)) @@ -529,15 +524,10 @@ mod tests { let mut keyring = Keyring::new(); keyring.add(KEYS.alice_secret.clone()); let empty_keyring = Keyring::new(); - let mut valid_signatures: HashSet = Default::default(); - let plain = pk_decrypt( - CTEXT_SIGNED.as_bytes().to_vec(), - keyring, - empty_keyring, - Some(&mut valid_signatures), - ) - .await - .unwrap(); + let (plain, valid_signatures) = + pk_decrypt(CTEXT_SIGNED.as_bytes().to_vec(), keyring, empty_keyring) + .await + .unwrap(); assert_eq!(plain, CLEARTEXT); assert_eq!(valid_signatures.len(), 0); } @@ -549,12 +539,10 @@ mod tests { decrypt_keyring.add(KEYS.bob_secret.clone()); let mut sig_check_keyring = Keyring::new(); sig_check_keyring.add(KEYS.bob_public.clone()); - let mut valid_signatures: HashSet = Default::default(); - let plain = pk_decrypt( + let (plain, valid_signatures) = pk_decrypt( CTEXT_SIGNED.as_bytes().to_vec(), decrypt_keyring, sig_check_keyring, - Some(&mut valid_signatures), ) .await .unwrap(); @@ -567,34 +555,14 @@ mod tests { let mut decrypt_keyring = Keyring::new(); decrypt_keyring.add(KEYS.bob_secret.clone()); let sig_check_keyring = Keyring::new(); - let mut valid_signatures: HashSet = Default::default(); - let plain = pk_decrypt( + let (plain, valid_signatures) = pk_decrypt( CTEXT_UNSIGNED.as_bytes().to_vec(), decrypt_keyring, sig_check_keyring, - Some(&mut valid_signatures), ) .await .unwrap(); assert_eq!(plain, CLEARTEXT); assert_eq!(valid_signatures.len(), 0); } - - #[async_std::test] - async fn test_decrypt_signed_no_sigret() { - // Check decrypting signed cyphertext without providing the HashSet for signatures. - let mut decrypt_keyring = Keyring::new(); - decrypt_keyring.add(KEYS.bob_secret.clone()); - let mut sig_check_keyring = Keyring::new(); - sig_check_keyring.add(KEYS.alice_public.clone()); - let plain = pk_decrypt( - CTEXT_SIGNED.as_bytes().to_vec(), - decrypt_keyring, - sig_check_keyring, - None, - ) - .await - .unwrap(); - assert_eq!(plain, CLEARTEXT); - } }