diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2019-03-26 15:01:54 +0100 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-03-26 16:30:56 +0100 |
commit | 81f5cbe9384eb92f2264d774a5d55bd70022b36f (patch) | |
tree | f3802b4a6d10bcb575fa93fcb3f86bcbb11b06ad /openpgp | |
parent | b78ece7128a128ced693143d453bae2463d29168 (diff) |
openpgp: Add enum PKESK.
- See #228.
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/src/message/mod.rs | 4 | ||||
-rw-r--r-- | openpgp/src/packet/key.rs | 8 | ||||
-rw-r--r-- | openpgp/src/packet/mod.rs | 50 | ||||
-rw-r--r-- | openpgp/src/packet/pkesk.rs | 58 | ||||
-rw-r--r-- | openpgp/src/packet/prelude.rs | 1 | ||||
-rw-r--r-- | openpgp/src/parse/parse.rs | 48 | ||||
-rw-r--r-- | openpgp/src/serialize/mod.rs | 30 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 2 |
8 files changed, 143 insertions, 58 deletions
diff --git a/openpgp/src/message/mod.rs b/openpgp/src/message/mod.rs index 6262e3be..3ea99194 100644 --- a/openpgp/src/message/mod.rs +++ b/openpgp/src/message/mod.rs @@ -1048,10 +1048,10 @@ mod tests { #[allow(deprecated)] packets.insert( 1, - Packet::PKESK(PKESK::new( + PKESK3::new( KeyID::from_hex("0000111122223333").unwrap(), PublicKeyAlgorithm::RSAEncrypt, - Ciphertext::RSA { c: MPI::new(&[]) }).unwrap())); + Ciphertext::RSA { c: MPI::new(&[]) }).unwrap().into()); assert!(packets.iter().map(|p| p.tag()).collect::<Vec<Tag>>() == [ Tag::SKESK, Tag::PKESK, Tag::SKESK, Tag::SEIP ]); diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs index 04329e4f..862eba6f 100644 --- a/openpgp/src/packet/key.rs +++ b/openpgp/src/packet/key.rs @@ -685,6 +685,7 @@ impl SecretKey { mod tests { use packet::Tag; use TPK; + use packet::pkesk::PKESK3; use packet::key::SecretKey; use std::path::PathBuf; use super::*; @@ -786,7 +787,6 @@ mod tests { fn encryption_roundtrip() { use packet::key::SecretKey; use crypto::SessionKey; - use packet::PKESK; use constants::Curve::*; let keys = vec![NistP256, NistP384, NistP521].into_iter().map(|cv| { @@ -809,7 +809,7 @@ mod tests { let sk = SessionKey::new(&mut Default::default(), cipher.key_size().unwrap()); - let pkesk = PKESK::for_recipient(cipher, &sk, &key).unwrap(); + let pkesk = PKESK3::for_recipient(cipher, &sk, &key).unwrap(); let (cipher_, sk_) = pkesk.decrypt(&key, &secret).unwrap(); assert_eq!(cipher, cipher_); @@ -912,7 +912,6 @@ mod tests { #[test] fn import_rsa() { - use packet::PKESK; use crypto::SessionKey; use self::mpis::{MPI, Ciphertext}; use time::{at, Timespec}; @@ -929,7 +928,8 @@ mod tests { let ciphertext = Ciphertext::RSA{ c: MPI::new(&c[..]), }; - let pkesk = PKESK::new(key.keyid(), PublicKeyAlgorithm::RSAEncryptSign, ciphertext).unwrap(); + let pkesk = PKESK3::new(key.keyid(), PublicKeyAlgorithm::RSAEncryptSign, + ciphertext).unwrap(); // Session key let dek = b"\xA5\x58\x3A\x04\x35\x8B\xC7\x3F\x4A\xEF\x0C\x5A\xEB\xED\x59\xCA\xFD\x96\xB5\x32\x23\x26\x0C\x91\x78\xD1\x31\x12\xF0\x41\x42\x9D"; diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs index c37093c2..5eff6652 100644 --- a/openpgp/src/packet/mod.rs +++ b/openpgp/src/packet/mod.rs @@ -41,8 +41,7 @@ mod compressed_data; pub use self::compressed_data::CompressedData; pub mod seip; pub mod skesk; -mod pkesk; -pub use self::pkesk::PKESK; +pub mod pkesk; mod mdc; pub use self::mdc::MDC; pub mod aed; @@ -695,6 +694,53 @@ impl DerefMut for OnePassSig { } } +/// 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. +/// +/// [Section 5.1 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.1 +#[derive(PartialEq, Eq, Hash, Clone, Debug)] +pub enum PKESK { + /// PKESK packet version 3. + V3(self::pkesk::PKESK3), +} + +impl PKESK { + /// Gets the version. + pub fn version(&self) -> u8 { + match self { + PKESK::V3(_) => 3, + } + } +} + +impl From<PKESK> for Packet { + fn from(p: PKESK) -> Self { + Packet::PKESK(p) + } +} + +// Trivial forwarder for singleton enum. +impl Deref for PKESK { + type Target = self::pkesk::PKESK3; + + fn deref(&self) -> &Self::Target { + match self { + PKESK::V3(ref p) => p, + } + } +} + +// Trivial forwarder for singleton enum. +impl DerefMut for PKESK { + fn deref_mut(&mut self) -> &mut Self::Target { + match self { + PKESK::V3(ref mut p) => p, + } + } +} + /// Holds an symmetrically encrypted session key. /// /// Holds an symmetrically encrypted session key. The session key is diff --git a/openpgp/src/packet/pkesk.rs b/openpgp/src/packet/pkesk.rs index cb03ff4b..75591ccd 100644 --- a/openpgp/src/packet/pkesk.rs +++ b/openpgp/src/packet/pkesk.rs @@ -1,3 +1,10 @@ +//! PublicKey-Encrypted Session Key packets. +//! +//! The session key is needed to decrypt the actual ciphertext. See +//! [Section 5.1 of RFC 4880] for details. +//! +//! [Section 5.1 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.1 + use quickcheck::{Arbitrary, Gen}; use Error; @@ -20,11 +27,9 @@ use packet; /// /// [Section 5.1 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.1 #[derive(PartialEq, Eq, Hash, Clone, Debug)] -pub struct PKESK { +pub struct PKESK3 { /// CTB header fields. pub(crate) common: packet::Common, - /// Packet version. Must be 3. - version: u8, /// Key ID of the key this is encrypted to. recipient: KeyID, /// Public key algorithm used to encrypt the session key. @@ -33,27 +38,26 @@ pub struct PKESK { esk: Ciphertext, } -impl PKESK { - /// Creates a new PKESK packet. +impl PKESK3 { + /// Creates a new PKESK3 packet. pub fn new(recipient: KeyID, pk_algo: PublicKeyAlgorithm, encrypted_session_key: Ciphertext) - -> Result<PKESK> { - Ok(PKESK { + -> Result<PKESK3> { + Ok(PKESK3 { common: Default::default(), - version: 3, recipient: recipient, pk_algo: pk_algo, esk: encrypted_session_key, }) } - /// Creates a new PKESK packet for the given recipent. + /// Creates a new PKESK3 packet for the given recipent. /// /// The given symmetric algorithm must match the algorithm that is /// used to encrypt the payload. pub fn for_recipient(algo: SymmetricAlgorithm, session_key: &SessionKey, recipient: &Key) - -> Result<PKESK> { + -> Result<PKESK3> { use PublicKeyAlgorithm::*; let mut rng = Yarrow::default(); @@ -100,20 +104,14 @@ impl PKESK { return Err(Error::UnsupportedPublicKeyAlgorithm(algo).into()), }; - Ok(PKESK{ + Ok(PKESK3{ common: Default::default(), - version: 3, recipient: recipient.keyid(), pk_algo: recipient.pk_algo(), esk: esk, }) } - /// Gets the version. - pub fn version(&self) -> u8 { - self.version - } - /// Gets the recipient. pub fn recipient(&self) -> &KeyID { &self.recipient @@ -211,13 +209,19 @@ impl PKESK { } } -impl From<PKESK> for Packet { - fn from(s: PKESK) -> Self { - Packet::PKESK(s) +impl From<PKESK3> for super::PKESK { + fn from(p: PKESK3) -> Self { + super::PKESK::V3(p) + } +} + +impl From<PKESK3> for Packet { + fn from(p: PKESK3) -> Self { + Packet::PKESK(p.into()) } } -impl Arbitrary for PKESK { +impl Arbitrary for PKESK3 { fn arbitrary<G: Gen>(g: &mut G) -> Self { let (ciphertext, pk_algo) = loop { let ciphertext = Ciphertext::arbitrary(g); @@ -226,7 +230,7 @@ impl Arbitrary for PKESK { } }; - PKESK::new(KeyID::arbitrary(g), pk_algo, ciphertext).unwrap() + PKESK3::new(KeyID::arbitrary(g), pk_algo, ciphertext).unwrap() } } @@ -242,8 +246,8 @@ mod tests { use serialize::SerializeInto; quickcheck! { - fn roundtrip(p: PKESK) -> bool { - let q = PKESK::from_bytes(&p.to_vec().unwrap()).unwrap(); + fn roundtrip(p: PKESK3) -> bool { + let q = PKESK3::from_bytes(&p.to_vec().unwrap()).unwrap(); assert_eq!(p, q); true } @@ -378,7 +382,7 @@ mod tests { #[test] fn decrypt_with_short_cv25519_secret_key() { use conversions::Time; - use super::PKESK; + use super::PKESK3; use crypto::SessionKey; use crypto::mpis::{self, MPI}; use PublicKeyAlgorithm; @@ -414,8 +418,8 @@ mod tests { .unwrap(); let mut rng = Yarrow::default(); let sess_key = SessionKey::new(&mut rng, 32); - let pkesk = PKESK::for_recipient(SymmetricAlgorithm::AES256, &sess_key, - &key).unwrap(); + let pkesk = PKESK3::for_recipient(SymmetricAlgorithm::AES256, &sess_key, + &key).unwrap(); pkesk.decrypt(&key, &private_mpis).unwrap(); } diff --git a/openpgp/src/packet/prelude.rs b/openpgp/src/packet/prelude.rs index b28d70e8..54b2bcdd 100644 --- a/openpgp/src/packet/prelude.rs +++ b/openpgp/src/packet/prelude.rs @@ -14,6 +14,7 @@ pub use super::{ Literal, CompressedData, PKESK, + pkesk::PKESK3, SKESK, skesk::SKESK4, skesk::SKESK5, diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs index a79e83cd..c7798308 100644 --- a/openpgp/src/parse/parse.rs +++ b/openpgp/src/parse/parse.rs @@ -2246,22 +2246,10 @@ impl PKESK { fn parse<'a>(mut php: PacketHeaderParser<'a>) -> Result<PacketParser<'a>> { make_php_try!(php); let version = php_try!(php.parse_u8("version")); - if version != 3 { - // We only support version 3 packets. - return php.fail("unknown version"); - } - - let mut keyid = [0u8; 8]; - keyid.copy_from_slice(&php_try!(php.parse_bytes("keyid", 8))); - let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into(); - if ! pk_algo.can_encrypt() { - return php.fail("not an encryption algorithm"); + match version { + 3 => PKESK3::parse(php), + _ => php.fail("unknown version"), } - let mpis = crypto::mpis::Ciphertext::parse(pk_algo, &mut php)?; - - let pkesk = php_try!(PKESK::new(KeyID::from_bytes(&keyid), - pk_algo, mpis)); - php.ok(Packet::PKESK(pkesk)) } } @@ -2290,6 +2278,36 @@ impl<'a> Parse<'a, PKESK> for PKESK { } } } + +impl PKESK3 { + /// Parses the body of an PK-ESK packet. + fn parse<'a>(mut php: PacketHeaderParser<'a>) -> Result<PacketParser<'a>> { + make_php_try!(php); + let mut keyid = [0u8; 8]; + keyid.copy_from_slice(&php_try!(php.parse_bytes("keyid", 8))); + let pk_algo: PublicKeyAlgorithm = php_try!(php.parse_u8("pk_algo")).into(); + if ! pk_algo.can_encrypt() { + return php.fail("not an encryption algorithm"); + } + let mpis = crypto::mpis::Ciphertext::parse(pk_algo, &mut php)?; + + let pkesk = php_try!(PKESK3::new(KeyID::from_bytes(&keyid), + pk_algo, mpis)); + php.ok(pkesk.into()) + } +} + +impl<'a> Parse<'a, PKESK3> for PKESK3 { + fn from_reader<R: 'a + Read>(reader: R) -> Result<Self> { + PKESK::from_reader(reader).and_then(|p| match p { + PKESK::V3(p) => Ok(p), + // XXX: Once we have a second variant. + // + // p => Err(Error::InvalidOperation( + // format!("Not a PKESKv3 packet: {:?}", p)).into()), + }) + } +} // State that lives for the life of the packet parser, not the life of // an individual packet. diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs index ec789111..5968f6a4 100644 --- a/openpgp/src/serialize/mod.rs +++ b/openpgp/src/serialize/mod.rs @@ -1478,18 +1478,34 @@ impl SerializeInto for CompressedData { impl Serialize for PKESK { fn serialize<W: io::Write>(&self, o: &mut W) -> Result<()> { - if self.version() != 3 { - return Err(Error::InvalidArgument( - "Don't know how to serialize \ - non-version 3 packets.".into()).into()); + match self { + &PKESK::V3(ref p) => p.serialize(o), } + } +} + +impl SerializeInto for PKESK { + fn serialized_len(&self) -> usize { + match self { + &PKESK::V3(ref p) => p.serialized_len(), + } + } + fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> { + match self { + &PKESK::V3(ref p) => generic_serialize_into(p, buf), + } + } +} + +impl Serialize for PKESK3 { + fn serialize<W: io::Write>(&self, o: &mut W) -> Result<()> { let len = self.net_len(); CTB::new(Tag::PKESK).serialize(o)?; BodyLength::Full(len as u32).serialize(o)?; - write_byte(o, self.version())?; + write_byte(o, 3)?; // Version. self.recipient().serialize(o)?; write_byte(o, self.pk_algo().into())?; self.esk().serialize(o)?; @@ -1498,7 +1514,7 @@ impl Serialize for PKESK { } } -impl NetLength for PKESK { +impl NetLength for PKESK3 { fn net_len(&self) -> usize { 1 // Version. + 8 // Recipient's key id. @@ -1507,7 +1523,7 @@ impl NetLength for PKESK { } } -impl SerializeInto for PKESK { +impl SerializeInto for PKESK3 { fn serialized_len(&self) -> usize { self.gross_len() } diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index f2588602..6b3b0f52 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -981,7 +981,7 @@ impl<'a> Encryptor<'a> { let mut count = 0; for key in keys { - if let Ok(pkesk) = PKESK::for_recipient(algo, &sk, key) { + if let Ok(pkesk) = PKESK3::for_recipient(algo, &sk, key) { pkesk.serialize(&mut inner)?; count += 1; } |