summaryrefslogtreecommitdiffstats
path: root/openpgp/src
diff options
context:
space:
mode:
authorKai Michaelis <kai@sequoia-pgp.org>2018-11-02 16:01:22 +0100
committerKai Michaelis <kai@sequoia-pgp.org>2018-11-02 16:04:12 +0100
commit50c7119c9f79c7a2a7764f76609c147aa7200b07 (patch)
tree549bc34786b02ff20f0c8746992259598795b0cf /openpgp/src
parentf2b9a7e0b40823c2403faae7e073f2ae5610ce92 (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.rs55
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()