diff options
-rw-r--r-- | guide/src/chapter_02.md | 20 | ||||
-rw-r--r-- | ipc/examples/gpg-agent-decrypt.rs | 4 | ||||
-rw-r--r-- | ipc/tests/gpg-agent.rs | 6 | ||||
-rw-r--r-- | openpgp-ffi/src/packet/pkesk.rs | 6 | ||||
-rw-r--r-- | openpgp/examples/decrypt-with.rs | 5 | ||||
-rw-r--r-- | openpgp/examples/generate-encrypt-decrypt.rs | 5 | ||||
-rw-r--r-- | openpgp/src/packet/pkesk.rs | 14 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 8 | ||||
-rw-r--r-- | openpgp/src/policy.rs | 5 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 5 | ||||
-rw-r--r-- | sop/src/main.rs | 24 | ||||
-rw-r--r-- | tool/src/commands/decrypt.rs | 30 |
12 files changed, 80 insertions, 52 deletions
diff --git a/guide/src/chapter_02.md b/guide/src/chapter_02.md index 64ba07cb..91b01513 100644 --- a/guide/src/chapter_02.md +++ b/guide/src/chapter_02.md @@ -137,10 +137,11 @@ fn main() { # let mut pair = key.into_keypair().unwrap(); # # pkesks[0].decrypt(&mut pair, sym_algo) -# .and_then(|(algo, session_key)| decrypt(algo, &session_key)) -# .map(|_| None) +# .and_then(|(algo, session_key)| decrypt(algo, &session_key).ok()); +# # // XXX: In production code, return the Fingerprint of the # // recipient's Cert here +# Ok(None) # } # } ``` @@ -282,10 +283,11 @@ fn generate() -> openpgp::Result<openpgp::Cert> { # let mut pair = key.into_keypair().unwrap(); # # pkesks[0].decrypt(&mut pair, sym_algo) -# .and_then(|(algo, session_key)| decrypt(algo, &session_key)) -# .map(|_| None) +# .and_then(|(algo, session_key)| decrypt(algo, &session_key).ok()); +# # // XXX: In production code, return the Fingerprint of the # // recipient's Cert here +# Ok(None) # } # } ``` @@ -427,10 +429,11 @@ fn encrypt(policy: &dyn Policy, # let mut pair = key.into_keypair().unwrap(); # # pkesks[0].decrypt(&mut pair, sym_algo) -# .and_then(|(algo, session_key)| decrypt(algo, &session_key)) -# .map(|_| None) +# .and_then(|(algo, session_key)| decrypt(algo, &session_key).ok()); +# # // XXX: In production code, return the Fingerprint of the # // recipient's Cert here +# Ok(None) # } # } ``` @@ -586,10 +589,11 @@ impl<'a> DecryptionHelper for Helper<'a> { let mut pair = key.into_keypair().unwrap(); pkesks[0].decrypt(&mut pair, sym_algo) - .and_then(|(algo, session_key)| decrypt(algo, &session_key)) - .map(|_| None) + .and_then(|(algo, session_key)| decrypt(algo, &session_key).ok()); + // XXX: In production code, return the Fingerprint of the // recipient's Cert here + Ok(None) } } ``` diff --git a/ipc/examples/gpg-agent-decrypt.rs b/ipc/examples/gpg-agent-decrypt.rs index 254aebdd..b580b353 100644 --- a/ipc/examples/gpg-agent-decrypt.rs +++ b/ipc/examples/gpg-agent-decrypt.rs @@ -106,8 +106,8 @@ impl<'a> DecryptionHelper for Helper<'a> { for pkesk in pkesks { if let Some(key) = self.keys.get(pkesk.recipient()) { let mut pair = KeyPair::new(self.ctx, key)?; - if let Ok(_) = pkesk.decrypt(&mut pair, sym_algo) - .and_then(|(algo, session_key)| decrypt(algo, &session_key)) + if let Some(_) = pkesk.decrypt(&mut pair, sym_algo) + .and_then(|(algo, session_key)| decrypt(algo, &session_key).ok()) { break; } diff --git a/ipc/tests/gpg-agent.rs b/ipc/tests/gpg-agent.rs index 9b0e2fc9..606dd683 100644 --- a/ipc/tests/gpg-agent.rs +++ b/ipc/tests/gpg-agent.rs @@ -287,10 +287,12 @@ fn decrypt() -> openpgp::Result<()> { .unwrap(); pkesks[0].decrypt(&mut keypair, sym_algo) - .and_then(|(algo, session_key)| decrypt(algo, &session_key)) - .map(|_| None) + .and_then( + |(algo, session_key)| decrypt(algo, &session_key).ok()); + // XXX: In production code, return the Fingerprint of the // recipient's Cert here + Ok(None) } } } diff --git a/openpgp-ffi/src/packet/pkesk.rs b/openpgp-ffi/src/packet/pkesk.rs index 084505ff..bbecddb0 100644 --- a/openpgp-ffi/src/packet/pkesk.rs +++ b/openpgp-ffi/src/packet/pkesk.rs @@ -48,7 +48,7 @@ pub extern "C" fn pgp_pkesk_decrypt(errp: Option<&mut *mut crate::error::Error>, { Ok(mut keypair) => { match pkesk.decrypt(&mut keypair, None /* XXX */) { - Ok((a, k)) => { + Some((a, k)) => { *algo = a.into(); if !key.is_null() && *key_len >= k.len() { unsafe { @@ -60,7 +60,9 @@ pub extern "C" fn pgp_pkesk_decrypt(errp: Option<&mut *mut crate::error::Error>, *key_len = k.len(); Status::Success }, - Err(e) => ffi_try_status!(Err::<(), anyhow::Error>(e)), + None => ffi_try_status!(Err::<(), anyhow::Error>( + openpgp::Error::InvalidSessionKey( + "Decryption failed".into()).into())), } }, Err(e) => { diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index 09f44794..3a5723bc 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -89,8 +89,9 @@ impl DecryptionHelper for Helper { // Try each PKESK until we succeed. for pkesk in pkesks { if let Some(pair) = self.keys.get_mut(pkesk.recipient()) { - if let Ok(_) = pkesk.decrypt(pair, sym_algo) - .and_then(|(algo, session_key)| decrypt(algo, &session_key)) + if let Some(_) = pkesk.decrypt(pair, sym_algo) + .and_then(|(algo, session_key)| decrypt(algo, &session_key) + .ok()) { break; } diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs index 3960b22e..c7e2e38d 100644 --- a/openpgp/examples/generate-encrypt-decrypt.rs +++ b/openpgp/examples/generate-encrypt-decrypt.rs @@ -128,9 +128,10 @@ impl<'a> DecryptionHelper for Helper<'a> { let mut pair = key.into_keypair().unwrap(); pkesks[0].decrypt(&mut pair, sym_algo) - .and_then(|(algo, session_key)| decrypt(algo, &session_key)) - .map(|_| None) + .and_then(|(algo, session_key)| decrypt(algo, &session_key).ok()); + // XXX: In production code, return the Fingerprint of the // recipient's Cert here + Ok(None) } } diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs index 0724e50f..f92c596e 100644 --- a/openpgp/src/packet/pkesk.rs +++ b/openpgp/src/packet/pkesk.rs @@ -128,8 +128,22 @@ impl PKESK3 { /// /// Returns the session key and symmetric algorithm used to /// encrypt the following payload. + /// + /// Returns `None` on errors. This prevents leaking information + /// to an attacker, which could lead to compromise of secret key + /// material with certain algorithms (RSA). See [Section 14 of + /// RFC 4880]. + /// + /// [Section 14 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-14 pub fn decrypt(&self, decryptor: &mut dyn Decryptor, sym_algo_hint: Option<SymmetricAlgorithm>) + -> Option<(SymmetricAlgorithm, SessionKey)> + { + self.decrypt_insecure(decryptor, sym_algo_hint).ok() + } + + fn decrypt_insecure(&self, decryptor: &mut dyn Decryptor, + sym_algo_hint: Option<SymmetricAlgorithm>) -> Result<(SymmetricAlgorithm, SessionKey)> { let plaintext_len = if let Some(s) = sym_algo_hint { diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index bf4fc4bc..69513432 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -1390,8 +1390,8 @@ pub trait DecryptionHelper { /// if ! key.secret().is_encrypted() { /// let mut keypair = key.clone().into_keypair()?; /// if pkesk.decrypt(&mut keypair, sym_algo) - /// .and_then(|(algo, sk)| decrypt(algo, &sk)) - /// .is_ok() + /// .and_then(|(algo, sk)| decrypt(algo, &sk).ok()) + /// .is_some() /// { /// return Ok(Some(fp)); /// } @@ -1407,8 +1407,8 @@ pub trait DecryptionHelper { /// if ! key.secret().is_encrypted() { /// let mut keypair = key.clone().into_keypair()?; /// if pkesk.decrypt(&mut keypair, sym_algo) - /// .and_then(|(algo, sk)| decrypt(algo, &sk)) - /// .is_ok() + /// .and_then(|(algo, sk)| decrypt(algo, &sk).ok()) + /// .is_some() /// { /// return Ok(Some(fp)); /// } diff --git a/openpgp/src/policy.rs b/openpgp/src/policy.rs index 259099d2..fe266b79 100644 --- a/openpgp/src/policy.rs +++ b/openpgp/src/policy.rs @@ -1819,8 +1819,9 @@ mod test { .for_transport_encryption().secret().nth(0).unwrap() .key().clone().into_keypair()?; pkesks[0].decrypt(&mut pair, algo) - .and_then(|(algo, session_key)| decrypt(algo, &session_key)) - .map(|_| None) + .and_then(|(algo, session_key)| + decrypt(algo, &session_key).ok()); + Ok(None) } } diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index 357fa871..7228bcd5 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -3065,8 +3065,9 @@ mod test { .clone().parts_into_secret().unwrap() .into_keypair().unwrap(); pkesks[0].decrypt(&mut keypair, sym_algo) - .and_then(|(algo, session_key)| decrypt(algo, &session_key)) - .map(|_| None) + .and_then(|(algo, session_key)| + decrypt(algo, &session_key).ok()); + Ok(None) } } diff --git a/sop/src/main.rs b/sop/src/main.rs index f8abce91..5d707b8c 100644 --- a/sop/src/main.rs +++ b/sop/src/main.rs @@ -669,18 +669,18 @@ impl<'a> Helper<'a> { algo: Option<SymmetricAlgorithm>, keypair: &mut dyn crypto::Decryptor, decrypt: &mut D) - -> openpgp::Result<(SymmetricAlgorithm, - SessionKey, - Option<Fingerprint>)> + -> Option<(SymmetricAlgorithm, + SessionKey, + Option<Fingerprint>)> where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()> { let keyid = keypair.public().fingerprint().into(); let (algo, sk) = pkesk.decrypt(keypair, algo) .and_then(|(algo, sk)| { - decrypt(algo, &sk)?; Ok((algo, sk)) + decrypt(algo, &sk).ok()?; Some((algo, sk)) })?; - Ok((algo, sk, self.identities.get(&keyid).map(|fp| fp.clone()))) + Some((algo, sk, self.identities.get(&keyid).map(|fp| fp.clone()))) } /// Dumps the session key. @@ -726,9 +726,10 @@ impl<'a> DecryptionHelper for Helper<'a> { let keyid = pkesk.recipient(); if let Some(key) = self.secret_keys.get(&keyid) { if ! key.secret().is_encrypted() { - if let Ok((algo, sk, fp)) = key.clone().into_keypair() - .and_then(|mut k| - self.try_decrypt(pkesk, algo, &mut k, &mut decrypt)) + if let Some((algo, sk, fp)) = + key.clone().into_keypair().ok().and_then(|mut k| { + self.try_decrypt(pkesk, algo, &mut k, &mut decrypt) + }) { self.dump_session_key(algo, &sk)?; return Ok(fp); @@ -743,9 +744,10 @@ impl<'a> DecryptionHelper for Helper<'a> { for pkesk in pkesks.iter().filter(|p| p.recipient().is_wildcard()) { for key in self.secret_keys.values() { if ! key.secret().is_encrypted() { - if let Ok((algo, sk, fp)) = key.clone().into_keypair() - .and_then(|mut k| - self.try_decrypt(pkesk, algo, &mut k, &mut decrypt)) + if let Some((algo, sk, fp)) = + key.clone().into_keypair().ok().and_then(|mut k| { + self.try_decrypt(pkesk, algo, &mut k, &mut decrypt) + }) { self.dump_session_key(algo, &sk)?; return Ok(fp); diff --git a/tool/src/commands/decrypt.rs b/tool/src/commands/decrypt.rs index 9e951af4..ea48eb0b 100644 --- a/tool/src/commands/decrypt.rs +++ b/tool/src/commands/decrypt.rs @@ -89,26 +89,22 @@ impl<'a> Helper<'a> { sym_algo: Option<SymmetricAlgorithm>, keypair: &mut dyn crypto::Decryptor, decrypt: &mut D) - -> openpgp::Result<Option<Fingerprint>> + -> Option<Option<Fingerprint>> where D: FnMut(SymmetricAlgorithm, &SessionKey) -> openpgp::Result<()> { let keyid = keypair.public().fingerprint().into(); match pkesk.decrypt(keypair, sym_algo) .and_then(|(algo, sk)| { - decrypt(algo, &sk)?; Ok(sk) + decrypt(algo, &sk).ok()?; Some(sk) }) { - Ok(sk) => { + Some(sk) => { if self.dump_session_key { eprintln!("Session key: {}", hex::encode(&sk)); } - Ok(self.key_identities.get(&keyid).map(|fp| fp.clone())) - }, - Err(e) => { - eprintln!("Decryption using {} failed:\n {}", - self.key_hints.get(&keyid).unwrap(), e); - Err(e) + Some(self.key_identities.get(&keyid).map(|fp| fp.clone())) }, + None => None, } } } @@ -144,7 +140,7 @@ impl<'a> DecryptionHelper for Helper<'a> { let keyid = pkesk.recipient(); if let Some(key) = self.secret_keys.get(&keyid) { if ! key.secret().is_encrypted() { - if let Ok(fp) = key.clone().into_keypair() + if let Some(fp) = key.clone().into_keypair().ok() .and_then(|mut k| self.try_decrypt(pkesk, sym_algo, &mut k, &mut decrypt)) { @@ -183,8 +179,10 @@ impl<'a> DecryptionHelper for Helper<'a> { } }; - if let Ok(fp) = self.try_decrypt(pkesk, sym_algo, &mut keypair, - &mut decrypt) { + if let Some(fp) = + self.try_decrypt(pkesk, sym_algo, &mut keypair, + &mut decrypt) + { return Ok(fp); } } @@ -196,7 +194,7 @@ impl<'a> DecryptionHelper for Helper<'a> { for pkesk in pkesks.iter().filter(|p| p.recipient().is_wildcard()) { for key in self.secret_keys.values() { if ! key.secret().is_encrypted() { - if let Ok(fp) = key.clone().into_keypair() + if let Some(fp) = key.clone().into_keypair().ok() .and_then(|mut k| self.try_decrypt(pkesk, sym_algo, &mut k, &mut decrypt)) { @@ -240,8 +238,10 @@ impl<'a> DecryptionHelper for Helper<'a> { } }; - if let Ok(fp) = self.try_decrypt(pkesk, sym_algo, &mut keypair, - &mut decrypt) { + if let Some(fp) = + self.try_decrypt(pkesk, sym_algo, &mut keypair, + &mut decrypt) + { return Ok(fp); } } |