use std::io::{self, Write};
use std::cmp;
use std::convert::{TryFrom, TryInto};
use super::*;
mod cert;
pub use self::cert::TSK;
mod cert_armored;
pub mod stream;
use crate::crypto::S2K;
use crate::packet::header::{
BodyLength,
CTB,
CTBNew,
CTBOld,
};
use crate::packet::signature::subpacket::{
SubpacketArea, Subpacket, SubpacketValue, SubpacketLength
};
use crate::packet::prelude::*;
use crate::types::{
RevocationKey,
Timestamp,
};
const TRACE : bool = false;
pub trait Serialize : Marshal {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
Marshal::serialize(self, o)
}
fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
Marshal::export(self, o)
}
}
pub trait Marshal {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()>;
fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
self.serialize(o)
}
}
pub trait SerializeInto : MarshalInto {
fn serialized_len(&self) -> usize {
MarshalInto::serialized_len(self)
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
MarshalInto::serialize_into(self, buf)
}
fn to_vec(&self) -> Result<Vec<u8>> {
MarshalInto::to_vec(self)
}
fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
MarshalInto::export_into(self, buf)
}
fn export_to_vec(&self) -> Result<Vec<u8>> {
MarshalInto::export_to_vec(self)
}
}
pub trait MarshalInto {
fn serialized_len(&self) -> usize;
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize>;
fn to_vec(&self) -> Result<Vec<u8>> {
let mut o = vec![0; self.serialized_len()];
let len = self.serialize_into(&mut o[..])?;
vec_truncate(&mut o, len);
o.shrink_to_fit();
Ok(o)
}
fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
self.serialize_into(buf)
}
fn export_to_vec(&self) -> Result<Vec<u8>> {
let mut o = vec![0; self.serialized_len()];
let len = self.export_into(&mut o[..])?;
vec_truncate(&mut o, len);
o.shrink_to_fit();
Ok(o)
}
}
trait NetLength {
fn net_len(&self) -> usize;
fn gross_len(&self) -> usize {
let net = self.net_len();
1
+ BodyLength::Full(net as u32).serialized_len()
+ net
}
}
fn generic_serialize_into(o: &dyn Marshal, serialized_len: usize,
buf: &mut [u8])
-> Result<usize> {
let buf_len = buf.len();
let mut cursor = ::std::io::Cursor::new(buf);
match o.serialize(&mut cursor) {
Ok(_) => (),
Err(e) => {
let short_write =
if let Some(ioe) = e.downcast_ref::<io::Error>() {
ioe.kind() == io::ErrorKind::WriteZero
} else {
false
};
return if short_write {
assert!(buf_len < serialized_len,
"o.serialized_len() underestimated the required space");
Err(Error::InvalidArgument(
format!("Invalid buffer size, expected {}, got {}",
serialized_len, buf_len)).into())
} else {
Err(e)
}
}
};
Ok(cursor.position() as usize)
}
fn generic_export_into(o: &dyn Marshal, serialized_len: usize,
buf: &mut [u8])
-> Result<usize> {
let buf_len = buf.len();
let mut cursor = ::std::io::Cursor::new(buf);
match o.export(&mut cursor) {
Ok(_) => (),
Err(e) => {
let short_write =
if let Some(ioe) = e.downcast_ref::<io::Error>() {
ioe.kind() == io::ErrorKind::WriteZero
} else {
false
};
return if short_write {
assert!(buf_len < serialized_len,
"o.serialized_len() underestimated the required space");
Err(Error::InvalidArgument(
format!("Invalid buffer size, expected {}, got {}",
serialized_len, buf_len)).into())
} else {
Err(e)
}
}
};
Ok(cursor.position() as usize)
}
#[test]
fn test_generic_serialize_into() {
let u = UserID::from("Mr. Pink");
let mut b = vec![0; u.serialized_len()];
u.serialize_into(&mut b[..]).unwrap();
let mut b = vec![0; u.serialized_len() - 1];
let e = u.serialize_into(&mut b[..]).unwrap_err();
assert_match!(Some(Error::InvalidArgument(_)) = e.downcast_ref());
}
#[test]
fn test_generic_export_into() {
let u = UserID::from("Mr. Pink");
let mut b = vec![0; u.serialized_len()];
u.export_into(&mut b[..]).unwrap();
let mut b = vec![0; u.serialized_len() - 1];
let e = u.export_into(&mut b[..]).unwrap_err();
assert_match!(Some(Error::InvalidArgument(_)) = e.downcast_ref());
}
fn write_byte(o: &mut dyn std::io::Write, b: u8) -> io::Result<()> {
o.write_all(&[b])
}
fn write_be_u16(o: &mut dyn std::io::Write, n: u16) -> io::Result<()> {
o.write_all(&n.to_be_bytes())
}
fn write_be_u32(o: &mut dyn std::io::Write, n: u32) -> io::Result<()> {
o.write_all(&n.to_be_bytes())
}
fn log2(x: u32) -> usize {
if x == 0 {
0
} else {
31 - x.leading_zeros() as usize
}
}
#[test]
fn log2_test() {
for i in 0..32 {
assert_eq!(log2(1u32 << i), i);
if i > 0 {
assert_eq!(log2((1u32 << i) - 1), i - 1);
assert_eq!(log2((1u32 << i) + 1), i);
}
}
}
impl Marshal for BodyLength {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
&BodyLength::Full(l) => {
if l <= 191 {
write_byte(o, l as u8)?;
} else if l <= 8383 {
let v = l - 192;
let v = v + (192 << 8);
write_be_u16(o, v as u16)?;
} else {
write_byte(o, 0xff)?;
write_be_u32(o, l)?;
}
},
&BodyLength::Partial(l) => {
if l > 1 << 30 {
return Err(Error::InvalidArgument(
format!("Partial length too large: {}", l)).into());
}
let chunk_size_log2 = log2(l);
let chunk_size = 1 << chunk_size_log2;
if l != chunk_size {
return Err(Error::InvalidArgument(
format!("Not a power of two: {}", l)).into());
}
let size_byte = 224 + chunk_size_log2;
assert!(size_byte < 255);
write_byte(o, size_byte as u8)?;
},
&BodyLength::Indeterminate =>
return Err(Error::InvalidArgument(
"Indeterminate lengths are not support for new format packets".
into()).into()),
}
Ok(())
}
}
impl MarshalInto for BodyLength {
fn serialized_len(&self) -> usize {
match self {
&BodyLength::Full(l) => {
if l <= 191 {
1
} else if l <= 8383 {
2
} else {
5
}
},
&BodyLength::Partial(_) => 1,
&BodyLength::Indeterminate => 0,
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl BodyLength {
pub fn serialize_old<W: io::Write>(&self, o: &mut W) -> Result<()> {
let mut buffer = Vec::with_capacity(4);
match self {
&BodyLength::Full(l) => {
match l {
0 ..= 0xFF =>
write_byte(&mut buffer, l as u8).unwrap(),
0x1_00 ..= 0xFF_FF =>
write_be_u16(&mut buffer, l as u16).unwrap(),
_ =>
write_be_u32(&mut buffer, l as u32).unwrap(),
}
},
&BodyLength::Indeterminate => {},
&BodyLength::Partial(_) =>
return Err(Error::InvalidArgument(
"Partial body lengths are not support for old format packets".
into()).into()),
}
o.write_all(&buffer)?;
Ok(())
}
}
impl Marshal for CTBNew {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
let tag: u8 = self.tag().into();
o.write_all(&[0b1100_0000u8 | tag])?;
Ok(())
}
}
impl MarshalInto for CTBNew {
fn serialized_len(&self) -> usize { 1 }
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for CTBOld {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
let tag: u8 = self.tag().into();
let length_type: u8 = self.length_type().into();
o.write_all(&[0b1000_0000u8 | (tag << 2) | length_type])?;
Ok(())
}
}
impl MarshalInto for CTBOld {
fn serialized_len(&self) -> usize { 1 }
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for CTB {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
&CTB::New(ref c) => c.serialize(o),
&CTB::Old(ref c) => c.serialize(o),
}?;
Ok(())
}
}
impl MarshalInto for CTB {
fn serialized_len(&self) -> usize { 1 }
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for Header {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
self.ctb().serialize(o)?;
self.length().serialize(o)?;
Ok(())
}
}
impl MarshalInto for Header {
fn serialized_len(&self) -> usize {
self.ctb().serialized_len() + self.length().serialized_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Serialize for KeyID {}
impl Marshal for KeyID {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
let raw = match self {
&KeyID::V4(ref fp) => &fp[..],
&KeyID::Invalid(ref fp) => &fp[..],
KeyID::__Nonexhaustive => unreachable!(),
};
o.write_all(raw)?;
Ok(())
}
}
impl SerializeInto for KeyID {}
impl MarshalInto for KeyID {
fn serialized_len(&self) -> usize {
match self {
&KeyID::V4(_) => 8,
&KeyID::Invalid(ref fp) => fp.len(),
KeyID::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Serialize for Fingerprint {}
impl Marshal for Fingerprint {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
o.write_all(self.as_bytes())?;
Ok(())
}
}
impl SerializeInto for Fingerprint {}
impl MarshalInto for Fingerprint {
fn serialized_len(&self) -> usize {
match self {
Fingerprint::V4(_) => 20,
Fingerprint::Invalid(ref fp) => fp.len(),
Fingerprint::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for crypto::mpi::MPI {
fn serialize(&self, w: &mut dyn std::io::Write) -> Result<()> {
write_be_u16(w, self.bits() as u16)?;
w.write_all(self.value())?;
Ok(())
}
}
impl MarshalInto for crypto::mpi::MPI {
fn serialized_len(&self) -> usize {
2 + self.value().len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for crypto::mpi::ProtectedMPI {
fn serialize(&self, w: &mut dyn std::io::Write) -> Result<()> {
write_be_u16(w, self.bits() as u16)?;
w.write_all(self.value())?;
Ok(())
}
}
impl MarshalInto for crypto::mpi::ProtectedMPI {
fn serialized_len(&self) -> usize {
2 + self.value().len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
fn write_field_with_u8_size(w: &mut dyn Write, name: &str, buf: &[u8])
-> Result<()> {
w.write_all(&[buf.len().try_into()
.map_err(|_| anyhow::Error::from(
Error::InvalidArgument(
format!("{} exceeds 255 bytes: {:?}",
name, buf))))?])?;
w.write_all(buf)?;
Ok(())
}
impl Marshal for crypto::mpi::PublicKey {
fn serialize(&self, w: &mut dyn std::io::Write) -> Result<()> {
use crate::crypto::mpi::PublicKey::*;
match self {
&RSA { ref e, ref n } => {
n.serialize(w)?;
e.serialize(w)?;
}
&DSA { ref p, ref q, ref g, ref y } => {
p.serialize(w)?;
q.serialize(w)?;
g.serialize(w)?;
y.serialize(w)?;
}
&ElGamal { ref p, ref g, ref y } => {
p.serialize(w)?;
g.serialize(w)?;
y.serialize(w)?;
}
&EdDSA { ref curve, ref q } => {
write_field_with_u8_size(w, "Curve's OID", curve.oid())?;
q.serialize(w)?;
}
&ECDSA { ref curve, ref q } => {
write_field_with_u8_size(w, "Curve's OID", curve.oid())?;
q.serialize(w)?;
}
&ECDH { ref curve, ref q, hash, sym } => {
write_field_with_u8_size(w, "Curve's OID", curve.oid())?;
q.serialize(w)?;
w.write_all(&[3u8, 1u8, u8::from(hash), u8::from(sym)])?;
}
&Unknown { ref mpis, ref rest } => {
for mpi in mpis.iter() {
mpi.serialize(w)?;
}
w.write_all(rest)?;
}
__Nonexhaustive => unreachable!(),
}
Ok(())
}
}
impl MarshalInto for crypto::mpi::PublicKey {
fn serialized_len(&self) -> usize {
use crate::crypto::mpi::PublicKey::*;
match self {
&RSA { ref e, ref n } => {
n.serialized_len() + e.serialized_len()
}
&DSA { ref p, ref q, ref g, ref y } => {
p.serialized_len() + q.serialized_len() + g.serialized_len()
+ y.serialized_len()
}
&ElGamal { ref p, ref g, ref y } => {
p.serialized_len() + g.serialized_len() + y.serialized_len()
}
&EdDSA { ref curve, ref q } => {
1 + curve.oid().len() + q.serialized_len()
}
&ECDSA { ref curve, ref q } => {
1 + curve.oid().len() + q.serialized_len()
}
&ECDH { ref curve, ref q, hash: _, sym: _ } => {
1 + curve.oid().len() + q.serialized_len() + 4
}
&Unknown { ref mpis, ref rest } => {
mpis.iter().map(|mpi| mpi.serialized_len()).sum::<usize>()
+ rest.len()
}
__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for crypto::mpi::SecretKeyMaterial {
fn serialize(&self, w: &mut dyn std::io::Write) -> Result<()> {
use crate::crypto::mpi::SecretKeyMaterial::*;
match self {
&RSA{ ref d, ref p, ref q, ref u } => {
d.serialize(w)?;
p.serialize(w)?;
q.serialize(w)?;
u.serialize(w)?;
}
&DSA{ ref x } => {
x.serialize(w)?;
}
&ElGamal{ ref x } => {
x.serialize(w)?;
}
&EdDSA{ ref scalar } => {
scalar.serialize(w)?;
}
&ECDSA{ ref scalar } => {
scalar.serialize(w)?;
}
&ECDH{ ref scalar } => {
scalar.serialize(w)?;
}
&Unknown { ref mpis, ref rest } => {
for mpi in mpis.iter() {
mpi.serialize(w)?;
}
w.write_all(rest)?;
}
__Nonexhaustive => unreachable!(),
}
Ok(())
}
}
impl MarshalInto for crypto::mpi::SecretKeyMaterial {
fn serialized_len(&self) -> usize {
use crate::crypto::mpi::SecretKeyMaterial::*;
match self {
&RSA{ ref d, ref p, ref q, ref u } => {
d.serialized_len() + p.serialized_len() + q.serialized_len()
+ u.serialized_len()
}
&DSA{ ref x } => {
x.serialized_len()
}
&ElGamal{ ref x } => {
x.serialized_len()
}
&EdDSA{ ref scalar } => {
scalar.serialized_len()
}
&ECDSA{ ref scalar } => {
scalar.serialized_len()
}
&ECDH{ ref scalar } => {
scalar.serialized_len()
}
&Unknown { ref mpis, ref rest } => {
mpis.iter().map(|mpi| mpi.serialized_len()).sum::<usize>()
+ rest.len()
}
__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl crypto::mpi::SecretKeyMaterial {
pub fn serialize_with_checksum(
&self, w: &mut dyn io::Write,
checksum: crypto::mpi::SecretKeyChecksum)
-> Result<()>
{
self.serialize(w)?;
match checksum {
crypto::mpi::SecretKeyChecksum::SHA1 => {
let mut hash = HashAlgorithm::SHA1.context().unwrap();
self.serialize(&mut hash)?;
let mut digest = [0u8; 20];
hash.digest(&mut digest);
w.write_all(&digest)?;
},
crypto::mpi::SecretKeyChecksum::Sum16 => {
w.write_all(&self.to_vec()?.iter()
.fold(0u16, |acc, v| acc.wrapping_add(*v as u16))
.to_be_bytes())?;
},
}
Ok(())
}
}
impl Marshal for crypto::mpi::Ciphertext {
fn serialize(&self, w: &mut dyn std::io::Write) -> Result<()> {
use crate::crypto::mpi::Ciphertext::*;
match self {
&RSA{ ref c } => {
c.serialize(w)?;
}
&ElGamal{ ref e, ref c } => {
e.serialize(w)?;
c.serialize(w)?;
}
&ECDH{ ref e, ref key } => {
e.serialize(w)?;
write_field_with_u8_size(w, "Key", key)?;
}
&Unknown { ref mpis, ref rest } => {
for mpi in mpis.iter() {
mpi.serialize(w)?;
}
w.write_all(rest)?;
}
__Nonexhaustive => unreachable!(),
}
Ok(())
}
}
impl MarshalInto for crypto::mpi::Ciphertext {
fn serialized_len(&self) -> usize {
use crate::crypto::mpi::Ciphertext::*;
match self {
&RSA{ ref c } => {
c.serialized_len()
}
&ElGamal{ ref e, ref c } => {
e.serialized_len() + c.serialized_len()
}
&ECDH{ ref e, ref key } => {
e.serialized_len() + 1 + key.len()
}
&Unknown { ref mpis, ref rest } => {
mpis.iter().map(|mpi| mpi.serialized_len()).sum::<usize>()
+ rest.len()
}
__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for crypto::mpi::Signature {
fn serialize(&self, w: &mut dyn std::io::Write) -> Result<()> {
use crate::crypto::mpi::Signature::*;
match self {
&RSA { ref s } => {
s.serialize(w)?;
}
&DSA { ref r, ref s } => {
r.serialize(w)?;
s.serialize(w)?;
}
&ElGamal { ref r, ref s } => {
r.serialize(w)?;
s.serialize(w)?;
}
&EdDSA { ref r, ref s } => {
r.serialize(w)?;
s.serialize(w)?;
}
&ECDSA { ref r, ref s } => {
r.serialize(w)?;
s.serialize(w)?;
}
&Unknown { ref mpis, ref rest } => {
for mpi in mpis.iter() {
mpi.serialize(w)?;
}
w.write_all(rest)?;
}
__Nonexhaustive => unreachable!(),
}
Ok(())
}
}
impl MarshalInto for crypto::mpi::Signature {
fn serialized_len(&self) -> usize {
use crate::crypto::mpi::Signature::*;
match self {
&RSA { ref s } => {
s.serialized_len()
}
&DSA { ref r, ref s } => {
r.serialized_len() + s.serialized_len()
}
&ElGamal { ref r, ref s } => {
r.serialized_len() + s.serialized_len()
}
&EdDSA { ref r, ref s } => {
r.serialized_len() + s.serialized_len()
}
&ECDSA { ref r, ref s } => {
r.serialized_len() + s.serialized_len()
}
&Unknown { ref mpis, ref rest } => {
mpis.iter().map(|mpi| mpi.serialized_len()).sum::<usize>()
+ rest.len()
}
__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for S2K {
fn serialize(&self, w: &mut dyn std::io::Write) -> Result<()> {
#[allow(deprecated)]
match self {
&S2K::Simple{ hash } => {
w.write_all(&[0, hash.into()])?;
}
&S2K::Salted{ hash, salt } => {
w.write_all(&[1, hash.into()])?;
w.write_all(&salt[..])?;
}
&S2K::Iterated{ hash, salt, hash_bytes } => {
w.write_all(&[3, hash.into()])?;
w.write_all(&salt[..])?;
w.write_all(&[S2K::encode_count(hash_bytes)?])?;
}
S2K::Private { tag, parameters }
| S2K::Unknown { tag, parameters} => {
w.write_all(&[*tag])?;
if let Some(p) = parameters.as_ref() {
w.write_all(p)?;
}
}
S2K::__Nonexhaustive => unreachable!(),
}
Ok(())
}
}
impl MarshalInto for S2K {
fn serialized_len(&self) -> usize {
#[allow(deprecated)]
match self {
&S2K::Simple{ .. } => 2,
&S2K::Salted{ .. } => 2 + 8,
&S2K::Iterated{ .. } => 2 + 8 + 1,
S2K::Private { parameters, .. }
| S2K::Unknown { parameters, .. } =>
1 + parameters.as_ref().map(|p| p.len()).unwrap_or(0),
S2K::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for Unknown {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
o.write_all(self.body())?;
Ok(())
}
}
impl NetLength for Unknown {
fn net_len(&self) -> usize {
self.body().len()
}
}
impl MarshalInto for Unknown {
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 Marshal for SubpacketArea {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
for sb in self.iter() {
sb.serialize(o)?;
}
Ok(())
}
}
impl MarshalInto for SubpacketArea {
fn serialized_len(&self) -> usize {
self.iter().map(|sb| sb.serialized_len()).sum()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
let mut written = 0;
for sb in self.iter() {
let n = sb.serialize_into(&mut buf[written..])?;
written += cmp::min(buf.len() - written, n);
}
Ok(written)
}
}
impl Marshal for Subpacket {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
let tag = u8::from(self.tag())
| if self.critical() { 1 << 7 } else { 0 };
self.length.serialize(o)?;
o.write_all(&[tag])?;
self.value().serialize(o)
}
}
impl MarshalInto for Subpacket {
fn serialized_len(&self) -> usize {
self.length.serialized_len() + 1 + self.value().serialized_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for SubpacketValue {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
use self::SubpacketValue::*;
match self {
SignatureCreationTime(t) =>
write_be_u32(o, t.clone().into())?,
SignatureExpirationTime(t) =>
write_be_u32(o, t.clone().into())?,
ExportableCertification(e) =>
o.write_all(&[if *e { 1 } else { 0 }])?,
TrustSignature { ref level, ref trust } =>
o.write_all(&[*level, *trust])?,
RegularExpression(ref re) => {
o.write_all(re)?;
o.write_all(&[0])?;
},
Revocable(r) =>
o.write_all(&[if *r { 1 } else { 0 }])?,
KeyExpirationTime(t) =>
write_be_u32(o, t.clone().into())?,
PreferredSymmetricAlgorithms(ref p) =>
for a in p {
o.write_all(&[(*a).into()])?;
},
RevocationKey(rk) => rk.serialize(o)?,
Issuer(ref id) =>
o.write_all(id.as_bytes())?,
NotationData(nd) => {
o.write_all(nd.flags().as_slice())?;
write_be_u16(o, nd.name().len() as u16)?;
write_be_u16(o, nd.value().len() as u16)?;
o.write_all(nd.name().as_bytes())?;
o.write_all(nd.value())?;
},
PreferredHashAlgorithms(ref p) =>
for a in p {
o.write_all(&[(*a).into()])?;
},
PreferredCompressionAlgorithms(ref p) =>
for a in p {
o.write_all(&[(*a).into()])?;
},
KeyServerPreferences(ref p) =>
o.write_all(p.as_slice())?,
PreferredKeyServer(ref p) =>
o.write_all(p)?,
PrimaryUserID(p) =>
o.write_all(&[if *p { 1 } else { 0 }])?,
PolicyURI(ref p) =>
o.write_all(p)?,
KeyFlags(ref f) =>
o.write_all(f.as_slice())?,
SignersUserID(ref uid) =>
o.write_all(uid)?,
ReasonForRevocation { ref code, ref reason } => {
o.write_all(&[(*code).into()])?;
o.write_all(reason)?;
},
Features(ref f) =>
o.write_all(&f.as_slice())?,
SignatureTarget { pk_algo, hash_algo, ref digest } => {
o.write_all(&[(*pk_algo).into(), (*hash_algo).into()])?;
o.write_all(digest)?;
},
EmbeddedSignature(sig) => sig.serialize(o)?,
IssuerFingerprint(ref fp) => match fp {
Fingerprint::V4(_) => {
o.write_all(&[4])?;
o.write_all(fp.as_bytes())?;
},
_ => return Err(Error::InvalidArgument(
"Unknown kind of fingerprint".into()).into()),
}
PreferredAEADAlgorithms(ref p) =>
for a in p {
o.write_all(&[(*a).into()])?;
},
IntendedRecipient(ref fp) => match fp {
Fingerprint::V4(_) => {
o.write_all(&[4])?;
o.write_all(fp.as_bytes())?;
},
_ => return Err(Error::InvalidArgument(
"Unknown kind of fingerprint".into()).into()),
}
Unknown { body, .. } =>
o.write_all(body)?,
__Nonexhaustive => unreachable!(),
}
Ok(())
}
}
impl MarshalInto for SubpacketValue {
fn serialized_len(&self) -> usize {
use self::SubpacketValue::*;
match self {
SignatureCreationTime(_) => 4,
SignatureExpirationTime(_) => 4,
ExportableCertification(_) => 1,
TrustSignature { .. } => 2,
RegularExpression(ref re) => re.len() + 1,
Revocable(_) => 1,
KeyExpirationTime(_) => 4,
PreferredSymmetricAlgorithms(ref p) => p.len(),
RevocationKey(rk) => rk.serialized_len(),
Issuer(ref id) => (id as &dyn MarshalInto).serialized_len(),
NotationData(nd) => 4 + 2 + 2 + nd.name().len() + nd.value().len(),
PreferredHashAlgorithms(ref p) => p.len(),
PreferredCompressionAlgorithms(ref p) => p.len(),
KeyServerPreferences(ref p) => p.as_slice().len(),
PreferredKeyServer(ref p) => p.len(),
PrimaryUserID(_) => 1,
PolicyURI(ref p) => p.len(),
KeyFlags(ref f) => f.as_slice().len(),
SignersUserID(ref uid) => uid.len(),
ReasonForRevocation { ref reason, .. } => 1 + reason.len(),
Features(ref f) => f.as_slice().len(),
SignatureTarget { ref digest, .. } => 2 + digest.len(),
EmbeddedSignature(sig) => sig.serialized_len(),
IssuerFingerprint(ref fp) => match fp {
Fingerprint::V4(_) =>
1 + (fp as &dyn MarshalInto).serialized_len(),
Fingerprint::Invalid(_) => 1 + fp.as_bytes().len(),
Fingerprint::__Nonexhaustive => unreachable!(),
},
PreferredAEADAlgorithms(ref p) => p.len(),
IntendedRecipient(ref fp) => match fp {
Fingerprint::V4(_) =>
1 + (fp as &dyn MarshalInto).serialized_len(),
Fingerprint::Invalid(_) => 1 + fp.as_bytes().len(),
Fingerprint::__Nonexhaustive => unreachable!(),
},
Unknown { body, .. } => body.len(),
__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for SubpacketLength {
fn serialize(&self, sink: &mut dyn std::io::Write)
-> Result<()> {
match self.raw {
Some(ref raw) => sink.write_all(raw)?,
None => {
BodyLength::serialize(&BodyLength::Full(self.len() as u32), sink)?
}
};
Ok(())
}
}
impl MarshalInto for SubpacketLength {
fn serialized_len(&self) -> usize {
if let Some(ref raw) = self.raw {
raw.len()
} else {
Self::len_optimal_encoding(self.len() as u32)
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for RevocationKey {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
let (pk_algo, fp) = self.revoker();
o.write_all(&[self.class(), (pk_algo).into()])?;
o.write_all(fp.as_bytes())?;
Ok(())
}
}
impl MarshalInto for RevocationKey {
fn serialized_len(&self) -> usize {
1 + 1 + self.revoker().1.as_bytes().len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for Signature {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
&Signature::V4(ref s) => s.serialize(o),
Signature::__Nonexhaustive => unreachable!(),
}
}
fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
&Signature::V4(ref s) => s.export(o),
Signature::__Nonexhaustive => unreachable!(),
}
}
}
impl MarshalInto for Signature {
fn serialized_len(&self) -> usize {
match self {
&Signature::V4(ref s) => s.serialized_len(),
Signature::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
match self {
&Signature::V4(ref s) => s.serialize_into(buf),
Signature::__Nonexhaustive => unreachable!(),
}
}
fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
match self {
&Signature::V4(ref s) => s.export_into(buf),
Signature::__Nonexhaustive => unreachable!(),
}
}
fn export_to_vec(&self) -> Result<Vec<u8>> {
match self {
&Signature::V4(ref s) => s.export_to_vec(),
Signature::__Nonexhaustive => unreachable!(),
}
}
}
impl Marshal for Signature4 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
assert_eq!(self.version(), 4);
write_byte(o, self.version())?;
write_byte(o, self.typ().into())?;
write_byte(o, self.pk_algo().into())?;
write_byte(o, self.hash_algo().into())?;
let l = self.hashed_area().serialized_len();
if l > std::u16::MAX as usize {
return Err(Error::InvalidArgument(
"Hashed area too large".into()).into());
}
write_be_u16(o, l as u16)?;
self.hashed_area().serialize(o)?;
let l = self.unhashed_area().serialized_len();
if l > std::u16::MAX as usize {
return Err(Error::InvalidArgument(
"Unhashed area too large".into()).into());
}
write_be_u16(o, l as u16)?;
self.unhashed_area().serialize(o)?;
write_byte(o, self.digest_prefix()[0])?;
write_byte(o, self.digest_prefix()[1])?;
self.mpis().serialize(o)?;
Ok(())
}
fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
self.exportable()?;
self.serialize(o)
}
}
impl NetLength for Signature4 {
fn net_len(&self) -> usize {
1
+ 1
+ 1
+ 1
+ 2
+ self.hashed_area().serialized_len()
+ 2
+ self.unhashed_area().serialized_len()
+ 2
+ self.mpis().serialized_len()
}
}
impl MarshalInto for Signature4 {
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)
}
fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
if ! self.exportable_certification().unwrap_or(true) {
return Err(Error::InvalidOperation(
"Cannot export non-exportable certification".into()).into());
}
self.serialize_into(buf)
}
fn export_to_vec(&self) -> Result<Vec<u8>> {
if ! self.exportable_certification().unwrap_or(true) {
return Err(Error::InvalidOperation(
"Cannot export non-exportable certification".into()).into());
}
self.to_vec()
}
}
impl Marshal for OnePassSig {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
&OnePassSig::V3(ref s) => s.serialize(o),
OnePassSig::__Nonexhaustive => unreachable!(),
}
}
}
impl MarshalInto for OnePassSig {
fn serialized_len(&self) -> usize {
match self {
&OnePassSig::V3(ref s) => s.serialized_len(),
OnePassSig::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
match self {
&OnePassSig::V3(ref s) => s.serialize_into(buf),
OnePassSig::__Nonexhaustive => unreachable!(),
}
}
}
impl Marshal for OnePassSig3 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
write_byte(o, 3)?;
write_byte(o, self.typ().into())?;
write_byte(o, self.hash_algo().into())?;
write_byte(o, self.pk_algo().into())?;
o.write_all(self.issuer().as_bytes())?;
write_byte(o, self.last_raw())?;
Ok(())
}
}
impl NetLength for OnePassSig3 {
fn net_len(&self) -> usize {
1
+ 1
+ 1
+ 1
+ 8
+ 1
}
}
impl MarshalInto for OnePassSig3 {
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<P: key::KeyParts, R: key::KeyRole> Marshal for Key<P, R> {
fn serialize(&self, o: &mut dyn io::Write) -> Result<()> {
match self {
&Key::V4(ref p) => p.serialize(o),
Key::__Nonexhaustive => unreachable!(),
}
}
}
impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
fn net_len_key(&self, serialize_secrets: bool) -> usize {
match self {
&Key::V4(ref p) => p.net_len_key(serialize_secrets),
Key::__Nonexhaustive => unreachable!(),
}
}
}
impl<P: key::KeyParts, R: key::KeyRole> MarshalInto for Key<P, R> {
fn serialized_len(&self) -> usize {
match self {
&Key::V4(ref p) => p.serialized_len(),
Key::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
match self {
&Key::V4(ref p) => p.serialize_into(buf),
Key::__Nonexhaustive => unreachable!(),
}
}
}
impl<P, R> Marshal for Key4<P, R>
where P: key::KeyParts,
R: key::KeyRole,
{
fn serialize(&self, o: &mut dyn io::Write) -> Result<()> {
self.serialize_key(o, true)
}
}
impl<P, R> Key4<P, R>
where P: key::KeyParts,
R: key::KeyRole,
{
pub(crate)
fn serialize_key(&self, o: &mut dyn io::Write, serialize_secrets: bool)
-> Result<()> {
let have_secret_key = self.has_secret() && serialize_secrets;
write_byte(o, 4)?;
write_be_u32(o, Timestamp::try_from(self.creation_time())?.into())?;
write_byte(o, self.pk_algo().into())?;
self.mpis().serialize(o)?;
if have_secret_key {
use crypto::mpi::SecretKeyChecksum;
match self.optional_secret().unwrap() {
SecretKeyMaterial::Unencrypted(ref u) => u.map(|mpis| -> Result<()> {
write_byte(o, 0)?;
mpis.serialize_with_checksum(o, SecretKeyChecksum::Sum16)
})?,
SecretKeyMaterial::Encrypted(ref e) => {
write_byte(o, match e.checksum() {
Some(SecretKeyChecksum::SHA1) => 254,
Some(SecretKeyChecksum::Sum16) => 255,
None => return Err(Error::InvalidOperation(
"In Key4 packets, encrypted secret keys must be \
checksummed".into()).into()),
})?;
write_byte(o, e.algo().into())?;
e.s2k().serialize(o)?;
o.write_all(e.raw_ciphertext())?;
},
}
}
Ok(())
}
fn net_len_key(&self, serialize_secrets: bool) -> usize {
let have_secret_key = self.has_secret() && serialize_secrets;
1
+ 4
+ 1
+ self.mpis().serialized_len()
+ if have_secret_key {
1 + match self.optional_secret().unwrap() {
SecretKeyMaterial::Unencrypted(ref u) =>
u.map(|mpis| mpis.serialized_len())
+ 2,
SecretKeyMaterial::Encrypted(ref e) =>
1 + e.s2k().serialized_len()
+ e.raw_ciphertext().len(),
}
} else {
0
}
}
}
impl<P, R> MarshalInto for Key4<P, R>
where P: key::KeyParts,
R: key::KeyRole,
{
fn serialized_len(&self) -> usize {
self.net_len_key(true)
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for Marker {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
o.write_all(Marker::BODY)?;
Ok(())
}
}
impl NetLength for Marker {
fn net_len(&self) -> usize {
Marker::BODY.len()
}
}
impl MarshalInto for Marker {
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 Marshal for Trust {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
o.write_all(self.value())?;
Ok(())
}
}
impl NetLength for Trust {
fn net_len(&self) -> usize {
self.value().len()
}
}
impl MarshalInto for Trust {
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 Marshal for UserID {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
o.write_all(self.value())?;
Ok(())
}
}
impl NetLength for UserID {
fn net_len(&self) -> usize {
self.value().len()
}
}
impl MarshalInto for UserID {
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 Marshal for UserAttribute {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
o.write_all(self.value())?;
Ok(())
}
}
impl NetLength for UserAttribute {
fn net_len(&self) -> usize {
self.value().len()
}
}
impl MarshalInto for UserAttribute {
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 Marshal for user_attribute::Subpacket {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
let body_len = match self {
user_attribute::Subpacket::Image(image) =>
image.serialized_len(),
user_attribute::Subpacket::Unknown(_tag, data) =>
data.len(),
};
BodyLength::Full(1 + body_len as u32).serialize(o)?;
match self {
user_attribute::Subpacket::Image(image) => {
write_byte(o, 1)?;
image.serialize(o)?;
},
user_attribute::Subpacket::Unknown(tag, data) => {
write_byte(o, *tag)?;
o.write_all(&data[..])?;
}
}
Ok(())
}
}
impl MarshalInto for user_attribute::Subpacket {
fn serialized_len(&self) -> usize {
let body_len = match self {
user_attribute::Subpacket::Image(image) =>
image.serialized_len(),
user_attribute::Subpacket::Unknown(_tag, data) =>
data.len(),
};
let header_len =
BodyLength::Full(1 + body_len as u32).serialized_len();
header_len + 1 + body_len
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for user_attribute::Image {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
const V1HEADER_TOP: [u8; 3] = [0x10, 0x00, 0x01];
const V1HEADER_PAD: [u8; 12] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
match self {
user_attribute::Image::JPEG(data) => {
o.write_all(&V1HEADER_TOP[..])?;
write_byte(o, 1)?;
o.write_all(&V1HEADER_PAD[..])?;
o.write_all(&data[..])?;
}
user_attribute::Image::Unknown(tag, data)
| user_attribute::Image::Private(tag, data) => {
o.write_all(&V1HEADER_TOP[..])?;
write_byte(o, *tag)?;
o.write_all(&V1HEADER_PAD[..])?;
o.write_all(&data[..])?;
}
}
Ok(())
}
}
impl MarshalInto for user_attribute::Image {
fn serialized_len(&self) -> usize {
const V1HEADER_LEN: usize =
2
+ 1
+ 1
+ 12;
match self {
user_attribute::Image::JPEG(data)
| user_attribute::Image::Unknown(_, data)
| user_attribute::Image::Private(_, data) =>
V1HEADER_LEN + data.len(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Literal {
pub(crate) fn serialize_headers(&self, o: &mut dyn std::io::Write,
write_tag: bool) -> Result<()>
{
let filename = if let Some(ref filename) = self.filename() {
let len = cmp::min(filename.len(), 255) as u8;
&filename[..len as usize]
} else {
&b""[..]
};
let date = if let Some(d) = self.date() {
Timestamp::try_from(d)?.into()
} else {
0
};
if write_tag {
let len = 1 + (1 + filename.len()) + 4
+ self.body().len();
CTB::new(Tag::Literal).serialize(o)?;
BodyLength::Full(len as u32).serialize(o)?;
}
write_byte(o, self.format().into())?;
write_byte(o, filename.len() as u8)?;
o.write_all(filename)?;
write_be_u32(o, date)?;
Ok(())
}
}
impl Marshal for Literal {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
let body = self.body();
if TRACE {
let prefix = &body[..cmp::min(body.len(), 20)];
eprintln!("Literal::serialize({}{}, {} bytes)",
String::from_utf8_lossy(prefix),
if body.len() > 20 { "..." } else { "" },
body.len());
}
self.serialize_headers(o, false)?;
o.write_all(body)?;
Ok(())
}
}
impl NetLength for Literal {
fn net_len(&self) -> usize {
1 + (1 + self.filename().map(|f| f.len()).unwrap_or(0)) + 4
+ self.body().len()
}
}
impl MarshalInto for Literal {
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 Marshal for CompressedData {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self.body() {
Body::Unprocessed(bytes) => {
if TRACE {
eprintln!("CompressedData::serialize(\
algo: {}, {} bytes of unprocessed body)",
self.algo(), bytes.len());
}
o.write_all(&[self.algo().into()])?;
o.write_all(bytes)?;
},
Body::Processed(bytes) => {
if TRACE {
eprintln!("CompressedData::serialize(\
algo: {}, {} bytes of processed body)",
self.algo(), bytes.len());
}
let o = stream::Message::new(o);
let mut o = stream::Compressor::new_naked(
o, self.algo(), Default::default(), 0)?;
o.write_all(bytes)?;
o.finalize()?;
},
Body::Structured(children) => {
if TRACE {
eprintln!("CompressedData::serialize(\
algo: {}, {:?} children)",
self.algo(), children.len());
}
let o = stream::Message::new(o);
let mut o = stream::Compressor::new_naked(
o, self.algo(), Default::default(), 0)?;
for p in children {
(p as &dyn Marshal).serialize(&mut o)?;
}
o.finalize()?;
},
}
Ok(())
}
}
impl NetLength for CompressedData {
fn net_len(&self) -> usize {
let compressed = |l| l + cmp::max(l / 5, 4096);
match self.body() {
Body::Unprocessed(bytes) => 1 + bytes.len(),
Body::Processed(bytes) => 1 + compressed(bytes.len()),
Body::Structured(packets) =>
1
+ compressed(packets.iter().map(|p| {
(p as &dyn MarshalInto).serialized_len()
}).sum::<usize>()),
}
}
}
impl MarshalInto for CompressedData {
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 Marshal for PKESK {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
&PKESK::V3(ref p) => p.serialize(o),
PKESK::__Nonexhaustive => unreachable!(),
}
}
}
impl MarshalInto for PKESK {
fn serialized_len(&self) -> usize {
match self {
&PKESK::V3(ref p) => p.serialized_len(),
PKESK::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
match self {
PKESK::V3(p) =>
generic_serialize_into(p, MarshalInto::serialized_len(p), buf),
PKESK::__Nonexhaustive => unreachable!(),
}
}
}
impl Marshal for PKESK3 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
write_byte(o, 3)?;
(self.recipient() as &dyn Marshal).serialize(o)?;
write_byte(o, self.pk_algo().into())?;
self.esk().serialize(o)?;
Ok(())
}
}
impl NetLength for PKESK3 {
fn net_len(&self) -> usize {
1
+ 8
+ 1
+ self.esk().serialized_len()
}
}
impl MarshalInto for PKESK3 {
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 Marshal for SKESK {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
&SKESK::V4(ref s) => s.serialize(o),
&SKESK::V5(ref s) => s.serialize(o),
SKESK::__Nonexhaustive => unreachable!(),
}
}
}
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(),
SKESK::__Nonexhaustive => unreachable!(),
}
}
}
impl MarshalInto for SKESK {
fn serialized_len(&self) -> usize {
match self {
&SKESK::V4(ref s) => s.serialized_len(),
&SKESK::V5(ref s) => s.serialized_len(),
SKESK::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
match self {
SKESK::V4(s) =>
generic_serialize_into(s, MarshalInto::serialized_len(s), buf),
SKESK::V5(s) =>
generic_serialize_into(s, MarshalInto::serialized_len(s), buf),
SKESK::__Nonexhaustive => unreachable!(),
}
}
}
impl Marshal for SKESK4 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
write_byte(o, 4)?;
write_byte(o, self.symmetric_algo().into())?;
self.s2k().serialize(o)?;
o.write_all(self.raw_esk())?;
Ok(())
}
}
impl NetLength for SKESK4 {
fn net_len(&self) -> usize {
1
+ 1
+ self.s2k().serialized_len()
+ self.raw_esk().len()
}
}
impl MarshalInto for SKESK4 {
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 Marshal for SKESK5 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
write_byte(o, 5)?;
write_byte(o, self.symmetric_algo().into())?;
write_byte(o, self.aead_algo().into())?;
self.s2k().serialize(o)?;
if let Ok(iv) = self.aead_iv() {
o.write_all(iv)?;
}
o.write_all(self.raw_esk())?;
o.write_all(self.aead_digest())?;
Ok(())
}
}
impl NetLength for SKESK5 {
fn net_len(&self) -> usize {
1
+ 1
+ 1
+ self.s2k().serialized_len()
+ self.aead_iv().map(|iv| iv.len()).unwrap_or(0)
+ self.raw_esk().len()
+ self.aead_digest().len()
}
}
impl MarshalInto for SKESK5 {
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 Marshal for SEIP {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self.body() {
Body::Unprocessed(bytes) => {
o.write_all(&[self.version()])?;
o.write_all(bytes)?;
Ok(())
},
_ => Err(Error::InvalidOperation(
"Cannot encrypt, use serialize::stream::Encryptor".into())
.into()),
}
}
}
impl NetLength for SEIP {
fn net_len(&self) -> usize {
match self.body() {
Body::Unprocessed(bytes) => 1 + bytes.len(),
_ => 0,
}
}
}
impl MarshalInto for SEIP {
fn serialized_len(&self) -> usize {
self.gross_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Marshal for MDC {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
o.write_all(self.digest())?;
Ok(())
}
}
impl NetLength for MDC {
fn net_len(&self) -> usize {
20
}
}
impl MarshalInto for MDC {
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 Marshal for AED {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self {
&AED::V1(ref p) => p.serialize(o),
AED::__Nonexhaustive => unreachable!(),
}
}
}
impl MarshalInto for AED {
fn serialized_len(&self) -> usize {
match self {
&AED::V1(ref p) => p.serialized_len(),
AED::__Nonexhaustive => unreachable!(),
}
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
match self {
&AED::V1(ref p) => p.serialize_into(buf),
AED::__Nonexhaustive => unreachable!(),
}
}
}
impl AED1 {
fn serialize_headers(&self, o: &mut dyn std::io::Write) -> Result<()> {
o.write_all(&[1,
self.symmetric_algo().into(),
self.aead().into(),
self.chunk_size().trailing_zeros() as u8 - 6])?;
o.write_all(self.iv())?;
Ok(())
}
}
impl Marshal for AED1 {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
match self.body() {
Body::Unprocessed(bytes) => {
self.serialize_headers(o)?;
o.write_all(bytes)?;
Ok(())
},
_ => Err(Error::InvalidOperation(
"Cannot encrypt, use serialize::stream::Encryptor".into())
.into()),
}
}
}
impl NetLength for AED1 {
fn net_len(&self) -> usize {
match self.body() {
Body::Unprocessed(bytes) =>
4
+ self.iv().len()
+ bytes.len(),
_ => 0,
}
}
}
impl MarshalInto for AED1 {
fn serialized_len(&self) -> usize {
self.gross_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Serialize for Packet {}
impl Marshal for Packet {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
CTB::new(self.tag()).serialize(o)?;
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_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(_) => unreachable!("handled above"),
&Packet::PKESK(ref p) => p.serialize(o),
&Packet::SKESK(ref p) => p.serialize(o),
&Packet::SEIP(ref p) => p.serialize(o),
&Packet::MDC(ref p) => p.serialize(o),
&Packet::AED(ref p) => p.serialize(o),
Packet::__Nonexhaustive => unreachable!(),
}
}
fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
CTB::new(self.tag()).serialize(o)?;
if let Packet::CompressedData(ref p) = self {
let mut body = Vec::new();
p.export(&mut body)?;
BodyLength::Full(body.len() as u32).export(o)?;
o.write_all(&body)?;
return Ok(());
}
BodyLength::Full(self.net_len() as u32).export(o)?;
match self {
&Packet::Unknown(ref p) => p.export(o),
&Packet::Signature(ref p) => p.export(o),
&Packet::OnePassSig(ref p) => p.export(o),
&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.export(o),
&Packet::Trust(ref p) => p.export(o),
&Packet::UserID(ref p) => p.export(o),
&Packet::UserAttribute(ref p) => p.export(o),
&Packet::Literal(ref p) => p.export(o),
&Packet::CompressedData(_) => unreachable!("handled above"),
&Packet::PKESK(ref p) => p.export(o),
&Packet::SKESK(ref p) => p.export(o),
&Packet::SEIP(ref p) => p.export(o),
&Packet::MDC(ref p) => p.export(o),
&Packet::AED(ref p) => p.export(o),
Packet::__Nonexhaustive => unreachable!(),
}
}
}
impl NetLength for Packet {
fn net_len(&self) -> usize {
match self {
&Packet::Unknown(ref p) => p.net_len(),
&Packet::Signature(ref p) => p.net_len(),
&Packet::OnePassSig(ref p) => p.net_len(),
&Packet::PublicKey(ref p) => p.net_len_key(false),
&Packet::PublicSubkey(ref p) => p.net_len_key(false),
&Packet::SecretKey(ref p) => p.net_len_key(true),
&Packet::SecretSubkey(ref p) => p.net_len_key(true),
&Packet::Marker(ref p) => p.net_len(),
&Packet::Trust(ref p) => p.net_len(),
&Packet::UserID(ref p) => p.net_len(),
&Packet::UserAttribute(ref p) => p.net_len(),
&Packet::Literal(ref p) => p.net_len(),
&Packet::CompressedData(ref p) => p.net_len(),
&Packet::PKESK(ref p) => p.net_len(),
&Packet::SKESK(ref p) => p.net_len(),
&Packet::SEIP(ref p) => p.net_len(),
&Packet::MDC(ref p) => p.net_len(),
&Packet::AED(ref p) => p.net_len(),
Packet::__Nonexhaustive => unreachable!(),
}
}
}
impl SerializeInto for Packet {}
impl MarshalInto for Packet {
fn serialized_len(&self) -> usize {
(match self {
&Packet::Unknown(ref p) => p.serialized_len(),
&Packet::Signature(ref p) => p.serialized_len(),
&Packet::OnePassSig(ref p) => p.serialized_len(),
&Packet::PublicKey(ref p) => p.serialized_len(),
&Packet::PublicSubkey(ref p) => p.serialized_len(),
&Packet::SecretKey(ref p) => p.serialized_len(),
&Packet::SecretSubkey(ref p) => p.serialized_len(),
&Packet::Marker(ref p) => p.serialized_len(),
&Packet::Trust(ref p) => p.serialized_len(),
&Packet::UserID(ref p) => p.serialized_len(),
&Packet::UserAttribute(ref p) => p.serialized_len(),
&Packet::Literal(ref p) => p.serialized_len(),
&Packet::CompressedData(ref p) => p.serialized_len(),
&Packet::PKESK(ref p) => p.serialized_len(),
&Packet::SKESK(ref p) => p.serialized_len(),
&Packet::SEIP(ref p) => p.serialized_len(),
&Packet::MDC(ref p) => p.serialized_len(),
&Packet::AED(ref p) => p.serialized_len(),
Packet::__Nonexhaustive => unreachable!(),
})
+ 1
+ BodyLength::Full(self.net_len() as u32).serialized_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_export_into(self, MarshalInto::serialized_len(self), buf)
}
}
#[allow(dead_code)]
enum PacketRef<'a> {
Unknown(&'a packet::Unknown),
Signature(&'a packet::Signature),
OnePassSig(&'a packet::OnePassSig),
PublicKey(&'a packet::key::PublicKey),
PublicSubkey(&'a packet::key::PublicSubkey),
SecretKey(&'a packet::key::SecretKey),
SecretSubkey(&'a packet::key::SecretSubkey),
Marker(&'a packet::Marker),
Trust(&'a packet::Trust),
UserID(&'a packet::UserID),
UserAttribute(&'a packet::UserAttribute),
Literal(&'a packet::Literal),
CompressedData(&'a packet::CompressedData),
PKESK(&'a packet::PKESK),
SKESK(&'a packet::SKESK),
SEIP(&'a packet::SEIP),
MDC(&'a packet::MDC),
AED(&'a packet::AED),
}
impl<'a> PacketRef<'a> {
fn tag(&self) -> packet::Tag {
match self {
PacketRef::Unknown(ref packet) => packet.tag(),
PacketRef::Signature(_) => Tag::Signature,
PacketRef::OnePassSig(_) => Tag::OnePassSig,
PacketRef::PublicKey(_) => Tag::PublicKey,
PacketRef::PublicSubkey(_) => Tag::PublicSubkey,
PacketRef::SecretKey(_) => Tag::SecretKey,
PacketRef::SecretSubkey(_) => Tag::SecretSubkey,
PacketRef::Marker(_) => Tag::Marker,
PacketRef::Trust(_) => Tag::Trust,
PacketRef::UserID(_) => Tag::UserID,
PacketRef::UserAttribute(_) => Tag::UserAttribute,
PacketRef::Literal(_) => Tag::Literal,
PacketRef::CompressedData(_) => Tag::CompressedData,
PacketRef::PKESK(_) => Tag::PKESK,
PacketRef::SKESK(_) => Tag::SKESK,
PacketRef::SEIP(_) => Tag::SEIP,
PacketRef::MDC(_) => Tag::MDC,
PacketRef::AED(_) => Tag::AED,
}
}
}
impl<'a> Serialize for PacketRef<'a> {}
impl<'a> Marshal for PacketRef<'a> {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
CTB::new(self.tag()).serialize(o)?;
if let PacketRef::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 {
PacketRef::Unknown(p) => p.serialize(o),
PacketRef::Signature(p) => p.serialize(o),
PacketRef::OnePassSig(p) => p.serialize(o),
PacketRef::PublicKey(p) => p.serialize_key(o, false),
PacketRef::PublicSubkey(p) => p.serialize_key(o, false),
PacketRef::SecretKey(p) => p.serialize_key(o, true),
PacketRef::SecretSubkey(p) => p.serialize_key(o, true),
PacketRef::Marker(p) => p.serialize(o),
PacketRef::Trust(p) => p.serialize(o),
PacketRef::UserID(p) => p.serialize(o),
PacketRef::UserAttribute(p) => p.serialize(o),
PacketRef::Literal(p) => p.serialize(o),
PacketRef::CompressedData(_) => unreachable!("handled above"),
PacketRef::PKESK(p) => p.serialize(o),
PacketRef::SKESK(p) => p.serialize(o),
PacketRef::SEIP(p) => p.serialize(o),
PacketRef::MDC(p) => p.serialize(o),
PacketRef::AED(p) => p.serialize(o),
}
}
fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
CTB::new(self.tag()).serialize(o)?;
if let PacketRef::CompressedData(ref p) = self {
let mut body = Vec::new();
p.export(&mut body)?;
BodyLength::Full(body.len() as u32).export(o)?;
o.write_all(&body)?;
return Ok(());
}
BodyLength::Full(self.net_len() as u32).export(o)?;
match self {
PacketRef::Unknown(p) => p.export(o),
PacketRef::Signature(p) => p.export(o),
PacketRef::OnePassSig(p) => p.export(o),
PacketRef::PublicKey(p) => p.serialize_key(o, false),
PacketRef::PublicSubkey(p) => p.serialize_key(o, false),
PacketRef::SecretKey(p) => p.serialize_key(o, true),
PacketRef::SecretSubkey(p) => p.serialize_key(o, true),
PacketRef::Marker(p) => p.export(o),
PacketRef::Trust(p) => p.export(o),
PacketRef::UserID(p) => p.export(o),
PacketRef::UserAttribute(p) => p.export(o),
PacketRef::Literal(p) => p.export(o),
PacketRef::CompressedData(_) => unreachable!("handled above"),
PacketRef::PKESK(p) => p.export(o),
PacketRef::SKESK(p) => p.export(o),
PacketRef::SEIP(p) => p.export(o),
PacketRef::MDC(p) => p.export(o),
PacketRef::AED(p) => p.export(o),
}
}
}
impl<'a> NetLength for PacketRef<'a> {
fn net_len(&self) -> usize {
match self {
PacketRef::Unknown(p) => p.net_len(),
PacketRef::Signature(p) => p.net_len(),
PacketRef::OnePassSig(p) => p.net_len(),
PacketRef::PublicKey(p) => p.net_len_key(false),
PacketRef::PublicSubkey(p) => p.net_len_key(false),
PacketRef::SecretKey(p) => p.net_len_key(true),
PacketRef::SecretSubkey(p) => p.net_len_key(true),
PacketRef::Marker(p) => p.net_len(),
PacketRef::Trust(p) => p.net_len(),
PacketRef::UserID(p) => p.net_len(),
PacketRef::UserAttribute(p) => p.net_len(),
PacketRef::Literal(p) => p.net_len(),
PacketRef::CompressedData(p) => p.net_len(),
PacketRef::PKESK(p) => p.net_len(),
PacketRef::SKESK(p) => p.net_len(),
PacketRef::SEIP(p) => p.net_len(),
PacketRef::MDC(p) => p.net_len(),
PacketRef::AED(p) => p.net_len(),
}
}
}
impl<'a> SerializeInto for PacketRef<'a> {}
impl<'a> MarshalInto for PacketRef<'a> {
fn serialized_len(&self) -> usize {
(match self {
PacketRef::Unknown(p) => p.serialized_len(),
PacketRef::Signature(p) => p.serialized_len(),
PacketRef::OnePassSig(p) => p.serialized_len(),
PacketRef::PublicKey(p) => p.serialized_len(),
PacketRef::PublicSubkey(p) => p.serialized_len(),
PacketRef::SecretKey(p) => p.serialized_len(),
PacketRef::SecretSubkey(p) => p.serialized_len(),
PacketRef::Marker(p) => p.serialized_len(),
PacketRef::Trust(p) => p.serialized_len(),
PacketRef::UserID(p) => p.serialized_len(),
PacketRef::UserAttribute(p) => p.serialized_len(),
PacketRef::Literal(p) => p.serialized_len(),
PacketRef::CompressedData(p) => p.serialized_len(),
PacketRef::PKESK(p) => p.serialized_len(),
PacketRef::SKESK(p) => p.serialized_len(),
PacketRef::SEIP(p) => p.serialized_len(),
PacketRef::MDC(p) => p.serialized_len(),
PacketRef::AED(p) => p.serialized_len(),
})
+ 1
+ BodyLength::Full(self.net_len() as u32).serialized_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_export_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Serialize for PacketPile {}
impl Marshal for PacketPile {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
for p in self.children() {
(p as &dyn Marshal).serialize(o)?;
}
Ok(())
}
fn export(&self, o: &mut dyn std::io::Write) -> Result<()> {
for p in self.children() {
(p as &dyn Marshal).export(o)?;
}
Ok(())
}
}
impl SerializeInto for PacketPile {}
impl MarshalInto for PacketPile {
fn serialized_len(&self) -> usize {
self.children().map(|p| {
(p as &dyn MarshalInto).serialized_len()
}).sum()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_serialize_into(self, MarshalInto::serialized_len(self), buf)
}
fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
generic_export_into(self, MarshalInto::serialized_len(self), buf)
}
}
impl Serialize for Message {}
impl Marshal for Message {
fn serialize(&self, o: &mut dyn std::io::Write) -> Result<()> {
use std::ops::Deref;
(self.deref() as &dyn Marshal).serialize(o)
}
}
impl SerializeInto for Message {}
impl MarshalInto for Message {
fn serialized_len(&self) -> usize {
use std::ops::Deref;
(self.deref() as &dyn MarshalInto).serialized_len()
}
fn serialize_into(&self, buf: &mut [u8]) -> Result<usize> {
use std::ops::Deref;
(self.deref() as &dyn MarshalInto).serialize_into(buf)
}
fn export_into(&self, buf: &mut [u8]) -> Result<usize> {
use std::ops::Deref;
(self.deref() as &dyn MarshalInto).export_into(buf)
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::types::CompressionAlgorithm;
use crate::parse::to_unknown_packet;
use crate::parse::PacketParserBuilder;
use crate::parse::Parse;
fn binary_pp(data: &[u8]) -> String {
let mut output = Vec::new();
crate::fmt::hex::Dumper::new(&mut output, "")
.write_ascii(data).unwrap();
String::from_utf8(output).unwrap()
}
fn packets_bitwise_compare(filename: &str, packet: &Packet,
expected: &[u8], got: &[u8]) {
let expected = to_unknown_packet(expected).unwrap();
let got = to_unknown_packet(got).unwrap();
let expected_body = expected.body();
let got_body = got.body();
let mut fail = false;
if expected.tag() != got.tag() {
eprintln!("Expected a {:?}, got a {:?}", expected.tag(), got.tag());
fail = true;
}
if expected_body != got_body {
eprintln!("Packet contents don't match (for {}):",
filename);
eprintln!("Expected ({} bytes):\n{}",
expected_body.len(), binary_pp(&expected_body));
eprintln!("Got ({} bytes):\n{}",
got_body.len(), binary_pp(&got_body));
eprintln!("Packet: {:#?}", packet);
fail = true;
}
if fail {
panic!("Packets don't match (for {}).", filename);
}
}
#[test]
fn serialize_test_1() {
let filenames = [
"literal-mode-b.gpg",
"literal-mode-t-partial-body.gpg",
"sig.gpg",
"public-key-bare.gpg",
"public-subkey-bare.gpg",
"userid-bare.gpg",
"s2k/mode-0-password-1234.gpg",
"s2k/mode-0-password-1234.gpg",
"s2k/mode-1-password-123456-1.gpg",
"s2k/mode-1-password-foobar-2.gpg",
"s2k/mode-3-aes128-password-13-times-0123456789.gpg",
"s2k/mode-3-aes192-password-123.gpg",
"s2k/mode-3-encrypted-key-password-bgtyhn.gpg",
"s2k/mode-3-password-9876-2.gpg",
"s2k/mode-3-password-qwerty-1.gpg",
"s2k/mode-3-twofish-password-13-times-0123456789.gpg",
];
for filename in filenames.iter() {
let data = crate::tests::message(filename);
let pile = PacketPile::from_bytes(&data[..]).unwrap();
assert_eq!(pile.children().len(), 1);
let p = pile.descendants().next().unwrap();
let mut buffer = Vec::new();
match p {
Packet::Literal(_) | Packet::Signature(_)
| Packet::PublicKey(_) | Packet::PublicSubkey(_)
| Packet::UserID(_) | Packet::SKESK(_) => (),
ref p => {
panic!("Didn't expect a {:?} packet.", p.tag());
},
}
(p as &dyn Marshal).serialize(&mut buffer).unwrap();
packets_bitwise_compare(filename, p, &data[..], &buffer[..]);
}
}
#[test]
fn serialize_test_1_unknown() {
let filenames = [
"compressed-data-algo-1.gpg",
"compressed-data-algo-2.gpg",
"compressed-data-algo-3.gpg",
"recursive-2.gpg",
"recursive-3.gpg",
];
for filename in filenames.iter() {
let data = crate::tests::message(filename);
let u = Packet::Unknown(to_unknown_packet(&data[..]).unwrap());
let data2 = (&u as &dyn MarshalInto).to_vec().unwrap();
packets_bitwise_compare(filename, &u, &data[..], &data2[..]);
}
}
#[cfg(feature = "compression-deflate")]
#[test]
fn serialize_test_2() {
let filenames = [
"compressed-data-algo-1.gpg",
"compressed-data-algo-2.gpg",
"compressed-data-algo-3.gpg",
"recursive-2.gpg",
"recursive-3.gpg",
];
for filename in filenames.iter() {
eprintln!("{}...", filename);
let data = crate::tests::message(filename);
let pile = PacketParserBuilder::from_bytes(&data[..]).unwrap()
.max_recursion_depth(0)
.buffer_unread_content()
.into_packet_pile().unwrap();
let po = pile.descendants().next();
if let Some(&Packet::CompressedData(ref cd)) = po {
let buffer =
(&Packet::CompressedData(cd.clone()) as &dyn MarshalInto)
.to_vec().unwrap();
let pile2 = PacketParserBuilder::from_bytes(&buffer[..]).unwrap()
.max_recursion_depth(0)
.buffer_unread_content()
.into_packet_pile().unwrap();
if pile != pile2 {
eprintln!("Orig:");
let p = pile.children().next().unwrap();
eprintln!("{:?}", p);
let body = p.processed_body().unwrap();
eprintln!("Body: {}", body.len());
eprintln!("{}", binary_pp(body));
eprintln!("Reparsed:");
let p = pile2.children().next().unwrap();
eprintln!("{:?}", p);
let body = p.processed_body().unwrap();
eprintln!("Body: {}", body.len());
eprintln!("{}", binary_pp(body));
assert_eq!(pile, pile2);
}
} else {
panic!("Expected a compressed data data packet.");
}
}
}
#[test]
fn serialize_test_3() {
use crate::types::DataFormat::Text as T;
let mut messages = Vec::new();
let mut one = Literal::new(T);
one.set_body(b"one".to_vec());
let mut two = Literal::new(T);
two.set_body(b"two".to_vec());
let mut three = Literal::new(T);
three.set_body(b"three".to_vec());
let mut four = Literal::new(T);
four.set_body(b"four".to_vec());
let mut five = Literal::new(T);
five.set_body(b"five".to_vec());
let mut six = Literal::new(T);
six.set_body(b"six".to_vec());
let mut top_level = Vec::new();
top_level.push(
CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(one.clone().into())
.push(two.clone().into())
.into());
top_level.push(three.clone().into());
messages.push(top_level);
let mut top_level = Vec::new();
top_level.push(
CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(one.clone().into())
.push(two.clone().into())
.into())
.push(CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(three.clone().into())
.push(four.clone().into())
.into())
.into());
messages.push(top_level);
let mut top_level = Vec::new();
top_level.push(
CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(one.clone().into())
.push(two.clone().into())
.into())
.into())
.into())
.push(CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(three.clone().into())
.into())
.push(four.clone().into())
.into())
.into());
messages.push(top_level);
let mut top_level = Vec::new();
top_level.push(
CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(one.clone().into())
.push(two.clone().into())
.into());
top_level.push(
three.clone().into());
top_level.push(
four.clone().into());
top_level.push(
CompressedData::new(CompressionAlgorithm::Uncompressed)
.push(five.into())
.push(six.into())
.into());
messages.push(top_level);
let mut top_level = Vec::new();
let uid = UserID::from("Foo");
top_level.push(uid.into());
messages.push(top_level);
for m in messages.into_iter() {
let pile = PacketPile::from(m);
pile.pretty_print();
let mut buffer = Vec::new();
(&pile as &dyn Marshal).serialize(&mut buffer).unwrap();
let pile2 = PacketParserBuilder::from_bytes(&buffer[..]).unwrap()
.buffer_unread_content()
.into_packet_pile().unwrap();
if pile != pile2 {
eprintln!("ORIG...");
pile.pretty_print();
eprintln!("REPARSED...");
pile2.pretty_print();
panic!("Reparsed packet does not match original packet!");
}
}
}
#[test]
fn body_length_edge_cases() {
{
let mut buf = vec![];
BodyLength::Full(0).serialize(&mut buf).unwrap();
assert_eq!(&buf[..], &b"\x00"[..]);
}
{
let mut buf = vec![];
BodyLength::Full(1).serialize(&mut buf).unwrap();
assert_eq!(&buf[..], &b"\x01"[..]);
}
{
let mut buf = vec![];
BodyLength::Full(191).serialize(&mut buf).unwrap();
assert_eq!(&buf[..], &b"\xbf"[..]);
}
{
let mut buf = vec![];
BodyLength::Full(192).serialize(&mut buf).unwrap();
assert_eq!(&buf[..], &b"\xc0\x00"[..]);
}
{
let mut buf = vec![];
BodyLength::Full(193).serialize(&mut buf).unwrap();
assert_eq!(&buf[..], &b"\xc0\x01"[..]);
}
{
let mut buf = vec![];
BodyLength::Full(8383).serialize(&mut buf).unwrap();
assert_eq!(&buf[..], &b"\xdf\xff"[..]);
}
{
let mut buf = vec![];
BodyLength::Full(8384).serialize(&mut buf).unwrap();
assert_eq!(&buf[..], &b"\xff\x00\x00\x20\xc0"[..]);
}
{
let mut buf = vec![];
BodyLength::Full(0xffffffff).serialize(&mut buf).unwrap();
assert_eq!(&buf[..], &b"\xff\xff\xff\xff\xff"[..]);
}
}
#[test]
fn export_signature() {
use crate::cert::prelude::*;
let (cert, _) = CertBuilder::new().generate().unwrap();
let mut keypair = cert.primary_key().key().clone().parts_into_secret()
.unwrap().into_keypair().unwrap();
let uid = UserID::from("foo");
let sig = uid.bind(
&mut keypair, &cert,
signature::SignatureBuilder::new(SignatureType::GenericCertification))
.unwrap();
sig.export(&mut Vec::new()).unwrap();
sig.export_into(&mut vec![0; sig.serialized_len()]).unwrap();
sig.export_to_vec().unwrap();
(&PacketRef::Signature(&sig) as &dyn Marshal)
.export(&mut Vec::new()).unwrap();
(&PacketRef::Signature(&sig) as &dyn MarshalInto).export_into(
&mut vec![0; (&PacketRef::Signature(&sig) as &dyn MarshalInto)
.serialized_len()]).unwrap();
(&PacketRef::Signature(&sig) as &dyn MarshalInto)
.export_to_vec().unwrap();
let p = Packet::Signature(sig);
(&p as &dyn Marshal).export(&mut Vec::new()).unwrap();
(&p as &dyn MarshalInto)
.export_into(
&mut vec![0; (&p as &dyn MarshalInto).serialized_len()])
.unwrap();
(&p as &dyn MarshalInto).export_to_vec().unwrap();
let pp = PacketPile::from(vec![p]);
(&pp as &dyn Marshal).export(&mut Vec::new()).unwrap();
(&pp as &dyn MarshalInto)
.export_into(
&mut vec![0; (&pp as &dyn MarshalInto).serialized_len()])
.unwrap();
(&pp as &dyn MarshalInto).export_to_vec().unwrap();
let sig = uid.bind(
&mut keypair, &cert,
signature::SignatureBuilder::new(SignatureType::GenericCertification)
.set_exportable_certification(true).unwrap()).unwrap();
sig.export(&mut Vec::new()).unwrap();
sig.export_into(&mut vec![0; sig.serialized_len()]).unwrap();
sig.export_to_vec().unwrap();
(&PacketRef::Signature(&sig) as &dyn Marshal)
.export(&mut Vec::new()).unwrap();
(&PacketRef::Signature(&sig) as &dyn MarshalInto)
.export_into(
&mut vec![0; (&PacketRef::Signature(&sig)
as &dyn MarshalInto).serialized_len()])
.unwrap();
(&PacketRef::Signature(&sig) as &dyn MarshalInto)
.export_to_vec().unwrap();
let p = Packet::Signature(sig);
(&p as &dyn Marshal).export(&mut Vec::new()).unwrap();
(&p as &dyn MarshalInto)
.export_into(
&mut vec![0; (&p as &dyn MarshalInto).serialized_len()])
.unwrap();
(&p as &dyn MarshalInto).export_to_vec().unwrap();
let pp = PacketPile::from(vec![p]);
(&pp as &dyn Marshal).export(&mut Vec::new()).unwrap();
(&pp as &dyn MarshalInto)
.export_into(
&mut vec![0; (&pp as &dyn MarshalInto).serialized_len()])
.unwrap();
(&pp as &dyn MarshalInto).export_to_vec().unwrap();
let sig = uid.bind(
&mut keypair, &cert,
signature::SignatureBuilder::new(SignatureType::GenericCertification)
.set_exportable_certification(false).unwrap()).unwrap();
sig.export(&mut Vec::new()).unwrap_err();
sig.export_into(&mut vec![0; sig.serialized_len()]).unwrap_err();
sig.export_to_vec().unwrap_err();
(&PacketRef::Signature(&sig) as &dyn Marshal)
.export(&mut Vec::new()).unwrap_err();
(&PacketRef::Signature(&sig) as &dyn MarshalInto)
.export_into(
&mut vec![0; (&PacketRef::Signature(&sig)
as &dyn MarshalInto).serialized_len()])
.unwrap_err();
(&PacketRef::Signature(&sig) as &dyn MarshalInto)
.export_to_vec().unwrap_err();
let p = Packet::Signature(sig);
(&p as &dyn Marshal).export(&mut Vec::new()).unwrap_err();
(&p as &dyn MarshalInto)
.export_into(&mut vec![0; (&p as &dyn MarshalInto).serialized_len()])
.unwrap_err();
(&p as &dyn MarshalInto).export_to_vec().unwrap_err();
let pp = PacketPile::from(vec![p]);
(&pp as &dyn Marshal).export(&mut Vec::new()).unwrap_err();
(&pp as &dyn MarshalInto)
.export_into(
&mut vec![0; (&pp as &dyn MarshalInto).serialized_len()])
.unwrap_err();
(&pp as &dyn MarshalInto).export_to_vec().unwrap_err();
}
}