use std::cmp;
use std::io::{self, Read};
use std::path::Path;
use std::time;
use buffered_reader::BufferedReader;
use crate::{
Error,
Fingerprint,
types::{
AEADAlgorithm,
CompressionAlgorithm,
RevocationStatus,
SymmetricAlgorithm,
},
packet::{
key,
OnePassSig,
PKESK,
SKESK,
},
KeyID,
Packet,
Result,
packet,
packet::Signature,
cert::prelude::*,
crypto::SessionKey,
policy::Policy,
};
use crate::parse::{
Cookie,
PacketParser,
PacketParserBuilder,
PacketParserResult,
};
const TRACE : bool = false;
const BUFFER_SIZE: usize = 25 * 1024 * 1024;
pub type VerificationResult<'a> =
std::result::Result<GoodChecksum<'a>, VerificationError<'a>>;
#[derive(Debug)]
pub struct GoodChecksum<'a> {
pub sig: &'a Signature,
pub ka: ValidErasedKeyAmalgamation<'a, key::PublicParts>,
}
#[derive(Debug)]
pub enum VerificationError<'a> {
MalformedSignature {
sig: &'a Signature,
error: anyhow::Error,
},
MissingKey {
sig: &'a Signature,
},
UnboundKey {
sig: &'a Signature,
cert: &'a Cert,
error: anyhow::Error,
},
BadKey {
sig: &'a Signature,
ka: ValidErasedKeyAmalgamation<'a, key::PublicParts>,
error: anyhow::Error,
},
BadSignature {
sig: &'a Signature,
ka: ValidErasedKeyAmalgamation<'a, key::PublicParts>,
error: anyhow::Error,
},
}
impl<'a> From<VerificationError<'a>> for Error {
fn from(e: VerificationError<'a>) -> Self {
use self::VerificationError::*;
match e {
MalformedSignature { error, .. } =>
Error::MalformedPacket(error.to_string()),
MissingKey { .. } =>
Error::InvalidKey("Could not locate signing key".into()),
UnboundKey { error, .. } =>
Error::InvalidKey(error.to_string()),
BadKey { error, .. } =>
Error::InvalidKey(error.to_string()),
BadSignature { error, .. } =>
Error::BadSignature(error.to_string()),
}
}
}
#[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,
})
}
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,
});
}
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<()>;
}
struct NoDecryptionHelper<V: VerificationHelper> {
v: V,
}
impl<V: VerificationHelper> VerificationHelper for NoDecryptionHelper<V> {
fn get_public_keys(&mut self, ids: &[crate::KeyHandle]) -> Result<Vec<Cert>>
{
self.v.get_public_keys(ids)
}
fn check(&mut self, structure: MessageStructure) -> Result<()>
{
self.v.check(structure)
}
}
impl<V: VerificationHelper> DecryptionHelper for NoDecryptionHelper<V> {
fn decrypt<D>(&mut self, _: &[PKESK], _: &[SKESK],
_: Option<SymmetricAlgorithm>,
_: D) -> Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> Result<()>
{
unreachable!("This is not used for verifications")
}
}
pub struct Verifier<'a, H: VerificationHelper> {
decryptor: Decryptor<'a, NoDecryptionHelper<H>>,
}
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.decryptor.helper_ref().v
}
pub fn helper_mut(&mut self) -> &mut H {
&mut self.decryptor.helper_mut().v
}
pub fn into_helper(self) -> H {
self.decryptor.into_helper().v
}
pub fn message_processed(&self) -> bool {
self.decryptor.message_processed()
}
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>>
{
Ok(Verifier {
decryptor: Decryptor::from_buffered_reader(
policy, bio, NoDecryptionHelper { v: helper, }, time,
Mode::Verify)?,
})
}
}
impl<'a, H: VerificationHelper> io::Read for Verifier<'a, H> {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.decryptor.read(buf)
}
}
pub struct DetachedVerifier<'a, H: VerificationHelper> {
decryptor: Decryptor<'a, NoDecryptionHelper<H>>,
}
impl<'a, H: VerificationHelper> DetachedVerifier<'a, H> {
pub fn from_reader<S, T>(policy: &'a dyn Policy,
signature_reader: S,
helper: H, t: T)
-> Result<DetachedVerifier<'a, H>>
where S: io::Read + 'a,
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())),
helper, t)
}
pub fn from_file<S, T>(policy: &'a dyn Policy,
signature_path: S,
helper: H, t: T)
-> Result<DetachedVerifier<'a, H>>
where 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())?),
helper, t)
}
pub fn from_bytes<T>(policy: &'a dyn Policy,
signature_bytes: &'a [u8],
helper: H, t: T)
-> Result<DetachedVerifier<'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())),
helper, t)
}
pub(crate) fn from_buffered_reader<T>
(policy: &'a dyn Policy,
signature_bio: Box<dyn BufferedReader<Cookie> + 'a>,
helper: H, t: T)
-> Result<DetachedVerifier<'a, H>>
where H: VerificationHelper,
T: Into<Option<time::SystemTime>>
{
let t = t.into();
Ok(Self {
decryptor: Decryptor::from_buffered_reader(
policy,
signature_bio,
NoDecryptionHelper { v: helper, },
t, Mode::VerifyDetached)?,
})
}
pub fn verify_reader<R: io::Read>(&mut self, reader: R) -> Result<()> {
self.verify(buffered_reader::Generic::with_cookie(
reader, None, Default::default()).as_boxed())
}
pub fn verify_file<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
self.verify(buffered_reader::File::with_cookie(
path, Default::default())?.as_boxed())
}
pub fn verify_bytes<B: AsRef<[u8]>>(&mut self, buf: B) -> Result<()> {
self.verify(buffered_reader::Memory::with_cookie(
buf.as_ref(), Default::default()).as_boxed())
}
fn verify<R>(&mut self, reader: R) -> Result<()>
where R: BufferedReader<Cookie>,
{
self.decryptor.verify_detached(reader)
}
pub fn helper_ref(&self) -> &H {
&self.decryptor.helper_ref().v
}
pub fn helper_mut(&mut self) -> &mut H {
&mut self.decryptor.helper_mut().v
}
pub fn into_helper(self) -> H {
self.decryptor.into_helper().v
}
}
#[derive(Debug, PartialEq, Eq)]
enum Mode {
Decrypt,
Verify,
VerifyDetached,
}
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>>,
cursor: usize,
mode: Mode,
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],
sym_algo: Option<SymmetricAlgorithm>,
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, Mode::Decrypt)
}
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, Mode::Decrypt)
}
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, Mode::Decrypt)
}
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()
}
fn from_buffered_reader<T>(
policy: &'a dyn Policy,
bio: Box<dyn BufferedReader<Cookie> + 'a>,
helper: H, time: T,
mode: Mode)
-> 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,
certs: Vec::new(),
oppr: None,
identity: None,
structure: IMessageStructure::new(),
reserve: None,
cursor: 0,
mode,
time,
clock_skew_tolerance: tolerance,
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.policy.packet(&pp.packet)?;
v.helper.inspect(&pp)?;
if v.mode != Mode::VerifyDetached {
if let Err(err) = pp.possible_message() {
t!("Malformed message: {}", err);
return Err(err.context("Malformed OpenPGP message").into());
}
}
let sym_algo_hint = if let Packet::AED(ref aed) = pp.packet {
Some(aed.symmetric_algo())
} else {
None
};
match pp.packet {
Packet::CompressedData(ref p) =>
v.structure.new_compression_layer(p.algo()),
Packet::SEIP(_) | Packet::AED(_) if v.mode == Mode::Decrypt => {
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[..],
sym_algo_hint,
decryption_proxy)?;
}
if ! pp.decrypted() {
return Err(
Error::MissingSessionKey(
"No session key decrypted".into()).into());
}
let sym_algo =
sym_algo.expect("if we got here, sym_algo is set");
v.policy.symmetric_algorithm(sym_algo)?;
if let Packet::AED(ref p) = pp.packet {
v.policy.aead_algorithm(p.aead())?;
}
v.structure.new_encryption_layer(
sym_algo,
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;
}
if v.mode == Mode::VerifyDetached {
v.certs = v.helper.get_public_keys(&issuers)?;
return Ok(v);
}
Err(Error::MalformedMessage(
"Malformed OpenPGP message".into()).into())
}
fn verify_detached<D>(&mut self, data: D) -> Result<()>
where D: BufferedReader<Cookie>
{
assert_eq!(self.mode, Mode::VerifyDetached);
let sigs = if let IMessageLayer::SignatureGroup {
sigs, .. } = &mut self.structure.layers[0] {
sigs
} else {
unreachable!("There is exactly one signature group layer")
};
let algos: Vec<_> = sigs.iter().map(|s| s.hash_algo()).collect();
let hashes = crate::crypto::hash_buffered_reader(data, &algos)?;
for sig in sigs.iter_mut() {
let algo = sig.hash_algo();
for hash in hashes.iter().filter(|c| c.algo() == algo) {
use crate::crypto::hash::Hash;
let mut hash = hash.clone();
sig.hash(&mut hash);
let mut digest = vec![0; hash.digest_size()];
hash.digest(&mut digest);
sig.set_computed_digest(Some(digest.into()));
}
}
self.verify_signatures()
}
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()?);
self.cursor = 0;
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<()> {
tracer!(TRACE, "Decryptor::verify_signatures", 0);
t!("called");
let mut results = MessageStructure::new();
for layer in self.structure.layers.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.iter() {
let sigid = sig.digest_prefix().clone();
let sig_time = if let Some(t) = sig.signature_creation_time() {
t
} else {
results.push_verification_result(
Err(VerificationError::MalformedSignature {
sig,
error: Error::MalformedPacket(
"missing a Signature Creation Time \
subpacket"
.into()).into(),
}));
t!("{:02X}{:02X}: Missing a signature creation time subpacket",
sigid[0], sigid[1]);
continue;
};
let mut err = VerificationError::MissingKey {
sig,
};
let issuers = sig.get_issuers();
for ka in self.certs.iter()
.flat_map(|cert| {
cert.keys().key_handles(issuers.iter())
})
{
let cert = ka.cert();
let fingerprint = ka.fingerprint();
let ka = match ka.with_policy(self.policy, sig_time) {
Err(policy_err) => {
t!("{:02X}{:02X}: key {} rejected by policy: {}",
sigid[0], sigid[1], fingerprint, policy_err);
err = VerificationError::UnboundKey {
sig,
cert,
error: policy_err,
};
continue;
}
Ok(ka) => {
t!("{:02X}{:02X}: key {} accepted by policy",
sigid[0], sigid[1], fingerprint);
ka
}
};
err = if let Err(err) = ka.cert_alive() {
t!("{:02X}{:02X}: cert {} not alive: {}",
sigid[0], sigid[1], ka.cert().fingerprint(), err);
VerificationError::BadKey {
sig,
ka,
error: err,
}
} else if let Err(err) = ka.alive() {
t!("{:02X}{:02X}: key {} not alive: {}",
sigid[0], sigid[1], ka.fingerprint(), err);
VerificationError::BadKey {
sig,
ka,
error: err,
}
} else if let
RevocationStatus::Revoked(rev) = ka.cert_revoked()
{
t!("{:02X}{:02X}: cert {} revoked: {:?}",
sigid[0], sigid[1], ka.cert().fingerprint(), rev);
VerificationError::BadKey {
sig,
ka,
error: Error::InvalidKey(
"certificate is revoked".into())
.into(),
}
} else if let
RevocationStatus::Revoked(rev) = ka.revoked()
{
t!("{:02X}{:02X}: key {} revoked: {:?}",
sigid[0], sigid[1], ka.fingerprint(), rev);
VerificationError::BadKey {
sig,
ka,
error: Error::InvalidKey(
"signing key is revoked".into())
.into(),
}
} else if ! ka.for_signing() {
t!("{:02X}{:02X}: key {} not signing capable",
sigid[0], sigid[1], ka.fingerprint());
VerificationError::BadKey {
sig,
ka,
error: Error::InvalidKey(
"key is not signing capable".into())
.into(),
}
} else if let Err(err) = sig.signature_alive(
self.time, self.clock_skew_tolerance)
{
t!("{:02X}{:02X}: Signature not alive: {}",
sigid[0], sigid[1], err);
VerificationError::BadSignature {
sig,
ka,
error: err,
}
} else if self.identity.as_ref().map(|identity| {
let ir = sig.intended_recipients();
! ir.is_empty() && ! ir.contains(identity)
}).unwrap_or(false) {
t!("{:02X}{:02X}: not an intended recipient",
sigid[0], sigid[1]);
VerificationError::BadSignature {
sig,
ka,
error: Error::BadSignature(
"Not an intended recipient".into())
.into(),
}
} else {
match sig.verify(ka.key()) {
Ok(()) => {
if let Err(err) = self.policy.signature(&sig) {
t!("{:02X}{:02X}: signature rejected by policy: {}",
sigid[0], sigid[1], err);
VerificationError::BadSignature {
sig,
ka,
error: err,
}
} else {
t!("{:02X}{:02X}: good checksum using {}",
sigid[0], sigid[1], ka.fingerprint());
results.push_verification_result(
Ok(GoodChecksum {
sig: sig,
ka,
}));
continue 'sigs;
}
}
Err(err) => {
t!("{:02X}{:02X} using {}: error: {}",
sigid[0], sigid[1], ka.fingerprint(), err);
VerificationError::BadSignature {
sig,
ka,
error: err,
}
}
}
}
}
t!("{:02X}{:02X}: returning: {:?}", sigid[0], sigid[1], err);
results.push_verification_result(Err(err));
}
}
}
}
let r = self.helper.check(results);
t!("-> {:?}", r);
r
}
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());
assert!(self.cursor <= reserve.len());
let n = cmp::min(buf.len(), reserve.len() - self.cursor);
&mut buf[..n]
.copy_from_slice(&reserve[self.cursor..n + self.cursor]);
self.cursor += 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)),
},
}
}
}
#[cfg(test)]
mod test {
use super::*;
use std::convert::TryFrom;
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,
unknown,
bad,
error,
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::VerificationError::*;
for layer in structure.iter() {
match layer {
MessageLayer::SignatureGroup { ref results } =>
for result in results {
match result {
Ok(_) => self.good += 1,
Err(MissingKey { .. }) => self.unknown += 1,
Err(UnboundKey { .. }) => self.unknown += 1,
Err(MalformedSignature { .. }) => self.bad += 1,
Err(BadKey { .. }) => self.bad += 1,
Err(BadSignature { error, .. }) => {
eprintln!("error: {}", error);
self.bad += 1;
},
}
}
MessageLayer::Compression { .. } => (),
_ => unreachable!(),
}
}
if self.good > 0 && self.bad == 0 {
Ok(())
} else {
Err(anyhow::anyhow!("Verification failed"))
}
}
}
impl DecryptionHelper for VHelper {
fn decrypt<D>(&mut self, _: &[PKESK], _: &[SKESK],
_: Option<SymmetricAlgorithm>, _: 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 Err(VerificationError::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!(),
}
);
} else {
unreachable!()
}
},
_ => unreachable!(),
}
}
Ok(())
}
}
impl DecryptionHelper for VHelper {
fn decrypt<D>(&mut self, _: &[PKESK], _: &[SKESK],
_: Option<SymmetricAlgorithm>, _: 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());
}
#[test]
fn detached_verifier() {
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<_>>();
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, h, reference).unwrap();
v.verify_bytes(content).unwrap();
let h = v.into_helper();
assert_eq!(h.good, 1);
assert_eq!(h.bad, 0);
}
}
#[test]
fn verify_long_message() {
use std::io::Write;
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().parts_into_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);
}
}