summaryrefslogtreecommitdiffstats
path: root/openpgp
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2020-01-16 17:22:06 +0100
committerJustus Winter <justus@sequoia-pgp.org>2020-01-16 17:22:06 +0100
commitf1dabd075d78cf45c4e0b2e61334267c22d7145b (patch)
tree04336625151c05936d26e01ef6ba72658a5e1710 /openpgp
parentc9fa96fbef7e759629a43bc5610a34a97e42de87 (diff)
openpgp: Rework Decryptor::verify_signatures like Verifier.
Diffstat (limited to 'openpgp')
-rw-r--r--openpgp/src/parse/stream.rs188
1 files changed, 133 insertions, 55 deletions
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs
index 54c33424..93ca9b7e 100644
--- a/openpgp/src/parse/stream.rs
+++ b/openpgp/src/parse/stream.rs
@@ -1652,71 +1652,149 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
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.iter().find(|(h, _)| {
- h.aliases(&issuer)
- }) {
- let cert = &self.certs[*i];
- let ka = cert.keys().policy(self.time).nth(*j).unwrap();
- results.push_verification_result(
- if sig.verify(ka.key()).unwrap_or(false) &&
- sig.signature_alive(
- self.time, self.clock_skew_tolerance)
- .is_ok()
- {
- // Check intended recipients.
- if let Some(identity) =
- self.identity.as_ref()
- {
- let ir = sig.intended_recipients();
- if !ir.is_empty()
- && !ir.contains(identity)
- {
- // The signature
- // contains intended
- // recipients, but we
- // are not one. Treat
- // the signature as
- // bad.
- VerificationResult::BadChecksum
- {
- sig: sig.clone(),
- cert, ka,
- }
- } else {
- VerificationResult::GoodChecksum
- {
- sig: sig.clone(),
- cert, ka,
- }
- }
- } else {
- // No identity information.
+ let sig_time = if let Some(t) = sig.signature_creation_time() {
+ t
+ } else {
+ // Invalid signature.
+ results.push_verification_result(
+ VerificationResult::Error {
+ sig,
+ error: Error::MalformedPacket(
+ "missing a Signature Creation Time \
+ subpacket"
+ .into()).into()
+ });
+ continue;
+ };
+
+ if let Err(_err) = sig.signature_alive(
+ self.time, self.clock_skew_tolerance)
+ {
+ // Invalid signature.
+ results.push_verification_result(
+ VerificationResult::NotAlive {
+ sig: sig.clone(),
+ });
+ continue;
+ }
+
+ let mut err = VerificationResult::MissingKey {
+ sig: sig.clone(),
+ };
+
+ let issuers = sig.get_issuers();
+ for ka in self.certs.iter()
+ .flat_map(|cert| {
+ cert.keys().policy(sig_time)
+ .key_handles(issuers.iter())
+ })
+ {
+ err = if let Err(err) = ka.cert_alive() {
+ VerificationResult::Error {
+ sig: sig.clone(),
+ error: err,
+ }
+ } else if let Err(err) = ka.alive() {
+ VerificationResult::Error {
+ sig: sig.clone(),
+ error: err,
+ }
+ } else if destructures_to!(
+ RevocationStatus::Revoked(_) = ka.cert_revoked())
+ {
+ VerificationResult::Error {
+ sig: sig.clone(),
+ error: Error::InvalidKey(
+ "certificate is revoked".into())
+ .into(),
+ }
+ } else if destructures_to!(
+ RevocationStatus::Revoked(_) = ka.revoked())
+ {
+ VerificationResult::Error {
+ sig: sig.clone(),
+ error: Error::InvalidKey(
+ "signing key is revoked".into())
+ .into(),
+ }
+ } else if ! ka.for_signing() {
+ VerificationResult::Error {
+ sig: sig.clone(),
+ error: Error::InvalidKey(
+ "key is not signing capable".into())
+ .into(),
+ }
+ } else if self.identity.as_ref().map(|identity| {
+ let ir = sig.intended_recipients();
+ ! ir.is_empty() && ! ir.contains(identity)
+ }).unwrap_or(false) {
+ // The signature contains intended
+ // recipients, but we are not one.
+ // Treat the signature as bad.
+ VerificationResult::Error {
+ sig: sig.clone(),
+ error: Error::BadSignature(
+ "Not an intended recipient".into())
+ .into(),
+ }
+ } else {
+ match sig.verify(ka.key()) {
+ Ok(true) => {
+ results.push_verification_result(
VerificationResult::GoodChecksum {
- sig: sig.clone(),
- cert, ka,
- }
- }
- } else {
+ sig: sig,
+ cert: ka.cert(),
+ ka,
+ });
+ // Continue to the next sig.
+ continue 'sigs;
+ }
+ Ok(false) => {
VerificationResult::BadChecksum {
sig: sig.clone(),
- cert, ka,
+ cert: ka.cert(),
+ ka,
}
}
- );
-
- // We found a key, continue to next sig.
- continue 'sigs;
+ Err(err) => {
+ VerificationResult::Error {
+ sig: sig.clone(),
+ error: err,
+ }
+ }
+ }
}
}
- results.push_verification_result(
- VerificationResult::MissingKey {
- sig,
+ // Hmm, we didn't consider any keys. Iterate
+ // over the keys again, but this time, don't
+ // use a policy. If we find something now,
+ // the policy must have rejected it. Turn
+ // that information into a more useful (and
+ // less misleading) error message than
+ // `VerificationResult::MissingKey`.
+ if let VerificationResult::MissingKey { .. } = err {
+ if let Some(key) = self.certs.iter()
+ .flat_map(|cert| {
+ cert.keys().key_handles(issuers.iter())
+ })
+ .next()
+ {
+ err = VerificationResult::Error {
+ sig: sig.clone(),
+ error: Error::InvalidKey(
+ format!(
+ "Signing key ({}) not valid \
+ when signature was created",
+ key.fingerprint()))
+ .into(),
+ }
}
- );
+ }
+
+ results.push_verification_result(err);
}
- },
+ }
}
}