use std::cmp;
use std::convert::TryFrom;
use std::io::{self, Read};
use std::path::Path;
use std::time;
use buffered_reader::BufferedReader;
use crate::{
Error,
Fingerprint,
types::{
AEADAlgorithm,
CompressionAlgorithm,
DataFormat,
SymmetricAlgorithm,
},
packet::{
header::BodyLength,
header::CTB,
key,
Literal,
OnePassSig,
one_pass_sig::OnePassSig3,
PKESK,
SKESK,
Tag,
},
KeyID,
Packet,
Result,
RevocationStatus,
packet,
packet::Signature,
Cert,
cert::components::{
Amalgamation,
ValidKeyAmalgamation,
},
crypto::SessionKey,
serialize::Serialize,
policy::Policy,
};
use crate::parse::{
Cookie,
PacketParser,
PacketParserBuilder,
PacketParserResult,
};
const TRACE : bool = false;
const BUFFER_SIZE: usize = 25 * 1024 * 1024;
pub struct Verifier<'a, H: VerificationHelper> {
helper: H,
certs: Vec<Cert>,
oppr: Option<PacketParserResult<'a>>,
structure: IMessageStructure,
reserve: Option<Vec<u8>>,
time: time::SystemTime,
clock_skew_tolerance: time::Duration,
policy: &'a dyn Policy,
}
#[derive(Debug)]
pub enum VerificationResult<'a> {
GoodChecksum {
sig: Signature,
cert: &'a Cert,
ka: ValidKeyAmalgamation<'a, key::PublicParts>,
},
NotAlive {
sig: Signature,
},
MissingKey {
sig: Signature,
},
Error {
sig: Signature,
error: failure::Error,
},
}
impl<'a> VerificationResult<'a> {
pub fn level(&self) -> usize {
use self::VerificationResult::*;
match self {
GoodChecksum { sig, .. } => sig.level(),
NotAlive { sig, .. } => sig.level(),
MissingKey { sig, .. } => sig.level(),
Error { sig, .. } => sig.level(),
}
}
}
#[derive(Debug)]
pub struct MessageStructure<'a>(Vec<MessageLayer<'a>>);
impl<'a> MessageStructure<'a> {
fn new() -> Self {
MessageStructure(Vec::new())
}
fn new_compression_layer(&mut self, algo: CompressionAlgorithm) {
self.0.push(MessageLayer::Compression {
algo: algo,
})
}
fn new_encryption_layer(&mut self, sym_algo: SymmetricAlgorithm,
aead_algo: Option<AEADAlgorithm>) {
self.0.push(MessageLayer::Encryption {
sym_algo: sym_algo,
aead_algo: aead_algo,
})
}
fn new_signature_group(&mut self) {
self.0.push(MessageLayer::SignatureGroup {
results: Vec::new(),
})
}
fn push_verification_result(&mut self, sig: VerificationResult<'a>) {
if let Some(MessageLayer::SignatureGroup { ref mut results }) =
self.0.iter_mut().last()
{
results.push(sig);
} else {
panic!("cannot push to encryption or compression layer");
}
}
pub fn iter(&self) -> MessageStructureIter {
MessageStructureIter(self.0.iter())
}
pub fn into_iter(self) -> impl Iterator<Item = MessageLayer<'a>> {
MessageStructureIntoIter(self.0.into_iter())
}
}
pub struct MessageStructureIter<'a>(::std::slice::Iter<'a, MessageLayer<'a>>);
impl<'a> Iterator for MessageStructureIter<'a> {
type Item = &'a MessageLayer<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
struct MessageStructureIntoIter<'a>(::std::vec::IntoIter<MessageLayer<'a>>);
impl<'a> Iterator for MessageStructureIntoIter<'a> {
type Item = MessageLayer<'a>;
fn next(&mut self) -> Option<Self::Item> {
self.0.next()
}
}
#[derive(Debug)]
pub enum MessageLayer<'a> {
Compression {
algo: CompressionAlgorithm,
},
Encryption {
sym_algo: SymmetricAlgorithm,
aead_algo: Option<AEADAlgorithm>,
},
SignatureGroup {
results: Vec<VerificationResult<'a>>,
}
}
#[derive(Debug)]
struct IMessageStructure {
layers: Vec<IMessageLayer>,
sig_group_counter: usize,
}
impl IMessageStructure {
fn new() -> Self {
IMessageStructure {
layers: Vec::new(),
sig_group_counter: 0,
}
}
fn new_compression_layer(&mut self, algo: CompressionAlgorithm) {
self.insert_missing_signature_group();
self.layers.push(IMessageLayer::Compression {
algo: algo,
});
}
fn new_encryption_layer(&mut self, sym_algo: SymmetricAlgorithm,
aead_algo: Option<AEADAlgorithm>) {
self.insert_missing_signature_group();
self.layers.push(IMessageLayer::Encryption {
sym_algo: sym_algo,
aead_algo: aead_algo,
});
}
fn insert_missing_signature_group(&mut self) {
if self.sig_group_counter > 0 {
self.layers.push(IMessageLayer::SignatureGroup {
sigs: Vec::new(),
count: self.sig_group_counter,
});
}
self.sig_group_counter = 0;
}
fn push_ops(&mut self, ops: &OnePassSig) {
self.sig_group_counter += 1;
if ops.last() {
self.layers.push(IMessageLayer::SignatureGroup {
sigs: Vec::new(),
count: self.sig_group_counter,
});
self.sig_group_counter = 0;
}
}
fn push_signature(&mut self, sig: Signature) {
for layer in self.layers.iter_mut().rev() {
match layer {
IMessageLayer::SignatureGroup {
ref mut sigs, ref mut count,
} if *count > 0 => {
sigs.push(sig);
*count -= 1;
return;
},
_ => (),
}
}
panic!("signature unaccounted for");
}
fn push_bare_signature(&mut self, sig: Signature) {
if let Some(IMessageLayer::SignatureGroup { .. }) = self.layers.iter().last() {
} else {
self.layers.push(IMessageLayer::SignatureGroup {
sigs: Vec::new(),
count: 0,
});
}
if let IMessageLayer::SignatureGroup { ref mut sigs, .. } =
self.layers.iter_mut().last().expect("just checked or created")
{
sigs.push(sig);
} else {
unreachable!()
}
}
}
#[derive(Debug)]
enum IMessageLayer {
Compression {
algo: CompressionAlgorithm,
},
Encryption {
sym_algo: SymmetricAlgorithm,
aead_algo: Option<AEADAlgorithm>,
},
SignatureGroup {
sigs: Vec<Signature>,
count: usize,
}
}
pub trait VerificationHelper {
fn get_public_keys(&mut self, ids: &[crate::KeyHandle]) -> Result<Vec<Cert>>;
fn check(&mut self, structure: MessageStructure) -> Result<()>;
}
impl<'a, H: VerificationHelper> Verifier<'a, H> {
pub fn from_reader<R, T>(policy: &'a dyn Policy, reader: R, helper: H, t: T)
-> Result<Verifier<'a, H>>
where R: io::Read + 'a, T: Into<Option<time::SystemTime>>
{
let t = t.into();
Verifier::from_buffered_reader(
policy,
Box::new(buffered_reader::Generic::with_cookie(reader, None,
Default::default())),
helper, t)
}
pub fn from_file<P, T>(policy: &'a dyn Policy, path: P, helper: H, t: T)
-> Result<Verifier<'a, H>>
where P: AsRef<Path>,
T: Into<Option<time::SystemTime>>
{
let t = t.into();
Verifier::from_buffered_reader(
policy,
Box::new(buffered_reader::File::with_cookie(path,
Default::default())?),
helper, t)
}
pub fn from_bytes<T>(policy: &'a dyn Policy,
bytes: &'a [u8], helper: H, t: T)
-> Result<Verifier<'a, H>>
where T: Into<Option<time::SystemTime>>
{
let t = t.into();
Verifier::from_buffered_reader(
policy,
Box::new(buffered_reader::Memory::with_cookie(bytes,
Default::default())),
helper, t)
}
pub fn helper_ref(&self) -> &H {
&self.helper
}
pub fn helper_mut(&mut self) -> &mut H {
&mut self.helper
}
pub fn into_helper(self) -> H {
self.helper
}
pub fn message_processed(&self) -> bool {
self.oppr.is_none()
}
pub(crate) fn from_buffered_reader<T>(policy: &'a dyn Policy,
bio: Box<dyn BufferedReader<Cookie> + 'a>,
helper: H, time: T)
-> Result<Verifier<'a, H>>
where T: Into<Option<time::SystemTime>>
{
let time = time.into();
let tolerance = time
.map(|_| time::Duration::new(0, 0))
.unwrap_or(
*crate::packet::signature::subpacket::CLOCK_SKEW_TOLERANCE);
let time = time
.unwrap_or_else(|| time::SystemTime::now());
let mut ppr = PacketParser::from_buffered_reader(bio)?;
let mut v = Verifier {
helper: helper,
certs: Vec::new(),
oppr: None,
structure: IMessageStructure::new(),
reserve: None,
time: time,
clock_skew_tolerance: tolerance,
policy: policy,
};
let mut issuers = Vec::new();
while let PacketParserResult::Some(pp) = ppr {
if let Err(err) = pp.possible_message() {
return Err(err.context("Malformed OpenPGP message").into());
}
match pp.packet {
Packet::CompressedData(ref p) =>
v.structure.new_compression_layer(p.algo()),
Packet::OnePassSig(ref ops) => {
v.structure.push_ops(ops);
issuers.push(ops.issuer().clone().into());
},
Packet::Literal(_) => {
v.structure.insert_missing_signature_group();
v.certs = v.helper.get_public_keys(&issuers)?;
v.oppr = Some(PacketParserResult::Some(pp));
v.finish_maybe()?;
return Ok(v);
},
_ => (),
}
let (p, ppr_tmp) = pp.recurse()?;
if let Packet::Signature(sig) = p {
let sig_issuers = sig.get_issuers();
if sig_issuers.is_empty() {
issuers.push(KeyID::wildcard().into());
} else {
for issuer in sig_issuers {
issuers.push(issuer);
}
}
v.structure.push_bare_signature(sig);
}
ppr = ppr_tmp;
}
Err(Error::MalformedMessage(
"Malformed OpenPGP message".into()).into())
}
fn push_sig(&mut self, p: Packet) -> Result<()> {
match p {
Packet::Signature(sig) => {
self.structure.push_signature(sig);
},
_ => (),
}
Ok(())
}
fn check_signatures(&mut self) -> Result<()> {
assert!(self.oppr.is_none());
let mut results = MessageStructure::new();
for layer in ::std::mem::replace(&mut self.structure,
IMessageStructure::new())
.layers.into_iter()
{
match layer {
IMessageLayer::Compression { algo } =>
results.new_compression_layer(algo),
IMessageLayer::Encryption { .. } =>
unreachable!("not decrypting messages"),
IMessageLayer::SignatureGroup { sigs, .. } => {
results.new_signature_group();
'sigs: for sig in sigs.into_iter() {
let sig_time = if let Some(t) = sig.signature_creation_time() {
t
} else {
results.push_verification_result(
VerificationResult::Error {
sig,
error: Error::MalformedPacket(
"missing a Signature Creation Time \
subpacket"
.into()).into()
});
continue;
};
if let Err(_err) = sig.signature_alive(
self.time, self.clock_skew_tolerance)
{
results.push_verification_result(
VerificationResult::NotAlive {
sig: sig.clone(),
});
continue;
}
let mut err = VerificationResult::MissingKey {
sig: sig.clone(),
};
let issuers = sig.get_issuers();
for ka in self.certs.iter()
.flat_map(|cert| {
cert.keys().with_policy(self.policy, sig_time)
.key_handles(issuers.iter())
})
{
err = if let Err(err) = ka.cert_alive() {
VerificationResult::Error {
sig: sig.clone(),
error: err,
}
} else if let Err(err) = ka.alive() {
VerificationResult::Error {
sig: sig.clone(),
error: err,
}
} else if destructures_to!(
RevocationStatus::Revoked(_) = ka.cert_revoked())
{
VerificationResult::Error {
sig: sig.clone(),
error: Error::InvalidKey(
"certificate is revoked".into())
.into(),
}
} else if destructures_to!(
RevocationStatus::Revoked(_) = ka.revoked())
{
VerificationResult::Error {
sig: sig.clone(),
error: Error::InvalidKey(
"signing key is revoked".into())
.into(),
}
} else if ! ka.for_signing() {
VerificationResult::Error {
sig: sig.clone(),
error: Error::InvalidKey(
"key is not signing capable".into())
.into(),
}
} else {
match sig.verify(ka.key()) {
Ok(()) => {
if let Err(err) = self.policy.signature(&sig) {
VerificationResult::Error {
sig: sig.clone(),
error: err,
}
} else {
results.push_verification_result(
VerificationResult::GoodChecksum {
sig: sig,
cert: ka.cert(),
ka,
});
continue 'sigs;
}
}
Err(err) => {
VerificationResult::Error {
sig: sig.clone(),
error: err,
}
}
}
}
}
if let VerificationResult::MissingKey { .. } = err {
if let Some(ka) = self.certs.iter()
.flat_map(|cert| {
cert.keys().key_handles(issuers.iter())
})
.next()
{
err = VerificationResult::Error {
sig: sig.clone(),
error: Error::InvalidKey(
format!(
"Signing key ({}) not valid \
when signature was created",
ka.key().fingerprint()))
.into(),
}
}
}
results.push_verification_result(err);
}
}
}
}
self.helper.check(results)
}
fn finish_maybe(&mut self) -> Result<()> {
if let Some(PacketParserResult::Some(mut pp)) = self.oppr.take() {
let data_len = pp.data(BUFFER_SIZE + 1)?.len();
if data_len <= BUFFER_SIZE {
let data_len = pp.data(BUFFER_SIZE + 1)?.len();
assert!(data_len <= BUFFER_SIZE);
self.reserve = Some(pp.steal_eof()?);
let mut ppr = PacketParserResult::Some(pp);
while let PacketParserResult::Some(pp) = ppr {
if let Err(err) = pp.possible_message() {
return Err(err.context(
"Malformed OpenPGP message").into());
}
let (p, ppr_tmp) = pp.recurse()?;
self.push_sig(p)?;
ppr = ppr_tmp;
}
self.check_signatures()
} else {
self.oppr = Some(PacketParserResult::Some(pp));
Ok(())
}
} else {
panic!("No ppr.");
}
}
fn read_helper(&mut self, buf: &mut [u8]) -> Result<usize> {
if buf.len() == 0 {
return Ok(0);
}
if let Some(ref mut reserve) = self.reserve {
assert!(self.oppr.is_none());
let n = cmp::min(buf.len(), reserve.len());
&mut buf[..n].copy_from_slice(&reserve[..n]);
crate::vec_drain_prefix(reserve, n);
return Ok(n);
}
if let Some(PacketParserResult::Some(mut pp)) = self.oppr.take() {
let data_len = pp.data(BUFFER_SIZE + buf.len())?.len();
if data_len <= BUFFER_SIZE {
self.oppr = Some(PacketParserResult::Some(pp));
self.finish_maybe()?;
self.read_helper(buf)
} else {
let n = cmp::min(buf.len(), data_len - BUFFER_SIZE);
let buf = &mut buf[..n];
let result = pp.read(buf);
self.oppr = Some(PacketParserResult::Some(pp));
Ok(result?)
}
} else {
panic!("No ppr.");
}
}
}
impl<'a, H: VerificationHelper> io::Read for Verifier<'a, H> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.read_helper(buf) {
Ok(n) => Ok(n),
Err(e) => match e.downcast::<io::Error>() {
Ok(e) => Err(e),
Err(e) => Err(io::Error::new(io::ErrorKind::Other,
e.compat())),
},
}
}
}
struct Transformer<'a> {
state: TransformationState,
sigs: Vec<Signature>,
reader: Box<dyn BufferedReader<()> + 'a>,
buffer: Vec<u8>,
}
#[derive(PartialEq, Debug)]
enum TransformationState {
Data,
Sigs,
Done,
}
impl<'a> Transformer<'a> {
fn new<'b>(signatures: Box<dyn BufferedReader<Cookie> + 'b>,
mut data: Box<dyn BufferedReader<()> + 'a>)
-> Result<Transformer<'a>>
{
let mut sigs = Vec::new();
let mut ppr = PacketParser::from_buffered_reader(signatures)?;
while let PacketParserResult::Some(pp) = ppr {
let (packet, ppr_) = pp.next()?;
ppr = ppr_;
match packet {
Packet::Signature(sig) => sigs.push(sig),
_ => return Err(Error::InvalidArgument(
format!("Not a signature packet: {:?}",
packet.tag())).into()),
}
}
let mut buf = Vec::new();
for (i, sig) in sigs.iter().rev().enumerate() {
let mut ops = OnePassSig3::try_from(sig)?;
if i == sigs.len() - 1 {
ops.set_last(true);
}
Packet::OnePassSig(ops.into()).serialize(&mut buf)?;
}
let state = {
const HEADER_LEN: usize = 6;
let data_prefix = data.data_consume(512 - HEADER_LEN)?;
if data_prefix.len() < 512 - HEADER_LEN {
CTB::new(Tag::Literal).serialize(&mut buf)?;
let len = BodyLength::Full((data_prefix.len() + HEADER_LEN) as u32);
len.serialize(&mut buf)?;
let lit = Literal::new(DataFormat::Binary);
lit.serialize_headers(&mut buf, false)?;
buf.extend_from_slice(data_prefix);
TransformationState::Sigs
} else {
CTB::new(Tag::Literal).serialize(&mut buf)?;
let len = BodyLength::Partial(512);
len.serialize(&mut buf)?;
let lit = Literal::new(DataFormat::Binary);
lit.serialize_headers(&mut buf, false)?;
buf.extend_from_slice(&data_prefix[..512 - HEADER_LEN]);
TransformationState::Data
}
};
Ok(Self {
state: state,
sigs: sigs,
reader: data,
buffer: buf,
})
}
fn read_helper(&mut self, mut buf: &mut [u8]) -> Result<usize> {
let mut bytes_read = 0;
if self.buffer.is_empty() {
self.state = match self.state {
TransformationState::Data => {
let mut s = buf.len().next_power_of_two();
if ! buf.len().is_power_of_two() {
s >>= 1;
}
const MAX_CHUNK_SIZE: usize = 1 << 22; if s > MAX_CHUNK_SIZE {
s = MAX_CHUNK_SIZE;
}
assert!(s <= ::std::u32::MAX as usize);
let data = self.reader.data_consume(s)?;
let mut data = &data[..cmp::min(s, data.len())];
let short_read = data.len() < s;
let len = if short_read {
BodyLength::Full(data.len() as u32)
} else {
BodyLength::Partial(data.len() as u32)
};
len.serialize(&mut self.buffer)?;
let mut off = self.buffer.len();
if off < buf.len() {
&mut buf[..off].copy_from_slice(&self.buffer[..off]);
buf = &mut buf[off..];
bytes_read += off;
off = 0;
let n = cmp::min(buf.len(), data.len());
&mut buf[..n].copy_from_slice(&data[..n]);
data = &data[n..];
bytes_read += n;
}
self.buffer.resize(off + data.len(), 0);
&mut self.buffer[off..].copy_from_slice(data);
if short_read {
TransformationState::Sigs
} else {
TransformationState::Data
}
},
TransformationState::Sigs => {
for sig in self.sigs.drain(..) {
Packet::Signature(sig).serialize(&mut self.buffer)?;
}
TransformationState::Done
},
TransformationState::Done =>
TransformationState::Done,
};
}
if bytes_read > 0 {
return Ok(bytes_read);
}
let n = cmp::min(buf.len(), self.buffer.len());
&mut buf[..n].copy_from_slice(&self.buffer[..n]);
crate::vec_drain_prefix(&mut self.buffer, n);
Ok(n)
}
}
impl<'a> io::Read for Transformer<'a> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.read_helper(buf) {
Ok(n) => Ok(n),
Err(e) => match e.downcast::<io::Error>() {
Ok(e) => Err(e),
Err(e) => Err(io::Error::new(io::ErrorKind::Other,
e.compat())),
},
}
}
}
pub struct DetachedVerifier {
}
impl DetachedVerifier {
pub fn from_reader<'a, 's, H, R, S, T>(policy: &'a dyn Policy,
signature_reader: S, reader: R,
helper: H, t: T)
-> Result<Verifier<'a, H>>
where R: io::Read + 'a, S: io::Read + 's, H: VerificationHelper,
T: Into<Option<time::SystemTime>>
{
let t = t.into();
Self::from_buffered_reader(
policy,
Box::new(buffered_reader::Generic::with_cookie(signature_reader, None,
Default::default())),
Box::new(buffered_reader::Generic::new(reader, None)),
helper, t)
}
pub fn from_file<'a, H, P, S, T>(policy: &'a dyn Policy,
signature_path: S, path: P,
helper: H, t: T)
-> Result<Verifier<'a, H>>
where P: AsRef<Path>, S: AsRef<Path>, H: VerificationHelper,
T: Into<Option<time::SystemTime>>
{
let t = t.into();
Self::from_buffered_reader(
policy,
Box::new(buffered_reader::File::with_cookie(signature_path,
Default::default())?),
Box::new(buffered_reader::File::open(path)?),
helper, t)
}
pub fn from_bytes<'a, 's, H, T>(policy: &'a dyn Policy,
signature_bytes: &'s [u8], bytes: &'a [u8],
helper: H, t: T)
-> Result<Verifier<'a, H>>
where H: VerificationHelper, T: Into<Option<time::SystemTime>>
{
let t = t.into();
Self::from_buffered_reader(
policy,
Box::new(buffered_reader::Memory::with_cookie(signature_bytes,
Default::default())),
Box::new(buffered_reader::Memory::new(bytes)),
helper, t)
}
pub(crate) fn from_buffered_reader<'a, 's, H, T>
(policy: &'a dyn Policy,
signature_bio: Box<dyn BufferedReader<Cookie> + 's>,
reader: Box<dyn BufferedReader<()> + 'a>,
helper: H, t: T)
-> Result<Verifier<'a, H>>
where H: VerificationHelper,
T: Into<Option<time::SystemTime>>
{
let t = t.into();
Verifier::from_buffered_reader(
policy,
Box::new(buffered_reader::Generic::with_cookie(
Transformer::new(signature_bio, reader)?,
None, Default::default())),
helper, t)
}
}
pub struct Decryptor<'a, H: VerificationHelper + DecryptionHelper> {
helper: H,
certs: Vec<Cert>,
oppr: Option<PacketParserResult<'a>>,
identity: Option<Fingerprint>,
structure: IMessageStructure,
reserve: Option<Vec<u8>>,
time: time::SystemTime,
clock_skew_tolerance: time::Duration,
policy: &'a dyn Policy,
}
pub trait DecryptionHelper {
fn mapping(&self) -> bool {
false
}
fn inspect(&mut self, pp: &PacketParser) -> Result<()> {
let _ = pp;
Ok(())
}
fn decrypt<D>(&mut self, pkesks: &[PKESK], skesks: &[SKESK],
decrypt: D) -> Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> Result<()>;
}
impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
pub fn from_reader<R, T>(policy: &'a dyn Policy,
reader: R, helper: H, t: T)
-> Result<Decryptor<'a, H>>
where R: io::Read + 'a, T: Into<Option<time::SystemTime>>
{
let t = t.into();
Decryptor::from_buffered_reader(
policy,
Box::new(buffered_reader::Generic::with_cookie(reader, None,
Default::default())),
helper, t)
}
pub fn from_file<P, T>(policy: &'a dyn Policy, path: P, helper: H, t: T)
-> Result<Decryptor<'a, H>>
where P: AsRef<Path>,
T: Into<Option<time::SystemTime>>
{
let t = t.into();
Decryptor::from_buffered_reader(
policy,
Box::new(buffered_reader::File::with_cookie(path,
Default::default())?),
helper, t)
}
pub fn from_bytes<T>(policy: &'a dyn Policy, bytes: &'a [u8], helper: H, t: T)
-> Result<Decryptor<'a, H>>
where T: Into<Option<time::SystemTime>>
{
let t = t.into();
Decryptor::from_buffered_reader(
policy,
Box::new(buffered_reader::Memory::with_cookie(bytes,
Default::default())),
helper, t)
}
pub fn helper_ref(&self) -> &H {
&self.helper
}
pub fn helper_mut(&mut self) -> &mut H {
&mut self.helper
}
pub fn into_helper(self) -> H {
self.helper
}
pub fn message_processed(&self) -> bool {
self.oppr.is_none()
}
pub(crate) fn from_buffered_reader<T>(
policy: &'a dyn Policy,
bio: Box<dyn BufferedReader<Cookie> + 'a>,
helper: H, time: T)
-> Result<Decryptor<'a, H>>
where T: Into<Option<time::SystemTime>>
{
tracer!(TRACE, "Decryptor::from_buffered_reader", 0);
let time = time.into();
let tolerance = time
.map(|_| time::Duration::new(0, 0))
.unwrap_or(
*crate::packet::signature::subpacket::CLOCK_SKEW_TOLERANCE);
let time = time
.unwrap_or_else(|| time::SystemTime::now());
let mut ppr = PacketParserBuilder::from_buffered_reader(bio)?
.map(helper.mapping()).finalize()?;
let mut v = Decryptor {
helper: helper,
certs: Vec::new(),
oppr: None,
identity: None,
structure: IMessageStructure::new(),
reserve: None,
time: time,
clock_skew_tolerance: tolerance,
policy: policy,
};
let mut issuers = Vec::new();
let mut pkesks: Vec<packet::PKESK> = Vec::new();
let mut skesks: Vec<packet::SKESK> = Vec::new();
let mut saw_content = false;
while let PacketParserResult::Some(mut pp) = ppr {
v.helper.inspect(&pp)?;
if let Err(err) = pp.possible_message() {
t!("Malformed message: {}", err);
return Err(err.context("Malformed OpenPGP message").into());
}
match pp.packet {
Packet::CompressedData(ref p) =>
v.structure.new_compression_layer(p.algo()),
Packet::SEIP(_) | Packet::AED(_) => {
saw_content = true;
let mut sym_algo = None;
{
let decryption_proxy = |algo, secret: &SessionKey| {
let result = pp.decrypt(algo, secret);
if let Ok(_) = result {
sym_algo = Some(algo);
}
result
};
v.identity =
v.helper.decrypt(&pkesks[..], &skesks[..],
decryption_proxy)?;
}
if ! pp.decrypted() {
return Err(
Error::InvalidSessionKey("No session key".into())
.into());
}
v.structure.new_encryption_layer(
sym_algo.expect("if we got here, sym_algo is set"),
if let Packet::AED(ref p) = pp.packet {
Some(p.aead())
} else {
None
});
},
Packet::OnePassSig(ref ops) => {
v.structure.push_ops(ops);
issuers.push(ops.issuer().clone().into());
},
Packet::Literal(_) => {
v.structure.insert_missing_signature_group();
v.certs = v.helper.get_public_keys(&issuers)?;
v.oppr = Some(PacketParserResult::Some(pp));
v.finish_maybe()?;
return Ok(v);
},
Packet::MDC(ref mdc) => if ! mdc.valid() {
return Err(Error::ManipulatedMessage.into());
},
_ => (),
}
let (p, ppr_tmp) = pp.recurse()?;
match p {
Packet::PKESK(pkesk) => pkesks.push(pkesk),
Packet::SKESK(skesk) => skesks.push(skesk),
Packet::Signature(sig) => {
if ! saw_content {
let sig_issuers = sig.get_issuers();
if sig_issuers.is_empty() {
issuers.push(KeyID::wildcard().into());
} else {
for issuer in sig_issuers {
issuers.push(issuer);
}
}
}
v.structure.push_bare_signature(sig);
}
_ => (),
}
ppr = ppr_tmp;
}
Err(Error::MalformedMessage(
"Malformed OpenPGP message".into()).into())
}
fn push_sig(&mut self, p: Packet) -> Result<()> {
match p {
Packet::Signature(sig) => {
self.structure.push_signature(sig);
},
_ => (),
}
Ok(())
}
fn finish_maybe(&mut self) -> Result<()> {
if let Some(PacketParserResult::Some(mut pp)) = self.oppr.take() {
let data_len = pp.data(BUFFER_SIZE + 1)?.len();
if data_len <= BUFFER_SIZE {
self.reserve = Some(pp.steal_eof()?);
let mut ppr = PacketParserResult::Some(pp);
let mut first = true;
while let PacketParserResult::Some(pp) = ppr {
if first {
assert_eq!(pp.packet.tag(), packet::Tag::Literal);
first = false;
} else {
self.helper.inspect(&pp)?;
}
if let Err(err) = pp.possible_message() {
return Err(err.context(
"Malformed OpenPGP message").into());
}
match pp.packet {
Packet::MDC(ref mdc) => if ! mdc.valid() {
return Err(Error::ManipulatedMessage.into());
}
_ => (),
}
let (p, ppr_tmp) = pp.recurse()?;
self.push_sig(p)?;
ppr = ppr_tmp;
}
self.verify_signatures()
} else {
self.oppr = Some(PacketParserResult::Some(pp));
Ok(())
}
} else {
panic!("No ppr.");
}
}
fn verify_signatures(&mut self) -> Result<()> {
let mut results = MessageStructure::new();
for layer in ::std::mem::replace(&mut self.structure,
IMessageStructure::new())
.layers.into_iter()
{
match layer {
IMessageLayer::Compression { algo } =>
results.new_compression_layer(algo),
IMessageLayer::Encryption { sym_algo, aead_algo } =>
results.new_encryption_layer(sym_algo, aead_algo),
IMessageLayer::SignatureGroup { sigs, .. } => {
results.new_signature_group();
'sigs: for sig in sigs.into_iter() {
let sig_time = if let Some(t) = sig.signature_creation_time() {
t
} else {
results.push_verification_result(
VerificationResult::Error {
sig,
error: Error::MalformedPacket(
"missing a Signature Creation Time \
subpacket"
.into()).into()
});
continue;
};
if let Err(_err) = sig.signature_alive(
self.time, self.clock_skew_tolerance)
{
results.push_verification_result(
VerificationResult::NotAlive {
sig: sig.clone(),
});
continue;
}
let mut err = VerificationResult::MissingKey {
sig: sig.clone(),
};
let issuers = sig.get_issuers();
for ka in self.certs.iter()
.flat_map(|cert| {
cert.keys().with_policy(self.policy, sig_time)
.key_handles(issuers.iter())
})
{
err = if let Err(err) = ka.cert_alive() {
VerificationResult::Error {
sig: sig.clone(),
error: err,
}
} else if let Err(err) = ka.alive() {
VerificationResult::Error {
sig: sig.clone(),
error: err,
}
} else if destructures_to!(
RevocationStatus::Revoked(_) = ka.cert_revoked())
{
VerificationResult::Error {
sig: sig.clone(),
error: Error::InvalidKey(
"certificate is revoked".into())
.into(),
}
} else if destructures_to!(
RevocationStatus::Revoked(_) = ka.revoked())
{
VerificationResult::Error {
sig: sig.clone(),
error: Error::InvalidKey(
"signing key is revoked".into())
.into(),
}
} else if ! ka.for_signing() {
VerificationResult::Error {
sig: sig.clone(),
error: Error::InvalidKey(
"key is not signing capable".into())
.into(),
}
} else if self.identity.as_ref().map(|identity| {
let ir = sig.intended_recipients();
! ir.is_empty() && ! ir.contains(identity)
}).unwrap_or(false) {
VerificationResult::Error {
sig: sig.clone(),
error: Error::BadSignature(
"Not an intended recipient".into())
.into(),
}
} else {
match sig.verify(ka.key()) {
Ok(()) => {
if let Err(err) = self.policy.signature(&sig) {
VerificationResult::Error {
sig: sig.clone(),
error: err,
}
} else {
results.push_verification_result(
VerificationResult::GoodChecksum {
sig: sig,
cert: ka.cert(),
ka,
});
continue 'sigs;
}
}
Err(err) => {
VerificationResult::Error {
sig: sig.clone(),
error: err,
}
}
}
}
}
if let VerificationResult::MissingKey { .. } = err {
if let Some(ka) = self.certs.iter()
.flat_map(|cert| {
cert.keys().key_handles(issuers.iter())
})
.next()
{
err = VerificationResult::Error {
sig: sig.clone(),
error: Error::InvalidKey(
format!(
"Signing key ({}) not valid \
when signature was created",
ka.key().fingerprint()))
.into(),
}
}
}
results.push_verification_result(err);
}
}
}
}
self.helper.check(results)
}
fn read_helper(&mut self, buf: &mut [u8]) -> Result<usize> {
if buf.len() == 0 {
return Ok(0);
}
if let Some(ref mut reserve) = self.reserve {
assert!(self.oppr.is_none());
let n = cmp::min(buf.len(), reserve.len());
&mut buf[..n].copy_from_slice(&reserve[..n]);
crate::vec_drain_prefix(reserve, n);
return Ok(n);
}
if let Some(PacketParserResult::Some(mut pp)) = self.oppr.take() {
let data_len = pp.data(BUFFER_SIZE + buf.len())?.len();
if data_len <= BUFFER_SIZE {
self.oppr = Some(PacketParserResult::Some(pp));
self.finish_maybe()?;
self.read_helper(buf)
} else {
let n = cmp::min(buf.len(), data_len - BUFFER_SIZE);
let buf = &mut buf[..n];
let result = pp.read(buf);
self.oppr = Some(PacketParserResult::Some(pp));
Ok(result?)
}
} else {
panic!("No ppr.");
}
}
}
impl<'a, H: VerificationHelper + DecryptionHelper> io::Read for Decryptor<'a, H>
{
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
match self.read_helper(buf) {
Ok(n) => Ok(n),
Err(e) => match e.downcast::<io::Error>() {
Ok(e) => Err(e),
Err(e) => Err(io::Error::new(io::ErrorKind::Other,
e.compat())),
},
}
}
}
#[cfg(test)]
mod test {
use failure;
use super::*;
use crate::parse::Parse;
use crate::policy::StandardPolicy as P;
#[derive(PartialEq)]
struct VHelper {
good: usize,
unknown: usize,
bad: usize,
error: usize,
keys: Vec<Cert>,
}
impl std::fmt::Debug for VHelper {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_struct("VHelper")
.field("good", &self.good)
.field("unknown", &self.unknown)
.field("bad", &self.bad)
.field("error", &self.error)
.finish()
}
}
impl Default for VHelper {
fn default() -> Self {
VHelper {
good: 0,
unknown: 0,
bad: 0,
error: 0,
keys: Vec::default(),
}
}
}
impl VHelper {
fn new(good: usize, unknown: usize, bad: usize, error: usize, keys: Vec<Cert>) -> Self {
VHelper {
good: good,
unknown: unknown,
bad: bad,
error: error,
keys: keys,
}
}
}
impl VerificationHelper for VHelper {
fn get_public_keys(&mut self, _ids: &[crate::KeyHandle]) -> Result<Vec<Cert>> {
Ok(self.keys.clone())
}
fn check(&mut self, structure: MessageStructure) -> Result<()> {
use self::VerificationResult::*;
for layer in structure.iter() {
match layer {
MessageLayer::SignatureGroup { ref results } =>
for result in results {
match result {
GoodChecksum { .. } => self.good += 1,
MissingKey { .. } => self.unknown += 1,
NotAlive { .. } => self.bad += 1,
Error { error, .. } => {
eprintln!("error: {}", error);
self.bad += 1;
},
}
}
MessageLayer::Compression { .. } => (),
_ => unreachable!(),
}
}
if self.good > 0 && self.bad == 0 {
Ok(())
} else {
Err(failure::err_msg("Verification failed"))
}
}
}
impl DecryptionHelper for VHelper {
fn decrypt<D>(&mut self, _: &[PKESK], _: &[SKESK], _: D)
-> Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> Result<()>
{
unreachable!();
}
}
#[test]
fn verifier() {
let p = P::new();
let keys = [
"neal.pgp",
"emmelie-dorothea-dina-samantha-awina-ed25519.pgp"
].iter()
.map(|f| Cert::from_bytes(crate::tests::key(f)).unwrap())
.collect::<Vec<_>>();
let tests = &[
("messages/signed-1.gpg", VHelper::new(1, 0, 0, 0, keys.clone())),
("messages/signed-1-sha256-testy.gpg", VHelper::new(0, 1, 0, 0, keys.clone())),
("messages/signed-1-notarized-by-ed25519.pgp", VHelper::new(2, 0, 0, 0, keys.clone())),
("keys/neal.pgp", VHelper::new(0, 0, 0, 1, keys.clone())),
];
let reference = crate::tests::manifesto();
for (f, r) in tests {
eprintln!("{}...", f);
let h = VHelper::new(0, 0, 0, 0, keys.clone());
let mut v =
match Verifier::from_bytes(&p, crate::tests::file(f), h,
crate::frozen_time()) {
Ok(v) => v,
Err(e) => if r.error > 0 || r.unknown > 0 {
continue;
} else {
panic!("{}: {}", f, e);
},
};
assert!(v.message_processed());
assert_eq!(v.helper_ref(), r);
if v.helper_ref().error > 0 {
continue;
}
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
let h = VHelper::new(0, 0, 0, 0, keys.clone());
let mut v =
match Decryptor::from_bytes(&p, crate::tests::file(f), h,
crate::frozen_time()) {
Ok(v) => v,
Err(e) => if r.error > 0 || r.unknown > 0 {
continue;
} else {
panic!("{}: {}", f, e);
},
};
assert!(v.message_processed());
assert_eq!(v.helper_ref(), r);
if v.helper_ref().error > 0 {
continue;
}
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
}
}
#[test]
fn verifier_levels() {
let p = P::new();
struct VHelper(());
impl VerificationHelper for VHelper {
fn get_public_keys(&mut self, _ids: &[crate::KeyHandle])
-> Result<Vec<Cert>> {
Ok(Vec::new())
}
fn check(&mut self, structure: MessageStructure) -> Result<()> {
assert_eq!(structure.iter().count(), 2);
for (i, layer) in structure.into_iter().enumerate() {
match layer {
MessageLayer::SignatureGroup { results } => {
assert_eq!(results.len(), 1);
if let VerificationResult::MissingKey { sig, .. } =
&results[0]
{
assert_eq!(
&sig.issuer_fingerprint().unwrap()
.to_string(),
match i {
0 => "8E8C 33FA 4626 3379 76D9 7978 069C 0C34 8DD8 2C19",
1 => "C03F A641 1B03 AE12 5764 6118 7223 B566 78E0 2528",
_ => unreachable!(),
}
);
}
},
_ => unreachable!(),
}
}
Ok(())
}
}
impl DecryptionHelper for VHelper {
fn decrypt<D>(&mut self, _: &[PKESK], _: &[SKESK], _: D)
-> Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> Result<()>
{
unreachable!();
}
}
let v = Verifier::from_bytes(
&p, crate::tests::message("signed-1-notarized-by-ed25519.pgp"),
VHelper(()), crate::frozen_time()).unwrap();
assert!(v.message_processed());
let v = Decryptor::from_bytes(
&p, crate::tests::message("signed-1-notarized-by-ed25519.pgp"),
VHelper(()), crate::frozen_time()).unwrap();
assert!(v.message_processed());
}
fn detached_verifier_read_size(l: usize) {
lazy_static! {
static ref ZEROS: Vec<u8> = vec![0; 100 * 1024 * 1024];
}
let p = P::new();
struct Test<'a> {
sig: &'a [u8],
content: &'a [u8],
reference: time::SystemTime,
};
let tests = [
Test {
sig: crate::tests::message(
"a-cypherpunks-manifesto.txt.ed25519.sig"),
content: crate::tests::manifesto(),
reference: crate::frozen_time(),
},
Test {
sig: crate::tests::message(
"emmelie-dorothea-dina-samantha-awina-detached-signature-of-100MB-of-zeros.sig"),
content: &ZEROS[..],
reference:
crate::types::Timestamp::try_from(1572602018).unwrap().into(),
},
];
let keys = [
"emmelie-dorothea-dina-samantha-awina-ed25519.pgp"
].iter()
.map(|f| Cert::from_bytes(crate::tests::key(f)).unwrap())
.collect::<Vec<_>>();
let read_to_end = |v: &mut Verifier<_>, l, buffer: &mut Vec<_>| {
let mut offset = 0;
loop {
if offset + l > buffer.len() {
if buffer.len() < buffer.capacity() {
buffer.resize(buffer.capacity(), 0);
} else {
buffer.resize(buffer.capacity() * 2, 0);
}
}
match v.read(&mut buffer[offset..offset + l]) {
Ok(0) => break,
Ok(l) => offset += l,
Err(err) => panic!("Error reading data: {:?}", err),
}
}
offset
};
let mut buffer = vec![0; 104 * 1024 * 1024];
for test in tests.iter() {
let sig = test.sig;
let content = test.content;
let reference = test.reference;
let h = VHelper::new(0, 0, 0, 0, keys.clone());
let mut v = DetachedVerifier::from_bytes(
&p, sig, content, h, reference).unwrap();
let got = read_to_end(&mut v, l, &mut buffer);
assert!(v.message_processed());
let got = &buffer[..got];
assert_eq!(got.len(), content.len());
assert_eq!(got, &content[..]);
let h = v.into_helper();
assert_eq!(h.good, 1);
assert_eq!(h.bad, 0);
}
crate::vec_truncate(&mut buffer, 0);
}
#[test]
fn detached_verifier1() {
detached_verifier_read_size(4 * 1024 * 1024 - 1);
}
#[test]
fn detached_verifier2() {
detached_verifier_read_size(4 * 1024 * 1024);
}
#[test]
fn detached_verifier3() {
detached_verifier_read_size(4 * 1024 * 1024 + 1);
}
#[test]
fn verify_long_message() {
use std::io::Write;
use crate::cert::{CertBuilder, CipherSuite};
use crate::serialize::stream::{LiteralWriter, Signer, Message};
let p = &P::new();
let (cert, _) = CertBuilder::new()
.set_cipher_suite(CipherSuite::Cv25519)
.add_signing_subkey()
.generate().unwrap();
let mut buf = vec![];
{
let key = cert.keys().with_policy(p, None).for_signing().nth(0).unwrap().key();
let keypair =
key.clone().mark_parts_secret().unwrap()
.into_keypair().unwrap();
let m = Message::new(&mut buf);
let signer = Signer::new(m, keypair).build().unwrap();
let mut ls = LiteralWriter::new(signer).build().unwrap();
ls.write_all(&mut vec![42u8; 30 * 1024 * 1024]).unwrap();
ls.finalize().unwrap();
}
let h = VHelper::new(0, 0, 0, 0, vec![cert.clone()]);
let mut v = Verifier::from_bytes(p, &buf, h, None).unwrap();
assert!(!v.message_processed());
assert!(v.helper_ref().good == 0);
assert!(v.helper_ref().bad == 0);
assert!(v.helper_ref().unknown == 0);
assert!(v.helper_ref().error == 0);
let mut message = Vec::new();
v.read_to_end(&mut message).unwrap();
assert!(v.message_processed());
assert_eq!(30 * 1024 * 1024, message.len());
assert!(message.iter().all(|&b| b == 42));
assert!(v.helper_ref().good == 1);
assert!(v.helper_ref().bad == 0);
assert!(v.helper_ref().unknown == 0);
assert!(v.helper_ref().error == 0);
let h = VHelper::new(0, 0, 1, 0,
vec![cert.clone()]);
let mut v = Verifier::from_bytes(p, &buf, h, None).unwrap();
assert!(!v.message_processed());
assert!(v.helper_ref().good == 0);
assert!(v.helper_ref().bad == 1);
assert!(v.helper_ref().unknown == 0);
assert!(v.helper_ref().error == 0);
let mut message = Vec::new();
let r = v.read_to_end(&mut message);
assert!(r.is_err());
assert!(v.message_processed());
assert!(message.len() > 0);
assert!(message.len() <= 5 * 1024 * 1024);
assert!(message.iter().all(|&b| b == 42));
assert!(v.helper_ref().good == 1);
assert!(v.helper_ref().bad == 1);
assert!(v.helper_ref().unknown == 0);
assert!(v.helper_ref().error == 0);
let h = VHelper::new(0, 0, 0, 0, vec![cert.clone()]);
let mut v = Decryptor::from_bytes(p, &buf, h, None).unwrap();
assert!(!v.message_processed());
assert!(v.helper_ref().good == 0);
assert!(v.helper_ref().bad == 0);
assert!(v.helper_ref().unknown == 0);
assert!(v.helper_ref().error == 0);
let mut message = Vec::new();
v.read_to_end(&mut message).unwrap();
assert!(v.message_processed());
assert_eq!(30 * 1024 * 1024, message.len());
assert!(message.iter().all(|&b| b == 42));
assert!(v.helper_ref().good == 1);
assert!(v.helper_ref().bad == 0);
assert!(v.helper_ref().unknown == 0);
assert!(v.helper_ref().error == 0);
let h = VHelper::new(0, 0, 1, 0,
vec![cert.clone()]);
let mut v = Decryptor::from_bytes(p, &buf, h, None).unwrap();
assert!(!v.message_processed());
assert!(v.helper_ref().good == 0);
assert!(v.helper_ref().bad == 1);
assert!(v.helper_ref().unknown == 0);
assert!(v.helper_ref().error == 0);
let mut message = Vec::new();
let r = v.read_to_end(&mut message);
assert!(r.is_err());
assert!(v.message_processed());
assert!(message.len() > 0);
assert!(message.len() <= 5 * 1024 * 1024);
assert!(message.iter().all(|&b| b == 42));
assert!(v.helper_ref().good == 1);
assert!(v.helper_ref().bad == 1);
assert!(v.helper_ref().unknown == 0);
assert!(v.helper_ref().error == 0);
}
}