summaryrefslogtreecommitdiffstats
path: root/openpgp
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-03-26 15:01:54 +0100
committerJustus Winter <justus@sequoia-pgp.org>2019-03-26 16:30:56 +0100
commit81f5cbe9384eb92f2264d774a5d55bd70022b36f (patch)
treef3802b4a6d10bcb575fa93fcb3f86bcbb11b06ad /openpgp
parentb78ece7128a128ced693143d453bae2463d29168 (diff)
openpgp: Add enum PKESK.
- See #228.
Diffstat (limited to 'openpgp')
-rw-r--r--openpgp/src/message/mod.rs4
-rw-r--r--openpgp/src/packet/key.rs8
-rw-r--r--openpgp/src/packet/mod.rs50
-rw-r--r--openpgp/src/packet/pkesk.rs58
-rw-r--r--openpgp/src/packet/prelude.rs1
-rw-r--r--openpgp/src/parse/parse.rs48
-rw-r--r--openpgp/src/serialize/mod.rs30
-rw-r--r--openpgp/src/serialize/stream.rs2
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;
}