#![warn(missing_docs)]
extern crate lalrpop_util;
#[macro_use]
extern crate failure;
extern crate buffered_reader;
extern crate memsec;
extern crate nettle;
#[cfg(feature = "compression-deflate")]
extern crate flate2;
#[cfg(feature = "compression-bzip2")]
extern crate bzip2;
#[cfg(test)]
#[macro_use]
extern crate quickcheck;
#[cfg(not(test))]
extern crate quickcheck;
extern crate rand;
#[macro_use] extern crate lazy_static;
extern crate idna;
#[macro_use]
mod macros;
fn vec_truncate(v: &mut Vec<u8>, len: usize) {
if cfg!(debug_assertions) {
if len < v.len() {
unsafe { v.set_len(len); }
}
} else {
v.truncate(len);
}
}
fn vec_drain_prefix(v: &mut Vec<u8>, prefix_len: usize) {
if cfg!(debug_assertions) {
assert!(prefix_len <= v.len(), "prefix len {} > vector len {}",
prefix_len, v.len());
let new_len = v.len() - prefix_len;
unsafe {
std::ptr::copy(v[prefix_len..].as_ptr(),
v[..].as_mut_ptr(),
new_len);
}
vec_truncate(v, new_len);
} else {
v.drain(..prefix_len);
}
}
#[allow(unused_macros)]
macro_rules! assert_match {
( $error: pat = $expr:expr, $fmt:expr, $($pargs:expr),* ) => {
let x = $expr;
if let $error = x {
} else {
let extra = format!($fmt, $($pargs),*);
panic!("Expected {}, got {:?}{}{}",
stringify!($error), x,
if $fmt.len() > 0 { ": " } else { "." }, extra);
}
};
( $error: pat = $expr: expr, $fmt:expr ) => {
assert_match!($error = $expr, $fmt, );
};
( $error: pat = $expr: expr ) => {
assert_match!($error = $expr, "");
};
}
#[macro_use]
pub mod armor;
pub mod fmt;
pub mod crypto;
pub mod packet;
use crate::packet::{Container, key};
pub mod parse;
pub mod cert;
pub use cert::Cert;
pub mod serialize;
mod packet_pile;
pub mod message;
pub mod types;
use crate::types::{
PublicKeyAlgorithm,
SymmetricAlgorithm,
HashAlgorithm,
SignatureType,
};
mod fingerprint;
mod keyid;
mod keyhandle;
pub use keyhandle::KeyHandle;
pub mod policy;
pub(crate) mod utils;
#[cfg(test)]
mod tests;
#[cfg(test)]
fn frozen_time() -> std::time::SystemTime {
crate::types::Timestamp::from(1554542220 - 1).into()
}
pub type Result<T> = ::std::result::Result<T, failure::Error>;
#[derive(Fail, Debug, Clone)]
pub enum Error {
#[fail(display = "Invalid argument: {}", _0)]
InvalidArgument(String),
#[fail(display = "Invalid operation: {}", _0)]
InvalidOperation(String),
#[fail(display = "Malformed packet: {}", _0)]
MalformedPacket(String),
#[fail(display = "{} Packet ({} bytes) exceeds limit of {} bytes",
_0, _1, _2)]
PacketTooLarge(packet::Tag, u32, u32),
#[fail(display = "Unsupported packet type. Tag: {}", _0)]
UnsupportedPacketType(packet::Tag),
#[fail(display = "Unsupported hash algorithm: {}", _0)]
UnsupportedHashAlgorithm(HashAlgorithm),
#[fail(display = "Unsupported public key algorithm: {}", _0)]
UnsupportedPublicKeyAlgorithm(PublicKeyAlgorithm),
#[fail(display = "Unsupported elliptic curve: {}", _0)]
UnsupportedEllipticCurve(types::Curve),
#[fail(display = "Unsupported symmetric algorithm: {}", _0)]
UnsupportedSymmetricAlgorithm(SymmetricAlgorithm),
#[fail(display = "Unsupported AEAD algorithm: {}", _0)]
UnsupportedAEADAlgorithm(types::AEADAlgorithm),
#[fail(display = "Unsupported Compression algorithm: {}", _0)]
UnsupportedCompressionAlgorithm(types::CompressionAlgorithm),
#[fail(display = "Unsupported signature type: {}", _0)]
UnsupportedSignatureType(SignatureType),
#[fail(display = "Invalid password")]
InvalidPassword,
#[fail(display = "Invalid session key: {}", _0)]
InvalidSessionKey(String),
#[fail(display = "Missing session key: {}", _0)]
MissingSessionKey(String),
#[fail(display = "Malformed MPI: {}", _0)]
MalformedMPI(String),
#[fail(display = "Bad signature: {}", _0)]
BadSignature(String),
#[fail(display = "Message has been manipulated")]
ManipulatedMessage,
#[fail(display = "Malformed Message: {}", _0)]
MalformedMessage(String),
#[fail(display = "Malformed Cert: {}", _0)]
MalformedCert(String),
#[fail(display = "Unsupported Cert: {}", _0)]
UnsupportedCert(String),
#[fail(display = "Index out of range")]
IndexOutOfRange,
#[fail(display = "Expired on {:?}", _0)]
Expired(std::time::SystemTime),
#[fail(display = "Not live until {:?}", _0)]
NotYetLive(std::time::SystemTime),
#[fail(display = "No binding signature at time {:?}", _0)]
NoBindingSignature(std::time::SystemTime),
#[fail(display = "Invalid key: {:?}", _0)]
InvalidKey(String),
#[doc(hidden)] #[fail(display = "__Nonexhaustive")] __Nonexhaustive,
}
#[derive(Debug)]
#[derive(PartialEq, Eq, Hash, Clone)]
pub enum Packet {
Unknown(packet::Unknown),
Signature(packet::Signature),
OnePassSig(packet::OnePassSig),
PublicKey(packet::key::PublicKey),
PublicSubkey(packet::key::PublicSubkey),
SecretKey(packet::key::SecretKey),
SecretSubkey(packet::key::SecretSubkey),
Marker(packet::Marker),
Trust(packet::Trust),
UserID(packet::UserID),
UserAttribute(packet::UserAttribute),
Literal(packet::Literal),
CompressedData(packet::CompressedData),
PKESK(packet::PKESK),
SKESK(packet::SKESK),
SEIP(packet::SEIP),
MDC(packet::MDC),
AED(packet::AED),
#[doc(hidden)] __Nonexhaustive,
}
impl Packet {
pub fn tag(&self) -> packet::Tag {
use crate::packet::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<packet::Tag> {
use crate::packet::Tag;
match self {
&Packet::Unknown(_) => None,
&Packet::Signature(_) => Some(Tag::Signature),
&Packet::OnePassSig(_) => Some(Tag::OnePassSig),
&Packet::PublicKey(_) => Some(Tag::PublicKey),
&Packet::PublicSubkey(_) => Some(Tag::PublicSubkey),
&Packet::SecretKey(_) => Some(Tag::SecretKey),
&Packet::SecretSubkey(_) => Some(Tag::SecretSubkey),
&Packet::Marker(_) => Some(Tag::Marker),
&Packet::Trust(_) => Some(Tag::Trust),
&Packet::UserID(_) => Some(Tag::UserID),
&Packet::UserAttribute(_) => Some(Tag::UserAttribute),
&Packet::Literal(_) => Some(Tag::Literal),
&Packet::CompressedData(_) => Some(Tag::CompressedData),
&Packet::PKESK(_) => Some(Tag::PKESK),
&Packet::SKESK(_) => Some(Tag::SKESK),
&Packet::SEIP(_) => Some(Tag::SEIP),
&Packet::MDC(_) => Some(Tag::MDC),
&Packet::AED(_) => Some(Tag::AED),
Packet::__Nonexhaustive => unreachable!(),
}
}
}
#[derive(PartialEq, Clone)]
pub struct PacketPile {
top_level: Container,
}
#[derive(PartialEq)]
pub struct Message {
pile: PacketPile,
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum Fingerprint {
V4([u8;20]),
Invalid(Box<[u8]>)
}
#[derive(PartialEq, Eq, PartialOrd, Ord, Clone, Hash)]
pub enum KeyID {
V4([u8;8]),
Invalid(Box<[u8]>)
}
#[derive(Debug, Clone, PartialEq, Eq)]
pub enum RevocationStatus<'a> {
Revoked(Vec<&'a packet::Signature>),
CouldBe(Vec<&'a packet::Signature>),
NotAsFarAsWeKnow,
}