sequoia_openpgp/cert/amalgamation/key.rs
1//! Keys, their associated signatures, and some useful methods.
2//!
3//! A [`KeyAmalgamation`] is similar to a [`ComponentAmalgamation`],
4//! but a `KeyAmalgamation` includes some additional functionality
5//! that is needed to correctly implement a [`Key`] component's
6//! semantics. In particular, unlike other components where the
7//! binding signature stores the component's meta-data, a Primary Key
8//! doesn't have a binding signature (it is the thing that other
9//! components are bound to!), and, as a consequence, the associated
10//! meta-data is stored elsewhere.
11//!
12//! Unfortunately, a primary Key's meta-data is usually not stored on
13//! a direct key signature, which would be convenient as it is located
14//! at the same place as a binding signature would be, but on the
15//! primary User ID's binding signature. This requires some
16//! acrobatics on the implementation side to realize the correct
17//! semantics. In particular, a `Key` needs to memorize its role
18//! (i.e., whether it is a primary key or a subkey) in order to know
19//! whether to consider its own self signatures or the primary User
20//! ID's self signatures when looking for its meta-data.
21//!
22//! Ideally, a `KeyAmalgamation`'s role would be encoded in its type.
23//! This increases safety, and reduces the run-time overhead.
24//! However, we want [`Cert::keys`] to return an iterator over all
25//! keys; we don't want the user to have to specially handle the
26//! primary key when that fact is not relevant. This means that
27//! `Cert::keys` has to erase the returned `Key`s' roles: all items in
28//! an iterator must have the same type. To support this, we have to
29//! keep track of a `KeyAmalgamation`'s role at run-time.
30//!
31//! But, just because we need to erase a `KeyAmalgamation`'s role to
32//! implement `Cert::keys` doesn't mean that we have to always erase
33//! it. To achieve this, we use three data types:
34//! [`PrimaryKeyAmalgamation`], [`SubordinateKeyAmalgamation`], and
35//! [`ErasedKeyAmalgamation`]. The first two encode the role
36//! information in their type, and the last one stores it at run time.
37//! We provide conversion functions to convert the static type
38//! information into dynamic type information, and vice versa.
39//!
40//! Note: `KeyBundle`s and `KeyAmalgamation`s have a notable
41//! difference: whereas a `KeyBundle`'s role is a marker, a
42//! `KeyAmalgamation`'s role determines its semantics. A consequence
43//! of this is that it is not possible to convert a
44//! `PrimaryKeyAmalgamation` into a `SubordinateAmalgamation`s, or
45//! vice versa even though we support changing a `KeyBundle`'s role:
46//!
47//! ```
48//! # fn main() -> sequoia_openpgp::Result<()> {
49//! # use std::convert::TryInto;
50//! # use sequoia_openpgp as openpgp;
51//! # use openpgp::cert::prelude::*;
52//! # use openpgp::packet::prelude::*;
53//! # let (cert, _) = CertBuilder::new()
54//! # .add_userid("Alice")
55//! # .add_signing_subkey()
56//! # .add_transport_encryption_subkey()
57//! # .generate()?;
58//! // This works:
59//! cert.primary_key().bundle().role_as_subordinate();
60//!
61//! // But this doesn't:
62//! let ka: ErasedKeyAmalgamation<_> = cert.keys().nth(0).expect("primary key");
63//! let ka: openpgp::Result<SubordinateKeyAmalgamation<key::PublicParts>> = ka.try_into();
64//! assert!(ka.is_err());
65//! # Ok(()) }
66//! ```
67//!
68//! The use of the prefix `Erased` instead of `Unspecified`
69//! (cf. [`KeyRole::UnspecifiedRole`]) emphasizes this.
70//!
71//! # Selecting Keys
72//!
73//! It is essential to choose the right keys, and to make sure that
74//! they are appropriate. Below, we present some guidelines for the most
75//! common situations.
76//!
77//! ## Encrypting and Signing Messages
78//!
79//! As a general rule of thumb, when encrypting or signing a message,
80//! you want to use keys that are alive, not revoked, and have the
81//! appropriate capabilities right now. For example, the following
82//! code shows how to find a key, which is appropriate for signing a
83//! message:
84//!
85//! ```rust
86//! # use sequoia_openpgp as openpgp;
87//! # use openpgp::Result;
88//! # use openpgp::cert::prelude::*;
89//! use openpgp::types::RevocationStatus;
90//! use sequoia_openpgp::policy::StandardPolicy;
91//!
92//! # fn main() -> Result<()> {
93//! # let (cert, _) =
94//! # CertBuilder::general_purpose(Some("alice@example.org"))
95//! # .generate()?;
96//! # let mut i = 0;
97//! let p = &StandardPolicy::new();
98//!
99//! let cert = cert.with_policy(p, None)?;
100//!
101//! if let RevocationStatus::Revoked(_) = cert.revocation_status() {
102//! // The certificate is revoked, don't use any keys from it.
103//! # unreachable!();
104//! } else if let Err(_) = cert.alive() {
105//! // The certificate is not alive, don't use any keys from it.
106//! # unreachable!();
107//! } else {
108//! for ka in cert.keys() {
109//! if let RevocationStatus::Revoked(_) = ka.revocation_status() {
110//! // The key is revoked.
111//! # unreachable!();
112//! } else if let Err(_) = ka.alive() {
113//! // The key is not alive.
114//! # unreachable!();
115//! } else if ! ka.for_signing() {
116//! // The key is not signing capable.
117//! } else {
118//! // Use it!
119//! # i += 1;
120//! }
121//! }
122//! }
123//! # assert_eq!(i, 1);
124//! # Ok(())
125//! # }
126//! ```
127//!
128//! ## Verifying a Message
129//!
130//! When verifying a message, you only want to use keys that were
131//! alive, not revoked, and signing capable *when the message was
132//! signed*. These are the keys that the signer would have used, and
133//! they reflect the signer's policy when they made the signature.
134//! (See the [`Policy` discussion] for an explanation.)
135//!
136//! For version 4 Signature packets, the `Signature Creation Time`
137//! subpacket indicates when the signature was allegedly created. For
138//! the purpose of finding the key to verify the signature, this time
139//! stamp should be trusted: if the key is authenticated and the
140//! signature is valid, then the time stamp is valid; if the signature
141//! is not valid, then forging the time stamp won't help an attacker.
142//!
143//! ```rust
144//! # use sequoia_openpgp as openpgp;
145//! # use openpgp::Result;
146//! # use openpgp::cert::prelude::*;
147//! use openpgp::types::RevocationStatus;
148//! use sequoia_openpgp::policy::StandardPolicy;
149//!
150//! # fn main() -> Result<()> {
151//! let p = &StandardPolicy::new();
152//!
153//! # let (cert, _) =
154//! # CertBuilder::general_purpose(Some("alice@example.org"))
155//! # .generate()?;
156//! # let timestamp = None;
157//! # let issuer = cert.with_policy(p, None)?.keys()
158//! # .for_signing().nth(0).unwrap().key().fingerprint();
159//! # let mut i = 0;
160//! let cert = cert.with_policy(p, timestamp)?;
161//! if let RevocationStatus::Revoked(_) = cert.revocation_status() {
162//! // The certificate is revoked, don't use any keys from it.
163//! # unreachable!();
164//! } else if let Err(_) = cert.alive() {
165//! // The certificate is not alive, don't use any keys from it.
166//! # unreachable!();
167//! } else {
168//! for ka in cert.keys().key_handle(issuer) {
169//! if let RevocationStatus::Revoked(_) = ka.revocation_status() {
170//! // The key is revoked, don't use it!
171//! # unreachable!();
172//! } else if let Err(_) = ka.alive() {
173//! // The key was not alive when the signature was made!
174//! // Something fishy is going on.
175//! # unreachable!();
176//! } else if ! ka.for_signing() {
177//! // The key was not signing capable! Better be safe
178//! // than sorry.
179//! # unreachable!();
180//! } else {
181//! // Try verifying the message with this key.
182//! # i += 1;
183//! }
184//! }
185//! }
186//! # assert_eq!(i, 1);
187//! # Ok(())
188//! # }
189//! ```
190//!
191//! ## Decrypting a Message
192//!
193//! When decrypting a message, it seems like one ought to only use keys
194//! that were alive, not revoked, and encryption-capable when the
195//! message was encrypted. Unfortunately, we don't know when a
196//! message was encrypted. But anyway, due to the slow propagation of
197//! revocation certificates, we can't assume that senders won't
198//! mistakenly use a revoked key.
199//!
200//! However, wanting to decrypt a message encrypted using an expired
201//! or revoked key is reasonable. If someone is trying to decrypt a
202//! message using an expired key, then they are the certificate
203//! holder, and probably attempting to access archived data using a
204//! key that they themselves revoked! We don't want to prevent that.
205//!
206//! We do, however, want to check whether a key is really encryption
207//! capable. [This discussion] explains why using a signing key to
208//! decrypt a message can be dangerous. Since we need a binding
209//! signature to determine this, but we don't have the time that the
210//! message was encrypted, we need a workaround. One approach would
211//! be to check whether the key is encryption capable now. Since a
212//! key's key flags don't typically change, this will correctly filter
213//! out keys that are not encryption capable. But, it will skip keys
214//! whose self signature has expired. But that is not a problem
215//! either: no one sets self signatures to expire; if anything, they
216//! set keys to expire. Thus, this will not result in incorrectly
217//! failing to decrypt messages in practice, and is a reasonable
218//! approach.
219//!
220//! ```rust
221//! # use sequoia_openpgp as openpgp;
222//! # use openpgp::Result;
223//! # use openpgp::cert::prelude::*;
224//! use sequoia_openpgp::policy::StandardPolicy;
225//!
226//! # fn main() -> Result<()> {
227//! let p = &StandardPolicy::new();
228//!
229//! # let (cert, _) =
230//! # CertBuilder::general_purpose(Some("alice@example.org"))
231//! # .generate()?;
232//! let decryption_keys = cert.keys().with_policy(p, None)
233//! .for_storage_encryption().for_transport_encryption()
234//! .collect::<Vec<_>>();
235//! # Ok(())
236//! # }
237//! ```
238//!
239//! [`ComponentAmalgamation`]: super::ComponentAmalgamation
240//! [`Key`]: crate::packet::key
241//! [`Cert::keys`]: super::super::Cert::keys()
242//! [`PrimaryKeyAmalgamation`]: super::PrimaryKeyAmalgamation
243//! [`SubordinateKeyAmalgamation`]: super::SubordinateKeyAmalgamation
244//! [`ErasedKeyAmalgamation`]: super::ErasedKeyAmalgamation
245//! [`KeyRole::UnspecifiedRole`]: crate::packet::key::KeyRole
246//! [`Policy` discussion]: super
247//! [This discussion]: https://crypto.stackexchange.com/a/12138
248use std::time;
249use std::time::SystemTime;
250use std::borrow::Borrow;
251use std::convert::TryFrom;
252use std::convert::TryInto;
253
254use anyhow::Context;
255
256use crate::{
257 Cert,
258 cert::bundle::KeyBundle,
259 cert::amalgamation::{
260 ComponentAmalgamation,
261 key::signature::subpacket::SubpacketValue,
262 ValidAmalgamation,
263 ValidBindingSignature,
264 ValidateAmalgamation,
265 },
266 cert::ValidCert,
267 crypto::Signer,
268 Error,
269 packet::Key,
270 packet::key,
271 packet::Signature,
272 packet::signature,
273 packet::signature::subpacket::SubpacketTag,
274 policy::Policy,
275 Result,
276 seal,
277 types::{
278 KeyFlags,
279 RevocationKey,
280 RevocationStatus,
281 SignatureType,
282 },
283};
284
285mod iter;
286pub use iter::{
287 KeyAmalgamationIter,
288 ValidKeyAmalgamationIter,
289};
290
291/// Whether the key is a primary key.
292///
293/// This trait is an implementation detail. It exists so that we can
294/// have a blanket implementation of [`ValidAmalgamation`] for
295/// [`ValidKeyAmalgamation`], for instance, even though we only have
296/// specialized implementations of `PrimaryKey`.
297///
298/// [`ValidAmalgamation`]: super::ValidAmalgamation
299///
300/// # Sealed trait
301///
302/// This trait is [sealed] and cannot be implemented for types outside this crate.
303/// Therefore it can be extended in a non-breaking way.
304/// If you want to implement the trait inside the crate
305/// you also need to implement the `seal::Sealed` marker trait.
306///
307/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
308pub trait PrimaryKey<'a, P, R>: seal::Sealed
309 where P: 'a + key::KeyParts,
310 R: 'a + key::KeyRole,
311{
312 /// Returns whether the key amalgamation is a primary key
313 /// amalgamation.
314 ///
315 /// # Examples
316 ///
317 /// ```
318 /// # use sequoia_openpgp as openpgp;
319 /// # use openpgp::cert::prelude::*;
320 /// # use openpgp::policy::StandardPolicy;
321 /// #
322 /// # fn main() -> openpgp::Result<()> {
323 /// # let p = &StandardPolicy::new();
324 /// # let (cert, _) =
325 /// # CertBuilder::general_purpose(Some("alice@example.org"))
326 /// # .generate()?;
327 /// # let fpr = cert.fingerprint();
328 /// // This works if the type is concrete:
329 /// let ka: PrimaryKeyAmalgamation<_> = cert.primary_key();
330 /// assert!(ka.primary());
331 ///
332 /// // Or if it has been erased:
333 /// for (i, ka) in cert.keys().enumerate() {
334 /// let ka: ErasedKeyAmalgamation<_> = ka;
335 /// if i == 0 {
336 /// // The primary key is always the first key returned by
337 /// // `Cert::keys`.
338 /// assert!(ka.primary());
339 /// } else {
340 /// // The rest are subkeys.
341 /// assert!(! ka.primary());
342 /// }
343 /// }
344 /// # Ok(()) }
345 /// ```
346 fn primary(&self) -> bool;
347}
348
349/// A key, and its associated data, and useful methods.
350///
351/// A `KeyAmalgamation` is like a [`ComponentAmalgamation`], but
352/// specialized for keys. Due to the requirement to keep track of the
353/// key's role when it is erased ([see the module's documentation] for
354/// more details), this is a different data structure rather than a
355/// specialized type alias.
356///
357/// Generally, you won't use this type directly, but instead use
358/// [`PrimaryKeyAmalgamation`], [`SubordinateKeyAmalgamation`], or
359/// [`ErasedKeyAmalgamation`].
360///
361/// A `KeyAmalgamation` is returned by [`Cert::primary_key`], and
362/// [`Cert::keys`].
363///
364/// `KeyAmalgamation` implements [`ValidateAmalgamation`], which
365/// allows you to turn a `KeyAmalgamation` into a
366/// [`ValidKeyAmalgamation`] using [`KeyAmalgamation::with_policy`].
367///
368/// # Examples
369///
370/// Iterating over all keys:
371///
372/// ```
373/// # use sequoia_openpgp as openpgp;
374/// # use openpgp::cert::prelude::*;
375/// # use openpgp::policy::StandardPolicy;
376/// #
377/// # fn main() -> openpgp::Result<()> {
378/// # let p = &StandardPolicy::new();
379/// # let (cert, _) =
380/// # CertBuilder::general_purpose(Some("alice@example.org"))
381/// # .generate()?;
382/// # let fpr = cert.fingerprint();
383/// for ka in cert.keys() {
384/// let ka: ErasedKeyAmalgamation<_> = ka;
385/// }
386/// # Ok(())
387/// # }
388/// ```
389///
390/// Getting the primary key:
391///
392/// ```
393/// # use sequoia_openpgp as openpgp;
394/// # use openpgp::cert::prelude::*;
395/// # use openpgp::policy::StandardPolicy;
396/// #
397/// # fn main() -> openpgp::Result<()> {
398/// # let p = &StandardPolicy::new();
399/// # let (cert, _) =
400/// # CertBuilder::general_purpose(Some("alice@example.org"))
401/// # .generate()?;
402/// # let fpr = cert.fingerprint();
403/// let ka: PrimaryKeyAmalgamation<_> = cert.primary_key();
404/// # Ok(())
405/// # }
406/// ```
407///
408/// Iterating over just the subkeys:
409///
410/// ```
411/// # use sequoia_openpgp as openpgp;
412/// # use openpgp::cert::prelude::*;
413/// # use openpgp::policy::StandardPolicy;
414/// #
415/// # fn main() -> openpgp::Result<()> {
416/// # let p = &StandardPolicy::new();
417/// # let (cert, _) =
418/// # CertBuilder::general_purpose(Some("alice@example.org"))
419/// # .generate()?;
420/// # let fpr = cert.fingerprint();
421/// // We can skip the primary key (it's always first):
422/// for ka in cert.keys().skip(1) {
423/// let ka: ErasedKeyAmalgamation<_> = ka;
424/// }
425///
426/// // Or use `subkeys`, which returns a more accurate type:
427/// for ka in cert.keys().subkeys() {
428/// let ka: SubordinateKeyAmalgamation<_> = ka;
429/// }
430/// # Ok(())
431/// # }
432/// ```
433///
434/// [`ComponentAmalgamation`]: super::ComponentAmalgamation
435/// [see the module's documentation]: self
436/// [`Cert::primary_key`]: crate::cert::Cert::primary_key()
437/// [`Cert::keys`]: crate::cert::Cert::keys()
438/// [`ValidateAmalgamation`]: super::ValidateAmalgamation
439/// [`KeyAmalgamation::with_policy`]: super::ValidateAmalgamation::with_policy()
440#[derive(Debug, PartialEq)]
441pub struct KeyAmalgamation<'a, P, R, R2>
442 where P: 'a + key::KeyParts,
443 R: 'a + key::KeyRole,
444{
445 ca: ComponentAmalgamation<'a, Key<P, R>>,
446 primary: R2,
447}
448assert_send_and_sync!(KeyAmalgamation<'_, P, R, R2>
449 where P: key::KeyParts,
450 R: key::KeyRole,
451 R2,
452);
453
454impl<'a, P, R> ComponentAmalgamation<'a, Key<P, R>>
455where
456 P: key::KeyParts,
457 R: key::KeyRole,
458{
459 /// Returns a reference to the key.
460 ///
461 /// This is just a type-specific alias for
462 /// [`ComponentAmalgamation::component`].
463 ///
464 /// [`ComponentAmalgamation::component`]: ComponentAmalgamation::component()
465 ///
466 /// # Examples
467 ///
468 /// ```
469 /// # use sequoia_openpgp as openpgp;
470 /// # use openpgp::cert::prelude::*;
471 /// #
472 /// # fn main() -> openpgp::Result<()> {
473 /// # let (cert, _) =
474 /// # CertBuilder::general_purpose(Some("alice@example.org"))
475 /// # .generate()?;
476 /// // Display some information about the keys.
477 /// for ka in cert.keys() {
478 /// eprintln!(" - {:?}", ka.key());
479 /// }
480 /// # Ok(()) }
481 /// ```
482 pub fn key(&self) -> &Key<P, R> {
483 self.component()
484 }
485
486 pub(crate) fn set_role(&mut self, _: key::KeyRoleRT) {
487 // The amalgamation only has an immutable reference, we cannot
488 // change the role.
489 }
490
491 /// Forwarder for the conversion macros.
492 pub(crate) fn has_secret(&self) -> bool {
493 self.key().has_secret()
494 }
495}
496
497// derive(Clone) doesn't work with generic parameters that don't
498// implement clone. But, we don't need to require that C implements
499// Clone, because we're not cloning C, just the reference.
500//
501// See: https://github.com/rust-lang/rust/issues/26925
502impl<'a, P, R, R2> Clone for KeyAmalgamation<'a, P, R, R2>
503 where P: 'a + key::KeyParts,
504 R: 'a + key::KeyRole,
505 R2: Copy,
506{
507 fn clone(&self) -> Self {
508 Self {
509 ca: self.ca.clone(),
510 primary: self.primary,
511 }
512 }
513}
514
515
516/// A primary key amalgamation.
517///
518/// A specialized version of [`KeyAmalgamation`].
519///
520pub type PrimaryKeyAmalgamation<'a, P>
521 = KeyAmalgamation<'a, P, key::PrimaryRole, ()>;
522
523/// A subordinate key amalgamation.
524///
525/// A specialized version of [`KeyAmalgamation`].
526///
527pub type SubordinateKeyAmalgamation<'a, P>
528 = KeyAmalgamation<'a, P, key::SubordinateRole, ()>;
529
530
531impl<'a, P> SubordinateKeyAmalgamation<'a, P>
532where
533 P: key::KeyParts,
534{
535 /// Returns the subkey's revocation status at time `t`.
536 ///
537 /// A subkey is revoked at time `t` if:
538 ///
539 /// - There is a live revocation at time `t` that is newer than
540 /// all live self signatures at time `t`, or
541 ///
542 /// - There is a hard revocation (even if it is not live at
543 /// time `t`, and even if there is a newer self-signature).
544 ///
545 /// Note: Certs and subkeys have different criteria from User IDs
546 /// and User Attributes.
547 ///
548 /// Note: this only returns whether this subkey is revoked; it
549 /// does not imply anything about the Cert or other components.
550 ///
551 /// # Examples
552 ///
553 /// ```
554 /// # use sequoia_openpgp as openpgp;
555 /// # use openpgp::cert::prelude::*;
556 /// use openpgp::policy::StandardPolicy;
557 /// #
558 /// # fn main() -> openpgp::Result<()> {
559 /// let p = &StandardPolicy::new();
560 ///
561 /// # let (cert, _) =
562 /// # CertBuilder::general_purpose(Some("alice@example.org"))
563 /// # .generate()?;
564 /// // Display the subkeys' revocation status.
565 /// for ka in cert.keys().subkeys() {
566 /// eprintln!(" Revocation status of {}: {:?}",
567 /// ka.key().fingerprint(), ka.revocation_status(p, None));
568 /// }
569 /// # Ok(()) }
570 /// ```
571 pub fn revocation_status<T>(&self, policy: &dyn Policy, t: T)
572 -> RevocationStatus
573 where
574 T: Into<Option<time::SystemTime>>,
575 {
576 let t = t.into();
577 self.bundle().revocation_status(policy, t)
578 }
579}
580
581/// An amalgamation whose role is not known at compile time.
582///
583/// A specialized version of [`KeyAmalgamation`].
584///
585/// Unlike a [`Key`] or a [`KeyBundle`] with an unspecified role, an
586/// `ErasedKeyAmalgamation` remembers its role; it is just not exposed
587/// to the type system. For details, see the [module-level
588/// documentation].
589///
590/// [`Key`]: crate::packet::key
591/// [`KeyBundle`]: super::super::bundle
592/// [module-level documentation]: self
593pub type ErasedKeyAmalgamation<'a, P>
594 = KeyAmalgamation<'a, P, key::UnspecifiedRole, bool>;
595
596impl<'a, P> seal::Sealed
597 for PrimaryKeyAmalgamation<'a, P>
598 where P: 'a + key::KeyParts
599{}
600impl<'a, P> ValidateAmalgamation<'a, Key<P, key::PrimaryRole>>
601 for PrimaryKeyAmalgamation<'a, P>
602 where P: 'a + key::KeyParts
603{
604 type V = ValidPrimaryKeyAmalgamation<'a, P>;
605
606 fn with_policy<T>(&self, policy: &'a dyn Policy, time: T)
607 -> Result<Self::V>
608 where T: Into<Option<time::SystemTime>>
609 {
610 let ka : ErasedKeyAmalgamation<P> = self.clone().into();
611 Ok(ka.with_policy(policy, time)?
612 .try_into().expect("conversion is symmetric"))
613 }
614}
615
616impl<'a, P> seal::Sealed
617 for SubordinateKeyAmalgamation<'a, P>
618 where P: 'a + key::KeyParts
619{}
620impl<'a, P> ValidateAmalgamation<'a, Key<P, key::SubordinateRole>>
621 for SubordinateKeyAmalgamation<'a, P>
622 where P: 'a + key::KeyParts
623{
624 type V = ValidSubordinateKeyAmalgamation<'a, P>;
625
626 fn with_policy<T>(&self, policy: &'a dyn Policy, time: T)
627 -> Result<Self::V>
628 where T: Into<Option<time::SystemTime>>
629 {
630 let ka : ErasedKeyAmalgamation<P> = self.clone().into();
631 Ok(ka.with_policy(policy, time)?
632 .try_into().expect("conversion is symmetric"))
633 }
634}
635
636impl<'a, P> seal::Sealed
637 for ErasedKeyAmalgamation<'a, P>
638 where P: 'a + key::KeyParts
639{}
640impl<'a, P> ValidateAmalgamation<'a, Key<P, key::UnspecifiedRole>>
641 for ErasedKeyAmalgamation<'a, P>
642 where P: 'a + key::KeyParts
643{
644 type V = ValidErasedKeyAmalgamation<'a, P>;
645
646 fn with_policy<T>(&self, policy: &'a dyn Policy, time: T)
647 -> Result<Self::V>
648 where T: Into<Option<time::SystemTime>>
649 {
650 let time = time.into().unwrap_or_else(crate::now);
651
652 // We need to make sure the certificate is okay. This means
653 // checking the primary key. But, be careful: we don't need
654 // to double-check.
655 if ! self.primary() {
656 let pka = PrimaryKeyAmalgamation::new(self.cert());
657 pka.with_policy(policy, time).context("primary key")?;
658 }
659
660 let binding_signature = self.binding_signature(policy, time)?;
661 let cert = self.ca.cert();
662 let vka = ValidErasedKeyAmalgamation {
663 ka: KeyAmalgamation {
664 ca: self.ca.clone().parts_into_public(),
665 primary: self.primary,
666 },
667 // We need some black magic to avoid infinite
668 // recursion: a ValidCert must be valid for the
669 // specified policy and reference time. A ValidCert
670 // is considered valid if the primary key is valid.
671 // ValidCert::with_policy checks that by calling this
672 // function. So, if we call ValidCert::with_policy
673 // here we'll recurse infinitely.
674 //
675 // But, hope is not lost! We know that if we get
676 // here, we've already checked that the primary key is
677 // valid (see above), or that we're in the process of
678 // evaluating the primary key's validity and we just
679 // need to check the user's policy. So, it is safe to
680 // create a ValidCert from scratch.
681 cert: ValidCert {
682 cert,
683 policy,
684 time,
685 },
686 binding_signature
687 };
688 policy.key(&vka)?;
689 Ok(ValidErasedKeyAmalgamation {
690 ka: KeyAmalgamation {
691 ca: P::convert_key_amalgamation(
692 vka.ka.ca.parts_into_unspecified()).expect("roundtrip"),
693 primary: vka.ka.primary,
694 },
695 cert: vka.cert,
696 binding_signature,
697 })
698 }
699}
700
701impl<'a, P> PrimaryKey<'a, P, key::PrimaryRole>
702 for PrimaryKeyAmalgamation<'a, P>
703 where P: 'a + key::KeyParts
704{
705 fn primary(&self) -> bool {
706 true
707 }
708}
709
710impl<'a, P> PrimaryKey<'a, P, key::SubordinateRole>
711 for SubordinateKeyAmalgamation<'a, P>
712 where P: 'a + key::KeyParts
713{
714 fn primary(&self) -> bool {
715 false
716 }
717}
718
719impl<'a, P> PrimaryKey<'a, P, key::UnspecifiedRole>
720 for ErasedKeyAmalgamation<'a, P>
721 where P: 'a + key::KeyParts
722{
723 fn primary(&self) -> bool {
724 self.primary
725 }
726}
727
728
729impl<'a, P: 'a + key::KeyParts> From<PrimaryKeyAmalgamation<'a, P>>
730 for ErasedKeyAmalgamation<'a, P>
731{
732 fn from(ka: PrimaryKeyAmalgamation<'a, P>) -> Self {
733 ErasedKeyAmalgamation {
734 ca: ka.ca.role_into_unspecified(),
735 primary: true,
736 }
737 }
738}
739
740impl<'a, P: 'a + key::KeyParts> From<SubordinateKeyAmalgamation<'a, P>>
741 for ErasedKeyAmalgamation<'a, P>
742{
743 fn from(ka: SubordinateKeyAmalgamation<'a, P>) -> Self {
744 ErasedKeyAmalgamation {
745 ca: ka.ca.role_into_unspecified(),
746 primary: false,
747 }
748 }
749}
750
751
752// We can infallibly convert part X to part Y for everything but
753// Public -> Secret and Unspecified -> Secret.
754macro_rules! impl_conversion {
755 ($s:ident, $primary:expr, $p1:path, $p2:path) => {
756 impl<'a> From<$s<'a, $p1>>
757 for ErasedKeyAmalgamation<'a, $p2>
758 {
759 fn from(ka: $s<'a, $p1>) -> Self {
760 ErasedKeyAmalgamation {
761 ca: ka.ca.into(),
762 primary: $primary,
763 }
764 }
765 }
766 }
767}
768
769impl_conversion!(PrimaryKeyAmalgamation, true,
770 key::SecretParts, key::PublicParts);
771impl_conversion!(PrimaryKeyAmalgamation, true,
772 key::SecretParts, key::UnspecifiedParts);
773impl_conversion!(PrimaryKeyAmalgamation, true,
774 key::PublicParts, key::UnspecifiedParts);
775impl_conversion!(PrimaryKeyAmalgamation, true,
776 key::UnspecifiedParts, key::PublicParts);
777
778impl_conversion!(SubordinateKeyAmalgamation, false,
779 key::SecretParts, key::PublicParts);
780impl_conversion!(SubordinateKeyAmalgamation, false,
781 key::SecretParts, key::UnspecifiedParts);
782impl_conversion!(SubordinateKeyAmalgamation, false,
783 key::PublicParts, key::UnspecifiedParts);
784impl_conversion!(SubordinateKeyAmalgamation, false,
785 key::UnspecifiedParts, key::PublicParts);
786
787
788impl<'a, P, P2> TryFrom<ErasedKeyAmalgamation<'a, P>>
789 for PrimaryKeyAmalgamation<'a, P2>
790 where P: 'a + key::KeyParts,
791 P2: 'a + key::KeyParts,
792{
793 type Error = anyhow::Error;
794
795 fn try_from(ka: ErasedKeyAmalgamation<'a, P>) -> Result<Self> {
796 if ka.primary {
797 Ok(Self {
798 ca: P2::convert_key_amalgamation(
799 ka.ca.role_into_primary().parts_into_unspecified())?,
800 primary: (),
801 })
802 } else {
803 Err(Error::InvalidArgument(
804 "can't convert a SubordinateKeyAmalgamation \
805 to a PrimaryKeyAmalgamation".into()).into())
806 }
807 }
808}
809
810impl<'a, P, P2> TryFrom<ErasedKeyAmalgamation<'a, P>>
811 for SubordinateKeyAmalgamation<'a, P2>
812 where P: 'a + key::KeyParts,
813 P2: 'a + key::KeyParts,
814{
815 type Error = anyhow::Error;
816
817 fn try_from(ka: ErasedKeyAmalgamation<'a, P>) -> Result<Self> {
818 if ka.primary {
819 Err(Error::InvalidArgument(
820 "can't convert a PrimaryKeyAmalgamation \
821 to a SubordinateKeyAmalgamation".into()).into())
822 } else {
823 Ok(Self {
824 ca: P2::convert_key_amalgamation(
825 ka.ca.role_into_subordinate().parts_into_unspecified())?,
826 primary: (),
827 })
828 }
829 }
830}
831
832impl<'a> PrimaryKeyAmalgamation<'a, key::PublicParts> {
833 pub(crate) fn new(cert: &'a Cert) -> Self {
834 PrimaryKeyAmalgamation {
835 ca: ComponentAmalgamation::new(cert, &cert.primary),
836 primary: (),
837 }
838 }
839}
840
841impl<'a, P> PrimaryKeyAmalgamation<'a, P>
842where
843 P: key::KeyParts,
844{
845 /// Returns the active binding signature at time `t`.
846 ///
847 /// The active binding signature is the most recent, non-revoked
848 /// self-signature that is valid according to the `policy` and
849 /// alive at time `t` (`creation time <= t`, `t < expiry`). If
850 /// there are multiple such signatures then the signatures are
851 /// ordered by their MPIs interpreted as byte strings.
852 ///
853 /// # Examples
854 ///
855 /// ```
856 /// # use sequoia_openpgp as openpgp;
857 /// # use openpgp::cert::prelude::*;
858 /// use openpgp::policy::StandardPolicy;
859 /// #
860 /// # fn main() -> openpgp::Result<()> {
861 /// let p = &StandardPolicy::new();
862 ///
863 /// # let (cert, _) =
864 /// # CertBuilder::general_purpose(Some("alice@example.org"))
865 /// # .generate()?;
866 /// // Display information about the primary key's current active
867 /// // binding signature (the `time` parameter is `None`), if any.
868 /// eprintln!("{:?}", cert.primary_key().binding_signature(p, None));
869 /// # Ok(()) }
870 /// ```
871 pub fn binding_signature<T>(&self, policy: &dyn Policy, time: T)
872 -> Result<&'a Signature>
873 where T: Into<Option<time::SystemTime>>
874 {
875 let time = time.into().unwrap_or_else(crate::now);
876 self.bundle().binding_signature(policy, time)
877 }
878}
879
880impl<'a, P: 'a + key::KeyParts> SubordinateKeyAmalgamation<'a, P> {
881 pub(crate) fn new(
882 cert: &'a Cert, bundle: &'a KeyBundle<P, key::SubordinateRole>)
883 -> Self
884 {
885 SubordinateKeyAmalgamation {
886 ca: ComponentAmalgamation::new(cert, bundle),
887 primary: (),
888 }
889 }
890
891 /// Returns the active binding signature at time `t`.
892 ///
893 /// The active binding signature is the most recent, non-revoked
894 /// self-signature that is valid according to the `policy` and
895 /// alive at time `t` (`creation time <= t`, `t < expiry`). If
896 /// there are multiple such signatures then the signatures are
897 /// ordered by their MPIs interpreted as byte strings.
898 ///
899 /// # Examples
900 ///
901 /// ```
902 /// # use sequoia_openpgp as openpgp;
903 /// # use openpgp::cert::prelude::*;
904 /// use openpgp::policy::StandardPolicy;
905 /// #
906 /// # fn main() -> openpgp::Result<()> {
907 /// let p = &StandardPolicy::new();
908 ///
909 /// # let (cert, _) =
910 /// # CertBuilder::general_purpose(Some("alice@example.org"))
911 /// # .generate()?;
912 /// // Display information about each keys' current active
913 /// // binding signature (the `time` parameter is `None`), if any.
914 /// for k in cert.keys().subkeys() {
915 /// eprintln!("{:?}", k.binding_signature(p, None));
916 /// }
917 /// # Ok(()) }
918 /// ```
919 pub fn binding_signature<T>(&self, policy: &dyn Policy, time: T)
920 -> Result<&'a Signature>
921 where T: Into<Option<time::SystemTime>>
922 {
923 let time = time.into().unwrap_or_else(crate::now);
924 self.bundle().binding_signature(policy, time)
925 }
926}
927
928impl<'a, P: 'a + key::KeyParts> ErasedKeyAmalgamation<'a, P> {
929 /// Returns the key's binding signature as of the reference time,
930 /// if any.
931 ///
932 /// Note: this function is not exported. Users of this interface
933 /// should instead do: `ka.with_policy(policy,
934 /// time)?.binding_signature()`.
935 fn binding_signature<T>(&self, policy: &'a dyn Policy, time: T)
936 -> Result<&'a Signature>
937 where T: Into<Option<time::SystemTime>>
938 {
939 let time = time.into().unwrap_or_else(crate::now);
940 if self.primary {
941 self.cert().primary_userid_relaxed(policy, time, false)
942 .map(|u| u.binding_signature())
943 .or_else(|e0| {
944 // Lookup of the primary user id binding failed.
945 // Look for direct key signatures.
946 self.cert().primary_key().bundle()
947 .binding_signature(policy, time)
948 .map_err(|e1| {
949 // Both lookups failed. Keep the more
950 // meaningful error.
951 if let Some(Error::NoBindingSignature(_))
952 = e1.downcast_ref()
953 {
954 e0 // Return the original error.
955 } else {
956 e1
957 }
958 })
959 })
960 } else {
961 self.bundle().binding_signature(policy, time)
962 }
963 }
964}
965
966
967impl<'a, P, R, R2> KeyAmalgamation<'a, P, R, R2>
968 where P: 'a + key::KeyParts,
969 R: 'a + key::KeyRole,
970
971{
972 /// Returns the component's associated certificate.
973 ///
974 /// ```
975 /// # use sequoia_openpgp as openpgp;
976 /// # use openpgp::cert::prelude::*;
977 /// #
978 /// # fn main() -> openpgp::Result<()> {
979 /// # let (cert, _) =
980 /// # CertBuilder::general_purpose(Some("alice@example.org"))
981 /// # .generate()?;
982 /// for k in cert.keys() {
983 /// // It's not only an identical `Cert`, it's the same one.
984 /// assert!(std::ptr::eq(k.cert(), &cert));
985 /// }
986 /// # Ok(()) }
987 /// ```
988 pub fn cert(&self) -> &'a Cert {
989 self.ca.cert()
990 }
991
992 /// Returns this amalgamation's bundle.
993 pub fn bundle(&self) -> &'a crate::cert::ComponentBundle<Key<P, R>> {
994 self.ca.bundle()
995 }
996
997 /// Returns this amalgamation's component.
998 ///
999 /// # Examples
1000 ///
1001 /// ```
1002 /// # use sequoia_openpgp as openpgp;
1003 /// # use openpgp::cert::prelude::*;
1004 /// #
1005 /// # fn main() -> openpgp::Result<()> {
1006 /// # let (cert, _) =
1007 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1008 /// # .generate()?;
1009 /// // Display some information about any unknown components.
1010 /// for k in cert.keys() {
1011 /// eprintln!(" - {:?}", k.component());
1012 /// }
1013 /// # Ok(()) }
1014 /// ```
1015 pub fn component(&self) -> &'a Key<P, R> {
1016 self.bundle().component()
1017 }
1018
1019 /// Returns the `KeyAmalgamation`'s key.
1020 pub fn key(&self) -> &'a Key<P, R> {
1021 self.component()
1022 }
1023
1024 /// Returns the component's self-signatures.
1025 ///
1026 /// The signatures are validated, and they are sorted by their
1027 /// creation time, most recent first.
1028 ///
1029 /// # Examples
1030 ///
1031 /// ```
1032 /// # use sequoia_openpgp as openpgp;
1033 /// # use openpgp::cert::prelude::*;
1034 /// #
1035 /// # fn main() -> openpgp::Result<()> {
1036 /// # let (cert, _) =
1037 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1038 /// # .generate()?;
1039 /// for (i, ka) in cert.keys().enumerate() {
1040 /// eprintln!("Key #{} ({}) has {:?} self signatures",
1041 /// i, ka.key().fingerprint(),
1042 /// ka.self_signatures().count());
1043 /// }
1044 /// # Ok(()) }
1045 /// ```
1046 pub fn self_signatures(&self) -> impl Iterator<Item=&'a Signature> + Send + Sync {
1047 self.ca.self_signatures()
1048 }
1049
1050 /// Returns the component's third-party certifications.
1051 ///
1052 /// The signatures are *not* validated. They are sorted by their
1053 /// creation time, most recent first.
1054 ///
1055 /// # Examples
1056 ///
1057 /// ```
1058 /// # use sequoia_openpgp as openpgp;
1059 /// # use openpgp::cert::prelude::*;
1060 /// #
1061 /// # fn main() -> openpgp::Result<()> {
1062 /// # let (cert, _) =
1063 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1064 /// # .generate()?;
1065 /// for k in cert.keys() {
1066 /// eprintln!("Key {} has {:?} unverified, third-party certifications",
1067 /// k.key().fingerprint(),
1068 /// k.certifications().count());
1069 /// }
1070 /// # Ok(()) }
1071 /// ```
1072 pub fn certifications(&self) -> impl Iterator<Item=&'a Signature> + Send + Sync {
1073 self.ca.certifications()
1074 }
1075
1076 /// Returns the component's revocations that were issued by the
1077 /// certificate holder.
1078 ///
1079 /// The revocations are validated, and they are sorted by their
1080 /// creation time, most recent first.
1081 ///
1082 /// # Examples
1083 ///
1084 /// ```
1085 /// # use sequoia_openpgp as openpgp;
1086 /// # use openpgp::cert::prelude::*;
1087 /// use openpgp::policy::StandardPolicy;
1088 /// #
1089 /// # fn main() -> openpgp::Result<()> {
1090 /// let p = &StandardPolicy::new();
1091 ///
1092 /// # let (cert, _) =
1093 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1094 /// # .generate()?;
1095 /// for k in cert.keys() {
1096 /// eprintln!("Key {} has {:?} revocation certificates.",
1097 /// k.key().fingerprint(),
1098 /// k.self_revocations().count());
1099 /// }
1100 /// # Ok(()) }
1101 /// ```
1102 pub fn self_revocations(&self) -> impl Iterator<Item=&'a Signature> + Send + Sync {
1103 self.ca.self_revocations()
1104 }
1105
1106 /// Returns the component's revocations that were issued by other
1107 /// certificates.
1108 ///
1109 /// The revocations are *not* validated. They are sorted by their
1110 /// creation time, most recent first.
1111 ///
1112 /// # Examples
1113 ///
1114 /// ```
1115 /// # use sequoia_openpgp as openpgp;
1116 /// # use openpgp::cert::prelude::*;
1117 /// use openpgp::policy::StandardPolicy;
1118 /// #
1119 /// # fn main() -> openpgp::Result<()> {
1120 /// let p = &StandardPolicy::new();
1121 ///
1122 /// # let (cert, _) =
1123 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1124 /// # .generate()?;
1125 /// for k in cert.keys() {
1126 /// eprintln!("Key {} has {:?} unverified, third-party revocation certificates.",
1127 /// k.key().fingerprint(),
1128 /// k.other_revocations().count());
1129 /// }
1130 /// # Ok(()) }
1131 /// ```
1132 pub fn other_revocations(&self) -> impl Iterator<Item=&'a Signature> + Send + Sync {
1133 self.ca.other_revocations()
1134 }
1135
1136 /// Returns all of the component's signatures.
1137 ///
1138 /// Only the self-signatures are validated. The signatures are
1139 /// sorted first by type, then by creation time. The self
1140 /// revocations come first, then the self signatures,
1141 /// then any certification approval key signatures,
1142 /// certifications, and third-party revocations coming last. This
1143 /// function may return additional types of signatures that could
1144 /// be associated to this component.
1145 ///
1146 /// # Examples
1147 ///
1148 /// ```
1149 /// # use sequoia_openpgp as openpgp;
1150 /// # use openpgp::cert::prelude::*;
1151 /// use openpgp::policy::StandardPolicy;
1152 /// #
1153 /// # fn main() -> openpgp::Result<()> {
1154 /// let p = &StandardPolicy::new();
1155 ///
1156 /// # let (cert, _) =
1157 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1158 /// # .generate()?;
1159 /// for (i, ka) in cert.keys().enumerate() {
1160 /// eprintln!("Key #{} ({}) has {:?} signatures",
1161 /// i, ka.key().fingerprint(),
1162 /// ka.signatures().count());
1163 /// }
1164 /// # Ok(()) }
1165 /// ```
1166 pub fn signatures(&self)
1167 -> impl Iterator<Item = &'a Signature> + Send + Sync {
1168 self.ca.signatures()
1169 }
1170
1171 /// Forwarder for the conversion macros.
1172 pub(crate) fn has_secret(&self) -> bool {
1173 self.key().has_secret()
1174 }
1175}
1176
1177impl<'a, P, R, R2> KeyAmalgamation<'a, P, R, R2>
1178 where Self: PrimaryKey<'a, P, R>,
1179 P: 'a + key::KeyParts,
1180 R: 'a + key::KeyRole,
1181{
1182 /// Returns the third-party certifications issued by the specified
1183 /// key, and valid at the specified time.
1184 ///
1185 /// This function returns the certifications issued by the
1186 /// specified key. Specifically, it returns a certification if:
1187 ///
1188 /// - it is well-formed,
1189 /// - it is live with respect to the reference time,
1190 /// - it conforms to the policy, and
1191 /// - the signature is cryptographically valid.
1192 ///
1193 /// This method is implemented on a [`KeyAmalgamation`] and not
1194 /// a [`ValidKeyAmalgamation`], because a third-party
1195 /// certification does not require the key to be self-signed.
1196 ///
1197 /// # Examples
1198 ///
1199 /// Alice has certified that a certificate belongs to Bob on two
1200 /// occasions. Whereas
1201 /// [`KeyAmalgamation::valid_certifications_by_key`] returns
1202 /// both certifications,
1203 /// [`KeyAmalgamation::active_certifications_by_key`] only
1204 /// returns the most recent certification.
1205 ///
1206 /// ```rust
1207 /// use sequoia_openpgp as openpgp;
1208 /// use openpgp::cert::prelude::*;
1209 /// # use openpgp::packet::signature::SignatureBuilder;
1210 /// # use openpgp::packet::UserID;
1211 /// use openpgp::policy::StandardPolicy;
1212 /// # use openpgp::types::SignatureType;
1213 ///
1214 /// const P: &StandardPolicy = &StandardPolicy::new();
1215 ///
1216 /// # fn main() -> openpgp::Result<()> {
1217 /// # let epoch = std::time::SystemTime::now()
1218 /// # - std::time::Duration::new(100, 0);
1219 /// # let t0 = epoch;
1220 /// #
1221 /// # let (alice, _) = CertBuilder::new()
1222 /// # .set_creation_time(t0)
1223 /// # .add_userid("<alice@example.org>")
1224 /// # .generate()
1225 /// # .unwrap();
1226 /// let alice: Cert = // ...
1227 /// # alice;
1228 /// #
1229 /// # let bob_userid = "<bob@example.org>";
1230 /// # let (bob, _) = CertBuilder::new()
1231 /// # .set_creation_time(t0)
1232 /// # .add_userid(bob_userid)
1233 /// # .generate()
1234 /// # .unwrap();
1235 /// let bob: Cert = // ...
1236 /// # bob;
1237 ///
1238 /// # // Alice has not certified Bob's User ID.
1239 /// # let ka = bob.primary_key();
1240 /// # assert_eq!(
1241 /// # ka.active_certifications_by_key(
1242 /// # P, t0, alice.primary_key().key()).count(),
1243 /// # 0);
1244 /// #
1245 /// # // Have Alice certify Bob's certificate.
1246 /// # let mut alice_signer = alice
1247 /// # .keys()
1248 /// # .with_policy(P, None)
1249 /// # .for_certification()
1250 /// # .next().expect("have a certification-capable key")
1251 /// # .key()
1252 /// # .clone()
1253 /// # .parts_into_secret().expect("have unencrypted key material")
1254 /// # .into_keypair().expect("have unencrypted key material");
1255 /// #
1256 /// # let mut bob = bob;
1257 /// # for i in 1..=2usize {
1258 /// # let ti = t0 + std::time::Duration::new(i as u64, 0);
1259 /// #
1260 /// # let certification = SignatureBuilder::new(SignatureType::DirectKey)
1261 /// # .set_signature_creation_time(ti)?
1262 /// # .sign_direct_key(
1263 /// # &mut alice_signer,
1264 /// # bob.primary_key().key())?;
1265 /// # bob = bob.insert_packets(certification)?.0;
1266 /// #
1267 /// # let ka = bob.primary_key();
1268 /// # assert_eq!(
1269 /// # ka.valid_certifications_by_key(
1270 /// # P, ti, alice.primary_key().key()).count(),
1271 /// # i);
1272 /// #
1273 /// # assert_eq!(
1274 /// # ka.active_certifications_by_key(
1275 /// # P, ti, alice.primary_key().key()).count(),
1276 /// # 1);
1277 /// # }
1278 /// let bob_pk = bob.primary_key();
1279 ///
1280 /// let valid_certifications = bob_pk.valid_certifications_by_key(
1281 /// P, None, alice.primary_key().key());
1282 /// // Alice certified Bob's certificate twice.
1283 /// assert_eq!(valid_certifications.count(), 2);
1284 ///
1285 /// let active_certifications = bob_pk.active_certifications_by_key(
1286 /// P, None, alice.primary_key().key());
1287 /// // But only the most recent one is active.
1288 /// assert_eq!(active_certifications.count(), 1);
1289 /// # Ok(()) }
1290 /// ```
1291 pub fn valid_certifications_by_key<T, PK>(&self,
1292 policy: &'a dyn Policy,
1293 reference_time: T,
1294 issuer: PK)
1295 -> impl Iterator<Item=&Signature> + Send + Sync
1296 where
1297 T: Into<Option<time::SystemTime>>,
1298 PK: Into<&'a Key<key::PublicParts,
1299 key::UnspecifiedRole>>,
1300 {
1301 let reference_time = reference_time.into();
1302 let issuer = issuer.into();
1303
1304 let primary = self.primary();
1305
1306 self.ca.valid_certifications_by_key_(
1307 policy, reference_time, issuer, false,
1308 self.certifications(),
1309 move |sig| {
1310 if primary {
1311 sig.clone().verify_direct_key(
1312 issuer,
1313 self.component().role_as_primary())
1314 } else {
1315 sig.clone().verify_subkey_binding(
1316 issuer,
1317 self.cert().primary_key().key(),
1318 self.component().role_as_subordinate())
1319 }
1320 })
1321 }
1322
1323 /// Returns any active third-party certifications issued by the
1324 /// specified key.
1325 ///
1326 /// This function is like
1327 /// [`KeyAmalgamation::valid_certifications_by_key`], but it
1328 /// only returns active certifications. Active certifications are
1329 /// the most recent valid certifications with respect to the
1330 /// reference time.
1331 ///
1332 /// Although there is normally only a single active certification,
1333 /// there can be multiple certifications with the same timestamp.
1334 /// In this case, all of them are returned.
1335 ///
1336 /// Unlike self-signatures, multiple third-party certifications
1337 /// issued by the same key at the same time can be sensible. For
1338 /// instance, Alice may fully trust a CA for user IDs in a
1339 /// particular domain, and partially trust it for everything else.
1340 /// This can only be expressed using multiple certifications.
1341 ///
1342 /// This method is implemented on a [`KeyAmalgamation`] and not
1343 /// a [`ValidKeyAmalgamation`], because a third-party
1344 /// certification does not require the user ID to be self-signed.
1345 ///
1346 /// # Examples
1347 ///
1348 /// See the examples for
1349 /// [`KeyAmalgamation::valid_certifications_by_key`].
1350 pub fn active_certifications_by_key<T, PK>(&self,
1351 policy: &'a dyn Policy,
1352 reference_time: T,
1353 issuer: PK)
1354 -> impl Iterator<Item=&Signature> + Send + Sync
1355 where
1356 T: Into<Option<time::SystemTime>>,
1357 PK: Into<&'a Key<key::PublicParts,
1358 key::UnspecifiedRole>>,
1359 {
1360 let reference_time = reference_time.into();
1361 let issuer = issuer.into();
1362
1363 let primary = self.primary();
1364
1365 self.ca.valid_certifications_by_key_(
1366 policy, reference_time, issuer, true,
1367 self.certifications(),
1368 move |sig| {
1369 if primary {
1370 sig.clone().verify_direct_key(
1371 issuer,
1372 self.component().role_as_primary())
1373 } else {
1374 sig.clone().verify_subkey_binding(
1375 issuer,
1376 self.cert().primary_key().key(),
1377 &self.component().role_as_subordinate())
1378 }
1379 })
1380 }
1381
1382 /// Returns the third-party revocations issued by the specified
1383 /// key, and valid at the specified time.
1384 ///
1385 /// This function returns the revocations issued by the specified
1386 /// key. Specifically, it returns a revocation if:
1387 ///
1388 /// - it is well-formed,
1389 /// - it is a [hard revocation](crate::types::RevocationType),
1390 /// or it is live with respect to the reference time,
1391 /// - it conforms to the policy, and
1392 /// - the signature is cryptographically valid.
1393 ///
1394 /// This method is implemented on a [`KeyAmalgamation`] and not
1395 /// a [`ValidKeyAmalgamation`], because a third-party
1396 /// revocation does not require the key to be self-signed.
1397 ///
1398 /// # Examples
1399 ///
1400 /// Alice revoked Bob's certificate.
1401 ///
1402 /// ```rust
1403 /// use sequoia_openpgp as openpgp;
1404 /// use openpgp::cert::prelude::*;
1405 /// # use openpgp::Packet;
1406 /// # use openpgp::packet::signature::SignatureBuilder;
1407 /// # use openpgp::packet::UserID;
1408 /// use openpgp::policy::StandardPolicy;
1409 /// # use openpgp::types::ReasonForRevocation;
1410 /// # use openpgp::types::SignatureType;
1411 ///
1412 /// const P: &StandardPolicy = &StandardPolicy::new();
1413 ///
1414 /// # fn main() -> openpgp::Result<()> {
1415 /// # let epoch = std::time::SystemTime::now()
1416 /// # - std::time::Duration::new(100, 0);
1417 /// # let t0 = epoch;
1418 /// # let t1 = epoch + std::time::Duration::new(1, 0);
1419 /// #
1420 /// # let (alice, _) = CertBuilder::new()
1421 /// # .set_creation_time(t0)
1422 /// # .add_userid("<alice@example.org>")
1423 /// # .generate()
1424 /// # .unwrap();
1425 /// let alice: Cert = // ...
1426 /// # alice;
1427 /// #
1428 /// # let bob_userid = "<bob@example.org>";
1429 /// # let (bob, _) = CertBuilder::new()
1430 /// # .set_creation_time(t0)
1431 /// # .add_userid(bob_userid)
1432 /// # .generate()
1433 /// # .unwrap();
1434 /// let bob: Cert = // ...
1435 /// # bob;
1436 ///
1437 /// # // Have Alice certify Bob's certificate.
1438 /// # let mut alice_signer = alice
1439 /// # .keys()
1440 /// # .with_policy(P, None)
1441 /// # .for_certification()
1442 /// # .next().expect("have a certification-capable key")
1443 /// # .key()
1444 /// # .clone()
1445 /// # .parts_into_secret().expect("have unencrypted key material")
1446 /// # .into_keypair().expect("have unencrypted key material");
1447 /// #
1448 /// # let certification = SignatureBuilder::new(SignatureType::KeyRevocation)
1449 /// # .set_signature_creation_time(t1)?
1450 /// # .set_reason_for_revocation(
1451 /// # ReasonForRevocation::KeyRetired, b"")?
1452 /// # .sign_direct_key(
1453 /// # &mut alice_signer,
1454 /// # bob.primary_key().key())?;
1455 /// # let bob = bob.insert_packets(certification)?.0;
1456 /// let ka = bob.primary_key();
1457 ///
1458 /// let revs = ka.valid_third_party_revocations_by_key(
1459 /// P, None, alice.primary_key().key());
1460 /// // Alice revoked Bob's certificate.
1461 /// assert_eq!(revs.count(), 1);
1462 /// # Ok(()) }
1463 /// ```
1464 pub fn valid_third_party_revocations_by_key<T, PK>(&self,
1465 policy: &'a dyn Policy,
1466 reference_time: T,
1467 issuer: PK)
1468 -> impl Iterator<Item=&Signature> + Send + Sync
1469 where
1470 T: Into<Option<time::SystemTime>>,
1471 PK: Into<&'a Key<key::PublicParts,
1472 key::UnspecifiedRole>>,
1473 {
1474 let issuer = issuer.into();
1475 let reference_time = reference_time.into();
1476
1477 let primary = self.primary();
1478
1479 self.ca.valid_certifications_by_key_(
1480 policy, reference_time, issuer, false,
1481 self.other_revocations(),
1482 move |sig| {
1483 if primary {
1484 sig.clone().verify_primary_key_revocation(
1485 issuer,
1486 self.component().role_as_primary())
1487 } else {
1488 sig.clone().verify_subkey_revocation(
1489 issuer,
1490 self.cert().primary_key().key(),
1491 &self.component().role_as_subordinate())
1492 }
1493 })
1494 }
1495}
1496
1497/// A `KeyAmalgamation` plus a `Policy` and a reference time.
1498///
1499/// In the same way that a [`ValidComponentAmalgamation`] extends a
1500/// [`ComponentAmalgamation`], a `ValidKeyAmalgamation` extends a
1501/// [`KeyAmalgamation`]: a `ValidKeyAmalgamation` combines a
1502/// `KeyAmalgamation`, a [`Policy`], and a reference time. This
1503/// allows it to implement the [`ValidAmalgamation`] trait, which
1504/// provides methods like [`ValidAmalgamation::binding_signature`] that require a
1505/// `Policy` and a reference time. Although `KeyAmalgamation` could
1506/// implement these methods by requiring that the caller explicitly
1507/// pass them in, embedding them in the `ValidKeyAmalgamation` helps
1508/// ensure that multipart operations, even those that span multiple
1509/// functions, use the same `Policy` and reference time.
1510///
1511/// A `ValidKeyAmalgamation` can be obtained by transforming a
1512/// `KeyAmalgamation` using [`ValidateAmalgamation::with_policy`]. A
1513/// [`KeyAmalgamationIter`] can also be changed to yield
1514/// `ValidKeyAmalgamation`s.
1515///
1516/// A `ValidKeyAmalgamation` is guaranteed to come from a valid
1517/// certificate, and have a valid and live *binding* signature at the
1518/// specified reference time. Note: this only means that the binding
1519/// signatures are live; it says nothing about whether the
1520/// *certificate* or the *`Key`* is live and non-revoked. If you care
1521/// about those things, you need to check them separately.
1522///
1523/// # Examples:
1524///
1525/// Find all non-revoked, live, signing-capable keys:
1526///
1527/// ```
1528/// # use sequoia_openpgp as openpgp;
1529/// # use openpgp::cert::prelude::*;
1530/// use openpgp::policy::StandardPolicy;
1531/// use openpgp::types::RevocationStatus;
1532///
1533/// # fn main() -> openpgp::Result<()> {
1534/// let p = &StandardPolicy::new();
1535///
1536/// # let (cert, _) = CertBuilder::new()
1537/// # .add_userid("Alice")
1538/// # .add_signing_subkey()
1539/// # .add_transport_encryption_subkey()
1540/// # .generate().unwrap();
1541/// // `with_policy` ensures that the certificate and any components
1542/// // that it returns have valid *binding signatures*. But, we still
1543/// // need to check that the certificate and `Key` are not revoked,
1544/// // and live.
1545/// //
1546/// // Note: `ValidKeyAmalgamation::revocation_status`, etc. use the
1547/// // embedded policy and timestamp. Even though we used `None` for
1548/// // the timestamp (i.e., now), they are guaranteed to use the same
1549/// // timestamp, because `with_policy` eagerly transforms it into
1550/// // the current time.
1551/// let cert = cert.with_policy(p, None)?;
1552/// if let RevocationStatus::Revoked(_revs) = cert.revocation_status() {
1553/// // Revoked by the certificate holder. (If we care about
1554/// // designated revokers, then we need to check those
1555/// // ourselves.)
1556/// # unreachable!();
1557/// } else if let Err(_err) = cert.alive() {
1558/// // Certificate was created in the future or is expired.
1559/// # unreachable!();
1560/// } else {
1561/// // `ValidCert::keys` returns `ValidKeyAmalgamation`s.
1562/// for ka in cert.keys() {
1563/// if let RevocationStatus::Revoked(_revs) = ka.revocation_status() {
1564/// // Revoked by the key owner. (If we care about
1565/// // designated revokers, then we need to check those
1566/// // ourselves.)
1567/// # unreachable!();
1568/// } else if let Err(_err) = ka.alive() {
1569/// // Key was created in the future or is expired.
1570/// # unreachable!();
1571/// } else if ! ka.for_signing() {
1572/// // We're looking for a signing-capable key, skip this one.
1573/// } else {
1574/// // Use it!
1575/// }
1576/// }
1577/// }
1578/// # Ok(()) }
1579/// ```
1580///
1581/// [`ValidComponentAmalgamation`]: super::ValidComponentAmalgamation
1582/// [`ComponentAmalgamation`]: super::ComponentAmalgamation
1583/// [`Policy`]: crate::policy::Policy
1584/// [`ValidAmalgamation`]: super::ValidAmalgamation
1585/// [`ValidAmalgamation::binding_signature`]: super::ValidAmalgamation::binding_signature()
1586/// [`ValidateAmalgamation::with_policy`]: super::ValidateAmalgamation::with_policy
1587#[derive(Debug, Clone)]
1588pub struct ValidKeyAmalgamation<'a, P, R, R2>
1589 where P: 'a + key::KeyParts,
1590 R: 'a + key::KeyRole,
1591 R2: Copy,
1592{
1593 // Ouch, ouch, ouch! ka is a `KeyAmalgamation`, which contains a
1594 // reference to a `Cert`. `cert` is a `ValidCert` and contains a
1595 // reference to the same `Cert`! We do this so that
1596 // `ValidKeyAmalgamation` can deref to a `KeyAmalgamation` and
1597 // `ValidKeyAmalgamation::cert` can return a `&ValidCert`.
1598
1599 ka: KeyAmalgamation<'a, P, R, R2>,
1600 cert: ValidCert<'a>,
1601
1602 // The binding signature at time `time`. (This is just a cache.)
1603 binding_signature: &'a Signature,
1604}
1605assert_send_and_sync!(ValidKeyAmalgamation<'_, P, R, R2>
1606 where P: key::KeyParts,
1607 R: key::KeyRole,
1608 R2: Copy,
1609);
1610
1611
1612impl<'a, P, R, R2> ValidKeyAmalgamation<'a, P, R, R2>
1613where
1614 P: 'a + key::KeyParts,
1615 R: 'a + key::KeyRole,
1616 R2: Copy,
1617{
1618 /// Returns the component's associated certificate.
1619 ///
1620 /// ```
1621 /// # use sequoia_openpgp as openpgp;
1622 /// # use openpgp::cert::prelude::*;
1623 /// use openpgp::policy::StandardPolicy;
1624 /// #
1625 /// # fn main() -> openpgp::Result<()> {
1626 /// let p = &StandardPolicy::new();
1627 ///
1628 /// # let (cert, _) =
1629 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1630 /// # .generate()?;
1631 /// for k in cert.with_policy(p, None)?.keys() {
1632 /// // It's not only an identical `Cert`, it's the same one.
1633 /// assert!(std::ptr::eq(k.cert(), &cert));
1634 /// }
1635 /// # Ok(()) }
1636 /// ```
1637 pub fn cert(&self) -> &'a Cert {
1638 self.ka.cert()
1639 }
1640
1641 /// Returns the valid amalgamation's active binding signature.
1642 ///
1643 /// The active binding signature is the most recent, non-revoked
1644 /// self-signature that is valid according to the `policy` and
1645 /// alive at time `t` (`creation time <= t`, `t < expiry`). If
1646 /// there are multiple such signatures then the signatures are
1647 /// ordered by their MPIs interpreted as byte strings.
1648 ///
1649 /// # Examples
1650 ///
1651 /// ```
1652 /// # use sequoia_openpgp as openpgp;
1653 /// # use openpgp::cert::prelude::*;
1654 /// use openpgp::policy::StandardPolicy;
1655 /// #
1656 /// # fn main() -> openpgp::Result<()> {
1657 /// let p = &StandardPolicy::new();
1658 ///
1659 /// # let (cert, _) =
1660 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1661 /// # .generate()?;
1662 /// // Display information about each User ID's current active
1663 /// // binding signature (the `time` parameter is `None`), if any.
1664 /// for ua in cert.with_policy(p, None)?.userids() {
1665 /// eprintln!("{:?}", ua.binding_signature());
1666 /// }
1667 /// # Ok(()) }
1668 /// ```
1669 pub fn binding_signature(&self) -> &'a Signature {
1670 self.binding_signature
1671 }
1672
1673 /// Returns the valid amalgamation's amalgamation.
1674 ///
1675 /// # Examples
1676 ///
1677 /// ```
1678 /// # use sequoia_openpgp as openpgp;
1679 /// # use openpgp::cert::prelude::*;
1680 /// use openpgp::policy::StandardPolicy;
1681 ///
1682 /// # fn main() -> openpgp::Result<()> {
1683 /// let p = &StandardPolicy::new();
1684 ///
1685 /// # let (cert, _) = CertBuilder::new()
1686 /// # .add_userid("Alice")
1687 /// # .add_signing_subkey()
1688 /// # .add_transport_encryption_subkey()
1689 /// # .generate()?;
1690 /// // Get a key amalgamation.
1691 /// let ka = cert.primary_key();
1692 ///
1693 /// // Validate it, yielding a valid key amalgamation.
1694 /// let vka = ka.with_policy(p, None)?;
1695 ///
1696 /// // And here we get the amalgamation back.
1697 /// let ka2 = vka.amalgamation();
1698 /// assert_eq!(&ka, ka2);
1699 /// # Ok(()) }
1700 /// ```
1701 pub fn amalgamation(&self) -> &KeyAmalgamation<'a, P, R, R2> {
1702 &self.ka
1703 }
1704
1705 /// Returns this amalgamation's bundle.
1706 pub fn bundle(&self) -> &'a crate::cert::ComponentBundle<Key<P, R>> {
1707 self.ka.bundle()
1708 }
1709
1710 /// Returns this amalgamation's component.
1711 ///
1712 /// # Examples
1713 ///
1714 /// ```
1715 /// # use sequoia_openpgp as openpgp;
1716 /// # use openpgp::cert::prelude::*;
1717 /// use openpgp::policy::StandardPolicy;
1718 /// #
1719 /// # fn main() -> openpgp::Result<()> {
1720 /// let p = &StandardPolicy::new();
1721 ///
1722 /// # let (cert, _) =
1723 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1724 /// # .generate()?;
1725 /// // Display some information about any unknown components.
1726 /// for k in cert.with_policy(p, None)?.keys() {
1727 /// eprintln!(" - {:?}", k.component());
1728 /// }
1729 /// # Ok(()) }
1730 /// ```
1731 pub fn component(&self) -> &'a Key<P, R> {
1732 self.bundle().component()
1733 }
1734
1735 /// Returns the `KeyAmalgamation`'s key.
1736 pub fn key(&self) -> &'a Key<P, R> {
1737 self.component()
1738 }
1739
1740 /// Returns the component's self-signatures.
1741 ///
1742 /// The signatures are validated, and they are sorted by their
1743 /// creation time, most recent first.
1744 ///
1745 /// # Examples
1746 ///
1747 /// ```
1748 /// # use sequoia_openpgp as openpgp;
1749 /// # use openpgp::cert::prelude::*;
1750 /// use openpgp::policy::StandardPolicy;
1751 /// #
1752 /// # fn main() -> openpgp::Result<()> {
1753 /// let p = &StandardPolicy::new();
1754 ///
1755 /// # let (cert, _) =
1756 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1757 /// # .generate()?;
1758 /// for (i, ka) in cert.with_policy(p, None)?.keys().enumerate() {
1759 /// eprintln!("Key #{} ({}) has {:?} self signatures",
1760 /// i, ka.key().fingerprint(),
1761 /// ka.self_signatures().count());
1762 /// }
1763 /// # Ok(()) }
1764 /// ```
1765 pub fn self_signatures(&self) -> impl Iterator<Item=&'a Signature> + Send + Sync {
1766 self.ka.self_signatures()
1767 }
1768
1769 /// Returns the component's third-party certifications.
1770 ///
1771 /// The signatures are *not* validated. They are sorted by their
1772 /// creation time, most recent first.
1773 ///
1774 /// # Examples
1775 ///
1776 /// ```
1777 /// # use sequoia_openpgp as openpgp;
1778 /// # use openpgp::cert::prelude::*;
1779 /// use openpgp::policy::StandardPolicy;
1780 /// #
1781 /// # fn main() -> openpgp::Result<()> {
1782 /// let p = &StandardPolicy::new();
1783 ///
1784 /// # let (cert, _) =
1785 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1786 /// # .generate()?;
1787 /// for k in cert.with_policy(p, None)?.keys() {
1788 /// eprintln!("Key {} has {:?} unverified, third-party certifications",
1789 /// k.key().fingerprint(),
1790 /// k.certifications().count());
1791 /// }
1792 /// # Ok(()) }
1793 /// ```
1794 pub fn certifications(&self) -> impl Iterator<Item=&'a Signature> + Send + Sync {
1795 self.ka.certifications()
1796 }
1797
1798 /// Returns the component's revocations that were issued by the
1799 /// certificate holder.
1800 ///
1801 /// The revocations are validated, and they are sorted by their
1802 /// creation time, most recent first.
1803 ///
1804 /// # Examples
1805 ///
1806 /// ```
1807 /// # use sequoia_openpgp as openpgp;
1808 /// # use openpgp::cert::prelude::*;
1809 /// use openpgp::policy::StandardPolicy;
1810 /// #
1811 /// # fn main() -> openpgp::Result<()> {
1812 /// let p = &StandardPolicy::new();
1813 ///
1814 /// # let (cert, _) =
1815 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1816 /// # .generate()?;
1817 /// for k in cert.with_policy(p, None)?.keys() {
1818 /// eprintln!("Key {} has {:?} revocation certificates.",
1819 /// k.key().fingerprint(),
1820 /// k.self_revocations().count());
1821 /// }
1822 /// # Ok(()) }
1823 /// ```
1824 pub fn self_revocations(&self) -> impl Iterator<Item=&'a Signature> + Send + Sync {
1825 self.ka.self_revocations()
1826 }
1827
1828 /// Returns the component's revocations that were issued by other
1829 /// certificates.
1830 ///
1831 /// The revocations are *not* validated. They are sorted by their
1832 /// creation time, most recent first.
1833 ///
1834 /// # Examples
1835 ///
1836 /// ```
1837 /// # use sequoia_openpgp as openpgp;
1838 /// # use openpgp::cert::prelude::*;
1839 /// use openpgp::policy::StandardPolicy;
1840 /// #
1841 /// # fn main() -> openpgp::Result<()> {
1842 /// let p = &StandardPolicy::new();
1843 ///
1844 /// # let (cert, _) =
1845 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1846 /// # .generate()?;
1847 /// for k in cert.with_policy(p, None)?.keys() {
1848 /// eprintln!("Key {} has {:?} unverified, third-party revocation certificates.",
1849 /// k.key().fingerprint(),
1850 /// k.other_revocations().count());
1851 /// }
1852 /// # Ok(()) }
1853 /// ```
1854 pub fn other_revocations(&self) -> impl Iterator<Item=&'a Signature> + Send + Sync {
1855 self.ka.other_revocations()
1856 }
1857
1858 /// Returns all of the component's signatures.
1859 ///
1860 /// Only the self-signatures are validated. The signatures are
1861 /// sorted first by type, then by creation time. The self
1862 /// revocations come first, then the self signatures,
1863 /// then any certification approval key signatures,
1864 /// certifications, and third-party revocations coming last. This
1865 /// function may return additional types of signatures that could
1866 /// be associated to this component.
1867 ///
1868 /// # Examples
1869 ///
1870 /// ```
1871 /// # use sequoia_openpgp as openpgp;
1872 /// # use openpgp::cert::prelude::*;
1873 /// use openpgp::policy::StandardPolicy;
1874 /// #
1875 /// # fn main() -> openpgp::Result<()> {
1876 /// let p = &StandardPolicy::new();
1877 ///
1878 /// # let (cert, _) =
1879 /// # CertBuilder::general_purpose(Some("alice@example.org"))
1880 /// # .generate()?;
1881 /// for (i, ka) in cert.with_policy(p, None)?.keys().enumerate() {
1882 /// eprintln!("Key #{} ({}) has {:?} signatures",
1883 /// i, ka.key().fingerprint(),
1884 /// ka.signatures().count());
1885 /// }
1886 /// # Ok(()) }
1887 /// ```
1888 pub fn signatures(&self)
1889 -> impl Iterator<Item = &'a Signature> + Send + Sync {
1890 self.ka.signatures()
1891 }
1892
1893 /// Forwarder for the conversion macros.
1894 pub(crate) fn has_secret(&self) -> bool {
1895 self.key().has_secret()
1896 }
1897}
1898
1899/// A Valid primary Key, and its associated data.
1900///
1901/// A specialized version of [`ValidKeyAmalgamation`].
1902///
1903pub type ValidPrimaryKeyAmalgamation<'a, P>
1904 = ValidKeyAmalgamation<'a, P, key::PrimaryRole, ()>;
1905
1906/// A Valid subkey, and its associated data.
1907///
1908/// A specialized version of [`ValidKeyAmalgamation`].
1909///
1910pub type ValidSubordinateKeyAmalgamation<'a, P>
1911 = ValidKeyAmalgamation<'a, P, key::SubordinateRole, ()>;
1912
1913/// A valid key whose role is not known at compile time.
1914///
1915/// A specialized version of [`ValidKeyAmalgamation`].
1916///
1917pub type ValidErasedKeyAmalgamation<'a, P>
1918 = ValidKeyAmalgamation<'a, P, key::UnspecifiedRole, bool>;
1919
1920
1921impl<'a, P, R, R2> From<ValidKeyAmalgamation<'a, P, R, R2>>
1922 for KeyAmalgamation<'a, P, R, R2>
1923 where P: 'a + key::KeyParts,
1924 R: 'a + key::KeyRole,
1925 R2: Copy,
1926{
1927 fn from(vka: ValidKeyAmalgamation<'a, P, R, R2>) -> Self {
1928 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
1929 vka.ka
1930 }
1931}
1932
1933impl<'a, P: 'a + key::KeyParts> From<ValidPrimaryKeyAmalgamation<'a, P>>
1934 for ValidErasedKeyAmalgamation<'a, P>
1935{
1936 fn from(vka: ValidPrimaryKeyAmalgamation<'a, P>) -> Self {
1937 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
1938 ValidErasedKeyAmalgamation {
1939 ka: vka.ka.into(),
1940 cert: vka.cert,
1941 binding_signature: vka.binding_signature,
1942 }
1943 }
1944}
1945
1946impl<'a, P: 'a + key::KeyParts> From<&ValidPrimaryKeyAmalgamation<'a, P>>
1947 for ValidErasedKeyAmalgamation<'a, P>
1948{
1949 fn from(vka: &ValidPrimaryKeyAmalgamation<'a, P>) -> Self {
1950 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
1951 ValidErasedKeyAmalgamation {
1952 ka: vka.ka.clone().into(),
1953 cert: vka.cert.clone(),
1954 binding_signature: vka.binding_signature,
1955 }
1956 }
1957}
1958
1959impl<'a, P: 'a + key::KeyParts> From<ValidSubordinateKeyAmalgamation<'a, P>>
1960 for ValidErasedKeyAmalgamation<'a, P>
1961{
1962 fn from(vka: ValidSubordinateKeyAmalgamation<'a, P>) -> Self {
1963 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
1964 ValidErasedKeyAmalgamation {
1965 ka: vka.ka.into(),
1966 cert: vka.cert,
1967 binding_signature: vka.binding_signature,
1968 }
1969 }
1970}
1971
1972impl<'a, P: 'a + key::KeyParts> From<&ValidSubordinateKeyAmalgamation<'a, P>>
1973 for ValidErasedKeyAmalgamation<'a, P>
1974{
1975 fn from(vka: &ValidSubordinateKeyAmalgamation<'a, P>) -> Self {
1976 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
1977 ValidErasedKeyAmalgamation {
1978 ka: vka.ka.clone().into(),
1979 cert: vka.cert.clone(),
1980 binding_signature: vka.binding_signature,
1981 }
1982 }
1983}
1984
1985// We can infallibly convert part X to part Y for everything but
1986// Public -> Secret and Unspecified -> Secret.
1987macro_rules! impl_conversion {
1988 ($s:ident, $p1:path, $p2:path) => {
1989 impl<'a> From<$s<'a, $p1>>
1990 for ValidErasedKeyAmalgamation<'a, $p2>
1991 {
1992 fn from(vka: $s<'a, $p1>) -> Self {
1993 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
1994 ValidErasedKeyAmalgamation {
1995 ka: vka.ka.into(),
1996 cert: vka.cert,
1997 binding_signature: vka.binding_signature,
1998 }
1999 }
2000 }
2001
2002 impl<'a> From<&$s<'a, $p1>>
2003 for ValidErasedKeyAmalgamation<'a, $p2>
2004 {
2005 fn from(vka: &$s<'a, $p1>) -> Self {
2006 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
2007 ValidErasedKeyAmalgamation {
2008 ka: vka.ka.clone().into(),
2009 cert: vka.cert.clone(),
2010 binding_signature: vka.binding_signature,
2011 }
2012 }
2013 }
2014 }
2015}
2016
2017impl_conversion!(ValidPrimaryKeyAmalgamation,
2018 key::SecretParts, key::PublicParts);
2019impl_conversion!(ValidPrimaryKeyAmalgamation,
2020 key::SecretParts, key::UnspecifiedParts);
2021impl_conversion!(ValidPrimaryKeyAmalgamation,
2022 key::PublicParts, key::UnspecifiedParts);
2023impl_conversion!(ValidPrimaryKeyAmalgamation,
2024 key::UnspecifiedParts, key::PublicParts);
2025
2026impl_conversion!(ValidSubordinateKeyAmalgamation,
2027 key::SecretParts, key::PublicParts);
2028impl_conversion!(ValidSubordinateKeyAmalgamation,
2029 key::SecretParts, key::UnspecifiedParts);
2030impl_conversion!(ValidSubordinateKeyAmalgamation,
2031 key::PublicParts, key::UnspecifiedParts);
2032impl_conversion!(ValidSubordinateKeyAmalgamation,
2033 key::UnspecifiedParts, key::PublicParts);
2034
2035
2036impl<'a, P, P2> TryFrom<ValidErasedKeyAmalgamation<'a, P>>
2037 for ValidPrimaryKeyAmalgamation<'a, P2>
2038 where P: 'a + key::KeyParts,
2039 P2: 'a + key::KeyParts,
2040{
2041 type Error = anyhow::Error;
2042
2043 fn try_from(vka: ValidErasedKeyAmalgamation<'a, P>) -> Result<Self> {
2044 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
2045 Ok(ValidPrimaryKeyAmalgamation {
2046 ka: vka.ka.try_into()?,
2047 cert: vka.cert,
2048 binding_signature: vka.binding_signature,
2049 })
2050 }
2051}
2052
2053impl<'a, P, P2> TryFrom<ValidErasedKeyAmalgamation<'a, P>>
2054 for ValidSubordinateKeyAmalgamation<'a, P2>
2055 where P: 'a + key::KeyParts,
2056 P2: 'a + key::KeyParts,
2057{
2058 type Error = anyhow::Error;
2059
2060 fn try_from(vka: ValidErasedKeyAmalgamation<'a, P>) -> Result<Self> {
2061 Ok(ValidSubordinateKeyAmalgamation {
2062 ka: vka.ka.try_into()?,
2063 cert: vka.cert,
2064 binding_signature: vka.binding_signature,
2065 })
2066 }
2067}
2068
2069
2070impl<'a, P> ValidateAmalgamation<'a, Key<P, key::PrimaryRole>>
2071 for ValidPrimaryKeyAmalgamation<'a, P>
2072 where P: 'a + key::KeyParts
2073{
2074 type V = Self;
2075
2076 fn with_policy<T>(&self, policy: &'a dyn Policy, time: T) -> Result<Self::V>
2077 where T: Into<Option<time::SystemTime>>,
2078 Self: Sized
2079 {
2080 assert!(std::ptr::eq(self.ka.cert(), self.cert.cert()));
2081 self.ka.with_policy(policy, time)
2082 .map(|vka| {
2083 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
2084 vka
2085 })
2086 }
2087}
2088
2089impl<'a, P> ValidateAmalgamation<'a, Key<P, key::SubordinateRole>>
2090 for ValidSubordinateKeyAmalgamation<'a, P>
2091 where P: 'a + key::KeyParts
2092{
2093 type V = Self;
2094
2095 fn with_policy<T>(&self, policy: &'a dyn Policy, time: T) -> Result<Self::V>
2096 where T: Into<Option<time::SystemTime>>,
2097 Self: Sized
2098 {
2099 assert!(std::ptr::eq(self.ka.cert(), self.cert.cert()));
2100 self.ka.with_policy(policy, time)
2101 .map(|vka| {
2102 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
2103 vka
2104 })
2105 }
2106}
2107
2108
2109impl<'a, P> ValidateAmalgamation<'a, Key<P, key::UnspecifiedRole>>
2110 for ValidErasedKeyAmalgamation<'a, P>
2111 where P: 'a + key::KeyParts
2112{
2113 type V = Self;
2114
2115 fn with_policy<T>(&self, policy: &'a dyn Policy, time: T) -> Result<Self::V>
2116 where T: Into<Option<time::SystemTime>>,
2117 Self: Sized
2118 {
2119 assert!(std::ptr::eq(self.ka.cert(), self.cert.cert()));
2120 self.ka.with_policy(policy, time)
2121 .map(|vka| {
2122 assert!(std::ptr::eq(vka.ka.cert(), vka.cert.cert()));
2123 vka
2124 })
2125 }
2126}
2127
2128impl<'a, P, R, R2> seal::Sealed for ValidKeyAmalgamation<'a, P, R, R2>
2129 where P: 'a + key::KeyParts,
2130 R: 'a + key::KeyRole,
2131 R2: Copy,
2132 Self: PrimaryKey<'a, P, R>,
2133{}
2134
2135impl<'a, P, R, R2> ValidAmalgamation<'a, Key<P, R>>
2136 for ValidKeyAmalgamation<'a, P, R, R2>
2137 where P: 'a + key::KeyParts,
2138 R: 'a + key::KeyRole,
2139 R2: Copy,
2140 Self: PrimaryKey<'a, P, R>,
2141{
2142 fn valid_cert(&self) -> &ValidCert<'a> {
2143 assert!(std::ptr::eq(self.ka.cert(), self.cert.cert()));
2144 &self.cert
2145 }
2146
2147 fn time(&self) -> SystemTime {
2148 self.cert.time()
2149 }
2150
2151 fn policy(&self) -> &'a dyn Policy {
2152 assert!(std::ptr::eq(self.ka.cert(), self.cert.cert()));
2153 self.cert.policy()
2154 }
2155
2156 fn binding_signature(&self) -> &'a Signature {
2157 self.binding_signature
2158 }
2159
2160 fn revocation_status(&self) -> RevocationStatus<'a> {
2161 if self.primary() {
2162 self.cert.revocation_status()
2163 } else {
2164 self.bundle().revocation_status_intern(
2165 self.policy(), Some(self.time()), true,
2166 Some(self.binding_signature))
2167 }
2168 }
2169
2170 fn revocation_keys(&self)
2171 -> Box<dyn Iterator<Item = &'a RevocationKey> + 'a>
2172 {
2173 let mut keys = std::collections::HashSet::new();
2174
2175 let policy = self.policy();
2176 let pk_sec = self.cert().primary_key().key().hash_algo_security();
2177
2178 // All valid self-signatures.
2179 let sec = self.bundle().hash_algo_security;
2180 self.self_signatures()
2181 .filter(move |sig| {
2182 policy.signature(sig, sec).is_ok()
2183 })
2184 // All direct-key signatures.
2185 .chain(self.cert().primary_key()
2186 .self_signatures()
2187 .filter(|sig| {
2188 policy.signature(sig, pk_sec).is_ok()
2189 }))
2190 .flat_map(|sig| sig.revocation_keys())
2191 .for_each(|rk| { keys.insert(rk); });
2192
2193 Box::new(keys.into_iter())
2194 }
2195}
2196
2197impl<'a, P, R, R2> ValidBindingSignature<'a, Key<P, R>>
2198 for ValidKeyAmalgamation<'a, P, R, R2>
2199where P: 'a + key::KeyParts,
2200 R: 'a + key::KeyRole,
2201 R2: Copy,
2202 Self: PrimaryKey<'a, P, R>,
2203{}
2204
2205impl<'a, P> PrimaryKey<'a, P, key::PrimaryRole>
2206 for ValidPrimaryKeyAmalgamation<'a, P>
2207 where P: 'a + key::KeyParts
2208{
2209 fn primary(&self) -> bool {
2210 true
2211 }
2212}
2213
2214impl<'a, P> PrimaryKey<'a, P, key::SubordinateRole>
2215 for ValidSubordinateKeyAmalgamation<'a, P>
2216 where P: 'a + key::KeyParts
2217{
2218 fn primary(&self) -> bool {
2219 false
2220 }
2221}
2222
2223impl<'a, P> PrimaryKey<'a, P, key::UnspecifiedRole>
2224 for ValidErasedKeyAmalgamation<'a, P>
2225 where P: 'a + key::KeyParts
2226{
2227 fn primary(&self) -> bool {
2228 self.ka.primary
2229 }
2230}
2231
2232
2233impl<'a, P, R, R2> ValidKeyAmalgamation<'a, P, R, R2>
2234 where P: 'a + key::KeyParts,
2235 R: 'a + key::KeyRole,
2236 R2: Copy,
2237 Self: ValidAmalgamation<'a, Key<P, R>>,
2238 Self: PrimaryKey<'a, P, R>,
2239{
2240 /// Returns whether the key is alive as of the amalgamation's
2241 /// reference time.
2242 ///
2243 /// A `ValidKeyAmalgamation` is guaranteed to have a live binding
2244 /// signature. This is independent of whether the component is
2245 /// live.
2246 ///
2247 /// If the certificate is not alive as of the reference time, no
2248 /// subkey can be alive.
2249 ///
2250 /// This function considers both the binding signature and the
2251 /// direct key signature. Information in the binding signature
2252 /// takes precedence over the direct key signature. See [Section
2253 /// 5.2.3.10 of RFC 9580].
2254 ///
2255 /// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
2256 ///
2257 /// For a definition of liveness, see the [`key_alive`] method.
2258 ///
2259 /// [`key_alive`]: crate::packet::signature::subpacket::SubpacketAreas::key_alive()
2260 ///
2261 /// # Examples
2262 ///
2263 /// ```
2264 /// # use sequoia_openpgp as openpgp;
2265 /// # use openpgp::cert::prelude::*;
2266 /// use openpgp::policy::StandardPolicy;
2267 ///
2268 /// # fn main() -> openpgp::Result<()> {
2269 /// let p = &StandardPolicy::new();
2270 ///
2271 /// # let (cert, _) = CertBuilder::new()
2272 /// # .add_userid("Alice")
2273 /// # .add_signing_subkey()
2274 /// # .add_transport_encryption_subkey()
2275 /// # .generate()?;
2276 /// let ka = cert.primary_key().with_policy(p, None)?;
2277 /// if let Err(_err) = ka.alive() {
2278 /// // Not alive.
2279 /// # unreachable!();
2280 /// }
2281 /// # Ok(()) }
2282 /// ```
2283 pub fn alive(&self) -> Result<()>
2284 {
2285 if ! self.primary() {
2286 // First, check the certificate.
2287 self.valid_cert().alive()
2288 .context("The certificate is not live")?;
2289 }
2290
2291 let sig = {
2292 let binding : &Signature = self.binding_signature();
2293 if binding.key_validity_period().is_some() {
2294 Some(binding)
2295 } else {
2296 self.direct_key_signature().ok()
2297 }
2298 };
2299 if let Some(sig) = sig {
2300 sig.key_alive(self.key(), self.time())
2301 .with_context(|| if self.primary() {
2302 "The primary key is not live"
2303 } else {
2304 "The subkey is not live"
2305 })
2306 } else {
2307 // There is no key expiration time on the binding
2308 // signature. This key does not expire.
2309 Ok(())
2310 }
2311 }
2312}
2313
2314impl<'a, P, R, R2> ValidKeyAmalgamation<'a, P, R, R2>
2315 where P: key::KeyParts,
2316 R: key::KeyRole,
2317 R2: Copy,
2318 Self: PrimaryKey<'a, P, R>,
2319{
2320 /// Returns the key's primary key binding signature, if any.
2321 ///
2322 /// The [primary key binding signature] is embedded inside a
2323 /// subkey binding signature. It is made by the subkey to
2324 /// indicate that it should be associated with the primary key.
2325 /// This prevents an attack in which an attacker creates a
2326 /// certificate, and associates the victim's subkey with it
2327 /// thereby creating confusion about the certificate that issued a
2328 /// signature.
2329 ///
2330 /// [primary key binding signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
2331 ///
2332 /// Not all keys have primary key binding signatures. First,
2333 /// primary keys don't have them, because they don't need them.
2334 /// Second, encrypt-capable subkeys don't have them because they
2335 /// are not (usually) able to issue signatures.
2336 ///
2337 /// # Examples
2338 ///
2339 /// ```
2340 /// # use sequoia_openpgp as openpgp;
2341 /// # use openpgp::cert::prelude::*;
2342 /// # use openpgp::policy::StandardPolicy;
2343 /// #
2344 /// # const P: &StandardPolicy = &StandardPolicy::new();
2345 /// #
2346 /// # fn main() -> openpgp::Result<()> {
2347 /// # let (cert, _) =
2348 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2349 /// # .generate()?;
2350 /// # let fpr = cert.fingerprint();
2351 /// let vc = cert.with_policy(P, None)?;
2352 ///
2353 /// assert!(vc.primary_key().primary_key_binding_signature().is_none());
2354 ///
2355 /// // A signing key has to have a primary key binding signature.
2356 /// for ka in vc.keys().for_signing() {
2357 /// assert!(ka.primary_key_binding_signature().is_some());
2358 /// }
2359 ///
2360 /// // Encryption keys normally can't have a primary key binding
2361 /// // signature, because they can't issue signatures.
2362 /// for ka in vc.keys().for_transport_encryption() {
2363 /// assert!(ka.primary_key_binding_signature().is_none());
2364 /// }
2365 /// # Ok(())
2366 /// # }
2367 /// ```
2368 pub fn primary_key_binding_signature(&self) -> Option<&Signature> {
2369 let subkey = if self.primary() {
2370 // A primary key has no backsig.
2371 return None;
2372 } else {
2373 self.key().role_as_subordinate()
2374 };
2375
2376 let pk = self.cert().primary_key().key();
2377
2378 for backsig in
2379 self.binding_signature.subpackets(SubpacketTag::EmbeddedSignature)
2380 {
2381 if let SubpacketValue::EmbeddedSignature(sig) =
2382 backsig.value()
2383 {
2384 if sig.verify_primary_key_binding(pk, subkey).is_ok() {
2385 // Mark the subpacket as authenticated by the
2386 // embedded signature.
2387 backsig.set_authenticated(true);
2388
2389 return Some(sig);
2390 }
2391 } else {
2392 unreachable!("subpackets(EmbeddedSignature) returns \
2393 EmbeddedSignatures");
2394 }
2395 }
2396
2397 None
2398 }
2399}
2400
2401impl<'a, P> ValidPrimaryKeyAmalgamation<'a, P>
2402 where P: 'a + key::KeyParts
2403{
2404 /// Sets the key to expire in delta seconds.
2405 ///
2406 /// Note: the time is relative to the key's creation time, not the
2407 /// current time!
2408 ///
2409 /// This function exists to facilitate testing, which is why it is
2410 /// not exported.
2411 #[cfg(test)]
2412 pub(crate) fn set_validity_period_as_of(&self,
2413 primary_signer: &mut dyn Signer,
2414 expiration: Option<time::Duration>,
2415 now: time::SystemTime)
2416 -> Result<Vec<Signature>>
2417 {
2418 ValidErasedKeyAmalgamation::<P>::from(self)
2419 .set_validity_period_as_of(primary_signer, None, expiration, now)
2420 }
2421
2422 /// Creates signatures that cause the key to expire at the specified time.
2423 ///
2424 /// This function creates new binding signatures that cause the
2425 /// key to expire at the specified time when integrated into the
2426 /// certificate. For the primary key, it is necessary to
2427 /// create a new self-signature for each non-revoked User ID, and
2428 /// to create a direct key signature. This is needed, because the
2429 /// primary User ID is first consulted when determining the
2430 /// primary key's expiration time, and certificates can be
2431 /// distributed with a possibly empty subset of User IDs.
2432 ///
2433 /// Setting a key's expiry time means updating an existing binding
2434 /// signature---when looking up information, only one binding
2435 /// signature is normally considered, and we don't want to drop
2436 /// the other information stored in the current binding signature.
2437 /// This function uses the binding signature determined by
2438 /// `ValidKeyAmalgamation`'s policy and reference time for this.
2439 ///
2440 /// # Examples
2441 ///
2442 /// ```
2443 /// use std::time;
2444 /// # use sequoia_openpgp as openpgp;
2445 /// # use openpgp::cert::prelude::*;
2446 /// use openpgp::policy::StandardPolicy;
2447 ///
2448 /// # fn main() -> openpgp::Result<()> {
2449 /// let p = &StandardPolicy::new();
2450 ///
2451 /// # let t = time::SystemTime::now() - time::Duration::from_secs(10);
2452 /// # let (cert, _) = CertBuilder::new()
2453 /// # .set_creation_time(t)
2454 /// # .add_userid("Alice")
2455 /// # .add_signing_subkey()
2456 /// # .add_transport_encryption_subkey()
2457 /// # .generate()?;
2458 /// let vc = cert.with_policy(p, None)?;
2459 ///
2460 /// // Assert that the primary key is not expired.
2461 /// assert!(vc.primary_key().alive().is_ok());
2462 ///
2463 /// // Make the primary key expire in a week.
2464 /// let t = time::SystemTime::now()
2465 /// + time::Duration::from_secs(7 * 24 * 60 * 60);
2466 ///
2467 /// // We assume that the secret key material is available, and not
2468 /// // password protected.
2469 /// let mut signer = vc.primary_key()
2470 /// .key().clone().parts_into_secret()?.into_keypair()?;
2471 ///
2472 /// let sigs = vc.primary_key().set_expiration_time(&mut signer, Some(t))?;
2473 /// let cert = cert.insert_packets(sigs)?.0;
2474 ///
2475 /// // The primary key isn't expired yet.
2476 /// let vc = cert.with_policy(p, None)?;
2477 /// assert!(vc.primary_key().alive().is_ok());
2478 ///
2479 /// // But in two weeks, it will be...
2480 /// let t = time::SystemTime::now()
2481 /// + time::Duration::from_secs(2 * 7 * 24 * 60 * 60);
2482 /// let vc = cert.with_policy(p, t)?;
2483 /// assert!(vc.primary_key().alive().is_err());
2484 /// # Ok(()) }
2485 pub fn set_expiration_time(&self,
2486 primary_signer: &mut dyn Signer,
2487 expiration: Option<time::SystemTime>)
2488 -> Result<Vec<Signature>>
2489 {
2490 ValidErasedKeyAmalgamation::<P>::from(self)
2491 .set_expiration_time(primary_signer, None, expiration)
2492 }
2493}
2494
2495impl<'a, P> ValidSubordinateKeyAmalgamation<'a, P>
2496 where P: 'a + key::KeyParts
2497{
2498 /// Creates signatures that cause the key to expire at the specified time.
2499 ///
2500 /// This function creates new binding signatures that cause the
2501 /// key to expire at the specified time when integrated into the
2502 /// certificate. For subkeys, a single `Signature` is returned.
2503 ///
2504 /// Setting a key's expiry time means updating an existing binding
2505 /// signature---when looking up information, only one binding
2506 /// signature is normally considered, and we don't want to drop
2507 /// the other information stored in the current binding signature.
2508 /// This function uses the binding signature determined by
2509 /// `ValidKeyAmalgamation`'s policy and reference time for this.
2510 ///
2511 /// When updating the expiration time of signing-capable subkeys,
2512 /// we need to create a new [primary key binding signature].
2513 /// Therefore, we need a signer for the subkey. If
2514 /// `subkey_signer` is `None`, and this is a signing-capable
2515 /// subkey, this function fails with [`Error::InvalidArgument`].
2516 /// Likewise, this function fails if `subkey_signer` is not `None`
2517 /// when updating the expiration of a non signing-capable subkey.
2518 ///
2519 /// [primary key binding signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
2520 /// [`Error::InvalidArgument`]: super::super::super::Error::InvalidArgument
2521 ///
2522 /// # Examples
2523 ///
2524 /// ```
2525 /// use std::time;
2526 /// # use sequoia_openpgp as openpgp;
2527 /// # use openpgp::cert::prelude::*;
2528 /// use openpgp::policy::StandardPolicy;
2529 ///
2530 /// # fn main() -> openpgp::Result<()> {
2531 /// let p = &StandardPolicy::new();
2532 ///
2533 /// # let t = time::SystemTime::now() - time::Duration::from_secs(10);
2534 /// # let (cert, _) = CertBuilder::new()
2535 /// # .set_creation_time(t)
2536 /// # .add_userid("Alice")
2537 /// # .add_signing_subkey()
2538 /// # .add_transport_encryption_subkey()
2539 /// # .generate()?;
2540 /// let vc = cert.with_policy(p, None)?;
2541 ///
2542 /// // Assert that the keys are not expired.
2543 /// for ka in vc.keys() {
2544 /// assert!(ka.alive().is_ok());
2545 /// }
2546 ///
2547 /// // Make the keys expire in a week.
2548 /// let t = time::SystemTime::now()
2549 /// + time::Duration::from_secs(7 * 24 * 60 * 60);
2550 ///
2551 /// // We assume that the secret key material is available, and not
2552 /// // password protected.
2553 /// let mut primary_signer = vc.primary_key()
2554 /// .key().clone().parts_into_secret()?.into_keypair()?;
2555 /// let mut signing_subkey_signer = vc.keys().for_signing().nth(0).unwrap()
2556 /// .key().clone().parts_into_secret()?.into_keypair()?;
2557 ///
2558 /// let mut sigs = Vec::new();
2559 /// for ka in vc.keys() {
2560 /// if ! ka.for_signing() {
2561 /// // Non-signing-capable subkeys are easy to update.
2562 /// sigs.append(&mut ka.set_expiration_time(&mut primary_signer,
2563 /// None, Some(t))?);
2564 /// } else {
2565 /// // Signing-capable subkeys need to create a primary
2566 /// // key binding signature with the subkey:
2567 /// assert!(ka.set_expiration_time(&mut primary_signer,
2568 /// None, Some(t)).is_err());
2569 ///
2570 /// // Here, we need the subkey's signer:
2571 /// sigs.append(&mut ka.set_expiration_time(&mut primary_signer,
2572 /// Some(&mut signing_subkey_signer),
2573 /// Some(t))?);
2574 /// }
2575 /// }
2576 /// let cert = cert.insert_packets(sigs)?.0;
2577 ///
2578 /// // They aren't expired yet.
2579 /// let vc = cert.with_policy(p, None)?;
2580 /// for ka in vc.keys() {
2581 /// assert!(ka.alive().is_ok());
2582 /// }
2583 ///
2584 /// // But in two weeks, they will be...
2585 /// let t = time::SystemTime::now()
2586 /// + time::Duration::from_secs(2 * 7 * 24 * 60 * 60);
2587 /// let vc = cert.with_policy(p, t)?;
2588 /// for ka in vc.keys() {
2589 /// assert!(ka.alive().is_err());
2590 /// }
2591 /// # Ok(()) }
2592 pub fn set_expiration_time(&self,
2593 primary_signer: &mut dyn Signer,
2594 subkey_signer: Option<&mut dyn Signer>,
2595 expiration: Option<time::SystemTime>)
2596 -> Result<Vec<Signature>>
2597 {
2598 ValidErasedKeyAmalgamation::<P>::from(self)
2599 .set_expiration_time(primary_signer, subkey_signer, expiration)
2600 }
2601}
2602
2603impl<'a, P> ValidErasedKeyAmalgamation<'a, P>
2604 where P: 'a + key::KeyParts
2605{
2606 /// Sets the key to expire in delta seconds.
2607 ///
2608 /// Note: the time is relative to the key's creation time, not the
2609 /// current time!
2610 ///
2611 /// This function exists to facilitate testing, which is why it is
2612 /// not exported.
2613 pub(crate) fn set_validity_period_as_of(&self,
2614 primary_signer: &mut dyn Signer,
2615 subkey_signer:
2616 Option<&mut dyn Signer>,
2617 expiration: Option<time::Duration>,
2618 now: time::SystemTime)
2619 -> Result<Vec<Signature>>
2620 {
2621 let mut sigs = Vec::new();
2622
2623 // There are two cases to consider. If we are extending the
2624 // validity of the primary key, we also need to create new
2625 // binding signatures for all userids.
2626 if self.primary() {
2627 // First, update or create a direct key signature.
2628 let template = self.direct_key_signature()
2629 .map(|sig| {
2630 signature::SignatureBuilder::from(sig.clone())
2631 })
2632 .unwrap_or_else(|_| {
2633 let mut template = signature::SignatureBuilder::from(
2634 self.binding_signature().clone())
2635 .set_type(SignatureType::DirectKey);
2636
2637 // We're creating a direct signature from a User
2638 // ID self signature. Remove irrelevant packets.
2639 use SubpacketTag::*;
2640 let ha = template.hashed_area_mut();
2641 ha.remove_all(ExportableCertification);
2642 ha.remove_all(Revocable);
2643 ha.remove_all(TrustSignature);
2644 ha.remove_all(RegularExpression);
2645 ha.remove_all(PrimaryUserID);
2646 ha.remove_all(SignersUserID);
2647 ha.remove_all(ReasonForRevocation);
2648 ha.remove_all(SignatureTarget);
2649 ha.remove_all(EmbeddedSignature);
2650
2651 template
2652 });
2653 let mut builder = template
2654 .set_signature_creation_time(now)?
2655 .set_key_validity_period(expiration)?;
2656 builder.hashed_area_mut().remove_all(
2657 signature::subpacket::SubpacketTag::PrimaryUserID);
2658
2659 // Generate the signature.
2660 sigs.push(builder.sign_direct_key(primary_signer, None)?);
2661
2662 // Second, generate a new binding signature for every
2663 // userid. We need to be careful not to change the
2664 // primary userid, so we make it explicit using the
2665 // primary userid subpacket.
2666 for userid in self.valid_cert().userids().revoked(false) {
2667 // To extend the validity of the subkey, create a new
2668 // binding signature with updated key validity period.
2669 let binding_signature = userid.binding_signature();
2670
2671 let builder = signature::SignatureBuilder::from(binding_signature.clone())
2672 .set_signature_creation_time(now)?
2673 .set_key_validity_period(expiration)?
2674 .set_primary_userid(
2675 self.valid_cert().primary_userid().map(|primary| {
2676 userid.userid() == primary.userid()
2677 }).unwrap_or(false))?;
2678
2679 sigs.push(builder.sign_userid_binding(primary_signer,
2680 self.cert().primary_key().component(),
2681 userid.userid())?);
2682 }
2683 } else {
2684 // To extend the validity of the subkey, create a new
2685 // binding signature with updated key validity period.
2686 let backsig = if self.for_certification() || self.for_signing()
2687 || self.for_authentication()
2688 {
2689 if let Some(subkey_signer) = subkey_signer {
2690 Some(signature::SignatureBuilder::new(
2691 SignatureType::PrimaryKeyBinding)
2692 .set_signature_creation_time(now)?
2693 .set_hash_algo(self.binding_signature.hash_algo())
2694 .sign_primary_key_binding(
2695 subkey_signer,
2696 self.cert().primary_key().key(),
2697 self.key().role_as_subordinate())?)
2698 } else {
2699 return Err(Error::InvalidArgument(
2700 "Changing expiration of signing-capable subkeys \
2701 requires subkey signer".into()).into());
2702 }
2703 } else {
2704 if subkey_signer.is_some() {
2705 return Err(Error::InvalidArgument(
2706 "Subkey signer given but subkey is not signing-capable"
2707 .into()).into());
2708 }
2709 None
2710 };
2711
2712 let mut sig =
2713 signature::SignatureBuilder::from(
2714 self.binding_signature().clone())
2715 .set_signature_creation_time(now)?
2716 .set_key_validity_period(expiration)?;
2717
2718 if let Some(bs) = backsig {
2719 sig = sig.set_embedded_signature(bs)?;
2720 }
2721
2722 sigs.push(sig.sign_subkey_binding(
2723 primary_signer,
2724 self.cert().primary_key().component(),
2725 self.key().role_as_subordinate())?);
2726 }
2727
2728 Ok(sigs)
2729 }
2730
2731 /// Creates signatures that cause the key to expire at the specified time.
2732 ///
2733 /// This function creates new binding signatures that cause the
2734 /// key to expire at the specified time when integrated into the
2735 /// certificate. For subkeys, only a single `Signature` is
2736 /// returned. For the primary key, however, it is necessary to
2737 /// create a new self-signature for each non-revoked User ID, and
2738 /// to create a direct key signature. This is needed, because the
2739 /// primary User ID is first consulted when determining the
2740 /// primary key's expiration time, and certificates can be
2741 /// distributed with a possibly empty subset of User IDs.
2742 ///
2743 /// Setting a key's expiry time means updating an existing binding
2744 /// signature---when looking up information, only one binding
2745 /// signature is normally considered, and we don't want to drop
2746 /// the other information stored in the current binding signature.
2747 /// This function uses the binding signature determined by
2748 /// `ValidKeyAmalgamation`'s policy and reference time for this.
2749 ///
2750 /// When updating the expiration time of signing-capable subkeys,
2751 /// we need to create a new [primary key binding signature].
2752 /// Therefore, we need a signer for the subkey. If
2753 /// `subkey_signer` is `None`, and this is a signing-capable
2754 /// subkey, this function fails with [`Error::InvalidArgument`].
2755 /// Likewise, this function fails if `subkey_signer` is not `None`
2756 /// when updating the expiration of the primary key, or a non
2757 /// signing-capable subkey.
2758 ///
2759 /// [primary key binding signature]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.1
2760 /// [`Error::InvalidArgument`]: super::super::super::Error::InvalidArgument
2761 ///
2762 /// # Examples
2763 ///
2764 /// ```
2765 /// use std::time;
2766 /// # use sequoia_openpgp as openpgp;
2767 /// # use openpgp::cert::prelude::*;
2768 /// use openpgp::policy::StandardPolicy;
2769 ///
2770 /// # fn main() -> openpgp::Result<()> {
2771 /// let p = &StandardPolicy::new();
2772 ///
2773 /// # let t = time::SystemTime::now() - time::Duration::from_secs(10);
2774 /// # let (cert, _) = CertBuilder::new()
2775 /// # .set_creation_time(t)
2776 /// # .add_userid("Alice")
2777 /// # .add_signing_subkey()
2778 /// # .add_transport_encryption_subkey()
2779 /// # .generate()?;
2780 /// let vc = cert.with_policy(p, None)?;
2781 ///
2782 /// // Assert that the keys are not expired.
2783 /// for ka in vc.keys() {
2784 /// assert!(ka.alive().is_ok());
2785 /// }
2786 ///
2787 /// // Make the keys expire in a week.
2788 /// let t = time::SystemTime::now()
2789 /// + time::Duration::from_secs(7 * 24 * 60 * 60);
2790 ///
2791 /// // We assume that the secret key material is available, and not
2792 /// // password protected.
2793 /// let mut primary_signer = vc.primary_key()
2794 /// .key().clone().parts_into_secret()?.into_keypair()?;
2795 /// let mut signing_subkey_signer = vc.keys().for_signing().nth(0).unwrap()
2796 /// .key().clone().parts_into_secret()?.into_keypair()?;
2797 ///
2798 /// let mut sigs = Vec::new();
2799 /// for ka in vc.keys() {
2800 /// if ! ka.for_signing() {
2801 /// // Non-signing-capable subkeys are easy to update.
2802 /// sigs.append(&mut ka.set_expiration_time(&mut primary_signer,
2803 /// None, Some(t))?);
2804 /// } else {
2805 /// // Signing-capable subkeys need to create a primary
2806 /// // key binding signature with the subkey:
2807 /// assert!(ka.set_expiration_time(&mut primary_signer,
2808 /// None, Some(t)).is_err());
2809 ///
2810 /// // Here, we need the subkey's signer:
2811 /// sigs.append(&mut ka.set_expiration_time(&mut primary_signer,
2812 /// Some(&mut signing_subkey_signer),
2813 /// Some(t))?);
2814 /// }
2815 /// }
2816 /// let cert = cert.insert_packets(sigs)?.0;
2817 ///
2818 /// // They aren't expired yet.
2819 /// let vc = cert.with_policy(p, None)?;
2820 /// for ka in vc.keys() {
2821 /// assert!(ka.alive().is_ok());
2822 /// }
2823 ///
2824 /// // But in two weeks, they will be...
2825 /// let t = time::SystemTime::now()
2826 /// + time::Duration::from_secs(2 * 7 * 24 * 60 * 60);
2827 /// let vc = cert.with_policy(p, t)?;
2828 /// for ka in vc.keys() {
2829 /// assert!(ka.alive().is_err());
2830 /// }
2831 /// # Ok(()) }
2832 pub fn set_expiration_time(&self,
2833 primary_signer: &mut dyn Signer,
2834 subkey_signer: Option<&mut dyn Signer>,
2835 expiration: Option<time::SystemTime>)
2836 -> Result<Vec<Signature>>
2837 {
2838 let expiration =
2839 if let Some(e) = expiration.map(crate::types::normalize_systemtime)
2840 {
2841 let ct = self.key().creation_time();
2842 match e.duration_since(ct) {
2843 Ok(v) => Some(v),
2844 Err(_) => return Err(Error::InvalidArgument(
2845 format!("Expiration time {:?} predates creation time \
2846 {:?}", e, ct)).into()),
2847 }
2848 } else {
2849 None
2850 };
2851
2852 self.set_validity_period_as_of(primary_signer, subkey_signer,
2853 expiration, crate::now())
2854 }
2855}
2856
2857impl<'a, P, R, R2> ValidKeyAmalgamation<'a, P, R, R2>
2858 where P: 'a + key::KeyParts,
2859 R: 'a + key::KeyRole,
2860 R2: Copy,
2861 Self: ValidAmalgamation<'a, Key<P, R>>,
2862 Self: ValidBindingSignature<'a, Key<P, R>>,
2863{
2864 /// Returns the key's `Key Flags`.
2865 ///
2866 /// A Key's [`Key Flags`] holds information about the key. As of
2867 /// RFC 9580, this information is primarily concerned with the
2868 /// key's capabilities (e.g., whether it may be used for signing).
2869 /// The other information that has been defined is: whether the
2870 /// key has been split using something like [SSS], and whether the
2871 /// primary key material is held by multiple parties. In
2872 /// practice, the latter two flags are ignored.
2873 ///
2874 /// As per [Section 5.2.3.10 of RFC 9580], when looking for the
2875 /// `Key Flags`, the key's binding signature is first consulted
2876 /// (in the case of the primary Key, this is the binding signature
2877 /// of the primary User ID). If the `Key Flags` subpacket is not
2878 /// present, then the direct key signature is consulted.
2879 ///
2880 /// Since the key flags are taken from the active self signature,
2881 /// a key's flags may change depending on the policy and the
2882 /// reference time.
2883 ///
2884 /// To increase compatibility with early v4 certificates, if there
2885 /// is no key flags subpacket on the considered signatures, we
2886 /// infer the key flags from the key's role and public key
2887 /// algorithm.
2888 ///
2889 /// [`Key Flags`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
2890 /// [SSS]: https://de.wikipedia.org/wiki/Shamir%E2%80%99s_Secret_Sharing
2891 /// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
2892 ///
2893 /// # Examples
2894 ///
2895 /// ```
2896 /// # use sequoia_openpgp as openpgp;
2897 /// # use openpgp::cert::prelude::*;
2898 /// # use openpgp::policy::{Policy, StandardPolicy};
2899 /// #
2900 /// # fn main() -> openpgp::Result<()> {
2901 /// # let p: &dyn Policy = &StandardPolicy::new();
2902 /// # let (cert, _) =
2903 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2904 /// # .generate()?;
2905 /// # let cert = cert.with_policy(p, None)?;
2906 /// let ka = cert.primary_key();
2907 /// println!("Primary Key's Key Flags: {:?}", ka.key_flags());
2908 /// # assert!(ka.key_flags().unwrap().for_certification());
2909 /// # Ok(()) }
2910 /// ```
2911 pub fn key_flags(&self) -> Option<KeyFlags> {
2912 self.map(|s| s.key_flags())
2913 .or_else(|| {
2914 // There is no key flags subpacket. Match on the key
2915 // role and algorithm and synthesize one. We do this
2916 // to better support very early v4 certificates, where
2917 // either the binding signature is a v3 signature and
2918 // cannot contain subpackets, or it is a v4 signature,
2919 // but the key's capabilities were implied by the
2920 // public key algorithm.
2921 use crate::types::PublicKeyAlgorithm;
2922
2923 // XXX: We cannot know whether this is a primary key
2924 // or not because of
2925 // https://gitlab.com/sequoia-pgp/sequoia/-/issues/1036
2926 let is_primary = false;
2927
2928 // We only match on public key algorithms used at the
2929 // time.
2930 #[allow(deprecated)]
2931 match (is_primary, self.key().pk_algo()) {
2932 (true, PublicKeyAlgorithm::RSAEncryptSign) =>
2933 Some(KeyFlags::empty()
2934 .set_certification()
2935 .set_transport_encryption()
2936 .set_storage_encryption()
2937 .set_signing()),
2938
2939 (true, _) =>
2940 Some(KeyFlags::empty()
2941 .set_certification()
2942 .set_signing()),
2943
2944 (false, PublicKeyAlgorithm::RSAEncryptSign) =>
2945 Some(KeyFlags::empty()
2946 .set_transport_encryption()
2947 .set_storage_encryption()
2948 .set_signing()),
2949
2950 (false,
2951 | PublicKeyAlgorithm::RSASign
2952 | PublicKeyAlgorithm::DSA) =>
2953 Some(KeyFlags::empty().set_signing()),
2954
2955 (false,
2956 | PublicKeyAlgorithm::RSAEncrypt
2957 | PublicKeyAlgorithm::ElGamalEncrypt
2958 | PublicKeyAlgorithm::ElGamalEncryptSign) =>
2959 Some(KeyFlags::empty()
2960 .set_transport_encryption()
2961 .set_storage_encryption()),
2962
2963 // Be conservative: newer algorithms don't get to
2964 // benefit from implicit key flags.
2965 (false, _) => None,
2966 }
2967 })
2968 }
2969
2970 /// Returns whether the key has at least one of the specified key
2971 /// flags.
2972 ///
2973 /// The key flags are looked up as described in
2974 /// [`ValidKeyAmalgamation::key_flags`].
2975 ///
2976 /// # Examples
2977 ///
2978 /// Finds keys that may be used for transport encryption (data in
2979 /// motion) *or* storage encryption (data at rest):
2980 ///
2981 /// ```
2982 /// # use sequoia_openpgp as openpgp;
2983 /// # use openpgp::cert::prelude::*;
2984 /// use openpgp::policy::StandardPolicy;
2985 /// use openpgp::types::KeyFlags;
2986 ///
2987 /// # fn main() -> openpgp::Result<()> {
2988 /// let p = &StandardPolicy::new();
2989 ///
2990 /// # let (cert, _) =
2991 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2992 /// # .generate()?;
2993 /// for ka in cert.keys().with_policy(p, None) {
2994 /// if ka.has_any_key_flag(KeyFlags::empty()
2995 /// .set_storage_encryption()
2996 /// .set_transport_encryption())
2997 /// {
2998 /// // `ka` is encryption capable.
2999 /// }
3000 /// }
3001 /// # Ok(()) }
3002 /// ```
3003 ///
3004 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3005 pub fn has_any_key_flag<F>(&self, flags: F) -> bool
3006 where F: Borrow<KeyFlags>
3007 {
3008 let our_flags = self.key_flags().unwrap_or_else(KeyFlags::empty);
3009 !(&our_flags & flags.borrow()).is_empty()
3010 }
3011
3012 /// Returns whether the key is certification capable.
3013 ///
3014 /// Note: [Section 10.1 of RFC 9580] says that the primary key is
3015 /// certification capable independent of the `Key Flags`
3016 /// subpacket:
3017 ///
3018 /// > In a V4 key, the primary key MUST be a key capable of
3019 /// > certification.
3020 ///
3021 /// This function only reflects what is stored in the `Key Flags`
3022 /// packet; it does not implicitly set this flag. In practice,
3023 /// there are keys whose primary key's `Key Flags` do not have the
3024 /// certification capable flag set. Some versions of netpgp, for
3025 /// instance, create keys like this. Sequoia's higher-level
3026 /// functionality correctly handles these keys by always
3027 /// considering the primary key to be certification capable.
3028 /// Users of this interface should too.
3029 ///
3030 /// The key flags are looked up as described in
3031 /// [`ValidKeyAmalgamation::key_flags`].
3032 ///
3033 /// # Examples
3034 ///
3035 /// Finds keys that are certification capable:
3036 ///
3037 /// ```
3038 /// # use sequoia_openpgp as openpgp;
3039 /// # use openpgp::cert::prelude::*;
3040 /// use openpgp::policy::StandardPolicy;
3041 ///
3042 /// # fn main() -> openpgp::Result<()> {
3043 /// let p = &StandardPolicy::new();
3044 ///
3045 /// # let (cert, _) =
3046 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3047 /// # .generate()?;
3048 /// for ka in cert.keys().with_policy(p, None) {
3049 /// if ka.primary() || ka.for_certification() {
3050 /// // `ka` is certification capable.
3051 /// }
3052 /// }
3053 /// # Ok(()) }
3054 /// ```
3055 ///
3056 /// [Section 10.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
3057 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3058 pub fn for_certification(&self) -> bool {
3059 self.has_any_key_flag(KeyFlags::empty().set_certification())
3060 }
3061
3062 /// Returns whether the key is signing capable.
3063 ///
3064 /// The key flags are looked up as described in
3065 /// [`ValidKeyAmalgamation::key_flags`].
3066 ///
3067 /// # Examples
3068 ///
3069 /// Finds keys that are signing capable:
3070 ///
3071 /// ```
3072 /// # use sequoia_openpgp as openpgp;
3073 /// # use openpgp::cert::prelude::*;
3074 /// use openpgp::policy::StandardPolicy;
3075 ///
3076 /// # fn main() -> openpgp::Result<()> {
3077 /// let p = &StandardPolicy::new();
3078 ///
3079 /// # let (cert, _) =
3080 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3081 /// # .generate()?;
3082 /// for ka in cert.keys().with_policy(p, None) {
3083 /// if ka.for_signing() {
3084 /// // `ka` is signing capable.
3085 /// }
3086 /// }
3087 /// # Ok(()) }
3088 /// ```
3089 ///
3090 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3091 pub fn for_signing(&self) -> bool {
3092 self.has_any_key_flag(KeyFlags::empty().set_signing())
3093 }
3094
3095 /// Returns whether the key is authentication capable.
3096 ///
3097 /// The key flags are looked up as described in
3098 /// [`ValidKeyAmalgamation::key_flags`].
3099 ///
3100 /// # Examples
3101 ///
3102 /// Finds keys that are authentication capable:
3103 ///
3104 /// ```
3105 /// # use sequoia_openpgp as openpgp;
3106 /// # use openpgp::cert::prelude::*;
3107 /// use openpgp::policy::StandardPolicy;
3108 ///
3109 /// # fn main() -> openpgp::Result<()> {
3110 /// let p = &StandardPolicy::new();
3111 ///
3112 /// # let (cert, _) =
3113 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3114 /// # .generate()?;
3115 /// for ka in cert.keys().with_policy(p, None) {
3116 /// if ka.for_authentication() {
3117 /// // `ka` is authentication capable.
3118 /// }
3119 /// }
3120 /// # Ok(()) }
3121 /// ```
3122 ///
3123 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3124 pub fn for_authentication(&self) -> bool
3125 {
3126 self.has_any_key_flag(KeyFlags::empty().set_authentication())
3127 }
3128
3129 /// Returns whether the key is storage-encryption capable.
3130 ///
3131 /// OpenPGP distinguishes two types of encryption keys: those for
3132 /// storage ([data at rest]) and those for transport ([data in
3133 /// transit]). Most OpenPGP implementations, however, don't
3134 /// distinguish between them in practice. Instead, when they
3135 /// create a new encryption key, they just set both flags.
3136 /// Likewise, when encrypting a message, it is not typically
3137 /// possible to indicate the type of protection that is needed.
3138 /// Sequoia supports creating keys with only one of these flags
3139 /// set, and makes it easy to select the right type of key when
3140 /// encrypting messages.
3141 ///
3142 /// The key flags are looked up as described in
3143 /// [`ValidKeyAmalgamation::key_flags`].
3144 ///
3145 /// # Examples
3146 ///
3147 /// Finds keys that are storage-encryption capable:
3148 ///
3149 /// ```
3150 /// # use sequoia_openpgp as openpgp;
3151 /// # use openpgp::cert::prelude::*;
3152 /// use openpgp::policy::StandardPolicy;
3153 ///
3154 /// # fn main() -> openpgp::Result<()> {
3155 /// let p = &StandardPolicy::new();
3156 ///
3157 /// # let (cert, _) =
3158 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3159 /// # .generate()?;
3160 /// for ka in cert.keys().with_policy(p, None) {
3161 /// if ka.for_storage_encryption() {
3162 /// // `ka` is storage-encryption capable.
3163 /// }
3164 /// }
3165 /// # Ok(()) }
3166 /// ```
3167 ///
3168 /// [data at rest]: https://en.wikipedia.org/wiki/Data_at_rest
3169 /// [data in transit]: https://en.wikipedia.org/wiki/Data_in_transit
3170 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3171 pub fn for_storage_encryption(&self) -> bool
3172 {
3173 self.has_any_key_flag(KeyFlags::empty().set_storage_encryption())
3174 }
3175
3176 /// Returns whether the key is transport-encryption capable.
3177 ///
3178 /// OpenPGP distinguishes two types of encryption keys: those for
3179 /// storage ([data at rest]) and those for transport ([data in
3180 /// transit]). Most OpenPGP implementations, however, don't
3181 /// distinguish between them in practice. Instead, when they
3182 /// create a new encryption key, they just set both flags.
3183 /// Likewise, when encrypting a message, it is not typically
3184 /// possible to indicate the type of protection that is needed.
3185 /// Sequoia supports creating keys with only one of these flags
3186 /// set, and makes it easy to select the right type of key when
3187 /// encrypting messages.
3188 ///
3189 /// The key flags are looked up as described in
3190 /// [`ValidKeyAmalgamation::key_flags`].
3191 ///
3192 /// # Examples
3193 ///
3194 /// Finds keys that are transport-encryption capable:
3195 ///
3196 /// ```
3197 /// # use sequoia_openpgp as openpgp;
3198 /// # use openpgp::cert::prelude::*;
3199 /// use openpgp::policy::StandardPolicy;
3200 ///
3201 /// # fn main() -> openpgp::Result<()> {
3202 /// let p = &StandardPolicy::new();
3203 ///
3204 /// # let (cert, _) =
3205 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3206 /// # .generate()?;
3207 /// for ka in cert.keys().with_policy(p, None) {
3208 /// if ka.for_transport_encryption() {
3209 /// // `ka` is transport-encryption capable.
3210 /// }
3211 /// }
3212 /// # Ok(()) }
3213 /// ```
3214 ///
3215 /// [data at rest]: https://en.wikipedia.org/wiki/Data_at_rest
3216 /// [data in transit]: https://en.wikipedia.org/wiki/Data_in_transit
3217 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3218 pub fn for_transport_encryption(&self) -> bool
3219 {
3220 self.has_any_key_flag(KeyFlags::empty().set_transport_encryption())
3221 }
3222
3223 /// Returns how long the key is live.
3224 ///
3225 /// This returns how long the key is live relative to its creation
3226 /// time. Use [`ValidKeyAmalgamation::key_expiration_time`] to
3227 /// get the key's absolute expiry time.
3228 ///
3229 /// This function considers both the binding signature and the
3230 /// direct key signature. Information in the binding signature
3231 /// takes precedence over the direct key signature. See [Section
3232 /// 5.2.3.10 of RFC 9580].
3233 ///
3234 /// # Examples
3235 ///
3236 /// ```
3237 /// use std::time;
3238 /// use std::convert::TryInto;
3239 /// # use sequoia_openpgp as openpgp;
3240 /// # use openpgp::cert::prelude::*;
3241 /// use openpgp::policy::StandardPolicy;
3242 /// use openpgp::types::Timestamp;
3243 ///
3244 /// # fn main() -> openpgp::Result<()> {
3245 /// let p = &StandardPolicy::new();
3246 ///
3247 /// // OpenPGP Timestamps have a one-second resolution. Since we
3248 /// // want to round trip the time, round it down.
3249 /// let now: Timestamp = time::SystemTime::now().try_into()?;
3250 /// let now: time::SystemTime = now.try_into()?;
3251 ///
3252 /// let a_week = time::Duration::from_secs(7 * 24 * 60 * 60);
3253 ///
3254 /// let (cert, _) =
3255 /// CertBuilder::general_purpose(Some("alice@example.org"))
3256 /// .set_creation_time(now)
3257 /// .set_validity_period(a_week)
3258 /// .generate()?;
3259 ///
3260 /// assert_eq!(cert.primary_key().with_policy(p, None)?.key_validity_period(),
3261 /// Some(a_week));
3262 /// # Ok(()) }
3263 /// ```
3264 ///
3265 /// [`ValidKeyAmalgamation::key_expiration_time`]: ValidKeyAmalgamation::key_expiration_time()
3266 /// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
3267 pub fn key_validity_period(&self) -> Option<std::time::Duration> {
3268 self.map(|s| s.key_validity_period())
3269 }
3270
3271 /// Returns the key's expiration time.
3272 ///
3273 /// If this function returns `None`, the key does not expire.
3274 ///
3275 /// This returns the key's expiration time. Use
3276 /// [`ValidKeyAmalgamation::key_validity_period`] to get the
3277 /// duration of the key's lifetime.
3278 ///
3279 /// This function considers both the binding signature and the
3280 /// direct key signature. Information in the binding signature
3281 /// takes precedence over the direct key signature. See [Section
3282 /// 5.2.3.10 of RFC 9580].
3283 ///
3284 /// # Examples
3285 ///
3286 /// ```
3287 /// use std::time;
3288 /// use std::convert::TryInto;
3289 /// # use sequoia_openpgp as openpgp;
3290 /// # use openpgp::cert::prelude::*;
3291 /// use openpgp::policy::StandardPolicy;
3292 /// use openpgp::types::Timestamp;
3293 ///
3294 /// # fn main() -> openpgp::Result<()> {
3295 /// let p = &StandardPolicy::new();
3296 ///
3297 /// // OpenPGP Timestamps have a one-second resolution. Since we
3298 /// // want to round trip the time, round it down.
3299 /// let now: Timestamp = time::SystemTime::now().try_into()?;
3300 /// let now: time::SystemTime = now.try_into()?;
3301 //
3302 /// let a_week = time::Duration::from_secs(7 * 24 * 60 * 60);
3303 /// let a_week_later = now + a_week;
3304 ///
3305 /// let (cert, _) =
3306 /// CertBuilder::general_purpose(Some("alice@example.org"))
3307 /// .set_creation_time(now)
3308 /// .set_validity_period(a_week)
3309 /// .generate()?;
3310 ///
3311 /// assert_eq!(cert.primary_key().with_policy(p, None)?.key_expiration_time(),
3312 /// Some(a_week_later));
3313 /// # Ok(()) }
3314 /// ```
3315 ///
3316 /// [`ValidKeyAmalgamation::key_validity_period`]: ValidKeyAmalgamation::key_validity_period()
3317 /// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
3318 pub fn key_expiration_time(&self) -> Option<time::SystemTime> {
3319 match self.key_validity_period() {
3320 Some(vp) if vp.as_secs() > 0 => Some(self.key().creation_time() + vp),
3321 _ => None,
3322 }
3323 }
3324
3325 // NOTE: If you add a method to ValidKeyAmalgamation that takes
3326 // ownership of self, then don't forget to write a forwarder for
3327 // it for ValidPrimaryKeyAmalgamation.
3328}
3329
3330
3331#[cfg(test)]
3332mod test {
3333 use std::time::Duration;
3334 use std::time::UNIX_EPOCH;
3335
3336 use crate::policy::StandardPolicy as P;
3337 use crate::cert::prelude::*;
3338 use crate::packet::Packet;
3339 use crate::packet::signature::SignatureBuilder;
3340 use crate::types::ReasonForRevocation;
3341 use crate::types::RevocationType;
3342
3343 use super::*;
3344
3345 #[test]
3346 fn expire_subkeys() {
3347 let p = &P::new();
3348
3349 // Timeline:
3350 //
3351 // -1: Key created with no key expiration.
3352 // 0: Setkeys set to expire in 1 year
3353 // 1: Subkeys expire
3354
3355 let now = crate::now();
3356 let a_year = time::Duration::from_secs(365 * 24 * 60 * 60);
3357 let in_a_year = now + a_year;
3358 let in_two_years = now + 2 * a_year;
3359
3360 let (cert, _) = CertBuilder::new()
3361 .set_creation_time(now - a_year)
3362 .add_signing_subkey()
3363 .add_transport_encryption_subkey()
3364 .generate().unwrap();
3365
3366 for ka in cert.keys().with_policy(p, None) {
3367 assert!(ka.alive().is_ok());
3368 }
3369
3370 let mut primary_signer = cert.primary_key().key().clone()
3371 .parts_into_secret().unwrap().into_keypair().unwrap();
3372 let mut signing_subkey_signer = cert.with_policy(p, None).unwrap()
3373 .keys().for_signing().next().unwrap()
3374 .key().clone().parts_into_secret().unwrap()
3375 .into_keypair().unwrap();
3376
3377 // Only expire the subkeys.
3378 let sigs = cert.keys().subkeys().with_policy(p, None)
3379 .flat_map(|ka| {
3380 if ! ka.for_signing() {
3381 ka.set_expiration_time(&mut primary_signer,
3382 None,
3383 Some(in_a_year)).unwrap()
3384 } else {
3385 ka.set_expiration_time(&mut primary_signer,
3386 Some(&mut signing_subkey_signer),
3387 Some(in_a_year)).unwrap()
3388 }
3389 .into_iter()
3390 .map(Into::into)
3391 })
3392 .collect::<Vec<Packet>>();
3393 let cert = cert.insert_packets(sigs).unwrap().0;
3394
3395 for ka in cert.keys().with_policy(p, None) {
3396 assert!(ka.alive().is_ok());
3397 }
3398
3399 // Primary should not be expired two years from now.
3400 assert!(cert.primary_key().with_policy(p, in_two_years).unwrap()
3401 .alive().is_ok());
3402 // But the subkeys should be.
3403 for ka in cert.keys().subkeys().with_policy(p, in_two_years) {
3404 assert!(ka.alive().is_err());
3405 }
3406 }
3407
3408 /// Test that subkeys of expired certificates are also considered
3409 /// expired.
3410 #[test]
3411 fn issue_564() -> Result<()> {
3412 use crate::parse::Parse;
3413 use crate::packet::signature::subpacket::SubpacketTag;
3414 let p = &P::new();
3415 let cert = Cert::from_bytes(crate::tests::key("testy.pgp"))?;
3416 assert!(cert.with_policy(p, None)?.alive().is_err());
3417 let subkey = cert.with_policy(p, None)?.keys().nth(1).unwrap();
3418 assert!(subkey.binding_signature().hashed_area()
3419 .subpacket(SubpacketTag::KeyExpirationTime).is_none());
3420 assert!(subkey.alive().is_err());
3421 Ok(())
3422 }
3423
3424 /// When setting the primary key's validity period, we create a
3425 /// direct key signature. Check that this works even when the
3426 /// original certificate doesn't have a direct key signature.
3427 #[test]
3428 fn set_expiry_on_certificate_without_direct_signature() -> Result<()> {
3429 use crate::policy::StandardPolicy;
3430
3431 let p = &StandardPolicy::new();
3432
3433 let (cert, _) =
3434 CertBuilder::general_purpose(Some("alice@example.org"))
3435 .set_validity_period(None)
3436 .generate()?;
3437
3438 // Remove the direct key signatures.
3439 let cert = Cert::from_packets(
3440 cert.as_tsk().into_packets()
3441 .filter(|p| ! matches!(
3442 p,
3443 Packet::Signature(s) if s.typ() == SignatureType::DirectKey
3444 )))?;
3445
3446 let vc = cert.with_policy(p, None)?;
3447
3448 // Assert that the keys are not expired.
3449 for ka in vc.keys() {
3450 assert!(ka.alive().is_ok());
3451 }
3452
3453 // Make the primary key expire in a week.
3454 let t = crate::now()
3455 + time::Duration::from_secs(7 * 24 * 60 * 60);
3456
3457 let mut signer = vc
3458 .primary_key().key().clone().parts_into_secret()?
3459 .into_keypair()?;
3460 let sigs = vc.primary_key()
3461 .set_expiration_time(&mut signer, Some(t))?;
3462
3463 assert!(sigs.iter().any(|s| {
3464 s.typ() == SignatureType::DirectKey
3465 }));
3466
3467 let cert = cert.insert_packets(sigs)?.0;
3468
3469 // Make sure the primary key *and* all subkeys expire in a
3470 // week: the subkeys inherit the KeyExpirationTime subpacket
3471 // from the direct key signature.
3472 for ka in cert.keys() {
3473 let ka = ka.with_policy(p, None)?;
3474 assert!(ka.alive().is_ok());
3475
3476 let ka = ka.with_policy(p, t + std::time::Duration::new(1, 0))?;
3477 assert!(ka.alive().is_err());
3478 }
3479
3480 Ok(())
3481 }
3482
3483 #[test]
3484 fn key_amalgamation_certifications_by_key() -> Result<()> {
3485 // Alice and Bob certify Carol's certificate. We then check
3486 // that valid_certifications_by_key and
3487 // active_certifications_by_key return them.
3488 let p = &crate::policy::StandardPolicy::new();
3489
3490 // $ date -u -d '2024-01-02 13:00' +%s
3491 let t0 = UNIX_EPOCH + Duration::new(1704200400, 0);
3492 // $ date -u -d '2024-01-02 14:00' +%s
3493 let t1 = UNIX_EPOCH + Duration::new(1704204000, 0);
3494 // $ date -u -d '2024-01-02 15:00' +%s
3495 let t2 = UNIX_EPOCH + Duration::new(1704207600, 0);
3496
3497 let (alice, _) = CertBuilder::new()
3498 .set_creation_time(t0)
3499 .add_userid("<alice@example.example>")
3500 .generate()
3501 .unwrap();
3502 let alice_primary = alice.primary_key().key();
3503
3504 let (bob, _) = CertBuilder::new()
3505 .set_creation_time(t0)
3506 .add_userid("<bob@example.example>")
3507 .generate()
3508 .unwrap();
3509 let bob_primary = bob.primary_key().key();
3510
3511 let carol_userid = "<carol@example.example>";
3512 let (carol, _) = CertBuilder::new()
3513 .set_creation_time(t0)
3514 .add_userid(carol_userid)
3515 .generate()
3516 .unwrap();
3517
3518 let ka = alice.primary_key();
3519 assert_eq!(
3520 ka.valid_certifications_by_key(p, None, alice_primary).count(),
3521 0);
3522 assert_eq!(
3523 ka.active_certifications_by_key(p, None, alice_primary).count(),
3524 0);
3525
3526 // Alice has not certified Bob's User ID.
3527 let ka = bob.primary_key();
3528 assert_eq!(
3529 ka.valid_certifications_by_key(p, None, alice_primary).count(),
3530 0);
3531 assert_eq!(
3532 ka.active_certifications_by_key(p, None, alice_primary).count(),
3533 0);
3534
3535 // Alice has not certified Carol's User ID.
3536 let ka = carol.primary_key();
3537 assert_eq!(
3538 ka.valid_certifications_by_key(p, None, alice_primary).count(),
3539 0);
3540 assert_eq!(
3541 ka.active_certifications_by_key(p, None, alice_primary).count(),
3542 0);
3543
3544
3545 // Have Alice certify Carol's certificate at t1.
3546 let mut alice_signer = alice_primary
3547 .clone()
3548 .parts_into_secret().expect("have unencrypted key material")
3549 .into_keypair().expect("have unencrypted key material");
3550 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3551 .set_signature_creation_time(t1)?
3552 .sign_direct_key(
3553 &mut alice_signer,
3554 carol.primary_key().key())?;
3555 let carol = carol.insert_packets(certification.clone())?.0;
3556
3557 // Check that it is returned.
3558 let ka = carol.primary_key();
3559 assert_eq!(ka.certifications().count(), 1);
3560
3561 assert_eq!(
3562 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3563 0);
3564 assert_eq!(
3565 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3566 0);
3567
3568 assert_eq!(
3569 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3570 1);
3571 assert_eq!(
3572 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3573 1);
3574
3575 assert_eq!(
3576 ka.valid_certifications_by_key(p, t1, bob_primary).count(),
3577 0);
3578 assert_eq!(
3579 ka.active_certifications_by_key(p, t1, bob_primary).count(),
3580 0);
3581
3582
3583 // Have Alice certify Carol's certificate at t1 (again).
3584 // Since both certifications were created at t1, they should
3585 // both be returned.
3586 let mut alice_signer = alice_primary
3587 .clone()
3588 .parts_into_secret().expect("have unencrypted key material")
3589 .into_keypair().expect("have unencrypted key material");
3590 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3591 .set_signature_creation_time(t1)?
3592 .sign_direct_key(
3593 &mut alice_signer,
3594 carol.primary_key().key())?;
3595 let carol = carol.insert_packets(certification.clone())?.0;
3596
3597 // Check that it is returned.
3598 let ka = carol.primary_key();
3599 assert_eq!(ka.certifications().count(), 2);
3600 assert_eq!(
3601 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3602 0);
3603 assert_eq!(
3604 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3605 0);
3606
3607 assert_eq!(
3608 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3609 2);
3610 assert_eq!(
3611 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3612 2);
3613
3614 assert_eq!(
3615 ka.valid_certifications_by_key(p, t2, alice_primary).count(),
3616 2);
3617 assert_eq!(
3618 ka.active_certifications_by_key(p, t2, alice_primary).count(),
3619 2);
3620
3621 assert_eq!(
3622 ka.valid_certifications_by_key(p, t0, bob_primary).count(),
3623 0);
3624 assert_eq!(
3625 ka.active_certifications_by_key(p, t0, bob_primary).count(),
3626 0);
3627
3628
3629 // Have Alice certify Carol's certificate at t2. Now we only
3630 // have one active certification.
3631 let mut alice_signer = alice_primary
3632 .clone()
3633 .parts_into_secret().expect("have unencrypted key material")
3634 .into_keypair().expect("have unencrypted key material");
3635 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3636 .set_signature_creation_time(t2)?
3637 .sign_direct_key(
3638 &mut alice_signer,
3639 carol.primary_key().key())?;
3640 let carol = carol.insert_packets(certification.clone())?.0;
3641
3642 // Check that it is returned.
3643 let ka = carol.primary_key();
3644 assert_eq!(ka.certifications().count(), 3);
3645 assert_eq!(
3646 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3647 0);
3648 assert_eq!(
3649 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3650 0);
3651
3652 assert_eq!(
3653 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3654 2);
3655 assert_eq!(
3656 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3657 2);
3658
3659 assert_eq!(
3660 ka.valid_certifications_by_key(p, t2, alice_primary).count(),
3661 3);
3662 assert_eq!(
3663 ka.active_certifications_by_key(p, t2, alice_primary).count(),
3664 1);
3665
3666 assert_eq!(
3667 ka.valid_certifications_by_key(p, t0, bob_primary).count(),
3668 0);
3669 assert_eq!(
3670 ka.active_certifications_by_key(p, t0, bob_primary).count(),
3671 0);
3672
3673
3674 // Have Bob certify Carol's certificate at t1 and have it expire at t2.
3675 let mut bob_signer = bob.primary_key()
3676 .key()
3677 .clone()
3678 .parts_into_secret().expect("have unencrypted key material")
3679 .into_keypair().expect("have unencrypted key material");
3680 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3681 .set_signature_creation_time(t1)?
3682 .set_signature_validity_period(t2.duration_since(t1)?)?
3683 .sign_direct_key(
3684 &mut bob_signer,
3685 carol.primary_key().key())?;
3686 let carol = carol.insert_packets(certification.clone())?.0;
3687
3688 // Check that it is returned.
3689 let ka = carol.primary_key();
3690 assert_eq!(ka.certifications().count(), 4);
3691
3692 assert_eq!(
3693 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3694 0);
3695 assert_eq!(
3696 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3697 0);
3698
3699 assert_eq!(
3700 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3701 2);
3702 assert_eq!(
3703 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3704 2);
3705
3706 assert_eq!(
3707 ka.valid_certifications_by_key(p, t2, alice_primary).count(),
3708 3);
3709 assert_eq!(
3710 ka.active_certifications_by_key(p, t2, alice_primary).count(),
3711 1);
3712
3713 assert_eq!(
3714 ka.valid_certifications_by_key(p, t0, bob_primary).count(),
3715 0);
3716 assert_eq!(
3717 ka.active_certifications_by_key(p, t0, bob_primary).count(),
3718 0);
3719
3720 assert_eq!(
3721 ka.valid_certifications_by_key(p, t1, bob_primary).count(),
3722 1);
3723 assert_eq!(
3724 ka.active_certifications_by_key(p, t1, bob_primary).count(),
3725 1);
3726
3727 // It expired.
3728 assert_eq!(
3729 ka.valid_certifications_by_key(p, t2, bob_primary).count(),
3730 0);
3731 assert_eq!(
3732 ka.active_certifications_by_key(p, t2, bob_primary).count(),
3733 0);
3734
3735
3736 // Have Bob certify Carol's certificate at t1 again. This
3737 // time don't have it expire.
3738 let mut bob_signer = bob.primary_key()
3739 .key()
3740 .clone()
3741 .parts_into_secret().expect("have unencrypted key material")
3742 .into_keypair().expect("have unencrypted key material");
3743 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3744 .set_signature_creation_time(t1)?
3745 .sign_direct_key(
3746 &mut bob_signer,
3747 carol.primary_key().key())?;
3748 let carol = carol.insert_packets(certification.clone())?.0;
3749
3750 // Check that it is returned.
3751 let ka = carol.primary_key();
3752 assert_eq!(ka.certifications().count(), 5);
3753 assert_eq!(
3754 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3755 0);
3756 assert_eq!(
3757 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3758 0);
3759
3760 assert_eq!(
3761 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3762 2);
3763 assert_eq!(
3764 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3765 2);
3766
3767 assert_eq!(
3768 ka.valid_certifications_by_key(p, t2, alice_primary).count(),
3769 3);
3770 assert_eq!(
3771 ka.active_certifications_by_key(p, t2, alice_primary).count(),
3772 1);
3773
3774 assert_eq!(
3775 ka.valid_certifications_by_key(p, t0, bob_primary).count(),
3776 0);
3777 assert_eq!(
3778 ka.active_certifications_by_key(p, t0, bob_primary).count(),
3779 0);
3780
3781 assert_eq!(
3782 ka.valid_certifications_by_key(p, t1, bob_primary).count(),
3783 2);
3784 assert_eq!(
3785 ka.active_certifications_by_key(p, t1, bob_primary).count(),
3786 2);
3787
3788 // One of the certifications expired.
3789 assert_eq!(
3790 ka.valid_certifications_by_key(p, t2, bob_primary).count(),
3791 1);
3792 assert_eq!(
3793 ka.active_certifications_by_key(p, t2, bob_primary).count(),
3794 1);
3795
3796 Ok(())
3797 }
3798
3799 fn key_amalgamation_valid_third_party_revocations_by_key(
3800 reason: ReasonForRevocation)
3801 -> Result<()>
3802 {
3803 // Hard revocations are returned independent of the reference
3804 // time and independent of their expiration. They are always
3805 // live.
3806 let soft = reason.revocation_type() == RevocationType::Soft;
3807
3808 // Alice and Bob revoke Carol's certificate. We then check
3809 // that valid_third_party_revocations_by_key returns them.
3810 let p = &crate::policy::StandardPolicy::new();
3811
3812 // $ date -u -d '2024-01-02 13:00' +%s
3813 let t0 = UNIX_EPOCH + Duration::new(1704200400, 0);
3814 // $ date -u -d '2024-01-02 14:00' +%s
3815 let t1 = UNIX_EPOCH + Duration::new(1704204000, 0);
3816 // $ date -u -d '2024-01-02 15:00' +%s
3817 let t2 = UNIX_EPOCH + Duration::new(1704207600, 0);
3818
3819 let (alice, _) = CertBuilder::new()
3820 .set_creation_time(t0)
3821 .add_userid("<alice@example.example>")
3822 .generate()
3823 .unwrap();
3824 let alice_primary = alice.primary_key().key();
3825
3826 let (bob, _) = CertBuilder::new()
3827 .set_creation_time(t0)
3828 .add_userid("<bob@example.example>")
3829 .generate()
3830 .unwrap();
3831 let bob_primary = bob.primary_key().key();
3832
3833 let carol_userid = "<carol@example.example>";
3834 let (carol, _) = CertBuilder::new()
3835 .set_creation_time(t0)
3836 .add_userid(carol_userid)
3837 .generate()
3838 .unwrap();
3839
3840 let ka = alice.primary_key();
3841 assert_eq!(
3842 ka.valid_third_party_revocations_by_key(p, None, alice_primary).count(),
3843 0);
3844
3845 // Alice has not revoked Bob's certificate.
3846 let ka = bob.primary_key();
3847 assert_eq!(
3848 ka.valid_third_party_revocations_by_key(p, None, alice_primary).count(),
3849 0);
3850
3851 // Alice has not revoked Carol's certificate.
3852 let ka = carol.primary_key();
3853 assert_eq!(
3854 ka.valid_third_party_revocations_by_key(p, None, alice_primary).count(),
3855 0);
3856
3857
3858 // Have Alice revoke Carol's revoke at t1.
3859 let mut alice_signer = alice_primary
3860 .clone()
3861 .parts_into_secret().expect("have unencrypted key material")
3862 .into_keypair().expect("have unencrypted key material");
3863 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3864 .set_signature_creation_time(t1)?
3865 .set_reason_for_revocation(
3866 reason, b"")?
3867 .sign_direct_key(
3868 &mut alice_signer,
3869 carol.primary_key().key())?;
3870 let carol = carol.insert_packets(rev)?.0;
3871
3872 // Check that it is returned.
3873 let ka = carol.primary_key();
3874 assert_eq!(ka.other_revocations().count(), 1);
3875
3876 assert_eq!(
3877 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3878 if soft { 0 } else { 1 });
3879 assert_eq!(
3880 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3881 1);
3882 assert_eq!(
3883 ka.valid_third_party_revocations_by_key(p, t1, bob_primary).count(),
3884 0);
3885
3886
3887 // Have Alice revoke Carol's certificate at t1 (again).
3888 let mut alice_signer = alice_primary
3889 .clone()
3890 .parts_into_secret().expect("have unencrypted key material")
3891 .into_keypair().expect("have unencrypted key material");
3892 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3893 .set_signature_creation_time(t1)?
3894 .set_reason_for_revocation(reason, b"")?
3895 .sign_direct_key(
3896 &mut alice_signer,
3897 carol.primary_key().key())?;
3898 let carol = carol.insert_packets(rev)?.0;
3899
3900 // Check that it is returned.
3901 let ka = carol.primary_key();
3902 assert_eq!(ka.other_revocations().count(), 2);
3903 assert_eq!(
3904 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3905 if soft { 0 } else { 2 });
3906 assert_eq!(
3907 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3908 2);
3909 assert_eq!(
3910 ka.valid_third_party_revocations_by_key(p, t2, alice_primary).count(),
3911 2);
3912 assert_eq!(
3913 ka.valid_third_party_revocations_by_key(p, t0, bob_primary).count(),
3914 0);
3915
3916
3917 // Have Alice revoke Carol's certificate at t2.
3918 let mut alice_signer = alice_primary
3919 .clone()
3920 .parts_into_secret().expect("have unencrypted key material")
3921 .into_keypair().expect("have unencrypted key material");
3922 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3923 .set_signature_creation_time(t2)?
3924 .set_reason_for_revocation(reason, b"")?
3925 .sign_direct_key(
3926 &mut alice_signer,
3927 carol.primary_key().key())?;
3928 let carol = carol.insert_packets(rev)?.0;
3929
3930 // Check that it is returned.
3931 let ka = carol.primary_key();
3932 assert_eq!(ka.other_revocations().count(), 3);
3933 assert_eq!(
3934 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3935 if soft { 0 } else { 3 });
3936 assert_eq!(
3937 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3938 if soft { 2 } else { 3 });
3939 assert_eq!(
3940 ka.valid_third_party_revocations_by_key(p, t2, alice_primary).count(),
3941 3);
3942 assert_eq!(
3943 ka.valid_third_party_revocations_by_key(p, t0, bob_primary).count(),
3944 0);
3945
3946
3947 // Have Bob revoke Carol's certificate at t1 and have it expire at t2.
3948 let mut bob_signer = bob.primary_key()
3949 .key()
3950 .clone()
3951 .parts_into_secret().expect("have unencrypted key material")
3952 .into_keypair().expect("have unencrypted key material");
3953 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3954 .set_signature_creation_time(t1)?
3955 .set_signature_validity_period(t2.duration_since(t1)?)?
3956 .set_reason_for_revocation(reason, b"")?
3957 .sign_direct_key(
3958 &mut bob_signer,
3959 carol.primary_key().key())?;
3960 let carol = carol.insert_packets(rev)?.0;
3961
3962 // Check that it is returned.
3963 let ka = carol.primary_key();
3964 assert_eq!(ka.other_revocations().count(), 4);
3965
3966 assert_eq!(
3967 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3968 if soft { 0 } else { 3 });
3969 assert_eq!(
3970 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3971 if soft { 2 } else { 3 });
3972 assert_eq!(
3973 ka.valid_third_party_revocations_by_key(p, t2, alice_primary).count(),
3974 3);
3975 assert_eq!(
3976 ka.valid_third_party_revocations_by_key(p, t0, bob_primary).count(),
3977 if soft { 0 } else { 1 });
3978 assert_eq!(
3979 ka.valid_third_party_revocations_by_key(p, t1, bob_primary).count(),
3980 1);
3981 // It expired.
3982 assert_eq!(
3983 ka.valid_third_party_revocations_by_key(p, t2, bob_primary).count(),
3984 if soft { 0 } else { 1 });
3985
3986
3987 // Have Bob revoke Carol's certificate at t1 again. This
3988 // time don't have it expire.
3989 let mut bob_signer = bob.primary_key()
3990 .key()
3991 .clone()
3992 .parts_into_secret().expect("have unencrypted key material")
3993 .into_keypair().expect("have unencrypted key material");
3994 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3995 .set_signature_creation_time(t1)?
3996 .set_reason_for_revocation(reason, b"")?
3997 .sign_direct_key(
3998 &mut bob_signer,
3999 carol.primary_key().key())?;
4000 let carol = carol.insert_packets(rev)?.0;
4001
4002 // Check that it is returned.
4003 let ka = carol.primary_key();
4004 assert_eq!(
4005 ka.other_revocations().count(), 5);
4006 assert_eq!(
4007 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
4008 if soft { 0 } else { 3 });
4009 assert_eq!(
4010 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
4011 if soft { 2 } else { 3 });
4012 assert_eq!(
4013 ka.valid_third_party_revocations_by_key(p, t2, alice_primary).count(),
4014 3);
4015 assert_eq!(
4016 ka.valid_third_party_revocations_by_key(p, t0, bob_primary).count(),
4017 if soft { 0 } else { 2 });
4018 assert_eq!(
4019 ka.valid_third_party_revocations_by_key(p, t1, bob_primary).count(),
4020 2);
4021 // One of the revocations expired.
4022 assert_eq!(
4023 ka.valid_third_party_revocations_by_key(p, t2, bob_primary).count(),
4024 if soft { 1 } else { 2 });
4025
4026 Ok(())
4027 }
4028
4029 #[test]
4030 fn key_amalgamation_valid_third_party_revocations_by_key_soft()
4031 -> Result<()>
4032 {
4033 key_amalgamation_valid_third_party_revocations_by_key(
4034 ReasonForRevocation::KeyRetired)
4035 }
4036
4037 #[test]
4038 fn key_amalgamation_valid_third_party_revocations_by_key_hard()
4039 -> Result<()>
4040 {
4041 key_amalgamation_valid_third_party_revocations_by_key(
4042 ReasonForRevocation::KeyCompromised)
4043 }
4044}