use std::fmt;
use std::ops::{Deref, DerefMut};
use std::slice;
use quickcheck::{Arbitrary, Gen};
use crate::Error;
use crate::Result;
#[macro_use]
mod container;
pub use container::Container;
pub use container::Body;
pub mod prelude;
use crate::crypto::KeyPair;
mod tag;
pub use self::tag::Tag;
pub mod header;
pub use self::header::Header;
mod unknown;
pub use self::unknown::Unknown;
pub mod signature;
pub mod one_pass_sig;
pub mod key;
mod marker;
pub use self::marker::Marker;
mod trust;
pub use self::trust::Trust;
mod userid;
pub use self::userid::UserID;
pub mod user_attribute;
pub use self::user_attribute::UserAttribute;
mod literal;
pub use self::literal::Literal;
mod compressed_data;
pub use self::compressed_data::CompressedData;
pub mod seip;
pub mod skesk;
pub mod pkesk;
mod mdc;
pub use self::mdc::MDC;
pub mod aed;
pub use def::Packet;
mod def {
use super::*;
#[derive(Debug)]
#[derive(PartialEq, Eq, Hash, Clone)]
pub enum Packet {
Unknown(Unknown),
Signature(Signature),
OnePassSig(OnePassSig),
PublicKey(key::PublicKey),
PublicSubkey(key::PublicSubkey),
SecretKey(key::SecretKey),
SecretSubkey(key::SecretSubkey),
Marker(Marker),
Trust(Trust),
UserID(UserID),
UserAttribute(UserAttribute),
Literal(Literal),
CompressedData(CompressedData),
PKESK(PKESK),
SKESK(SKESK),
SEIP(SEIP),
MDC(MDC),
AED(AED),
#[doc(hidden)] __Nonexhaustive,
}
}
impl Packet {
pub fn tag(&self) -> Tag {
match self {
&Packet::Unknown(ref packet) => packet.tag(),
&Packet::Signature(_) => Tag::Signature,
&Packet::OnePassSig(_) => Tag::OnePassSig,
&Packet::PublicKey(_) => Tag::PublicKey,
&Packet::PublicSubkey(_) => Tag::PublicSubkey,
&Packet::SecretKey(_) => Tag::SecretKey,
&Packet::SecretSubkey(_) => Tag::SecretSubkey,
&Packet::Marker(_) => Tag::Marker,
&Packet::Trust(_) => Tag::Trust,
&Packet::UserID(_) => Tag::UserID,
&Packet::UserAttribute(_) => Tag::UserAttribute,
&Packet::Literal(_) => Tag::Literal,
&Packet::CompressedData(_) => Tag::CompressedData,
&Packet::PKESK(_) => Tag::PKESK,
&Packet::SKESK(_) => Tag::SKESK,
&Packet::SEIP(_) => Tag::SEIP,
&Packet::MDC(_) => Tag::MDC,
&Packet::AED(_) => Tag::AED,
Packet::__Nonexhaustive => unreachable!(),
}
}
pub fn kind(&self) -> Option<Tag> {
match self {
&Packet::Unknown(_) => None,
_ => Some(self.tag()),
}
}
}
impl<'a> Deref for Packet {
type Target = Common;
fn deref(&self) -> &Self::Target {
match self {
&Packet::Unknown(ref packet) => &packet.common,
&Packet::Signature(ref packet) => &packet.common,
&Packet::OnePassSig(ref packet) => &packet.common,
&Packet::PublicKey(ref packet) => &packet.common,
&Packet::PublicSubkey(ref packet) => &packet.common,
&Packet::SecretKey(ref packet) => &packet.common,
&Packet::SecretSubkey(ref packet) => &packet.common,
&Packet::Marker(ref packet) => &packet.common,
&Packet::Trust(ref packet) => &packet.common,
&Packet::UserID(ref packet) => &packet.common,
&Packet::UserAttribute(ref packet) => &packet.common,
&Packet::Literal(ref packet) => &packet.common,
&Packet::CompressedData(ref packet) => &packet.common,
&Packet::PKESK(ref packet) => &packet.common,
&Packet::SKESK(SKESK::V4(ref packet)) => &packet.common,
&Packet::SKESK(SKESK::V5(ref packet)) => &packet.skesk4.common,
Packet::SKESK(SKESK::__Nonexhaustive) => unreachable!(),
&Packet::SEIP(ref packet) => &packet.common,
&Packet::MDC(ref packet) => &packet.common,
&Packet::AED(ref packet) => &packet.common,
Packet::__Nonexhaustive => unreachable!(),
}
}
}
impl<'a> DerefMut for Packet {
fn deref_mut(&mut self) -> &mut Common {
match self {
&mut Packet::Unknown(ref mut packet) => &mut packet.common,
&mut Packet::Signature(ref mut packet) => &mut packet.common,
&mut Packet::OnePassSig(ref mut packet) => &mut packet.common,
&mut Packet::PublicKey(ref mut packet) => &mut packet.common,
&mut Packet::PublicSubkey(ref mut packet) => &mut packet.common,
&mut Packet::SecretKey(ref mut packet) => &mut packet.common,
&mut Packet::SecretSubkey(ref mut packet) => &mut packet.common,
&mut Packet::Marker(ref mut packet) => &mut packet.common,
&mut Packet::Trust(ref mut packet) => &mut packet.common,
&mut Packet::UserID(ref mut packet) => &mut packet.common,
&mut Packet::UserAttribute(ref mut packet) => &mut packet.common,
&mut Packet::Literal(ref mut packet) => &mut packet.common,
&mut Packet::CompressedData(ref mut packet) => &mut packet.common,
&mut Packet::PKESK(ref mut packet) => &mut packet.common,
&mut Packet::SKESK(SKESK::V4(ref mut packet)) => &mut packet.common,
&mut Packet::SKESK(SKESK::V5(ref mut packet)) => &mut packet.skesk4.common,
Packet::SKESK(SKESK::__Nonexhaustive) => unreachable!(),
&mut Packet::SEIP(ref mut packet) => &mut packet.common,
&mut Packet::MDC(ref mut packet) => &mut packet.common,
&mut Packet::AED(ref mut packet) => &mut packet.common,
Packet::__Nonexhaustive => unreachable!(),
}
}
}
impl Arbitrary for Packet {
fn arbitrary<G: Gen>(g: &mut G) -> Self {
use rand::Rng;
match g.gen_range(0, 14) {
0 => Signature::arbitrary(g).into(),
1 => OnePassSig::arbitrary(g).into(),
2 => Key::<key::PublicParts, key::UnspecifiedRole>::arbitrary(g)
.mark_role_primary().into(),
3 => Key::<key::PublicParts, key::UnspecifiedRole>::arbitrary(g)
.mark_role_subordinate().into(),
4 => Key::<key::SecretParts, key::UnspecifiedRole>::arbitrary(g)
.mark_role_primary().into(),
5 => Key::<key::SecretParts, key::UnspecifiedRole>::arbitrary(g)
.mark_role_subordinate().into(),
6 => Marker::arbitrary(g).into(),
7 => Trust::arbitrary(g).into(),
8 => UserID::arbitrary(g).into(),
9 => UserAttribute::arbitrary(g).into(),
10 => Literal::arbitrary(g).into(),
11 => CompressedData::arbitrary(g).into(),
12 => PKESK::arbitrary(g).into(),
13 => SKESK::arbitrary(g).into(),
_ => unreachable!(),
}
}
}
#[derive(Debug, Clone)]
pub struct Common {
dummy: std::marker::PhantomData<()>,
}
impl Arbitrary for Common {
fn arbitrary<G: Gen>(_: &mut G) -> Self {
Common::default()
}
}
impl Default for Common {
fn default() -> Common {
Common {
dummy: Default::default(),
}
}
}
impl PartialEq for Common {
fn eq(&self, _: &Common) -> bool {
true
}
}
impl Eq for Common {}
impl PartialOrd for Common {
fn partial_cmp(&self, _: &Self) -> Option<std::cmp::Ordering> {
Some(std::cmp::Ordering::Equal)
}
}
impl Ord for Common {
fn cmp(&self, _: &Self) -> std::cmp::Ordering {
std::cmp::Ordering::Equal
}
}
impl std::hash::Hash for Common {
fn hash<H: std::hash::Hasher>(&self, _: &mut H) {
}
}
pub struct Iter<'a> {
children: slice::Iter<'a, Packet>,
child: Option<&'a Packet>,
grandchildren: Option<Box<Iter<'a>>>,
depth: usize,
}
impl<'a> Default for Iter<'a> {
fn default() -> Self {
Iter {
children: [].iter(),
child: None,
grandchildren: None,
depth: 0,
}
}
}
impl<'a> Iterator for Iter<'a> {
type Item = &'a Packet;
fn next(&mut self) -> Option<Self::Item> {
if let Some(ref mut grandchildren) = self.grandchildren {
let grandchild = grandchildren.next();
if grandchild.is_some() {
self.depth = grandchildren.depth + 1;
return grandchild;
}
}
self.child = self.children.next();
if let Some(child) = self.child {
self.grandchildren = child.descendants().map(|d| Box::new(d));
}
self.depth = 0;
return self.child;
}
}
impl<'a> Iter<'a> {
pub fn paths(self) -> impl Iterator<Item = (Vec<usize>, &'a Packet)> {
PacketPathIter {
iter: self,
path: None,
}
}
}
struct PacketPathIter<'a> {
iter: Iter<'a>,
path: Option<Vec<usize>>,
}
impl<'a> Iterator for PacketPathIter<'a> {
type Item = (Vec<usize>, &'a Packet);
fn next(&mut self) -> Option<Self::Item> {
if let Some(packet) = self.iter.next() {
if self.path.is_none() {
let mut path = Vec::with_capacity(4);
path.push(0);
self.path = Some(path);
} else {
let mut path = self.path.take().unwrap();
let old_depth = path.len() - 1;
let depth = self.iter.depth;
if old_depth > depth {
path.truncate(depth + 1);
path[depth] += 1;
} else if old_depth == depth {
path[old_depth] += 1;
} else if old_depth + 1 == depth {
path.push(0);
}
self.path = Some(path);
}
Some((self.path.as_ref().unwrap().clone(), packet))
} else {
None
}
}
}
#[test]
fn packet_path_iter() {
use crate::parse::Parse;
use crate::PacketPile;
fn paths(iter: slice::Iter<Packet>) -> Vec<Vec<usize>> {
let mut lpaths : Vec<Vec<usize>> = Vec::new();
for (i, packet) in iter.enumerate() {
let mut v = Vec::new();
v.push(i);
lpaths.push(v);
if let Some(ref container) = packet.container_ref() {
if let Some(c) = container.children() {
for mut path in paths(c).into_iter()
{
path.insert(0, i);
lpaths.push(path);
}
}
}
}
lpaths
}
for i in 1..5 {
let pile = PacketPile::from_bytes(
crate::tests::message(&format!("recursive-{}.gpg", i)[..])).unwrap();
let mut paths1 : Vec<Vec<usize>> = Vec::new();
for path in paths(pile.children()).iter() {
paths1.push(path.clone());
}
let mut paths2 : Vec<Vec<usize>> = Vec::new();
for (path, packet) in pile.descendants().paths() {
assert_eq!(Some(packet), pile.path_ref(&path[..]));
paths2.push(path);
}
if paths1 != paths2 {
eprintln!("PacketPile:");
pile.pretty_print();
eprintln!("Expected paths:");
for p in paths1 {
eprintln!(" {:?}", p);
}
eprintln!("Got paths:");
for p in paths2 {
eprintln!(" {:?}", p);
}
panic!("Something is broken. Don't panic.");
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Signature {
V4(self::signature::Signature4),
#[doc(hidden)] __Nonexhaustive,
}
impl Signature {
pub fn version(&self) -> u8 {
match self {
&Signature::V4(_) => 4,
Signature::__Nonexhaustive => unreachable!(),
}
}
}
impl From<Signature> for Packet {
fn from(s: Signature) -> Self {
Packet::Signature(s)
}
}
impl Deref for Signature {
type Target = signature::Signature4;
fn deref(&self) -> &Self::Target {
match self {
Signature::V4(sig) => sig,
Signature::__Nonexhaustive => unreachable!(),
}
}
}
impl DerefMut for Signature {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Signature::V4(ref mut sig) => sig,
Signature::__Nonexhaustive => unreachable!(),
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum OnePassSig {
V3(self::one_pass_sig::OnePassSig3),
#[doc(hidden)] __Nonexhaustive,
}
impl OnePassSig {
pub fn version(&self) -> u8 {
match self {
&OnePassSig::V3(_) => 3,
OnePassSig::__Nonexhaustive => unreachable!(),
}
}
}
impl From<OnePassSig> for Packet {
fn from(s: OnePassSig) -> Self {
Packet::OnePassSig(s)
}
}
impl Deref for OnePassSig {
type Target = one_pass_sig::OnePassSig3;
fn deref(&self) -> &Self::Target {
match self {
OnePassSig::V3(ops) => ops,
OnePassSig::__Nonexhaustive => unreachable!(),
}
}
}
impl DerefMut for OnePassSig {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
OnePassSig::V3(ref mut ops) => ops,
OnePassSig::__Nonexhaustive => unreachable!(),
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum PKESK {
V3(self::pkesk::PKESK3),
#[doc(hidden)] __Nonexhaustive,
}
impl PKESK {
pub fn version(&self) -> u8 {
match self {
PKESK::V3(_) => 3,
PKESK::__Nonexhaustive => unreachable!(),
}
}
}
impl From<PKESK> for Packet {
fn from(p: PKESK) -> Self {
Packet::PKESK(p)
}
}
impl Deref for PKESK {
type Target = self::pkesk::PKESK3;
fn deref(&self) -> &Self::Target {
match self {
PKESK::V3(ref p) => p,
PKESK::__Nonexhaustive => unreachable!(),
}
}
}
impl DerefMut for PKESK {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
PKESK::V3(ref mut p) => p,
PKESK::__Nonexhaustive => unreachable!(),
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum SKESK {
V4(self::skesk::SKESK4),
V5(self::skesk::SKESK5),
#[doc(hidden)] __Nonexhaustive,
}
impl SKESK {
pub fn version(&self) -> u8 {
match self {
&SKESK::V4(_) => 4,
&SKESK::V5(_) => 5,
SKESK::__Nonexhaustive => unreachable!(),
}
}
}
impl From<SKESK> for Packet {
fn from(p: SKESK) -> Self {
Packet::SKESK(p)
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum Key<P: key::KeyParts, R: key::KeyRole> {
V4(self::key::Key4<P, R>),
#[doc(hidden)] __Nonexhaustive,
}
impl<P: key::KeyParts, R: key::KeyRole> fmt::Display for Key<P, R> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Key::V4(k) => k.fmt(f),
Key::__Nonexhaustive => unreachable!(),
}
}
}
impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
pub fn version(&self) -> u8 {
match self {
Key::V4(_) => 4,
Key::__Nonexhaustive => unreachable!(),
}
}
pub fn public_cmp<PB, RB>(&self, b: &Key<PB, RB>) -> std::cmp::Ordering
where PB: key::KeyParts,
RB: key::KeyRole,
{
match (self, b) {
(Key::V4(a), Key::V4(b)) => a.public_cmp(b),
(Key::__Nonexhaustive, _) => unreachable!(),
(_, Key::__Nonexhaustive) => unreachable!(),
}
}
pub fn public_eq<PB, RB>(&self, b: &Key<PB, RB>) -> bool
where PB: key::KeyParts,
RB: key::KeyRole,
{
self.public_cmp(b) == std::cmp::Ordering::Equal
}
}
impl From<Key<key::PublicParts, key::PrimaryRole>> for Packet {
fn from(k: Key<key::PublicParts, key::PrimaryRole>) -> Self {
Packet::PublicKey(k.into())
}
}
impl From<Key<key::PublicParts, key::SubordinateRole>> for Packet {
fn from(k: Key<key::PublicParts, key::SubordinateRole>) -> Self {
Packet::PublicSubkey(k.into())
}
}
impl From<Key<key::SecretParts, key::PrimaryRole>> for Packet {
fn from(k: Key<key::SecretParts, key::PrimaryRole>) -> Self {
Packet::SecretKey(k.into())
}
}
impl From<Key<key::SecretParts, key::SubordinateRole>> for Packet {
fn from(k: Key<key::SecretParts, key::SubordinateRole>) -> Self {
Packet::SecretSubkey(k.into())
}
}
impl<R: key::KeyRole> Key<key::SecretParts, R> {
pub fn into_keypair(self) -> Result<KeyPair> {
use crate::packet::key::SecretKeyMaterial;
let (key, secret) = self.take_secret();
let secret = match secret {
SecretKeyMaterial::Unencrypted(secret) => secret,
SecretKeyMaterial::Encrypted(_) =>
return Err(Error::InvalidArgument(
"secret key is encrypted".into()).into()),
};
KeyPair::new(key.mark_role_unspecified(), secret)
}
}
impl<R: key::KeyRole> key::Key4<key::SecretParts, R> {
pub fn into_keypair(self) -> Result<KeyPair> {
use crate::packet::key::SecretKeyMaterial;
let (key, secret) = self.take_secret();
let secret = match secret {
SecretKeyMaterial::Unencrypted(secret) => secret,
SecretKeyMaterial::Encrypted(_) =>
return Err(Error::InvalidArgument(
"secret key is encrypted".into()).into()),
};
KeyPair::new(key.mark_role_unspecified().into(), secret)
}
}
macro_rules! impl_common_secret_functions {
($t: path) => {
impl<R: key::KeyRole> Key<$t, R> {
pub fn take_secret(self)
-> (Key<key::PublicParts, R>,
Option<key::SecretKeyMaterial>)
{
match self {
Key::V4(k) => {
let (k, s) = k.take_secret();
(k.into(), s)
},
Key::__Nonexhaustive => unreachable!(),
}
}
pub fn add_secret(self, secret: key::SecretKeyMaterial)
-> (Key<key::SecretParts, R>,
Option<key::SecretKeyMaterial>)
{
match self {
Key::V4(k) => {
let (k, s) = k.add_secret(secret);
(k.into(), s)
},
Key::__Nonexhaustive => unreachable!(),
}
}
}
}
}
impl_common_secret_functions!(key::PublicParts);
impl_common_secret_functions!(key::UnspecifiedParts);
impl<R: key::KeyRole> Key<key::SecretParts, R> {
pub fn take_secret(self)
-> (Key<key::PublicParts, R>, key::SecretKeyMaterial)
{
match self {
Key::V4(k) => {
let (k, s) = k.take_secret();
(k.into(), s)
},
Key::__Nonexhaustive => unreachable!(),
}
}
pub fn add_secret(self, secret: key::SecretKeyMaterial)
-> (Key<key::SecretParts, R>, key::SecretKeyMaterial)
{
match self {
Key::V4(k) => {
let (k, s) = k.add_secret(secret);
(k.into(), s)
},
Key::__Nonexhaustive => unreachable!(),
}
}
}
impl<P: key::KeyParts, R: key::KeyRole> Deref for Key<P, R> {
type Target = self::key::Key4<P, R>;
fn deref(&self) -> &Self::Target {
match self {
Key::V4(ref p) => p,
Key::__Nonexhaustive => unreachable!(),
}
}
}
impl<P: key::KeyParts, R: key::KeyRole> DerefMut for Key<P, R> {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
Key::V4(ref mut p) => p,
Key::__Nonexhaustive => unreachable!(),
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum SEIP {
V1(self::seip::SEIP1),
}
impl SEIP {
pub fn version(&self) -> u8 {
match self {
SEIP::V1(_) => 1,
}
}
}
impl From<SEIP> for Packet {
fn from(p: SEIP) -> Self {
Packet::SEIP(p)
}
}
impl Deref for SEIP {
type Target = self::seip::SEIP1;
fn deref(&self) -> &Self::Target {
match self {
SEIP::V1(ref p) => p,
}
}
}
impl DerefMut for SEIP {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
SEIP::V1(ref mut p) => p,
}
}
}
#[derive(PartialEq, Eq, Hash, Clone, Debug)]
pub enum AED {
V1(self::aed::AED1),
#[doc(hidden)] __Nonexhaustive,
}
impl AED {
pub fn version(&self) -> u8 {
match self {
AED::V1(_) => 1,
AED::__Nonexhaustive => unreachable!(),
}
}
}
impl From<AED> for Packet {
fn from(p: AED) -> Self {
Packet::AED(p)
}
}
impl Deref for AED {
type Target = self::aed::AED1;
fn deref(&self) -> &Self::Target {
match self {
AED::V1(ref p) => p,
AED::__Nonexhaustive => unreachable!(),
}
}
}
impl DerefMut for AED {
fn deref_mut(&mut self) -> &mut Self::Target {
match self {
AED::V1(ref mut p) => p,
AED::__Nonexhaustive => unreachable!(),
}
}
}
#[cfg(test)]
mod test {
use super::*;
use crate::serialize::SerializeInto;
use crate::parse::Parse;
#[test]
fn packet_is_send_and_sync() {
fn f<T: Send + Sync>(_: T) {}
f(Packet::Marker(Default::default()));
}
quickcheck! {
fn roundtrip(p: Packet) -> bool {
let buf = p.to_vec().expect("Failed to serialize packet");
let q = Packet::from_bytes(&buf).unwrap();
assert_eq!(p, q);
true
}
}
quickcheck! {
fn mutate_eq_discriminates(p: Packet, i: usize) -> bool {
if p.tag() == Tag::CompressedData {
return true;
}
let mut buf = p.to_vec().unwrap();
let bit =
i.saturating_add(16)
% (buf.len() * 8);
buf[bit / 8] ^= 1 << (bit % 8);
match Packet::from_bytes(&buf) {
Ok(q) => p != q,
Err(_) => true,
}
}
}
}