summaryrefslogtreecommitdiffstats
path: root/openpgp
diff options
context:
space:
mode:
authorJustus Winter <justus@sequoia-pgp.org>2019-04-02 16:03:09 +0200
committerJustus Winter <justus@sequoia-pgp.org>2019-04-02 17:04:04 +0200
commit4e6d4a045af89567b8ff84c830775649d09900b0 (patch)
tree2d7977eac52f374a60d303791931a3da2d860308 /openpgp
parentd770aae9dbd037206505b5f77d63991fad28ceb0 (diff)
openpgp: Delay the checking of signatures in the streaming verifier.
Diffstat (limited to 'openpgp')
-rw-r--r--openpgp/src/parse/stream.rs180
1 files changed, 101 insertions, 79 deletions
diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs
index 7f66efbf..fc35a796 100644
--- a/openpgp/src/parse/stream.rs
+++ b/openpgp/src/parse/stream.rs
@@ -119,7 +119,7 @@ pub struct Verifier<'a, H: VerificationHelper> {
/// Maps KeyID to tpks[i].keys_all().nth(j).
keys: HashMap<KeyID, (usize, usize)>,
oppr: Option<PacketParserResult<'a>>,
- sigs: Vec<Vec<VerificationResult>>,
+ sigs: Vec<Vec<Signature>>,
// The reserve data.
reserve: Option<Vec<u8>>,
@@ -298,9 +298,9 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> {
v.oppr = Some(PacketParserResult::Some(pp));
v.finish_maybe()?;
- // Verify any queued signatures.
+ // Stash signatures.
for sig in sigs.into_iter() {
- v.verify(Packet::Signature(sig))?;
+ v.push_sig(Packet::Signature(sig))?;
}
return Ok(v);
@@ -328,9 +328,9 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> {
}
- /// Verifies the given Signature (if it is one), and stores the
- /// result.
- fn verify(&mut self, p: Packet) -> Result<()> {
+ /// Stashes the given Signature (if it is one) for later
+ /// verification.
+ fn push_sig(&mut self, p: Packet) -> Result<()> {
match p {
Packet::Signature(sig) => {
if self.sigs.is_empty() {
@@ -346,29 +346,8 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> {
}
}
- if let Some(issuer) = sig.get_issuer() {
- if let Some((i, j)) = self.keys.get(&issuer) {
- let (_, _, key)
- = self.tpks[*i].keys_all().nth(*j).unwrap();
- if sig.verify(key).unwrap_or(false) {
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::GoodChecksum(sig));
- } else {
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::BadChecksum(sig));
- }
- } else {
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::MissingKey(sig));
- }
- } else {
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::BadChecksum(sig));
- }
+ self.sigs.iter_mut().last()
+ .expect("sigs is never empty").push(sig);
},
_ => (),
}
@@ -396,13 +375,40 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> {
}
let (p, ppr_tmp) = pp.recurse()?;
- self.verify(p)?;
+ self.push_sig(p)?;
ppr = ppr_tmp;
}
// Verify the signatures.
- self.helper.check(::std::mem::replace(&mut self.sigs,
- Vec::new()))
+ let mut results = Vec::new();
+ for sigs in ::std::mem::replace(&mut self.sigs, Vec::new())
+ .into_iter()
+ {
+ results.push(Vec::new());
+ for sig in sigs.into_iter() {
+ results.iter_mut().last().expect("never empty").push(
+ if let Some(issuer) = sig.get_issuer() {
+ if let Some((i, j)) = self.keys.get(&issuer) {
+ let (_, _, key)
+ = self.tpks[*i].keys_all().nth(*j)
+ .unwrap();
+ if sig.verify(key).unwrap_or(false) {
+ VerificationResult::GoodChecksum(sig)
+ } else {
+ VerificationResult::BadChecksum(sig)
+ }
+ } else {
+ VerificationResult::MissingKey(sig)
+ }
+ } else {
+ // No issuer.
+ VerificationResult::BadChecksum(sig)
+ }
+ )
+ }
+ }
+
+ self.helper.check(results)
} else {
self.oppr = Some(PacketParserResult::Some(pp));
Ok(())
@@ -815,7 +821,7 @@ pub struct Decryptor<'a, H: VerificationHelper + DecryptionHelper> {
keys: HashMap<KeyID, (usize, usize)>,
oppr: Option<PacketParserResult<'a>>,
identity: Option<Fingerprint>,
- sigs: Vec<Vec<VerificationResult>>,
+ sigs: Vec<Vec<Signature>>,
reserve: Option<Vec<u8>>,
}
@@ -996,9 +1002,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
v.oppr = Some(PacketParserResult::Some(pp));
v.finish_maybe()?;
- // Verify any queued signatures.
+ // Stash signatures.
for sig in sigs.into_iter() {
- v.verify(Packet::Signature(sig))?;
+ v.push_sig(Packet::Signature(sig))?;
}
return Ok(v);
@@ -1015,7 +1021,7 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
Packet::SKESK(skesk) => skesks.push(skesk),
Packet::Signature(sig) => {
if saw_content {
- v.verify(Packet::Signature(sig))?;
+ v.push_sig(Packet::Signature(sig))?;
} else {
if let Some(issuer) = sig.get_issuer() {
issuers.push(issuer);
@@ -1036,9 +1042,9 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
"Malformed OpenPGP message".into()).into())
}
- /// Verifies the given Signature (if it is one), and stores the
- /// result.
- fn verify(&mut self, p: Packet) -> Result<()> {
+ /// Stashes the given Signature (if it is one) for later
+ /// verification.
+ fn push_sig(&mut self, p: Packet) -> Result<()> {
match p {
Packet::Signature(sig) => {
if self.sigs.is_empty() {
@@ -1054,43 +1060,8 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
}
}
- // 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.
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::BadChecksum(sig));
- return Ok(());
- }
- }
-
- if let Some(issuer) = sig.get_issuer() {
- if let Some((i, j)) = self.keys.get(&issuer) {
- let (_, _, key)
- = self.tpks[*i].keys_all().nth(*j).unwrap();
- if sig.verify(key).unwrap_or(false) {
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::GoodChecksum(sig));
- } else {
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::BadChecksum(sig));
- }
- } else {
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::MissingKey(sig));
- }
- } else {
- self.sigs.iter_mut().last()
- .expect("sigs is never empty").push(
- VerificationResult::BadChecksum(sig));
- }
+ self.sigs.iter_mut().last()
+ .expect("sigs is never empty").push(sig);
},
_ => (),
}
@@ -1134,13 +1105,64 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> {
}
let (p, ppr_tmp) = pp.recurse()?;
- self.verify(p)?;
+ self.push_sig(p)?;
ppr = ppr_tmp;
}
// Verify the signatures.
- self.helper.check(::std::mem::replace(&mut self.sigs,
- Vec::new()))
+ let mut results = Vec::new();
+ for sigs in ::std::mem::replace(&mut self.sigs, Vec::new())
+ .into_iter()
+ {
+ results.push(Vec::new());
+ for sig in sigs.into_iter() {
+ results.iter_mut().last().expect("never empty").push(
+ if let Some(issuer) = sig.get_issuer() {
+ if let Some((i, j)) = self.keys.get(&issuer) {
+ let (_, _, key)
+ = self.tpks[*i].keys_all().nth(*j)
+ .unwrap();
+ if sig.verify(key).unwrap_or(false) {
+ // 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)
+ } else {
+ VerificationResult::GoodChecksum
+ (sig)
+ }
+ } else {
+ // No identity information.
+ VerificationResult::GoodChecksum
+ (sig)
+ }
+ } else {
+ VerificationResult::BadChecksum(sig)
+ }
+ } else {
+ VerificationResult::MissingKey(sig)
+ }
+ } else {
+ // No issuer.
+ VerificationResult::BadChecksum(sig)
+ }
+ )
+ }
+ }
+
+ self.helper.check(results)
} else {
self.oppr = Some(PacketParserResult::Some(pp));
Ok(())