diff options
author | Justus Winter <justus@sequoia-pgp.org> | 2018-10-17 14:06:50 +0200 |
---|---|---|
committer | Justus Winter <justus@sequoia-pgp.org> | 2019-03-26 16:30:56 +0100 |
commit | c3b76589463017ddaa186c45108c4f91db5a14cf (patch) | |
tree | 25ef976d55ce15f40cd5661cbcab7fc9a2e3ae9c /openpgp/src | |
parent | b2d5cabc889d157f6e93ceca7b64c0246ca459bf (diff) |
openpgp: Introduce explicit packet versions, move enum SKESK.
- This patch makes packet::skesk public, exports the SKESK4 and
SKESK5 type there, and moves the SKESK enum to packet.
- This is a clean and faithful way to represent packet versions. It
allows us to cleanly support future versions, and offer partial
support for older versions. Parsing and understanding old
versions allows Sequoia to be used to access archived information.
- This is the first of a series of patches that introduces explicit
packet versions for all packet types in the form of enums like the
SKESK enum.
- See #228.
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/message/mod.rs | 2 | ||||
-rw-r--r-- | openpgp/src/packet/mod.rs | 34 | ||||
-rw-r--r-- | openpgp/src/packet/skesk.rs | 71 | ||||
-rw-r--r-- | openpgp/src/parse/parse.rs | 2 | ||||
-rw-r--r-- | openpgp/src/serialize/mod.rs | 16 |
5 files changed, 56 insertions, 69 deletions
diff --git a/openpgp/src/message/mod.rs b/openpgp/src/message/mod.rs index 883b8465..66b735f0 100644 --- a/openpgp/src/message/mod.rs +++ b/openpgp/src/message/mod.rs @@ -410,7 +410,7 @@ mod tests { use packet::CompressedData; use packet::Literal; use packet::OnePassSig; - use packet::SKESK4; + use packet::skesk::SKESK4; use packet::PKESK; use packet::SEIP; use packet::MDC; diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs index f689301f..46a4d250 100644 --- a/openpgp/src/packet/mod.rs +++ b/openpgp/src/packet/mod.rs @@ -43,8 +43,7 @@ mod compressed_data; pub use self::compressed_data::CompressedData; mod seip; pub use self::seip::SEIP; -mod skesk; -pub use self::skesk::{SKESK, SKESK4, SKESK5}; +pub mod skesk; mod pkesk; pub use self::pkesk::PKESK; mod mdc; @@ -603,3 +602,34 @@ fn packet_path_iter() { } } } + +/// Holds an symmetrically encrypted session key. +/// +/// Holds an symmetrically encrypted session key. The session key is +/// needed to decrypt the actual ciphertext. See [Section 5.3 of RFC +/// 4880] for details. +/// +/// [Section 5.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.3 +#[derive(PartialEq, Eq, Hash, Clone, Debug)] +pub enum SKESK { + /// SKESK packet version 4. + V4(self::skesk::SKESK4), + /// SKESK packet version 5. + V5(self::skesk::SKESK5), +} + +impl SKESK { + /// Gets the version. + pub fn version(&self) -> u8 { + match self { + &SKESK::V4(_) => 4, + &SKESK::V5(_) => 5, + } + } +} + +impl From<SKESK> for Packet { + fn from(p: SKESK) -> Self { + Packet::SKESK(p) + } +} diff --git a/openpgp/src/packet/skesk.rs b/openpgp/src/packet/skesk.rs index 256a1c8d..64c9f99b 100644 --- a/openpgp/src/packet/skesk.rs +++ b/openpgp/src/packet/skesk.rs @@ -1,3 +1,11 @@ +//! Symmetric-Key Encrypted Session Key Packets. +//! +//! SKESK packets hold symmetrically encrypted session keys. The +//! session key is needed to decrypt the actual ciphertext. See +//! [Section 5.3 of RFC 4880] for details. +//! +//! [Section 5.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.3 + use std::ops::{Deref, DerefMut}; use quickcheck::{Arbitrary, Gen}; @@ -10,26 +18,11 @@ use constants::{ AEADAlgorithm, SymmetricAlgorithm, }; -use packet; +use packet::{self, SKESK}; use Packet; use crypto::Password; use crypto::SessionKey; -/// Holds an symmetrically encrypted session key. -/// -/// Holds an symmetrically encrypted session key. The session key is -/// needed to decrypt the actual ciphertext. See [Section 5.3 of RFC -/// 4880] for details. -/// -/// [Section 5.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.3 -#[derive(PartialEq, Eq, Hash, Clone, Debug)] -pub enum SKESK { - /// SKESK packet version 4. - V4(SKESK4), - /// SKESK packet version 5. - V5(SKESK5), -} - impl SKESK { /// Derives the key inside this SKESK from `password`. Returns a /// tuple of the symmetric cipher to use with the key and the key @@ -42,14 +35,6 @@ impl SKESK { &SKESK::V5(ref s) => s.decrypt(password), } } - - /// Gets the version. - pub fn version(&self) -> u8 { - match self { - &SKESK::V4(_) => 4, - &SKESK::V5(_) => 5, - } - } } impl Arbitrary for SKESK { @@ -74,6 +59,9 @@ pub struct SKESK4 { /// CTB header fields. pub(crate) common: packet::Common, /// Packet version. Must be 4 or 5. + /// + /// This struct is also used by SKESK5, hence we have a version + /// field. version: u8, /// Symmetric algorithm used to encrypt the session key. symm_algo: SymmetricAlgorithm, @@ -89,16 +77,11 @@ impl SKESK4 { /// The given symmetric algorithm must match the algorithm that is /// used to encrypt the payload, and is also used to encrypt the /// given session key. - pub fn new(version: u8, cipher: SymmetricAlgorithm, s2k: S2K, + pub fn new(cipher: SymmetricAlgorithm, s2k: S2K, esk: Option<Vec<u8>>) -> Result<SKESK4> { - if version != 4 { - return Err(Error::InvalidArgument( - format!("Invalid version: {}", version)).into()); - } - Ok(SKESK4{ common: Default::default(), - version: version, + version: 4, symm_algo: cipher, s2k: s2k, esk: esk.and_then(|esk| { @@ -132,12 +115,7 @@ impl SKESK4 { cipher.encrypt(&mut iv[..], ct, pt)?; } - SKESK4::new(4, algo, s2k, Some(esk)) - } - - /// Gets the version. - pub fn version(&self) -> u8 { - self.version + SKESK4::new(algo, s2k, Some(esk)) } /// Gets the symmetric encryption algorithm. @@ -227,8 +205,7 @@ impl From<SKESK4> for Packet { impl Arbitrary for SKESK4 { fn arbitrary<G: Gen>(g: &mut G) -> Self { - SKESK4::new(4, - SymmetricAlgorithm::arbitrary(g), + SKESK4::new(SymmetricAlgorithm::arbitrary(g), S2K::arbitrary(g), Option::<Vec<u8>>::arbitrary(g)) .unwrap() @@ -274,18 +251,13 @@ impl SKESK5 { /// The given symmetric algorithm must match the algorithm that is /// used to encrypt the payload, and is also used to encrypt the /// given session key. - pub fn new(version: u8, cipher: SymmetricAlgorithm, aead: AEADAlgorithm, + pub fn new(cipher: SymmetricAlgorithm, aead: AEADAlgorithm, s2k: S2K, iv: Box<[u8]>, esk: Vec<u8>, digest: Box<[u8]>) -> Result<Self> { - if version != 5 { - return Err(Error::InvalidArgument( - format!("Invalid version: {}", version)).into()); - } - Ok(SKESK5{ skesk4: SKESK4{ common: Default::default(), - version: version, + version: 5, symm_algo: cipher, s2k: s2k, esk: Some(esk), @@ -319,7 +291,7 @@ impl SKESK5 { let mut digest = vec![0u8; aead.digest_size()?]; ctx.digest(&mut digest); - SKESK5::new(5, cipher, aead, s2k, iv.into_boxed_slice(), esk, + SKESK5::new(cipher, aead, s2k, iv.into_boxed_slice(), esk, digest.into_boxed_slice()) } @@ -336,7 +308,7 @@ impl SKESK5 { let mut cipher = self.aead_algo.context( self.symmetric_algo(), &key, &self.aead_iv)?; - let ad = [0xc3, self.version(), self.symmetric_algo().into(), + let ad = [0xc3, 5 /* Version. */, self.symmetric_algo().into(), self.aead_algo.into()]; cipher.update(&ad); let mut plain = vec![0; esk.len()]; @@ -404,8 +376,7 @@ impl Arbitrary for SKESK5 { for b in digest.iter_mut() { *b = u8::arbitrary(g); } - SKESK5::new(5, - SymmetricAlgorithm::arbitrary(g), + SKESK5::new(SymmetricAlgorithm::arbitrary(g), algo, S2K::arbitrary(g), iv.into_boxed_slice(), diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs index a145389c..10942048 100644 --- a/openpgp/src/parse/parse.rs +++ b/openpgp/src/parse/parse.rs @@ -1789,7 +1789,6 @@ impl SKESK { let esk = php_try!(php.parse_bytes_eof("esk")); SKESK::V4(php_try!(SKESK4::new( - version, symm_algo.into(), s2k, if esk.len() > 0 { Some(esk) } else { None }, @@ -1818,7 +1817,6 @@ impl SKESK { php_try!(php.parse_bytes("aead_digest", digest_size)); SKESK::V5(php_try!(SKESK5::new( - version, symm_algo, aead_algo, s2k, diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs index 6de111c5..85e2c819 100644 --- a/openpgp/src/serialize/mod.rs +++ b/openpgp/src/serialize/mod.rs @@ -1492,18 +1492,12 @@ impl SerializeInto for SKESK { impl Serialize for SKESK4 { fn serialize<W: io::Write>(&self, o: &mut W) -> Result<()> { - if self.version() != 4 { - return Err(Error::InvalidArgument( - "Don't know how to serialize \ - non-version 4 packets.".into()).into()); - } - let len = self.net_len(); CTB::new(Tag::SKESK).serialize(o)?; BodyLength::Full(len as u32).serialize(o)?; - write_byte(o, self.version())?; + write_byte(o, 4)?; // Version. write_byte(o, self.symmetric_algo().into())?; self.s2k().serialize(o)?; if let Some(ref esk) = self.esk() { @@ -1535,18 +1529,12 @@ impl SerializeInto for SKESK4 { impl Serialize for SKESK5 { fn serialize<W: io::Write>(&self, o: &mut W) -> Result<()> { - if self.version() != 5 { - return Err(Error::InvalidArgument( - "Don't know how to serialize \ - non-version 4 packets.".into()).into()); - } - let len = self.net_len(); CTB::new(Tag::SKESK).serialize(o)?; BodyLength::Full(len as u32).serialize(o)?; - write_byte(o, self.version())?; + write_byte(o, 5)?; // Version. write_byte(o, self.symmetric_algo().into())?; write_byte(o, self.aead_algo().into())?; self.s2k().serialize(o)?; |