diff options
Diffstat (limited to 'openpgp')
-rw-r--r-- | openpgp/examples/decrypt-with.rs | 19 | ||||
-rw-r--r-- | openpgp/examples/generate-sign-verify.rs | 12 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 265 | ||||
-rw-r--r-- | openpgp/src/policy.rs | 12 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 10 |
5 files changed, 152 insertions, 166 deletions
diff --git a/openpgp/examples/decrypt-with.rs b/openpgp/examples/decrypt-with.rs index c4b9f56a..ca84a918 100644 --- a/openpgp/examples/decrypt-with.rs +++ b/openpgp/examples/decrypt-with.rs @@ -16,7 +16,7 @@ use crate::openpgp::parse::{ DecryptionHelper, Decryptor, VerificationHelper, - VerificationResult, + GoodChecksum, MessageStructure, MessageLayer, }, @@ -108,7 +108,6 @@ impl VerificationHelper for Helper { } fn check(&mut self, structure: MessageStructure) -> failure::Fallible<()> { - use self::VerificationResult::*; for layer in structure.iter() { match layer { MessageLayer::Compression { algo } => @@ -123,19 +122,11 @@ impl VerificationHelper for Helper { MessageLayer::SignatureGroup { ref results } => for result in results { match result { - GoodChecksum { cert, .. } => { - eprintln!("Good signature from {}", cert); - }, - NotAlive { sig, .. } => { - eprintln!("Good, but not alive signature from {:?}", - sig.get_issuers()); - }, - MissingKey { .. } => { - eprintln!("No key to check signature"); - }, - Error { error, .. } => { - eprintln!("Error: {}", error); + Ok(GoodChecksum { ka, .. }) => { + eprintln!("Good signature from {}", ka.cert()); }, + Err(e) => + eprintln!("Error: {:?}", e), } } } diff --git a/openpgp/examples/generate-sign-verify.rs b/openpgp/examples/generate-sign-verify.rs index d371a812..e5f21505 100644 --- a/openpgp/examples/generate-sign-verify.rs +++ b/openpgp/examples/generate-sign-verify.rs @@ -113,16 +113,10 @@ impl<'a> VerificationHelper for Helper<'a> { // whether the signature checks out mathematically, we apply // our policy. match results.into_iter().next() { - Some(VerificationResult::GoodChecksum { .. }) => + Some(Ok(_)) => good = true, - Some(VerificationResult::NotAlive { .. }) => - return Err(failure::err_msg( - "Signature good, but not alive")), - Some(VerificationResult::MissingKey { .. }) => - return Err(failure::err_msg( - "Missing key to verify signature")), - Some(VerificationResult::Error { error, .. }) => - return Err(error), + Some(Err(e)) => + return Err(openpgp::Error::from(e).into()), None => return Err(failure::err_msg("No signature")), } diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index 891a88ef..c458ed7b 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -64,90 +64,113 @@ const TRACE : bool = false; /// How much data to buffer before giving it to the caller. const BUFFER_SIZE: usize = 25 * 1024 * 1024; -/// Contains the result of a signature verification. +/// The result of a signature verification. +pub type VerificationResult<'a> = + std::result::Result<GoodChecksum<'a>, VerificationError<'a>>; + +/// The signature is good. +/// +/// A signature is considered good if: +/// +/// - The signature has a Signature Creation Time subpacket. +/// +/// - The signature is alive at the specified time (the time +/// parameter passed to, e.g., `Verifier::from_reader`). +/// +/// - The certificate is alive and not revoked as of the signature's +/// creation time. +/// +/// - The signing key is alive, not revoked, and signing capable as +/// of the signature's creation time. +/// +/// - The signature was generated by the signing key. +/// +/// Note: This doesn't mean that the key that generated the +/// signature is in anyway trustworthy in the sense that it +/// belongs to the person or entity that the user thinks it +/// belongs to. This property can only be evaluated within a +/// trust model, such as the [web of trust] (WoT). This policy is +/// normally implemented in the `VerificationHelper::check` +/// method. +/// +/// [web of trust]: https://en.wikipedia.org/wiki/Web_of_trust #[derive(Debug)] -pub enum VerificationResult<'a> { - /// The signature is good. - /// - /// A signature is considered good if: - /// - /// - The signature has a Signature Creation Time subpacket. - /// - /// - The signature is alive at the specified time (the time - /// parameter passed to, e.g., `Verifier::from_reader`). - /// - /// - The certificate is alive and not revoked as of the - /// signature's creation time. - /// - /// - The signing key is alive, not revoked, and signing - /// capable as of the signature's creation time. - /// - /// - The signature was generated by the signing key. - /// - /// Note: This doesn't mean that the key that generated the - /// signature is in anyway trustworthy in the sense that it - /// belongs to the person or entity that the user thinks it - /// belongs to. This property can only be evaluated within a - /// trust model, such as the [web of trust] (WoT). This - /// policy is normally implemented in the - /// `VerificationHelper::check` method. - /// - /// [web of trust]: https://en.wikipedia.org/wiki/Web_of_trust - GoodChecksum { +pub struct GoodChecksum<'a> { + /// The signature. + pub sig: Signature, + + /// The signing key that made the signature. + pub ka: ValidKeyAmalgamation<'a, key::PublicParts>, +} + +/// Possible errors during signature verifications. +#[derive(Debug)] +pub enum VerificationError<'a> { + /// Malformed signature (no signature creation subpacket, etc.) + MalformedSignature { /// The signature. sig: Signature, - /// The signature's issuer. - cert: &'a Cert, - - /// The signing key that made the signature. - ka: ValidKeyAmalgamation<'a, key::PublicParts>, + /// The reason why the signature is malformed. + error: failure::Error, }, - - /// The signature is good, but it is not alive at the specified - /// time. - /// - /// See `SubpacketAreas::signature_alive` for a definition of - /// liveness. - NotAlive { + /// Missing Key + MissingKey { /// The signature. sig: Signature, }, - - /// Unable to verify the signature because the key is missing. - MissingKey { + /// Unbound key. + /// + /// There is no valid binding signature at the time the signature + /// was created under the given policy. + UnboundKey { /// The signature. sig: Signature, + + /// The certificate that made the signature. + cert: &'a Cert, + + /// The reason why the key is bad. + error: failure::Error, }, + /// Bad key (have a key, but it is not alive, etc.) + BadKey { + /// The signature. + sig: Signature, - /// An error occurred while verifying the signature. - /// - /// This could occur if the signature is invalid (e.g., no - /// Signature Creation Time packet), the key is invalid (e.g., the - /// key is not alive, the key is revoked, the key is not signing - /// capable), etc. - Error { + /// The signing key that made the signature. + ka: ValidKeyAmalgamation<'a, key::PublicParts>, + + /// The reason why the key is bad. + error: failure::Error, + }, + /// Bad signature (have a valid key, but the signature didn't check out) + BadSignature { /// The signature. sig: Signature, - /// The reason. + /// The signing key that made the signature. + ka: ValidKeyAmalgamation<'a, key::PublicParts>, + + /// The reason why the signature is bad. error: failure::Error, }, } -impl<'a> VerificationResult<'a> { - /// Gets the signature level. - /// - /// A level of 0 indicates that the signature is directly over the - /// data, a level of 1 means that the signature is a notarization - /// over all level 0 signatures and the data, and so on. - pub fn level(&self) -> usize { - use self::VerificationResult::*; - match self { - GoodChecksum { sig, .. } => sig.level(), - NotAlive { sig, .. } => sig.level(), - MissingKey { sig, .. } => sig.level(), - Error { sig, .. } => sig.level(), +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()), } } } @@ -1449,32 +1472,19 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { } else { // Invalid signature. results.push_verification_result( - VerificationResult::Error { + Err(VerificationError::MalformedSignature { sig, error: Error::MalformedPacket( "missing a Signature Creation Time \ subpacket" - .into()).into() - }); + .into()).into(), + })); t!("{:02X}{:02X}: Missing a signature creation time subpacket", sigid[0], sigid[1]); 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(), - }); - t!("{:02X}{:02X}: Signature not alive: {}", - sigid[0], sigid[1], err); - continue; - } - - let mut err = VerificationResult::MissingKey { + let mut err = VerificationError::MissingKey { sig: sig.clone(), }; @@ -1484,13 +1494,15 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { 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 = VerificationResult::Error { + err = VerificationError::UnboundKey { sig: sig.clone(), + cert, error: policy_err, }; continue; @@ -1505,15 +1517,17 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { err = if let Err(err) = ka.cert_alive() { t!("{:02X}{:02X}: cert {} not alive: {}", sigid[0], sigid[1], ka.cert().fingerprint(), err); - VerificationResult::Error { + VerificationError::BadKey { sig: sig.clone(), + ka, error: err, } } else if let Err(err) = ka.alive() { t!("{:02X}{:02X}: key {} not alive: {}", sigid[0], sigid[1], ka.fingerprint(), err); - VerificationResult::Error { + VerificationError::BadKey { sig: sig.clone(), + ka, error: err, } } else if let @@ -1521,8 +1535,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { { t!("{:02X}{:02X}: cert {} revoked: {:?}", sigid[0], sigid[1], ka.cert().fingerprint(), rev); - VerificationResult::Error { + VerificationError::BadKey { sig: sig.clone(), + ka, error: Error::InvalidKey( "certificate is revoked".into()) .into(), @@ -1532,8 +1547,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { { t!("{:02X}{:02X}: key {} revoked: {:?}", sigid[0], sigid[1], ka.fingerprint(), rev); - VerificationResult::Error { + VerificationError::BadKey { sig: sig.clone(), + ka, error: Error::InvalidKey( "signing key is revoked".into()) .into(), @@ -1541,12 +1557,23 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { } else if ! ka.for_signing() { t!("{:02X}{:02X}: key {} not signing capable", sigid[0], sigid[1], ka.fingerprint()); - VerificationResult::Error { + VerificationError::BadKey { sig: sig.clone(), + 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: sig.clone(), + ka, + error: err, + } } else if self.identity.as_ref().map(|identity| { let ir = sig.intended_recipients(); ! ir.is_empty() && ! ir.contains(identity) @@ -1556,8 +1583,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { // Treat the signature as bad. t!("{:02X}{:02X}: not an intended recipient", sigid[0], sigid[1]); - VerificationResult::Error { + VerificationError::BadSignature { sig: sig.clone(), + ka, error: Error::BadSignature( "Not an intended recipient".into()) .into(), @@ -1568,19 +1596,19 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { if let Err(err) = self.policy.signature(&sig) { t!("{:02X}{:02X}: signature rejected by policy: {}", sigid[0], sigid[1], err); - VerificationResult::Error { + VerificationError::BadSignature { sig: sig.clone(), + ka, error: err, } } else { t!("{:02X}{:02X}: good checksum using {}", sigid[0], sigid[1], ka.fingerprint()); results.push_verification_result( - VerificationResult::GoodChecksum { + Ok(GoodChecksum { sig: sig, - cert: ka.cert(), ka, - }); + })); // Continue to the next sig. continue 'sigs; } @@ -1588,8 +1616,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { Err(err) => { t!("{:02X}{:02X} using {}: error: {}", sigid[0], sigid[1], ka.fingerprint(), err); - VerificationResult::Error { + VerificationError::BadSignature { sig: sig.clone(), + ka, error: err, } } @@ -1597,34 +1626,8 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { } } - // 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(ka) = self.certs.iter() - .flat_map(|cert| { - cert.keys().key_handles(issuers.iter()) - }) - .next() - { - err = VerificationResult::Error { - sig: sig.clone(), - error: Error::InvalidKey( - format!( - "Signing key ({}) not valid \ - when signature was created", - ka.fingerprint())) - .into(), - } - } - } - t!("{:02X}{:02X}: returning: {:?}", sigid[0], sigid[1], err); - results.push_verification_result(err); + results.push_verification_result(Err(err)); } } } @@ -1746,16 +1749,18 @@ mod test { } fn check(&mut self, structure: MessageStructure) -> Result<()> { - use self::VerificationResult::*; + use self::VerificationError::*; for layer in structure.iter() { match layer { MessageLayer::SignatureGroup { ref results } => for result in results { match result { - GoodChecksum { .. } => self.good += 1, - MissingKey { .. } => self.unknown += 1, - NotAlive { .. } => self.bad += 1, - Error { error, .. } => { + 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; }, @@ -1883,9 +1888,9 @@ mod test { match layer { MessageLayer::SignatureGroup { results } => { assert_eq!(results.len(), 1); - if let VerificationResult::MissingKey { sig, .. } = - &results[0] - { + if let Err(VerificationError::MissingKey { + sig, .. + }) = &results[0] { assert_eq!( &sig.issuer_fingerprint().unwrap() .to_string(), @@ -1895,6 +1900,8 @@ mod test { _ => unreachable!(), } ); + } else { + unreachable!() } }, _ => unreachable!(), diff --git a/openpgp/src/policy.rs b/openpgp/src/policy.rs index 2e31fb24..890513d5 100644 --- a/openpgp/src/policy.rs +++ b/openpgp/src/policy.rs @@ -566,16 +566,14 @@ mod test { fn check(&mut self, structure: MessageStructure) -> Result<()> { - use crate::parse::stream::VerificationResult::*; for layer in structure.iter() { match layer { MessageLayer::SignatureGroup { ref results } => for result in results { eprintln!("result: {:?}", result); match result { - GoodChecksum { .. } => self.good += 1, - Error { .. } => self.errors += 1, - _ => (), + Ok(_) => self.good += 1, + Err(_) => self.errors += 1, } } MessageLayer::Compression { .. } => (), @@ -1033,15 +1031,13 @@ mod test { fn check(&mut self, structure: MessageStructure) -> Result<()> { - use crate::parse::stream::VerificationResult::*; for layer in structure.iter() { match layer { MessageLayer::SignatureGroup { ref results } => for result in results { match result { - GoodChecksum { .. } => self.good += 1, - Error { .. } => self.errors += 1, - _ => (), + Ok(_) => self.good += 1, + Err(_) => self.errors += 1, } } MessageLayer::Compression { .. } => (), diff --git a/openpgp/src/serialize/stream.rs b/openpgp/src/serialize/stream.rs index 7e30dc88..6769a17c 100644 --- a/openpgp/src/serialize/stream.rs +++ b/openpgp/src/serialize/stream.rs @@ -263,9 +263,8 @@ impl<'a> Signer<'a> { /// if let MessageLayer::SignatureGroup { ref results } = /// structure.iter().nth(0).unwrap() /// { - /// if let VerificationResult::GoodChecksum { .. } = - /// results.get(0).unwrap() - /// { Ok(()) /* good */ } else { panic!() } + /// results.get(0).unwrap().as_ref().unwrap(); + /// Ok(()) /// } else { panic!() } /// } /// } @@ -375,9 +374,8 @@ impl<'a> Signer<'a> { /// if let MessageLayer::SignatureGroup { ref results } = /// structure.iter().nth(0).unwrap() /// { - /// if let VerificationResult::GoodChecksum { .. } = - /// results.get(0).unwrap() - /// { Ok(()) /* good */ } else { panic!() } + /// results.get(0).unwrap().as_ref().unwrap(); + /// Ok(()) /// } else { panic!() } /// } /// } |