summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2023-04-25 18:35:48 +0200
committerJustus Winter <justus@sequoia-pgp.org>2023-06-26 13:36:39 +0200
commit743288ca7a998211b34064a57b0215a2ed337902 (patch)
treec9e1a46c85624b22d90254c459e85862a8aa656c
parent1fc751e6dfb95fd26923a7612b3d2f3a4a57eb22 (diff)
wip pkeskv6
-rw-r--r--openpgp/examples/decrypt-with.rs4
-rw-r--r--openpgp/examples/generate-encrypt-decrypt.rs2
-rw-r--r--openpgp/examples/reply-encrypted.rs10
-rw-r--r--openpgp/src/keyhandle.rs10
-rw-r--r--openpgp/src/packet/mod.rs82
-rw-r--r--openpgp/src/packet/pkesk.rs9
-rw-r--r--openpgp/src/packet/pkesk/v6.rs189
-rw-r--r--openpgp/src/packet/prelude.rs5
-rw-r--r--openpgp/src/packet/skesk.rs11
-rw-r--r--openpgp/src/parse.rs95
-rw-r--r--openpgp/src/parse/stream.rs46
-rw-r--r--openpgp/src/policy.rs8
-rw-r--r--openpgp/src/serialize.rs59
-rw-r--r--openpgp/src/serialize/stream.rs40
14 files changed, 486 insertions, 84 deletions
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs
index 20382d3a..c5cfe17b 100644
--- a/openpgp/examples/decrypt-with.rs
+++ b/openpgp/examples/decrypt-with.rs
@@ -91,12 +91,12 @@ impl DecryptionHelper for Helper {
sym_algo: Option<SymmetricAlgorithm>,
mut decrypt: D)
-> openpgp::Result<Option<openpgp::Fingerprint>>
- where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
+ where D: FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool
{
// Try each PKESK until we succeed.
let mut recipient = None;
for pkesk in pkesks {
- if let Some((fp, pair)) = self.keys.get_mut(pkesk.recipient()) {
+ if let Some((fp, pair)) = self.keys.get_mut(&KeyID::from(pkesk.recipient())) {
if pkesk.decrypt(pair, sym_algo)
.map(|(algo, session_key)| decrypt(algo, &session_key))
.unwrap_or(false)
diff --git a/openpgp/examples/generate-encrypt-decrypt.rs b/openpgp/examples/generate-encrypt-decrypt.rs
index bd8e1dfa..e080c423 100644
--- a/openpgp/examples/generate-encrypt-decrypt.rs
+++ b/openpgp/examples/generate-encrypt-decrypt.rs
@@ -121,7 +121,7 @@ impl<'a> DecryptionHelper for Helper<'a> {
sym_algo: Option<SymmetricAlgorithm>,
mut decrypt: D)
-> openpgp::Result<Option<openpgp::Fingerprint>>
- where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
+ where D: FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool
{
let key = self.secret.keys().unencrypted_secret()
.with_policy(self.policy, None)
diff --git a/openpgp/examples/reply-encrypted.rs b/openpgp/examples/reply-encrypted.rs
index b0d521c5..0f6a09ee 100644
--- a/openpgp/examples/reply-encrypted.rs
+++ b/openpgp/examples/reply-encrypted.rs
@@ -88,7 +88,7 @@ pub fn main() -> openpgp::Result<()> {
.context("Decryption failed")?;
let (algo, sk, pkesks) = decryptor.into_helper().recycling_bin.unwrap();
- eprintln!("- Reusing ({}, {}) with {} PKESK packets",
+ eprintln!("- Reusing ({:?}, {}) with {} PKESK packets",
algo, openpgp::fmt::hex::encode(&sk), pkesks.len());
// Compose a writer stack corresponding to the output format and
@@ -105,7 +105,7 @@ pub fn main() -> openpgp::Result<()> {
}
// We want to encrypt a literal data packet.
- let message = Encryptor::with_session_key(message, algo, sk)?
+ let message = Encryptor::with_session_key(message, algo.expect("XXX seipdv2"), sk)?
.build().context("Failed to create encryptor")?;
let mut message = LiteralWriter::new(message).build()
@@ -128,7 +128,7 @@ pub fn main() -> openpgp::Result<()> {
/// verification policy.
struct Helper {
keys: HashMap<KeyID, (Fingerprint, KeyPair)>,
- recycling_bin: Option<(SymmetricAlgorithm, SessionKey, Vec<PKESK>)>,
+ recycling_bin: Option<(Option<SymmetricAlgorithm>, SessionKey, Vec<PKESK>)>,
}
impl Helper {
@@ -161,13 +161,13 @@ impl DecryptionHelper for Helper {
sym_algo: Option<SymmetricAlgorithm>,
mut decrypt: D)
-> openpgp::Result<Option<openpgp::Fingerprint>>
- where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
+ where D: FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool
{
// Try each PKESK until we succeed.
let mut recipient = None;
let mut encryption_context = None;
for pkesk in pkesks {
- if let Some((fp, pair)) = self.keys.get_mut(pkesk.recipient()) {
+ if let Some((fp, pair)) = self.keys.get_mut(&KeyID::from(pkesk.recipient())) {
if pkesk.decrypt(pair, sym_algo)
.map(|(algo, session_key)| {
let success = decrypt(algo, &session_key);
diff --git a/openpgp/src/keyhandle.rs b/openpgp/src/keyhandle.rs
index 9ce528ba..092a0aa2 100644
--- a/openpgp/src/keyhandle.rs
+++ b/openpgp/src/keyhandle.rs
@@ -126,6 +126,16 @@ impl From<KeyHandle> for KeyID {
}
}
+impl From<Option<KeyHandle>> for KeyID {
+ fn from(i: Option<KeyHandle>) -> Self {
+ match i {
+ Some(KeyHandle::Fingerprint(i)) => i.into(),
+ Some(KeyHandle::KeyID(i)) => i,
+ None => KeyID::wildcard(),
+ }
+ }
+}
+
impl From<&KeyHandle> for KeyID {
fn from(i: &KeyHandle) -> Self {
match i {
diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs
index c004155a..8e0be2c7 100644
--- a/openpgp/src/packet/mod.rs
+++ b/openpgp/src/packet/mod.rs
@@ -170,11 +170,14 @@ pub mod prelude;
use crate::{
crypto::{
+ Decryptor,
KeyPair,
Password,
+ SessionKey,
},
types::{
SignatureType,
+ SymmetricAlgorithm,
PublicKeyAlgorithm,
HashAlgorithm,
},
@@ -474,7 +477,8 @@ impl Deref for Packet {
Packet::UserAttribute(ref packet) => &packet.common,
Packet::Literal(ref packet) => &packet.common,
Packet::CompressedData(ref packet) => &packet.common,
- Packet::PKESK(ref packet) => &packet.common,
+ Packet::PKESK(PKESK::V3(packet)) => &packet.common,
+ Packet::PKESK(PKESK::V6(packet)) => &packet.common,
Packet::SKESK(SKESK::V4(ref packet)) => &packet.common,
Packet::SKESK(SKESK::V6(ref packet)) => &packet.skesk4.common,
Packet::SEIP(SEIP::V1(packet)) => &packet.common,
@@ -503,7 +507,8 @@ impl DerefMut for Packet {
Packet::UserAttribute(ref mut packet) => &mut packet.common,
Packet::Literal(ref mut packet) => &mut packet.common,
Packet::CompressedData(ref mut packet) => &mut packet.common,
- Packet::PKESK(ref mut packet) => &mut packet.common,
+ Packet::PKESK(PKESK::V3(packet)) => &mut packet.common,
+ Packet::PKESK(PKESK::V6(packet)) => &mut packet.common,
Packet::SKESK(SKESK::V4(ref mut packet)) => &mut packet.common,
Packet::SKESK(SKESK::V6(ref mut packet)) => &mut packet.skesk4.common,
Packet::SEIP(SEIP::V1(packet)) => &mut packet.common,
@@ -1186,6 +1191,8 @@ impl From<OnePassSig> for Packet {
pub enum PKESK {
/// PKESK packet version 3.
V3(self::pkesk::PKESK3),
+ /// PKESK packet version 6.
+ V6(self::pkesk::PKESK6),
}
assert_send_and_sync!(PKESK);
@@ -1194,34 +1201,73 @@ impl PKESK {
pub fn version(&self) -> u8 {
match self {
PKESK::V3(_) => 3,
+ PKESK::V6(_) => 6,
}
}
-}
-impl From<PKESK> for Packet {
- fn from(p: PKESK) -> Self {
- Packet::PKESK(p)
+ /// Gets the recipient.
+ pub fn recipient(&self) -> Option<KeyHandle> {
+ match self {
+ PKESK::V3(p) => {
+ let id = p.recipient();
+ if id.is_wildcard() {
+ None
+ } else {
+ Some(id.into())
+ }
+ },
+ PKESK::V6(p) => p.recipient().map(Into::into),
+ }
}
-}
-
-// Trivial forwarder for singleton enum.
-impl Deref for PKESK {
- type Target = self::pkesk::PKESK3;
- fn deref(&self) -> &Self::Target {
+ /// Gets the public key algorithm.
+ pub fn pk_algo(&self) -> PublicKeyAlgorithm {
match self {
- PKESK::V3(ref p) => p,
+ PKESK::V3(p) => p.pk_algo(),
+ PKESK::V6(p) => p.pk_algo(),
}
}
-}
-// Trivial forwarder for singleton enum.
-impl DerefMut for PKESK {
- fn deref_mut(&mut self) -> &mut Self::Target {
+ /// Gets the encrypted session key.
+ pub fn esk(&self) -> &crate::crypto::mpi::Ciphertext {
match self {
- PKESK::V3(ref mut p) => p,
+ PKESK::V3(p) => p.esk(),
+ PKESK::V6(p) => p.esk(),
}
}
+ /// Decrypts the encrypted session key.
+ ///
+ /// If the symmetric algorithm used to encrypt the message is
+ /// known in advance, it should be given as argument. This allows
+ /// us to reduce the side-channel leakage of the decryption
+ /// operation for RSA.
+ ///
+ /// 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<(Option<SymmetricAlgorithm>, SessionKey)>
+ {
+ match self {
+ PKESK::V3(p) => p.decrypt(decryptor, sym_algo_hint)
+ .map(|(s, k)| (Some(s), k)),
+ PKESK::V6(p) => p.decrypt(decryptor, sym_algo_hint)
+ .map(|k| (None, k)),
+ }
+ }
+}
+
+impl From<PKESK> for Packet {
+ fn from(p: PKESK) -> Self {
+ Packet::PKESK(p)
+ }
}
/// Holds a symmetrically encrypted session key.
diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs
index c394e7c8..e4273bb8 100644
--- a/openpgp/src/packet/pkesk.rs
+++ b/openpgp/src/packet/pkesk.rs
@@ -21,6 +21,9 @@ use crate::SymmetricAlgorithm;
use crate::crypto::SessionKey;
use crate::packet;
+mod v6;
+pub use v6::PKESK6;
+
/// Holds an asymmetrically encrypted session key.
///
/// The session key is needed to decrypt the actual ciphertext. See
@@ -207,7 +210,11 @@ impl From<PKESK3> for Packet {
#[cfg(test)]
impl Arbitrary for super::PKESK {
fn arbitrary(g: &mut Gen) -> Self {
- PKESK3::arbitrary(g).into()
+ if bool::arbitrary(g) {
+ PKESK3::arbitrary(g).into()
+ } else {
+ PKESK6::arbitrary(g).into()
+ }
}
}
diff --git a/openpgp/src/packet/pkesk/v6.rs b/openpgp/src/packet/pkesk/v6.rs
new file mode 100644
index 00000000..48ef38e8
--- /dev/null
+++ b/openpgp/src/packet/pkesk/v6.rs
@@ -0,0 +1,189 @@
+//! PublicKey-Encrypted Session Key packets version 6.
+//!
+//! The session key is needed to decrypt the actual ciphertext. See
+//! [Section 5.1 of RFC 4880] for details. XXX fix reference
+//!
+//! [Section 5.1 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.1
+
+#[cfg(test)]
+use quickcheck::{Arbitrary, Gen};
+
+use crate::packet::key;
+use crate::packet::Key;
+use crate::Fingerprint;
+use crate::crypto::Decryptor;
+use crate::crypto::mpi::Ciphertext;
+use crate::Packet;
+use crate::PublicKeyAlgorithm;
+use crate::Result;
+use crate::SymmetricAlgorithm;
+use crate::crypto::SessionKey;
+use crate::packet;
+
+/// Holds an asymmetrically encrypted session key.
+///
+/// The session key is needed to decrypt the actual ciphertext. See
+/// [Section 5.1 of RFC 4880] for details. XXX fix reference
+///
+/// [Section 5.1 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.1
+#[derive(Clone, Debug, PartialEq, Eq, Hash)]
+pub struct PKESK6 {
+ /// CTB header fields.
+ pub(crate) common: packet::Common,
+ /// Fingerprint of the key this is encrypted to.
+ ///
+ /// If the value is `None`, the recipient has not been specified
+ /// by the sender to decrease metadata leakage.
+ recipient: Option<Fingerprint>,
+ /// Public key algorithm used to encrypt the session key.
+ pk_algo: PublicKeyAlgorithm,
+ /// The encrypted session key.
+ esk: Ciphertext,
+}
+
+assert_send_and_sync!(PKESK6);
+
+impl PKESK6 {
+ /// Creates a new PKESK6 packet.
+ pub fn new(recipient: Option<Fingerprint>, pk_algo: PublicKeyAlgorithm,
+ encrypted_session_key: Ciphertext)
+ -> Result<PKESK6> {
+ Ok(PKESK6 {
+ common: Default::default(),
+ recipient,
+ pk_algo,
+ esk: encrypted_session_key,
+ })
+ }
+
+ /// Creates a new PKESK6 packet for the given recipient.
+ ///
+ /// The given symmetric algorithm must match the algorithm that is
+ /// used to encrypt the payload.
+ pub fn for_recipient<P, R>(session_key: &SessionKey,
+ recipient: &Key<P, R>)
+ -> Result<PKESK6>
+ where P: key::KeyParts,
+ R: key::KeyRole,
+ {
+ // XXX: Checksumming for non X25519 and X448 keys..
+ let esk = recipient.encrypt(session_key)?;
+ Ok(PKESK6 {
+ common: Default::default(),
+ recipient: Some(recipient.fingerprint()),
+ pk_algo: recipient.pk_algo(),
+ esk,
+ })
+ }
+
+ /// Gets the recipient.
+ pub fn recipient(&self) -> Option<&Fingerprint> {
+ self.recipient.as_ref()
+ }
+
+ /// Sets the recipient.
+ pub fn set_recipient(&mut self, recipient: Option<Fingerprint>)
+ -> Option<Fingerprint> {
+ std::mem::replace(&mut self.recipient, recipient)
+ }
+
+ /// Gets the public key algorithm.
+ pub fn pk_algo(&self) -> PublicKeyAlgorithm {
+ self.pk_algo
+ }
+
+ /// Sets the public key algorithm.
+ pub fn set_pk_algo(&mut self, algo: PublicKeyAlgorithm)
+ -> PublicKeyAlgorithm {
+ std::mem::replace(&mut self.pk_algo, algo)
+ }
+
+ /// Gets the encrypted session key.
+ pub fn esk(&self) -> &Ciphertext {
+ &self.esk
+ }
+
+ /// Sets the encrypted session key.
+ pub fn set_esk(&mut self, esk: Ciphertext) -> Ciphertext {
+ std::mem::replace(&mut self.esk, esk)
+ }
+
+ /// Decrypts the encrypted session key.
+ ///
+ /// If the symmetric algorithm used to encrypt the message is
+ /// known in advance, it should be given as argument. This allows
+ /// us to reduce the side-channel leakage of the decryption
+ /// operation for RSA.
+ ///
+ /// 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<SessionKey>
+ {
+ self.decrypt_insecure(decryptor, sym_algo_hint).ok()
+ }
+
+ fn decrypt_insecure(&self, decryptor: &mut dyn Decryptor,
+ sym_algo_hint: Option<SymmetricAlgorithm>)
+ -> Result<SessionKey>
+ {
+ // XXX: Checksumming for non X25519 and X448 keys..
+ let plaintext_len = if let Some(s) = sym_algo_hint {
+ Some(s.key_size()? /* + 2 chksum */)
+ } else {
+ None
+ };
+ let plain = decryptor.decrypt(&self.esk, plaintext_len)?;
+ Ok(plain)
+ }
+}
+
+impl From<PKESK6> for packet::PKESK {
+ fn from(p: PKESK6) -> Self {
+ packet::PKESK::V6(p)
+ }
+}
+
+impl From<PKESK6> for Packet {
+ fn from(p: PKESK6) -> Self {
+ Packet::PKESK(p.into())
+ }
+}
+
+#[cfg(test)]
+impl Arbitrary for PKESK6 {
+ fn arbitrary(g: &mut Gen) -> Self {
+ let (ciphertext, pk_algo) = loop {
+ let ciphertext = Ciphertext::arbitrary(g);
+ if let Some(pk_algo) = ciphertext.pk_algo() {
+ break (ciphertext, pk_algo);
+ }
+ };
+
+ PKESK6::new(bool::arbitrary(g).then(|| Fingerprint::arbitrary_v6(g)),
+ pk_algo, ciphertext).unwrap()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::parse::Parse;
+ use crate::serialize::MarshalInto;
+
+ quickcheck! {
+ fn roundtrip(p: PKESK6) -> bool {
+ let q = PKESK6::from_bytes(&p.to_vec().unwrap()).unwrap();
+ assert_eq!(p, q);
+ true
+ }
+ }
+}
diff --git a/openpgp/src/packet/prelude.rs b/openpgp/src/packet/prelude.rs
index bda7a7e2..0e9627d7 100644
--- a/openpgp/src/packet/prelude.rs
+++ b/openpgp/src/packet/prelude.rs
@@ -50,7 +50,10 @@ pub use crate::packet::{
key::SecretKeyMaterial,
one_pass_sig::OnePassSig3,
one_pass_sig::OnePassSig6,
- pkesk::PKESK3,
+ pkesk::{
+ PKESK3,
+ PKESK6,
+ },
seip::{
SEIP1,
SEIP2,
diff --git a/openpgp/src/packet/skesk.rs b/openpgp/src/packet/skesk.rs
index 98075970..4be1a086 100644
--- a/openpgp/src/packet/skesk.rs
+++ b/openpgp/src/packet/skesk.rs
@@ -33,12 +33,13 @@ impl SKESK {
/// tuple of the symmetric cipher to use with the key and the key
/// itself.
pub fn decrypt(&self, password: &Password)
- -> Result<(SymmetricAlgorithm, SessionKey)>
+ -> Result<(Option<SymmetricAlgorithm>, SessionKey)>
{
match self {
- SKESK::V4(ref s) => s.decrypt(password),
+ SKESK::V4(s) => s.decrypt(password)
+ .map(|(algo, sk)| (Some(algo), sk)),
SKESK::V6(ref s) =>
- Ok((SymmetricAlgorithm::Unencrypted, s.decrypt(password)?)),
+ Ok((None, s.decrypt(password)?)),
}
}
}
@@ -637,11 +638,11 @@ mod test {
fn decrypt<D>(&mut self, _: &[PKESK], skesks: &[SKESK],
_: Option<SymmetricAlgorithm>,
mut decrypt: D) -> Result<Option<Fingerprint>>
- where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
+ where D: FnMut(Option<SymmetricAlgorithm>, &SessionKey) -> bool
{
assert_eq!(skesks.len(), 1);
let (cipher, sk) = skesks[0].decrypt(&"password".into())?;
- assert_eq!(cipher, SymmetricAlgorithm::AES256);
+ assert_eq!(cipher, Some(SymmetricAlgorithm::AES256));
let r = decrypt(cipher, &sk);
assert!(r);
Ok(None)
diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs
index 894bfb89..84fa6913 100644
--- a/openpgp/src/parse.rs
+++ b/openpgp/src/parse.rs
@@ -3542,6 +3542,7 @@ impl PKESK {
let version = php_try!(php.parse_u8("version"));
match version {
3 => PKESK3::parse(php),
+ 6 => PKESK6::parse(php),
_ => php.fail("unknown version"),
}
}
@@ -3569,12 +3570,55 @@ impl PKESK3 {
impl<'a> Parse<'a, PKESK3> for PKESK3 {
fn from_reader<R: 'a + Read + Send + Sync>(reader: R) -> Result<Self> {
- PKESK::from_reader(reader).map(|p| match p {
- PKESK::V3(p) => p,
- // XXX: Once we have a second variant.
- //
- // p => Err(Error::InvalidOperation(
- // format!("Not a PKESKv3 packet: {:?}", p)).into()),
+ PKESK::from_reader(reader).and_then(|p| match p {
+ PKESK::V3(p) => Ok(p),
+ p => Err(Error::InvalidOperation(
+ format!("Not a PKESKv3 packet: {:?}", p)).into()),
+ })
+ }
+}
+
+impl PKESK6 {
+ /// Parses the body of an PKESKv6 packet.
+ fn parse(mut php: PacketHeaderParser) -> Result<PacketParser> {
+ make_php_try!(php);
+ let fp_len = php_try!(php.parse_u8("recipient_len"));
+ let fingerprint = if fp_len == 0 {
+ None
+ } else {
+ // Get the version and sanity check the length.
+ let fp_version = php_try!(php.parse_u8("recipient_version"));
+ if let Some(expected_length) = match fp_version {
+ 4 => Some(20),
+ 6 => Some(32),
+ _ => None,
+ } {
+ if fp_len - 1 != expected_length {
+ return php.fail("bad fingerprint length");
+ }
+ }
+ Some(Fingerprint::from_bytes(
+ &php_try!(php.parse_bytes("recipient", (fp_len - 1).into()))))
+ };
+
+ let pk_algo: PublicKeyAlgorithm =
+ php_try!(php.parse_u8("pk_algo")).into();
+ if ! pk_algo.for_encryption() { // XXX
+ return php.fail("not an encryption algorithm");
+ }
+ let mpis = crypto::mpi::Ciphertext::_parse(pk_algo, &mut php)?;
+
+ let pkesk = php_try!(PKESK6::new(fingerprint, pk_algo, mpis));
+ php.ok(pkesk.into())
+ }
+}
+
+impl<'a> Parse<'a, PKESK6> for PKESK6 {
+ fn from_reader<R: 'a + Read + Send + Sync>(reader: R) -> Result<Self> {
+ PKESK::from_reader(reader).and_then(|p| match p {
+ PKESK::V6(p) => Ok(p),
+ p => Err(Error::InvalidOperation(
+ format!("Not a PKESKv6 packet: {:?}", p)).into()),
})
}
}
@@ -5840,8 +5884,18 @@ impl<'a> PacketParser<'a> {
/// OpenPGP].
///
/// [Format Oracles on OpenPGP]: https://www.ssi.gouv.fr/uploads/2015/05/format-Oracles-on-OpenPGP.pdf
- pub fn decrypt(&mut self, algo: SymmetricAlgorithm, key: &SessionKey)
- -> Result<()>
+ pub fn decrypt<A>(&mut self, algo: A, key: &SessionKey)
+ -> Result<()>
+ where
+ A: Into<Option<SymmetricAlgorithm>>,
+ {
+ self.decrypt_(algo.into(), key)
+ }
+
+ fn decrypt_(&mut self,
+ algo: Option<SymmetricAlgorithm>,
+ key: &SessionKey)
+ -> Result<()>
{
let indent = self.recursion_depth();
tracer!(TRACE, "PacketParser::decrypt", indent);
@@ -5855,14 +5909,23 @@ impl<'a> PacketParser<'a> {
"Packet not encrypted.".to_string()).into());
}
- if algo.key_size()? != key.len () {
- return Err(Error::InvalidOperation(
- format!("Bad key size: {} expected: {}",
- key.len(), algo.key_size()?)).into());
- }
-
match self.packet.clone() {
Packet::SEIP(SEIP::V1(_)) => {
+ let algo = if let Some(a) = algo {
+ a
+ } else {
+ return Err(Error::InvalidOperation(
+ "Trying to decrypt a SEIPDv1 packet: \
+ no symmetric algorithm given".into()).into());
+ };
+
+ if algo.key_size()? != key.len () {
+ return Err(Error::InvalidOperation(
+ format!("Bad key size: {} expected: {}",
+ key.len(), algo.key_size()?)).into());
+ }
+
+
// Get the first blocksize plus two bytes and check
// whether we can decrypt them using the provided key.
// Don't actually consume them in case we can't.
@@ -6313,7 +6376,7 @@ mod test {
let key = crate::fmt::from_hex(test.key_hex, false)
.unwrap().into();
- pp.decrypt(test.algo, &key).unwrap();
+ pp.decrypt(Some(test.algo), &key).unwrap();
} else {
panic!("Expected a SEIP/AED packet. Got: {:?}", ppr);
}
@@ -6410,7 +6473,7 @@ mod test {
Packet::SEIP(_) | Packet::AED(_) => {
let key = crate::fmt::from_hex(test.key_hex, false)
.unwrap().into();
- pp.decrypt(test.algo, &key).unwrap();
+ pp.decrypt(Some(test.algo), &key).unwrap();
},
Packet::Literal(_) => {
assert!(! saw_literal);
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs
index 9641ed4f..eeae2d84 100644
--- a/openpgp/src/parse/stream.rs
+++ b/openpgp/src/parse/stream.rs
@@ -930,7 +930,7 @@ impl<V: VerificationHelper> DecryptionHelper for NoDecryptionHelper<V> {
fn decrypt<D>(&mut self, _: &[PKESK], _: &[SKESK],
_: Option<SymmetricAlgorithm>,
_: D) -> Res