From 0012dc4f4f99d2c4aea94bc63dc64e126cd3a306 Mon Sep 17 00:00:00 2001 From: "Neal H. Walfield" Date: Fri, 6 Sep 2019 12:37:17 +0200 Subject: openpgp: Add a timestamp arg to ComponentBinding::binding_signature - Change ComponentBinding::binding_signature to take an optional timestamp and return the self signature that is active at that time. --- openpgp-ffi/src/tpk.rs | 2 +- openpgp/src/parse/stream.rs | 4 ++-- openpgp/src/serialize/tpk.rs | 6 ++--- openpgp/src/serialize/tpk_armored.rs | 2 +- openpgp/src/tpk/keyiter.rs | 2 +- openpgp/src/tpk/mod.rs | 46 ++++++++++++++++++++++-------------- tool/src/commands/decrypt.rs | 2 +- tool/src/commands/inspect.rs | 4 ++-- 8 files changed, 39 insertions(+), 29 deletions(-) diff --git a/openpgp-ffi/src/tpk.rs b/openpgp-ffi/src/tpk.rs index b7c269fb..80801789 100644 --- a/openpgp-ffi/src/tpk.rs +++ b/openpgp-ffi/src/tpk.rs @@ -429,7 +429,7 @@ pub extern "C" fn pgp_user_id_binding_selfsig( -> Maybe { let binding = ffi_param_ref!(binding); - binding.binding_signature().move_into_raw() + binding.binding_signature(None).move_into_raw() } diff --git a/openpgp/src/parse/stream.rs b/openpgp/src/parse/stream.rs index d0805643..0d5e8e01 100644 --- a/openpgp/src/parse/stream.rs +++ b/openpgp/src/parse/stream.rs @@ -525,7 +525,7 @@ impl<'a, H: VerificationHelper> Verifier<'a, H> { for (j, skb) in tpk.subkeys().enumerate() { let key = skb.key(); - if can_sign(key, skb.binding_signature(), t) { + if can_sign(key, skb.binding_signature(None), t) { v.keys.insert(key.keyid(), (i, j + 1)); } @@ -1312,7 +1312,7 @@ impl<'a, H: VerificationHelper + DecryptionHelper> Decryptor<'a, H> { for (j, skb) in tpk.subkeys().enumerate() { let key = skb.key(); - if can_sign(key.into(), skb.binding_signature()) { + if can_sign(key.into(), skb.binding_signature(None)) { v.keys.insert(key.keyid(), (i, j + 1)); } } diff --git a/openpgp/src/serialize/tpk.rs b/openpgp/src/serialize/tpk.rs index 8f35d653..94b945f9 100644 --- a/openpgp/src/serialize/tpk.rs +++ b/openpgp/src/serialize/tpk.rs @@ -767,11 +767,11 @@ mod test { ]).unwrap(); assert_eq!(tpk.subkeys().count(), 1); - assert!(tpk.subkeys().nth(0).unwrap().binding_signature().is_some()); + assert!(tpk.subkeys().nth(0).unwrap().binding_signature(None).is_some()); assert_eq!(tpk.userids().count(), 1); - assert!(tpk.userids().nth(0).unwrap().binding_signature().is_some()); + assert!(tpk.userids().nth(0).unwrap().binding_signature(None).is_some()); assert_eq!(tpk.user_attributes().count(), 1); - assert!(tpk.user_attributes().nth(0).unwrap().binding_signature() + assert!(tpk.user_attributes().nth(0).unwrap().binding_signature(None) .is_some()); // The binding signature is not exportable, so when we export diff --git a/openpgp/src/serialize/tpk_armored.rs b/openpgp/src/serialize/tpk_armored.rs index ee31b72a..3c602965 100644 --- a/openpgp/src/serialize/tpk_armored.rs +++ b/openpgp/src/serialize/tpk_armored.rs @@ -39,7 +39,7 @@ impl TPK { } // Ignore userids not "alive". }).filter_map(|uidb| { - if uidb.binding_signature()?.signature_alive() { + if uidb.binding_signature(None)?.signature_alive() { Some(uidb) } else { None diff --git a/openpgp/src/tpk/keyiter.rs b/openpgp/src/tpk/keyiter.rs index c1383c73..e865a176 100644 --- a/openpgp/src/tpk/keyiter.rs +++ b/openpgp/src/tpk/keyiter.rs @@ -100,7 +100,7 @@ impl<'a, P: 'a + key::KeyParts, R: 'a + key::KeyRole> Iterator tpk.primary().key().into()) } else { self.subkey_iter.next() - .map(|sk_binding| (sk_binding.binding_signature(), + .map(|sk_binding| (sk_binding.binding_signature(None), sk_binding.revoked(None), sk_binding.key().into(),))? }; diff --git a/openpgp/src/tpk/mod.rs b/openpgp/src/tpk/mod.rs index 98dac651..f489881e 100644 --- a/openpgp/src/tpk/mod.rs +++ b/openpgp/src/tpk/mod.rs @@ -175,16 +175,26 @@ impl ComponentBinding { &mut self.component } - /// Returns the most recent binding signature. + /// Returns the active binding signature at time `t`. /// - /// This will never return a revocation certificate. + /// An active binding signature is a non-revoked, self-signature + /// that is alive at time `t` (`creation time <= t`, `t <= + /// expiry`). /// - /// Normally, we ignore subkeys that don't have a binding - /// signature. However, if there is a valid revocation - /// certificate for the subkey, we keep it. In such cases, this - /// function will return None. - pub fn binding_signature(&self) -> Option<&Signature> { - self.selfsigs.last() + /// This function returns None if there are no active binding + /// signatures at time `t`. + pub fn binding_signature(&self, t: T) -> Option<&Signature> + where T: Into> + { + let t = t.into().unwrap_or_else(time::now_utc); + let time_zero = time::at_utc(time::Timespec::new(0, 0)); + + self.selfsigs.iter().filter(|s| { + s.signature_alive_at(t) + }).max_by(|a, b| { + a.signature_creation_time().unwrap_or(time_zero).cmp( + &b.signature_creation_time().unwrap_or(time_zero)) + }) } /// The self-signatures. @@ -364,8 +374,8 @@ impl Ord for UserIDBinding { return Ordering::Less; } - let a_selfsig = self.binding_signature(); - let b_selfsig = b.binding_signature(); + let a_selfsig = self.binding_signature(None); + let b_selfsig = b.binding_signature(None); if a_revoked && b_revoked { // Both are revoked. @@ -462,8 +472,8 @@ impl Ord for UserAttributeBinding { return Ordering::Less; } - let a_selfsig = self.binding_signature(); - let b_selfsig = b.binding_signature(); + let a_selfsig = self.binding_signature(None); + let b_selfsig = b.binding_signature(None); if a_revoked && b_revoked { // Both are revoked. @@ -566,8 +576,8 @@ impl Ord for KeyBinding return Ordering::Less; } - let a_selfsig = self.binding_signature(); - let b_selfsig = b.binding_signature(); + let a_selfsig = self.binding_signature(None); + let b_selfsig = b.binding_signature(None); if a_revoked && b_revoked { // Both are revoked. @@ -1624,7 +1634,7 @@ impl TPK { return true; } self.subkeys().any(|sk| { - sk.binding_signature().is_some() && sk.key().secret().is_some() + sk.binding_signature(None).is_some() && sk.key().secret().is_some() }) } } @@ -2246,7 +2256,7 @@ mod test { } for userid in tpk.userids() { - let typ = userid.binding_signature().unwrap().typ(); + let typ = userid.binding_signature(None).unwrap().typ(); assert_eq!(typ, SignatureType::PositiveCertificate, "{:#?}", tpk); @@ -2260,7 +2270,7 @@ mod test { } for subkey in tpk.subkeys() { - let typ = subkey.binding_signature().unwrap().typ(); + let typ = subkey.binding_signature(None).unwrap().typ(); assert_eq!(typ, SignatureType::SubkeyBinding, "{:#?}", tpk); @@ -2610,7 +2620,7 @@ Pu1xwz57O4zo1VYf6TqHJzVC3OMvMUM2hhdecMUe5x6GorNaj6g= < uidb.selfsigs()[1].signature_creation_time()); // Make sure we return the most recent here. assert_eq!(uidb.selfsigs().last().unwrap(), - uidb.binding_signature().unwrap()); + uidb.binding_signature(None).unwrap()); } #[test] diff --git a/tool/src/commands/decrypt.rs b/tool/src/commands/decrypt.rs index 444f1cbd..48b14e46 100644 --- a/tool/src/commands/decrypt.rs +++ b/tool/src/commands/decrypt.rs @@ -67,7 +67,7 @@ impl<'a> Helper<'a> { for skb in tsk.subkeys() { let key = skb.key(); - if can_encrypt(key, skb.binding_signature()) { + if can_encrypt(key, skb.binding_signature(None)) { let id = key.fingerprint().to_keyid(); keys.insert(id.clone(), key.clone().into()); identities.insert(id.clone(), tsk.fingerprint()); diff --git a/tool/src/commands/inspect.rs b/tool/src/commands/inspect.rs index bb8ed112..95fd07fa 100644 --- a/tool/src/commands/inspect.rs +++ b/tool/src/commands/inspect.rs @@ -139,7 +139,7 @@ fn inspect_tpk(output: &mut io::Write, tpk: &openpgp::TPK, for skb in tpk.subkeys() { writeln!(output, " Subkey: {}", skb.key().fingerprint())?; inspect_revocation(output, "", skb.revoked(None))?; - inspect_key(output, "", skb.key(), skb.binding_signature(), + inspect_key(output, "", skb.key(), skb.binding_signature(None), skb.certifications(), print_keygrips, print_certifications)?; writeln!(output)?; @@ -148,7 +148,7 @@ fn inspect_tpk(output: &mut io::Write, tpk: &openpgp::TPK, for uidb in tpk.userids() { writeln!(output, " UserID: {}", uidb.userid())?; inspect_revocation(output, "", uidb.revoked(None))?; - if let Some(sig) = uidb.binding_signature() { + if let Some(sig) = uidb.binding_signature(None) { if sig.signature_expired() { writeln!(output, " Expired")?; } else if ! sig.signature_alive() { -- cgit v1.2.3