use std::cmp;
use std::convert::TryFrom;
use std::collections::HashMap;
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,
Key,
Literal,
OnePassSig,
one_pass_sig::OnePassSig3,
PKESK,
SKESK,
Tag,
},
KeyID,
Packet,
Result,
RevocationStatus,
packet,
packet::Signature,
Cert,
crypto::SessionKey,
serialize::Serialize,
};
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>,
keys: HashMap<crate::KeyHandle, (usize, usize)>,
oppr: Option<PacketParserResult<'a>>,
structure: IMessageStructure,
reserve: Option<Vec<u8>>,
time: time::SystemTime,
clock_skew_tolerance: time::Duration,
}
#[derive(Debug)]
pub enum VerificationResult<'a> {
GoodChecksum {
sig: Signature,
cert: &'a Cert,
key: &'a key::UnspecifiedPublic,
binding: Option<&'a Signature>,
revoked: RevocationStatus<'a>,
},
NotAlive {
sig: Signature,
cert: &'a Cert,
key: &'a key::UnspecifiedPublic,
binding: Option<&'a Signature>,
revoked: RevocationStatus<'a>,
},
MissingKey {
sig: Signature,
},
BadChecksum {
sig: Signature,
cert: &'a Cert,
key: &'a key::UnspecifiedPublic,
binding: Option<&'a Signature>,
revoked: RevocationStatus<'a>,
},
}
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(),
BadChecksum { 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 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()
}
}
#[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, _: &[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>(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(
Box::new(buffered_reader::Generic::with_cookie(reader, None,
Default::default())),
helper, t)
}
pub fn from_file<P, T>(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(
Box::new(buffered_reader::File::with_cookie(path,
Default::default())?),
helper, t)
}
pub fn from_bytes<T>(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(
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>(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());
fn for_signing<P, R>(key: &Key<P, R>, sig: Option<&Signature>,
time: time::SystemTime, tolerance: time::Duration)
-> bool
where P: key::KeyParts, R: key::KeyRole
{
if let Some(sig) = sig {
sig.key_flags().for_signing()
&& sig.signature_alive(time, tolerance).is_ok()
&& sig.key_alive(key, time).is_ok()
} else {
false
}
}
let mut ppr = PacketParser::from_buffered_reader(bio)?;
let mut v = Verifier {
helper: helper,
certs: Vec::new(),
keys: HashMap::new(),
oppr: None,
structure: IMessageStructure::new(),
reserve: None,
time: time,
clock_skew_tolerance: tolerance,
};
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.algorithm()),
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)?;
for (i, cert) in v.certs.iter().enumerate() {
if for_signing(cert.primary(),
cert.primary_key_signature(None),
time, tolerance) {
v.keys.insert(cert.fingerprint().into(), (i, 0));
v.keys.insert(cert.keyid().into(), (i, 0));
}
for (j, skb) in cert.subkeys().enumerate() {
let key = skb.key();
if for_signing(key, skb.binding_signature(None),
time, tolerance) {
v.keys.insert(key.fingerprint().into(),
(i, j + 1));
v.keys.insert(key.keyid().into(),
(i, j + 1));
}
}
}
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() {
for issuer in sig.get_issuers() {
if let Some((i, j)) = self.keys.get(&issuer) {
let cert = &self.certs[*i];
let ka = cert.keys().nth(*j).unwrap();
let binding = ka.binding_signature(self.time);
let revoked = ka.revoked(self.time);
let key = ka.key();
results.push_verification_result(
if sig.verify(key).unwrap_or(false) {
if sig.signature_alive(
self.time, self.clock_skew_tolerance)
.is_ok()
{
VerificationResult::GoodChecksum {
sig: sig.clone(),
cert, key, binding, revoked,
}
} else {
VerificationResult::NotAlive {
sig: sig.clone(),
cert, key, binding, revoked,
}
}
} else {
VerificationResult::BadChecksum {
sig: sig.clone(),
cert, key, binding, revoked,
}
}
);
continue 'sigs;
}
}
results.push_verification_result(
VerificationResult::MissingKey {
sig,
}
);
}
},
}
}
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]);
reserve.drain(..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, buf: &mut [u8]) -> Result<usize> {
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 data = &data[..cmp::min(s, data.len())];
if data.len() < s {
let len = BodyLength::Full(data.len() as u32);
len.serialize(&mut self.buffer)?;
let l = self.buffer.len();
self.buffer.resize(l + data.len(), 0);
&mut self.buffer[l..].copy_from_slice(data);
TransformationState::Sigs
} else {
let len = BodyLength::Partial(data.len() as u32);
len.serialize(&mut self.buffer)?;
let l = self.buffer.len();
self.buffer.resize(l + data.len(), 0);
&mut self.buffer[l..].copy_from_slice(data);
TransformationState::Data
}
},
TransformationState::Sigs => {
for sig in self.sigs.drain(..) {
Packet::Signature(sig).serialize(&mut self.buffer)?;
}
TransformationState::Done
},
TransformationState::Done =>
TransformationState::Done,
};
}
let n = cmp::min(buf.len(), self.buffer.len());
&mut buf[..n].copy_from_slice(&self.buffer[..n]);
self.buffer.drain(..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>(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(
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>(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(
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>(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(
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>
(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(
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>,
keys: HashMap<crate::KeyHandle, (usize, usize)>,
oppr: Option<PacketParserResult<'a>>,
identity: Option<Fingerprint>,
structure: IMessageStructure,
reserve: Option<Vec<u8>>,
time: time::SystemTime,
clock_skew_tolerance: time::Duration,
}
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>(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(
Box::new(buffered_reader::Generic::with_cookie(reader, None,
Default::default())),
helper, t)
}
pub fn from_file<P, T>(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(
Box::new(buffered_reader::File::with_cookie(path,
Default::default())?),
helper, t)
}
pub fn from_bytes<T>(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(
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>(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(),
keys: HashMap::new(),
oppr: None,
identity: None,
structure: IMessageStructure::new(),
reserve: None,
time: time,
clock_skew_tolerance: tolerance,
};
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.algorithm()),
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)?;
for (i, cert) in v.certs.iter().enumerate() {
let for_signing = |key: &key::UnspecifiedKey,
sig: Option<&Signature>| -> bool
{
if let Some(sig) = sig {
sig.key_flags().for_signing()
&& sig.signature_alive(time, tolerance)
.is_ok()
&& sig.key_alive(key, time).is_ok()
} else {
false
}
};
if for_signing(cert.primary().into(),
cert.primary_key_signature(None)) {
v.keys.insert(cert.fingerprint().into(), (i, 0));
v.keys.insert(cert.keyid().into(), (i, 0));
}
for (j, skb) in cert.subkeys().enumerate() {
let key = skb.key();
if for_signing(key.into(), skb.binding_signature(None)) {
v.keys.insert(key.fingerprint().into(),
(i, j + 1));
v.keys.insert(key.keyid().into(),
(i, j + 1));
}
}
}
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() {
for issuer in sig.get_issuers() {
if let Some((i, j)) = self.keys.get(&issuer) {
let cert = &self.certs[*i];
let ka = cert.keys().nth(*j).unwrap();
let binding = ka.binding_signature(self.time);
let revoked = ka.revoked(self.time);
let key = ka.key();
results.push_verification_result(
if sig.verify(key).unwrap_or(false) &&
sig.signature_alive(
self.time, self.clock_skew_tolerance)
.is_ok()
{
if let Some(identity) =
self.identity.as_ref()
{
let ir = sig.intended_recipients();
if !ir.is_empty()
&& !ir.contains(identity)
{
VerificationResult::BadChecksum
{
sig: sig.clone(),
cert, key, binding, revoked,
}
} else {
VerificationResult::GoodChecksum
{
sig: sig.clone(),
cert, key, binding, revoked,
}
}
} else {
VerificationResult::GoodChecksum {
sig: sig.clone(),
cert, key, binding, revoked,
}
}
} else {
VerificationResult::BadChecksum {
sig: sig.clone(),
cert, key, binding, revoked,
}
}
);
continue 'sigs;
}
}
results.push_verification_result(
VerificationResult::MissingKey {
sig,
}
);
}
},
}
}
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]);
reserve.drain(..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;
#[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,
BadChecksum { .. } => 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 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 {
let h = VHelper::new(0, 0, 0, 0, keys.clone());
let mut v =
match Verifier::from_bytes(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(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() {
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.iter().enumerate() {
match layer {
MessageLayer::SignatureGroup { ref 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(
crate::tests::message("signed-1-notarized-by-ed25519.pgp"),
VHelper(()), crate::frozen_time()).unwrap();
assert!(v.message_processed());
let v = Decryptor::from_bytes(
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) {
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: &vec![ 0; 100 * 1024 * 1024 ][..],
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 mut buffer = Vec::with_capacity(104 * 1024 * 1024);
buffer.resize(buffer.capacity(), 0);
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
};
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(
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);
use std::io::Cursor;
let h = VHelper::new(0, 0, 0, 0, keys.clone());
let mut v = DetachedVerifier::from_reader(
Cursor::new(sig), Cursor::new(content),
h, reference).unwrap();
let got = read_to_end(&mut v, l, &mut buffer);
let got = &buffer[..got];
assert!(v.message_processed());
assert_eq!(got.len(), content.len());
assert_eq!(got, &content[..]);
}
}
#[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 crate::cert::{CertBuilder, CipherSuite};
use crate::serialize::stream::{LiteralWriter, Signer, Message};
use std::io::Write;
let (cert, _) = CertBuilder::new()
.set_cipher_suite(CipherSuite::Cv25519)
.add_signing_subkey()
.generate().unwrap();
let mut buf = vec![];
{
let key = cert.keys().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(&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(&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(&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(&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);
}
}