diff options
Diffstat (limited to 'openpgp/src')
-rw-r--r-- | openpgp/src/autocrypt.rs | 11 | ||||
-rw-r--r-- | openpgp/src/cert/amalgamation.rs | 56 | ||||
-rw-r--r-- | openpgp/src/cert/bindings.rs | 7 | ||||
-rw-r--r-- | openpgp/src/cert/builder.rs | 46 | ||||
-rw-r--r-- | openpgp/src/cert/component_iter.rs | 15 | ||||
-rw-r--r-- | openpgp/src/cert/components.rs | 27 | ||||
-rw-r--r-- | openpgp/src/cert/key_amalgamation.rs | 52 | ||||
-rw-r--r-- | openpgp/src/cert/keyiter.rs | 91 | ||||
-rw-r--r-- | openpgp/src/cert/mod.rs | 323 | ||||
-rw-r--r-- | openpgp/src/cert/revoke.rs | 23 | ||||
-rw-r--r-- | openpgp/src/lib.rs | 1 | ||||
-rw-r--r-- | openpgp/src/packet/signature/mod.rs | 7 | ||||
-rw-r--r-- | openpgp/src/parse/stream.rs | 163 | ||||
-rw-r--r-- | openpgp/src/policy.rs | 82 | ||||
-rw-r--r-- | openpgp/src/serialize/cert.rs | 26 | ||||
-rw-r--r-- | openpgp/src/serialize/cert_armored.rs | 13 | ||||
-rw-r--r-- | openpgp/src/serialize/stream.rs | 42 | ||||
-rw-r--r-- | openpgp/src/types/timestamp.rs | 8 |
18 files changed, 674 insertions, 319 deletions
diff --git a/openpgp/src/autocrypt.rs b/openpgp/src/autocrypt.rs index b308e29d..cb579211 100644 --- a/openpgp/src/autocrypt.rs +++ b/openpgp/src/autocrypt.rs @@ -36,6 +36,7 @@ use crate::serialize::stream::{ Message, LiteralWriter, Encryptor, }; use crate::crypto::Password; +use crate::policy::Policy; /// Version of Autocrypt to use. `Autocrypt::default()` always returns the /// latest version. @@ -97,7 +98,8 @@ impl AutocryptHeader { } /// Creates a new "Autocrypt" header. - pub fn new_sender<'a, P>(cert: &Cert, addr: &str, prefer_encrypt: P) + pub fn new_sender<'a, P>(policy: &dyn Policy, + cert: &Cert, addr: &str, prefer_encrypt: P) -> Result<Self> where P: Into<Option<&'a str>> { @@ -128,7 +130,7 @@ impl AutocryptHeader { } // The UserIDs matching ADDR. - for uidb in cert.userids().policy(None) { + for uidb in cert.userids().set_policy(policy, None) { // XXX: Fix match once we have the rfc2822-name-addr. if let Ok(Some(a)) = uidb.userid().email() { if &a == addr { @@ -773,6 +775,7 @@ mod test { use super::*; use crate::Fingerprint; + use crate::policy::StandardPolicy as P; #[test] fn decode_test() { @@ -1067,8 +1070,10 @@ In the light of the Efail vulnerability I am asking myself if it's #[test] fn autocrypt_header_new() { + let p = &P::new(); + let cert = Cert::from_bytes(crate::tests::key("testy.pgp")).unwrap(); - let header = AutocryptHeader::new_sender(&cert, "testy@example.org", + let header = AutocryptHeader::new_sender(p, &cert, "testy@example.org", "mutual").unwrap(); let mut buf = Vec::new(); write!(&mut buf, "Autocrypt: ").unwrap(); diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs index 205099c1..cd9b2079 100644 --- a/openpgp/src/cert/amalgamation.rs +++ b/openpgp/src/cert/amalgamation.rs @@ -8,6 +8,7 @@ use crate::{ packet::Signature, Result, RevocationStatus, + policy::Policy, }; /// A certificate's component and its associated data. @@ -49,12 +50,13 @@ impl<'a, C> ComponentAmalgamation<'a, C> { /// time, if any. /// /// Note: this function is not exported. Users of this interface - /// should do: ca.policy(time)?.binding_signature(). - fn binding_signature<T>(&self, time: T) -> Option<&'a Signature> + /// should do: ca.set_policy(policy, time)?.binding_signature(). + fn binding_signature<T>(&self, policy: &dyn Policy, time: T) + -> Option<&'a Signature> where T: Into<Option<time::SystemTime>> { let time = time.into().unwrap_or_else(SystemTime::now); - self.binding.binding_signature(time) + self.binding.binding_signature(policy, time) } /// Sets the reference time for the amalgamation. @@ -63,14 +65,15 @@ impl<'a, C> ComponentAmalgamation<'a, C> { /// /// This transforms the `ComponentAmalgamation` into a /// `ValidComponentAmalgamation`. - pub fn policy<T>(self, time: T) + pub fn set_policy<T>(self, policy: &'a dyn Policy, time: T) -> Result<ValidComponentAmalgamation<'a, C>> where T: Into<Option<time::SystemTime>> { let time = time.into().unwrap_or_else(SystemTime::now); - if let Some(binding_signature) = self.binding_signature(time) { + if let Some(binding_signature) = self.binding_signature(policy, time) { Ok(ValidComponentAmalgamation { a: self, + policy: policy, time: time, binding_signature: binding_signature, }) @@ -98,6 +101,7 @@ impl<'a> ComponentAmalgamation<'a, crate::packet::UserAttribute> { #[derive(Debug, Clone)] pub struct ValidComponentAmalgamation<'a, C> { a: ComponentAmalgamation<'a, C>, + policy: &'a dyn Policy, // The reference time. time: SystemTime, // The binding signature at time `time`. (This is just a cache.) @@ -131,25 +135,25 @@ impl<'a, C> ValidComponentAmalgamation<'a, C> /// deterministic, but undefined manner. pub(super) fn primary(cert: &'a Cert, iter: std::slice::Iter<'a, ComponentBinding<C>>, - t: SystemTime) - -> Option<ValidComponentAmalgamation<'a, C>> + policy: &'a dyn Policy, t: SystemTime) + -> Option<ValidComponentAmalgamation<'a, C>> { use std::cmp::Ordering; // Filter out components that are not alive at time `t`. - // - // While we have the binding signature, extract a few - // properties to avoid recomputing the same thing multiple - // times. + // + // While we have the binding signature, extract a few + // properties to avoid recomputing the same thing multiple + // times. iter.filter_map(|c| { // No binding signature at time `t` => not alive. - let sig = c.binding_signature(t)?; + let sig = c.binding_signature(policy, t)?; if !sig.signature_alive(t, std::time::Duration::new(0, 0)).is_ok() { return None; } - let revoked = c._revoked(false, Some(sig), t); + let revoked = c._revoked(policy, t, false, Some(sig)); let primary = sig.primary_userid().unwrap_or(false); let signature_creation_time = sig.signature_creation_time()?; @@ -185,7 +189,7 @@ impl<'a, C> ValidComponentAmalgamation<'a, C> } }) .and_then(|c| ComponentAmalgamation::new(cert, (c.0).0) - .policy(t).ok()) + .set_policy(policy, t).ok()) } } @@ -203,10 +207,13 @@ pub trait Amalgamation<'a> { /// time is greater than or equal to `t_c` and less than `t_e`. fn time(&self) -> SystemTime; + /// Returns the amalgamation's policy. + fn policy(&self) -> &'a dyn Policy; + /// Changes the amalgamation's policy. /// /// If `time` is `None`, the current time is used. - fn policy<T>(self, time: T) -> Result<Self> + fn set_policy<T>(self, policy: &'a dyn Policy, time: T) -> Result<Self> where Self: Sized, T: Into<Option<time::SystemTime>>; /// Returns the component's binding signature as of the reference time. @@ -228,13 +235,13 @@ pub trait Amalgamation<'a> { /// Returns the certificate's revocation status as of the /// amalgamtion's reference time. fn cert_revoked(&self) -> RevocationStatus<'a> { - self.cert().revoked(self.time()) + self.cert().revoked(self.policy(), self.time()) } /// Returns whether the certificateis alive as of the /// amalgamtion's reference time. fn cert_alive(&self) -> Result<()> { - self.cert().alive(self.time()) + self.cert().alive(self.policy(), self.time()) } } @@ -256,14 +263,20 @@ impl<'a, C> Amalgamation<'a> for ValidComponentAmalgamation<'a, C> { self.time } + /// Returns the amalgamation's policy. + fn policy(&self) -> &'a dyn Policy + { + self.policy + } + /// Changes the amalgamation's policy. /// /// If `time` is `None`, the current time is used. - fn policy<T>(self, time: T) -> Result<Self> + fn set_policy<T>(self, policy: &'a dyn Policy, time: T) -> Result<Self> where T: Into<Option<time::SystemTime>> { let time = time.into().unwrap_or_else(SystemTime::now); - self.a.policy(time) + self.a.set_policy(policy, time) } /// Returns the component's binding signature as of the reference time. @@ -277,7 +290,7 @@ impl<'a, C> Amalgamation<'a> for ValidComponentAmalgamation<'a, C> { /// Subpackets on direct key signatures apply to all components of /// the certificate. fn direct_key_signature(&self) -> Option<&'a Signature> { - self.cert.primary.binding_signature(self.time()) + self.cert.primary.binding_signature(self.policy(), self.time()) } /// Returns the component's revocation status as of the amalgamation's @@ -285,7 +298,8 @@ impl<'a, C> Amalgamation<'a> for ValidComponentAmalgamation<'a, C> { /// /// Note: this does not return whether the certificate is valid. fn revoked(&self) -> RevocationStatus<'a> { - self.binding._revoked(false, Some(self.binding_signature), self.time) + self.binding._revoked(self.policy(), self.time, + false, Some(self.binding_signature)) } } diff --git a/openpgp/src/cert/bindings.rs b/openpgp/src/cert/bindings.rs index 2dd3aac4..83d319a2 100644 --- a/openpgp/src/cert/bindings.rs +++ b/openpgp/src/cert/bindings.rs @@ -29,6 +29,9 @@ impl<P: key::KeyParts> Key<P, key::SubordinateRole> { /// # use sequoia_openpgp::{*, packet::prelude::*, types::*, cert::*}; /// # f().unwrap(); /// # fn f() -> Result<()> { + /// use sequoia_openpgp::policy::StandardPolicy; + /// let p = &StandardPolicy::new(); + /// /// // Generate a Cert, and create a keypair from the primary key. /// let (cert, _) = CertBuilder::new().generate()?; /// let mut keypair = cert.primary_key().key().clone() @@ -36,7 +39,7 @@ impl<P: key::KeyParts> Key<P, key::SubordinateRole> { /// /// // Let's add an encryption subkey. /// let flags = KeyFlags::default().set_storage_encryption(true); - /// assert_eq!(cert.keys().policy(None).alive().revoked(false) + /// assert_eq!(cert.keys().set_policy(p, None).alive().revoked(false) /// .key_flags(&flags).count(), /// 0); /// @@ -53,7 +56,7 @@ impl<P: key::KeyParts> Key<P, key::SubordinateRole> { /// binding.into()])?; /// /// // Check that we have an encryption subkey. - /// assert_eq!(cert.keys().policy(None).alive().revoked(false) + /// assert_eq!(cert.keys().set_policy(p, None).alive().revoked(false) /// .key_flags(flags).count(), /// 1); /// # Ok(()) } diff --git a/openpgp/src/cert/builder.rs b/openpgp/src/cert/builder.rs index 2df4606d..f950b484 100644 --- a/openpgp/src/cert/builder.rs +++ b/openpgp/src/cert/builder.rs @@ -466,9 +466,12 @@ mod tests { use crate::cert::components::Amalgamation; use crate::packet::signature::subpacket::{SubpacketTag, SubpacketValue}; use crate::types::PublicKeyAlgorithm; + use crate::policy::StandardPolicy as P; #[test] fn all_opts() { + let p = &P::new(); + let (cert, _) = CertBuilder::new() .set_cipher_suite(CipherSuite::Cv25519) .add_userid("test1@example.com") @@ -478,7 +481,7 @@ mod tests { .add_certification_subkey() .generate().unwrap(); - let mut userids = cert.userids().policy(None) + let mut userids = cert.userids().set_policy(p, None) .map(|u| String::from_utf8_lossy(u.userid().value()).into_owned()) .collect::<Vec<String>>(); userids.sort(); @@ -492,6 +495,8 @@ mod tests { #[test] fn direct_key_sig() { + let p = &P::new(); + let (cert, _) = CertBuilder::new() .set_cipher_suite(CipherSuite::Cv25519) .add_signing_subkey() @@ -502,7 +507,7 @@ mod tests { assert_eq!(cert.userids().count(), 0); assert_eq!(cert.subkeys().count(), 3); let sig = - cert.primary_key().policy(None).unwrap().binding_signature(); + cert.primary_key().set_policy(p, None).unwrap().binding_signature(); assert_eq!(sig.typ(), crate::types::SignatureType::DirectKey); assert!(sig.features().unwrap().supports_mdc()); } @@ -529,13 +534,14 @@ mod tests { #[test] fn defaults() { + let p = &P::new(); let (cert1, _) = CertBuilder::new() .add_userid("test2@example.com") .generate().unwrap(); assert_eq!(cert1.primary_key().pk_algo(), PublicKeyAlgorithm::EdDSA); assert!(cert1.subkeys().next().is_none()); - assert!(cert1.primary_userid(None).unwrap() + assert!(cert1.primary_userid(p, None).unwrap() .binding_signature().features().unwrap().supports_mdc()); } @@ -569,12 +575,13 @@ mod tests { #[test] fn always_certify() { + let p = &P::new(); let (cert1, _) = CertBuilder::new() .set_cipher_suite(CipherSuite::Cv25519) .primary_key_flags(KeyFlags::default()) .add_transport_encryption_subkey() .generate().unwrap(); - assert!(cert1.primary_key().policy(None).unwrap().for_certification()); + assert!(cert1.primary_key().set_policy(p, None).unwrap().for_certification()); assert_eq!(cert1.keys().subkeys().count(), 1); } @@ -597,15 +604,16 @@ mod tests { #[test] fn generate_revocation_certificate() { + let p = &P::new(); use crate::RevocationStatus; let (cert, revocation) = CertBuilder::new() .set_cipher_suite(CipherSuite::Cv25519) .generate().unwrap(); - assert_eq!(cert.revoked(None), + assert_eq!(cert.revoked(p, None), RevocationStatus::NotAsFarAsWeKnow); let cert = cert.merge_packets(vec![revocation.clone().into()]).unwrap(); - assert_eq!(cert.revoked(None), + assert_eq!(cert.revoked(p, None), RevocationStatus::Revoked(vec![ &revocation ])); } @@ -646,6 +654,8 @@ mod tests { #[test] fn expiration_times() { + let p = &P::new(); + let s = std::time::Duration::new(1, 0); let (cert,_) = CertBuilder::new() .set_expiration(600 * s) @@ -663,23 +673,25 @@ mod tests { assert!(sig.key_alive(key, now + 590 * s).is_ok()); assert!(! sig.key_alive(key, now + 610 * s).is_ok()); - let ka = cert.keys().policy(now).alive().revoked(false) + let ka = cert.keys().set_policy(p, now).alive().revoked(false) .for_signing() .nth(0).unwrap(); assert!(ka.alive().is_ok()); - assert!(ka.clone().policy(now + 290 * s).unwrap().alive().is_ok()); - assert!(! ka.clone().policy(now + 310 * s).unwrap().alive().is_ok()); + assert!(ka.clone().set_policy(p, now + 290 * s).unwrap().alive().is_ok()); + assert!(! ka.clone().set_policy(p, now + 310 * s).unwrap().alive().is_ok()); - let ka = cert.keys().policy(now).alive().revoked(false) + let ka = cert.keys().set_policy(p, now).alive().revoked(false) .for_authentication() .nth(0).unwrap(); assert!(ka.alive().is_ok()); - assert!(ka.clone().policy(now + 590 * s).unwrap().alive().is_ok()); - assert!(! ka.clone().policy(now + 610 * s).unwrap().alive().is_ok()); + assert!(ka.clone().set_policy(p, now + 590 * s).unwrap().alive().is_ok()); + assert!(! ka.clone().set_policy(p, now + 610 * s).unwrap().alive().is_ok()); } #[test] fn creation_time() { + let p = &P::new(); + use std::time::UNIX_EPOCH; let (cert, rev) = CertBuilder::new() .set_creation_time(UNIX_EPOCH) @@ -689,17 +701,17 @@ mod tests { .generate().unwrap(); assert_eq!(cert.primary_key().creation_time(), UNIX_EPOCH); - assert_eq!(cert.primary_key().policy(None).unwrap() + assert_eq!(cert.primary_key().set_policy(p, None).unwrap() .binding_signature() .signature_creation_time().unwrap(), UNIX_EPOCH); - assert_eq!(cert.primary_key().policy(None).unwrap() + assert_eq!(cert.primary_key().set_policy(p, None).unwrap() .direct_key_signature().unwrap() .signature_creation_time().unwrap(), UNIX_EPOCH); assert_eq!(rev.signature_creation_time().unwrap(), UNIX_EPOCH); // (Sub)Keys. - assert_eq!(cert.keys().policy(None).count(), 2); - for ka in cert.keys().policy(None) { + assert_eq!(cert.keys().set_policy(p, None).count(), 2); + for ka in cert.keys().set_policy(p, None) { assert_eq!(ka.key().creation_time(), UNIX_EPOCH); assert_eq!(ka.binding_signature() .signature_creation_time().unwrap(), UNIX_EPOCH); @@ -707,7 +719,7 @@ mod tests { // UserIDs. assert_eq!(cert.userids().count(), 1); - for ui in cert.userids().policy(None) { + for ui in cert.userids().set_policy(p, None) { assert_eq!(ui.binding_signature() .signature_creation_time().unwrap(), UNIX_EPOCH); } diff --git a/openpgp/src/cert/component_iter.rs b/openpgp/src/cert/component_iter.rs index 9f7b015e..9cd9cada 100644 --- a/openpgp/src/cert/component_iter.rs +++ b/openpgp/src/cert/component_iter.rs @@ -13,6 +13,7 @@ use crate::{ ValidComponentAmalgamation, }, }, + policy::Policy, }; /// An iterator over all components in a certificate. @@ -59,13 +60,15 @@ impl<'a, C> ComponentIter<'a, C> { /// If `time` is None, then the current time is used. /// /// See `ValidComponentIter` for the definition of a valid component. - pub fn policy<T>(self, time: T) -> ValidComponentIter<'a, C> + pub fn set_policy<T>(self, policy: &'a dyn Policy, time: T) + -> ValidComponentIter<'a, C> where T: Into<Option<SystemTime>> { ValidComponentIter { cert: self.cert, iter: self.iter, time: time.into().unwrap_or_else(SystemTime::now), + policy: policy, revoked: None, } } @@ -92,8 +95,11 @@ pub struct ValidComponentIter<'a, C> { // This is an option to make it easier to create an empty ValidComponentIter. cert: &'a Cert, iter: ComponentBindingIter<'a, C>, + + policy: &'a dyn Policy, // The time. time: SystemTime, + // If not None, filters by whether the component is revoked or not // at time `t`. revoked: Option<bool>, @@ -122,7 +128,7 @@ impl<'a, C> Iterator for ValidComponentIter<'a, C> t!("Considering component: {:?}", ca.binding()); let vca - = if let Ok(vca) = ca.policy(self.time) { + = if let Ok(vca) = ca.set_policy(self.policy, self.time) { vca } else { t!("No self-signature at time {:?}", self.time); @@ -177,16 +183,19 @@ impl<'a, C> ValidComponentIter<'a, C> { /// # use openpgp::cert::CertBuilder; /// use openpgp::RevocationStatus; /// use openpgp::cert::components::Amalgamation; + /// use sequoia_openpgp::policy::StandardPolicy; /// /// # fn main() { f().unwrap(); } /// # fn f() -> Result<()> { + /// let p = &StandardPolicy::new(); + /// /// # let (cert, _) = /// # CertBuilder::general_purpose(None, Some("alice@example.org")) /// # .generate()?; /// # let timestamp = None; /// let non_revoked_uas = cert /// .user_attributes() - /// .policy(timestamp) + /// .set_policy(p, timestamp) /// .filter(|ca| { /// match ca.revoked() { /// RevocationStatus::Revoked(_) => diff --git a/openpgp/src/cert/components.rs b/openpgp/src/cert/components.rs index 0b9b2da6..6351fef9 100644 --- a/openpgp/src/cert/components.rs +++ b/openpgp/src/cert/components.rs @@ -13,6 +13,7 @@ use crate::{ packet::UserAttribute, packet::Unknown, Packet, + policy::Policy, }; use crate::types::{ RevocationType, @@ -110,7 +111,7 @@ impl<C> ComponentBinding<C> { /// /// This function returns None if there are no active binding /// signatures at time `t`. - pub fn binding_signature<T>(&self, t: T) -> Option<&Signature> + pub fn binding_signature<T>(&self, policy: &dyn Policy, t: T) -> Option<&Signature> where T: Into<Option<time::SystemTime>> { let t = t.into().unwrap_or_else(|| time::SystemTime::now()); @@ -169,6 +170,7 @@ impl<C> ComponentBinding<C> { self.self_signatures[i..].iter().filter(|s| { s.signature_alive(t, time::Duration::new(0, 0)).is_ok() + && policy.signature(s).is_ok() }).nth(0) } @@ -216,8 +218,9 @@ impl<C> ComponentBinding<C> { /// if there is a newer self-signature). /// /// selfsig must be the newest live self signature at time `t`. - pub(crate) fn _revoked<'a, T>(&'a self, hard_revocations_are_final: bool, - selfsig: Option<&Signature>, t: T) + pub(crate) fn _revoked<'a, T>(&'a self, policy: &dyn Policy, t: T, + hard_revocations_are_final: bool, + selfsig: Option<&Signature>) -> RevocationStatus<'a> where T: Into<Option<time::SystemTime>> { @@ -266,8 +269,7 @@ impl<C> ComponentBinding<C> { .unwrap_or_else(time_zero)); None } else if - ! rev.signature_alive(t, time::Duration::new(0, 0)) - .is_ok() + ! rev.signature_alive(t, time::Duration::new(0, 0)).is_ok() { t!(" ignoring revocation that is not alive ({:?} - {:?})", rev.signature_creation_time() @@ -275,6 +277,9 @@ impl<C> ComponentBinding<C> { rev.signature_expiration_time() .unwrap_or_else(|| time::Duration::new(0, 0))); None + } else if let Err(err) = policy.signature(rev) { + t!(" revocation rejected by caller policy: {}", err); + None } else { t!(" got a revocation: {:?} ({:?})", rev.signature_creation_time() @@ -370,12 +375,12 @@ impl<P: key::KeyParts> ComponentBinding<Key<P, key::SubordinateRole>> { /// /// Note: this only returns whether this subkey is revoked; it /// does not imply anything about the Cert or other components. - pub fn revoked<T>(&self, t: T) + pub fn revoked<T>(&self, policy: &dyn Policy, t: T) -> RevocationStatus where T: Into<Option<time::SystemTime>> { let t = t.into(); - self._revoked(true, self.binding_signature(t), t) + self._revoked(policy, t, true, self.binding_signature(policy, t)) } } @@ -397,12 +402,12 @@ impl ComponentBinding<UserID> { /// /// Note: this only returns whether this User ID is revoked; it /// does not imply anything about the Cert or other components. - pub fn revoked<T>(&self, t: T) + pub fn revoked<T>(&self, policy: &dyn Policy, t: T) -> RevocationStatus where T: Into<Option<time::SystemTime>> { let t = t.into(); - self._revoked(false, self.binding_signature(t), t) + self._revoked(policy, t, false, self.binding_signature(policy, t)) } } @@ -424,12 +429,12 @@ impl ComponentBinding<UserAttribute> { /// /// Note: this only returns whether this User Attribute is revoked; /// it does not imply anything about the Cert or other components. - pub fn revoked<T>(&self, t: T) + pub fn revoked<T>(&self, policy: &dyn Policy, t: T) -> RevocationStatus where T: Into<Option<time::SystemTime>> { let t = t.into(); - self._revoked(false, self.binding_signature(t), t) + self._revoked(policy, t, false, self.binding_signature(policy, t)) } } diff --git a/openpgp/src/cert/key_amalgamation.rs b/openpgp/src/cert/key_amalgamation.rs index 55605ee1..c9b7b4ed 100644 --- a/openpgp/src/cert/key_amalgamation.rs +++ b/openpgp/src/cert/key_amalgamation.rs @@ -16,6 +16,7 @@ use crate::{ packet::key::SecretKeyMaterial, packet::Key, packet::Signature, + policy::Policy, Result, RevocationStatus, types::KeyFlags, @@ -218,8 +219,9 @@ impl<'a, P: 'a + key::KeyParts> KeyAmalgamation<'a, P> { /// if any. /// /// Note: this function is not exported. Users of this interface - /// should do: ka.policy(time)?.binding_signature(). - fn binding_signature&l |