summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-05-21 17:50:22 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-05-22 15:45:29 +0200
commit387ac1cc1477d37003e659c3183b81300afcb2c3 (patch)
tree8d7180c9e3b776147feacbc06dc475455016afac
parent5d59509fd7e09f19eb5d21ec94b7905ac30af562 (diff)
openpgp: Trait Serialize/Parse cleanup.
- Currently, when we serialize a packet structure, like Signature, we get a full packet with CTB and length, even though we didn't really ask for that. If we want to create an embedded signature, we need to use the special interface Signature::serialize_naked() to get it without frame. - Also consider Key. Here, we don't know whether it is supposed to be primary or subkey, or public or secret. Therefore, we have SerializeKey, which is like Serialize, but also gets a tag. Now, if Key::serialize() would only emit the body, it wouldn't need to know what kind of key to emit. - The same applies to trait Parse. If we use, say, Signature::from_bytes(), the parser expects a framed signature. If we want to parse an embedded signature, we need to use a special interface again. - This patch changes how we parse and serialize packet structures to not expect or emit the frame. If we want to include the frame, we need to explicitly wrap it into an enum Packet. - This patch does not include any cleanups and optimizations to keep the size manageable. - See #255.
-rw-r--r--openpgp/src/packet/key.rs7
-rw-r--r--openpgp/src/packet/signature/mod.rs7
-rw-r--r--openpgp/src/packet/user_attribute.rs9
-rw-r--r--openpgp/src/parse/parse.rs36
-rw-r--r--openpgp/src/parse/stream.rs6
-rw-r--r--openpgp/src/serialize/mod.rs318
-rw-r--r--openpgp/src/serialize/stream.rs24
-rw-r--r--openpgp/src/serialize/tpk.rs230
-rw-r--r--tool/src/commands/key.rs3
-rw-r--r--tool/src/commands/sign.rs10
10 files changed, 299 insertions, 351 deletions
diff --git a/openpgp/src/packet/key.rs b/openpgp/src/packet/key.rs
index c1fce733..42339644 100644
--- a/openpgp/src/packet/key.rs
+++ b/openpgp/src/packet/key.rs
@@ -698,14 +698,13 @@ impl SecretKey {
#[cfg(test)]
mod tests {
- use packet::Tag;
use packet::Key;
use TPK;
use packet::pkesk::PKESK3;
use packet::key::SecretKey;
use super::*;
use PacketPile;
- use serialize::SerializeKey;
+ use serialize::Serialize;
use parse::Parse;
#[test]
@@ -763,7 +762,7 @@ mod tests {
for mut key in keys {
let mut b = Vec::new();
- key.serialize(&mut b, Tag::SecretKey).unwrap();
+ Packet::SecretKey(key.clone().into()).serialize(&mut b).unwrap();
let pp = PacketPile::from_bytes(&b).unwrap();
if let Some(Packet::SecretKey(Key::V4(ref parsed_key))) =
@@ -781,7 +780,7 @@ mod tests {
}
let mut b = Vec::new();
- key.serialize(&mut b, Tag::PublicKey).unwrap();
+ Packet::PublicKey(key.clone().into()).serialize(&mut b).unwrap();
let pp = PacketPile::from_bytes(&b).unwrap();
if let Some(Packet::PublicKey(Key::V4(ref parsed_key))) =
diff --git a/openpgp/src/packet/signature/mod.rs b/openpgp/src/packet/signature/mod.rs
index 756fc96d..f71eab51 100644
--- a/openpgp/src/packet/signature/mod.rs
+++ b/openpgp/src/packet/signature/mod.rs
@@ -1152,9 +1152,14 @@ mod test {
let tpk = TPK::from_bytes(::tests::key(
"emmelie-dorothea-dina-samantha-awina-ed25519.pgp")).unwrap();
let msg = ::tests::manifesto();
- let sig = Signature::from_bytes(
+ let p = Packet::from_bytes(
::tests::message("a-cypherpunks-manifesto.txt.ed25519.sig"))
.unwrap();
+ let sig = if let Packet::Signature(s) = p {
+ s
+ } else {
+ panic!("Expected a Signature, got: {:?}", p);
+ };
assert!(sig.verify_message(tpk.primary(), &msg[..]).unwrap());
}
diff --git a/openpgp/src/packet/user_attribute.rs b/openpgp/src/packet/user_attribute.rs
index 101e9866..b5f8bf79 100644
--- a/openpgp/src/packet/user_attribute.rs
+++ b/openpgp/src/packet/user_attribute.rs
@@ -253,7 +253,8 @@ mod tests {
#[test]
fn image() {
- let ua = UserAttribute::from_bytes(b"
+ use Packet;
+ let p = Packet::from_bytes(b"
-----BEGIN PGP ARMORED FILE-----
0cFuwWwBEAABAQAAAAAAAAAAAAAAAP/Y/+AAEEpGSUYAAQEBASwBLAAA//4AE0Ny
@@ -271,7 +272,11 @@ ABQQAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQEAAT8Qf//Z
=nUQg
-----END PGP ARMORED FILE-----
").unwrap();
- let subpackets: Vec<_> = ua.subpackets().collect();
+ let subpackets: Vec<_> = if let Packet::UserAttribute(ua) = p {
+ ua.subpackets().collect()
+ } else {
+ panic!("Expected an UserAttribute, got: {:?}", p);
+ };
assert_eq!(subpackets.len(), 1);
if let Ok(Subpacket::Image(Image::JPEG(img))) = &subpackets[0] {
assert_eq!(img.len(), 539);
diff --git a/openpgp/src/parse/parse.rs b/openpgp/src/parse/parse.rs
index 736e3b08..23f86730 100644
--- a/openpgp/src/parse/parse.rs
+++ b/openpgp/src/parse/parse.rs
@@ -100,18 +100,14 @@ macro_rules! impl_parse_generic_packet {
($typ: ident) => {
impl<'a> Parse<'a, $typ> for $typ {
fn from_reader<R: 'a + Read>(reader: R) -> Result<Self> {
- let ppr = PacketParserBuilder::from_reader(reader)?
- .buffer_unread_content().finalize()?;
- let (p, ppr) = match ppr {
- PacketParserResult::Some(mut pp) => {
- pp.next()?
- },
- PacketParserResult::EOF(_) =>
- return Err(Error::InvalidOperation(
- "Unexpected EOF".into()).into()),
- };
+ let bio = buffered_reader::Generic::with_cookie(
+ reader, None, Cookie::default());
+ let parser = PacketHeaderParser::new_naked(Box::new(bio));
+
+ let mut pp = Self::parse(parser)?;
+ pp.buffer_unread_content()?;
- match (p, ppr) {
+ match pp.next()? {
(Packet::$typ(o), PacketParserResult::EOF(_))
=> Ok(o),
(p, PacketParserResult::EOF(_)) =>
@@ -1462,18 +1458,14 @@ impl Key4 {
impl<'a> Parse<'a, Key> for Key {
fn from_reader<R: 'a + Read>(reader: R) -> Result<Self> {
- let ppr = PacketParserBuilder::from_reader(reader)?
- .buffer_unread_content().finalize()?;
- let (p, ppr) = match ppr {
- PacketParserResult::Some(mut pp) => {
- pp.next()?
- },
- PacketParserResult::EOF(_) =>
- return Err(Error::InvalidOperation(
- "Unexpected EOF".into()).into()),
- };
+ let bio = buffered_reader::Generic::with_cookie(
+ reader, None, Cookie::default());
+ let parser = PacketHeaderParser::new_naked(Box::new(bio));
- match (p, ppr) {
+ let mut pp = Self::parse(parser)?;
+ pp.buffer_unread_content()?;
+
+ match pp.next()? {
(Packet::PublicKey(o), PacketParserResult::EOF(_))
| (Packet::PublicSubkey(o), PacketParserResult::EOF(_))
| (Packet::SecretKey(o), PacketParserResult::EOF(_))
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs
index 8c0a70bc..6a379687 100644
--- a/openpgp/src/parse/stream.rs
+++ b/openpgp/src/parse/stream.rs
@@ -748,7 +748,7 @@ impl<'a> Transformer<'a> {
ops.set_last(true);
}
- ops.serialize(&mut buf)?;
+ Packet::OnePassSig(ops.into()).serialize(&mut buf)?;
}
// We need to decide whether to use partial body encoding or
@@ -845,8 +845,8 @@ impl<'a> Transformer<'a> {
},
TransformationState::Sigs => {
- for sig in self.sigs.iter() {
- sig.serialize(&mut self.buffer)?;
+ for sig in self.sigs.drain(..) {
+ Packet::Signature(sig).serialize(&mut self.buffer)?;
}
TransformationState::Done
diff --git a/openpgp/src/serialize/mod.rs b/openpgp/src/serialize/mod.rs
index b218f3a0..f6280f11 100644
--- a/openpgp/src/serialize/mod.rs
+++ b/openpgp/src/serialize/mod.rs
@@ -34,25 +34,13 @@ use packet::prelude::*;
// Whether to trace the modules execution (on stderr).
const TRACE : bool = false;
-/// Packet serialization.
-///
-/// This interfaces serializes packets and packet trees.
+/// Serializes OpenPGP data structures.
pub trait Serialize {
- /// Writes a serialized version of the packet to `o`.
+ /// Writes a serialized version of the object to `o`.
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()>;
}
-/// Key packet serialization.
-///
-/// This interface serializes key packets.
-pub trait SerializeKey {
- /// Writes a serialized version of the key packet to `o`.
- ///
- /// Tag identifies the kind of packet to write.
- fn serialize(&self, o: &mut dyn io::Write, tag: Tag) -> Result<()>;
-}
-
-/// Serialization into pre-allocated buffers.
+/// Serializes OpenPGP data structures into pre-allocated buffers.
pub trait SerializeInto {
/// Computes the maximal length of the serialized representation.
///
@@ -109,37 +97,6 @@ trait NetLength {
}
}
-/// Serialization into pre-allocated buffers.
-pub trait SerializeKeyInto {
- /// Computes the maximal length of the serialized representation.
- ///
- /// # Errors
- ///
- /// If serialization would fail, this function underestimates the
- /// length.
- fn serialized_len(&self, tag: Tag) -> usize;
-
- /// Serializes into the given buffer.
- ///
- /// Returns the length of the serialized representation.
- ///
- /// # Errors
- ///
- /// If the length of the given slice is smaller than the maximal
- /// length computed by `serialized_len()`, this function returns
- /// `Error::InvalidArgument`.
- fn serialize_into(&self, buf: &mut [u8], tag: Tag) -> Result<usize>;
-
- /// Serializes the packet to a vector.
- fn to_vec(&self, tag: Tag) -> Result<Vec<u8>> {
- let mut o = vec![0; self.serialized_len(tag)];
- let len = self.serialize_into(&mut o[..], tag)?;
- o.truncate(len);
- o.shrink_to_fit();
- Ok(o)
- }
-}
-
/// Provides a generic implementation for SerializeInto::serialize_into.
///
/// For now, we express SerializeInto using Serialize. In the future,
@@ -842,8 +799,6 @@ impl Serialize for Unknown {
&b""[..]
};
- CTB::new(self.tag()).serialize(o)?;
- BodyLength::Full(body.len() as u32).serialize(o)?;
o.write_all(&body[..])?;
Ok(())
@@ -858,7 +813,7 @@ impl NetLength for Unknown {
impl SerializeInto for Unknown {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1076,10 +1031,6 @@ impl Serialize for Signature4 {
///
/// [`Error::InvalidArgument`]: ../../enum.Error.html#variant.InvalidArgument
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let len = self.net_len();
- CTB::new(Tag::Signature).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
-
self.serialize_naked(o)
}
}
@@ -1101,7 +1052,7 @@ impl NetLength for Signature4 {
impl SerializeInto for Signature4 {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1183,10 +1134,6 @@ impl SerializeInto for OnePassSig {
impl Serialize for OnePassSig3 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let len = self.net_len();
- CTB::new(Tag::OnePassSig).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
-
write_byte(o, 3)?; // Version.
write_byte(o, self.sigtype().into())?;
write_byte(o, self.hash_algo().into())?;
@@ -1211,7 +1158,7 @@ impl NetLength for OnePassSig3 {
impl SerializeInto for OnePassSig3 {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1219,50 +1166,44 @@ impl SerializeInto for OnePassSig3 {
}
}
-impl SerializeKey for Key {
- fn serialize(&self, o: &mut io::Write, tag: Tag) -> Result<()> {
+impl Serialize for Key {
+ fn serialize(&self, o: &mut io::Write) -> Result<()> {
match self {
- &Key::V4(ref p) => p.serialize(o, tag),
+ &Key::V4(ref p) => p.serialize(o),
}
}
}
-impl SerializeKeyInto for Key {
- fn serialized_len(&self, tag: Tag) -> usize {
+impl SerializeInto for Key {
+ fn serialized_len(&self) -> usize {
match self {
- &Key::V4(ref p) => p.serialized_len(tag),
+ &Key::V4(ref p) => p.serialized_len(),
}
}
- fn serialize_into(&self, buf: &mut [u8], tag: Tag) -> Result<usize> {
+ fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
match self {
- &Key::V4(ref p) => p.serialize_into(buf, tag)
+ &Key::V4(ref p) => p.serialize_into(buf)
}
}
}
-impl SerializeKey for Key4 {
- fn serialize(&self, o: &mut io::Write, tag: Tag) -> Result<()> {
- assert!(tag == Tag::PublicKey
- || tag == Tag::PublicSubkey
- || tag == Tag::SecretKey
- || tag == Tag::SecretSubkey);
- let have_secret_key =
- (tag == Tag::SecretKey || tag == Tag::SecretSubkey)
- && self.secret().is_some();
-
- // Only emit packets with the SecretKey or SecretSubkey tags
- // if we have secrets.
- let tag = match tag {
- Tag::SecretKey if ! have_secret_key => Tag::PublicKey,
- Tag::SecretSubkey if ! have_secret_key => Tag::PublicSubkey,
- t => t,
- };
+impl Serialize for Key4 {
+ fn serialize(&self, o: &mut io::Write) -> Result<()> {
+ self.serialize_key(o, true)
+ }
+}
- let len = self.net_len(tag);
+impl Key4 {
+ pub(crate) // For tests in key.
+ fn serialize_key(&self, o: &mut io::Write, serialize_secrets: bool)
+ -> Result<()> {
+ if serialize_secrets && ! self.secret().is_some() {
+ return Err(Error::InvalidOperation(
+ "Cannot serialize secret key: No secrets".into()).into());
+ }
- CTB::new(tag).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
+ let have_secret_key = self.secret().is_some() && serialize_secrets;
write_byte(o, 4)?; // Version.
write_be_u32(o, self.creation_time().to_pgp()?)?;
@@ -1301,13 +1242,9 @@ impl SerializeKey for Key4 {
Ok(())
}
-}
-impl Key4 {
- fn net_len(&self, tag: Tag) -> usize {
- let have_secret_key =
- (tag == Tag::SecretKey || tag == Tag::SecretSubkey)
- && self.secret().is_some();
+ fn net_len_key(&self, serialize_secrets: bool) -> usize {
+ let have_secret_key = self.secret().is_some() && serialize_secrets;
1 // Version.
+ 4 // Creation time.
@@ -1330,32 +1267,18 @@ impl Key4 {
}
}
-impl SerializeKeyInto for Key4 {
- fn serialized_len(&self, tag: Tag) -> usize {
- // gross_len() by foot.
- let net = self.net_len(tag);
- 1 // CTB
- + BodyLength::Full(net as u32).serialized_len()
- + net
+impl SerializeInto for Key4 {
+ fn serialized_len(&self) -> usize {
+ self.net_len_key(true)
}
- fn serialize_into(&self, buf: &mut [u8], tag: Tag) -> Result<usize> {
- if buf.len() != self.serialized_len(tag) {
- return Err(Error::InvalidArgument(
- format!("Invalid buffer size, expected {}, got {}",
- self.serialized_len(tag), buf.len())).into());
- }
-
- let mut cursor = ::std::io::Cursor::new(buf);
- self.serialize(&mut cursor, tag)?;
- Ok(cursor.position() as usize)
+ fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
+ generic_serialize_into(self, buf)
}
}
impl Serialize for Marker {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- CTB::new(Tag::Marker).serialize(o)?;
- BodyLength::Full(Marker::BODY.len() as u32).serialize(o)?;
o.write_all(Marker::BODY)?;
Ok(())
}
@@ -1369,7 +1292,7 @@ impl NetLength for Marker {
impl SerializeInto for Marker {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1379,12 +1302,7 @@ impl SerializeInto for Marker {
impl Serialize for Trust {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let len = self.value().len();
-
- CTB::new(Tag::Trust).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
o.write_all(self.value())?;
-
Ok(())
}
}
@@ -1397,7 +1315,7 @@ impl NetLength for Trust {
impl SerializeInto for Trust {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1407,12 +1325,7 @@ impl SerializeInto for Trust {
impl Serialize for UserID {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let len = self.value().len();
-
- CTB::new(Tag::UserID).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
o.write_all(self.value())?;
-
Ok(())
}
}
@@ -1425,7 +1338,7 @@ impl NetLength for UserID {
impl SerializeInto for UserID {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1435,12 +1348,7 @@ impl SerializeInto for UserID {
impl Serialize for UserAttribute {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let len = self.value().len();
-
- CTB::new(Tag::UserAttribute).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
o.write_all(self.value())?;
-
Ok(())
}
}
@@ -1453,7 +1361,7 @@ impl NetLength for UserAttribute {
impl SerializeInto for UserAttribute {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1582,7 +1490,7 @@ impl Serialize for Literal {
body.len());
}
- self.serialize_headers(o, true)?;
+ self.serialize_headers(o, false)?;
o.write_all(body)?;
Ok(())
@@ -1598,7 +1506,7 @@ impl NetLength for Literal {
impl SerializeInto for Literal {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1623,7 +1531,7 @@ impl Serialize for CompressedData {
}
let o = stream::Message::new(o);
- let mut o = stream::Compressor::new(o, self.algorithm())?;
+ let mut o = stream::Compressor::new_naked(o, self.algorithm(), 0)?;
// Serialize the packets.
if let Some(ref children) = self.common.children {
@@ -1672,7 +1580,7 @@ impl SerializeInto for CompressedData {
///
/// If serialization would fail, this function returns 0.
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1704,11 +1612,6 @@ impl SerializeInto for PKESK {
impl Serialize for PKESK3 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let len = self.net_len();
-
- CTB::new(Tag::PKESK).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
-
write_byte(o, 3)?; // Version.
self.recipient().serialize(o)?;
write_byte(o, self.pk_algo().into())?;
@@ -1729,7 +1632,7 @@ impl NetLength for PKESK3 {
impl SerializeInto for PKESK3 {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1746,6 +1649,15 @@ impl Serialize for SKESK {
}
}
+impl NetLength for SKESK {
+ fn net_len(&self) -> usize {
+ match self {
+ &SKESK::V4(ref s) => s.net_len(),
+ &SKESK::V5(ref s) => s.net_len(),
+ }
+ }
+}
+
impl SerializeInto for SKESK {
fn serialized_len(&self) -> usize {
match self {
@@ -1764,11 +1676,6 @@ impl SerializeInto for SKESK {
impl Serialize for SKESK4 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let len = self.net_len();
-
- CTB::new(Tag::SKESK).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
-
write_byte(o, 4)?; // Version.
write_byte(o, self.symmetric_algo().into())?;
self.s2k().serialize(o)?;
@@ -1791,7 +1698,7 @@ impl NetLength for SKESK4 {
impl SerializeInto for SKESK4 {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1801,11 +1708,6 @@ impl SerializeInto for SKESK4 {
impl Serialize for SKESK5 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let len = self.net_len();
-
- CTB::new(Tag::SKESK).serialize(o)?;
- BodyLength::Full(len as u32).serialize(o)?;
-
write_byte(o, 5)?; // Version.
write_byte(o, self.symmetric_algo().into())?;
write_byte(o, self.aead_algo().into())?;
@@ -1834,7 +1736,7 @@ impl NetLength for SKESK5 {
impl SerializeInto for SKESK5 {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1857,11 +1759,6 @@ impl Serialize for SEIP {
"Cannot encrypt, use serialize::stream::Encryptor".into())
.into());
} else {
- let body_len = 1
- + self.common.body.as_ref().map(|b| b.len()).unwrap_or(0);
-
- CTB::new(Tag::SEIP).serialize(o)?;
- BodyLength::Full(body_len as u32).serialize(o)?;
o.write_all(&[self.version()])?;
if let Some(ref body) = self.common.body {
o.write_all(&body[..])?;
@@ -1895,8 +1792,6 @@ impl SerializeInto for SEIP {
impl Serialize for MDC {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- CTB::new(Tag::MDC).serialize(o)?;
- BodyLength::Full(20).serialize(o)?;
o.write_all(self.hash())?;
Ok(())
}
@@ -1910,7 +1805,7 @@ impl NetLength for MDC {
impl SerializeInto for MDC {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -1967,10 +1862,6 @@ impl Serialize for AED1 {
"Cannot encrypt, use serialize::stream::Encryptor".into())
.into());
} else {
- let body_len = self.net_len();
-
- CTB::new(Tag::AED).serialize(o)?;
- BodyLength::Full(body_len as u32).serialize(o)?;
self.serialize_headers(o)?;
if let Some(ref body) = self.common.body {
@@ -1996,7 +1887,7 @@ impl NetLength for AED1 {
impl SerializeInto for AED1 {
fn serialized_len(&self) -> usize {
- self.gross_len()
+ self.net_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
@@ -2010,21 +1901,34 @@ impl Serialize for Packet {
/// This function works recursively: if the packet contains any
/// packets, they are also serialized.
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
- let tag = self.tag();
+ CTB::new(self.tag()).serialize(o)?;
+
+ // Special-case the compressed data packet, because we need
+ // the accurate length, and CompressedData::net_len()
+ // overestimates the size.
+ if let Packet::CompressedData(ref p) = self {
+ let mut body = Vec::new();
+ p.serialize(&mut body)?;
+ BodyLength::Full(body.len() as u32).serialize(o)?;
+ o.write_all(&body)?;
+ return Ok(());
+ }
+
+ BodyLength::Full(self.net_len() as u32).serialize(o)?;
match self {
&Packet::Unknown(ref p) => p.serialize(o),
&Packet::Signature(ref p) => p.serialize(o),
&Packet::OnePassSig(ref p) => p.serialize(o),
- &Packet::PublicKey(ref p) => p.serialize(o, tag),
- &Packet::PublicSubkey(ref p) => p.serialize(o, tag),
- &Packet::SecretKey(ref p) => p.serialize(o, tag),
- &Packet::SecretSubkey(ref p) => p.serialize(o, tag),
+ &Packet::PublicKey(ref p) => p.serialize_key(o, false),
+ &Packet::PublicSubkey(ref p) => p.serialize_key(o, false),
+ &Packet::SecretKey(ref p) => p.serialize_key(o, true),
+ &Packet::SecretSubkey(ref p) => p.serialize_key(o, true),
&Packet::Marker(ref p) => p.serialize(o),
&Packet::Trust(ref p) => p.serialize(o),
&Packet::UserID(ref p) => p.serialize(o),
&Packet::UserAttribute(ref p) => p.serialize(o),
&Packet::Literal(ref p) => p.serialize(o),
- &Packet::CompressedData(ref p) => p.serialize(o),
+ &Packet::CompressedData(_) => unreachable!("handled above"),
&Packet::PKESK(ref p) => p.serialize(o),
&Packet::SKESK(ref p) => p.serialize(o),
&Packet::SEIP(ref p) => p.serialize(o),
@@ -2034,17 +1938,41 @@ impl Serialize for Packet {
}
}
+impl NetLength for Packet {
+ fn net_len(&self) -> usize {
+ match self {
+