sequoia_openpgp/cert/bundle.rs
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 an 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`]: super
69//! [`Packet`]: crate::packet
70//! [`Signature`]: crate::packet::signature
71//! [`Key`]: crate::packet::key
72//! [`UserID`]: crate::packet::UserID
73//! [`UserAttribute`]: crate::packet::user_attribute
74//! [`Unknown`]: crate::packet::Unknown
75//! [`Tag`]: crate::packet::Tag
76//! [designated revoker]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.23
77//! [`ComponentAmalgamation`]: super::amalgamation
78//! [`KeyAmalgamation`]: super::amalgamation::key::KeyAmalgamation
79//! [complicated semantics]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
80
81use std::time;
82use std::cmp::{self, Ordering};
83use std::ops::{Deref, DerefMut};
84use std::sync::Arc;
85
86use crate::{
87 cert::lazysigs::{LazySignatures, SigState},
88 Error,
89 packet::Signature,
90 packet::Key,
91 packet::key,
92 packet::UserID,
93 packet::UserAttribute,
94 packet::Unknown,
95 Packet,
96 policy::HashAlgoSecurity,
97 policy::Policy,
98 Result,
99};
100use crate::types::{
101 RevocationType,
102 RevocationStatus,
103};
104
105use super::{
106 sig_cmp,
107 canonical_signature_order,
108};
109
110/// A certificate component and its associated signatures.
111///
112/// [See the module level documentation](self) for a detailed
113/// description.
114#[derive(Debug, Clone, PartialEq)]
115pub struct ComponentBundle<C> {
116 component: C,
117
118 pub(super) hash_algo_security: HashAlgoSecurity,
119
120 // Self signatures.
121 pub(super) self_signatures: LazySignatures,
122
123 /// If set, is equal to `component`, and provides context to
124 /// verify primary key binding signatures.
125 backsig_signer: Option<Key<key::PublicParts, key::SubordinateRole>>,
126
127 // Third-party certifications. (In general, this will only be by
128 // designated revokers.)
129 pub(super) certifications: Vec<Signature>,
130
131 // Attestation key signatures.
132 pub(super) attestations: LazySignatures,
133
134 // Self revocations.
135 pub(super) self_revocations: LazySignatures,
136
137 // Third-party revocations (e.g., designated revokers).
138 pub(super) other_revocations: Vec<Signature>,
139}
140assert_send_and_sync!(ComponentBundle<C> where C);
141
142/// A key (primary or subkey, public or private) and any associated
143/// signatures.
144///
145/// [See the module level documentation.](self)
146pub type KeyBundle<KeyPart, KeyRole> = ComponentBundle<Key<KeyPart, KeyRole>>;
147
148/// A primary key and any associated signatures.
149///
150/// [See the module level documentation.](self)
151pub type PrimaryKeyBundle<KeyPart> =
152 KeyBundle<KeyPart, key::PrimaryRole>;
153
154/// A subkey and any associated signatures.
155///
156/// [See the module level documentation.](self)
157pub type SubkeyBundle<KeyPart>
158 = KeyBundle<KeyPart, key::SubordinateRole>;
159
160/// A User ID and any associated signatures.
161///
162/// [See the module level documentation.](self)
163pub type UserIDBundle = ComponentBundle<UserID>;
164
165/// A User Attribute and any associated signatures.
166///
167/// [See the module level documentation.](self)
168pub type UserAttributeBundle = ComponentBundle<UserAttribute>;
169
170/// An unknown component and any associated signatures.
171///
172/// Note: all signatures are stored as certifications.
173///
174/// [See the module level documentation.](self)
175pub type UnknownBundle = ComponentBundle<Unknown>;
176
177
178impl<C> ComponentBundle<C> {
179 /// Creates a new component.
180 ///
181 /// Should only be used from the cert parser. However, we cannot
182 /// use `pub(in ...)` because the cert parser isn't an ancestor of
183 /// this module.
184 pub(crate) fn new(component: C,
185 hash_algo_security: HashAlgoSecurity,
186 sigs: Vec<Signature>,
187 primary_key: Arc<Key<key::PublicParts, key::PrimaryRole>>)
188 -> ComponentBundle<C>
189 {
190 ComponentBundle {
191 component,
192 hash_algo_security,
193 self_signatures: LazySignatures::new(primary_key.clone()),
194 backsig_signer: None,
195 certifications: sigs,
196 attestations: LazySignatures::new(primary_key.clone()),
197 self_revocations: LazySignatures::new(primary_key),
198 other_revocations: vec![],
199 }
200 }
201
202 /// Returns a reference to the bundle's component.
203 ///
204 /// # Examples
205 ///
206 /// ```
207 /// # use sequoia_openpgp as openpgp;
208 /// # use openpgp::cert::prelude::*;
209 /// #
210 /// # fn main() -> openpgp::Result<()> {
211 /// # let (cert, _) =
212 /// # CertBuilder::general_purpose(Some("alice@example.org"))
213 /// # .generate()?;
214 /// // Display some information about any unknown components.
215 /// for u in cert.unknowns() {
216 /// eprintln!(" - {:?}", u.bundle().component());
217 /// }
218 /// # Ok(()) }
219 /// ```
220 pub fn component(&self) -> &C {
221 &self.component
222 }
223
224 /// Returns a mutable reference to the component.
225 pub(crate) fn component_mut(&mut self) -> &mut C {
226 &mut self.component
227 }
228
229 /// Returns the active binding signature at time `t`.
230 ///
231 /// The active binding signature is the most recent, non-revoked
232 /// self-signature that is valid according to the `policy` and
233 /// alive at time `t` (`creation time <= t`, `t < expiry`). If
234 /// there are multiple such signatures then the signatures are
235 /// ordered by their MPIs interpreted as byte strings.
236 ///
237 /// # Examples
238 ///
239 /// ```
240 /// # use sequoia_openpgp as openpgp;
241 /// # use openpgp::cert::prelude::*;
242 /// use openpgp::policy::StandardPolicy;
243 /// #
244 /// # fn main() -> openpgp::Result<()> {
245 /// let p = &StandardPolicy::new();
246 ///
247 /// # let (cert, _) =
248 /// # CertBuilder::general_purpose(Some("alice@example.org"))
249 /// # .generate()?;
250 /// // Display information about each User ID's current active
251 /// // binding signature (the `time` parameter is `None`), if any.
252 /// for ua in cert.userids() {
253 /// eprintln!("{:?}", ua.bundle().binding_signature(p, None));
254 /// }
255 /// # Ok(()) }
256 /// ```
257 pub fn binding_signature<T>(&self, policy: &dyn Policy, t: T)
258 -> Result<&Signature>
259 where T: Into<Option<time::SystemTime>>
260 {
261 let t = t.into().unwrap_or_else(crate::now);
262
263 /// Finds the active binding signature.
264 ///
265 /// This function does not depend on the type of `C`, but it
266 /// is unfortunately monomorphized for every `C`. Prevent
267 /// this by moving the code to a function independent of `C`.
268 fn find_binding_signature<'s>(policy: &dyn Policy,
269 self_signatures: &'s LazySignatures,
270 backsig_signer:
271 Option<&Key<key::PublicParts, key::SubordinateRole>>,
272 hash_algo_security: HashAlgoSecurity,
273 t: time::SystemTime)
274 -> Result<&'s Signature>
275 {
276 // Recall: the signatures are sorted by their creation time in
277 // descending order, i.e., newest first.
278 //
279 // We want the newest signature that is older than `t`, or
280 // that has been created at `t`. So, search for `t`.
281
282 // We search all signatures without triggering the signature
283 // verification. Later, we will verify the candidates, and
284 // reject bad signatures.
285 let unverified_self_signatures = self_signatures.as_slice_unverified();
286
287 let i =
288 // Usually, the first signature is what we are looking for.
289 // Short circuit the binary search.
290 if unverified_self_signatures.get(0)
291 .filter(|s| s.signature_creation_time().map(|c| t >= c)
292 .unwrap_or(false))
293 .filter(
294 // Verify the signature now.
295 |_| matches!(self_signatures.verify_sig(0, backsig_signer),
296 Ok(SigState::Good)))
297 .is_some()
298 {
299 0
300 } else {
301 match unverified_self_signatures.binary_search_by(
302 |s| canonical_signature_order(
303 s.signature_creation_time(), Some(t)))
304 {
305 // If there are multiple matches, then we need to search
306 // backwards to find the first one. Consider:
307 //
308 // t: 9 8 8 8 8 7
309 // i: 0 1 2 3 4 5
310 //
311 // If we are looking for t == 8, then binary_search could
312 // return index 1, 2, 3 or 4.
313 Ok(mut i) => {
314 while i > 0
315 && unverified_self_signatures[i - 1].signature_creation_time()
316 == Some(t)
317 {
318 i -= 1;
319 }
320 i
321 }
322
323 // There was no match. `i` is where a new element could
324 // be inserted while maintaining the sorted order.
325 // Consider:
326 //
327 // t: 9 8 6 5
328 // i: 0 1 2 3
329 //
330 // If we are looing for t == 7, then binary_search will
331 // return i == 2. That's exactly where we should start
332 // looking.
333 Err(i) => i,
334 }
335 };
336
337 let mut sig = None;
338
339 // Prefer the first error, which is the error arising from the
340 // most recent binding signature that wasn't created after
341 // `t`.
342 let mut error = None;
343
344 'next_sig: for (j, s) in unverified_self_signatures[i..].iter()
345 .enumerate()
346 {
347 if let Err(e) = s.signature_alive(t, time::Duration::new(0, 0)) {
348 // We know that t >= signature's creation time. So,
349 // it is expired. But an older signature might not
350 // be. So, keep trying.
351 if error.is_none() {
352 error = Some(e);
353 }
354 continue;
355 }
356
357 if let Err(e) = policy.signature(s, hash_algo_security)
358 {
359 if error.is_none() {
360 error = Some(e);
361 }
362 continue;
363 }
364
365 // Verify the signature now.
366 if ! matches!(self_signatures.verify_sig(i + j, backsig_signer),
367 Ok(SigState::Good)) {
368 // Reject bad signatures.
369 continue;
370 }
371
372 // The signature is good, but we may still need to verify the
373 // back sig.
374 if s.typ() == crate::types::SignatureType::SubkeyBinding &&
375 s.key_flags().map(|kf| kf.for_signing()).unwrap_or(false)
376 {
377 let mut n = 0;
378 let mut one_good_backsig = false;
379 'next_backsig: for backsig in s.embedded_signatures() {
380 n += 1;
381 if let Err(e) = backsig.signature_alive(
382 t, time::Duration::new(0, 0))
383 {
384 // The primary key binding signature is not
385 // alive.
386 if error.is_none() {
387 error = Some(e);
388 }
389 continue 'next_backsig;
390 }
391
392 if let Err(e) = policy
393 .signature(backsig, hash_algo_security)
394 {
395 if error.is_none() {
396 error = Some(e);
397 }
398 continue 'next_backsig;
399 }
400
401 one_good_backsig = true;
402 }
403
404 if n == 0 {
405 // This shouldn't happen because
406 // Signature::verify_subkey_binding checks for the
407 // primary key binding signature. But, better be
408 // safe.
409 if error.is_none() {
410 error = Some(Error::BadSignature(
411 "Primary key binding signature missing".into())
412 .into());
413 }
414 continue 'next_sig;
415 }
416
417 if ! one_good_backsig {
418 continue 'next_sig;
419 }
420 }
421
422 sig = Some(s);
423 break;
424 }
425
426 if let Some(sig) = sig {
427 Ok(sig)
428 } else if let Some(err) = error {
429 Err(err)
430 } else {
431 Err(Error::NoBindingSignature(t).into())
432 }
433 }
434
435 find_binding_signature(
436 policy,
437 &self.self_signatures,
438 self.backsig_signer.as_ref(),
439 self.hash_algo_security, t)
440 }
441
442 /// Returns the component's self-signatures.
443 ///
444 /// The signatures are validated, and they are sorted by their
445 /// creation time, most recent first.
446 ///
447 /// # Examples
448 ///
449 /// ```
450 /// # use sequoia_openpgp as openpgp;
451 /// # use openpgp::cert::prelude::*;
452 /// use openpgp::policy::StandardPolicy;
453 /// #
454 /// # fn main() -> openpgp::Result<()> {
455 /// let p = &StandardPolicy::new();
456 ///
457 /// # let (cert, _) =
458 /// # CertBuilder::general_purpose(Some("alice@example.org"))
459 /// # .generate()?;
460 /// for (i, ka) in cert.keys().enumerate() {
461 /// eprintln!("Key #{} ({}) has {:?} self signatures",
462 /// i, ka.key().fingerprint(),
463 /// ka.bundle().self_signatures().count());
464 /// }
465 /// # Ok(()) }
466 /// ```
467 pub fn self_signatures(&self)
468 -> impl Iterator<Item=&Signature> + Send + Sync {
469 self.self_signatures.iter_verified(self.backsig_signer.as_ref())
470 }
471
472 /// Returns the component's third-party certifications.
473 ///
474 /// The signatures are *not* validated. They are sorted by their
475 /// creation time, most recent first.
476 ///
477 /// # Examples
478 ///
479 /// ```
480 /// # use sequoia_openpgp as openpgp;
481 /// # use openpgp::cert::prelude::*;
482 /// use openpgp::policy::StandardPolicy;
483 /// #
484 /// # fn main() -> openpgp::Result<()> {
485 /// let p = &StandardPolicy::new();
486 ///
487 /// # let (cert, _) =
488 /// # CertBuilder::general_purpose(Some("alice@example.org"))
489 /// # .generate()?;
490 /// for ua in cert.userids() {
491 /// eprintln!("User ID {} has {:?} unverified, third-party certifications",
492 /// String::from_utf8_lossy(ua.userid().value()),
493 /// ua.bundle().certifications().count());
494 /// }
495 /// # Ok(()) }
496 /// ```
497 pub fn certifications(&self)
498 -> impl Iterator<Item=&Signature> + Send + Sync {
499 self.certifications.iter()
500 }
501
502 /// Returns the component's revocations that were issued by the
503 /// certificate holder.
504 ///
505 /// The revocations are validated, and they are sorted by their
506 /// creation time, most recent first.
507 ///
508 /// # Examples
509 ///
510 /// ```
511 /// # use sequoia_openpgp as openpgp;
512 /// # use openpgp::cert::prelude::*;
513 /// use openpgp::policy::StandardPolicy;
514 /// #
515 /// # fn main() -> openpgp::Result<()> {
516 /// let p = &StandardPolicy::new();
517 ///
518 /// # let (cert, _) =
519 /// # CertBuilder::general_purpose(Some("alice@example.org"))
520 /// # .generate()?;
521 /// for u in cert.userids() {
522 /// eprintln!("User ID {} has {:?} revocation certificates.",
523 /// String::from_utf8_lossy(u.userid().value()),
524 /// u.bundle().self_revocations().count());
525 /// }
526 /// # Ok(()) }
527 /// ```
528 pub fn self_revocations(&self)
529 -> impl Iterator<Item=&Signature> + Send + Sync {
530 self.self_revocations.iter_verified(self.backsig_signer.as_ref())
531 }
532
533 /// Returns the component's revocations that were issued by other
534 /// certificates.
535 ///
536 /// The revocations are *not* validated. They are sorted by their
537 /// creation time, most recent first.
538 ///
539 /// # Examples
540 ///
541 /// ```
542 /// # use sequoia_openpgp as openpgp;
543 /// # use openpgp::cert::prelude::*;
544 /// use openpgp::policy::StandardPolicy;
545 /// #
546 /// # fn main() -> openpgp::Result<()> {
547 /// let p = &StandardPolicy::new();
548 ///
549 /// # let (cert, _) =
550 /// # CertBuilder::general_purpose(Some("alice@example.org"))
551 /// # .generate()?;
552 /// for u in cert.userids() {
553 /// eprintln!("User ID {} has {:?} unverified, third-party revocation certificates.",
554 /// String::from_utf8_lossy(u.userid().value()),
555 /// u.bundle().other_revocations().count());
556 /// }
557 /// # Ok(()) }
558 /// ```
559 pub fn other_revocations(&self)
560 -> impl Iterator<Item=&Signature> + Send + Sync {
561 self.other_revocations.iter()
562 }
563
564 /// Returns all the component's Certification Approval Key
565 /// Signatures.
566 ///
567 /// This feature is [experimental](crate#experimental-features).
568 ///
569 /// The signatures are validated, and they are sorted by their
570 /// creation time, most recent first.
571 ///
572 /// A certificate owner can use Certification Approval Key
573 /// Signatures to approve of third party certifications.
574 /// Currently, only user ID and user attribute certifications can
575 /// be approved. See [Approved Certifications subpacket] for
576 /// details.
577 ///
578 /// [Approved Certifications subpacket]: https://www.ietf.org/archive/id/draft-dkg-openpgp-1pa3pc-02.html#approved-certifications-subpacket
579 ///
580 /// # Examples
581 ///
582 /// ```
583 /// # use sequoia_openpgp as openpgp;
584 /// # fn main() -> openpgp::Result<()> {
585 /// # use openpgp::cert::prelude::*;
586 /// use openpgp::policy::StandardPolicy;
587 /// let p = &StandardPolicy::new();
588 ///
589 /// # let (cert, _) =
590 /// # CertBuilder::general_purpose(Some("alice@example.org"))
591 /// # .generate()?;
592 /// for (i, uid) in cert.userids().enumerate() {
593 /// eprintln!("UserID #{} ({:?}) has {:?} certification approval key signatures",
594 /// i, uid.userid().email(),
595 /// uid.bundle().approvals().count());
596 /// }
597 /// # Ok(()) }
598 /// ```
599 pub fn approvals(&self)
600 -> impl Iterator<Item = &Signature> + Send + Sync
601 {
602 self.attestations.iter_verified(None)
603 }
604
605 /// Returns all the component's signatures.
606 ///
607 /// Only the self-signatures are validated. The signatures are
608 /// sorted first by type, then by creation time. The self
609 /// revocations come first, then the self signatures,
610 /// then any certification approval key signatures,
611 /// certifications, and third-party revocations coming last. This
612 /// function may return additional types of signatures that could
613 /// be associated to this component.
614 ///
615 /// # Examples
616 ///
617 /// ```
618 /// # use sequoia_openpgp as openpgp;
619 /// # use openpgp::cert::prelude::*;
620 /// use openpgp::policy::StandardPolicy;
621 /// #
622 /// # fn main() -> openpgp::Result<()> {
623 /// let p = &StandardPolicy::new();
624 ///
625 /// # let (cert, _) =
626 /// # CertBuilder::general_purpose(Some("alice@example.org"))
627 /// # .generate()?;
628 /// for (i, ka) in cert.keys().enumerate() {
629 /// eprintln!("Key #{} ({}) has {:?} signatures",
630 /// i, ka.key().fingerprint(),
631 /// ka.bundle().signatures().count());
632 /// }
633 /// # Ok(()) }
634 /// ```
635 pub fn signatures(&self)
636 -> impl Iterator<Item = &Signature> + Send + Sync
637 {
638 self.self_revocations()
639 .chain(self.self_signatures())
640 .chain(self.approvals())
641 .chain(self.certifications())
642 .chain(self.other_revocations())
643 }
644
645 /// Returns all the bundles' bad signatures.
646 pub(crate) fn bad_signatures(&self)
647 -> impl Iterator<Item = &Signature> + Send + Sync
648 {
649 self.self_signatures.iter_bad(self.backsig_signer.as_ref())
650 .chain(self.self_revocations.iter_bad(self.backsig_signer.as_ref()))
651 }
652
653 /// Returns the component's revocation status at time `t`.
654 ///
655 /// A component is considered to be revoked at time `t` if:
656 ///
657 /// - There is a live revocation at time `t` that is newer than
658 /// all live self signatures at time `t`.
659 ///
660 /// - `hard_revocations_are_final` is true, and there is a hard
661 /// revocation (even if it is not yet live at time `t`, and
662 /// even if there is a newer self-signature).
663 ///
664 /// selfsig must be the newest live self signature at time `t`.
665 pub(crate) fn _revocation_status<'a, T>(&'a self, policy: &dyn Policy, t: T,
666 hard_revocations_are_final: bool,
667 selfsig: Option<&Signature>)
668 -> RevocationStatus<'a>
669 where T: Into<Option<time::SystemTime>>
670 {
671 // Fallback time.
672 let time_zero = || time::UNIX_EPOCH;
673 let t = t.into().unwrap_or_else(crate::now);
674 let selfsig_creation_time
675 = selfsig.and_then(|s| s.signature_creation_time())
676 .unwrap_or_else(time_zero);
677
678 tracer!(super::TRACE, "ComponentBundle::_revocation_status", 0);
679 t!("hard_revocations_are_final: {}, selfsig: {:?}, t: {:?}",
680 hard_revocations_are_final,
681 selfsig_creation_time,
682 t);
683 if let Some(selfsig) = selfsig {
684 assert!(
685 selfsig.signature_alive(t, time::Duration::new(0, 0)).is_ok());
686 }
687
688 let check = |revs: &mut dyn Iterator<Item=&'a Signature>, sec: HashAlgoSecurity|
689 -> Option<Vec<&'a Signature>>
690 {
691 let revs = revs.filter(|rev| {
692 if let Err(err) = policy.signature(rev, sec) {
693 t!(" revocation rejected by caller policy: {}", err);
694 false
695 } else if hard_revocations_are_final
696 && rev.reason_for_revocation()
697 .map(|(r, _)| {
698 r.revocation_type() == RevocationType::Hard
699 })
700 // If there is no Reason for Revocation
701 // packet, assume that it is a hard
702 // revocation.
703 .unwrap_or(true)
704 {
705 t!(" got a hard revocation: {:?}, {:?}",
706 rev.signature_creation_time()
707 .unwrap_or_else(time_zero),
708 rev.reason_for_revocation()
709 .map(|r| (r.0, String::from_utf8_lossy(r.1))));
710 true
711 } else if selfsig_creation_time
712 > rev.signature_creation_time().unwrap_or_else(time_zero)
713 {
714 // This comes after the hard revocation check,
715 // because a hard revocation is always valid.
716 t!(" newer binding signature trumps soft revocation ({:?} > {:?})",
717 selfsig_creation_time,
718 rev.signature_creation_time().unwrap_or_else(time_zero));
719 false
720 } else if let Err(err)
721 = rev.signature_alive(t, time::Duration::new(0, 0))
722 {
723 // This comes after the hard revocation check,
724 // because a hard revocation is always valid.
725 t!(" revocation not alive ({:?} - {:?}): {}",
726 rev.signature_creation_time().unwrap_or_else(time_zero),
727 rev.signature_validity_period()
728 .unwrap_or_else(|| time::Duration::new(0, 0)),
729 err);
730 false
731 } else {
732 t!(" got a revocation: {:?} ({:?})",
733 rev.signature_creation_time().unwrap_or_else(time_zero),
734 rev.reason_for_revocation()
735 .map(|r| (r.0, String::from_utf8_lossy(r.1))));
736 true
737 }
738 }).collect::<Vec<&Signature>>();
739
740 if revs.is_empty() {
741 None
742 } else {
743 Some(revs)
744 }
745 };
746
747 if let Some(revs)
748 = check(&mut self.self_revocations.iter_verified(self.backsig_signer.as_ref()),
749 self.hash_algo_security)
750 {
751 t!("-> RevocationStatus::Revoked({})", revs.len());
752 RevocationStatus::Revoked(revs)
753 } else if let Some(revs)
754 = check(&mut self.other_revocations.iter(), Default::default())
755 {
756 t!("-> RevocationStatus::CouldBe({})", revs.len());
757 RevocationStatus::CouldBe(revs)
758 } else {
759 t!("-> RevocationStatus::NotAsFarAsWeKnow");
760 RevocationStatus::NotAsFarAsWeKnow
761 }
762 }
763
764 /// Turns the `ComponentBundle` into an iterator over its
765 /// `Packet`s.
766 ///
767 /// The signatures are ordered as follows:
768 ///
769 /// - Self revocations,
770 /// - Self signatures,
771 /// - Third-party signatures, and
772 /// - Third-party revocations.
773 ///
774 /// For a given type of signature, the signatures are ordered by
775 /// their creation time, most recent first.
776 ///
777 /// When turning the `Key` in a `KeyBundle` into a `Packet`, this
778 /// function uses the component's type (`C`) to determine the
779 /// packet's type; the type is not a function of whether the key
780 /// has secret key material.
781 pub(crate) fn into_packets(self)
782 -> impl Iterator<Item=Packet> + Send + Sync
783 where Packet: From<C>
784 {
785 let p : Packet = self.component.into();
786 std::iter::once(p)
787 .chain(self.self_revocations.into_unverified().map(|s| s.into()))
788 .chain(self.self_signatures.into_unverified().map(|s| s.into()))
789 .chain(self.attestations.into_unverified().map(|s| s.into()))
790 .chain(self.certifications.into_iter().map(|s| s.into()))
791 .chain(self.other_revocations.into_iter().map(|s| s.into()))
792 }
793
794 // Sorts and dedups the binding's signatures.
795 //
796 // Note: this uses Signature::normalized_eq to compare signatures.
797 // That function ignores unhashed packets. If there are two
798 // signatures that only differ in their unhashed subpackets, they
799 // will be deduped. The unhashed areas are merged as discussed in
800 // Signature::merge.
801 pub(crate) fn sort_and_dedup(&mut self)
802 {
803 // `same_bucket` function for Vec::dedup_by that compares
804 // signatures and merges them if they are equal modulo
805 // unhashed subpackets.
806 fn sig_merge(a: &mut Signature, b: &mut Signature) -> bool {
807 // If a == b, a is removed. Hence, we merge into b.
808 if a.normalized_eq(b) {
809 b.merge_internal(a)
810 .expect("checked for equality above");
811 true
812 } else {
813 false
814 }
815 }
816
817 // If two signatures are merged, we also do some fixups. Make
818 // sure we also do this to signatures that are not merged, so
819 // that `cert.merge(cert) == cert`.
820 fn sig_fixup(sig: &mut Signature) {
821 // Add missing issuer information. This is a best effort
822 // though. If the unhashed area is full, there is nothing
823 // we can do.
824 let _ = sig.add_missing_issuers();
825
826 // Merging Signatures sorts the unhashed subpacket area.
827 // Do the same.
828 sig.unhashed_area_mut().sort();
829 }
830
831 self.self_signatures.sort_by(Signature::normalized_cmp);
832 self.self_signatures.dedup_by(sig_merge);
833 // Order self signatures so that the most recent one comes
834 // first.
835 self.self_signatures.sort_by(sig_cmp);
836 self.self_signatures.iter_mut_unverified().for_each(sig_fixup);
837
838 self.attestations.sort_by(Signature::normalized_cmp);
839 self.attestations.dedup_by(sig_merge);
840 self.attestations.sort_by(sig_cmp);
841 self.attestations.iter_mut_unverified().for_each(sig_fixup);
842
843 self.certifications.sort_by(Signature::normalized_cmp);
844 self.certifications.dedup_by(sig_merge);
845 // There is no need to sort the certifications, but doing so
846 // has the advantage that the most recent ones (and therefore
847 // presumably the more relevant ones) come first. Also,
848 // cert::test::signature_order checks that the signatures are
849 // sorted.
850 self.certifications.sort_by(sig_cmp);
851 self.certifications.iter_mut().for_each(sig_fixup);
852
853 self.self_revocations.sort_by(Signature::normalized_cmp);
854 self.self_revocations.dedup_by(sig_merge);
855 self.self_revocations.sort_by(sig_cmp);
856 self.self_revocations.iter_mut_unverified().for_each(sig_fixup);
857
858 self.other_revocations.sort_by(Signature::normalized_cmp);
859 self.other_revocations.dedup_by(sig_merge);
860 self.other_revocations.sort_by(sig_cmp);
861 self.other_revocations.iter_mut().for_each(sig_fixup);
862 }
863}
864
865impl<P: key::KeyParts, R: key::KeyRole> ComponentBundle<Key<P, R>> {
866 /// Returns a reference to the key.
867 ///
868 /// This is just a type-specific alias for
869 /// [`ComponentBundle::component`].
870 ///
871 /// [`ComponentBundle::component`]: ComponentBundle::component()
872 ///
873 /// # Examples
874 ///
875 /// ```
876 /// # use sequoia_openpgp as openpgp;
877 /// # use openpgp::cert::prelude::*;
878 /// #
879 /// # fn main() -> openpgp::Result<()> {
880 /// # let (cert, _) =
881 /// # CertBuilder::general_purpose(Some("alice@example.org"))
882 /// # .generate()?;
883 /// // Display some information about the keys.
884 /// for ka in cert.keys() {
885 /// eprintln!(" - {:?}", ka.bundle().key());
886 /// }
887 /// # Ok(()) }
888 /// ```
889 pub fn key(&self) -> &Key<P, R> {
890 self.component()
891 }
892
893 /// Returns a mut reference to the key.
894 pub(crate) fn key_mut(&mut self) -> &mut Key<P, R> {
895 self.component_mut()
896 }
897
898 pub(crate) fn set_role(&mut self, role: key::KeyRoleRT) {
899 self.key_mut().set_role(role);
900 }
901
902 /// Forwarder for the conversion macros.
903 pub(crate) fn has_secret(&self) -> bool {
904 self.key().has_secret()
905 }
906}
907
908impl<P: key::KeyParts> ComponentBundle<Key<P, key::SubordinateRole>> {
909 /// Creates a new subkey component.
910 ///
911 /// Should only be used from the cert parser. However, we cannot
912 /// use `pub(in ...)` because the cert parser isn't an ancestor of
913 /// this module.
914 pub(crate) fn new_subkey(component: Key<P, key::SubordinateRole>,
915 hash_algo_security: HashAlgoSecurity,
916 sigs: Vec<Signature>,
917 primary_key: Arc<Key<key::PublicParts, key::PrimaryRole>>)
918 -> Self
919 {
920 let backsig_signer = component.pk_algo().for_signing()
921 .then(|| component.parts_as_public().clone());
922 ComponentBundle {
923 component,
924 hash_algo_security,
925 self_signatures: LazySignatures::new(primary_key.clone()),
926 backsig_signer,
927 certifications: sigs,
928 attestations: LazySignatures::new(primary_key.clone()),
929 self_revocations: LazySignatures::new(primary_key),
930 other_revocations: vec![],
931 }
932 }
933
934 /// Returns the subkey's revocation status at time `t`.
935 ///
936 /// A subkey is revoked at time `t` if:
937 ///
938 /// - There is a live revocation at time `t` that is newer than
939 /// all live self signatures at time `t`, or
940 ///
941 /// - There is a hard revocation (even if it is not live at
942 /// time `t`, and even if there is a newer self-signature).
943 ///
944 /// Note: Certs and subkeys have different criteria from User IDs
945 /// and User Attributes.
946 ///
947 /// Note: this only returns whether this subkey is revoked; it
948 /// does not imply anything about the Cert or other components.
949 ///
950 /// # Examples
951 ///
952 /// ```
953 /// # use sequoia_openpgp as openpgp;
954 /// # use openpgp::cert::prelude::*;
955 /// use openpgp::policy::StandardPolicy;
956 /// #
957 /// # fn main() -> openpgp::Result<()> {
958 /// let p = &StandardPolicy::new();
959 ///
960 /// # let (cert, _) =
961 /// # CertBuilder::general_purpose(Some("alice@example.org"))
962 /// # .generate()?;
963 /// // Display the subkeys' revocation status.
964 /// for ka in cert.keys().subkeys() {
965 /// eprintln!(" Revocation status of {}: {:?}",
966 /// ka.key().fingerprint(),
967 /// ka.bundle().revocation_status(p, None));
968 /// }
969 /// # Ok(()) }
970 /// ```
971 pub fn revocation_status<T>(&self, policy: &dyn Policy, t: T)
972 -> RevocationStatus
973 where T: Into<Option<time::SystemTime>>
974 {
975 let t = t.into();
976 self._revocation_status(policy, t, true,
977 self.binding_signature(policy, t).ok())
978 }
979}
980
981impl ComponentBundle<UserID> {
982 /// Returns a reference to the User ID.
983 ///
984 /// This is just a type-specific alias for
985 /// [`ComponentBundle::component`].
986 ///
987 /// [`ComponentBundle::component`]: ComponentBundle::component()
988 ///
989 /// # Examples
990 ///
991 /// ```
992 /// # use sequoia_openpgp as openpgp;
993 /// # use openpgp::cert::prelude::*;
994 /// #
995 /// # fn main() -> openpgp::Result<()> {
996 /// # let (cert, _) =
997 /// # CertBuilder::general_purpose(Some("alice@example.org"))
998 /// # .generate()?;
999 /// // Display some information about the User IDs.
1000 /// for ua in cert.userids() {
1001 /// eprintln!(" - {:?}", ua.bundle().userid());
1002 /// }
1003 /// # Ok(()) }
1004 /// ```
1005 pub fn userid(&self) -> &UserID {
1006 self.component()
1007 }
1008
1009 /// Returns the User ID's revocation status at time `t`.<a
1010 /// name="userid_revocation_status"></a>
1011 ///
1012 /// <!-- Why we have the above anchor:
1013 /// https://github.com/rust-lang/rust/issues/71912 -->
1014 ///
1015 /// A User ID is revoked at time `t` if:
1016 ///
1017 /// - There is a live revocation at time `t` that is newer than
1018 /// all live self signatures at time `t`.
1019 ///
1020 /// Note: Certs and subkeys have different criteria from User IDs
1021 /// and User Attributes.
1022 ///
1023 /// Note: this only returns whether this User ID is revoked; it
1024 /// does not imply anything about the Cert or other components.
1025 //
1026 /// # Examples
1027 ///
1028 /// ```
1029 /// # use sequoia_openpgp as openpgp;
1030 /// # use openpgp::cert::prelude::*;
1031 /// use openpgp::policy::StandardPolicy;
1032 /// #
1033 /// # fn main() -> openpgp::Result<()> {
1034 /// let p = &StandardPolicy::new();
1035 ///
1036 /// # let (cert, _) =
1037 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1038 /// # .generate()?;
1039 /// // Display the User IDs' revocation status.
1040 /// for ua in cert.userids() {
1041 /// eprintln!(" Revocation status of {}: {:?}",
1042 /// String::from_utf8_lossy(ua.userid().value()),
1043 /// ua.bundle().revocation_status(p, None));
1044 /// }
1045 /// # Ok(()) }
1046 /// ```
1047 pub fn revocation_status<T>(&self, policy: &dyn Policy, t: T)
1048 -> RevocationStatus
1049 where T: Into<Option<time::SystemTime>>
1050 {
1051 let t = t.into();
1052 self._revocation_status(policy, t, false, self.binding_signature(policy, t).ok())
1053 }
1054}
1055
1056impl ComponentBundle<UserAttribute> {
1057 /// Returns a reference to the User Attribute.
1058 ///
1059 /// This is just a type-specific alias for
1060 /// [`ComponentBundle::component`].
1061 ///
1062 /// [`ComponentBundle::component`]: ComponentBundle::component()
1063 ///
1064 /// # Examples
1065 ///
1066 /// ```
1067 /// # use sequoia_openpgp as openpgp;
1068 /// # use openpgp::cert::prelude::*;
1069 /// #
1070 /// # fn main() -> openpgp::Result<()> {
1071 /// # let (cert, _) =
1072 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1073 /// # .generate()?;
1074 /// // Display some information about the User Attributes
1075 /// for ua in cert.user_attributes() {
1076 /// eprintln!(" - {:?}", ua.bundle().user_attribute());
1077 /// }
1078 /// # Ok(()) }
1079 /// ```
1080 pub fn user_attribute(&self) -> &UserAttribute {
1081 self.component()
1082 }
1083
1084 /// Returns the User Attribute's revocation status at time `t`.
1085 ///
1086 /// A User Attribute is revoked at time `t` if:
1087 ///
1088 /// - There is a live revocation at time `t` that is newer than
1089 /// all live self signatures at time `t`.
1090 ///
1091 /// Note: Certs and subkeys have different criteria from User IDs
1092 /// and User Attributes.
1093 ///
1094 /// Note: this only returns whether this User Attribute is revoked;
1095 /// it does not imply anything about the Cert or other components.
1096 //
1097 /// # Examples
1098 ///
1099 /// ```
1100 /// # use sequoia_openpgp as openpgp;
1101 /// # use openpgp::cert::prelude::*;
1102 /// use openpgp::policy::StandardPolicy;
1103 /// #
1104 /// # fn main() -> openpgp::Result<()> {
1105 /// let p = &StandardPolicy::new();
1106 ///
1107 /// # let (cert, _) =
1108 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1109 /// # .generate()?;
1110 /// // Display the User Attributes' revocation status.
1111 /// for (i, ua) in cert.user_attributes().enumerate() {
1112 /// eprintln!(" Revocation status of User Attribute #{}: {:?}",
1113 /// i, ua.bundle().revocation_status(p, None));
1114 /// }
1115 /// # Ok(()) }
1116 /// ```
1117 pub fn revocation_status<T>(&self, policy: &dyn Policy, t: T)
1118 -> RevocationStatus
1119 where T: Into<Option<time::SystemTime>>
1120 {
1121 let t = t.into();
1122 self._revocation_status(policy, t, false,
1123 self.binding_signature(policy, t).ok())
1124 }
1125}
1126
1127impl ComponentBundle<Unknown> {
1128 /// Returns a reference to the unknown component.
1129 ///
1130 /// This is just a type-specific alias for
1131 /// [`ComponentBundle::component`].
1132 ///
1133 /// [`ComponentBundle::component`]: ComponentBundle::component()
1134 ///
1135 /// # Examples
1136 ///
1137 /// ```
1138 /// # use sequoia_openpgp as openpgp;
1139 /// # use openpgp::cert::prelude::*;
1140 /// #
1141 /// # fn main() -> openpgp::Result<()> {
1142 /// # let (cert, _) =
1143 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1144 /// # .generate()?;
1145 /// // Display some information about the User Attributes
1146 /// for u in cert.unknowns() {
1147 /// eprintln!(" - {:?}", u.unknown());
1148 /// }
1149 /// # Ok(()) }
1150 /// ```
1151 pub fn unknown(&self) -> &Unknown {
1152 self.component()
1153 }
1154}
1155
1156/// A collection of `ComponentBundles`.
1157///
1158/// Note: we need this, because we can't `impl Vec<ComponentBundles>`.
1159#[derive(Debug, Clone, PartialEq)]
1160pub(super) struct ComponentBundles<C>
1161 where ComponentBundle<C>: cmp::PartialEq
1162{
1163 bundles: Vec<ComponentBundle<C>>,
1164}
1165
1166impl<C> Default for ComponentBundles<C>
1167where
1168 ComponentBundle<C>: cmp::PartialEq,
1169{
1170 fn default() -> Self {
1171 ComponentBundles {
1172 bundles: vec![],
1173 }
1174 }
1175}
1176
1177impl<C> Deref for ComponentBundles<C>
1178 where ComponentBundle<C>: cmp::PartialEq
1179{
1180 type Target = Vec<ComponentBundle<C>>;
1181
1182 fn deref(&self) -> &Self::Target {
1183 &self.bundles
1184 }
1185}
1186
1187impl<C> DerefMut for ComponentBundles<C>
1188 where ComponentBundle<C>: cmp::PartialEq
1189{
1190 fn deref_mut(&mut self) -> &mut Vec<ComponentBundle<C>> {
1191 &mut self.bundles
1192 }
1193}
1194
1195impl<C> From<ComponentBundles<C>> for Vec<ComponentBundle<C>>
1196 where ComponentBundle<C>: cmp::PartialEq
1197{
1198 fn from(cb: ComponentBundles<C>) -> Vec<ComponentBundle<C>> {
1199 cb.bundles
1200 }
1201}
1202
1203impl<C> From<Vec<ComponentBundle<C>>> for ComponentBundles<C>
1204 where ComponentBundle<C>: cmp::PartialEq
1205{
1206 fn from(bundles: Vec<ComponentBundle<C>>) -> ComponentBundles<C> {
1207 ComponentBundles {
1208 bundles,
1209 }
1210 }
1211}
1212
1213impl<C> IntoIterator for ComponentBundles<C>
1214 where ComponentBundle<C>: cmp::PartialEq
1215{
1216 type Item = ComponentBundle<C>;
1217 type IntoIter = std::vec::IntoIter<Self::Item>;
1218
1219 fn into_iter(self) -> Self::IntoIter {
1220 self.bundles.into_iter()
1221 }
1222}
1223
1224impl<C> ComponentBundles<C>
1225 where ComponentBundle<C>: cmp::PartialEq
1226{
1227 // Sort and dedup the components.
1228 //
1229 // `cmp` is a function to sort the components for deduping.
1230 //
1231 // `merge` is a function that merges the first component into the
1232 // second component.
1233 pub(super) fn sort_and_dedup<F, F2>(&mut self, cmp: F, merge: F2)
1234 where F: Fn(&C, &C) -> Ordering,
1235 F2: Fn(&mut C, &mut C)
1236 {
1237 // We dedup by component (not bundles!). To do this, we need
1238 // to sort the bundles by their components.
1239
1240 self.bundles.sort_by(
1241 |a, b| cmp(&a.component, &b.component));
1242
1243 self.bundles.dedup_by(|a, b| {
1244 if cmp(&a.component, &b.component) == Ordering::Equal {
1245 // Merge.
1246 merge(&mut a.component, &mut b.component);
1247
1248 // Recall: if a and b are equal, a will be dropped.
1249 // Also, the elements are given in the opposite order
1250 // from their order in the vector.
1251 b.self_signatures.append(&mut a.self_signatures);
1252 b.attestations.append(&mut a.attestations);
1253 b.certifications.append(&mut a.certifications);
1254 b.self_revocations.append(&mut a.self_revocations);
1255 b.other_revocations.append(&mut a.other_revocations);
1256
1257 true
1258 } else {
1259 false
1260 }
1261 });
1262
1263 // And sort the certificates.
1264 for b in self.bundles.iter_mut() {
1265 b.sort_and_dedup();
1266 }
1267 }
1268}
1269
1270/// A vecor of key (primary or subkey, public or private) and any
1271/// associated signatures.
1272pub(super) type KeyBundles<KeyPart, KeyRole>
1273 = ComponentBundles<Key<KeyPart, KeyRole>>;
1274
1275/// A vector of subkeys and any associated signatures.
1276pub(super) type SubkeyBundles<KeyPart>
1277 = KeyBundles<KeyPart, key::SubordinateRole>;
1278
1279/// A vector of key (primary or subkey, public or private) and any
1280/// associated signatures.
1281#[allow(dead_code)]
1282pub(super) type GenericKeyBundles
1283 = ComponentBundles<Key<key::UnspecifiedParts, key::UnspecifiedRole>>;
1284
1285/// A vector of User ID bundles and any associated signatures.
1286pub(super) type UserIDBundles = ComponentBundles<UserID>;
1287
1288/// A vector of User Attribute bundles and any associated signatures.
1289pub(super) type UserAttributeBundles = ComponentBundles<UserAttribute>;
1290
1291/// A vector of unknown components and any associated signatures.
1292///
1293/// Note: all signatures are stored as certifications.
1294pub(super) type UnknownBundles = ComponentBundles<Unknown>;