1 //! A certificate component and its associated signatures.
2 //!
3 //! Certificates ([`Cert`]s) are a collection of components where each
4 //! component corresponds to a [`Packet`], and each component has zero
5 //! or more associated [`Signature`]s.  A [`ComponentBundle`]
6 //! encapsulates a component and its associated signatures.
7 //!
8 //! Sequoia supports four different kinds of components: [`Key`]s,
9 //! [`UserID`]s, [`UserAttribute`]s, and [`Unknown`] components.  The
10 //! `Unknown` component has two purposes.  First, it is used to store
11 //! packets that appear in a certificate and have an unknown [`Tag`].
12 //! By not silently dropping these packets, it is possible to round
13 //! trip certificates without losing any information.  This provides a
14 //! measure of future compatibility.  Second, the `Unknown` component
15 //! is used to store unsupported components.  For instance, Sequoia
16 //! doesn't support v3 `Key`s, which are deprecated, or v5 `Key`s,
17 //! which are still being standardized.  Because these keys are
18 //! effectively unusable, they are stored as `Unknown` components
19 //! instead of `Key`s.
20 //!
21 //! There are four types of signatures associated with a component:
22 //! self signatures, self revocations, third-party signatures, and
23 //! third-party revocations.  When parsing a certificate, self
24 //! signatures and self revocations are checked for validity and
25 //! invalid signatures and revocations are discarded.  Since the keys
26 //! are not normally available, third-party signatures and third-party
27 //! revocations cannot be rigorously (i.e., cryptographically) checked
28 //! for validity.
29 //!
30 //! With the exception of the primary key, a component's self
31 //! signatures are binding signatures.  A binding signature firstly
32 //! binds the component to the certificate.  That is, it provides
33 //! cryptographic evidence that the certificate holder intended for
34 //! the component to be associated with the certificate.  Binding
35 //! signatures also provide information about the component.  For
36 //! instance, the binding signature for a subkey includes its
37 //! capabilities, and its expiry time.
38 //!
39 //! Since the primary key is the embodiment of the certificate, there
40 //! is nothing to bind it to.  Correspondingly, self signatures on a
41 //! primary key are called direct key signatures.  Direct key
42 //! signatures are used to provide information about the whole
43 //! certificate.  For instance, they can include the default `Key`
44 //! expiry time.  This is used if a subkey's binding signature doesn't
45 //! include a expiry.
46 //!
47 //! Self-revocations are revocation certificates issued by the key
48 //! certificate holder.
49 //!
50 //! Third-party signatures are typically signatures certifying that a
51 //! `User ID` or `User Attribute` accurately describes the certificate
52 //! holder.  This information is used by trust models, like the Web of
53 //! Trust, to indirectly authenticate keys.
54 //!
55 //! Third-party revocations are revocations issued by another
56 //! certificate.  They should normally only be respected if the
57 //! certificate holder made the issuer a so-called [designated
58 //! revoker].
59 //!
60 //! # Important
61 //!
62 //! When looking up information about a component, it is generally
63 //! better to use the [`ComponentAmalgamation`] or [`KeyAmalgamation`]
64 //! data structures.  These data structures provide convenience
65 //! methods that implement the [complicated semantics] for correctly
66 //! locating information.
67 //!
68 //! [`Cert`]: ../index.html
69 //! [`Packet`]: ../../packet/index.html
70 //! [`Signature`]: ../../packet/signature/index.html
71 //! [`ComponentBundle`]: ./struct.ComponentBundle.html
72 //! [`Key`]: ../../packet/key/index.html
73 //! [`UserID`]: ../../packet/struct.UserID.html
74 //! [`UserAttribute`]: ../../packet/user_attribute/index.html
75 //! [`Unknown`]: ../../packet/struct.Unknown.html
76 //! [`Tag`]: ../../packet/enum.Tag.html
77 //! [designated revoker]: https://tools.ietf.org/html/rfc4880#section-5.2.3.15
78 //! [`ComponentAmalgamation`]: ../amalgamation/index.html
79 //! [`KeyAmalgamation`]: ../key_amalgamation/index.html
80 //! [complicated semantics]: https://tools.ietf.org/html/rfc4880#section-5.2.3.3
81 
82 use std::time;
83 use std::ops::Deref;
84 
85 use crate::{
86     Error,
87     packet::Signature,
88     packet::Key,
89     packet::key,
90     packet::UserID,
91     packet::UserAttribute,
92     packet::Unknown,
93     Packet,
94     policy::Policy,
95     Result,
96 };
97 use crate::types::{
98     RevocationType,
99     RevocationStatus,
100 };
101 
102 use super::{
103     sig_cmp,
104     canonical_signature_order,
105 };
106 
107 /// A certificate component and its associated signatures.
108 ///
109 /// [See the module level documentation]](index.html) for a detailed
110 /// description.
111 #[derive(Debug, Clone, PartialEq)]
112 pub struct ComponentBundle<C> {
113     pub(crate) component: C,
114 
115     // Self signatures.
116     pub(crate) self_signatures: Vec<Signature>,
117 
118     // Third-party certifications.  (In general, this will only be by
119     // designated revokers.)
120     pub(crate) certifications: Vec<Signature>,
121 
122     // Self revocations.
123     pub(crate) self_revocations: Vec<Signature>,
124 
125     // Third-party revocations (e.g., designated revokers).
126     pub(crate) other_revocations: Vec<Signature>,
127 }
128 
129 /// A key (primary or subkey, public or private) and any associated
130 /// signatures.
131 ///
132 /// [See the module level documentation.](index.html)
133 pub type KeyBundle<KeyPart, KeyRole> = ComponentBundle<Key<KeyPart, KeyRole>>;
134 
135 /// A primary key and any associated signatures.
136 ///
137 /// [See the module level documentation.](index.html)
138 pub type PrimaryKeyBundle<KeyPart> =
139     KeyBundle<KeyPart, key::PrimaryRole>;
140 
141 /// A subkey and any associated signatures.
142 ///
143 /// [See the module level documentation.](index.html)
144 pub type SubkeyBundle<KeyPart>
145     = KeyBundle<KeyPart, key::SubordinateRole>;
146 
147 /// A User ID and any associated signatures.
148 ///
149 /// [See the module level documentation.](index.html)
150 pub type UserIDBundle = ComponentBundle<UserID>;
151 
152 /// A User Attribute and any associated signatures.
153 ///
154 /// [See the module level documentation.](index.html)
155 pub type UserAttributeBundle = ComponentBundle<UserAttribute>;
156 
157 /// An unknown component and any associated signatures.
158 ///
159 /// Note: all signatures are stored as certifications.
160 ///
161 /// [See the module level documentation.](index.html)
162 pub type UnknownBundle = ComponentBundle<Unknown>;
163 
164 
165 impl<C> Deref for ComponentBundle<C>
166 {
167     type Target = C;
168 
deref(&self) -> &Self::Target169     fn deref(&self) -> &Self::Target {
170         &self.component
171     }
172 }
173 
174 impl<C> ComponentBundle<C> {
175     /// Returns a reference to the bundle's component.
176     ///
177     /// # Examples
178     ///
179     /// ```
180     /// # extern crate sequoia_openpgp as openpgp;
181     /// # use openpgp::cert::prelude::*;
182     /// #
183     /// # fn main() -> openpgp::Result<()> {
184     /// # let (cert, _) =
185     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
186     /// #     .generate()?;
187     /// // Display some information about any unknown components.
188     /// for u in cert.unknowns() {
189     ///     eprintln!(" - {:?}", u.component());
190     /// }
191     /// # Ok(()) }
192     /// ```
component(&self) -> &C193     pub fn component(&self) -> &C {
194         &self.component
195     }
196 
197     /// Returns a mutable reference to the component.
component_mut(&mut self) -> &mut C198     fn component_mut(&mut self) -> &mut C {
199         &mut self.component
200     }
201 
202     /// Returns the active binding signature at time `t`.
203     ///
204     /// The active binding signature is the most recent, non-revoked
205     /// self-signature that is valid according to the `policy` and
206     /// alive at time `t` (`creation time <= t`, `t < expiry`).  If
207     /// there are multiple such signatures then the signatures are
208     /// ordered by their MPIs interpreted as byte strings.
209     ///
210     /// # Examples
211     ///
212     /// ```
213     /// # extern crate sequoia_openpgp as openpgp;
214     /// # use openpgp::cert::prelude::*;
215     /// use openpgp::policy::StandardPolicy;
216     /// #
217     /// # fn main() -> openpgp::Result<()> {
218     /// let p = &StandardPolicy::new();
219     ///
220     /// # let (cert, _) =
221     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
222     /// #     .generate()?;
223     /// // Display information about each User ID's current active
224     /// // binding signature (the `time` parameter is `None`), if any.
225     /// for ua in cert.userids() {
226     ///     eprintln!("{:?}", ua.binding_signature(p, None));
227     /// }
228     /// # Ok(()) }
229     /// ```
binding_signature<T>(&self, policy: &dyn Policy, t: T) -> Result<&Signature> where T: Into<Option<time::SystemTime>>230     pub fn binding_signature<T>(&self, policy: &dyn Policy, t: T)
231                                 -> Result<&Signature>
232         where T: Into<Option<time::SystemTime>>
233     {
234         let t = t.into().unwrap_or_else(time::SystemTime::now);
235 
236         // Recall: the signatures are sorted by their creation time in
237         // descending order, i.e., newest first.
238         //
239         // We want the newest signature that is older than t.  So,
240         // search for `t`.
241 
242         let i =
243             // Usually, the first signature is what we are looking for.
244             // Short circuit the binary search.
245             if Some(t) >= self.self_signatures.get(0)
246                               .and_then(|s| s.signature_creation_time())
247             {
248                 0
249             } else {
250                 match self.self_signatures.binary_search_by(
251                     |s| canonical_signature_order(
252                         s.signature_creation_time(), Some(t)))
253                 {
254                     // If there are multiple matches, then we need to search
255                     // backwards to find the first one.  Consider:
256                     //
257                     //     t: 9 8 8 8 8 7
258                     //     i: 0 1 2 3 4 5
259                     //
260                     // If we are looking for t == 8, then binary_search could
261                     // return index 1, 2, 3 or 4.
262                     Ok(mut i) => {
263                         while i > 0
264                             && self.self_signatures[i - 1].signature_creation_time()
265                             == Some(t)
266                         {
267                             i -= 1;
268                         }
269                         i
270                     }
271 
272                     // There was no match.  `i` is where a new element could
273                     // be inserted while maintaining the sorted order.
274                     // Consider:
275                     //
276                     //    t: 9 8 6 5
277                     //    i: 0 1 2 3
278                     //
279                     // If we are looing for t == 7, then binary_search will
280                     // return i == 2.  That's exactly where we should start
281                     // looking.
282                     Err(i) => i,
283                 }
284             };
285 
286         let mut sig = None;
287 
288         // Prefer the first error, which is the error arising from the
289         // most recent binding signature that wasn't created after
290         // `t`.
291         let mut error = None;
292 
293         for s in self.self_signatures[i..].iter() {
294             if let Err(e) = s.signature_alive(t, time::Duration::new(0, 0)) {
295                 // We know that t >= signature's creation time.  So,
296                 // it is expired.  But an older signature might not
297                 // be.  So, keep trying.
298                 if error.is_none() {
299                     error = Some(e);
300                 }
301                 continue;
302             }
303 
304             if let Err(e) = policy.signature(s) {
305                 if error.is_none() {
306                     error = Some(e);
307                 }
308                 continue;
309             }
310 
311             // The signature is good, but we may still need to verify the
312             // back sig.
313             if s.typ() == crate::types::SignatureType::SubkeyBinding &&
314                 s.key_flags().map(|kf| kf.for_signing()).unwrap_or(false)
315             {
316                 if let Some(backsig) = s.embedded_signature() {
317                     if let Err(e) = backsig.signature_alive(
318                         t, time::Duration::new(0, 0))
319                     {
320                         // The primary key binding signature is not
321                         // alive.
322                         if error.is_none() {
323                             error = Some(e);
324                         }
325                         continue;
326                     }
327 
328                     if let Err(e) = policy.signature(backsig) {
329                         if error.is_none() {
330                             error = Some(e);
331                         }
332                         continue;
333                     }
334                 } else {
335                     // This shouldn't happen because
336                     // Signature::verify_subkey_binding checks for the
337                     // primary key signature.  But, better be safe.
338                     if error.is_none() {
339                         error = Some(Error::BadSignature(
340                             "Primary key binding signature missing".into())
341                                      .into());
342                     }
343                     continue;
344                 }
345             }
346 
347             sig = Some(s);
348             break;
349         }
350 
351         if let Some(sig) = sig {
352             Ok(sig)
353         } else if let Some(err) = error {
354             Err(err)
355         } else {
356             Err(Error::NoBindingSignature(t).into())
357         }
358     }
359 
360     /// Returns the component's self-signatures.
361     ///
362     /// The signatures are validated, and they are sorted by their
363     /// creation time, most recent first.
364     ///
365     /// # Examples
366     ///
367     /// ```
368     /// # extern crate sequoia_openpgp as openpgp;
369     /// # use openpgp::cert::prelude::*;
370     /// use openpgp::policy::StandardPolicy;
371     /// #
372     /// # fn main() -> openpgp::Result<()> {
373     /// let p = &StandardPolicy::new();
374     ///
375     /// # let (cert, _) =
376     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
377     /// #     .generate()?;
378     /// for (i, ka) in cert.keys().enumerate() {
379     ///     eprintln!("Key #{} ({}) has {:?} self signatures",
380     ///               i, ka.fingerprint(),
381     ///               ka.self_signatures().len());
382     /// }
383     /// # Ok(()) }
384     /// ```
self_signatures(&self) -> &[Signature]385     pub fn self_signatures(&self) -> &[Signature] {
386         &self.self_signatures
387     }
388 
389     /// Returns the component's third-party certifications.
390     ///
391     /// The signatures are *not* validated.  They are sorted by their
392     /// creation time, most recent first.
393     ///
394     /// # Examples
395     ///
396     /// ```
397     /// # extern crate sequoia_openpgp as openpgp;
398     /// # use openpgp::cert::prelude::*;
399     /// use openpgp::policy::StandardPolicy;
400     /// #
401     /// # fn main() -> openpgp::Result<()> {
402     /// let p = &StandardPolicy::new();
403     ///
404     /// # let (cert, _) =
405     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
406     /// #     .generate()?;
407     /// for ua in cert.userids() {
408     ///     eprintln!("User ID {} has {:?} unverified, third-party certifications",
409     ///               String::from_utf8_lossy(ua.userid().value()),
410     ///               ua.certifications().len());
411     /// }
412     /// # Ok(()) }
413     /// ```
certifications(&self) -> &[Signature]414     pub fn certifications(&self) -> &[Signature] {
415         &self.certifications
416     }
417 
418     /// Returns the component's revocations that were issued by the
419     /// certificate holder.
420     ///
421     /// The revocations are validated, and they are sorted by their
422     /// creation time, most recent first.
423     ///
424     /// # Examples
425     ///
426     /// ```
427     /// # extern crate sequoia_openpgp as openpgp;
428     /// # use openpgp::cert::prelude::*;
429     /// use openpgp::policy::StandardPolicy;
430     /// #
431     /// # fn main() -> openpgp::Result<()> {
432     /// let p = &StandardPolicy::new();
433     ///
434     /// # let (cert, _) =
435     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
436     /// #     .generate()?;
437     /// for u in cert.userids() {
438     ///     eprintln!("User ID {} has {:?} revocation certificates.",
439     ///               String::from_utf8_lossy(u.userid().value()),
440     ///               u.self_revocations().len());
441     /// }
442     /// # Ok(()) }
443     /// ```
self_revocations(&self) -> &[Signature]444     pub fn self_revocations(&self) -> &[Signature] {
445         &self.self_revocations
446     }
447 
448     /// Returns the component's revocations that were issued by other
449     /// certificates.
450     ///
451     /// The revocations are *not* validated.  They are sorted by their
452     /// creation time, most recent first.
453     ///
454     /// # Examples
455     ///
456     /// ```
457     /// # extern crate sequoia_openpgp as openpgp;
458     /// # use openpgp::cert::prelude::*;
459     /// use openpgp::policy::StandardPolicy;
460     /// #
461     /// # fn main() -> openpgp::Result<()> {
462     /// let p = &StandardPolicy::new();
463     ///
464     /// # let (cert, _) =
465     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
466     /// #     .generate()?;
467     /// for u in cert.userids() {
468     ///     eprintln!("User ID {} has {:?} unverified, third-party revocation certificates.",
469     ///               String::from_utf8_lossy(u.userid().value()),
470     ///               u.other_revocations().len());
471     /// }
472     /// # Ok(()) }
473     /// ```
other_revocations(&self) -> &[Signature]474     pub fn other_revocations(&self) -> &[Signature] {
475         &self.other_revocations
476     }
477 
478     /// Returns the component's revocation status at time `t`.
479     ///
480     /// A component is considered to be revoked at time `t` if:
481     ///
482     ///   - There is a live revocation at time `t` that is newer than
483     ///     all live self signatures at time `t`.
484     ///
485     ///   - `hard_revocations_are_final` is true, and there is a hard
486     ///     revocation (even if it is not yet live at time `t`, and
487     ///     even if there is a newer self-signature).
488     ///
489     /// selfsig must be the newest live self signature at time `t`.
_revocation_status<'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>>490     pub(crate) fn _revocation_status<'a, T>(&'a self, policy: &dyn Policy, t: T,
491                                             hard_revocations_are_final: bool,
492                                             selfsig: Option<&Signature>)
493         -> RevocationStatus<'a>
494         where T: Into<Option<time::SystemTime>>
495     {
496         // Fallback time.
497         let time_zero = || time::UNIX_EPOCH;
498         let t = t.into().unwrap_or_else(time::SystemTime::now);
499         let selfsig_creation_time
500             = selfsig.and_then(|s| s.signature_creation_time())
501                      .unwrap_or_else(time_zero);
502 
503         tracer!(super::TRACE, "ComponentBundle::_revocation_status", 0);
504         t!("hard_revocations_are_final: {}, selfsig: {:?}, t: {:?}",
505            hard_revocations_are_final,
506            selfsig_creation_time,
507            t);
508         if let Some(selfsig) = selfsig {
509             assert!(
510                 selfsig.signature_alive(t, time::Duration::new(0, 0)).is_ok());
511         }
512 
513         let check = |revs: &'a [Signature]| -> Option<Vec<&'a Signature>> {
514             let revs = revs.iter().filter_map(|rev| {
515                 if let Err(err) = policy.signature(rev) {
516                     t!("  revocation rejected by caller policy: {}", err);
517                     None
518                 } else if hard_revocations_are_final
519                     && rev.reason_for_revocation()
520                     .map(|(r, _)| {
521                         r.revocation_type() == RevocationType::Hard
522                     })
523                 // If there is no Reason for Revocation
524                 // packet, assume that it is a hard
525                 // revocation.
526                     .unwrap_or(true)
527                 {
528                     t!("  got a hard revocation: {:?}, {:?}",
529                        rev.signature_creation_time()
530                        .unwrap_or_else(time_zero),
531                        rev.reason_for_revocation()
532                        .map(|r| (r.0, String::from_utf8_lossy(r.1))));
533                     Some(rev)
534                 } else if selfsig_creation_time
535                     > rev.signature_creation_time().unwrap_or_else(time_zero)
536                 {
537                     // This comes after the hard revocation check,
538                     // because a hard revocation is always valid.
539                     t!("  newer binding signature trumps soft revocation ({:?} > {:?})",
540                        selfsig_creation_time,
541                        rev.signature_creation_time().unwrap_or_else(time_zero));
542                     None
543                 } else if let Err(err)
544                     = rev.signature_alive(t, time::Duration::new(0, 0))
545                 {
546                     // This comes after the hard revocation check,
547                     // because a hard revocation is always valid.
548                     t!("  revocation not alive ({:?} - {:?}): {}",
549                        rev.signature_creation_time().unwrap_or_else(time_zero),
550                        rev.signature_validity_period()
551                            .unwrap_or_else(|| time::Duration::new(0, 0)),
552                        err);
553                     None
554                 } else {
555                     t!("  got a revocation: {:?} ({:?})",
556                        rev.signature_creation_time().unwrap_or_else(time_zero),
557                        rev.reason_for_revocation()
558                            .map(|r| (r.0, String::from_utf8_lossy(r.1))));
559                     Some(rev)
560                 }
561             }).collect::<Vec<&Signature>>();
562 
563             if revs.len() == 0 {
564                 None
565             } else {
566                 Some(revs)
567             }
568         };
569 
570         if let Some(revs) = check(&self.self_revocations) {
571             RevocationStatus::Revoked(revs)
572         } else if let Some(revs) = check(&self.other_revocations) {
573             RevocationStatus::CouldBe(revs)
574         } else {
575             RevocationStatus::NotAsFarAsWeKnow
576         }
577     }
578 
579     /// Turns the `ComponentBundle` into an iterator over its
580     /// `Packet`s.
581     ///
582     /// The signatures are ordered as follows:
583     ///
584     ///   - Self revocations,
585     ///   - Self signatures,
586     ///   - Third-party signatures, and
587     ///   - Third-party revocations.
588     ///
589     /// For a given type of signature, the signatures are ordered by
590     /// their creation time, most recent first.
into_packets<'a>(self) -> impl Iterator<Item=Packet> where Packet: From<C>591     pub(crate) fn into_packets<'a>(self) -> impl Iterator<Item=Packet>
592         where Packet: From<C>
593     {
594         let p : Packet = self.component.into();
595         std::iter::once(p)
596             .chain(self.self_revocations.into_iter().map(|s| s.into()))
597             .chain(self.self_signatures.into_iter().map(|s| s.into()))
598             .chain(self.certifications.into_iter().map(|s| s.into()))
599             .chain(self.other_revocations.into_iter().map(|s| s.into()))
600     }
601 
602     // Sorts and dedups the binding's signatures.
603     //
604     // This function assumes that the signatures have already been
605     // cryptographically checked.
606     //
607     // Note: this uses Signature::eq to compare signatures.  That
608     // function ignores unhashed packets.  If there are two signatures
609     // that only differ in their unhashed subpackets, they will be
610     // deduped.  The unhashed areas are *not* merged; the one that is
611     // kept is undefined.
sort_and_dedup(&mut self)612     pub(crate) fn sort_and_dedup(&mut self)
613     {
614         self.self_signatures.sort_by(sig_cmp);
615         self.self_signatures.dedup();
616 
617         // There is no need to sort the certifications, but we do
618         // want to remove dups and sorting is a prerequisite.
619         self.certifications.sort_by(sig_cmp);
620         self.certifications.dedup();
621 
622         self.self_revocations.sort_by(sig_cmp);
623         self.self_revocations.dedup();
624 
625         self.other_revocations.sort_by(sig_cmp);
626         self.other_revocations.dedup();
627     }
628 }
629 
630 impl<P: key::KeyParts, R: key::KeyRole> ComponentBundle<Key<P, R>> {
631     /// Returns a reference to the key.
632     ///
633     /// This is just a type-specific alias for
634     /// [`ComponentBundle::component`].
635     ///
636     /// [`ComponentBundle::component`]: #method.component
637     ///
638     /// # Examples
639     ///
640     /// ```
641     /// # extern crate sequoia_openpgp as openpgp;
642     /// # use openpgp::cert::prelude::*;
643     /// #
644     /// # fn main() -> openpgp::Result<()> {
645     /// # let (cert, _) =
646     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
647     /// #     .generate()?;
648     /// // Display some information about the keys.
649     /// for ka in cert.keys() {
650     ///     eprintln!(" - {:?}", ka.key());
651     /// }
652     /// # Ok(()) }
653     /// ```
key(&self) -> &Key<P, R>654     pub fn key(&self) -> &Key<P, R> {
655         self.component()
656     }
657 
658     /// Returns a mut reference to the key.
key_mut(&mut self) -> &mut Key<P, R>659     pub(crate) fn key_mut(&mut self) -> &mut Key<P, R> {
660         self.component_mut()
661     }
662 }
663 
664 impl<P: key::KeyParts> ComponentBundle<Key<P, key::SubordinateRole>> {
665     /// Returns the subkey's revocation status at time `t`.
666     ///
667     /// A subkey is revoked at time `t` if:
668     ///
669     ///   - There is a live revocation at time `t` that is newer than
670     ///     all live self signatures at time `t`, or
671     ///
672     ///   - There is a hard revocation (even if it is not live at
673     ///     time `t`, and even if there is a newer self-signature).
674     ///
675     /// Note: Certs and subkeys have different criteria from User IDs
676     /// and User Attributes.
677     ///
678     /// Note: this only returns whether this subkey is revoked; it
679     /// does not imply anything about the Cert or other components.
680     ///
681     /// # Examples
682     ///
683     /// ```
684     /// # extern crate sequoia_openpgp as openpgp;
685     /// # use openpgp::cert::prelude::*;
686     /// use openpgp::policy::StandardPolicy;
687     /// #
688     /// # fn main() -> openpgp::Result<()> {
689     /// let p = &StandardPolicy::new();
690     ///
691     /// # let (cert, _) =
692     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
693     /// #     .generate()?;
694     /// // Display the subkeys' revocation status.
695     /// for ka in cert.keys().subkeys() {
696     ///     eprintln!(" Revocation status of {}: {:?}",
697     ///               ka.fingerprint(), ka.revocation_status(p, None));
698     /// }
699     /// # Ok(()) }
700     /// ```
revocation_status<T>(&self, policy: &dyn Policy, t: T) -> RevocationStatus where T: Into<Option<time::SystemTime>>701     pub fn revocation_status<T>(&self, policy: &dyn Policy, t: T)
702         -> RevocationStatus
703         where T: Into<Option<time::SystemTime>>
704     {
705         let t = t.into();
706         self._revocation_status(policy, t, true,
707                                 self.binding_signature(policy, t).ok())
708     }
709 }
710 
711 impl ComponentBundle<UserID> {
712     /// Returns a reference to the User ID.
713     ///
714     /// This is just a type-specific alias for
715     /// [`ComponentBundle::component`].
716     ///
717     /// [`ComponentBundle::component`]: #method.component
718     ///
719     /// # Examples
720     ///
721     /// ```
722     /// # extern crate sequoia_openpgp as openpgp;
723     /// # use openpgp::cert::prelude::*;
724     /// #
725     /// # fn main() -> openpgp::Result<()> {
726     /// # let (cert, _) =
727     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
728     /// #     .generate()?;
729     /// // Display some information about the User IDs.
730     /// for ua in cert.userids() {
731     ///     eprintln!(" - {:?}", ua.userid());
732     /// }
733     /// # Ok(()) }
734     /// ```
userid(&self) -> &UserID735     pub fn userid(&self) -> &UserID {
736         self.component()
737     }
738 
739     /// Returns the User ID's revocation status at time `t`.<a
740     /// name="userid_revocation_status"></a>
741     ///
742     /// <!-- Why we have the above anchor:
743     ///      https://github.com/rust-lang/rust/issues/71912 -->
744     ///
745     /// A User ID is revoked at time `t` if:
746     ///
747     ///   - There is a live revocation at time `t` that is newer than
748     ///     all live self signatures at time `t`.
749     ///
750     /// Note: Certs and subkeys have different criteria from User IDs
751     /// and User Attributes.
752     ///
753     /// Note: this only returns whether this User ID is revoked; it
754     /// does not imply anything about the Cert or other components.
755     //
756     /// # Examples
757     ///
758     /// ```
759     /// # extern crate sequoia_openpgp as openpgp;
760     /// # use openpgp::cert::prelude::*;
761     /// use openpgp::policy::StandardPolicy;
762     /// #
763     /// # fn main() -> openpgp::Result<()> {
764     /// let p = &StandardPolicy::new();
765     ///
766     /// # let (cert, _) =
767     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
768     /// #     .generate()?;
769     /// // Display the User IDs' revocation status.
770     /// for ua in cert.userids() {
771     ///     eprintln!(" Revocation status of {}: {:?}",
772     ///               String::from_utf8_lossy(ua.userid().value()),
773     ///               ua.revocation_status(p, None));
774     /// }
775     /// # Ok(()) }
776     /// ```
revocation_status<T>(&self, policy: &dyn Policy, t: T) -> RevocationStatus where T: Into<Option<time::SystemTime>>777     pub fn revocation_status<T>(&self, policy: &dyn Policy, t: T)
778         -> RevocationStatus
779         where T: Into<Option<time::SystemTime>>
780     {
781         let t = t.into();
782         self._revocation_status(policy, t, false, self.binding_signature(policy, t).ok())
783     }
784 }
785 
786 impl ComponentBundle<UserAttribute> {
787     /// Returns a reference to the User Attribute.
788     ///
789     /// This is just a type-specific alias for
790     /// [`ComponentBundle::component`].
791     ///
792     /// [`ComponentBundle::component`]: #method.component
793     ///
794     /// # Examples
795     ///
796     /// ```
797     /// # extern crate sequoia_openpgp as openpgp;
798     /// # use openpgp::cert::prelude::*;
799     /// #
800     /// # fn main() -> openpgp::Result<()> {
801     /// # let (cert, _) =
802     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
803     /// #     .generate()?;
804     /// // Display some information about the User Attributes
805     /// for ua in cert.user_attributes() {
806     ///     eprintln!(" - {:?}", ua.user_attribute());
807     /// }
808     /// # Ok(()) }
809     /// ```
user_attribute(&self) -> &UserAttribute810     pub fn user_attribute(&self) -> &UserAttribute {
811         self.component()
812     }
813 
814     /// Returns the User Attribute's revocation status at time `t`.
815     ///
816     /// A User Attribute is revoked at time `t` if:
817     ///
818     ///   - There is a live revocation at time `t` that is newer than
819     ///     all live self signatures at time `t`.
820     ///
821     /// Note: Certs and subkeys have different criteria from User IDs
822     /// and User Attributes.
823     ///
824     /// Note: this only returns whether this User Attribute is revoked;
825     /// it does not imply anything about the Cert or other components.
826     //
827     /// # Examples
828     ///
829     /// ```
830     /// # extern crate sequoia_openpgp as openpgp;
831     /// # use openpgp::cert::prelude::*;
832     /// use openpgp::policy::StandardPolicy;
833     /// #
834     /// # fn main() -> openpgp::Result<()> {
835     /// let p = &StandardPolicy::new();
836     ///
837     /// # let (cert, _) =
838     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
839     /// #     .generate()?;
840     /// // Display the User Attributes' revocation status.
841     /// for (i, ua) in cert.user_attributes().enumerate() {
842     ///     eprintln!(" Revocation status of User Attribute #{}: {:?}",
843     ///               i, ua.revocation_status(p, None));
844     /// }
845     /// # Ok(()) }
846     /// ```
revocation_status<T>(&self, policy: &dyn Policy, t: T) -> RevocationStatus where T: Into<Option<time::SystemTime>>847     pub fn revocation_status<T>(&self, policy: &dyn Policy, t: T)
848         -> RevocationStatus
849         where T: Into<Option<time::SystemTime>>
850     {
851         let t = t.into();
852         self._revocation_status(policy, t, false,
853                                 self.binding_signature(policy, t).ok())
854     }
855 }
856 
857 impl ComponentBundle<Unknown> {
858     /// Returns a reference to the unknown component.
859     ///
860     /// This is just a type-specific alias for
861     /// [`ComponentBundle::component`].
862     ///
863     /// [`ComponentBundle::component`]: #method.component
864     ///
865     /// # Examples
866     ///
867     /// ```
868     /// # extern crate sequoia_openpgp as openpgp;
869     /// # use openpgp::cert::prelude::*;
870     /// #
871     /// # fn main() -> openpgp::Result<()> {
872     /// # let (cert, _) =
873     /// #     CertBuilder::general_purpose(None, Some("alice@example.org"))
874     /// #     .generate()?;
875     /// // Display some information about the User Attributes
876     /// for u in cert.unknowns() {
877     ///     eprintln!(" - {:?}", u.unknown());
878     /// }
879     /// # Ok(()) }
880     /// ```
unknown(&self) -> &Unknown881     pub fn unknown(&self) -> &Unknown {
882         self.component()
883     }
884 }
885