use std::cmp;
use std::io;
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,
},
KeyHandle,
Packet,
Result,
packet,
packet::Signature,
cert::prelude::*,
crypto::SessionKey,
policy::Policy,
};
use crate::parse::{
Cookie,
HashingMode,
PacketParser,
PacketParserBuilder,
PacketParserResult,
Parse,
};
const TRACE : bool = false;
const TRACE_INDENT: isize = 5;
pub const DEFAULT_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>,
}
assert_send_and_sync!(GoodChecksum<'_>);
#[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,
},
}
assert_send_and_sync!(VerificationError<'_>);
impl<'a> std::fmt::Display for VerificationError<'a> {
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
use self::VerificationError::*;
match self {
MalformedSignature { error, .. } =>
write!(f, "Malformed signature: {}", error),
MissingKey { sig } =>
if let Some(issuer) = sig.get_issuers().get(0) {
write!(f, "Missing key: {}", issuer)
} else {
write!(f, "Missing key")
},
UnboundKey { cert, error, .. } =>
write!(f, "Subkey of {} not bound: {}", cert, error),
BadKey { ka, error, .. } =>
write!(f, "Subkey of {} is bad: {}", ka.cert(), error),
BadSignature { error, .. } =>
write!(f, "Bad signature: {}", error),
}
}
}
impl<'a> From<VerificationError<'a>> for Error {
fn from(e: VerificationError<'a>) -> Self {
use self::VerificationError::*;
match e {
MalformedSignature { .. } =>
Error::MalformedPacket(e.to_string()),
MissingKey { .. } =>
Error::InvalidKey(e.to_string()),
UnboundKey { .. } =>
Error::InvalidKey(e.to_string()),
BadKey { .. } =>
Error::InvalidKey(e.to_string()),
BadSignature { .. } =>
Error::BadSignature(e.to_string()),
}
}
}
enum VerificationErrorInternal<'a> {
MissingKey {
},
UnboundKey {
cert: &'a Cert,
error: anyhow::Error,
},
BadKey {
ka: ValidErasedKeyAmalgamation<'a, key::PublicParts>,
error: anyhow::Error,
},
BadSignature {
ka: ValidErasedKeyAmalgamation<'a, key::PublicParts>,
error: anyhow::Error,
},
}
impl<'a> VerificationErrorInternal<'a> {
fn attach_sig(self, sig: &'a Signature) -> VerificationError<'a> {
use self::VerificationErrorInternal::*;
match self {
MissingKey {} =>
VerificationError::MissingKey { sig },
UnboundKey { cert, error } =>
VerificationError::UnboundKey { sig, cert, error },
BadKey { ka, error } =>
VerificationError::BadKey { sig, ka, error },
BadSignature { ka, error } =>
VerificationError::BadSignature { sig, ka, error },
}
}
}
#[derive(Debug)]
pub struct MessageStructure<'a>(Vec<MessageLayer<'a>>);
assert_send_and_sync!(MessageStructure<'_>);
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,
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");
}
}
}
impl<'a> std::ops::Deref for MessageStructure<'a> {
type Target = [MessageLayer<'a>];
fn deref(&self) -> &Self::Target {
&self.0[..]
}
}
impl<'a> IntoIterator for MessageStructure<'a> {
type Item = MessageLayer<'a>;
type IntoIter = std::vec::IntoIter<MessageLayer<'a>>;
fn into_iter(self) -> Self::IntoIter {
self.0.into_iter()
}
}
#[derive(Debug)]
pub enum MessageLayer<'a> {
Compression {
algo: CompressionAlgorithm,
},
Encryption {
sym_algo: SymmetricAlgorithm,
aead_algo: Option<AEADAlgorithm>,
},
SignatureGroup {
results: Vec<VerificationResult<'a>>,
}
}
assert_send_and_sync!(MessageLayer<'_>);
#[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,
depth: isize,
expect_mdc: bool,
sym_algo: SymmetricAlgorithm,
aead_algo: Option<AEADAlgorithm>) {
self.insert_missing_signature_group();
self.layers.push(IMessageLayer::Encryption {
depth,
expect_mdc,
sym_algo,
aead_algo,
});
}
fn expect_mdc_at(&self, at: isize) -> bool {
for l in &self.layers {
match l {
IMessageLayer::Encryption {
depth,
expect_mdc,
..
} if *depth == at && *expect_mdc => return true,
_ => (),
}
}
false
}
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, csf_message: bool) {
for layer in self.layers.iter_mut().rev() {
match layer {
IMessageLayer::SignatureGroup {
ref mut sigs, ref mut count,
} if *count > 0 => {
sigs.push(sig);
if csf_message {
} else {
*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!("just checked or created")
}
}
}
#[derive(Debug)]
enum IMessageLayer {
Compression {
algo: CompressionAlgorithm,
},
Encryption {
depth: isize,
expect_mdc: bool,
sym_algo: SymmetricAlgorithm,
aead_algo: Option<AEADAlgorithm>,
},
SignatureGroup {
sigs: Vec<Signature>,
count: usize,
}
}
pub trait VerificationHelper {
fn inspect(&mut self, pp: &PacketParser) -> Result<()> {
let _ = pp;
Ok(())
}
fn get_certs(&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_certs(&mut self, ids: &[crate::KeyHandle]) -> Result<Vec<Cert>>
{
self.v.get_certs(ids)
}
fn check(&mut self, structure: MessageStructure) -> Result<()>
{
self.v.check(structure)
}
fn inspect(&mut self, pp: &PacketParser) -> Result<()> {
self.v.inspect(pp)
}
}
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) -> bool
{
unreachable!("This is not used for verifications")
}
}
pub struct Verifier<'a, H: VerificationHelper> {
decryptor: Decryptor<'a, NoDecryptionHelper<H>>,
}
assert_send_and_sync!(Verifier<'_, H> where H: VerificationHelper);
pub struct VerifierBuilder<'a> {
message: Box<dyn BufferedReader<Cookie> + 'a>,
buffer_size: usize,
mapping: bool,
}
assert_send_and_sync!(VerifierBuilder<'_>);
impl<'a> Parse<'a, VerifierBuilder<'a>>
for VerifierBuilder<'a>
{
fn from_reader<R>(reader: R) -> Result<VerifierBuilder<'a>>
where R: io::Read + 'a + Send + Sync,
{
VerifierBuilder::new(buffered_reader::Generic::with_cookie(
reader, None, Default::default()))
}
fn from_file<P>(path: P) -> Result<VerifierBuilder<'a>>
where P: AsRef<Path>,
{
VerifierBuilder::new(buffered_reader::File::with_cookie(
path, Default::default())?)
}
fn from_bytes<D>(data: &'a D) -> Result<VerifierBuilder<'a>>
where D: AsRef<[u8]> + ?Sized,
{
VerifierBuilder::new(buffered_reader::Memory::with_cookie(
data.as_ref(), Default::default()))
}
}
impl<'a> VerifierBuilder<'a> {
fn new<B>(signatures: B) -> Result<Self>
where B: buffered_reader::BufferedReader<Cookie> + 'a
{
Ok(VerifierBuilder {
message: Box::new(signatures),
buffer_size: DEFAULT_BUFFER_SIZE,
mapping: false,
})
}
pub fn buffer_size(mut self, size: usize) -> Self {
self.buffer_size = size;
self
}
pub fn mapping(mut self, enabled: bool) -> Self {
self.mapping = enabled;
self
}
pub fn with_policy<T, H>(self, policy: &'a dyn Policy, time: T, helper: H)
-> Result<Verifier<'a, H>>
where H: VerificationHelper,
T: Into<Option<time::SystemTime>>,
{
let t = time.into();
Ok(Verifier {
decryptor: Decryptor::from_buffered_reader(
policy,
self.message,
NoDecryptionHelper { v: helper, },
t, Mode::Verify, self.buffer_size, self.mapping, true)?,
})
}
}
impl<'a, H: VerificationHelper> Verifier<'a, H> {
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()
}
}
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>>,
}
assert_send_and_sync!(DetachedVerifier<'_, H> where H: VerificationHelper);
pub struct DetachedVerifierBuilder<'a> {
signatures: Box<dyn BufferedReader<Cookie> + 'a>,
mapping: bool,
}
assert_send_and_sync!(DetachedVerifierBuilder<'_>);
impl<'a> Parse<'a, DetachedVerifierBuilder<'a>>
for DetachedVerifierBuilder<'a>
{
fn from_reader<R>(reader: R) -> Result<DetachedVerifierBuilder<'a>>
where R: io::Read + 'a + Send + Sync,
{
DetachedVerifierBuilder::new(buffered_reader::Generic::with_cookie(
reader, None, Default::default()))
}
fn from_file<P>(path: P) -> Result<DetachedVerifierBuilder<'a>>
where P: AsRef<Path>,
{
DetachedVerifierBuilder::new(buffered_reader::File::with_cookie(
path, Default::default())?)
}
fn from_bytes<D>(data: &'a D) -> Result<DetachedVerifierBuilder<'a>>
where D: AsRef<[u8]> + ?Sized,
{
DetachedVerifierBuilder::new(buffered_reader::Memory::with_cookie(
data.as_ref(), Default::default()))
}
}
impl<'a> DetachedVerifierBuilder<'a> {
fn new<B>(signatures: B) -> Result<Self>
where B: buffered_reader::BufferedReader<Cookie> + 'a
{
Ok(DetachedVerifierBuilder {
signatures: Box::new(signatures),
mapping: false,
})
}
pub fn mapping(mut self, enabled: bool) -> Self {
self.mapping = enabled;
self
}
pub fn with_policy<T, H>(self, policy: &'a dyn Policy, time: T, helper: H)
-> Result<DetachedVerifier<'a, H>>
where H: VerificationHelper,
T: Into<Option<time::SystemTime>>,
{
let t = time.into();
Ok(DetachedVerifier {
decryptor: Decryptor::from_buffered_reader(
policy,
self.signatures,
NoDecryptionHelper { v: helper, },
t, Mode::VerifyDetached, 0, self.mapping, false)?,
})
}
}
impl<'a, H: VerificationHelper> DetachedVerifier<'a, H> {
pub fn verify_reader<R: io::Read + Send + Sync>(&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,
issuers: Vec<KeyHandle>,
certs: Vec<Cert>,
oppr: Option<PacketParserResult<'a>>,
identity: Option<Fingerprint>,
structure: IMessageStructure,
buffer_size: usize,
reserve: Option<Vec<u8>>,
cursor: usize,
mode: Mode,
processing_csf_message: Option<bool>,
time: time::SystemTime,
clock_skew_tolerance: time::Duration,
policy: &'a dyn Policy,
}
assert_send_and_sync!(Decryptor<'_, H>
where H: VerificationHelper + DecryptionHelper);
pub struct DecryptorBuilder<'a> {
message: Box<dyn BufferedReader<Cookie> + 'a>,
buffer_size: usize,
mapping: bool,
}
assert_send_and_sync!(DecryptorBuilder<'_>);
impl<'a> Parse<'a, DecryptorBuilder<'a>>
for DecryptorBuilder<'a>
{
fn from_reader<R>(reader: R) -> Result<DecryptorBuilder<'a>>
where R: io::Read + 'a + Send + Sync,
{
DecryptorBuilder::new(buffered_reader::Generic::with_cookie(
reader, None, Default::default()))
}
fn from_file<P>(path: P) -> Result<DecryptorBuilder<'a>>
where P: AsRef<Path>,
{
DecryptorBuilder::new(buffered_reader::File::with_cookie(
path, Default::default())?)
}
fn from_bytes<D>(data: &'a D) -> Result<DecryptorBuilder<'a>>
where D: AsRef<[u8]> + ?Sized,
{
DecryptorBuilder::new(buffered_reader::Memory::with_cookie(
data.as_ref(), Default::default()))
}
}
impl<'a> DecryptorBuilder<'a> {
fn new<B>(signatures: B) -> Result<Self>
where B: buffered_reader::BufferedReader<Cookie> + 'a
{
Ok(DecryptorBuilder {
message: Box::new(signatures),
buffer_size: DEFAULT_BUFFER_SIZE,
mapping: false,
})
}
pub fn buffer_size(mut self, size: usize) -> Self {
self.buffer_size = size;
self
}
pub fn mapping(mut self, enabled: bool) -> Self {
self.mapping = enabled;
self
}
pub fn with_policy<T, H>(self, policy: &'a dyn Policy, time: T, helper: H)
-> Result<Decryptor<'a, H>>
where H: VerificationHelper + DecryptionHelper,
T: Into<Option<time::SystemTime>>,
{
let t = time.into();
Decryptor::from_buffered_reader(
policy,
self.message,
helper,
t, Mode::Decrypt, self.buffer_size, self.mapping, false)
}
}
pub trait DecryptionHelper {
fn decrypt<D>(&mut self, pkesks: &[PKESK], skesks: &[SKESK],
sym_algo: Option<SymmetricAlgorithm>,
decrypt: D) -> Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool;
}
impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
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()
}
#[allow(clippy::redundant_pattern_matching)]
fn from_buffered_reader<T>(
policy: &'a dyn Policy,
bio: Box<dyn BufferedReader<Cookie> + 'a>,
helper: H, time: T,
mode: Mode,
buffer_size: usize,
mapping: bool,
csf_transformation: bool,
)
-> Result<Decryptor<'a, H>>
where T: Into<Option<time::SystemTime>>
{
tracer!(TRACE, "Decryptor::from_buffered_reader", TRACE_INDENT);
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(crate::now);
let mut ppr = PacketParserBuilder::from_buffered_reader(bio)?
.map(mapping)
.csf_transformation(csf_transformation)
.build()?;
let mut v = Decryptor {
helper,
issuers: Vec::new(),
certs: Vec::new(),
oppr: None,
identity: None,
structure: IMessageStructure::new(),
buffer_size,
reserve: None,
cursor: 0,
mode,
time,
clock_skew_tolerance: tolerance,
policy,
processing_csf_message: None, };
let mut pkesks: Vec<packet::PKESK> = Vec::new();
let mut skesks: Vec<packet::SKESK> = Vec::new();
while let PacketParserResult::Some(mut pp) = ppr {
if v.processing_csf_message.is_none() {
v.processing_csf_message = Some(pp.processing_csf_message());
}
v.policy.packet(&pp.packet)?;
v.helper.inspect(&pp)?;
if v.mode == Mode::VerifyDetached {
if pp.packet.tag() != packet::Tag::Signature
&& pp.packet.tag() != packet::Tag::Marker
{
return Err(Error::MalformedMessage(
format!("Expected signature, got {}", pp.packet.tag()))
.into());
}
} else if let Err(err) = pp.possible_message() {
if v.processing_csf_message.expect("set by now") {
} else {
t!("Malformed message: {}", err);
return Err(err.context("Malformed OpenPGP message"));
}
}
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 => {
let mut sym_algo = None;
{
let decryption_proxy = |algo, secret: &SessionKey| {
let algo = sym_algo_hint.unwrap_or(algo);
let result = pp.decrypt(algo, secret);
if let Ok(_) = result {
sym_algo = Some(algo);
true
} else {
false
}
};
v.identity =
v.helper.decrypt(&pkesks[..], &skesks[..],
sym_algo_hint,
decryption_proxy)?;
}
if ! pp.processed() {
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(
pp.recursion_depth(),
pp.packet.tag() == packet::Tag::SEIP
&& pp.packet.version() == Some(1),
sym_algo,
if let Packet::AED(ref p) = pp.packet {
Some(p.aead())
} else {
None
});
},
Packet::OnePassSig(ref ops) => {
v.structure.push_ops(ops);
v.push_issuer(ops.issuer().clone());
},
Packet::Literal(_) => {
v.structure.insert_missing_signature_group();
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) => {
sig.get_issuers().into_iter()
.for_each(|i| v.push_issuer(i));
v.structure.push_bare_signature(sig);
}
_ => (),
}
ppr = ppr_tmp;
}
if v.mode == Mode::VerifyDetached && !v.structure.layers.is_empty() {
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| {
HashingMode::for_signature(s.hash_algo(), s.typ())
}).collect();
let hashes =
crate::parse::hashed_reader::hash_buffered_reader(data, &algos)?;
for sig in sigs.iter_mut() {
let need_hash =
HashingMode::for_signature(sig.hash_algo(), sig.typ());
for mode in hashes.iter()
.filter(|m| m.map(|c| c.algo()) == need_hash)
{
use crate::crypto::hash::Hash;
let mut hash = mode.as_ref().clone();
sig.hash(&mut hash);
let mut digest = vec![0; hash.digest_size()];
let _ = hash.digest(&mut digest);
sig.set_computed_digest(Some(digest));
}
}
self.verify_signatures()
}
#[allow(clippy::single_match)]
fn push_sig(&mut self, p: Packet) -> Result<()> {
match p {
Packet::Signature(sig) => {
sig.get_issuers().into_iter().for_each(|i| self.push_issuer(i));
self.structure.push_signature(
sig, self.processing_csf_message.expect("set by now"));
},
_ => (),
}
Ok(())
}
fn push_issuer<I: Into<KeyHandle>>(&mut self, issuer: I) {
let issuer = issuer.into();
match issuer {
KeyHandle::KeyID(id) if id.is_wildcard() => {
},
KeyHandle::KeyID(_) => {
for known in self.issuers.iter() {
if known.aliases(&issuer) {
return;
}
}
self.issuers.push(issuer);
},
KeyHandle::Fingerprint(_) => {
for known in self.issuers.iter_mut() {
if known.aliases(&issuer) {
*known = issuer;
return;
}
}
self.issuers.push(issuer);
},
}
}
fn finish_maybe(&mut self) -> Result<()> {
tracer!(TRACE, "Decryptor::finish_maybe", TRACE_INDENT);
if let Some(PacketParserResult::Some(mut pp)) = self.oppr.take() {
let data_len = pp.data(self.buffer_size + 1)?.len();
if data_len - self.cursor <= self.buffer_size {
t!("Hit eof with {} bytes of the current buffer consumed.",
self.cursor);
pp.consume(self.cursor);
self.cursor = 0;
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)?;
}
let possible_message = pp.possible_message();
let last_recursion_depth = pp.recursion_depth();
let (p, ppr_tmp) = match pp.recurse() {
Ok(v) => v,
Err(e) => {
if self.structure.expect_mdc_at(
last_recursion_depth - 1)
{
return Err(Error::ManipulatedMessage.into());
} else {
return Err(e);
}
},
};
ppr = ppr_tmp;
let recursion_depth = ppr.as_ref()
.map(|pp| pp.recursion_depth()).unwrap_or(0);
if recursion_depth + 1 == last_recursion_depth
&& self.structure.expect_mdc_at(recursion_depth)
{
match &p {
Packet::MDC(mdc) if mdc.valid() =>
(), _ => return Err(Error::ManipulatedMessage.into()),
}
if possible_message.is_err() {
return Err(Error::ManipulatedMessage.into());
}
}
if let Err(_err) = possible_message {
if self.processing_csf_message.expect("set by now") {
} else {
return Err(Error::ManipulatedMessage.into());
}
}
self.push_sig(p)?;
}
self.verify_signatures()
} else {
t!("Didn't hit EOF.");
self.oppr = Some(PacketParserResult::Some(pp));
Ok(())
}
} else {
panic!("No ppr.");
}
}
#[allow(clippy::blocks_in_if_conditions)]
fn verify_signatures(&mut self) -> Result<()> {
tracer!(TRACE, "Decryptor::verify_signatures", TRACE_INDENT);
t!("called");
self.certs = self.helper.get_certs(&self.issuers)?;
t!("VerificationHelper::get_certs produced {} certs", self.certs.len());
let mut results = MessageStructure::new();
for layer in self.structure.layers.iter_mut() {
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_mut() {
let sigid = *sig.digest_prefix();
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 = VerificationErrorInternal::MissingKey {};
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 = VerificationErrorInternal::UnboundKey {
cert,
error: policy_err,
};
continue;
}
Ok(ka) => {
t!("{:02X}{:02X}: key {} accepted by policy",
sigid[0], sigid[1], fingerprint);
ka
}
};
err = if let Err(error) = ka.cert().alive() {
t!("{:02X}{:02X}: cert {} not alive: {}",
sigid[0], sigid[1], ka.cert().fingerprint(), error);
VerificationErrorInternal::BadKey {
ka,
error,
}
} else if let Err(error) = ka.alive() {
t!("{:02X}{:02X}: key {} not alive: {}",
sigid[0], sigid[1], ka.fingerprint(), error);
VerificationErrorInternal::BadKey {
ka,
error,
}
} else if let
RevocationStatus::Revoked(rev) = ka.cert().revocation_status()
{
t!("{:02X}{:02X}: cert {} revoked: {:?}",
sigid[0], sigid[1], ka.cert().fingerprint(), rev);
VerificationErrorInternal::BadKey {
ka,
error: Error::InvalidKey(
"certificate is revoked".into())
.into(),
}
} else if let
RevocationStatus::Revoked(rev) = ka.revocation_status()
{
t!("{:02X}{:02X}: key {} revoked: {:?}",
sigid[0], sigid[1], ka.fingerprint(), rev);
VerificationErrorInternal::BadKey {
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());
VerificationErrorInternal::BadKey {
ka,
error: Error::InvalidKey(
"key is not signing capable".into())
.into(),
}
} else if let Err(error) = sig.signature_alive(
self.time, self.clock_skew_tolerance)
{
t!("{:02X}{:02X}: Signature not alive: {}",
sigid[0], sigid[1], error);
VerificationErrorInternal::BadSignature {
ka,
error,
}
} else if self.identity.as_ref().map(|identity| {
let (have_one, contains_identity) =
sig.intended_recipients()
.fold((false, false),
|(_, contains_one), ir| {
(
true,
contains_one || identity == ir
)
});
have_one && ! contains_identity
}).unwrap_or(false) {
t!("{:02X}{:02X}: not an intended recipient",
sigid[0], sigid[1]);
VerificationErrorInternal::BadSignature {
ka,
error: Error::BadSignature(
"Not an intended recipient".into())
.into(),
}
} else {
match sig.verify(ka.key()) {
Ok(()) => {
if let Err(error)
= self.policy.signature(
sig, Default::default())
{
t!("{:02X}{:02X}: signature rejected by policy: {}",
sigid[0], sigid[1], error);
VerificationErrorInternal::BadSignature {
ka,
error,
}
} else {
t!("{:02X}{:02X}: good checksum using {}",
sigid[0], sigid[1], ka.fingerprint());
results.push_verification_result(
Ok(GoodChecksum {
sig,
ka,
}));
continue 'sigs;
}
}
Err(error) => {
t!("{:02X}{:02X} using {}: error: {}",
sigid[0], sigid[1], ka.fingerprint(), error);
VerificationErrorInternal::BadSignature {
ka,
error,
}
}
}
}
}
let err = err.attach_sig(sig);
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> {
tracer!(TRACE, "Decryptor::read_helper", TRACE_INDENT);
t!("read(buf of {} bytes)", buf.len());
if buf.is_empty() {
return Ok(0);
}
if let Some(ref mut reserve) = self.reserve {
t!("Message verified, draining reserve.");
assert!(self.oppr.is_none());
assert!(self.cursor <= reserve.len());
let n = cmp::min(buf.len(), reserve.len() - self.cursor);
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() {
if self.cursor >= self.buffer_size {
t!("Consuming first part of the buffer.");
pp.consume(self.buffer_size);
self.cursor -= self.buffer_size;
}
let data_len = pp.data(2 * self.buffer_size)?.len();
t!("Read {} bytes.", data_len);
if data_len - self.cursor <= self.buffer_size {
self.oppr = Some(PacketParserResult::Some(pp));
self.finish_maybe()?;
self.read_helper(buf)
} else {
let data = pp.data(2 * self.buffer_size - self.cursor)?;
assert_eq!(data.len(), data_len);
let n =
buf.len().min(data_len - self.buffer_size - self.cursor);
buf[..n].copy_from_slice(&data[self.cursor..self.cursor + n]);
self.cursor += n;
self.oppr = Some(PacketParserResult::Some(pp));
t!("Copied {} bytes from buffer, cursor is {}.", n, self.cursor);
Ok(n)
}
} 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 std::io::Read;
use super::*;
use std::convert::TryFrom;
use crate::parse::Parse;
use crate::policy::StandardPolicy as P;
use crate::serialize::Serialize;
use crate::{
crypto::Password,
};
#[derive(PartialEq)]
struct VHelper {
good: usize,
unknown: usize,
bad: usize,
error: usize,
certs: Vec<Cert>,
keys: Vec<Cert>,
passwords: Vec<Password>,
for_decryption: bool,
error_out: bool,
}
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)
.field("error_out", &self.error_out)
.finish()
}
}
impl Default for VHelper {
fn default() -> Self {
VHelper {
good: 0,
unknown: 0,
bad: 0,
error: 0,
certs: Vec::default(),
keys: Vec::default(),
passwords: Default::default(),
for_decryption: false,
error_out: true,
}
}
}
impl VHelper {
fn new(good: usize, unknown: usize, bad: usize, error: usize,
certs: Vec<Cert>)
-> Self {
VHelper {
good,
unknown,
bad,
error,
certs,
keys: Default::default(),
passwords: Default::default(),
for_decryption: false,
error_out: true,
}
}
fn for_decryption(good: usize, unknown: usize, bad: usize, error: usize,
certs: Vec<Cert>,
keys: Vec<Cert>,
passwords: Vec<Password>)
-> Self {
VHelper {
good,
unknown,
bad,
error,
certs,
keys,
passwords,
for_decryption: true,
error_out: true,
}
}
}
impl VerificationHelper for VHelper {
fn get_certs(&mut self, _ids: &[crate::KeyHandle]) -> Result<Vec<Cert>> {
Ok(self.certs.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 { .. } => (),
MessageLayer::Encryption { .. } => (),
}
}
if ! self.error_out || (self.good > 0 && self.bad == 0)
|| (self.for_decryption && self.certs.is_empty())
{
Ok(())
} else {
Err(anyhow::anyhow!("Verification failed: {:?}", self))
}
}
}
impl DecryptionHelper for VHelper {
fn decrypt<D>(&mut self, pkesks: &[PKESK], _skesks: &[SKESK],
sym_algo: Option<SymmetricAlgorithm>, mut decrypt: D)
-> Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
{
let p = P::new();
if ! self.for_decryption {
unreachable!("Shouldn't be called for verifications");
}
for pkesk in pkesks {
for key in &self.keys {
for subkey in key.with_policy(&p, None)?.keys().secret()
.key_handle(pkesk.recipient())
{
if let Some((algo, sk)) =
subkey.key().clone().into_keypair().ok()
.and_then(|mut k| pkesk.decrypt(&mut k, sym_algo))
{
if decrypt(algo, &sk) {
return Ok(None);
}
}
}
}
}
Err(Error::MissingSessionKey("Decryption failed".into()).into())
}
}
#[test]
fn verifier() -> Result<()> {
let p = P::new();
let certs = [
"neal.pgp",
"testy-new.pgp",
"emmelie-dorothea-dina-samantha-awina-ed25519.pgp"
].iter()
.map(|f| Cert::from_bytes(crate::tests::key(f)).unwrap())
.collect::<Vec<_>>();
let tests = &[
(crate::tests::message("signed-1.gpg").to_vec(),
crate::tests::manifesto().to_vec(),
true,
Some(crate::frozen_time()),
VHelper::new(1, 0, 0, 0, certs.clone())),
({
let pp = crate::PacketPile::from_bytes(
crate::tests::message("signed-1.gpg"))?;
let mut buf = Vec::new();
Packet::Marker(Default::default()).serialize(&mut buf)?;
pp.serialize(&mut buf)?;
buf
},
crate::tests::manifesto().to_vec(),
true,
Some(crate::frozen_time()),
VHelper::new(1, 0, 0, 0, certs.clone())),
(crate::tests::message("signed-1-sha256-testy.gpg").to_vec(),
crate::tests::manifesto().to_vec(),
true,
Some(crate::frozen_time()),
VHelper::new(0, 1, 0, 0, certs.clone())),
(crate::tests::message("signed-1-notarized-by-ed25519.pgp")
.to_vec(),
crate::tests::manifesto().to_vec(),
true,
Some(crate::frozen_time()),
VHelper::new(2, 0, 0, 0, certs.clone())),
(crate::tests::message("a-cypherpunks-manifesto.txt.cleartext.sig")
.to_vec(),
{
let mut manifesto = crate::tests::manifesto().to_vec();
let ws_at = manifesto.len() - 2;
let ws = manifesto.remove(ws_at);
assert_eq!(ws, b' ');
manifesto
},
false,
None,
VHelper::new(1, 0, 0, 0, certs.clone())),
(crate::tests::message("a-problematic-poem.txt.cleartext.sig")
.to_vec(),
crate::tests::message("a-problematic-poem.txt").to_vec(),
false,
None,
VHelper::new(1, 0, 0, 0, certs.clone())),
(crate::tests::key("neal.pgp").to_vec(),
crate::tests::manifesto().to_vec(),
true,
Some(crate::frozen_time()),
VHelper::new(0, 0, 0, 1, certs.clone())),
(crate::tests::message("crlf-straddles-chunks.txt.sig").to_vec(),
crate::tests::message("crlf-straddles-chunks.txt").to_vec(),
false,
None,
VHelper::new(1, 0, 0, 0, certs.clone())),
(crate::tests::message("text-signature-notation-has-lf.txt.sig").to_vec(),
crate::tests::message("text-signature-notation-has-lf.txt").to_vec(),
false,
None,
VHelper::new(1, 0, 0, 0, certs.clone())),
];
for (i, (signed, reference, test_decryptor, time, r))
in tests.iter().enumerate()
{
eprintln!("{}...", i);
let h = VHelper::new(0, 0, 0, 0, certs.clone());
let mut v =
match VerifierBuilder::from_bytes(&signed)?
.with_policy(&p, *time, h) {
Ok(v) => v,
Err(e) => if r.error > 0 || r.unknown > 0 {
continue;
} else {
panic!("{}: {}", i, 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[..]);
if ! test_decryptor {
continue;
}
let h = VHelper::new(0, 0, 0, 0, certs.clone());
let mut v = match DecryptorBuilder::from_bytes(&signed)?
.with_policy(&p, *time, h) {
Ok(v) => v,
Err(e) => if r.error > 0 || r.unknown > 0 {
continue;
} else {
panic!("{}: {}", i, 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[..]);
}
Ok(())
}
#[test]
fn decryptor() -> Result<()> {
let p = P::new();
for alg in &[
"rsa", "elg", "cv25519", "cv25519.unclamped",
"nistp256", "nistp384", "nistp521",
"brainpoolP256r1", "brainpoolP384r1", "brainpoolP512r1",
"secp256k1",
] {
eprintln!("Test vector {:?}...", alg);
let key = Cert::from_bytes(crate::tests::message(
&format!("encrypted/{}.sec.pgp", alg)))?;
if let Some(k) =
key.with_policy(&p, None)?.keys().subkeys().supported().next()
{
use crate::crypto::mpi::PublicKey;
match k.mpis() {
PublicKey::ECDH { curve, .. } if ! curve.is_supported() => {
eprintln!("Skipping {} because we don't support \
the curve {}", alg, curve);
continue;
},
_ => (),
}
} else {
eprintln!("Skipping {} because we don't support the algorithm",
alg);
continue;
}
let h = VHelper::for_decryption(0, 0, 0, 0, Vec::new(),
vec![key], Vec::new());
let mut d = DecryptorBuilder::from_bytes(
crate::tests::message(&format!("encrypted/{}.msg.pgp", alg)))?
.with_policy(&p, None, h)?;
assert!(d.message_processed());
if d.helper_ref().error > 0 {
continue;
}
let mut content = Vec::new();
d.read_to_end(&mut content).unwrap();
if content[0] == b'H' {
assert_eq!(&b"Hello World!\n"[..], &content[..]);
} else {
assert_eq!("дружба", &String::from_utf8_lossy(&content));
}
eprintln!("decrypted {:?} using {}",
String::from_utf8(content).unwrap(), alg);
}
Ok(())
}
#[test]
fn verifier_legacy() -> Result<()> {
let packets = crate::PacketPile::from_bytes(
crate::tests::message("signed-1.gpg")
)?
.into_children()
.collect::<Vec<_>>();
fn check(msg: &str, buf: &[u8], expect_good: usize) -> Result<()> {
eprintln!("{}...", msg);
let p = P::new();
let certs = [
"neal.pgp",
]
.iter()
.map(|f| Cert::from_bytes(crate::tests::key(f)).unwrap())
.collect::<Vec<_>>();
let mut h = VHelper::new(0, 0, 0, 0, certs.clone());
h.error_out = false;
let mut v = VerifierBuilder::from_bytes(buf)?
.with_policy(&p, crate::frozen_time(), h)?;
assert!(v.message_processed());
assert_eq!(v.helper_ref().good, expect_good);
let mut content = Vec::new();
v.read_to_end(&mut content).unwrap();
let reference = crate::tests::manifesto();
assert_eq!(reference.len(), content.len());
assert_eq!(reference, &content[..]);
Ok(())
}
let mut o = Vec::new();
packets[2].serialize(&mut o)?;
packets[1].serialize(&mut o)?;
check("bare", &o, 0 )?;
let mut o = Vec::new();
packets[2].serialize(&mut o)?;
packets[2].serialize(&mut o)?;
packets[1].serialize(&mut o)?;
check("double", &o, 0 )?;
let mut o = Vec::new();
packets[0].serialize(&mut o)?;
packets[2].serialize(&mut o)?;
packets[1].serialize(&mut o)?;
packets[2].serialize(&mut o)?;
check("weird", &o, 0 )?;
let mut o = Vec::new();
packets[2].serialize(&mut o)?;
packets[0].serialize(&mut o)?;
packets[1].serialize(&mut o)?;
packets[2].serialize(&mut o)?;
check("fubar", &o, 1 )?;
Ok(())
}
#[test]
fn verifier_levels() -> Result<()> {
let p = P::new();
struct VHelper(());
impl VerificationHelper for VHelper {
fn get_certs(&mut self, _ids: &[crate::KeyHandle])
-> Result<Vec<Cert>> {
Ok(Vec::new())
}
fn check(&mut self, structure: MessageStructure) -> Result<()> {
assert_eq!(structure.len(), 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_fingerprints().next().unwrap()
.to_hex(),
match i {
0 => "8E8C33FA4626337976D97978069C0C348DD82C19",
1 => "C03FA6411B03AE12576461187223B56678E02528",
_ => 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) -> bool
{
unreachable!();
}
}
let v = VerifierBuilder::from_bytes(
crate::tests::message("signed-1-notarized-by-ed25519.pgp"))?
.with_policy(&p, crate::frozen_time(), VHelper(()))?;
assert!(v.message_processed());
let v = DecryptorBuilder::from_bytes(
crate::tests::message("signed-1-notarized-by-ed25519.pgp"))?
.with_policy(&p, crate::frozen_time(), VHelper(()))?;
assert!(v.message_processed());
Ok(())
}
#[test]
fn detached_verifier() -> Result<()> {
lazy_static::lazy_static! {
static ref ZEROS: Vec<u8> = vec![0; 100 * 1024 * 1024];
}
let p = P::new();
struct Test<'a> {
sig: Vec<u8>,
content: &'a [u8],
reference: time::SystemTime,
}
let tests = [
Test {
sig: crate::tests::message(
"a-cypherpunks-manifesto.txt.ed25519.sig").to_vec(),
content: crate::tests::manifesto(),
reference: crate::frozen_time(),
},
Test {
sig: {
let sig = crate::PacketPile::from_bytes(
crate::tests::message(
"a-cypherpunks-manifesto.txt.ed25519.sig"))?;
let mut buf = Vec::new();
Packet::Marker(Default::default()).serialize(&mut buf)?;
sig.serialize(&mut buf)?;
buf
},
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")
.to_vec(),
content: &ZEROS[..],
reference:
crate::types::Timestamp::try_from(1572602018).unwrap().into(),
},
];
let certs = [
"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, certs.clone());
let mut v = DetachedVerifierBuilder::from_bytes(sig).unwrap()
.with_policy(&p, reference, h).unwrap();
v.verify_bytes(content).unwrap();
let h = v.into_helper();
assert_eq!(h.good, 1);
assert_eq!(h.bad, 0);
}
Ok(())
}
#[test]
fn test_streaming_verifier_bug_issue_682() -> Result<()> {
let p = P::new();
let sig = crate::tests::message("signature-with-broken-mpis.sig");
let h = VHelper::new(0, 0, 0, 0, vec![]);
let result = DetachedVerifierBuilder::from_bytes(sig)?
.with_policy(&p, None, h);
if let Err(e) = result {
let error = e.downcast::<crate::Error>()?;
assert!(matches!(error, Error::MalformedMessage(..)));
} else {
unreachable!("Should error out as the signature is broken.");
}
Ok(())
}
#[test]
fn verify_long_message() -> Result<()> {
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().next().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; 3 * 1024 * 1024]).unwrap();
ls.finalize().unwrap();
}
let h = VHelper::new(0, 0, 0, 0, vec![cert.clone()]);
let mut v = VerifierBuilder::from_bytes(&buf)?
.buffer_size(2 * 2usize.pow(20))
.with_policy(p, None, h)?;
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!(3 * 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 = VerifierBuilder::from_bytes(&buf)?
.buffer_size(2 * 2usize.pow(20))
.with_policy(p, None, h)?;
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.is_empty());
assert!(message.len() <= 1 * 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 = DecryptorBuilder::from_bytes(&buf)?
.buffer_size(2 * 2usize.pow(20))
.with_policy(p, None, h)?;
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!(3 * 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 = DecryptorBuilder::from_bytes(&buf)?
.buffer_size(2 * 2usize.pow(20))
.with_policy(p, None, h)?;
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.is_empty());
assert!(message.len() <= 1 * 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);
Ok(())
}
#[test]
fn issue_693() -> Result<()> {
struct H();
impl VerificationHelper for H {
fn get_certs(&mut self, _ids: &[crate::KeyHandle])
-> Result<Vec<Cert>> {
Ok(Vec::new())
}
fn check(&mut self, _: MessageStructure)
-> Result<()> {
Ok(())
}
}
impl DecryptionHelper for H {
fn decrypt<D>(&mut self, _: &[PKESK], s: &[SKESK],
_: Option<SymmetricAlgorithm>, mut decrypt: D)
-> Result<Option<Fingerprint>>
where D: FnMut(SymmetricAlgorithm, &SessionKey) -> bool
{
let (algo, sk) = s[0].decrypt(&"123".into()).unwrap();
let r = decrypt(algo, &sk);
assert!(r);
Ok(None)
}
}
fn check(m: &str) -> Result<()> {
let doit = || -> Result<()> {
let p = &P::new();
let mut decryptor = DecryptorBuilder::from_bytes(m.as_bytes())?
.with_policy(p, None, H())?;
let mut b = Vec::new();
decryptor.read_to_end(&mut b)?;
Ok(())
};
let e = doit().unwrap_err();
match e.downcast::<io::Error>() {
Ok(e) =>
assert_eq!(e.into_inner().unwrap().downcast().unwrap(),
Box::new(Error::ManipulatedMessage)),
Err(e) =>
assert_eq!(e.downcast::<Error>().unwrap(),
Error::ManipulatedMessage),
};
Ok(())
}
check("-----BEGIN PGP MESSAGE-----
wx4EBwMI7dKRUiOYGCUAWmzhiYGS8Pn/16QkyTous6vSOgFMcilte26C7kej
rKhvjj6uYNT+mt+L2Yg/FHFvpgVF3KfP0fb+9jZwgt4qpDkTMY7AWPTK6wXX
Jo8=
=LS8u
-----END PGP MESSAGE-----
")?;
check("-----BEGIN PGP MESSAGE-----
wx4EBwMI7sPTdlgQwd8AogIcbF/hLVrYbvVbgj4EC6/SOgGNaCyffrR4Fuwl
Ft2w56/hB/gTaGEhCgDGXg8NiFGIURqF3eIwxxdKWghUutYmsGwqOZmdJ49a
9gE=
=DzKF
-----END PGP MESSAGE-----
")?;
check("-----BEGIN PGP MESSAGE-----
wx4EBwMIhpEGBh3v0oMAYgGcj+4CG1mcWQwmyGIDRdvSOgFSHlL2GZ1ZKeXS
29kScqGg2U8N6ZF9vmj/9Sn7CFtO5PGXn2owQVsopeUSTofV3BNUBpxaBDCO
EK8=
=TgeJ
-----END PGP MESSAGE-----
")?;
Ok(())
}
#[test]
fn csf_multiple_signers() -> Result<()> {
struct H(bool);
impl VerificationHelper for H {
fn get_certs(&mut self, _ids: &[crate::KeyHandle])
-> Result<Vec<Cert>> {
crate::cert::CertParser::from_bytes(
crate::tests::key("InRelease.signers.pgp"))?
.collect()
}
fn check(&mut self, m: MessageStructure)
-> Result<()> {
for (i, layer) in m.into_iter().enumerate() {
assert_eq!(i, 0);
if let MessageLayer::SignatureGroup { results } = layer {
assert_eq!(results.len(), 3);
for result in results {
assert!(result.is_ok());
}
self.0 = true;
} else {
panic!();
}
}
Ok(())
}
}
let p = &P::new();
let mut verifier = VerifierBuilder::from_bytes(
crate::tests::message("InRelease"))?
.with_policy(p, None, H(false))?;
let mut b = Vec::new();
verifier.read_to_end(&mut b)?;
let h = verifier.into_helper();
assert!(h.0);
Ok(())
}
}