diff options
author | Kai Michaelis <kai@sequoia-pgp.org> | 2018-11-02 16:01:22 +0100 |
---|---|---|
committer | Kai Michaelis <kai@sequoia-pgp.org> | 2018-11-02 16:04:12 +0100 |
commit | 50c7119c9f79c7a2a7764f76609c147aa7200b07 (patch) | |
tree | 549bc34786b02ff20f0c8746992259598795b0cf /openpgp/src | |
parent | f2b9a7e0b40823c2403faae7e073f2ae5610ce92 (diff) |
openpgp: improve handling uid revocations.
Revocation signatures only revoke earlier self-sigs, not signatures made
after the rev-sig.
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/tpk/mod.rs | 55 |
1 files changed, 52 insertions, 3 deletions
diff --git a/openpgp/src/tpk/mod.rs b/openpgp/src/tpk/mod.rs index 3ccb0c0d..1ce03b3f 100644 --- a/openpgp/src/tpk/mod.rs +++ b/openpgp/src/tpk/mod.rs @@ -539,14 +539,54 @@ impl UserIDBinding { /// you want to know whether the key, subkey, etc., is revoked, /// then you need to query them separately. pub fn revoked(&self) -> RevocationStatus { - if self.self_revocations.len() > 0 { - RevocationStatus::Revoked(&self.self_revocations[..]) - } else if self.other_revocations.len() > 0 { + let has_self_revs = + Self::active_revocation(self.selfsigs.clone(), + self.self_revocations.clone()); + + if has_self_revs { + return RevocationStatus::Revoked(&self.self_revocations[..]); + } + + let has_other_revs = + Self::active_revocation(self.selfsigs.clone(), + self.other_revocations.clone()); + + if has_other_revs { RevocationStatus::CouldBe(&self.other_revocations[..]) } else { RevocationStatus::NotAsFarAsWeKnow } } + + /// Returns true if latest revocation signature in `revs` is newer than the + /// latest self signature in sigs. + /// + /// Signatures are expected to have the right signature types and be + /// cryptographically sound. + fn active_revocation(mut sigs: Vec<Signature>, mut revs: Vec<Signature>) + -> bool + { + let cmp = |a: &Signature, b: &Signature| { + match (a.signature_creation_time(),b.signature_creation_time()) { + (None, None) => Ordering::Equal, + (None, Some(_)) => Ordering::Greater, + (Some(_), None) => Ordering::Less, + (Some(ref a), Some(ref b)) => a.cmp(b), + } + }; + + sigs.sort_by(&cmp); + revs.sort_by(&cmp); + + match (sigs.last(), revs.last()) { + (None, Some(_)) => true, + (Some(_), None) => false, + (None, None) => false, + (Some(ref sig), Some(ref revc)) => { + cmp(sig, revc) != Ordering::Greater + } + } + } } /// A User Attribute and any associated signatures. @@ -3138,6 +3178,15 @@ mod test { } #[test] + fn unrevoked() { + let tpk = TPK::from_bytes(bytes!("un-revoked-userid.pgp")).unwrap(); + + for uid in tpk.userids() { + assert_eq!(uid.revoked(), RevocationStatus::NotAsFarAsWeKnow); + } + } + + #[test] fn tsk_filter() { let (tpk, _) = TPKBuilder::default() .add_signing_subkey() |