diff options
Diffstat (limited to 'openpgp/src/cert/amalgamation.rs')
-rw-r--r-- | openpgp/src/cert/amalgamation.rs | 323 |
1 files changed, 187 insertions, 136 deletions
diff --git a/openpgp/src/cert/amalgamation.rs b/openpgp/src/cert/amalgamation.rs index 29f1f4b4..71391761 100644 --- a/openpgp/src/cert/amalgamation.rs +++ b/openpgp/src/cert/amalgamation.rs @@ -127,91 +127,6 @@ trait ValidateAmalgamationRelaxed<'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. -/// -/// 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) -> &ValidCert<'a>; - - /// Returns the amalgamation's reference time. - /// - /// 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. - /// - /// Subpackets on direct key signatures apply to all components of - /// the certificate. - fn direct_key_signature(&self) -> Result<&'a Signature> { - self.cert().cert.primary.binding_signature(self.policy(), self.time()) - } - - - /// Returns the component's revocation status as of the amalgamation's - /// reference time. - /// - /// Note: this does not return whether the certificate is valid. - fn revoked(&self) -> RevocationStatus<'a>; - - /// Maps the given function over binding and direct key signature. - /// - /// Makes `f` consider 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]. - /// - /// [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().ok().and_then(f)) - } - - /// Returns the value of the Revocation Key subpacket, which - /// contains a designated revoker. - /// - /// Considers both the binding signature and the direct key - /// signature. - fn revocation_keys(&self) - -> Box<dyn Iterator<Item = &'a RevocationKey> + 'a> - { - if let Some(dk) = self.direct_key_signature().ok() { - let bs = self.binding_signature(); - if std::ptr::eq(dk, bs) { - // Avoid unnecessary duplicates. - Box::new(bs.revocation_keys()) - } else { - Box::new(bs.revocation_keys().chain(dk.revocation_keys())) - } - } else { - Box::new(self.binding_signature().revocation_keys()) - } - } -} - /// A certificate's component and its associated data. #[derive(Debug, PartialEq)] pub struct ComponentAmalgamation<'a, C, E> { @@ -388,6 +303,12 @@ impl<'a, C, E> ComponentAmalgamation<'a, C, E> { self.bundle().component() } + /// Returns a reference to the `ComponentAmalgamation`'s extra + /// data. + pub(crate) fn extra(&self) -> &E { + &self.extra + } + /// The component's self-signatures. /// /// This method is a forwarder for @@ -451,6 +372,8 @@ impl<'a, C, E> ComponentAmalgamation<'a, C, E> { } } +// We can't provide a blanket implementation, because the +// implementation for KeyAmalgamation is different. macro_rules! impl_with_policy { ($func:ident, $value:ident $(, $arg:ident: $type:ty )*) => { fn $func<T>(self, policy: &'a dyn Policy, time: T, $($arg: $type, )*) @@ -483,14 +406,30 @@ macro_rules! impl_with_policy { } } -impl<'a, C, E> ValidateAmalgamation<'a, C> for ComponentAmalgamation<'a, C, E> { - type V = ValidComponentAmalgamation<'a, C, E>; +impl<'a> ValidateAmalgamation<'a, UserID> for UserIDAmalgamation<'a> { + type V = ValidUserIDAmalgamation<'a>; impl_with_policy!(with_policy, true); } -impl<'a, C, E> ValidateAmalgamationRelaxed<'a, C> for ComponentAmalgamation<'a, C, E> { - type V = ValidComponentAmalgamation<'a, C, E>; +impl<'a> ValidateAmalgamationRelaxed<'a, UserID> for UserIDAmalgamation<'a> { + type V = ValidUserIDAmalgamation<'a>; + + impl_with_policy!(with_policy_relaxed, valid_cert, valid_cert: bool); +} + +impl<'a> ValidateAmalgamation<'a, UserAttribute> + for UserAttributeAmalgamation<'a> +{ + type V = ValidUserAttributeAmalgamation<'a>; + + impl_with_policy!(with_policy, true); +} + +impl<'a> ValidateAmalgamationRelaxed<'a, UserAttribute> + for UserAttributeAmalgamation<'a> +{ + type V = ValidUserAttributeAmalgamation<'a>; impl_with_policy!(with_policy_relaxed, valid_cert, valid_cert: bool); } @@ -505,18 +444,25 @@ impl<'a, C, E> ComponentAmalgamation<'a, C, E> { extra, } } +} - /// Returns the components's binding signature as of the reference - /// time, if any. - /// - /// Note: this function is not exported. Users of this interface - /// should do: ca.with_policy(policy, time)?.binding_signature(). - fn binding_signature<T>(&self, policy: &dyn Policy, time: T) - -> Result<&'a Signature> - where T: Into<Option<time::SystemTime>> - { - let time = time.into().unwrap_or_else(SystemTime::now); - self.bundle.binding_signature(policy, time) +// We can't do a blanket implementation, because the implementation +// for the primary key is different. +macro_rules! impl_binding_signature { + () => { + /// Returns the components's binding signature as of the + /// reference time, if any. + /// + /// Note: this function is not exported. Users of this + /// interface should do: ca.with_policy(policy, + /// time)?.binding_signature(). + fn binding_signature<T>(&self, policy: &dyn Policy, time: T) + -> Result<&'a Signature> + where T: Into<Option<time::SystemTime>> + { + let time = time.into().unwrap_or_else(SystemTime::now); + self.bundle.binding_signature(policy, time) + } } } @@ -525,6 +471,8 @@ impl<'a> UserIDAmalgamation<'a> { pub fn userid(&self) -> &'a UserID { self.component() } + + impl_binding_signature!(); } impl<'a> UserAttributeAmalgamation<'a> { @@ -532,6 +480,17 @@ impl<'a> UserAttributeAmalgamation<'a> { pub fn user_attribute(&self) -> &'a UserAttribute { self.component() } + + impl_binding_signature!(); +} + +impl<'a> UnknownComponentAmalgamation<'a> { + /// Returns a reference to the Unknown component. + pub fn unknown(&self) -> &'a Unknown { + self.component() + } + + impl_binding_signature!(); } /// A certificate's component and its associated data. @@ -595,8 +554,123 @@ impl<'a, C: 'a, E> From<ValidComponentAmalgamation<'a, C, E>> } } +impl<'a, C, E> ValidComponentAmalgamation<'a, C, E> +{ + /// Returns the wrapped `ComponentAmalgamation`. + pub(crate) fn into_component_amalgamation(self) + -> ComponentAmalgamation<'a, C, E> + { + self.ca + } + + /// Returns a reference to the wrapped `ComponentAmalgamation`. + pub(crate) fn component_amalgamation(&self) + -> &ComponentAmalgamation<'a, C, E> + { + &self.ca + } + + /// Returns the certificate. + pub fn cert(&self) -> &ValidCert<'a> { + assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); + &self.cert + } + + /// Returns the amalgamation's reference time. + /// + /// 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`. + pub fn time(&self) -> SystemTime { + assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); + self.cert.time + } + + /// Returns the amalgamation's policy. + pub fn policy(&self) -> &'a dyn Policy + { + assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); + self.cert.policy + } + + /// Returns the component's binding signature as of the reference time. + pub fn binding_signature(&self) -> &'a Signature { + assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); + self.binding_signature + } + + /// Returns the Certificate's direct key signature as of the + /// reference time, if any. + /// + /// Subpackets on direct key signatures apply to all components of + /// the certificate. + pub fn direct_key_signature(&self) -> Result<&'a Signature> { + self.cert().cert.primary.binding_signature(self.policy(), self.time()) + } + + /// Maps the given function over binding and direct key signature. + /// + /// Makes `f` consider 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]. + /// + /// [Section 5.2.3.3 of RFC 4880]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3 + pub fn map<F: Fn(&'a Signature) -> Option<T>, T>(&self, f: F) -> Option<T> { + f(self.binding_signature()) + .or_else(|| self.direct_key_signature().ok().and_then(f)) + } + + /// Returns the value of the Revocation Key subpacket, which + /// contains a designated revoker. + /// + /// Considers both the binding signature and the direct key + /// signature. + pub fn revocation_keys(&self) + -> Box<dyn Iterator<Item = &'a RevocationKey> + 'a> + { + if let Some(dk) = self.direct_key_signature().ok() { + let bs = self.binding_signature(); + if std::ptr::eq(dk, bs) { + // Avoid unnecessary duplicates. + Box::new(bs.revocation_keys()) + } else { + Box::new(bs.revocation_keys().chain(dk.revocation_keys())) + } + } else { + Box::new(self.binding_signature().revocation_keys()) + } + } +} + +impl<'a> ValidUserIDAmalgamation<'a> { + /// Returns the component's revocation status as of the amalgamation's + /// reference time. + /// + /// Note: this does not return whether the certificate is valid. + pub fn revoked(&self) -> RevocationStatus<'a> { + self.bundle._revoked(self.policy(), self.cert.time, + false, Some(self.binding_signature)) + } +} + +impl<'a> ValidUserAttributeAmalgamation<'a> { + /// Returns the component's revocation status as of the amalgamation's + /// reference time. + /// + /// Note: this does not return whether the certificate is valid. + pub fn revoked(&self) -> RevocationStatus<'a> { + self.bundle._revoked(self.policy(), self.cert.time, + false, Some(self.binding_signature)) + } +} + impl<'a, C> ValidComponentAmalgamation<'a, C, ()> - where C: Ord + where C: Ord, + C: 'a, + ComponentAmalgamation<'a, C, ()>: ValidateAmalgamationRelaxed<'a, C, V=Self>, { /// Returns the amalgamated primary component at time `time` /// @@ -711,6 +785,7 @@ impl<'a, C> ValidComponentAmalgamation<'a, C, ()> impl<'a, C, E> ValidateAmalgamation<'a, C> for ValidComponentAmalgamation<'a, C, E> + where ComponentAmalgamation<'a, C, E>: ValidateAmalgamation<'a, C, V=Self> { type V = Self; @@ -721,50 +796,26 @@ impl<'a, C, E> ValidateAmalgamation<'a, C> assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); let time = time.into().unwrap_or_else(SystemTime::now); - self.ca.with_policy(policy, time) + self.component_amalgamation().with_policy(policy, time) } } -impl<'a, C, E> ValidAmalgamation<'a, C> +impl<'a, C, E> ValidateAmalgamationRelaxed<'a, C> for ValidComponentAmalgamation<'a, C, E> + where ComponentAmalgamation<'a, C, E>: ValidateAmalgamationRelaxed<'a, C, V=Self> { - fn cert(&self) -> &ValidCert<'a> { - assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); - &self.cert - } - - /// Returns the amalgamation's reference time. - /// - /// 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 { - assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); - self.cert.time - } + type V = Self; - /// Returns the amalgamation's policy. - fn policy(&self) -> &'a dyn Policy + 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, { assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); - self.cert.policy - } - /// Returns the component's binding signature as of the reference time. - fn binding_signature(&self) -> &'a Signature { - assert!(std::ptr::eq(self.ca.cert(), self.cert.cert())); - self.binding_signature - } - - /// Returns the component's revocation status as of the amalgamation's - /// reference time. - /// - /// Note: this does not return whether the certificate is valid. - fn revoked(&self) -> RevocationStatus<'a> { - self.bundle._revoked(self.policy(), self.cert.time, - false, Some(self.binding_signature)) + let time = time.into().unwrap_or_else(SystemTime::now); + self.component_amalgamation() + .with_policy_relaxed(policy, time, valid_cert) } } |