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 /// [`Key Flags`]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
2885 /// [SSS]: https://de.wikipedia.org/wiki/Shamir%E2%80%99s_Secret_Sharing
2886 /// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
2887 ///
2888 /// # Examples
2889 ///
2890 /// ```
2891 /// # use sequoia_openpgp as openpgp;
2892 /// # use openpgp::cert::prelude::*;
2893 /// # use openpgp::policy::{Policy, StandardPolicy};
2894 /// #
2895 /// # fn main() -> openpgp::Result<()> {
2896 /// # let p: &dyn Policy = &StandardPolicy::new();
2897 /// # let (cert, _) =
2898 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2899 /// # .generate()?;
2900 /// # let cert = cert.with_policy(p, None)?;
2901 /// let ka = cert.primary_key();
2902 /// println!("Primary Key's Key Flags: {:?}", ka.key_flags());
2903 /// # assert!(ka.key_flags().unwrap().for_certification());
2904 /// # Ok(()) }
2905 /// ```
2906 pub fn key_flags(&self) -> Option<KeyFlags> {
2907 self.map(|s| s.key_flags())
2908 }
2909
2910 /// Returns whether the key has at least one of the specified key
2911 /// flags.
2912 ///
2913 /// The key flags are looked up as described in
2914 /// [`ValidKeyAmalgamation::key_flags`].
2915 ///
2916 /// # Examples
2917 ///
2918 /// Finds keys that may be used for transport encryption (data in
2919 /// motion) *or* storage encryption (data at rest):
2920 ///
2921 /// ```
2922 /// # use sequoia_openpgp as openpgp;
2923 /// # use openpgp::cert::prelude::*;
2924 /// use openpgp::policy::StandardPolicy;
2925 /// use openpgp::types::KeyFlags;
2926 ///
2927 /// # fn main() -> openpgp::Result<()> {
2928 /// let p = &StandardPolicy::new();
2929 ///
2930 /// # let (cert, _) =
2931 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2932 /// # .generate()?;
2933 /// for ka in cert.keys().with_policy(p, None) {
2934 /// if ka.has_any_key_flag(KeyFlags::empty()
2935 /// .set_storage_encryption()
2936 /// .set_transport_encryption())
2937 /// {
2938 /// // `ka` is encryption capable.
2939 /// }
2940 /// }
2941 /// # Ok(()) }
2942 /// ```
2943 ///
2944 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
2945 pub fn has_any_key_flag<F>(&self, flags: F) -> bool
2946 where F: Borrow<KeyFlags>
2947 {
2948 let our_flags = self.key_flags().unwrap_or_else(KeyFlags::empty);
2949 !(&our_flags & flags.borrow()).is_empty()
2950 }
2951
2952 /// Returns whether the key is certification capable.
2953 ///
2954 /// Note: [Section 10.1 of RFC 9580] says that the primary key is
2955 /// certification capable independent of the `Key Flags`
2956 /// subpacket:
2957 ///
2958 /// > In a V4 key, the primary key MUST be a key capable of
2959 /// > certification.
2960 ///
2961 /// This function only reflects what is stored in the `Key Flags`
2962 /// packet; it does not implicitly set this flag. In practice,
2963 /// there are keys whose primary key's `Key Flags` do not have the
2964 /// certification capable flag set. Some versions of netpgp, for
2965 /// instance, create keys like this. Sequoia's higher-level
2966 /// functionality correctly handles these keys by always
2967 /// considering the primary key to be certification capable.
2968 /// Users of this interface should too.
2969 ///
2970 /// The key flags are looked up as described in
2971 /// [`ValidKeyAmalgamation::key_flags`].
2972 ///
2973 /// # Examples
2974 ///
2975 /// Finds keys that are certification capable:
2976 ///
2977 /// ```
2978 /// # use sequoia_openpgp as openpgp;
2979 /// # use openpgp::cert::prelude::*;
2980 /// use openpgp::policy::StandardPolicy;
2981 ///
2982 /// # fn main() -> openpgp::Result<()> {
2983 /// let p = &StandardPolicy::new();
2984 ///
2985 /// # let (cert, _) =
2986 /// # CertBuilder::general_purpose(Some("alice@example.org"))
2987 /// # .generate()?;
2988 /// for ka in cert.keys().with_policy(p, None) {
2989 /// if ka.primary() || ka.for_certification() {
2990 /// // `ka` is certification capable.
2991 /// }
2992 /// }
2993 /// # Ok(()) }
2994 /// ```
2995 ///
2996 /// [Section 10.1 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.29
2997 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
2998 pub fn for_certification(&self) -> bool {
2999 self.has_any_key_flag(KeyFlags::empty().set_certification())
3000 }
3001
3002 /// Returns whether the key is signing capable.
3003 ///
3004 /// The key flags are looked up as described in
3005 /// [`ValidKeyAmalgamation::key_flags`].
3006 ///
3007 /// # Examples
3008 ///
3009 /// Finds keys that are signing capable:
3010 ///
3011 /// ```
3012 /// # use sequoia_openpgp as openpgp;
3013 /// # use openpgp::cert::prelude::*;
3014 /// use openpgp::policy::StandardPolicy;
3015 ///
3016 /// # fn main() -> openpgp::Result<()> {
3017 /// let p = &StandardPolicy::new();
3018 ///
3019 /// # let (cert, _) =
3020 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3021 /// # .generate()?;
3022 /// for ka in cert.keys().with_policy(p, None) {
3023 /// if ka.for_signing() {
3024 /// // `ka` is signing capable.
3025 /// }
3026 /// }
3027 /// # Ok(()) }
3028 /// ```
3029 ///
3030 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3031 pub fn for_signing(&self) -> bool {
3032 self.has_any_key_flag(KeyFlags::empty().set_signing())
3033 }
3034
3035 /// Returns whether the key is authentication capable.
3036 ///
3037 /// The key flags are looked up as described in
3038 /// [`ValidKeyAmalgamation::key_flags`].
3039 ///
3040 /// # Examples
3041 ///
3042 /// Finds keys that are authentication capable:
3043 ///
3044 /// ```
3045 /// # use sequoia_openpgp as openpgp;
3046 /// # use openpgp::cert::prelude::*;
3047 /// use openpgp::policy::StandardPolicy;
3048 ///
3049 /// # fn main() -> openpgp::Result<()> {
3050 /// let p = &StandardPolicy::new();
3051 ///
3052 /// # let (cert, _) =
3053 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3054 /// # .generate()?;
3055 /// for ka in cert.keys().with_policy(p, None) {
3056 /// if ka.for_authentication() {
3057 /// // `ka` is authentication capable.
3058 /// }
3059 /// }
3060 /// # Ok(()) }
3061 /// ```
3062 ///
3063 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3064 pub fn for_authentication(&self) -> bool
3065 {
3066 self.has_any_key_flag(KeyFlags::empty().set_authentication())
3067 }
3068
3069 /// Returns whether the key is storage-encryption capable.
3070 ///
3071 /// OpenPGP distinguishes two types of encryption keys: those for
3072 /// storage ([data at rest]) and those for transport ([data in
3073 /// transit]). Most OpenPGP implementations, however, don't
3074 /// distinguish between them in practice. Instead, when they
3075 /// create a new encryption key, they just set both flags.
3076 /// Likewise, when encrypting a message, it is not typically
3077 /// possible to indicate the type of protection that is needed.
3078 /// Sequoia supports creating keys with only one of these flags
3079 /// set, and makes it easy to select the right type of key when
3080 /// encrypting messages.
3081 ///
3082 /// The key flags are looked up as described in
3083 /// [`ValidKeyAmalgamation::key_flags`].
3084 ///
3085 /// # Examples
3086 ///
3087 /// Finds keys that are storage-encryption capable:
3088 ///
3089 /// ```
3090 /// # use sequoia_openpgp as openpgp;
3091 /// # use openpgp::cert::prelude::*;
3092 /// use openpgp::policy::StandardPolicy;
3093 ///
3094 /// # fn main() -> openpgp::Result<()> {
3095 /// let p = &StandardPolicy::new();
3096 ///
3097 /// # let (cert, _) =
3098 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3099 /// # .generate()?;
3100 /// for ka in cert.keys().with_policy(p, None) {
3101 /// if ka.for_storage_encryption() {
3102 /// // `ka` is storage-encryption capable.
3103 /// }
3104 /// }
3105 /// # Ok(()) }
3106 /// ```
3107 ///
3108 /// [data at rest]: https://en.wikipedia.org/wiki/Data_at_rest
3109 /// [data in transit]: https://en.wikipedia.org/wiki/Data_in_transit
3110 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3111 pub fn for_storage_encryption(&self) -> bool
3112 {
3113 self.has_any_key_flag(KeyFlags::empty().set_storage_encryption())
3114 }
3115
3116 /// Returns whether the key is transport-encryption capable.
3117 ///
3118 /// OpenPGP distinguishes two types of encryption keys: those for
3119 /// storage ([data at rest]) and those for transport ([data in
3120 /// transit]). Most OpenPGP implementations, however, don't
3121 /// distinguish between them in practice. Instead, when they
3122 /// create a new encryption key, they just set both flags.
3123 /// Likewise, when encrypting a message, it is not typically
3124 /// possible to indicate the type of protection that is needed.
3125 /// Sequoia supports creating keys with only one of these flags
3126 /// set, and makes it easy to select the right type of key when
3127 /// encrypting messages.
3128 ///
3129 /// The key flags are looked up as described in
3130 /// [`ValidKeyAmalgamation::key_flags`].
3131 ///
3132 /// # Examples
3133 ///
3134 /// Finds keys that are transport-encryption capable:
3135 ///
3136 /// ```
3137 /// # use sequoia_openpgp as openpgp;
3138 /// # use openpgp::cert::prelude::*;
3139 /// use openpgp::policy::StandardPolicy;
3140 ///
3141 /// # fn main() -> openpgp::Result<()> {
3142 /// let p = &StandardPolicy::new();
3143 ///
3144 /// # let (cert, _) =
3145 /// # CertBuilder::general_purpose(Some("alice@example.org"))
3146 /// # .generate()?;
3147 /// for ka in cert.keys().with_policy(p, None) {
3148 /// if ka.for_transport_encryption() {
3149 /// // `ka` is transport-encryption capable.
3150 /// }
3151 /// }
3152 /// # Ok(()) }
3153 /// ```
3154 ///
3155 /// [data at rest]: https://en.wikipedia.org/wiki/Data_at_rest
3156 /// [data in transit]: https://en.wikipedia.org/wiki/Data_in_transit
3157 /// [`ValidKeyAmalgamation::key_flags`]: ValidKeyAmalgamation::key_flags()
3158 pub fn for_transport_encryption(&self) -> bool
3159 {
3160 self.has_any_key_flag(KeyFlags::empty().set_transport_encryption())
3161 }
3162
3163 /// Returns how long the key is live.
3164 ///
3165 /// This returns how long the key is live relative to its creation
3166 /// time. Use [`ValidKeyAmalgamation::key_expiration_time`] to
3167 /// get the key's absolute expiry time.
3168 ///
3169 /// This function considers both the binding signature and the
3170 /// direct key signature. Information in the binding signature
3171 /// takes precedence over the direct key signature. See [Section
3172 /// 5.2.3.10 of RFC 9580].
3173 ///
3174 /// # Examples
3175 ///
3176 /// ```
3177 /// use std::time;
3178 /// use std::convert::TryInto;
3179 /// # use sequoia_openpgp as openpgp;
3180 /// # use openpgp::cert::prelude::*;
3181 /// use openpgp::policy::StandardPolicy;
3182 /// use openpgp::types::Timestamp;
3183 ///
3184 /// # fn main() -> openpgp::Result<()> {
3185 /// let p = &StandardPolicy::new();
3186 ///
3187 /// // OpenPGP Timestamps have a one-second resolution. Since we
3188 /// // want to round trip the time, round it down.
3189 /// let now: Timestamp = time::SystemTime::now().try_into()?;
3190 /// let now: time::SystemTime = now.try_into()?;
3191 ///
3192 /// let a_week = time::Duration::from_secs(7 * 24 * 60 * 60);
3193 ///
3194 /// let (cert, _) =
3195 /// CertBuilder::general_purpose(Some("alice@example.org"))
3196 /// .set_creation_time(now)
3197 /// .set_validity_period(a_week)
3198 /// .generate()?;
3199 ///
3200 /// assert_eq!(cert.primary_key().with_policy(p, None)?.key_validity_period(),
3201 /// Some(a_week));
3202 /// # Ok(()) }
3203 /// ```
3204 ///
3205 /// [`ValidKeyAmalgamation::key_expiration_time`]: ValidKeyAmalgamation::key_expiration_time()
3206 /// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
3207 pub fn key_validity_period(&self) -> Option<std::time::Duration> {
3208 self.map(|s| s.key_validity_period())
3209 }
3210
3211 /// Returns the key's expiration time.
3212 ///
3213 /// If this function returns `None`, the key does not expire.
3214 ///
3215 /// This returns the key's expiration time. Use
3216 /// [`ValidKeyAmalgamation::key_validity_period`] to get the
3217 /// duration of the key's lifetime.
3218 ///
3219 /// This function considers both the binding signature and the
3220 /// direct key signature. Information in the binding signature
3221 /// takes precedence over the direct key signature. See [Section
3222 /// 5.2.3.10 of RFC 9580].
3223 ///
3224 /// # Examples
3225 ///
3226 /// ```
3227 /// use std::time;
3228 /// use std::convert::TryInto;
3229 /// # use sequoia_openpgp as openpgp;
3230 /// # use openpgp::cert::prelude::*;
3231 /// use openpgp::policy::StandardPolicy;
3232 /// use openpgp::types::Timestamp;
3233 ///
3234 /// # fn main() -> openpgp::Result<()> {
3235 /// let p = &StandardPolicy::new();
3236 ///
3237 /// // OpenPGP Timestamps have a one-second resolution. Since we
3238 /// // want to round trip the time, round it down.
3239 /// let now: Timestamp = time::SystemTime::now().try_into()?;
3240 /// let now: time::SystemTime = now.try_into()?;
3241 //
3242 /// let a_week = time::Duration::from_secs(7 * 24 * 60 * 60);
3243 /// let a_week_later = now + a_week;
3244 ///
3245 /// let (cert, _) =
3246 /// CertBuilder::general_purpose(Some("alice@example.org"))
3247 /// .set_creation_time(now)
3248 /// .set_validity_period(a_week)
3249 /// .generate()?;
3250 ///
3251 /// assert_eq!(cert.primary_key().with_policy(p, None)?.key_expiration_time(),
3252 /// Some(a_week_later));
3253 /// # Ok(()) }
3254 /// ```
3255 ///
3256 /// [`ValidKeyAmalgamation::key_validity_period`]: ValidKeyAmalgamation::key_validity_period()
3257 /// [Section 5.2.3.10 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.2.3.10
3258 pub fn key_expiration_time(&self) -> Option<time::SystemTime> {
3259 match self.key_validity_period() {
3260 Some(vp) if vp.as_secs() > 0 => Some(self.key().creation_time() + vp),
3261 _ => None,
3262 }
3263 }
3264
3265 // NOTE: If you add a method to ValidKeyAmalgamation that takes
3266 // ownership of self, then don't forget to write a forwarder for
3267 // it for ValidPrimaryKeyAmalgamation.
3268}
3269
3270
3271#[cfg(test)]
3272mod test {
3273 use std::time::Duration;
3274 use std::time::UNIX_EPOCH;
3275
3276 use crate::policy::StandardPolicy as P;
3277 use crate::cert::prelude::*;
3278 use crate::packet::Packet;
3279 use crate::packet::signature::SignatureBuilder;
3280 use crate::types::ReasonForRevocation;
3281 use crate::types::RevocationType;
3282
3283 use super::*;
3284
3285 #[test]
3286 fn expire_subkeys() {
3287 let p = &P::new();
3288
3289 // Timeline:
3290 //
3291 // -1: Key created with no key expiration.
3292 // 0: Setkeys set to expire in 1 year
3293 // 1: Subkeys expire
3294
3295 let now = crate::now();
3296 let a_year = time::Duration::from_secs(365 * 24 * 60 * 60);
3297 let in_a_year = now + a_year;
3298 let in_two_years = now + 2 * a_year;
3299
3300 let (cert, _) = CertBuilder::new()
3301 .set_creation_time(now - a_year)
3302 .add_signing_subkey()
3303 .add_transport_encryption_subkey()
3304 .generate().unwrap();
3305
3306 for ka in cert.keys().with_policy(p, None) {
3307 assert!(ka.alive().is_ok());
3308 }
3309
3310 let mut primary_signer = cert.primary_key().key().clone()
3311 .parts_into_secret().unwrap().into_keypair().unwrap();
3312 let mut signing_subkey_signer = cert.with_policy(p, None).unwrap()
3313 .keys().for_signing().next().unwrap()
3314 .key().clone().parts_into_secret().unwrap()
3315 .into_keypair().unwrap();
3316
3317 // Only expire the subkeys.
3318 let sigs = cert.keys().subkeys().with_policy(p, None)
3319 .flat_map(|ka| {
3320 if ! ka.for_signing() {
3321 ka.set_expiration_time(&mut primary_signer,
3322 None,
3323 Some(in_a_year)).unwrap()
3324 } else {
3325 ka.set_expiration_time(&mut primary_signer,
3326 Some(&mut signing_subkey_signer),
3327 Some(in_a_year)).unwrap()
3328 }
3329 .into_iter()
3330 .map(Into::into)
3331 })
3332 .collect::<Vec<Packet>>();
3333 let cert = cert.insert_packets(sigs).unwrap().0;
3334
3335 for ka in cert.keys().with_policy(p, None) {
3336 assert!(ka.alive().is_ok());
3337 }
3338
3339 // Primary should not be expired two years from now.
3340 assert!(cert.primary_key().with_policy(p, in_two_years).unwrap()
3341 .alive().is_ok());
3342 // But the subkeys should be.
3343 for ka in cert.keys().subkeys().with_policy(p, in_two_years) {
3344 assert!(ka.alive().is_err());
3345 }
3346 }
3347
3348 /// Test that subkeys of expired certificates are also considered
3349 /// expired.
3350 #[test]
3351 fn issue_564() -> Result<()> {
3352 use crate::parse::Parse;
3353 use crate::packet::signature::subpacket::SubpacketTag;
3354 let p = &P::new();
3355 let cert = Cert::from_bytes(crate::tests::key("testy.pgp"))?;
3356 assert!(cert.with_policy(p, None)?.alive().is_err());
3357 let subkey = cert.with_policy(p, None)?.keys().nth(1).unwrap();
3358 assert!(subkey.binding_signature().hashed_area()
3359 .subpacket(SubpacketTag::KeyExpirationTime).is_none());
3360 assert!(subkey.alive().is_err());
3361 Ok(())
3362 }
3363
3364 /// When setting the primary key's validity period, we create a
3365 /// direct key signature. Check that this works even when the
3366 /// original certificate doesn't have a direct key signature.
3367 #[test]
3368 fn set_expiry_on_certificate_without_direct_signature() -> Result<()> {
3369 use crate::policy::StandardPolicy;
3370
3371 let p = &StandardPolicy::new();
3372
3373 let (cert, _) =
3374 CertBuilder::general_purpose(Some("alice@example.org"))
3375 .set_validity_period(None)
3376 .generate()?;
3377
3378 // Remove the direct key signatures.
3379 let cert = Cert::from_packets(
3380 cert.as_tsk().into_packets()
3381 .filter(|p| ! matches!(
3382 p,
3383 Packet::Signature(s) if s.typ() == SignatureType::DirectKey
3384 )))?;
3385
3386 let vc = cert.with_policy(p, None)?;
3387
3388 // Assert that the keys are not expired.
3389 for ka in vc.keys() {
3390 assert!(ka.alive().is_ok());
3391 }
3392
3393 // Make the primary key expire in a week.
3394 let t = crate::now()
3395 + time::Duration::from_secs(7 * 24 * 60 * 60);
3396
3397 let mut signer = vc
3398 .primary_key().key().clone().parts_into_secret()?
3399 .into_keypair()?;
3400 let sigs = vc.primary_key()
3401 .set_expiration_time(&mut signer, Some(t))?;
3402
3403 assert!(sigs.iter().any(|s| {
3404 s.typ() == SignatureType::DirectKey
3405 }));
3406
3407 let cert = cert.insert_packets(sigs)?.0;
3408
3409 // Make sure the primary key *and* all subkeys expire in a
3410 // week: the subkeys inherit the KeyExpirationTime subpacket
3411 // from the direct key signature.
3412 for ka in cert.keys() {
3413 let ka = ka.with_policy(p, None)?;
3414 assert!(ka.alive().is_ok());
3415
3416 let ka = ka.with_policy(p, t + std::time::Duration::new(1, 0))?;
3417 assert!(ka.alive().is_err());
3418 }
3419
3420 Ok(())
3421 }
3422
3423 #[test]
3424 fn key_amalgamation_certifications_by_key() -> Result<()> {
3425 // Alice and Bob certify Carol's certificate. We then check
3426 // that valid_certifications_by_key and
3427 // active_certifications_by_key return them.
3428 let p = &crate::policy::StandardPolicy::new();
3429
3430 // $ date -u -d '2024-01-02 13:00' +%s
3431 let t0 = UNIX_EPOCH + Duration::new(1704200400, 0);
3432 // $ date -u -d '2024-01-02 14:00' +%s
3433 let t1 = UNIX_EPOCH + Duration::new(1704204000, 0);
3434 // $ date -u -d '2024-01-02 15:00' +%s
3435 let t2 = UNIX_EPOCH + Duration::new(1704207600, 0);
3436
3437 let (alice, _) = CertBuilder::new()
3438 .set_creation_time(t0)
3439 .add_userid("<alice@example.example>")
3440 .generate()
3441 .unwrap();
3442 let alice_primary = alice.primary_key().key();
3443
3444 let (bob, _) = CertBuilder::new()
3445 .set_creation_time(t0)
3446 .add_userid("<bob@example.example>")
3447 .generate()
3448 .unwrap();
3449 let bob_primary = bob.primary_key().key();
3450
3451 let carol_userid = "<carol@example.example>";
3452 let (carol, _) = CertBuilder::new()
3453 .set_creation_time(t0)
3454 .add_userid(carol_userid)
3455 .generate()
3456 .unwrap();
3457
3458 let ka = alice.primary_key();
3459 assert_eq!(
3460 ka.valid_certifications_by_key(p, None, alice_primary).count(),
3461 0);
3462 assert_eq!(
3463 ka.active_certifications_by_key(p, None, alice_primary).count(),
3464 0);
3465
3466 // Alice has not certified Bob's User ID.
3467 let ka = bob.primary_key();
3468 assert_eq!(
3469 ka.valid_certifications_by_key(p, None, alice_primary).count(),
3470 0);
3471 assert_eq!(
3472 ka.active_certifications_by_key(p, None, alice_primary).count(),
3473 0);
3474
3475 // Alice has not certified Carol's User ID.
3476 let ka = carol.primary_key();
3477 assert_eq!(
3478 ka.valid_certifications_by_key(p, None, alice_primary).count(),
3479 0);
3480 assert_eq!(
3481 ka.active_certifications_by_key(p, None, alice_primary).count(),
3482 0);
3483
3484
3485 // Have Alice certify Carol's certificate at t1.
3486 let mut alice_signer = alice_primary
3487 .clone()
3488 .parts_into_secret().expect("have unencrypted key material")
3489 .into_keypair().expect("have unencrypted key material");
3490 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3491 .set_signature_creation_time(t1)?
3492 .sign_direct_key(
3493 &mut alice_signer,
3494 carol.primary_key().key())?;
3495 let carol = carol.insert_packets(certification.clone())?.0;
3496
3497 // Check that it is returned.
3498 let ka = carol.primary_key();
3499 assert_eq!(ka.certifications().count(), 1);
3500
3501 assert_eq!(
3502 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3503 0);
3504 assert_eq!(
3505 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3506 0);
3507
3508 assert_eq!(
3509 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3510 1);
3511 assert_eq!(
3512 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3513 1);
3514
3515 assert_eq!(
3516 ka.valid_certifications_by_key(p, t1, bob_primary).count(),
3517 0);
3518 assert_eq!(
3519 ka.active_certifications_by_key(p, t1, bob_primary).count(),
3520 0);
3521
3522
3523 // Have Alice certify Carol's certificate at t1 (again).
3524 // Since both certifications were created at t1, they should
3525 // both be returned.
3526 let mut alice_signer = alice_primary
3527 .clone()
3528 .parts_into_secret().expect("have unencrypted key material")
3529 .into_keypair().expect("have unencrypted key material");
3530 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3531 .set_signature_creation_time(t1)?
3532 .sign_direct_key(
3533 &mut alice_signer,
3534 carol.primary_key().key())?;
3535 let carol = carol.insert_packets(certification.clone())?.0;
3536
3537 // Check that it is returned.
3538 let ka = carol.primary_key();
3539 assert_eq!(ka.certifications().count(), 2);
3540 assert_eq!(
3541 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3542 0);
3543 assert_eq!(
3544 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3545 0);
3546
3547 assert_eq!(
3548 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3549 2);
3550 assert_eq!(
3551 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3552 2);
3553
3554 assert_eq!(
3555 ka.valid_certifications_by_key(p, t2, alice_primary).count(),
3556 2);
3557 assert_eq!(
3558 ka.active_certifications_by_key(p, t2, alice_primary).count(),
3559 2);
3560
3561 assert_eq!(
3562 ka.valid_certifications_by_key(p, t0, bob_primary).count(),
3563 0);
3564 assert_eq!(
3565 ka.active_certifications_by_key(p, t0, bob_primary).count(),
3566 0);
3567
3568
3569 // Have Alice certify Carol's certificate at t2. Now we only
3570 // have one active certification.
3571 let mut alice_signer = alice_primary
3572 .clone()
3573 .parts_into_secret().expect("have unencrypted key material")
3574 .into_keypair().expect("have unencrypted key material");
3575 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3576 .set_signature_creation_time(t2)?
3577 .sign_direct_key(
3578 &mut alice_signer,
3579 carol.primary_key().key())?;
3580 let carol = carol.insert_packets(certification.clone())?.0;
3581
3582 // Check that it is returned.
3583 let ka = carol.primary_key();
3584 assert_eq!(ka.certifications().count(), 3);
3585 assert_eq!(
3586 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3587 0);
3588 assert_eq!(
3589 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3590 0);
3591
3592 assert_eq!(
3593 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3594 2);
3595 assert_eq!(
3596 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3597 2);
3598
3599 assert_eq!(
3600 ka.valid_certifications_by_key(p, t2, alice_primary).count(),
3601 3);
3602 assert_eq!(
3603 ka.active_certifications_by_key(p, t2, alice_primary).count(),
3604 1);
3605
3606 assert_eq!(
3607 ka.valid_certifications_by_key(p, t0, bob_primary).count(),
3608 0);
3609 assert_eq!(
3610 ka.active_certifications_by_key(p, t0, bob_primary).count(),
3611 0);
3612
3613
3614 // Have Bob certify Carol's certificate at t1 and have it expire at t2.
3615 let mut bob_signer = bob.primary_key()
3616 .key()
3617 .clone()
3618 .parts_into_secret().expect("have unencrypted key material")
3619 .into_keypair().expect("have unencrypted key material");
3620 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3621 .set_signature_creation_time(t1)?
3622 .set_signature_validity_period(t2.duration_since(t1)?)?
3623 .sign_direct_key(
3624 &mut bob_signer,
3625 carol.primary_key().key())?;
3626 let carol = carol.insert_packets(certification.clone())?.0;
3627
3628 // Check that it is returned.
3629 let ka = carol.primary_key();
3630 assert_eq!(ka.certifications().count(), 4);
3631
3632 assert_eq!(
3633 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3634 0);
3635 assert_eq!(
3636 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3637 0);
3638
3639 assert_eq!(
3640 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3641 2);
3642 assert_eq!(
3643 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3644 2);
3645
3646 assert_eq!(
3647 ka.valid_certifications_by_key(p, t2, alice_primary).count(),
3648 3);
3649 assert_eq!(
3650 ka.active_certifications_by_key(p, t2, alice_primary).count(),
3651 1);
3652
3653 assert_eq!(
3654 ka.valid_certifications_by_key(p, t0, bob_primary).count(),
3655 0);
3656 assert_eq!(
3657 ka.active_certifications_by_key(p, t0, bob_primary).count(),
3658 0);
3659
3660 assert_eq!(
3661 ka.valid_certifications_by_key(p, t1, bob_primary).count(),
3662 1);
3663 assert_eq!(
3664 ka.active_certifications_by_key(p, t1, bob_primary).count(),
3665 1);
3666
3667 // It expired.
3668 assert_eq!(
3669 ka.valid_certifications_by_key(p, t2, bob_primary).count(),
3670 0);
3671 assert_eq!(
3672 ka.active_certifications_by_key(p, t2, bob_primary).count(),
3673 0);
3674
3675
3676 // Have Bob certify Carol's certificate at t1 again. This
3677 // time don't have it expire.
3678 let mut bob_signer = bob.primary_key()
3679 .key()
3680 .clone()
3681 .parts_into_secret().expect("have unencrypted key material")
3682 .into_keypair().expect("have unencrypted key material");
3683 let certification = SignatureBuilder::new(SignatureType::DirectKey)
3684 .set_signature_creation_time(t1)?
3685 .sign_direct_key(
3686 &mut bob_signer,
3687 carol.primary_key().key())?;
3688 let carol = carol.insert_packets(certification.clone())?.0;
3689
3690 // Check that it is returned.
3691 let ka = carol.primary_key();
3692 assert_eq!(ka.certifications().count(), 5);
3693 assert_eq!(
3694 ka.valid_certifications_by_key(p, t0, alice_primary).count(),
3695 0);
3696 assert_eq!(
3697 ka.active_certifications_by_key(p, t0, alice_primary).count(),
3698 0);
3699
3700 assert_eq!(
3701 ka.valid_certifications_by_key(p, t1, alice_primary).count(),
3702 2);
3703 assert_eq!(
3704 ka.active_certifications_by_key(p, t1, alice_primary).count(),
3705 2);
3706
3707 assert_eq!(
3708 ka.valid_certifications_by_key(p, t2, alice_primary).count(),
3709 3);
3710 assert_eq!(
3711 ka.active_certifications_by_key(p, t2, alice_primary).count(),
3712 1);
3713
3714 assert_eq!(
3715 ka.valid_certifications_by_key(p, t0, bob_primary).count(),
3716 0);
3717 assert_eq!(
3718 ka.active_certifications_by_key(p, t0, bob_primary).count(),
3719 0);
3720
3721 assert_eq!(
3722 ka.valid_certifications_by_key(p, t1, bob_primary).count(),
3723 2);
3724 assert_eq!(
3725 ka.active_certifications_by_key(p, t1, bob_primary).count(),
3726 2);
3727
3728 // One of the certifications expired.
3729 assert_eq!(
3730 ka.valid_certifications_by_key(p, t2, bob_primary).count(),
3731 1);
3732 assert_eq!(
3733 ka.active_certifications_by_key(p, t2, bob_primary).count(),
3734 1);
3735
3736 Ok(())
3737 }
3738
3739 fn key_amalgamation_valid_third_party_revocations_by_key(
3740 reason: ReasonForRevocation)
3741 -> Result<()>
3742 {
3743 // Hard revocations are returned independent of the reference
3744 // time and independent of their expiration. They are always
3745 // live.
3746 let soft = reason.revocation_type() == RevocationType::Soft;
3747
3748 // Alice and Bob revoke Carol's certificate. We then check
3749 // that valid_third_party_revocations_by_key returns them.
3750 let p = &crate::policy::StandardPolicy::new();
3751
3752 // $ date -u -d '2024-01-02 13:00' +%s
3753 let t0 = UNIX_EPOCH + Duration::new(1704200400, 0);
3754 // $ date -u -d '2024-01-02 14:00' +%s
3755 let t1 = UNIX_EPOCH + Duration::new(1704204000, 0);
3756 // $ date -u -d '2024-01-02 15:00' +%s
3757 let t2 = UNIX_EPOCH + Duration::new(1704207600, 0);
3758
3759 let (alice, _) = CertBuilder::new()
3760 .set_creation_time(t0)
3761 .add_userid("<alice@example.example>")
3762 .generate()
3763 .unwrap();
3764 let alice_primary = alice.primary_key().key();
3765
3766 let (bob, _) = CertBuilder::new()
3767 .set_creation_time(t0)
3768 .add_userid("<bob@example.example>")
3769 .generate()
3770 .unwrap();
3771 let bob_primary = bob.primary_key().key();
3772
3773 let carol_userid = "<carol@example.example>";
3774 let (carol, _) = CertBuilder::new()
3775 .set_creation_time(t0)
3776 .add_userid(carol_userid)
3777 .generate()
3778 .unwrap();
3779
3780 let ka = alice.primary_key();
3781 assert_eq!(
3782 ka.valid_third_party_revocations_by_key(p, None, alice_primary).count(),
3783 0);
3784
3785 // Alice has not revoked Bob's certificate.
3786 let ka = bob.primary_key();
3787 assert_eq!(
3788 ka.valid_third_party_revocations_by_key(p, None, alice_primary).count(),
3789 0);
3790
3791 // Alice has not revoked Carol's certificate.
3792 let ka = carol.primary_key();
3793 assert_eq!(
3794 ka.valid_third_party_revocations_by_key(p, None, alice_primary).count(),
3795 0);
3796
3797
3798 // Have Alice revoke Carol's revoke at t1.
3799 let mut alice_signer = alice_primary
3800 .clone()
3801 .parts_into_secret().expect("have unencrypted key material")
3802 .into_keypair().expect("have unencrypted key material");
3803 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3804 .set_signature_creation_time(t1)?
3805 .set_reason_for_revocation(
3806 reason, b"")?
3807 .sign_direct_key(
3808 &mut alice_signer,
3809 carol.primary_key().key())?;
3810 let carol = carol.insert_packets(rev)?.0;
3811
3812 // Check that it is returned.
3813 let ka = carol.primary_key();
3814 assert_eq!(ka.other_revocations().count(), 1);
3815
3816 assert_eq!(
3817 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3818 if soft { 0 } else { 1 });
3819 assert_eq!(
3820 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3821 1);
3822 assert_eq!(
3823 ka.valid_third_party_revocations_by_key(p, t1, bob_primary).count(),
3824 0);
3825
3826
3827 // Have Alice revoke Carol's certificate at t1 (again).
3828 let mut alice_signer = alice_primary
3829 .clone()
3830 .parts_into_secret().expect("have unencrypted key material")
3831 .into_keypair().expect("have unencrypted key material");
3832 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3833 .set_signature_creation_time(t1)?
3834 .set_reason_for_revocation(reason, b"")?
3835 .sign_direct_key(
3836 &mut alice_signer,
3837 carol.primary_key().key())?;
3838 let carol = carol.insert_packets(rev)?.0;
3839
3840 // Check that it is returned.
3841 let ka = carol.primary_key();
3842 assert_eq!(ka.other_revocations().count(), 2);
3843 assert_eq!(
3844 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3845 if soft { 0 } else { 2 });
3846 assert_eq!(
3847 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3848 2);
3849 assert_eq!(
3850 ka.valid_third_party_revocations_by_key(p, t2, alice_primary).count(),
3851 2);
3852 assert_eq!(
3853 ka.valid_third_party_revocations_by_key(p, t0, bob_primary).count(),
3854 0);
3855
3856
3857 // Have Alice revoke Carol's certificate at t2.
3858 let mut alice_signer = alice_primary
3859 .clone()
3860 .parts_into_secret().expect("have unencrypted key material")
3861 .into_keypair().expect("have unencrypted key material");
3862 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3863 .set_signature_creation_time(t2)?
3864 .set_reason_for_revocation(reason, b"")?
3865 .sign_direct_key(
3866 &mut alice_signer,
3867 carol.primary_key().key())?;
3868 let carol = carol.insert_packets(rev)?.0;
3869
3870 // Check that it is returned.
3871 let ka = carol.primary_key();
3872 assert_eq!(ka.other_revocations().count(), 3);
3873 assert_eq!(
3874 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3875 if soft { 0 } else { 3 });
3876 assert_eq!(
3877 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3878 if soft { 2 } else { 3 });
3879 assert_eq!(
3880 ka.valid_third_party_revocations_by_key(p, t2, alice_primary).count(),
3881 3);
3882 assert_eq!(
3883 ka.valid_third_party_revocations_by_key(p, t0, bob_primary).count(),
3884 0);
3885
3886
3887 // Have Bob revoke Carol's certificate at t1 and have it expire at t2.
3888 let mut bob_signer = bob.primary_key()
3889 .key()
3890 .clone()
3891 .parts_into_secret().expect("have unencrypted key material")
3892 .into_keypair().expect("have unencrypted key material");
3893 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3894 .set_signature_creation_time(t1)?
3895 .set_signature_validity_period(t2.duration_since(t1)?)?
3896 .set_reason_for_revocation(reason, b"")?
3897 .sign_direct_key(
3898 &mut bob_signer,
3899 carol.primary_key().key())?;
3900 let carol = carol.insert_packets(rev)?.0;
3901
3902 // Check that it is returned.
3903 let ka = carol.primary_key();
3904 assert_eq!(ka.other_revocations().count(), 4);
3905
3906 assert_eq!(
3907 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3908 if soft { 0 } else { 3 });
3909 assert_eq!(
3910 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3911 if soft { 2 } else { 3 });
3912 assert_eq!(
3913 ka.valid_third_party_revocations_by_key(p, t2, alice_primary).count(),
3914 3);
3915 assert_eq!(
3916 ka.valid_third_party_revocations_by_key(p, t0, bob_primary).count(),
3917 if soft { 0 } else { 1 });
3918 assert_eq!(
3919 ka.valid_third_party_revocations_by_key(p, t1, bob_primary).count(),
3920 1);
3921 // It expired.
3922 assert_eq!(
3923 ka.valid_third_party_revocations_by_key(p, t2, bob_primary).count(),
3924 if soft { 0 } else { 1 });
3925
3926
3927 // Have Bob revoke Carol's certificate at t1 again. This
3928 // time don't have it expire.
3929 let mut bob_signer = bob.primary_key()
3930 .key()
3931 .clone()
3932 .parts_into_secret().expect("have unencrypted key material")
3933 .into_keypair().expect("have unencrypted key material");
3934 let rev = SignatureBuilder::new(SignatureType::KeyRevocation)
3935 .set_signature_creation_time(t1)?
3936 .set_reason_for_revocation(reason, b"")?
3937 .sign_direct_key(
3938 &mut bob_signer,
3939 carol.primary_key().key())?;
3940 let carol = carol.insert_packets(rev)?.0;
3941
3942 // Check that it is returned.
3943 let ka = carol.primary_key();
3944 assert_eq!(
3945 ka.other_revocations().count(), 5);
3946 assert_eq!(
3947 ka.valid_third_party_revocations_by_key(p, t0, alice_primary).count(),
3948 if soft { 0 } else { 3 });
3949 assert_eq!(
3950 ka.valid_third_party_revocations_by_key(p, t1, alice_primary).count(),
3951 if soft { 2 } else { 3 });
3952 assert_eq!(
3953 ka.valid_third_party_revocations_by_key(p, t2, alice_primary).count(),
3954 3);
3955 assert_eq!(
3956 ka.valid_third_party_revocations_by_key(p, t0, bob_primary).count(),
3957 if soft { 0 } else { 2 });
3958 assert_eq!(
3959 ka.valid_third_party_revocations_by_key(p, t1, bob_primary).count(),
3960 2);
3961 // One of the revocations expired.
3962 assert_eq!(
3963 ka.valid_third_party_revocations_by_key(p, t2, bob_primary).count(),
3964 if soft { 1 } else { 2 });
3965
3966 Ok(())
3967 }
3968
3969 #[test]
3970 fn key_amalgamation_valid_third_party_revocations_by_key_soft()
3971 -> Result<()>
3972 {
3973 key_amalgamation_valid_third_party_revocations_by_key(
3974 ReasonForRevocation::KeyRetired)
3975 }
3976
3977 #[test]
3978 fn key_amalgamation_valid_third_party_revocations_by_key_hard()
3979 -> Result<()>
3980 {
3981 key_amalgamation_valid_third_party_revocations_by_key(
3982 ReasonForRevocation::KeyCompromised)
3983 }
3984}