summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2022-03-02 14:44:21 +0100
committerJustus Winter <justus@sequoia-pgp.org>2022-03-02 14:44:21 +0100
commitd9dcc59787177cc8171d22b600d6f32efc62564a (patch)
treedf312a7973dc0e4b47402f2303eb36fec850e695
parentcc038d2d34598ada45f7417c0f253ed96f6661d1 (diff)
wip: very rough padding packet supportjustus/openpgp-next-padding
-rw-r--r--openpgp/src/packet/header/mod.rs1
-rw-r--r--openpgp/src/packet/mod.rs15
-rw-r--r--openpgp/src/packet/padding.rs92
-rw-r--r--openpgp/src/packet/prelude.rs1
-rw-r--r--openpgp/src/packet/tag.rs6
-rw-r--r--openpgp/src/parse.rs18
-rw-r--r--openpgp/src/serialize.rs27
7 files changed, 157 insertions, 3 deletions
diff --git a/openpgp/src/packet/header/mod.rs b/openpgp/src/packet/header/mod.rs
index 0040d501..40bf2943 100644
--- a/openpgp/src/packet/header/mod.rs
+++ b/openpgp/src/packet/header/mod.rs
@@ -205,6 +205,7 @@ impl Header {
Tag::Marker => l == 3,
Tag::Reserved => true,
+ Tag::Padding => true,
};
if ! valid {
diff --git a/openpgp/src/packet/mod.rs b/openpgp/src/packet/mod.rs
index 991d3e38..d3703feb 100644
--- a/openpgp/src/packet/mod.rs
+++ b/openpgp/src/packet/mod.rs
@@ -205,6 +205,8 @@ pub mod pkesk;
mod mdc;
pub use self::mdc::MDC;
pub mod aed;
+mod padding;
+pub use self::padding::Padding;
/// Enumeration of packet types.
///
@@ -273,6 +275,8 @@ pub enum Packet {
MDC(MDC),
/// AEAD Encrypted Data Packet.
AED(AED),
+ /// Padding packet.
+ Padding(Padding),
}
assert_send_and_sync!(Packet);
@@ -348,6 +352,7 @@ impl Packet {
Packet::SEIP(_) => Tag::SEIP,
Packet::MDC(_) => Tag::MDC,
Packet::AED(_) => Tag::AED,
+ Packet::Padding(_) => Tag::Padding,
}
}
@@ -390,6 +395,7 @@ impl Packet {
Packet::SEIP(p) => Some(p.version()),
Packet::MDC(_) => None,
Packet::AED(p) => Some(p.version()),
+ Packet::Padding(_) => None,
}
}
@@ -431,6 +437,7 @@ impl Packet {
Packet::MDC(x) => Hash::hash(&x, state),
Packet::AED(x) => Hash::hash(&x, state),
Packet::Unknown(x) => Hash::hash(&x, state),
+ Packet::Padding(x) => Padding::hash(&x, state),
}
}
}
@@ -460,6 +467,7 @@ impl Deref for Packet {
Packet::SEIP(ref packet) => &packet.common,
Packet::MDC(ref packet) => &packet.common,
Packet::AED(ref packet) => &packet.common,
+ Packet::Padding(packet) => &packet.common,
}
}
}
@@ -486,6 +494,7 @@ impl DerefMut for Packet {
Packet::SEIP(ref mut packet) => &mut packet.common,
Packet::MDC(ref mut packet) => &mut packet.common,
Packet::AED(ref mut packet) => &mut packet.common,
+ Packet::Padding(packet) => &mut packet.common,
}
}
}
@@ -513,6 +522,7 @@ impl fmt::Debug for Packet {
SEIP(v) => write!(f, "SEIP({:?})", v),
MDC(v) => write!(f, "MDC({:?})", v),
AED(v) => write!(f, "AED({:?})", v),
+ Padding(v) => write!(f, "Padding({:?})", v),
}
}
@@ -539,7 +549,7 @@ impl Arbitrary for Packet {
fn arbitrary(g: &mut Gen) -> Self {
use crate::arbitrary_helper::gen_arbitrary_from_range;
- match gen_arbitrary_from_range(0..15, g) {
+ match gen_arbitrary_from_range(0..16, g) {
0 => Signature::arbitrary(g).into(),
1 => OnePassSig::arbitrary(g).into(),
2 => Key::<key::PublicParts, key::UnspecifiedRole>::arbitrary(g)
@@ -558,7 +568,8 @@ impl Arbitrary for Packet {
11 => CompressedData::arbitrary(g).into(),
12 => PKESK::arbitrary(g).into(),
13 => SKESK::arbitrary(g).into(),
- 14 => loop {
+ 14 => Padding::arbitrary(g).into(),
+ 15 => loop {
let mut u = Unknown::new(
Tag::arbitrary(g), anyhow::anyhow!("Arbitrary::arbitrary"));
u.set_body(Arbitrary::arbitrary(g));
diff --git a/openpgp/src/packet/padding.rs b/openpgp/src/packet/padding.rs
new file mode 100644
index 00000000..6b7fab5f
--- /dev/null
+++ b/openpgp/src/packet/padding.rs
@@ -0,0 +1,92 @@
+use std::fmt;
+
+#[cfg(test)]
+use quickcheck::{Arbitrary, Gen};
+
+use crate::packet;
+use crate::Packet;
+
+/// Holds a Padding packet.
+///
+/// Padding packets are used to obscure the size of cryptographic
+/// artifacts.
+///
+/// See [Section 5.15 of RFC XXX] for details.
+///
+/// [Section 5.15 of RFC XXX]: https://openpgp-wg.gitlab.io/rfc4880bis/#name-padding-packet-tag-21
+// IMPORTANT: If you add fields to this struct, you need to explicitly
+// IMPORTANT: implement PartialEq, Eq, and Hash.
+#[derive(Clone, PartialEq, Eq, Hash)]
+pub struct Padding {
+ pub(crate) common: packet::Common,
+ value: Vec<u8>,
+}
+
+assert_send_and_sync!(Padding);
+
+impl From<Vec<u8>> for Padding {
+ fn from(u: Vec<u8>) -> Self {
+ Padding {
+ common: Default::default(),
+ value: u,
+ }
+ }
+}
+
+impl fmt::Display for Padding {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ let padding = String::from_utf8_lossy(&self.value[..]);
+ write!(f, "{}", padding)
+ }
+}
+
+impl fmt::Debug for Padding {
+ fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+ write!(f, "Padding {{ {} bytes }}", self.value.len())
+ }
+}
+
+impl Padding {
+ /// Creates a new Padding packet of the given size.
+ ///
+ /// Note that this is the net size, packet framing (CTB and packet
+ /// length) will come on top.
+ pub fn new(size: usize) -> Padding {
+ let mut v = vec![0; size];
+ crate::crypto::random(&mut v);
+ v.into()
+ }
+
+ /// Gets the padding packet's value.
+ pub(crate) fn value(&self) -> &[u8] {
+ self.value.as_slice()
+ }
+}
+
+impl From<Padding> for Packet {
+ fn from(s: Padding) -> Self {
+ Packet::Padding(s)
+ }
+}
+
+#[cfg(test)]
+impl Arbitrary for Padding {
+ fn arbitrary(g: &mut Gen) -> Self {
+ Vec::<u8>::arbitrary(g).into()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::parse::Parse;
+ use crate::serialize::MarshalInto;
+
+ quickcheck! {
+ fn roundtrip(p: Padding) -> bool {
+ let q = Padding::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 74b96284..f1a81583 100644
--- a/openpgp/src/packet/prelude.rs
+++ b/openpgp/src/packet/prelude.rs
@@ -33,6 +33,7 @@ pub use crate::packet::{
OnePassSig,
PKESK,
Packet,
+ Padding,
SEIP,
SKESK,
Signature,
diff --git a/openpgp/src/packet/tag.rs b/openpgp/src/packet/tag.rs
index a1fc9768..956f91fc 100644
--- a/openpgp/src/packet/tag.rs
+++ b/openpgp/src/packet/tag.rs
@@ -54,6 +54,8 @@ pub enum Tag {
///
/// This feature is [experimental](crate#experimental-features).
AED,
+ /// Padding packet.
+ Padding,
/// Unassigned packets (as of RFC4880).
Unknown(u8),
/// Experimental packets.
@@ -116,6 +118,7 @@ impl From<u8> for Tag {
18 => SEIP,
19 => MDC,
20 => AED,
+ 21 => Padding,
60..=63 => Private(u),
_ => Unknown(u),
}
@@ -150,6 +153,7 @@ impl From<&Tag> for u8 {
Tag::SEIP => 18,
Tag::MDC => 19,
Tag::AED => 20,
+ Tag::Padding => 21,
Tag::Private(x) => *x,
Tag::Unknown(x) => *x,
}
@@ -209,6 +213,8 @@ impl fmt::Display for Tag {
f.write_str("Modification Detection Code Packet"),
Tag::AED =>
f.write_str("AEAD Encrypted Data Packet"),
+ Tag::Padding =>
+ f.write_str("Padding Packet"),
Tag::Private(u) =>
f.write_fmt(format_args!("Private/Experimental Packet {}", u)),
Tag::Unknown(u) =>
diff --git a/openpgp/src/parse.rs b/openpgp/src/parse.rs
index 35f0156a..df772c17 100644
--- a/openpgp/src/parse.rs
+++ b/openpgp/src/parse.rs
@@ -2871,6 +2871,19 @@ impl AED1 {
}
}
+impl Padding {
+ /// Parses the body of a padding packet.
+ fn parse<'a, T: 'a + BufferedReader<Cookie>>(mut php: PacketHeaderParser<T>)
+ -> Result<PacketParser<'a>>
+ {
+ make_php_try!(php);
+ let value = php_try!(php.parse_bytes_eof("value"));
+ php.ok(Packet::Padding(Padding::from(value)))
+ }
+}
+
+impl_parse_generic_packet!(Padding);
+
impl MPI {
/// Parses an OpenPGP MPI.
///
@@ -4134,6 +4147,7 @@ impl <'a> PacketParser<'a> {
Err(Error::MalformedPacket("Looks like garbage".into()).into()),
Tag::Marker => Marker::plausible(bio, header),
+ Tag::Padding => Ok(()),
Tag::Signature => Signature::plausible(bio, header),
Tag::SecretKey => Key::plausible(bio, header),
@@ -4364,6 +4378,7 @@ impl <'a> PacketParser<'a> {
Tag::MDC => MDC::parse(parser),
Tag::PKESK => PKESK::parse(parser),
Tag::AED => AED::parse(parser),
+ Tag::Padding => Padding::parse(parser),
_ => Unknown::parse(parser,
Error::UnsupportedPacketType(tag).into()),
}?;
@@ -4649,7 +4664,8 @@ impl <'a> PacketParser<'a> {
| Packet::Marker(_) | Packet::Trust(_)
| Packet::UserID(_) | Packet::UserAttribute(_)
| Packet::Literal(_) | Packet::PKESK(_) | Packet::SKESK(_)
- | Packet::SEIP(_) | Packet::MDC(_) | Packet::AED(_) => {
+ | Packet::SEIP(_) | Packet::MDC(_) | Packet::AED(_)
+ | Packet::Padding(_) => {
// Drop through.
t!("A {:?} packet is not a container, not recursing.",
self.packet.tag());
diff --git a/openpgp/src/serialize.rs b/openpgp/src/serialize.rs
index afbf1646..9ce63729 100644
--- a/openpgp/src/serialize.rs
+++ b/openpgp/src/serialize.rs
@@ -2549,6 +2549,30 @@ impl MarshalInto for AED1 {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
+
+impl seal::Sealed for Padding {}
+impl Marshal for Padding {
+ fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
+ o.write_all(self.value())?;
+ Ok(())
+ }
+}
+
+impl NetLength for Padding {
+ fn net_len(&self) -> usize {
+ self.value().len()
+ }
+}
+
+impl MarshalInto for Padding {
+ fn serialized_len(&self) -> usize {
+ self.net_len()
+ }
+
+ fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
+ generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
+ }
+}
impl Serialize for Packet {}
impl seal::Sealed for Packet {}
@@ -2591,6 +2615,7 @@ impl Marshal for Packet {
Packet::SEIP(ref p) => p.serialize(o),
Packet::MDC(ref p) => p.serialize(o),
Packet::AED(ref p) => p.serialize(o),
+ Packet::Padding(p) => p.serialize(o),
}
}
@@ -2632,6 +2657,7 @@ impl Marshal for Packet {
Packet::SEIP(ref p) => p.export(o),
Packet::MDC(ref p) => p.export(o),
Packet::AED(ref p) => p.export(o),
+ Packet::Padding(p) => p.export(o),
}
}
}
@@ -2657,6 +2683,7 @@ impl NetLength for Packet {
Packet::SEIP(ref p) => p.net_len(),
Packet::MDC(ref p) => p.net_len(),
Packet::AED(ref p) => p.net_len(),
+ Packet::Padding(p) => p.net_len(),
}
}
}