diff options
Diffstat (limited to 'openpgp/src/cert')
-rw-r--r-- | openpgp/src/cert/amalgamation.rs | 1353 | ||||
-rw-r--r-- | openpgp/src/cert/amalgamation/iter.rs | 388 | ||||
-rw-r--r-- | openpgp/src/cert/amalgamation/key.rs | 1937 | ||||
-rw-r--r-- | openpgp/src/cert/amalgamation/key/iter.rs | 1656 | ||||
-rw-r--r-- | openpgp/src/cert/bindings.rs | 40 | ||||
-rw-r--r-- | openpgp/src/cert/builder.rs | 829 | ||||
-rw-r--r-- | openpgp/src/cert/bundle.rs | 848 | ||||
-rw-r--r-- | openpgp/src/cert/component_iter.rs | 222 | ||||
-rw-r--r-- | openpgp/src/cert/components.rs | 495 | ||||
-rw-r--r-- | openpgp/src/cert/key_amalgamation.rs | 909 | ||||
-rw-r--r-- | openpgp/src/cert/keyiter.rs | 1075 | ||||
-rw-r--r-- | openpgp/src/cert/mod.rs | 2759 | ||||
-rw-r--r-- | openpgp/src/cert/parser/low_level/grammar.lalrpop | 4 | ||||
-rw-r--r-- | openpgp/src/cert/parser/low_level/grammar.rs | 1 | ||||
-rw-r--r-- | openpgp/src/cert/parser/low_level/lexer.rs | 4 | ||||
-rw-r--r-- | openpgp/src/cert/parser/mod.rs | 743 | ||||
-rw-r--r-- | openpgp/src/cert/prelude.rs | 59 | ||||
-rw-r--r-- | openpgp/src/cert/revoke.rs | 858 |
18 files changed, 10236 insertions, 3944 deletions
diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs index afe84ffe..8f887166 100644 --- a/openpgp/src/cert/amalgamation.rs +++ b/openpgp/src/cert/amalgamation.rs @@ -1,17 +1,224 @@ -//! Component amalgamations. +//! Components, their associated signatures, and some useful methods. //! -//! Whereas a `ComponentBundle` groups a `Component` with its self -//! signatures, its third-party signatures, and its revocation -//! certificates, an `Amalgamation` groups a `ComponentBundle` with -//! all of the necessary context needed to correctly implement -//! relevant functionality related to the component. Specifically, a -//! `Amalgamation` includes a reference to the `ComponentBundle`, and -//! a reference to the containing certificate. +//! Whereas a [`ComponentBundle`] owns a `Component` and its +//! associated [`Signature`]s, a [`ComponentAmalgamation`] references +//! a `ComponentBundle` and its containing [`Cert`]. This additional +//! context means that a `ComponentAmalgamation` can implement more of +//! OpenPGP's high-level semantics than a `ComponentBundle` can. For +//! instance, most of the information about a primary key, such as its +//! capabilities, is on the primary User ID's binding signature. A +//! `ComponentAmalgamation` can find the certificate's primary User +//! ID; a `ComponentBundle` can't. Similarly, when looking up a +//! subpacket, if it isn't present in the component's binding +//! signature, then an OpenPGP implementation [is supposed to] consult +//! the certificate's direct key signatures. A +//! `ComponentAmalgamation` has access to this information; a +//! `ComponentBundle` doesn't. //! -//! A notable differences between `ComponentBundle`s and -//! `Amalgamation`s is that a `ComponentBundle`, owns its data, but an -//! `Amalgamation` only references the contained data. -use std::borrow::Borrow; +//! Given the limitations of a `ComponentBundle`, it would seem more +//! useful to just change it to include a reference to its containing +//! certificate. That change would make `ComponentAmalgamation`s +//! redundant. Unfortunately, this isn't possible, because it would +//! result in a self-referential data structure, which Rust doesn't +//! allow. To understand how this arises, consider a certificate `C`, +//! which contains a `ComponentBundle` `B`. If `B` contains a +//! reference to `C`, then `C` references itself, because `C` contains +//! `B`! +//! +//! ```text +//! Cert:[ Bundle:[ &Cert ] ] +//! ^ | +//! `------------' +//! ``` +//! +//! # Policy +//! +//! Although a `ComponentAmalgamation` contains the information +//! necessary to realize high-level OpenPGP functionality, components +//! can have multiple self signatures, and functions that consult the +//! binding signature need to determine the best one to use. There +//! are two main concerns here. +//! +//! First, we need to protect the user from forgeries. As attacks +//! improve, cryptographic algorithms that were once considered secure +//! now provide insufficient security margins. For instance, in 2007 +//! it was possible to find [MD5 collisions] using just a few seconds +//! of computing time on a desktop computer. Sequoia provides a +//! flexible mechanism, called [`Policy`] objects, that allow users to +//! implement this type of filtering: before a self signature is used, +//! a policy object is queried to determine whether the `Signature` +//! should be rejected. If so, then it is skipped. +//! +//! Second, we need an algorithm to determine the most appropriate +//! self signature. Obvious non-candidate self signatures are self +//! signatures whose creation time is in the future. We don't assume +//! that these self signatures are bad per se, but that they represent +//! a policy that should go into effect some time in the future. +//! +//! We extend this idea of a self signature representing a policy for +//! a certain period of time to all self signatures. In particular, +//! Sequoia takes the view that *a binding signature represents a +//! policy that is valid from its creation time until its expiry*. +//! Thus, when considering what self signature to use, we need a +//! reference time. Given the reference time, we then use the self +//! signature that was in effect at that time, i.e., the most recent, +//! non-expired, non-revoked self signature that was created at or +//! prior to the reference time. In other words, we ignore self +//! signatures created after the reference time. We take the position +//! that if the certificate holder wants a new policy to apply to +//! existing signatures, then the new self signature should be +//! backdated, and existing self signatures revoked, if necessary. +//! +//! Consider evaluating a signature over a document. Sequoia's +//! [streaming verifier] uses the signature's creation time as the +//! reference time. Thus, if the signature was created on June 9th, +//! 2011, then, when evaluating that signature, the streaming verifier +//! uses a self signature that was live at that time, since that was +//! the self signature that represented the signer's policy at the +//! time the signature over the document was created. +//! +//! A consequence of this approach is that even if the self signature +//! were considered expired at the time the signature was evaluated +//! (e.g., "now"), this fact doesn't invalidate the signature. That +//! is, a self siganture's lifetime does not impact a signature's +//! lifetime; a signature's lifetime is defined by its own creation +//! time and expiry. Similarly, a key's lifetime is defined by its +//! own creation time and expiry. +//! +//! This interpretation of lifetimes removes a major disadvantage that +//! comes with fast rotation of subkeys: if an implementation binds +//! the lifetime of signatures to the signing key, and the key +//! expires, then old signatures are considered invalid. Consider a +//! user who generates a new signature subkey each week, and sets it +//! to expire after exactly one week. If we use the policy that the +//! signature is only valid while the key *and* the self signature are +//! live, then if someone checks the signature a week after receiving +//! it, the signature will be considered invalid, because the key has +//! expired. The practical result is that all old messages from this +//! user will be considered invalid! Unfortunately, this will result +//! in users becoming accustomed to seeing invalid signatures, and +//! cause them to be less suspcious of them. +//! +//! Sequoia's low-level mechanisms support this interpretation of self +//! signatures, but they do *not* enforce it. It is still possible to +//! realize other policies using this low-level API. +//! +//! The possibility of abuse of this interpretation of signature +//! lifetimes is limited. If a key has been compromised, then the +//! right thing to do is to revoke it. Expiry doesn't help: the +//! attacker can simply create self-signatures that say whatever she +//! wants. Assuming the secret key material has not been compromised, +//! then an attacker could still reuse a message that would otherwise +//! be considered expired. However, the attacker will not be able to +//! change the signature's creation time, so, assuming a mail context +//! and MUAs that check that the time in the message's headers matches +//! the signature's creation time, the mails will appear old. +//! Further, this type of attack will be mitigated by the proposed +//! "[Intended Recipients]" subpacket, which more tightly binds the +//! message to its context. +//! +//! # [`ValidComponentAmalgamation`] +//! +//! Most operations need to query a `ComponentAmalgamation` for +//! multiple pieces of information. Accidentally using a different +//! `Policy` or a different reference time for one of the queries is +//! easy, especially when the queries are spread across multiple +//! functions. Further, using `None` for the reference time can +//! result in subtle timing bugs as each function translates it to the +//! current time on demand. In these cases, the correct approach +//! would be for the user of the library to get the current time at +//! the start of the operation. But, this is less convenient. +//! Finally, passing a `Policy` and a reference time to most function +//! calls clutters the code. +//! +//! To mitigate these issues, we have a separate data structure, +//! `ValidComponentAmalgamation`, which combines a +//! `ComponetAmalgamation`, a `Policy` and a reference time. It +//! implements methods that require a `Policy` and reference time, but +//! instead of requiring the caller to pass them in, it uses the ones +//! embedded in the data structure. Further, when the +//! `ValidComponentAmalgamation` constructor is passed `None` for the +//! reference time, it eagerly stores the current time, and uses that +//! for all operations. This approach elegantly solves all of the +//! aforementioned problems. +//! +//! # Lifetimes +//! +//! `ComponentAmalgamation` autoderefs to `ComponentBundle`. +//! Unfortunately, due to the definition of the [`Deref` trait], +//! `ComponentBundle` is assigned the same lifetime as +//! `ComponentAmalgamation`. However, it's lifetime is actually `'a`. +//! Particularly when using combinators like [`std::iter::map`], the +//! `ComponentBundle`'s lifetime is longer. Consider the following +//! code, which doesn't compile: +//! +//! ```compile_fail +//! # extern crate sequoia_openpgp as openpgp; +//! use openpgp::cert::prelude::*; +//! use openpgp::packet::prelude::*; +//! +//! # let (cert, _) = CertBuilder::new() +//! # .add_userid("Alice") +//! # .add_signing_subkey() +//! # .add_transport_encryption_subkey() +//! # .generate().unwrap(); +//! cert.userids() +//! .map(|ua| { +//! // Use auto deref to get the containing `&ComponentBundle`. +//! let b: &ComponentBundle<_> = &ua; +//! b +//! }) +//! .collect::<Vec<&UserID>>(); +//! ``` +//! +//! Compiling it results in the following error: +//! +//! > `b` returns a value referencing data owned by the current +//! > function +//! +//! This error occurs because the `Deref` trait says that the lifetime +//! of the target, i.e., `&ComponentBundle`, is bounded by `ua`'s +//! lifetime, whose lifetime is indeed limited to the closure. But, +//! `&ComponentBundle` is independent of `ua`; it is a copy of the +//! `ComponentAmalgamation`'s reference to the `ComponentBundle` whose +//! lifetime is `'a`! Unfortunately, this can't be expressed using +//! `Deref`. But, it can be done using separate methods as shown +//! below for the [`ComponentAmalgamation::component`] method: +//! +//! ``` +//! # extern crate sequoia_openpgp as openpgp; +//! use openpgp::cert::prelude::*; +//! use openpgp::packet::prelude::*; +//! +//! # let (cert, _) = CertBuilder::new() +//! # .add_userid("Alice") +//! # .add_signing_subkey() +//! # .add_transport_encryption_subkey() +//! # .generate().unwrap(); +//! cert.userids() +//! .map(|ua| { +//! // ua's lifetime is this closure. But `component()` +//! // returns a reference whose lifetime is that of +//! // `cert`. +//! ua.component() +//! }) +//! .collect::<Vec<&UserID>>(); +//! ``` +//! +//! [`ComponentBundle`]: ../bundle/index.html +//! [`Signature`]: ../../packet/signature/index.html +//! [`ComponentAmalgamation`]: struct.ComponentAmalgamation.html +//! [`Cert`]: ../index.html +//! [is supposed to]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3 +//! [`ValidComponentAmalgamation`]: struct.ValidComponentAmalgamation.html +//! [`std::iter::map`]: https://doc.rust-lang.org/std/iter/struct.Map.html +//! [MD5 collisions]: https://en.wikipedia.org/wiki/MD5 +//! [`Policy`]: ../../policy/index.html +//! [streaming verifier]: ../../parse/stream.html +//! [Intended Recipients]: https://www.ietf.org/id/draft-ietf-openpgp-rfc4880bis-09.html#name-intended-recipient-fingerpr +//! [signature expirations]: https://tools.ietf.org/html/rfc4880#section-5.2.3.10 +//! [`Deref` trait]: https://doc.rust-lang.org/stable/std/ops/trait.Deref.html +//! [`ComponentAmalgamation::component`]: struct.ComponentAmalgamation.html#method.component use std::time; use std::time::SystemTime; use std::clone::Clone; @@ -19,27 +226,92 @@ use std::clone::Clone; use crate::{ cert::prelude::*, Error, - packet::Signature, + packet::{ + Signature, + Unknown, + UserAttribute, + UserID, + }, Result, policy::Policy, types::{ + AEADAlgorithm, + CompressionAlgorithm, + Features, + HashAlgorithm, + KeyServerPreferences, RevocationKey, RevocationStatus, - KeyFlags, + SymmetricAlgorithm, }, }; -/// Applies a policy to an amalgamation. +mod iter; +pub use iter::{ + ComponentAmalgamationIter, + UnknownComponentAmalgamationIter, + UserAttributeAmalgamationIter, + UserIDAmalgamationIter, + ValidComponentAmalgamationIter, + ValidUserAttributeAmalgamationIter, + ValidUserIDAmalgamationIter, +}; + +pub mod key; + +/// Embeds a policy and a reference time in an amalgamation. +/// +/// This is used to turn a [`ComponentAmalgamation`] into a +/// [`ValidComponentAmalgamation`], and a [`KeyAmalgamation`] into a +/// [`ValidKeyAmalgamation`]. +/// +/// A certificate or a component is consider valid if: /// -/// Note: This trait is split off from the `Amalgamation` trait, to -/// reduce code duplication: it is often possible to provide blanket -/// implementations of `Amalgamation`, but the `ValidateAmalgamation` -/// trait can only be implemented on more concrete types. +/// - It has a self signature that is live at time `t`. +/// +/// - The policy considers it acceptable. +/// +/// - The certificate is valid. +/// +/// # Examples +/// +/// ``` +/// # extern crate sequoia_openpgp as openpgp; +/// use openpgp::cert::prelude::*; +/// use openpgp::policy::{Policy, StandardPolicy}; +/// +/// const POLICY: &dyn Policy = &StandardPolicy::new(); +/// +/// fn f(ua: UserIDAmalgamation) -> openpgp::Result<()> { +/// let ua = ua.with_policy(POLICY, None)?; +/// // ... +/// # Ok(()) +/// } +/// # fn main() -> openpgp::Result<()> { +/// # let (cert, _) = +/// # CertBuilder::general_purpose(None, Some("alice@example.org")) +/// # .generate()?; +/// # let ua = cert.userids().nth(0).expect("User IDs"); +/// # f(ua); +/// # Ok(()) +/// # } +/// ``` +/// +/// [`ComponentAmalgamation`]: struct.ComponentAmalgamation.html +/// [`ValidComponentAmalgamation`]: struct.ValidComponentAmalgamation.html +/// [`KeyAmalgamation`]: struct.KeyAmalgamation.html +/// [`ValidKeyAmalgamation`]: struct.ValidKeyAmalgamation.html pub trait ValidateAmalgamation<'a, C: 'a> { /// The type returned by `with_policy`. + /// + /// This is either a [`ValidComponentAmalgamation`] or + /// a [`ValidKeyAmalgamation`]. + /// + /// [`ValidComponentAmalgamation`]: struct.ValidComponentAmalgamation.html + /// [`ValidKeyAmalgamation`]: struct.ValidKeyAmalgamation.html type V; - /// Changes the amalgamation's policy. + /// Uses the specified `Policy` and reference time with the amalgamation. /// /// If `time` is `None`, the current time is used. fn with_policy<T>(self, policy: &'a dyn Policy, time: T) -> Result<Self::V> @@ -47,65 +319,55 @@ pub trait ValidateAmalgamation<'a, C: 'a> { Self: Sized; } -/// An amalgamation with a policy and a reference time. -/// -/// In a certain sense, a `ValidAmalgamation` provides a view of an -/// `Amalgamation` as it was at a particular time. That is, -/// signatures and components that are not valid at the reference -/// time, because they were created after the reference time, for -/// instance, are ignored. +/// Applies a policy to an amalgamation. /// -/// The methods exposed by a `ValidAmalgamation` are similar to those -/// exposed by an `Amalgamation`, but the policy and reference time -/// are taken from the `ValidAmalgamation`. This helps prevent using -/// different policies or different reference times when using a -/// component, which can easily happen when the checks span multiple -/// functions. -pub trait ValidAmalgamation<'a, C: 'a> -{ - /// Returns the certificate. - fn cert(&self) -> &'a Cert; +/// This is an internal variant of `ValidateAmalgamation`, which +/// allows validating a component for an otherwise invalid +/// certificate. See `ValidComponentAmalgamation::primary` for an +/// explanation. +trait ValidateAmalgamationRelaxed<'a, C: 'a> { + /// The type returned by `with_policy`. + type V; - /// Returns the amalgamation's reference time. + /// Changes the amalgamation's policy. /// - /// For queries that are with respect to a point in time, this - /// determines that point in time. For instance, if a component is - /// created at `t_c` and expires at `t_e`, then - /// `ValidComponentAmalgamation::alive` will return true if the reference - /// 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; - - /// Returns the component's binding signature as of the reference time. - fn binding_signature(&self) -> &'a Signature; - - /// Returns the Certificate's direct key signature as of the - /// reference time, if any. + /// If `time` is `None`, the current time is used. /// - /// Subpackets on direct key signatures apply to all components of - /// the certificate. - fn direct_key_signature(&self) -> Option<&'a Signature>; - - /// Returns the component's revocation status as of the amalgamation's - /// reference time. + /// If `valid_cert` is `false`, then this does not also check + /// whether the certificate is valid; it only checks whether the + /// component is valid. Normally, this should be `true`. This + /// option is only expose to allow breaking an infinite recursion: /// - /// Note: this does not return whether the certificate is valid. - fn revoked(&self) -> RevocationStatus<'a>; - - /// Returns the certificate's revocation status as of the - /// amalgamation's reference time. - fn cert_revoked(&self) -> RevocationStatus<'a> { - self.cert().revoked(self.policy(), self.time()) - } - - /// Returns whether the certificate is alive as of the - /// amalgamation's reference time. - fn cert_alive(&self) -> Result<()> { - self.cert().alive(self.policy(), self.time()) - } + /// - To check if a certificate is valid, we check if the + /// primary key is valid. + /// + /// - To check if the primary key is valid, we need the primary + /// key's self signature + /// + /// - To find the primary key's self signature, we need to find + /// the primary user id + /// + /// - To find the primary user id, we need to check if the user + /// id is valid. + /// + /// - To check if the user id is valid, we need to check that + /// the corresponding certificate is valid. + fn with_policy_relaxed<T>(self, policy: &'a dyn Policy, time: T, + valid_cert: bool) -> Result<Self::V> + where T: Into<Option<time::SystemTime>>, + Self: Sized; +} +/// Methods for valid amalgamations. +/// +/// The methods exposed by a `ValidComponentAmalgamation` are similar +/// to those exposed by a `ComponentAmalgamation`, but the policy and +/// reference time are included in the `ValidComponentAmalgamation`. +/// This helps prevent using different policies or different reference +/// times when using a component, which can easily happen when the +/// checks span multiple functions. +pub trait ValidAmalgamation<'a, C: 'a> +{ /// Maps the given function over binding and direct key signature. /// /// Makes `f` consider both the binding signature and the direct @@ -116,132 +378,279 @@ pub trait ValidAmalgamation<'a, C: 'a> /// [Section 5.2.3.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3 fn map<F: Fn(&'a Signature) -> Option<T>, T>(&self, f: F) -> Option<T> { f(self.binding_signature()) - .or_else(|| self.direct_key_signature().and_then(f)) + .or_else(|| self.direct_key_signature().ok().and_then(f)) } - /// Returns the key's key flags as of the amalgamation's - /// reference time. + /// Returns the valid amalgamation's associated certificate. /// - /// Considers both the binding signature and the direct key - /// signature. Information in the binding signature takes - /// precedence over the direct key signature. See also [Section - /// 5.2.3.3 of RFC 4880]. + /// # Examples /// - /// [Section 5.2.3.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3 - fn key_flags(&self) -> Option<KeyFlags> { - self.map(|s| s.key_flags()) - } + /// ``` + /// # extern crate sequoia_openpgp as openpgp; + /// # use openpgp::cert::prelude::*; + /// # use openpgp::policy::StandardPolicy; + /// # + /// fn f(ua: &ValidUserIDAmalgamation) { + /// let cert = ua.cert(); + /// // ... + /// } + /// # fn main() -> openpgp::Result<()> { + /// # let p = &StandardPolicy::new(); + /// # let (cert, _) = + /// # CertBuilder::general_purpose(None, Some("alice@example.org")) + /// # .generate()?; + /// # let fpr = cert.fingerprint(); + /// # let ua = cert.userids().nth(0).expect("User IDs"); + /// # assert_eq!(ua.cert().fingerprint(), fpr); + /// # f(&ua.with_policy(p, None)?); + /// # Ok(()) + /// # } + /// ``` + fn cert(&self) -> &ValidCert<'a>; - /// Returns whether the key has at least one of the specified key - /// flags as of the amalgamation's reference time. + /// Returns the amalgamation's reference time. /// - /// Key flags are computed as described in - /// [`key_flags()`](#method.key_flags). - fn has_any_key_flag<F>(&self, flags: F) -> bool - where F: Borrow<KeyFlags> - { - let our_flags = self.key_flags().unwrap_or_default(); - !(&our_flags & flags.borrow()).is_empty() - } - - /// Returns whether key is certification capable as of the - /// amalgamtion's reference time. + /// # Examples /// - /// Key flags are computed as described in - /// [`key_flags()`](#method.key_flags). - fn for_certification(&self) -> bool { - self.has_any_key_flag(KeyFlags::default().set_certification(true)) - } + /// ``` + /// # use std::time::{SystemTime, Duration, UNIX_EPOCH}; + /// # + /// # extern crate sequoia_openpgp as openpgp; + /// # use openpgp::cert::prelude::*; + /// # use openpgp::policy::StandardPolicy; + /// fn f(ua: &ValidUserIDAmalgamation) { + /// let t = ua.time(); + /// // ... + /// } + /// # fn main() -> openpgp::Result<()> { + /// # let p = &StandardPolicy::new(); + /// # let t = UNIX_EPOCH + Duration::from_secs(1554542220); + /// # let (cert, _) = + /// # CertBuilder::general_purpose(None, Some("alice@example.org")) + /// # .set_creation_time(t) + /// # .generate()?; + /// # let ua = cert.userids().nth(0).expect("User IDs"); + /// # let ua = ua.with_policy(p, t)?; + /// # assert_eq!(t, ua.time()); + /// # f(&ua); + /// # Ok(()) + /// # } + /// ``` + fn time(&self) -> SystemTime; - /// Returns whether key is signing capable as of the amalgamation's - /// reference time. + /// Returns the amalgamation's policy. /// - /// Key flags are computed as described in - /// [`key_flags()`](#method.key_flags). - fn for_signing(&self) -> bool { - self.has_any_key_flag(KeyFlags::default().set_signing(true)) - } - - /// Returns whether key is authentication capable as of the - /// amalgamation's reference time. + /// # Examples /// - /// Key flags are computed as described in - /// [`key_flags()`](#method.key_flags). - fn for_authentication(&self) -> bool - { - self.has_any_key_flag(KeyFlags::default().set_authentication(true)) - } + /// ``` + /// # extern crate sequoia_openpgp as openpgp; + /// # use openpgp::cert::prelude::*; + /// # use openpgp::policy::{Policy, StandardPolicy}; + /// # + /// fn f(ua: &ValidUserIDAmalgamation) { + /// let policy = ua.policy(); + /// // ... + /// } + /// # fn main() -> openpgp::Result<()> { + /// # let p: &dyn Policy = &StandardPolicy::new(); + /// # let (cert, _) = + /// # CertBuilder::general_purpose(None, Some("alice@example.org")) + /// # .generate()?; + /// # let ua = cert.userids().nth(0).expect("User IDs"); + /// # let ua = ua.with_policy(p, None)?; + /// # assert!(std::ptr::eq(p, ua.policy())); + /// # f(&ua); + /// # Ok(()) + /// # } + /// ``` + fn policy(&self) -> &'a dyn Policy; - /// Returns whether key is intended for storage encryption as of - /// the amalgamation's reference time. + /// Returns the component's binding signature as of the reference time. /// - /// Key flags are computed as described in - /// [`key_flags()`](#method.key_flags). - fn for_storage_encryption(&self) -> bool - { - self.has_any_key_flag(KeyFlags::default().set_storage_encryption(true)) - } - - /// Returns whether key is intended for transport encryption as of the - /// amalgamtion's reference time. + /// # Examples /// - /// Key flags are computed as described in - /// [`key_flags()`](#method.key_flags). - fn for_transport_encryption(&self) -> bool - { - self.has_any_key_flag(KeyFlags::default().set_transport_encryption(true)) - } + /// ``` + /// # extern crate sequoia_openpgp as openpgp; + /// # use openpgp::cert::prelude: |