Skip to main content

sequoia_openpgp/packet/
key.rs

1//! Key-related functionality.
2//!
3//! # Data Types
4//!
5//! The main data type is the [`Key`] enum.  This enum abstracts away
6//! the differences between the key formats (the current [version 6],
7//! the deprecated [version 4], and the legacy [version 3]).
8//! Nevertheless, some functionality remains format specific.  For
9//! instance, the `Key` enum doesn't provide a mechanism to generate
10//! keys.  This functionality depends on the format.
11//!
12//! This version of Sequoia only supports version 6 and version 4 keys
13//! ([`Key6`], and [`Key4`]).  However, future versions may include
14//! limited support for version 3 keys to allow working with archived
15//! messages.
16//!
17//! OpenPGP specifies four different types of keys: [public keys],
18//! [secret keys], [public subkeys], and [secret subkeys].  These are
19//! all represented by the `Key` enum and the `Key4` struct using
20//! marker types.  We use marker types rather than an enum, to better
21//! exploit the type checking.  For instance, type-specific methods
22//! like [`Key4::secret`] are only exposed for those types that
23//! actually support them.  See the documentation for [`Key`] for an
24//! explanation of how the markers work.
25//!
26//! The [`SecretKeyMaterial`] data type allows working with secret key
27//! material directly.  This enum has two variants: [`Unencrypted`],
28//! and [`Encrypted`].  It is not normally necessary to use this data
29//! structure directly.  The primary functionality that is of interest
30//! to most users is decrypting secret key material.  This is usually
31//! more conveniently done using [`Key::decrypt_secret`].
32//!
33//! [`Key`]: super::Key
34//! [version 3]: https://tools.ietf.org/html/rfc1991#section-6.6
35//! [version 4]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.2
36//! [version 6]: https://www.rfc-editor.org/rfc/rfc9580.html#name-version-6-public-keys
37//! [public keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.1
38//! [secret keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.3
39//! [public subkeys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.2
40//! [secret subkeys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.5
41//! [`Key::decrypt_secret`]: super::Key::decrypt_secret()
42//!
43//! # Key Creation
44//!
45//! Use [`Key6::generate_x25519`], [`Key6::generate_ed25519`],
46//! [`Key6::generate_x448`], [`Key6::generate_ed448`],
47//! [`Key6::generate_ecc`], or [`Key6::generate_rsa`] to create a new
48//! key.
49//!
50//! Existing key material can be turned into an OpenPGP key using
51//! [`Key6::import_public_x25519`], [`Key6::import_public_ed25519`],
52//! [`Key6::import_public_x448`], [`Key6::import_public_ed448`],
53//! [`Key6::import_public_rsa`], [`Key6::import_secret_x25519`],
54//! [`Key6::import_secret_ed25519`], [`Key6::import_secret_x448`],
55//! [`Key6::import_secret_ed448`], and [`Key6::import_secret_rsa`].
56//!
57//! Whether you create a new key or import existing key material, you
58//! still need to create a binding signature, and, for signing keys, a
59//! back signature for the key to be usable.
60//!
61//! # In-Memory Protection of Secret Key Material
62//!
63//! Whether the secret key material is protected on disk or not,
64//! Sequoia encrypts unencrypted secret key material ([`Unencrypted`])
65//! while it is memory.  This helps protect against [heartbleed]-style
66//! attacks where a buffer over-read allows an attacker to read from
67//! the process's address space.  This protection is less important
68//! for Rust programs, which are memory safe.  However, it is
69//! essential when Sequoia is used via its FFI.
70//!
71//! See [`crypto::mem::Encrypted`] for details.
72//!
73//! [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed
74//! [`crypto::mem::Encrypted`]: super::super::crypto::mem::Encrypted
75
76use std::fmt;
77use std::convert::TryInto;
78use std::hash::Hasher;
79
80#[cfg(test)]
81use quickcheck::{Arbitrary, Gen};
82
83use crate::Error;
84use crate::cert::prelude::*;
85use crate::crypto::{self, mem, mpi, KeyPair};
86use crate::packet::prelude::*;
87use crate::policy::HashAlgoSecurity;
88use crate::PublicKeyAlgorithm;
89use crate::seal;
90use crate::SymmetricAlgorithm;
91use crate::HashAlgorithm;
92use crate::types::{
93    AEADAlgorithm,
94    Curve,
95};
96use crate::crypto::S2K;
97use crate::Result;
98use crate::crypto::Password;
99use crate::crypto::SessionKey;
100
101mod conversions;
102mod v6;
103pub use v6::Key6;
104mod v4;
105pub use v4::Key4;
106
107/// Holds a public key, public subkey, private key or private subkey packet.
108///
109/// The different `Key` packets are described in [Section 5.5 of RFC 9580].
110///
111///   [Section 5.5 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5
112///
113/// # Key Variants
114///
115/// There are four different types of keys in OpenPGP: [public keys],
116/// [secret keys], [public subkeys], and [secret subkeys].  Although
117/// the semantics of each type of key are slightly different, the
118/// underlying representation is identical (even a public key and a
119/// secret key are the same: the public key variant just contains 0
120/// bits of secret key material).
121///
122/// In Sequoia, we use a single type, `Key`, for all four variants.
123/// To improve type safety, we use marker traits rather than an `enum`
124/// to distinguish them.  Specifically, we `Key` is generic over two
125/// type variables, `P` and `R`.
126///
127/// `P` and `R` take marker traits, which describe how any secret key
128/// material should be treated, and the key's role (primary or
129/// subordinate).  The markers also determine the `Key`'s behavior and
130/// the exposed functionality.  `P` can be [`key::PublicParts`],
131/// [`key::SecretParts`], or [`key::UnspecifiedParts`].  And, `R` can
132/// be [`key::PrimaryRole`], [`key::SubordinateRole`], or
133/// [`key::UnspecifiedRole`].
134///
135/// If `P` is `key::PublicParts`, any secret key material that is
136/// present is ignored.  For instance, when serializing a key with
137/// this marker, any secret key material will be skipped.  This is
138/// illutrated in the following example.  If `P` is
139/// `key::SecretParts`, then the key definitely contains secret key
140/// material (although it is not guaranteed that the secret key
141/// material is valid), and methods that require secret key material
142/// are available.
143///
144/// Unlike `P`, `R` does not say anything about the `Key`'s content.
145/// But, a key's role does influence's the key's semantics.  For
146/// instance, some of a primary key's meta-data is located on the
147/// primary User ID whereas a subordinate key's meta-data is located
148/// on its binding signature.
149///
150/// The unspecified variants [`key::UnspecifiedParts`] and
151/// [`key::UnspecifiedRole`] exist to simplify type erasure, which is
152/// needed to mix different types of keys in a single collection.  For
153/// instance, [`Cert::keys`] returns an iterator over the keys in a
154/// certificate.  Since the keys have different roles (a primary key
155/// and zero or more subkeys), but the `Iterator` has to be over a
156/// single, fixed type, the returned keys use the
157/// `key::UnspecifiedRole` marker.
158///
159/// [public keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.1
160/// [secret keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.3
161/// [public subkeys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.2
162/// [secret subkeys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.1.5
163/// [`Cert::keys`]: crate::Cert::keys
164///
165/// ## Examples
166///
167/// Serializing a public key with secret key material drops the secret
168/// key material:
169///
170/// ```
171/// use sequoia_openpgp as openpgp;
172/// use openpgp::cert::prelude::*;
173/// use openpgp::packet::prelude::*;
174/// use sequoia_openpgp::parse::Parse;
175/// use openpgp::serialize::Serialize;
176///
177/// # fn main() -> openpgp::Result<()> {
178/// // Generate a new certificate.  It has secret key material.
179/// let (cert, _) = CertBuilder::new()
180///     .generate()?;
181///
182/// let pk = cert.primary_key().key();
183/// assert!(pk.has_secret());
184///
185/// // Serializing a `Key<key::PublicParts, _>` drops the secret key
186/// // material.
187/// let mut bytes = Vec::new();
188/// Packet::from(pk.clone()).serialize(&mut bytes);
189/// let p : Packet = Packet::from_bytes(&bytes)?;
190///
191/// if let Packet::PublicKey(key) = p {
192///     assert!(! key.has_secret());
193/// } else {
194///     unreachable!();
195/// }
196/// # Ok(())
197/// # }
198/// ```
199///
200/// # Conversions
201///
202/// Sometimes it is necessary to change a marker.  For instance, to
203/// help prevent a user from inadvertently leaking secret key
204/// material, the [`Cert`] data structure never returns keys with the
205/// [`key::SecretParts`] marker.  This means, to use any secret key
206/// material, e.g., when creating a [`Signer`], the user needs to
207/// explicitly opt-in by changing the marker using
208/// [`Key::parts_into_secret`] or [`Key::parts_as_secret`].
209///
210/// For `P`, the conversion functions are: [`Key::parts_into_public`],
211/// [`Key::parts_as_public`], [`Key::parts_into_secret`],
212/// [`Key::parts_as_secret`], [`Key::parts_into_unspecified`], and
213/// [`Key::parts_as_unspecified`].  With the exception of converting
214/// `P` to `key::SecretParts`, these functions are infallible.
215/// Converting `P` to `key::SecretParts` may fail if the key doesn't
216/// have any secret key material.  (Note: although the secret key
217/// material is required, it is not checked for validity.)
218///
219/// For `R`, the conversion functions are [`Key::role_into_primary`],
220/// [`Key::role_as_primary`], [`Key::role_into_subordinate`],
221/// [`Key::role_as_subordinate`], [`Key::role_into_unspecified`], and
222/// [`Key::role_as_unspecified`].
223///
224/// It is also possible to use `From`.
225///
226/// [`Signer`]: crate::crypto::Signer
227/// [`Key::parts_as_secret`]: Key::parts_as_secret()
228/// [`Key::parts_into_public`]: Key::parts_into_public()
229/// [`Key::parts_as_public`]: Key::parts_as_public()
230/// [`Key::parts_into_secret`]: Key::parts_into_secret()
231/// [`Key::parts_as_secret`]: Key::parts_as_secret()
232/// [`Key::parts_into_unspecified`]: Key::parts_into_unspecified()
233/// [`Key::parts_as_unspecified`]: Key::parts_as_unspecified()
234/// [`Key::role_into_primary`]: Key::role_into_primary()
235/// [`Key::role_as_primary`]: Key::role_as_primary()
236/// [`Key::role_into_subordinate`]: Key::role_into_subordinate()
237/// [`Key::role_as_subordinate`]: Key::role_as_subordinate()
238/// [`Key::role_into_unspecified`]: Key::role_into_unspecified()
239/// [`Key::role_as_unspecified`]: Key::role_as_unspecified()
240///
241/// ## Examples
242///
243/// Changing a marker:
244///
245/// ```
246/// use sequoia_openpgp as openpgp;
247/// use openpgp::cert::prelude::*;
248/// use openpgp::packet::prelude::*;
249///
250/// # fn main() -> openpgp::Result<()> {
251/// // Generate a new certificate.  It has secret key material.
252/// let (cert, _) = CertBuilder::new()
253///     .generate()?;
254///
255/// let pk: &Key<key::PublicParts, key::PrimaryRole>
256///     = cert.primary_key().key();
257/// // `has_secret`s is one of the few methods that ignores the
258/// // parts type.
259/// assert!(pk.has_secret());
260///
261/// // Treat it like a secret key.  This only works if `pk` really
262/// // has secret key material (which it does in this case, see above).
263/// let sk = pk.parts_as_secret()?;
264/// assert!(sk.has_secret());
265///
266/// // And back.
267/// let pk = sk.parts_as_public();
268/// // Yes, the secret key material is still there.
269/// assert!(pk.has_secret());
270/// # Ok(())
271/// # }
272/// ```
273///
274/// The [`Cert`] data structure only returns public keys.  To work
275/// with any secret key material, the `Key` first needs to be
276/// converted to a secret key.  This is necessary, for instance, when
277/// creating a [`Signer`]:
278///
279/// [`Cert`]: crate::Cert
280///
281/// ```rust
282/// use std::time;
283/// use sequoia_openpgp as openpgp;
284/// # use openpgp::Result;
285/// use openpgp::cert::prelude::*;
286/// use openpgp::crypto::KeyPair;
287/// use openpgp::policy::StandardPolicy;
288///
289/// # fn main() -> Result<()> {
290/// let p = &StandardPolicy::new();
291///
292/// let the_past = time::SystemTime::now() - time::Duration::from_secs(1);
293/// let (cert, _) = CertBuilder::new()
294///     .set_creation_time(the_past)
295///     .generate()?;
296///
297/// // Set the certificate to expire now.  To do this, we need
298/// // to create a new self-signature, and sign it using a
299/// // certification-capable key.  The primary key is always
300/// // certification capable.
301/// let mut keypair = cert.primary_key()
302///     .key().clone().parts_into_secret()?.into_keypair()?;
303/// let sigs = cert.set_expiration_time(p, None, &mut keypair,
304///                                     Some(time::SystemTime::now()))?;
305///
306/// let cert = cert.insert_packets(sigs)?.0;
307/// // It's expired now.
308/// assert!(cert.with_policy(p, None)?.alive().is_err());
309/// # Ok(())
310/// # }
311/// ```
312///
313/// # Key Generation
314///
315/// `Key` is a wrapper around [the different key formats].
316/// (Currently, Sequoia only supports version 6 and version 4 keys,
317/// however, future versions may add limited support for version 3
318/// keys to facilitate working with achieved messages.)  As such, it
319/// doesn't provide a mechanism to generate keys or import existing
320/// key material.  Instead, use the format-specific functions (e.g.,
321/// [`Key6::generate_ecc`]) and then convert the result into a `Key`
322/// packet, as the following example demonstrates.
323///
324/// [the different key formats]: https://www.rfc-editor.org/rfc/rfc9580.html#name-public-key-packet-formats
325///
326/// ## Examples
327///
328/// ```
329/// use sequoia_openpgp as openpgp;
330/// use openpgp::packet::prelude::*;
331/// use openpgp::types::Curve;
332///
333/// # fn main() -> openpgp::Result<()> {
334/// let key: Key<key::SecretParts, key::PrimaryRole>
335///     = Key::from(Key6::generate_ecc(true, Curve::Ed25519)?);
336/// # Ok(())
337/// # }
338/// ```
339///
340/// # Password Protection
341///
342/// OpenPGP provides a mechanism to [password protect keys].  If a key
343/// is password protected, you need to decrypt the password using
344/// [`Key::decrypt_secret`] before using its secret key material
345/// (e.g., to decrypt a message, or to generate a signature).
346///
347/// [password protect keys]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7
348/// [`Key::decrypt_secret`]: Key::decrypt_secret()
349///
350/// # A note on equality
351///
352/// The implementation of `Eq` for `Key` compares the serialized form
353/// of `Key`s.  Comparing or serializing values of `Key<PublicParts,
354/// _>` ignore secret key material, whereas the secret key material is
355/// considered and serialized for `Key<SecretParts, _>`, and for
356/// `Key<UnspecifiedParts, _>` if present.  To explicitly exclude the
357/// secret key material from the comparison, use [`Key::public_cmp`]
358/// or [`Key::public_eq`].
359///
360/// When merging in secret key material from untrusted sources, you
361/// need to be very careful: secret key material is not
362/// cryptographically protected by the key's self signature.  Thus, an
363/// attacker can provide a valid key with a valid self signature, but
364/// invalid secret key material.  If naively merged, this could
365/// overwrite valid secret key material, and thereby render the key
366/// useless.  Unfortunately, the only way to find out that the secret
367/// key material is bad is to actually try using it.  But, because the
368/// secret key material is usually encrypted, this can't always be
369/// done automatically.
370///
371/// [`Key::public_cmp`]: Key::public_cmp()
372/// [`Key::public_eq`]: Key::public_eq()
373///
374/// Compare:
375///
376/// ```
377/// use sequoia_openpgp as openpgp;
378/// use openpgp::cert::prelude::*;
379/// use openpgp::packet::prelude::*;
380/// use openpgp::packet::key::*;
381///
382/// # fn main() -> openpgp::Result<()> {
383/// // Generate a new certificate.  It has secret key material.
384/// let (cert, _) = CertBuilder::new()
385///     .generate()?;
386///
387/// let sk: &Key<PublicParts, _> = cert.primary_key().key();
388/// assert!(sk.has_secret());
389///
390/// // Strip the secret key material.
391/// let cert = cert.clone().strip_secret_key_material();
392/// let pk: &Key<PublicParts, _> = cert.primary_key().key();
393/// assert!(! pk.has_secret());
394///
395/// // Eq on Key<PublicParts, _> compares only the public bits, so it
396/// // considers pk and sk to be equal.
397/// assert_eq!(pk, sk);
398///
399/// // Convert to Key<UnspecifiedParts, _>.
400/// let sk: &Key<UnspecifiedParts, _> = sk.parts_as_unspecified();
401/// let pk: &Key<UnspecifiedParts, _> = pk.parts_as_unspecified();
402///
403/// // Eq on Key<UnspecifiedParts, _> compares both the public and the
404/// // secret bits, so it considers pk and sk to be different.
405/// assert_ne!(pk, sk);
406///
407/// // In any case, Key::public_eq only compares the public bits,
408/// // so it considers them to be equal.
409/// assert!(Key::public_eq(pk, sk));
410/// # Ok(())
411/// # }
412/// ```
413#[non_exhaustive]
414#[derive(PartialEq, Eq, Hash, Debug)]
415pub enum Key<P: key::KeyParts, R: key::KeyRole> {
416    /// A version 4 `Key` packet.
417    V4(Key4<P, R>),
418
419    /// A version 6 `Key` packet.
420    V6(Key6<P, R>),
421}
422assert_send_and_sync!(Key<P, R> where P: key::KeyParts, R: key::KeyRole);
423
424// derive(Clone) doesn't work as expected with generic type parameters
425// that don't implement clone: it adds a trait bound on Clone to P and
426// R in the Clone implementation.  Happily, we don't need P or R to
427// implement Clone: they are just marker traits, which we can clone
428// manually.
429//
430// See: https://github.com/rust-lang/rust/issues/26925
431impl<P, R> Clone for Key<P, R>
432    where P: key::KeyParts, R: key::KeyRole
433{
434    fn clone(&self) -> Self {
435        match self {
436            Key::V4(key) => Key::V4(key.clone()),
437            Key::V6(key) => Key::V6(key.clone()),
438        }
439    }
440}
441
442impl<P: key::KeyParts, R: key::KeyRole> fmt::Display for Key<P, R> {
443    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
444        match self {
445            Key::V4(k) => k.fmt(f),
446            Key::V6(k) => k.fmt(f),
447        }
448    }
449}
450
451impl From<Key<key::PublicParts, key::PrimaryRole>> for Packet {
452    /// Convert the `Key` struct to a `Packet`.
453    fn from(k: Key<key::PublicParts, key::PrimaryRole>) -> Self {
454        Packet::PublicKey(k)
455    }
456}
457
458impl From<Key<key::PublicParts, key::SubordinateRole>> for Packet {
459    /// Convert the `Key` struct to a `Packet`.
460    fn from(k: Key<key::PublicParts, key::SubordinateRole>) -> Self {
461        Packet::PublicSubkey(k)
462    }
463}
464
465impl From<Key<key::SecretParts, key::PrimaryRole>> for Packet {
466    /// Convert the `Key` struct to a `Packet`.
467    fn from(k: Key<key::SecretParts, key::PrimaryRole>) -> Self {
468        Packet::SecretKey(k)
469    }
470}
471
472impl From<Key<key::SecretParts, key::SubordinateRole>> for Packet {
473    /// Convert the `Key` struct to a `Packet`.
474    fn from(k: Key<key::SecretParts, key::SubordinateRole>) -> Self {
475        Packet::SecretSubkey(k)
476    }
477}
478
479impl<R: key::KeyRole> Key<key::SecretParts, R> {
480    /// Gets the `Key`'s `SecretKeyMaterial`.
481    pub fn secret(&self) -> &SecretKeyMaterial {
482        match self {
483            Key::V4(k) => k.secret(),
484            Key::V6(k) => k.secret(),
485        }
486    }
487
488    /// Gets a mutable reference to the `Key`'s `SecretKeyMaterial`.
489    pub fn secret_mut(&mut self) -> &mut SecretKeyMaterial {
490        match self {
491            Key::V4(k) => k.secret_mut(),
492            Key::V6(k) => k.secret_mut(),
493        }
494    }
495
496    /// Creates a new key pair from a `Key` with an unencrypted
497    /// secret key.
498    ///
499    /// If the `Key` is password protected, you first need to decrypt
500    /// it using [`Key::decrypt_secret`].
501    ///
502    /// [`Key::decrypt_secret`]: Key::decrypt_secret()
503    ///
504    /// # Errors
505    ///
506    /// Fails if the secret key is encrypted.
507    ///
508    /// # Examples
509    ///
510    /// Revoke a certificate by signing a new revocation certificate:
511    ///
512    /// ```rust
513    /// use std::time;
514    /// use sequoia_openpgp as openpgp;
515    /// # use openpgp::Result;
516    /// use openpgp::cert::prelude::*;
517    /// use openpgp::crypto::KeyPair;
518    /// use openpgp::types::ReasonForRevocation;
519    ///
520    /// # fn main() -> Result<()> {
521    /// // Generate a certificate.
522    /// let (cert, _) =
523    ///     CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
524    ///         .generate()?;
525    ///
526    /// // Use the secret key material to sign a revocation certificate.
527    /// let mut keypair = cert.primary_key()
528    ///     .key().clone().parts_into_secret()?
529    ///     .into_keypair()?;
530    /// let rev = cert.revoke(&mut keypair,
531    ///                       ReasonForRevocation::KeyCompromised,
532    ///                       b"It was the maid :/")?;
533    /// # Ok(())
534    /// # }
535    /// ```
536    pub fn into_keypair(self) -> Result<KeyPair> {
537        match self {
538            Key::V4(k) => k.into_keypair(),
539            Key::V6(k) => k.into_keypair(),
540        }
541    }
542
543    /// Decrypts the secret key material.
544    ///
545    /// In OpenPGP, secret key material can be [protected with a
546    /// password].  The password is usually hardened using a [KDF].
547    ///
548    /// [protected with a password]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.3
549    /// [KDF]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7
550    ///
551    /// This function takes ownership of the `Key`, decrypts the
552    /// secret key material using the password, and returns a new key
553    /// whose secret key material is not password protected.
554    ///
555    /// If the secret key material is not password protected or if the
556    /// password is wrong, this function returns an error.
557    ///
558    /// # Examples
559    ///
560    /// Sign a new revocation certificate using a password-protected
561    /// key:
562    ///
563    /// ```rust
564    /// use sequoia_openpgp as openpgp;
565    /// # use openpgp::Result;
566    /// use openpgp::cert::prelude::*;
567    /// use openpgp::types::ReasonForRevocation;
568    ///
569    /// # fn main() -> Result<()> {
570    /// // Generate a certificate whose secret key material is
571    /// // password protected.
572    /// let (cert, _) =
573    ///     CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
574    ///         .set_password(Some("1234".into()))
575    ///         .generate()?;
576    ///
577    /// // Use the secret key material to sign a revocation certificate.
578    /// let key = cert.primary_key().key().clone().parts_into_secret()?;
579    ///
580    /// // We can't turn it into a keypair without decrypting it.
581    /// assert!(key.clone().into_keypair().is_err());
582    ///
583    /// // And, we need to use the right password.
584    /// assert!(key.clone()
585    ///     .decrypt_secret(&"correct horse battery staple".into())
586    ///     .is_err());
587    ///
588    /// // Let's do it right:
589    /// let mut keypair = key.decrypt_secret(&"1234".into())?.into_keypair()?;
590    /// let rev = cert.revoke(&mut keypair,
591    ///                       ReasonForRevocation::KeyCompromised,
592    ///                       b"It was the maid :/")?;
593    /// # Ok(())
594    /// # }
595    /// ```
596    pub fn decrypt_secret(self, password: &Password) -> Result<Self>
597    {
598        match self {
599            Key::V4(k) => Ok(Key::V4(k.decrypt_secret(password)?)),
600            Key::V6(k) => Ok(Key::V6(k.decrypt_secret(password)?)),
601        }
602    }
603
604    /// Encrypts the secret key material.
605    ///
606    /// In OpenPGP, secret key material can be [protected with a
607    /// password].  The password is usually hardened using a [KDF].
608    ///
609    /// [protected with a password]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.3
610    /// [KDF]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7
611    ///
612    /// This function takes ownership of the `Key`, encrypts the
613    /// secret key material using the password, and returns a new key
614    /// whose secret key material is protected with the password.
615    ///
616    /// If the secret key material is already password protected, this
617    /// function returns an error.
618    ///
619    /// # Examples
620    ///
621    /// This example demonstrates how to encrypt the secret key
622    /// material of every key in a certificate.  Decryption can be
623    /// done the same way with [`Key::decrypt_secret`].
624    ///
625    /// ```rust
626    /// use sequoia_openpgp as openpgp;
627    /// # use openpgp::Result;
628    /// use openpgp::cert::prelude::*;
629    /// use openpgp::packet::Packet;
630    ///
631    /// # fn main() -> Result<()> {
632    /// // Generate a certificate whose secret key material is
633    /// // not password protected.
634    /// let (cert, _) =
635    ///     CertBuilder::general_purpose(Some("Alice Lovelace <alice@example.org>"))
636    ///         .generate()?;
637    ///
638    /// // Encrypt every key.
639    /// let mut encrypted_keys: Vec<Packet> = Vec::new();
640    /// for ka in cert.keys().secret() {
641    ///     assert!(ka.key().has_unencrypted_secret());
642    ///
643    ///     // Encrypt the key's secret key material.
644    ///     let key = ka.key().clone().encrypt_secret(&"1234".into())?;
645    ///     assert!(! key.has_unencrypted_secret());
646    ///
647    ///     // We cannot merge it right now, because `cert` is borrowed.
648    ///     encrypted_keys.push(if ka.primary() {
649    ///         key.role_into_primary().into()
650    ///     } else {
651    ///         key.role_into_subordinate().into()
652    ///     });
653    /// }
654    ///
655    /// // Merge the keys into the certificate.  Note: `Cert::insert_packets`
656    /// // prefers added versions of keys.  So, the encrypted version
657    /// // will override the decrypted version.
658    /// let cert = cert.insert_packets(encrypted_keys)?.0;
659    ///
660    /// // Now the every key's secret key material is encrypted.  We'll
661    /// // demonstrate this using the primary key:
662    /// let key = cert.primary_key().key().parts_as_secret()?;
663    /// assert!(! key.has_unencrypted_secret());
664    ///
665    /// // We can't turn it into a keypair without decrypting it.
666    /// assert!(key.clone().into_keypair().is_err());
667    ///
668    /// // And, we need to use the right password.
669    /// assert!(key.clone()
670    ///     .decrypt_secret(&"correct horse battery staple".into())
671    ///     .is_err());
672    ///
673    /// // Let's do it right:
674    /// let mut keypair = key.clone()
675    ///     .decrypt_secret(&"1234".into())?.into_keypair()?;
676    /// # Ok(())
677    /// # }
678    /// ```
679    pub fn encrypt_secret(self, password: &Password) -> Result<Self>
680    {
681        match self {
682            Key::V4(k) => Ok(Key::V4(k.encrypt_secret(password)?)),
683            Key::V6(k) => Ok(Key::V6(k.encrypt_secret(password)?)),
684        }
685    }
686}
687
688macro_rules! impl_common_secret_functions {
689    ($t: path) => {
690        /// Secret key handling.
691        impl<R: key::KeyRole> Key<$t, R> {
692            /// Takes the key packet's `SecretKeyMaterial`, if any.
693            pub fn take_secret(self)
694                               -> (Key<key::PublicParts, R>,
695                                   Option<key::SecretKeyMaterial>)
696            {
697                match self {
698                    Key::V4(k) => {
699                        let (k, s) = k.take_secret();
700                        (k.into(), s)
701                    },
702                    Key::V6(k) => {
703                        let (k, s) = k.take_secret();
704                        (k.into(), s)
705                    },
706                }
707            }
708
709            /// Adds `SecretKeyMaterial` to the packet, returning the old if
710            /// any.
711            pub fn add_secret(self, secret: key::SecretKeyMaterial)
712                              -> (Key<key::SecretParts, R>,
713                                  Option<key::SecretKeyMaterial>)
714            {
715                match self {
716                    Key::V4(k) => {
717                        let (k, s) = k.add_secret(secret);
718                        (k.into(), s)
719                    },
720                    Key::V6(k) => {
721                        let (k, s) = k.add_secret(secret);
722                        (k.into(), s)
723                    },
724                }
725            }
726
727            /// Takes the key packet's `SecretKeyMaterial`, if any.
728            pub fn steal_secret(&mut self) -> Option<key::SecretKeyMaterial>
729            {
730                match self {
731                    Key::V4(k) => k.steal_secret(),
732                    Key::V6(k) => k.steal_secret(),
733                }
734            }
735        }
736    }
737}
738impl_common_secret_functions!(key::PublicParts);
739impl_common_secret_functions!(key::UnspecifiedParts);
740
741/// Secret key handling.
742impl<R: key::KeyRole> Key<key::SecretParts, R> {
743    /// Takes the key packet's `SecretKeyMaterial`.
744    pub fn take_secret(self)
745                       -> (Key<key::PublicParts, R>, key::SecretKeyMaterial)
746    {
747        match self {
748            Key::V4(k) => {
749                let (k, s) = k.take_secret();
750                (k.into(), s)
751            },
752            Key::V6(k) => {
753                let (k, s) = k.take_secret();
754                (k.into(), s)
755            },
756        }
757    }
758
759    /// Adds `SecretKeyMaterial` to the packet, returning the old.
760    pub fn add_secret(self, secret: key::SecretKeyMaterial)
761                      -> (Key<key::SecretParts, R>, key::SecretKeyMaterial)
762    {
763        match self {
764            Key::V4(k) => {
765                let (k, s) = k.add_secret(secret);
766                (k.into(), s)
767            },
768            Key::V6(k) => {
769                let (k, s) = k.add_secret(secret);
770                (k.into(), s)
771            },
772        }
773    }
774}
775
776/// Ordering, equality, and hashing on the public parts only.
777impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
778    /// Compares the public bits of two keys.
779    ///
780    /// This returns `Ordering::Equal` if the public MPIs, creation
781    /// time, and algorithm of the two `Key4`s match.  This does not
782    /// consider the packets' encodings, packets' tags or their secret
783    /// key material.
784    pub fn public_cmp<PB, RB>(&self, b: &Key<PB, RB>)
785                              -> std::cmp::Ordering
786    where
787        PB: key::KeyParts,
788        RB: key::KeyRole,
789    {
790        match (self, b) {
791            (Key::V4(a), Key::V4(b)) => a.public_cmp(b),
792            (Key::V6(a), Key::V6(b)) => a.public_cmp(b),
793            // XXX: is that okay?
794            (Key::V4(_), Key::V6(_)) => std::cmp::Ordering::Less,
795            (Key::V6(_), Key::V4(_)) => std::cmp::Ordering::Greater,
796        }
797    }
798
799    /// Tests whether two keys are equal modulo their secret key
800    /// material.
801    ///
802    /// This returns true if the public MPIs, creation time and
803    /// algorithm of the two `Key4`s match.  This does not consider
804    /// the packets' encodings, packets' tags or their secret key
805    /// material.
806    pub fn public_eq<PB, RB>(&self, b: &Key<PB, RB>)
807                             -> bool
808    where
809        PB: key::KeyParts,
810        RB: key::KeyRole,
811    {
812        self.public_cmp(b) == std::cmp::Ordering::Equal
813    }
814
815    /// Hashes everything but any secret key material into state.
816    ///
817    /// This is an alternate implementation of [`Hash`], which never
818    /// hashes the secret key material.
819    ///
820    ///   [`Hash`]: std::hash::Hash
821    pub fn public_hash<H>(&self, state: &mut H)
822    where
823        H: Hasher,
824    {
825        use std::hash::Hash;
826
827        match self {
828            Key::V4(k) => k.common.hash(state),
829            Key::V6(k) => k.common.common.hash(state),
830        }
831        self.creation_time().hash(state);
832        self.pk_algo().hash(state);
833        Hash::hash(&self.mpis(), state);
834    }
835}
836
837/// Immutable key interface.
838impl<P: key::KeyParts, R: key::KeyRole> Key<P, R> {
839    /// Gets the version.
840    pub fn version(&self) -> u8 {
841        match self {
842            Key::V4(_) => 4,
843            Key::V6(_) => 6,
844        }
845    }
846
847    /// Gets the `Key`'s creation time.
848    pub fn creation_time(&self) -> std::time::SystemTime {
849        match self {
850            Key::V4(k) => k.creation_time(),
851            Key::V6(k) => k.creation_time(),
852        }
853    }
854
855    /// Sets the `Key`'s creation time.
856    ///
857    /// `timestamp` is converted to OpenPGP's internal format,
858    /// [`Timestamp`]: a 32-bit quantity containing the number of
859    /// seconds since the Unix epoch.
860    ///
861    /// `timestamp` is silently rounded to match the internal
862    /// resolution.  An error is returned if `timestamp` is out of
863    /// range.
864    ///
865    /// [`Timestamp`]: crate::types::Timestamp
866    pub fn set_creation_time<T>(&mut self, timestamp: T)
867                                -> Result<std::time::SystemTime>
868    where
869        T: Into<std::time::SystemTime>,
870    {
871        match self {
872            Key::V4(k) => k.set_creation_time(timestamp.into()),
873            Key::V6(k) => k.set_creation_time(timestamp.into()),
874        }
875    }
876
877    /// Gets the public key algorithm.
878    pub fn pk_algo(&self) -> PublicKeyAlgorithm {
879        match self {
880            Key::V4(k) => k.pk_algo(),
881            Key::V6(k) => k.pk_algo(),
882        }
883    }
884
885    /// Sets the public key algorithm.
886    ///
887    /// Returns the old public key algorithm.
888    pub fn set_pk_algo(&mut self, pk_algo: PublicKeyAlgorithm)
889                       -> PublicKeyAlgorithm
890    {
891        match self {
892            Key::V4(k) => k.set_pk_algo(pk_algo),
893            Key::V6(k) => k.set_pk_algo(pk_algo),
894        }
895    }
896
897    /// Returns a reference to the `Key`'s MPIs.
898    pub fn mpis(&self) -> &mpi::PublicKey {
899        match self {
900            Key::V4(k) => k.mpis(),
901            Key::V6(k) => k.mpis(),
902        }
903    }
904
905    /// Returns a mutable reference to the `Key`'s MPIs.
906    pub fn mpis_mut(&mut self) -> &mut mpi::PublicKey {
907        match self {
908            Key::V4(k) => k.mpis_mut(),
909            Key::V6(k) => k.mpis_mut(),
910        }
911    }
912
913    /// Sets the `Key`'s MPIs.
914    ///
915    /// This function returns the old MPIs, if any.
916    pub fn set_mpis(&mut self, mpis: mpi::PublicKey) -> mpi::PublicKey {
917        match self {
918            Key::V4(k) => k.set_mpis(mpis),
919            Key::V6(k) => k.set_mpis(mpis),
920        }
921    }
922
923    /// Returns whether the `Key` contains secret key material.
924    pub fn has_secret(&self) -> bool {
925        match self {
926            Key::V4(k) => k.has_secret(),
927            Key::V6(k) => k.has_secret(),
928        }
929    }
930
931    /// Returns whether the `Key` contains unencrypted secret key
932    /// material.
933    ///
934    /// This returns false if the `Key` doesn't contain any secret key
935    /// material.
936    pub fn has_unencrypted_secret(&self) -> bool {
937        match self {
938            Key::V4(k) => k.has_unencrypted_secret(),
939            Key::V6(k) => k.has_unencrypted_secret(),
940        }
941    }
942
943    /// Returns `Key`'s secret key material, if any.
944    pub fn optional_secret(&self) -> Option<&SecretKeyMaterial> {
945        match self {
946            Key::V4(k) => k.optional_secret(),
947            Key::V6(k) => k.optional_secret(),
948        }
949    }
950
951    /// Computes and returns the `Key`'s `Fingerprint` and returns it as
952    /// a `KeyHandle`.
953    ///
954    /// See [Section 5.5.4 of RFC 9580].
955    ///
956    /// [Section 5.5.4 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.4
957    pub fn key_handle(&self) -> crate::KeyHandle {
958        match self {
959            Key::V4(k) => k.key_handle(),
960            Key::V6(k) => k.key_handle(),
961        }
962    }
963
964    /// Computes and returns the `Key`'s `Fingerprint`.
965    ///
966    /// See [Section 5.5.4 of RFC 9580].
967    ///
968    /// [Section 5.5.4 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.4
969    pub fn fingerprint(&self) -> crate::Fingerprint {
970        match self {
971            Key::V4(k) => k.fingerprint(),
972            Key::V6(k) => k.fingerprint(),
973        }
974    }
975
976    /// Computes and returns the `Key`'s `Key ID`.
977    ///
978    /// See [Section 5.5.4 of RFC 9580].
979    ///
980    /// [Section 5.5.4 of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-5.5.4
981    pub fn keyid(&self) -> crate::KeyID {
982        match self {
983            Key::V4(k) => k.keyid(),
984            Key::V6(k) => k.keyid(),
985        }
986    }
987
988    /// The security requirements of the hash algorithm for
989    /// self-signatures.
990    ///
991    /// A cryptographic hash algorithm usually has [three security
992    /// properties]: pre-image resistance, second pre-image
993    /// resistance, and collision resistance.  If an attacker can
994    /// influence the signed data, then the hash algorithm needs to
995    /// have both second pre-image resistance, and collision
996    /// resistance.  If not, second pre-image resistance is
997    /// sufficient.
998    ///
999    ///   [three security properties]: https://en.wikipedia.org/wiki/Cryptographic_hash_function#Properties
1000    ///
1001    /// In general, an attacker may be able to influence third-party
1002    /// signatures.  But direct key signatures, and binding signatures
1003    /// are only over data fully determined by signer.  And, an
1004    /// attacker's control over self signatures over User IDs is
1005    /// limited due to their structure.
1006    ///
1007    /// These observations can be used to extend the life of a hash
1008    /// algorithm after its collision resistance has been partially
1009    /// compromised, but not completely broken.  For more details,
1010    /// please refer to the documentation for [HashAlgoSecurity].
1011    ///
1012    ///   [HashAlgoSecurity]: crate::policy::HashAlgoSecurity
1013    pub fn hash_algo_security(&self) -> HashAlgoSecurity {
1014        HashAlgoSecurity::SecondPreImageResistance
1015    }
1016
1017    pub(crate) fn role(&self) -> key::KeyRoleRT {
1018        match self {
1019            Key::V4(k) => k.role(),
1020            Key::V6(k) => k.role(),
1021        }
1022    }
1023
1024    pub(crate) fn set_role(&mut self, role: key::KeyRoleRT) {
1025        match self {
1026            Key::V4(k) => k.set_role(role),
1027            Key::V6(k) => k.set_role(role),
1028        }
1029    }
1030}
1031
1032#[cfg(test)]
1033impl<P, R> Arbitrary for Key<P, R>
1034where
1035    P: KeyParts,
1036    R: KeyRole,
1037    Key4<P, R>: Arbitrary,
1038    Key6<P, R>: Arbitrary,
1039{
1040    fn arbitrary(g: &mut Gen) -> Self {
1041        if <bool>::arbitrary(g) {
1042            Key4::arbitrary(g).into()
1043        } else {
1044            Key6::arbitrary(g).into()
1045        }
1046    }
1047}
1048
1049/// A marker trait that captures whether a `Key` definitely contains
1050/// secret key material.
1051///
1052/// A [`Key`] can be treated as if it only has public key material
1053/// ([`key::PublicParts`]) or also has secret key material
1054/// ([`key::SecretParts`]).  For those cases where the type
1055/// information needs to be erased (e.g., interfaces like
1056/// [`Cert::keys`]), we provide the [`key::UnspecifiedParts`] marker.
1057///
1058/// Even if a `Key` does not have the `SecretKey` marker, it may still
1059/// have secret key material.  But, it will generally act as if it
1060/// didn't.  In particular, when serializing a `Key` without the
1061/// `SecretKey` marker, secret key material will be ignored.  See the
1062/// documentation for [`Key`] for a demonstration of this behavior.
1063///
1064/// [`Cert::keys`]: crate::cert::Cert::keys()
1065/// [`Key`]: super::Key
1066/// [`key::PublicParts`]: PublicParts
1067/// [`key::SecretParts`]: SecretParts
1068/// [`key::UnspecifiedParts`]: UnspecifiedParts
1069///
1070/// # Sealed trait
1071///
1072/// This trait is [sealed] and cannot be implemented for types outside this crate.
1073/// Therefore it can be extended in a non-breaking way.
1074/// If you want to implement the trait inside the crate
1075/// you also need to implement the `seal::Sealed` marker trait.
1076///
1077/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
1078pub trait KeyParts: fmt::Debug + seal::Sealed {
1079    /// Converts a key with unspecified parts into this kind of key.
1080    ///
1081    /// This function is helpful when you need to convert a concrete
1082    /// type into a generic type.  Using `From` works, but requires
1083    /// adding a type bound to the generic type, which is ugly and
1084    /// invasive.
1085    ///
1086    /// Converting a key with [`key::PublicParts`] or
1087    /// [`key::UnspecifiedParts`] will always succeed.  However,
1088    /// converting a key to one with [`key::SecretParts`] only
1089    /// succeeds if the key actually contains secret key material.
1090    ///
1091    /// [`key::PublicParts`]: PublicParts
1092    /// [`key::UnspecifiedParts`]: UnspecifiedParts
1093    /// [`key::SecretParts`]: SecretParts
1094    ///
1095    /// # Examples
1096    ///
1097    /// For a less construed example, refer to the [source code]:
1098    ///
1099    /// [source code]: https://gitlab.com/search?search=convert_key&project_id=4469613&search_code=true&repository_ref=master
1100    ///
1101    /// ```
1102    /// use sequoia_openpgp as openpgp;
1103    /// use openpgp::Result;
1104    /// # use openpgp::cert::prelude::*;
1105    /// use openpgp::packet::prelude::*;
1106    ///
1107    /// fn f<P>(cert: &Cert, mut key: Key<P, key::UnspecifiedRole>)
1108    ///     -> Result<Key<P, key::UnspecifiedRole>>
1109    ///     where P: key::KeyParts
1110    /// {
1111    ///     // ...
1112    ///
1113    /// # let criterium = true;
1114    ///     if criterium {
1115    ///         // Cert::primary_key's return type is concrete
1116    ///         // (Key<key::PublicParts, key::PrimaryRole>).  We need to
1117    ///         // convert it to the generic type Key<P, key::UnspecifiedRole>.
1118    ///         // First, we "downcast" it to have unspecified parts and an
1119    ///         // unspecified role, then we use a method defined by the
1120    ///         // generic type to perform the conversion to the generic
1121    ///         // type P.
1122    ///         key = P::convert_key(
1123    ///             cert.primary_key().key().clone()
1124    ///                 .parts_into_unspecified()
1125    ///                 .role_into_unspecified())?;
1126    ///     }
1127    /// #   else { unreachable!() }
1128    ///
1129    ///     // ...
1130    ///
1131    ///     Ok(key)
1132    /// }
1133    /// # fn main() -> openpgp::Result<()> {
1134    /// # let (cert, _) =
1135    /// #     CertBuilder::general_purpose(Some("alice@example.org"))
1136    /// #     .generate()?;
1137    /// # f(&cert, cert.primary_key().key().clone().role_into_unspecified())?;
1138    /// # Ok(())
1139    /// # }
1140    /// ```
1141    fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
1142                               -> Result<Key<Self, R>>
1143        where Self: Sized;
1144
1145    /// Converts a key reference with unspecified parts into this kind
1146    /// of key reference.
1147    ///
1148    /// This function is helpful when you need to convert a concrete
1149    /// type into a generic type.  Using `From` works, but requires
1150    /// adding a type bound to the generic type, which is ugly and
1151    /// invasive.
1152    ///
1153    /// Converting a key with [`key::PublicParts`] or
1154    /// [`key::UnspecifiedParts`] will always succeed.  However,
1155    /// converting a key to one with [`key::SecretParts`] only
1156    /// succeeds if the key actually contains secret key material.
1157    ///
1158    /// [`key::PublicParts`]: PublicParts
1159    /// [`key::UnspecifiedParts`]: UnspecifiedParts
1160    /// [`key::SecretParts`]: SecretParts
1161    fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
1162                                   -> Result<&Key<Self, R>>
1163        where Self: Sized;
1164
1165    /// Converts a key bundle with unspecified parts into this kind of
1166    /// key bundle.
1167    ///
1168    /// This function is helpful when you need to convert a concrete
1169    /// type into a generic type.  Using `From` works, but requires
1170    /// adding a type bound to the generic type, which is ugly and
1171    /// invasive.
1172    ///
1173    /// Converting a key bundle with [`key::PublicParts`] or
1174    /// [`key::UnspecifiedParts`] will always succeed.  However,
1175    /// converting a key bundle to one with [`key::SecretParts`] only
1176    /// succeeds if the key bundle actually contains secret key
1177    /// material.
1178    ///
1179    /// [`key::PublicParts`]: PublicParts
1180    /// [`key::UnspecifiedParts`]: UnspecifiedParts
1181    /// [`key::SecretParts`]: SecretParts
1182    fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
1183                                  -> Result<KeyBundle<Self, R>>
1184        where Self: Sized;
1185
1186    /// Converts a key bundle reference with unspecified parts into
1187    /// this kind of key bundle reference.
1188    ///
1189    /// This function is helpful when you need to convert a concrete
1190    /// type into a generic type.  Using `From` works, but requires
1191    /// adding a type bound to the generic type, which is ugly and
1192    /// invasive.
1193    ///
1194    /// Converting a key bundle with [`key::PublicParts`] or
1195    /// [`key::UnspecifiedParts`] will always succeed.  However,
1196    /// converting a key bundle to one with [`key::SecretParts`] only
1197    /// succeeds if the key bundle actually contains secret key
1198    /// material.
1199    ///
1200    /// [`key::PublicParts`]: PublicParts
1201    /// [`key::UnspecifiedParts`]: UnspecifiedParts
1202    /// [`key::SecretParts`]: SecretParts
1203    fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
1204                                      -> Result<&KeyBundle<Self, R>>
1205        where Self: Sized;
1206
1207    /// Converts a key amalgamation with unspecified parts into this
1208    /// kind of key amalgamation.
1209    ///
1210    /// This function is helpful when you need to convert a concrete
1211    /// type into a generic type.  Using `From` works, but requires
1212    /// adding a type bound to the generic type, which is ugly and
1213    /// invasive.
1214    ///
1215    /// Converting a key amalgamation with [`key::PublicParts`] or
1216    /// [`key::UnspecifiedParts`] will always succeed.  However,
1217    /// converting a key amalgamation to one with [`key::SecretParts`]
1218    /// only succeeds if the key amalgamation actually contains secret
1219    /// key material.
1220    ///
1221    /// [`key::PublicParts`]: PublicParts
1222    /// [`key::UnspecifiedParts`]: UnspecifiedParts
1223    /// [`key::SecretParts`]: SecretParts
1224    fn convert_key_amalgamation<R: KeyRole>(
1225        ka: ComponentAmalgamation<Key<UnspecifiedParts, R>>)
1226        -> Result<ComponentAmalgamation<Key<Self, R>>>
1227        where Self: Sized;
1228
1229    /// Converts a key amalgamation reference with unspecified parts
1230    /// into this kind of key amalgamation reference.
1231    ///
1232    /// This function is helpful when you need to convert a concrete
1233    /// type into a generic type.  Using `From` works, but requires
1234    /// adding a type bound to the generic type, which is ugly and
1235    /// invasive.
1236    ///
1237    /// Converting a key amalgamation with [`key::PublicParts`] or
1238    /// [`key::UnspecifiedParts`] will always succeed.  However,
1239    /// converting a key amalgamation to one with [`key::SecretParts`]
1240    /// only succeeds if the key amalgamation actually contains secret
1241    /// key material.
1242    ///
1243    /// [`key::PublicParts`]: PublicParts
1244    /// [`key::UnspecifiedParts`]: UnspecifiedParts
1245    /// [`key::SecretParts`]: SecretParts
1246    fn convert_key_amalgamation_ref<'a, R: KeyRole>(
1247        ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
1248        -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>>
1249        where Self: Sized;
1250
1251    /// Indicates that secret key material should be considered when
1252    /// comparing or hashing this key.
1253    fn significant_secrets() -> bool;
1254}
1255
1256/// A marker trait that captures a `Key`'s role.
1257///
1258/// A [`Key`] can either be a primary key ([`key::PrimaryRole`]) or a
1259/// subordinate key ([`key::SubordinateRole`]).  For those cases where
1260/// the type information needs to be erased (e.g., interfaces like
1261/// [`Cert::keys`]), we provide the [`key::UnspecifiedRole`] marker.
1262///
1263/// [`Key`]: super::Key
1264/// [`key::PrimaryRole`]: PrimaryRole
1265/// [`key::SubordinateRole`]: SubordinateRole
1266/// [`Cert::keys`]: crate::cert::Cert::keys()
1267/// [`key::UnspecifiedRole`]: UnspecifiedRole
1268///
1269/// # Sealed trait
1270///
1271/// This trait is [sealed] and cannot be implemented for types outside this crate.
1272/// Therefore it can be extended in a non-breaking way.
1273/// If you want to implement the trait inside the crate
1274/// you also need to implement the `seal::Sealed` marker trait.
1275///
1276/// [sealed]: https://rust-lang.github.io/api-guidelines/future-proofing.html#sealed-traits-protect-against-downstream-implementations-c-sealed
1277pub trait KeyRole: fmt::Debug + seal::Sealed {
1278    /// Converts a key with an unspecified role into this kind of key.
1279    ///
1280    /// This function is helpful when you need to convert a concrete
1281    /// type into a generic type.  Using `From` works, but requires
1282    /// adding a type bound to the generic type, which is ugly and
1283    /// invasive.
1284    ///
1285    /// # Examples
1286    ///
1287    /// ```
1288    /// use sequoia_openpgp as openpgp;
1289    /// use openpgp::Result;
1290    /// # use openpgp::cert::prelude::*;
1291    /// use openpgp::packet::prelude::*;
1292    ///
1293    /// fn f<R>(cert: &Cert, mut key: Key<key::UnspecifiedParts, R>)
1294    ///     -> Result<Key<key::UnspecifiedParts, R>>
1295    ///     where R: key::KeyRole
1296    /// {
1297    ///     // ...
1298    ///
1299    /// # let criterium = true;
1300    ///     if criterium {
1301    ///         // Cert::primary_key's return type is concrete
1302    ///         // (Key<key::PublicParts, key::PrimaryRole>).  We need to
1303    ///         // convert it to the generic type Key<key::UnspecifiedParts, R>.
1304    ///         // First, we "downcast" it to have unspecified parts and an
1305    ///         // unspecified role, then we use a method defined by the
1306    ///         // generic type to perform the conversion to the generic
1307    ///         // type R.
1308    ///         key = R::convert_key(
1309    ///             cert.primary_key().key().clone()
1310    ///                 .parts_into_unspecified()
1311    ///                 .role_into_unspecified());
1312    ///     }
1313    /// #   else { unreachable!() }
1314    ///
1315    ///     // ...
1316    ///
1317    ///     Ok(key)
1318    /// }
1319    /// # fn main() -> openpgp::Result<()> {
1320    /// # let (cert, _) =
1321    /// #     CertBuilder::general_purpose(Some("alice@example.org"))
1322    /// #     .generate()?;
1323    /// # f(&cert, cert.primary_key().key().clone().parts_into_unspecified())?;
1324    /// # Ok(())
1325    /// # }
1326    /// ```
1327    fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
1328                                -> Key<P, Self>
1329        where Self: Sized;
1330
1331    /// Converts a key reference with an unspecified role into this
1332    /// kind of key reference.
1333    ///
1334    /// This function is helpful when you need to convert a concrete
1335    /// type into a generic type.  Using `From` works, but requires
1336    /// adding a type bound to the generic type, which is ugly and
1337    /// invasive.
1338    fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
1339                                    -> &Key<P, Self>
1340        where Self: Sized;
1341
1342    /// Converts a key bundle with an unspecified role into this kind
1343    /// of key bundle.
1344    ///
1345    /// This function is helpful when you need to convert a concrete
1346    /// type into a generic type.  Using `From` works, but requires
1347    /// adding a type bound to the generic type, which is ugly and
1348    /// invasive.
1349    fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
1350                                   -> KeyBundle<P, Self>
1351        where Self: Sized;
1352
1353    /// Converts a key bundle reference with an unspecified role into
1354    /// this kind of key bundle reference.
1355    ///
1356    /// This function is helpful when you need to convert a concrete
1357    /// type into a generic type.  Using `From` works, but requires
1358    /// adding a type bound to the generic type, which is ugly and
1359    /// invasive.
1360    fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
1361                                       -> &KeyBundle<P, Self>
1362        where Self: Sized;
1363
1364    /// Returns the role as a runtime value.
1365    fn role() -> KeyRoleRT;
1366}
1367
1368/// A marker that indicates that a `Key` should be treated like a
1369/// public key.
1370///
1371/// Note: this doesn't indicate whether the data structure contains
1372/// secret key material; it indicates whether any secret key material
1373/// should be ignored.  For instance, when exporting a key with the
1374/// `PublicParts` marker, secret key material will *not* be exported.
1375/// See the documentation for [`Key`] for a demonstration.
1376///
1377/// Refer to [`KeyParts`] for details.
1378///
1379/// [`Key`]: super::Key
1380#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1381pub struct PublicParts;
1382
1383assert_send_and_sync!(PublicParts);
1384
1385impl seal::Sealed for PublicParts {}
1386impl KeyParts for PublicParts {
1387    fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
1388                               -> Result<Key<Self, R>> {
1389        Ok(key.into())
1390    }
1391
1392    fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
1393                                   -> Result<&Key<Self, R>> {
1394        Ok(key.into())
1395    }
1396
1397    fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
1398                                  -> Result<KeyBundle<Self, R>> {
1399        Ok(bundle.into())
1400    }
1401
1402    fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
1403                                      -> Result<&KeyBundle<Self, R>> {
1404        Ok(bundle.into())
1405    }
1406
1407    fn convert_key_amalgamation<R: KeyRole>(
1408        ka: ComponentAmalgamation<Key<UnspecifiedParts, R>>)
1409        -> Result<ComponentAmalgamation<Key<Self, R>>> {
1410        Ok(ka.into())
1411    }
1412
1413    fn convert_key_amalgamation_ref<'a, R: KeyRole>(
1414        ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
1415        -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
1416        Ok(ka.into())
1417    }
1418
1419    fn significant_secrets() -> bool {
1420        false
1421    }
1422}
1423
1424/// A marker that indicates that a `Key` should be treated like a
1425/// secret key.
1426///
1427/// Unlike the [`key::PublicParts`] marker, this marker asserts that
1428/// the [`Key`] contains secret key material.  Because secret key
1429/// material is not protected by the self-signature, there is no
1430/// indication that the secret key material is actually valid.
1431///
1432/// Refer to [`KeyParts`] for details.
1433///
1434/// [`key::PublicParts`]: PublicParts
1435/// [`Key`]: super::Key
1436#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1437pub struct SecretParts;
1438
1439assert_send_and_sync!(SecretParts);
1440
1441impl seal::Sealed for SecretParts {}
1442impl KeyParts for SecretParts {
1443    fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
1444                               -> Result<Key<Self, R>>{
1445        key.try_into()
1446    }
1447
1448    fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
1449                                   -> Result<&Key<Self, R>> {
1450        key.try_into()
1451    }
1452
1453    fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
1454                                  -> Result<KeyBundle<Self, R>> {
1455        bundle.try_into()
1456    }
1457
1458    fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
1459                                      -> Result<&KeyBundle<Self, R>> {
1460        bundle.try_into()
1461    }
1462
1463    fn convert_key_amalgamation<R: KeyRole>(
1464        ka: ComponentAmalgamation<Key<UnspecifiedParts, R>>)
1465        -> Result<ComponentAmalgamation<Key<Self, R>>> {
1466        ka.try_into()
1467    }
1468
1469    fn convert_key_amalgamation_ref<'a, R: KeyRole>(
1470        ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
1471        -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
1472        ka.try_into()
1473    }
1474
1475    fn significant_secrets() -> bool {
1476        true
1477    }
1478}
1479
1480/// A marker that indicates that a `Key`'s parts are unspecified.
1481///
1482/// Neither public key-specific nor secret key-specific operations are
1483/// allowed on these types of keys.  For instance, it is not possible
1484/// to export a key with the `UnspecifiedParts` marker, because it is
1485/// unclear how to treat any secret key material.  To export such a
1486/// key, you need to first change the marker to [`key::PublicParts`]
1487/// or [`key::SecretParts`].
1488///
1489/// This marker is used when it is necessary to erase the type.  For
1490/// instance, we need to do this when mixing [`Key`]s with different
1491/// markers in the same collection.  See [`Cert::keys`] for an
1492/// example.
1493///
1494/// Refer to [`KeyParts`] for details.
1495///
1496/// [`key::PublicParts`]: PublicParts
1497/// [`key::SecretParts`]: SecretParts
1498/// [`Key`]: super::Key
1499/// [`Cert::keys`]: super::super::Cert::keys()
1500#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1501pub struct UnspecifiedParts;
1502
1503assert_send_and_sync!(UnspecifiedParts);
1504
1505impl seal::Sealed for UnspecifiedParts {}
1506impl KeyParts for UnspecifiedParts {
1507    fn convert_key<R: KeyRole>(key: Key<UnspecifiedParts, R>)
1508                               -> Result<Key<Self, R>> {
1509        Ok(key)
1510    }
1511
1512    fn convert_key_ref<R: KeyRole>(key: &Key<UnspecifiedParts, R>)
1513                                   -> Result<&Key<Self, R>> {
1514        Ok(key)
1515    }
1516
1517    fn convert_bundle<R: KeyRole>(bundle: KeyBundle<UnspecifiedParts, R>)
1518                                  -> Result<KeyBundle<Self, R>> {
1519        Ok(bundle)
1520    }
1521
1522    fn convert_bundle_ref<R: KeyRole>(bundle: &KeyBundle<UnspecifiedParts, R>)
1523                                      -> Result<&KeyBundle<Self, R>> {
1524        Ok(bundle)
1525    }
1526
1527    fn convert_key_amalgamation<R: KeyRole>(
1528        ka: ComponentAmalgamation<Key<UnspecifiedParts, R>>)
1529        -> Result<ComponentAmalgamation<Key<UnspecifiedParts, R>>> {
1530        Ok(ka)
1531    }
1532
1533    fn convert_key_amalgamation_ref<'a, R: KeyRole>(
1534        ka: &'a ComponentAmalgamation<'a, Key<UnspecifiedParts, R>>)
1535        -> Result<&'a ComponentAmalgamation<'a, Key<Self, R>>> {
1536        Ok(ka)
1537    }
1538
1539    fn significant_secrets() -> bool {
1540        true
1541    }
1542}
1543
1544/// A marker that indicates the `Key` should be treated like a primary key.
1545///
1546/// Refer to [`KeyRole`] for details.
1547///
1548#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1549pub struct PrimaryRole;
1550
1551assert_send_and_sync!(PrimaryRole);
1552
1553impl seal::Sealed for PrimaryRole {}
1554impl KeyRole for PrimaryRole {
1555    fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
1556                                -> Key<P, Self> {
1557        key.into()
1558    }
1559
1560    fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
1561                                    -> &Key<P, Self> {
1562        key.into()
1563    }
1564
1565    fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
1566                                   -> KeyBundle<P, Self> {
1567        bundle.into()
1568    }
1569
1570    fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
1571                                       -> &KeyBundle<P, Self> {
1572        bundle.into()
1573    }
1574
1575    fn role() -> KeyRoleRT {
1576        KeyRoleRT::Primary
1577    }
1578}
1579
1580/// A marker that indicates the `Key` should be treated like a subkey.
1581///
1582/// Refer to [`KeyRole`] for details.
1583///
1584#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1585pub struct SubordinateRole;
1586
1587assert_send_and_sync!(SubordinateRole);
1588
1589impl seal::Sealed for SubordinateRole {}
1590impl KeyRole for SubordinateRole {
1591    fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
1592                                -> Key<P, Self> {
1593        key.into()
1594    }
1595
1596    fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
1597                                    -> &Key<P, Self> {
1598        key.into()
1599    }
1600
1601    fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
1602                                   -> KeyBundle<P, Self> {
1603        bundle.into()
1604    }
1605
1606    fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
1607                                       -> &KeyBundle<P, Self> {
1608        bundle.into()
1609    }
1610
1611    fn role() -> KeyRoleRT {
1612        KeyRoleRT::Subordinate
1613    }
1614}
1615
1616/// A marker that indicates the `Key`'s role is unspecified.
1617///
1618/// Neither primary key-specific nor subkey-specific operations are
1619/// allowed.  To perform those operations, the marker first has to be
1620/// changed to either [`key::PrimaryRole`] or
1621/// [`key::SubordinateRole`], as appropriate.
1622///
1623/// Refer to [`KeyRole`] for details.
1624///
1625/// [`key::PrimaryRole`]: PrimaryRole
1626/// [`key::SubordinateRole`]: SubordinateRole
1627#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
1628pub struct UnspecifiedRole;
1629
1630assert_send_and_sync!(UnspecifiedRole);
1631
1632impl seal::Sealed for UnspecifiedRole {}
1633impl KeyRole for UnspecifiedRole {
1634    fn convert_key<P: KeyParts>(key: Key<P, UnspecifiedRole>)
1635                                -> Key<P, Self> {
1636        key
1637    }
1638
1639    fn convert_key_ref<P: KeyParts>(key: &Key<P, UnspecifiedRole>)
1640                                    -> &Key<P, Self> {
1641        key
1642    }
1643
1644    fn convert_bundle<P: KeyParts>(bundle: KeyBundle<P, UnspecifiedRole>)
1645                                   -> KeyBundle<P, Self> {
1646        bundle
1647    }
1648
1649    fn convert_bundle_ref<P: KeyParts>(bundle: &KeyBundle<P, UnspecifiedRole>)
1650                                       -> &KeyBundle<P, Self> {
1651        bundle
1652    }
1653
1654    fn role() -> KeyRoleRT {
1655        KeyRoleRT::Unspecified
1656    }
1657}
1658
1659/// Encodes the key role at run time.
1660///
1661/// While `KeyRole` tracks the key's role in the type system,
1662/// `KeyRoleRT` tracks the key role at run time.
1663///
1664/// When we are doing a reference conversion (e.g. by using
1665/// [`Key::role_as_primary`]), we do not change the key's role.  But,
1666/// when we are doing an owned conversion (e.g. by using
1667/// [`Key::role_into_primary`]), we do change the key's role.  The
1668/// rationale here is that the former conversion is done to allow a
1669/// reference to be given to a function expecting a certain shape of
1670/// key (e.g. to prevent excessive monomorphization), while the latter
1671/// conversion signals intent (e.g. to put a key into a
1672/// `Packet::PublicKey`).
1673///
1674/// This is similar to how we have `KeyParts` that track the presence
1675/// or absence of secret key material in the type system, yet at run
1676/// time a key may or may not actually have secret key material (with
1677/// the constraint that a key with `SecretParts` MUST have secret key
1678/// material).
1679#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1680pub enum KeyRoleRT {
1681    /// The key is a primary key.
1682    Primary,
1683
1684    /// The key is a subkey.
1685    Subordinate,
1686
1687    /// The key's role is unspecified.
1688    Unspecified,
1689}
1690
1691/// A Public Key.
1692pub(crate) type PublicKey = Key<PublicParts, PrimaryRole>;
1693/// A Public Subkey.
1694pub(crate) type PublicSubkey = Key<PublicParts, SubordinateRole>;
1695/// A Secret Key.
1696pub(crate) type SecretKey = Key<SecretParts, PrimaryRole>;
1697/// A Secret Subkey.
1698pub(crate) type SecretSubkey = Key<SecretParts, SubordinateRole>;
1699
1700/// A key with public parts, and an unspecified role
1701/// (`UnspecifiedRole`).
1702#[allow(dead_code)]
1703pub(crate) type UnspecifiedPublic = Key<PublicParts, UnspecifiedRole>;
1704/// A key with secret parts, and an unspecified role
1705/// (`UnspecifiedRole`).
1706pub(crate) type UnspecifiedSecret = Key<SecretParts, UnspecifiedRole>;
1707
1708/// A primary key with unspecified parts (`UnspecifiedParts`).
1709#[allow(dead_code)]
1710pub(crate) type UnspecifiedPrimary = Key<UnspecifiedParts, PrimaryRole>;
1711/// A subkey key with unspecified parts (`UnspecifiedParts`).
1712#[allow(dead_code)]
1713pub(crate) type UnspecifiedSecondary = Key<UnspecifiedParts, SubordinateRole>;
1714
1715/// A key whose parts and role are unspecified
1716/// (`UnspecifiedParts`, `UnspecifiedRole`).
1717#[allow(dead_code)]
1718pub(crate) type UnspecifiedKey = Key<UnspecifiedParts, UnspecifiedRole>;
1719
1720/// Cryptographic operations using the key material.
1721impl<P, R> Key<P, R>
1722     where P: key::KeyParts,
1723           R: key::KeyRole,
1724{
1725    /// Encrypts the given data with this key.
1726    pub fn encrypt(&self, data: &SessionKey) -> Result<mpi::Ciphertext> {
1727        use crate::crypto::ecdh::aes_key_wrap;
1728        use crate::crypto::backend::{Backend, interface::{Asymmetric, Kdf}};
1729        use crate::crypto::mpi::PublicKey;
1730        use PublicKeyAlgorithm::*;
1731
1732        #[allow(deprecated, non_snake_case)]
1733        #[allow(clippy::erasing_op, clippy::identity_op)]
1734        match self.pk_algo() {
1735            X25519 =>
1736                if let mpi::PublicKey::X25519 { u: U } = self.mpis()
1737            {
1738                // Generate an ephemeral key pair {v, V=vG}
1739                let (v, V) = Backend::x25519_generate_key()?;
1740
1741                // Compute the shared point S = vU;
1742                let S = Backend::x25519_shared_point(&v, U)?;
1743
1744                // Compute the wrap key.
1745                let wrap_algo = SymmetricAlgorithm::AES128;
1746                let mut ikm: SessionKey = vec![0; 32 + 32 + 32].into();
1747                ikm[0 * 32..1 * 32].copy_from_slice(&V[..]);
1748                ikm[1 * 32..2 * 32].copy_from_slice(&U[..]);
1749                ikm[2 * 32..3 * 32].copy_from_slice(&S[..]);
1750                let mut kek = vec![0; wrap_algo.key_size()?].into();
1751                Backend::hkdf_sha256(&ikm, None, b"OpenPGP X25519", &mut kek)?;
1752
1753                let esk = aes_key_wrap(wrap_algo, kek.as_protected(),
1754                                       data.as_protected())?;
1755                Ok(mpi::Ciphertext::X25519 {
1756                    e: Box::new(V),
1757                    key: esk.into(),
1758                })
1759            } else {
1760                Err(Error::MalformedPacket(format!(
1761                    "Key: Expected X25519 public key, got {:?}", self.mpis())).into())
1762            },
1763
1764            X448 =>
1765                if let mpi::PublicKey::X448 { u: U } = self.mpis()
1766            {
1767                let (v, V) = Backend::x448_generate_key()?;
1768
1769                // Compute the shared point S = vU;
1770                let S = Backend::x448_shared_point(&v, U)?;
1771
1772                // Compute the wrap key.
1773                let wrap_algo = SymmetricAlgorithm::AES256;
1774                let mut ikm: SessionKey = vec![0; 56 + 56 + 56].into();
1775                ikm[0 * 56..1 * 56].copy_from_slice(&V[..]);
1776                ikm[1 * 56..2 * 56].copy_from_slice(&U[..]);
1777                ikm[2 * 56..3 * 56].copy_from_slice(&S[..]);
1778                let mut kek = vec![0; wrap_algo.key_size()?].into();
1779                Backend::hkdf_sha512(&ikm, None, b"OpenPGP X448", &mut kek)?;
1780
1781                let esk = aes_key_wrap(wrap_algo, kek.as_protected(),
1782                                       data.as_protected())?;
1783                Ok(mpi::Ciphertext::X448 {
1784                    e: Box::new(V),
1785                    key: esk.into(),
1786                })
1787            } else {
1788                Err(Error::MalformedPacket(format!(
1789                    "Key: Expected X448 public key, got {:?}", self.mpis())).into())
1790            },
1791
1792            MLKEM768_X25519 => if let mpi::PublicKey::MLKEM768_X25519 {
1793                ecdh: ecdh_public, mlkem: mlkem_public,
1794            } = self.mpis()
1795            {
1796                let (ecdh_secret, ecdh_ciphertext) =
1797                    Backend::x25519_generate_key()?;
1798                let ecdh_keyshare = Backend::x25519_shared_point(
1799                    &ecdh_secret, ecdh_public)?;
1800
1801                let (mlkem_ciphertext, mlkem_keyshare) =
1802                    Backend::mlkem768_encapsulate(mlkem_public)?;
1803
1804                let kek = crate::crypto::asymmetric::multi_key_combine(
1805                    &mlkem_keyshare,
1806                    &ecdh_keyshare,
1807                    ecdh_ciphertext.as_ref(),
1808                    ecdh_public.as_ref(),
1809                    PublicKeyAlgorithm::MLKEM768_X25519)?;
1810
1811                let esk = aes_key_wrap(SymmetricAlgorithm::AES256,
1812                                       kek.as_protected(),
1813                                       data.as_protected())?.into();
1814                Ok(mpi::Ciphertext::MLKEM768_X25519 {
1815                    ecdh: Box::new(ecdh_ciphertext),
1816                    mlkem: mlkem_ciphertext,
1817                    esk,
1818                })
1819            } else {
1820                Err(Error::MalformedPacket(format!(
1821                    "Key: Expected MLKEM768_X25519 public key, got {:?}",
1822                    self.mpis())).into())
1823            },
1824
1825            MLKEM1024_X448 => if let mpi::PublicKey::MLKEM1024_X448 {
1826                ecdh: ecdh_public, mlkem: mlkem_public,
1827            } = self.mpis()
1828            {
1829                let (ecdh_secret, ecdh_ciphertext) =
1830                    Backend::x448_generate_key()?;
1831                let ecdh_keyshare = Backend::x448_shared_point(
1832                    &ecdh_secret, ecdh_public)?;
1833
1834                let (mlkem_ciphertext, mlkem_keyshare) =
1835                    Backend::mlkem1024_encapsulate(mlkem_public)?;
1836
1837                let kek = crate::crypto::asymmetric::multi_key_combine(
1838                    &mlkem_keyshare,
1839                    &ecdh_keyshare,
1840                    ecdh_ciphertext.as_ref(),
1841                    ecdh_public.as_ref(),
1842                    PublicKeyAlgorithm::MLKEM1024_X448)?;
1843
1844                let esk = aes_key_wrap(SymmetricAlgorithm::AES256,
1845                                       kek.as_protected(),
1846                                       data.as_protected())?.into();
1847                Ok(mpi::Ciphertext::MLKEM1024_X448 {
1848                    ecdh: Box::new(ecdh_ciphertext),
1849                    mlkem: mlkem_ciphertext,
1850                    esk,
1851                })
1852            } else {
1853                Err(Error::MalformedPacket(format!(
1854                    "Key: Expected MLKEM1024_X448 public key, got {:?}",
1855                    self.mpis())).into())
1856            },
1857
1858            RSASign | DSA | ECDSA | EdDSA | Ed25519 | Ed448
1859                | MLDSA65_Ed25519 | MLDSA87_Ed448
1860                | SLHDSA128s | SLHDSA128f | SLHDSA256s =>
1861                Err(Error::InvalidOperation(
1862                    format!("{} is not an encryption algorithm", self.pk_algo())
1863                ).into()),
1864
1865            ECDH if matches!(self.mpis(),
1866                             PublicKey::ECDH { curve: Curve::Cv25519, ..}) =>
1867            {
1868                let q = match self.mpis() {
1869                    PublicKey::ECDH { q, .. } => q,
1870                    _ => unreachable!(),
1871                };
1872
1873                // Obtain the authenticated recipient public key R
1874                let R = q.decode_point(&Curve::Cv25519)?.0;
1875
1876                // Generate an ephemeral key pair {v, V=vG}
1877                // Compute the public key.
1878                let (v, VB) = Backend::x25519_generate_key()?;
1879                let VB = mpi::MPI::new_compressed_point(&VB);
1880
1881                // Compute the shared point S = vR;
1882                let S = Backend::x25519_shared_point(&v, R.try_into()?)?;
1883
1884                crate::crypto::ecdh::encrypt_wrap(
1885                    self.parts_as_public().role_as_subordinate(), data, VB, &S)
1886            },
1887
1888            RSAEncryptSign | RSAEncrypt |
1889            ElGamalEncrypt | ElGamalEncryptSign |
1890            ECDH |
1891            Private(_) | Unknown(_) => self.encrypt_backend(data),
1892        }
1893    }
1894
1895    /// Verifies the given signature.
1896    pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
1897                  digest: &[u8]) -> Result<()> {
1898        use crate::crypto::backend::{Backend, interface::Asymmetric};
1899        use crate::crypto::mpi::{PublicKey, Signature};
1900
1901        fn bad(e: impl ToString) -> anyhow::Error {
1902            Error::BadSignature(e.to_string()).into()
1903        }
1904
1905        let ok = match (self.mpis(), sig) {
1906            (PublicKey::Ed25519 { a }, Signature::Ed25519 { s }) =>
1907                Backend::ed25519_verify(a, digest, s)?,
1908
1909            (PublicKey::Ed448 { a }, Signature::Ed448 { s }) =>
1910                Backend::ed448_verify(a, digest, s)?,
1911
1912            (PublicKey::EdDSA { curve, q }, Signature::EdDSA { r, s }) =>
1913              match curve {
1914                Curve::Ed25519 => {
1915                    let (public, ..) = q.decode_point(&Curve::Ed25519)?;
1916                    assert_eq!(public.len(), 32);
1917
1918                    // OpenPGP encodes R and S separately, but our
1919                    // cryptographic backends expect them to be
1920                    // concatenated.
1921                    let mut signature = Vec::with_capacity(64);
1922
1923                    // We need to zero-pad them at the front, because
1924                    // the MPI encoding drops leading zero bytes.
1925                    signature.extend_from_slice(
1926                        &r.value_padded(32).map_err(bad)?);
1927                    signature.extend_from_slice(
1928                        &s.value_padded(32).map_err(bad)?);
1929
1930                    // Let's see if we got it right.
1931                    debug_assert_eq!(signature.len(), 64);
1932
1933                    Backend::ed25519_verify(public.try_into()?,
1934                                            digest,
1935                                            &signature.as_slice().try_into()?)?
1936                },
1937                _ => return
1938                    Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
1939              },
1940
1941            (PublicKey::MLDSA65_Ed25519 { eddsa: eddsa_pub, mldsa: mldsa_pub },
1942             Signature::MLDSA65_Ed25519 { eddsa: eddsa_sig, mldsa: mldsa_sig })
1943                => {
1944                    let mut ok = 0;
1945
1946                    if let Ok(true) = Backend::ed25519_verify(
1947                        eddsa_pub, digest, eddsa_sig)
1948                    {
1949                        ok += 1;
1950                    }
1951
1952                    if let Ok(true) = Backend::mldsa65_verify(
1953                        mldsa_pub, digest, mldsa_sig)
1954                    {
1955                        ok += 1;
1956                    }
1957
1958                    ok == 2
1959                },
1960
1961            (PublicKey::MLDSA87_Ed448 { eddsa: eddsa_pub, mldsa: mldsa_pub },
1962             Signature::MLDSA87_Ed448 { eddsa: eddsa_sig, mldsa: mldsa_sig })
1963                => {
1964                    let mut ok = 0;
1965
1966                    if let Ok(true) = Backend::ed448_verify(
1967                        eddsa_pub, digest, eddsa_sig)
1968                    {
1969                        ok += 1;
1970                    }
1971
1972                    if let Ok(true) = Backend::mldsa87_verify(
1973                        mldsa_pub, digest, mldsa_sig)
1974                    {
1975                        ok += 1;
1976                    }
1977
1978                    ok == 2
1979                },
1980
1981            (PublicKey::SLHDSA128s { public }, Signature::SLHDSA128s { sig }) =>
1982                Backend::slhdsa128s_verify(public, digest, sig)?,
1983
1984            (PublicKey::SLHDSA128f { public }, Signature::SLHDSA128f { sig }) =>
1985                Backend::slhdsa128f_verify(public, digest, sig)?,
1986
1987            (PublicKey::SLHDSA256s { public }, Signature::SLHDSA256s { sig }) =>
1988                Backend::slhdsa256s_verify(public, digest, sig)?,
1989
1990            (PublicKey::DSA { p, q, g, y }, Signature::DSA { r, s }) =>
1991                Backend::dsa_verify(p, q, g, y, digest, r, s)?,
1992
1993            (PublicKey::RSA { .. }, Signature::RSA { .. }) |
1994            (PublicKey::ECDSA { .. }, Signature::ECDSA { .. }) =>
1995                return self.verify_backend(sig, hash_algo, digest),
1996
1997            _ => return Err(Error::MalformedPacket(format!(
1998                "unsupported combination of key {} and signature {:?}.",
1999                self.pk_algo(), sig)).into()),
2000        };
2001
2002        if ok {
2003            Ok(())
2004        } else {
2005            Err(Error::ManipulatedMessage.into())
2006        }
2007    }
2008}
2009
2010/// Holds secret key material.
2011///
2012/// This type allows postponing the decryption of the secret key
2013/// material until it is actually needed.
2014///
2015/// If the secret key material is not encrypted with a password, then
2016/// we encrypt it in memory.  This helps protect against
2017/// [heartbleed]-style attacks where a buffer over-read allows an
2018/// attacker to read from the process's address space.  This
2019/// protection is less important for Rust programs, which are memory
2020/// safe.  However, it is essential when Sequoia is used via its FFI.
2021///
2022/// See [`crypto::mem::Encrypted`] for details.
2023///
2024/// [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed
2025/// [`crypto::mem::Encrypted`]: super::super::crypto::mem::Encrypted
2026#[derive(PartialEq, Eq, Hash, Clone, Debug)]
2027pub enum SecretKeyMaterial {
2028    /// Unencrypted secret key. Can be used as-is.
2029    Unencrypted(Unencrypted),
2030    /// The secret key is encrypted with a password.
2031    Encrypted(Encrypted),
2032}
2033
2034assert_send_and_sync!(SecretKeyMaterial);
2035
2036impl From<mpi::SecretKeyMaterial> for SecretKeyMaterial {
2037    fn from(mpis: mpi::SecretKeyMaterial) -> Self {
2038        SecretKeyMaterial::Unencrypted(mpis.into())
2039    }
2040}
2041
2042impl From<Unencrypted> for SecretKeyMaterial {
2043    fn from(key: Unencrypted) -> Self {
2044        SecretKeyMaterial::Unencrypted(key)
2045    }
2046}
2047
2048impl From<Encrypted> for SecretKeyMaterial {
2049    fn from(key: Encrypted) -> Self {
2050        SecretKeyMaterial::Encrypted(key)
2051    }
2052}
2053
2054impl SecretKeyMaterial {
2055    /// Decrypts the secret key material using `password`.
2056    ///
2057    /// The `SecretKeyMaterial` type does not know what kind of key it
2058    /// contains.  So, in order to know how many MPIs to parse, the
2059    /// public key algorithm needs to be provided explicitly.
2060    ///
2061    /// This returns an error if the secret key material is not
2062    /// encrypted or the password is incorrect.
2063    pub fn decrypt<P, R>(mut self,
2064                         key: &Key<P, R>,
2065                         password: &Password)
2066                         -> Result<Self>
2067    where
2068        P: KeyParts,
2069        R: KeyRole,
2070    {
2071        self.decrypt_in_place(key, password)?;
2072        Ok(self)
2073    }
2074
2075    /// Decrypts the secret key material using `password`.
2076    ///
2077    /// The `SecretKeyMaterial` type does not know what kind of key it
2078    /// contains.  So, in order to know how many MPIs to parse, the
2079    /// public key algorithm needs to be provided explicitly.
2080    ///
2081    /// This returns an error if the secret key material is not
2082    /// encrypted or the password is incorrect.
2083    pub fn decrypt_in_place<P, R>(&mut self,
2084                                  key: &Key<P, R>,
2085                                  password: &Password)
2086                                  -> Result<()>
2087    where
2088        P: KeyParts,
2089        R: KeyRole,
2090    {
2091        match self {
2092            SecretKeyMaterial::Encrypted(e) => {
2093                *self = e.decrypt(key, password)?.into();
2094                Ok(())
2095            }
2096            SecretKeyMaterial::Unencrypted(_) =>
2097                Err(Error::InvalidArgument(
2098                    "secret key is not encrypted".into()).into()),
2099        }
2100    }
2101
2102    /// Encrypts the secret key material using `password`.
2103    ///
2104    /// This returns an error if the secret key material is encrypted.
2105    ///
2106    /// See [`Unencrypted::encrypt`] for details.
2107    pub fn encrypt<P, R>(mut self,
2108                         key: &Key<P, R>,
2109                         password: &Password)
2110                         -> Result<Self>
2111    where
2112        P: KeyParts,
2113        R: KeyRole,
2114    {
2115        self.encrypt_in_place(key, password)?;
2116        Ok(self)
2117    }
2118
2119    /// Encrypts the secret key material using `password` with the
2120    /// given parameters.
2121    ///
2122    /// This returns an error if the secret key material is encrypted.
2123    ///
2124    /// See [`Unencrypted::encrypt_with`] for details.
2125    pub fn encrypt_with<P, R>(mut self,
2126                              key: &Key<P, R>,
2127                              s2k: S2K,
2128                              symm: SymmetricAlgorithm,
2129                              aead: Option<AEADAlgorithm>,
2130                              password: &Password)
2131                              -> Result<Self>
2132    where
2133        P: KeyParts,
2134        R: KeyRole,
2135    {
2136        self.encrypt_in_place_with(key, s2k, symm, aead, password)?;
2137        Ok(self)
2138    }
2139
2140    /// Encrypts the secret key material using `password`.
2141    ///
2142    /// This returns an error if the secret key material is encrypted.
2143    ///
2144    /// See [`Unencrypted::encrypt`] for details.
2145    pub fn encrypt_in_place<P, R>(&mut self,
2146                                  key: &Key<P, R>,
2147                                  password: &Password)
2148                                  -> Result<()>
2149    where
2150        P: KeyParts,
2151        R: KeyRole,
2152    {
2153        match self {
2154            SecretKeyMaterial::Unencrypted(ref u) => {
2155                *self = SecretKeyMaterial::Encrypted(
2156                    u.encrypt(key, password)?);
2157                Ok(())
2158            }
2159            SecretKeyMaterial::Encrypted(_) =>
2160                Err(Error::InvalidArgument(
2161                    "secret key is encrypted".into()).into()),
2162        }
2163    }
2164
2165    /// Encrypts the secret key material using `password` and the
2166    /// given parameters.
2167    ///
2168    /// This returns an error if the secret key material is encrypted.
2169    ///
2170    /// See [`Unencrypted::encrypt`] for details.
2171    pub fn encrypt_in_place_with<P, R>(&mut self,
2172                                       key: &Key<P, R>,
2173                                       s2k: S2K,
2174                                       symm: SymmetricAlgorithm,
2175                                       aead: Option<AEADAlgorithm>,
2176                                       password: &Password)
2177                                       -> Result<()>
2178    where
2179        P: KeyParts,
2180        R: KeyRole,
2181    {
2182        match self {
2183            SecretKeyMaterial::Unencrypted(ref u) => {
2184                *self = SecretKeyMaterial::Encrypted(
2185                    u.encrypt_with(key, s2k, symm, aead, password)?);
2186                Ok(())
2187            }
2188            SecretKeyMaterial::Encrypted(_) =>
2189                Err(Error::InvalidArgument(
2190                    "secret key is encrypted".into()).into()),
2191        }
2192    }
2193
2194    /// Returns whether the secret key material is encrypted.
2195    pub fn is_encrypted(&self) -> bool {
2196        match self {
2197            SecretKeyMaterial::Encrypted(_) => true,
2198            SecretKeyMaterial::Unencrypted(_) => false,
2199        }
2200    }
2201}
2202
2203/// Unencrypted secret key material.
2204///
2205/// This data structure is used by the [`SecretKeyMaterial`] enum.
2206///
2207/// Unlike an [`Encrypted`] key, this key can be used as-is.
2208///
2209/// The secret key is encrypted in memory and only decrypted on
2210/// demand.  This helps protect against [heartbleed]-style
2211/// attacks where a buffer over-read allows an attacker to read from
2212/// the process's address space.  This protection is less important
2213/// for Rust programs, which are memory safe.  However, it is
2214/// essential when Sequoia is used via its FFI.
2215///
2216/// See [`crypto::mem::Encrypted`] for details.
2217///
2218/// [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed
2219/// [`crypto::mem::Encrypted`]: super::super::crypto::mem::Encrypted
2220// Note: PartialEq, Eq, and Hash on mem::Encrypted does the right
2221// thing.
2222#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2223pub struct Unencrypted {
2224    /// MPIs of the secret key.
2225    mpis: mem::Encrypted,
2226}
2227
2228assert_send_and_sync!(Unencrypted);
2229
2230impl From<mpi::SecretKeyMaterial> for Unencrypted {
2231    fn from(mpis: mpi::SecretKeyMaterial) -> Self {
2232        use crate::serialize::MarshalInto;
2233        // We need to store the type.
2234        let mut plaintext = mem::Protected::new(1 + mpis.serialized_len());
2235        plaintext[0] =
2236            mpis.algo().unwrap_or(PublicKeyAlgorithm::Unknown(0)).into();
2237
2238        mpis.serialize_into(&mut plaintext[1..])
2239            .expect("MPI serialization to vec failed");
2240        Unencrypted {
2241            mpis: mem::Encrypted::new(plaintext)
2242                .expect("encrypting memory failed"),
2243        }
2244    }
2245}
2246
2247impl Unencrypted {
2248    /// Maps the given function over the secret.
2249    pub fn map<F, T>(&self, fun: F) -> T
2250        where F: FnOnce(&mpi::SecretKeyMaterial) -> T
2251    {
2252        self.mpis.map(|plaintext| {
2253            let algo: PublicKeyAlgorithm = plaintext[0].into();
2254            let mpis = mpi::SecretKeyMaterial::from_bytes(algo, &plaintext[1..])
2255                .expect("Decrypted secret key is malformed");
2256            fun(&mpis)
2257        })
2258    }
2259
2260    /// Encrypts the secret key material using `password`.
2261    ///
2262    /// This encrypts the secret key material using AES-128/OCB and a
2263    /// key derived from the `password` using the default [`S2K`]
2264    /// scheme.
2265    pub fn encrypt<P, R>(&self,
2266                         key: &Key<P, R>,
2267                         password: &Password)
2268                         -> Result<Encrypted>
2269    where
2270        P: KeyParts,
2271        R: KeyRole,
2272    {
2273        // Pick sensible parameters according to the key version.
2274        let (s2k, symm, aead) = match key.version() {
2275            6 => (
2276                S2K::default(),
2277                SymmetricAlgorithm::AES128,
2278                Some(AEADAlgorithm::OCB),
2279            ),
2280
2281            _ => (
2282                S2K::default(),
2283                SymmetricAlgorithm::default(),
2284                None,
2285            ),
2286        };
2287
2288        self.encrypt_with(key, s2k, symm, aead, password)
2289    }
2290
2291    /// Encrypts the secret key material using `password` and the
2292    /// given parameters.
2293    pub fn encrypt_with<P, R>(&self,
2294                              key: &Key<P, R>,
2295                              s2k: S2K,
2296                              symm: SymmetricAlgorithm,
2297                              aead: Option<AEADAlgorithm>,
2298                              password: &Password)
2299                              -> Result<Encrypted>
2300    where
2301        P: KeyParts,
2302        R: KeyRole,
2303    {
2304        use std::io::Write;
2305        use crate::crypto::symmetric::Encryptor;
2306
2307        let derived_key = s2k.derive_key(password, symm.key_size()?)?;
2308        let checksum = Default::default();
2309
2310        constrain_encryption_methods(key, &s2k, symm, aead, Some(checksum))?;
2311
2312        if matches!(s2k, S2K::Argon2 { .. }) && aead.is_none() {
2313            return Err(Error::InvalidOperation(
2314                "Argon2 MUST be used with an AEAD mode".into()).into());
2315        }
2316
2317        if let Some(aead) = aead {
2318            use crate::serialize::MarshalInto;
2319
2320            let mut iv = vec![0; aead.nonce_size()?];
2321            crypto::random(&mut iv)?;
2322
2323            let schedule = Key253Schedule::new(
2324                match key.role() {
2325                    KeyRoleRT::Primary => Tag::SecretKey,
2326                    KeyRoleRT::Subordinate => Tag::SecretSubkey,
2327                    KeyRoleRT::Unspecified =>
2328                        return Err(Error::InvalidOperation(
2329                            "cannot encrypt key with unspecified role".into()).into()),
2330                },
2331                key.parts_as_public(), derived_key, symm, aead, &iv)?;
2332            let mut enc = schedule.encryptor()?;
2333
2334            // Encrypt the secret key.
2335            let esk = self.map(|mpis| -> Result<Vec<u8>> {
2336                let mut esk =
2337                    vec![0; mpis.serialized_len() + aead.digest_size()?];
2338                let secret = mpis.to_vec()?;
2339                enc.encrypt_seal(&mut esk, &secret)?;
2340                Ok(esk)
2341            })?;
2342
2343            Ok(Encrypted::new_aead(s2k, symm, aead, iv.into_boxed_slice(),
2344                                   esk.into_boxed_slice()))
2345        } else {
2346            use crypto::symmetric::{
2347                BlockCipherMode,
2348                PaddingMode,
2349            };
2350
2351            // Ciphertext is preceded by a random block.
2352            let mut trash = vec![0u8; symm.block_size()?];
2353            crypto::random(&mut trash)?;
2354
2355            let mut esk = Vec::new();
2356            let mut encryptor =
2357                Encryptor::new(symm, BlockCipherMode::CFB, PaddingMode::None,
2358                               &derived_key, None, &mut esk)?;
2359            encryptor.write_all(&trash)?;
2360            self.map(|mpis| mpis.serialize_with_checksum(&mut encryptor,
2361                                                         checksum))?;
2362            drop(encryptor);
2363
2364            Ok(Encrypted::new(s2k, symm, Some(checksum),
2365                              esk.into_boxed_slice()))
2366        }
2367    }
2368}
2369
2370/// Secret key material encrypted with a password.
2371///
2372/// This data structure is used by the [`SecretKeyMaterial`] enum.
2373///
2374#[derive(Clone, Debug)]
2375pub struct Encrypted {
2376    /// Key derivation mechanism to use.
2377    s2k: S2K,
2378    /// Symmetric algorithm used to encrypt the secret key material.
2379    algo: SymmetricAlgorithm,
2380    /// AEAD algorithm and IV used to encrypt the secret key material.
2381    aead: Option<(AEADAlgorithm, Box<[u8]>)>,
2382    /// Checksum method.
2383    checksum: Option<mpi::SecretKeyChecksum>,
2384    /// Encrypted MPIs prefixed with the IV.
2385    ///
2386    /// If we recognized the S2K object during parsing, we can
2387    /// successfully parse the data into S2K, IV, and ciphertext.
2388    /// However, if we do not recognize the S2K type, we do not know
2389    /// how large its parameters are, so we cannot cleanly parse it,
2390    /// and have to accept that the S2K's body bleeds into the rest of
2391    /// the data.
2392    ciphertext: std::result::Result<(usize, // IV length
2393                                     Box<[u8]>),    // IV + ciphertext.
2394                                    Box<[u8]>>, // S2K body + IV + ciphertext.
2395}
2396
2397assert_send_and_sync!(Encrypted);
2398
2399// Because the S2K and ciphertext cannot be cleanly separated at parse
2400// time, we need to carefully compare and hash encrypted key packets.
2401
2402impl PartialEq for Encrypted {
2403    fn eq(&self, other: &Encrypted) -> bool {
2404        self.algo == other.algo
2405            && self.aead == other.aead
2406            && self.checksum == other.checksum
2407            && match (&self.ciphertext, &other.ciphertext) {
2408                (Ok(a), Ok(b)) =>
2409                    self.s2k == other.s2k && a == b,
2410                (Err(a_raw), Err(b_raw)) => {
2411                    // Treat S2K and ciphertext as opaque blob.
2412                    // XXX: This would be nicer without the allocations.
2413                    use crate::serialize::MarshalInto;
2414                    let mut a = self.s2k.to_vec().unwrap();
2415                    let mut b = other.s2k.to_vec().unwrap();
2416                    a.extend_from_slice(a_raw);
2417                    b.extend_from_slice(b_raw);
2418                    a == b
2419                },
2420                _ => false,
2421            }
2422    }
2423}
2424
2425impl Eq for Encrypted {}
2426
2427impl std::hash::Hash for Encrypted {
2428    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2429        self.algo.hash(state);
2430        self.aead.hash(state);
2431        self.checksum.hash(state);
2432        match &self.ciphertext {
2433            Ok(c) => {
2434                self.s2k.hash(state);
2435                c.hash(state);
2436            },
2437            Err(c) => {
2438                // Treat S2K and ciphertext as opaque blob.
2439                // XXX: This would be nicer without the allocations.
2440                use crate::serialize::MarshalInto;
2441                let mut a = self.s2k.to_vec().unwrap();
2442                a.extend_from_slice(c);
2443                a.hash(state);
2444            },
2445        }
2446    }
2447}
2448
2449impl Encrypted {
2450    /// Creates a new encrypted key object.
2451    pub fn new(s2k: S2K, algo: SymmetricAlgorithm,
2452               checksum: Option<mpi::SecretKeyChecksum>, ciphertext: Box<[u8]>)
2453        -> Self
2454    {
2455        Self::new_raw(s2k, algo, checksum, Ok((0, ciphertext)))
2456    }
2457
2458    /// Creates a new encrypted key object.
2459    pub fn new_aead(s2k: S2K,
2460                    sym_algo: SymmetricAlgorithm,
2461                    aead_algo: AEADAlgorithm,
2462                    aead_iv: Box<[u8]>,
2463                    ciphertext: Box<[u8]>)
2464                    -> Self
2465    {
2466        Encrypted {
2467            s2k,
2468            algo: sym_algo,
2469            aead: Some((aead_algo, aead_iv)),
2470            checksum: None,
2471            ciphertext: Ok((0, ciphertext)),
2472        }
2473    }
2474
2475    /// Creates a new encrypted key object.
2476    pub(crate) fn new_raw(s2k: S2K, algo: SymmetricAlgorithm,
2477                          checksum: Option<mpi::SecretKeyChecksum>,
2478                          ciphertext: std::result::Result<(usize, Box<[u8]>),
2479                                                          Box<[u8]>>)
2480        -> Self
2481    {
2482        Encrypted { s2k, algo, aead: None, checksum, ciphertext }
2483    }
2484
2485    /// Returns the key derivation mechanism.
2486    pub fn s2k(&self) -> &S2K {
2487        &self.s2k
2488    }
2489
2490    /// Returns the symmetric algorithm used to encrypt the secret
2491    /// key material.
2492    pub fn algo(&self) -> SymmetricAlgorithm {
2493        self.algo
2494    }
2495
2496    /// Returns the AEAD algorithm used to encrypt the secret key
2497    /// material.
2498    pub fn aead_algo(&self) -> Option<AEADAlgorithm> {
2499        self.aead.as_ref().map(|(a, _iv)| *a)
2500    }
2501
2502    /// Returns the AEAD IV used to encrypt the secret key material.
2503    pub fn aead_iv(&self) -> Option<&[u8]> {
2504        self.aead.as_ref().map(|(_a, iv)| &iv[..])
2505    }
2506
2507    /// Returns the checksum method used to protect the encrypted
2508    /// secret key material, if any.
2509    pub fn checksum(&self) -> Option<mpi::SecretKeyChecksum> {
2510        self.checksum
2511    }
2512
2513    /// Returns the encrypted secret key material.
2514    ///
2515    /// If the [`S2K`] mechanism is not supported by Sequoia, this
2516    /// function will fail.  Note that the information is not lost,
2517    /// but stored in the packet.  If the packet is serialized again,
2518    /// it is written out.
2519    ///
2520    ///   [`S2K`]: super::super::crypto::S2K
2521    pub fn ciphertext(&self) -> Result<&[u8]> {
2522        self.ciphertext
2523            .as_ref()
2524            .map(|(_cfb_iv_len, ciphertext)| &ciphertext[..])
2525            .map_err(|_| Error::MalformedPacket(
2526                format!("Unknown S2K: {:?}", self.s2k)).into())
2527    }
2528
2529    /// Returns the encrypted secret key material, possibly including
2530    /// the body of the S2K object.
2531    pub(crate) fn raw_ciphertext(&self) -> &[u8] {
2532        match self.ciphertext.as_ref() {
2533            Ok((_cfb_iv_len, ciphertext)) => &ciphertext[..],
2534            Err(s2k_ciphertext) => &s2k_ciphertext[..],
2535        }
2536    }
2537
2538    /// Returns the length of the CFB IV, if used.
2539    ///
2540    /// In v6 key packets, we explicitly model the length of the IV,
2541    /// but in Sequoia we store the IV and the ciphertext as one
2542    /// block, due to how bad this was modeled in v4 key packets.
2543    /// However, now that our in-core representation is less precise
2544    /// to support v4, we need to track this length to uphold our
2545    /// equality guarantee.
2546    pub(crate) fn cfb_iv_len(&self) -> usize {
2547        self.ciphertext.as_ref().ok()
2548            .map(|(cfb_iv_len, _)| *cfb_iv_len)
2549            .unwrap_or(0)
2550    }
2551
2552    /// Decrypts the secret key material using `password`.
2553    ///
2554    /// The `Encrypted` key does not know what kind of key it is, so
2555    /// the public key algorithm is needed to parse the correct number
2556    /// of MPIs.
2557    pub fn decrypt<P, R>(&self, key: &Key<P, R>, password: &Password)
2558                         -> Result<Unencrypted>
2559    where
2560        P: KeyParts,
2561        R: KeyRole,
2562    {
2563        use std::io::Read;
2564        use crate::crypto;
2565
2566        constrain_encryption_methods(
2567            key, &self.s2k, self.algo,self.aead.as_ref().map(|(a, _)| *a),
2568            self.checksum)?;
2569
2570        let derived_key = self.s2k.derive_key(password, self.algo.key_size()?)?;
2571        let ciphertext = self.ciphertext()?;
2572
2573        if let Some((aead, iv)) = &self.aead {
2574            let schedule = Key253Schedule::new(
2575                match key.role() {
2576                    KeyRoleRT::Primary => Tag::SecretKey,
2577                    KeyRoleRT::Subordinate => Tag::SecretSubkey,
2578                    KeyRoleRT::Unspecified =>
2579                        return Err(Error::InvalidOperation(
2580                            "cannot decrypt key with unspecified role".into()).into()),
2581                },
2582                key.parts_as_public(), derived_key, self.algo, *aead, iv)?;
2583            let mut dec = schedule.decryptor()?;
2584
2585            // Read the secret key.
2586            let mut secret = mem::Protected::new(
2587                ciphertext.len().saturating_sub(aead.digest_size()?));
2588            dec.decrypt_verify(&mut secret, ciphertext)?;
2589
2590            mpi::SecretKeyMaterial::from_bytes(
2591                key.pk_algo(), &secret).map(|m| m.into())
2592        } else {
2593            use crypto::symmetric::{
2594                BlockCipherMode,
2595                UnpaddingMode,
2596            };
2597
2598            let cur = buffered_reader::Memory::with_cookie(
2599                ciphertext, Default::default());
2600            let mut dec =
2601                crypto::symmetric::InternalDecryptor::new(
2602                    self.algo,
2603                    BlockCipherMode::CFB,
2604                    UnpaddingMode::None,
2605                    &derived_key,
2606                    None,
2607                    cur)?;
2608
2609            // Consume the first block.
2610            let block_size = self.algo.block_size()?;
2611            let mut trash = mem::Protected::new(block_size);
2612            dec.read_exact(&mut trash)?;
2613
2614            // Read the secret key.
2615            let mut secret = mem::Protected::new(ciphertext.len() - block_size);
2616            dec.read_exact(&mut secret)?;
2617
2618            mpi::SecretKeyMaterial::from_bytes_with_checksum(
2619                key.pk_algo(), &secret, self.checksum.unwrap_or_default())
2620                .map(|m| m.into())
2621        }
2622    }
2623}
2624
2625/// Constrains the secret key material encryption methods according to
2626/// [Section 3.7.2.1. of RFC 9580].
2627///
2628/// [Section 3.7.2.1. of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7.2.1
2629fn constrain_encryption_methods<P, R>(key: &Key<P, R>,
2630                                      s2k: &S2K,
2631                                      _symm: SymmetricAlgorithm,
2632                                      aead: Option<AEADAlgorithm>,
2633                                      checksum: Option<mpi::SecretKeyChecksum>)
2634                                      -> Result<()>
2635where
2636    P: KeyParts,
2637    R: KeyRole,
2638{
2639    #[allow(deprecated)]
2640    match s2k {
2641        S2K::Argon2 { .. } if aead.is_none() =>
2642            Err(Error::InvalidOperation(
2643                "Argon2 MUST be used with an AEAD mode".into()).into()),
2644
2645        S2K::Implicit if key.version() == 6 =>
2646            Err(Error::InvalidOperation(
2647                "Implicit S2K MUST NOT be used with v6 keys".into()).into()),
2648
2649        // Technically not forbidden, but this is a terrible idea and
2650        // I doubt that anyone depends on it.  Let's see whether we
2651        // can get away with being strict here.
2652        S2K::Simple { .. } if key.version() == 6 =>
2653            Err(Error::InvalidOperation(
2654                "Simple S2K SHOULD NOT be used with v6 keys".into()).into()),
2655
2656        _ if key.version() == 6 && aead.is_none()
2657            && checksum != Some(mpi::SecretKeyChecksum::SHA1) =>
2658            Err(Error::InvalidOperation(
2659                "Malleable CFB MUST NOT be used with v6 keys".into()).into()),
2660
2661        _ => Ok(()),
2662    }
2663}
2664
2665pub(crate) struct Key253Schedule<'a> {
2666    symm: SymmetricAlgorithm,
2667    aead: AEADAlgorithm,
2668    nonce: &'a [u8],
2669    kek: SessionKey,
2670    ad: Vec<u8>
2671}
2672
2673impl<'a> Key253Schedule<'a> {
2674    fn new<R>(tag: Tag,
2675              key: &Key<PublicParts, R>,
2676              derived_key: SessionKey,
2677              symm: SymmetricAlgorithm,
2678              aead: AEADAlgorithm,
2679              nonce: &'a [u8])
2680              -> Result<Self>
2681    where
2682        R: KeyRole,
2683    {
2684        use crate::serialize::{Marshal, MarshalInto};
2685        use crate::crypto::backend::{Backend, interface::Kdf};
2686
2687        let info = [
2688            0b1100_0000 | u8::from(tag), // Canonicalized packet type.
2689            key.version(),
2690            symm.into(),
2691            aead.into(),
2692        ];
2693        let mut kek = vec![0; symm.key_size()?].into();
2694        Backend::hkdf_sha256(&derived_key, None, &info, &mut kek)?;
2695
2696        let mut ad = Vec::with_capacity(key.serialized_len());
2697        ad.push(0b1100_0000 | u8::from(tag)); // Canonicalized packet type.
2698        key.serialize(&mut ad)?;
2699
2700        Ok(Self {
2701            symm,
2702            aead,
2703            nonce,
2704            kek,
2705            ad,
2706        })
2707    }
2708
2709    fn decryptor(&self) -> Result<crypto::aead::DecryptionContext> {
2710        self.aead.context(self.symm, &self.kek, &self.ad, self.nonce)?
2711            .for_decryption()
2712    }
2713
2714    fn encryptor(&self) -> Result<crypto::aead::EncryptionContext> {
2715        self.aead.context(self.symm, &self.kek, &self.ad, self.nonce)?
2716            .for_encryption()
2717    }
2718}
2719
2720#[cfg(test)]
2721mod tests {
2722    use crate::packet::Key;
2723    use crate::Cert;
2724    use crate::packet::key::SecretKeyMaterial;
2725    use crate::packet::Packet;
2726    use super::*;
2727    use crate::parse::Parse;
2728    use crate::SignatureType;
2729    use crate::crypto::mpi::PublicKey;
2730
2731    #[test]
2732    fn encrypted_rsa_key() {
2733        let cert = Cert::from_bytes(
2734            crate::tests::key("testy-new-encrypted-with-123.pgp")).unwrap();
2735        let key = cert.primary_key().key().clone();
2736        let (key, secret) = key.take_secret();
2737        let mut secret = secret.unwrap();
2738
2739        assert!(secret.is_encrypted());
2740        secret.decrypt_in_place(&key, &"123".into()).unwrap();
2741        assert!(!secret.is_encrypted());
2742        let (pair, _) = key.add_secret(secret);
2743        assert!(pair.has_unencrypted_secret());
2744
2745        match pair.secret() {
2746            SecretKeyMaterial::Unencrypted(ref u) => u.map(|mpis| match mpis {
2747                mpi::SecretKeyMaterial::RSA { .. } => (),
2748                _ => panic!(),
2749            }),
2750            _ => panic!(),
2751        }
2752    }
2753
2754    #[test]
2755    fn signature_roundtrip() {
2756        let gen_v4_rsa = |bits: usize| -> Key<key::SecretParts, key::PrimaryRole> {
2757            Key4::generate_rsa(bits)
2758                .expect("Can generate a v4 RSA key")
2759                .into()
2760        };
2761        let gen_v6_rsa = |bits: usize| -> Key<_, _> {
2762            Key6::generate_rsa(bits)
2763                .expect("Can generate a v6 RSA key")
2764                .into()
2765        };
2766        // Disabled: see below.
2767        //let gen_v4_dsa = |bits: usize| -> Key<_, _> {
2768        //    Key4::generate_dsa(bits)
2769        //        .expect("Can generate a v4 DSA key")
2770        //        .into()
2771        //};
2772        let gen_v4_curve = |curve: Curve| -> Key<_, _> {
2773            Key4::generate_ecc(true, curve.clone())
2774                .unwrap_or_else(|_| panic!("Can generate a v4 {:?}", curve))
2775                .into()
2776        };
2777        let gen_v6_curve = |curve: Curve| -> Key<_, _> {
2778            Key6::generate_ecc(true, curve.clone())
2779                .unwrap_or_else(|_| panic!("Can generate a v6 {:?}", curve))
2780                .into()
2781        };
2782        let gen_v4_ed25519 = || -> Key<_, _> {
2783            Key4::generate_ed25519()
2784                .expect("Can generate a v4 Ed25519 key")
2785                .into()
2786        };
2787        let gen_v6_ed25519 = || -> Key<_, _> {
2788            Key6::generate_ed25519()
2789                .expect("Can generate a v6 Ed25519 key")
2790                .into()
2791        };
2792        let gen_v4_ed448 = || -> Key<_, _> {
2793            Key4::generate_ed448()
2794                .expect("Can generate a v4 Ed448 key")
2795                .into()
2796        };
2797        let gen_v6_ed448 = || -> Key<_, _> {
2798            Key6::generate_ed448()
2799                .expect("Can generate a v6 Ed448 key")
2800                .into()
2801        };
2802        let gen_v6_mldsa65_ed25519 = || -> Key<_, _> {
2803            Key6::generate_mldsa65_ed25519()
2804                .expect("Can generate a v6 ML-DSA-65+Ed25519 key")
2805                .into()
2806        };
2807        let gen_v6_mldsa87_ed448 = || -> Key<_, _> {
2808            Key6::generate_mldsa87_ed448()
2809                .expect("Can generate a v6 ML-DSA-87+Ed448 key")
2810                .into()
2811        };
2812        let gen_v6_slhdsa128s = || -> Key<_, _> {
2813            Key6::generate_slhdsa128s()
2814                .expect("Can generate a v6 SLH-DSA-128s key")
2815                .into()
2816        };
2817        let gen_v6_slhdsa128f = || -> Key<_, _> {
2818            Key6::generate_slhdsa128f()
2819                .expect("Can generate a v6 SLH-DSA-128f key")
2820                .into()
2821        };
2822        let gen_v6_slhdsa256s = || -> Key<_, _> {
2823            Key6::generate_slhdsa256s()
2824                .expect("Can generate a v6 SLH-DSA-256s key")
2825                .into()
2826        };
2827
2828        #[allow(deprecated)]
2829        for (algo, curve, profile, gen) in [
2830            // RSA
2831            (PublicKeyAlgorithm::RSAEncryptSign, None, 4,
2832             Box::new(|| gen_v4_rsa(2048)) as Box<dyn Fn () -> _>),
2833            (PublicKeyAlgorithm::RSAEncryptSign, None, 4,
2834             Box::new(|| gen_v4_rsa(3072)) as Box<dyn Fn () -> _>),
2835            (PublicKeyAlgorithm::RSAEncryptSign, None, 4,
2836             Box::new(|| gen_v4_rsa(4096)) as Box<dyn Fn () -> _>),
2837            (PublicKeyAlgorithm::RSAEncryptSign, None, 6,
2838             Box::new(|| gen_v6_rsa(2048))),
2839            (PublicKeyAlgorithm::RSAEncryptSign, None, 6,
2840             Box::new(|| gen_v6_rsa(3072))),
2841            (PublicKeyAlgorithm::RSAEncryptSign, None, 6,
2842             Box::new(|| gen_v6_rsa(4096))),
2843
2844            // DSA
2845            //
2846            // DSA is deprecated.
2847            //
2848            // Disabled, because DSA generation doesn't work on
2849            // Windows, but PublicKeyAlgorithm::DSA.is_supported()
2850            // returns true.  This is because CNG does support signing
2851            // and verification.
2852            //(PublicKeyAlgorithm::DSA, None, 4,
2853            // Box::new(|| gen_v4_dsa(2048)) as Box<dyn Fn () -> _>),
2854            //(PublicKeyAlgorithm::DSA, None, 4,
2855            // Box::new(|| gen_v4_dsa(3072)) as Box<dyn Fn () -> _>),
2856
2857            // EdDSA 25519.
2858            //
2859            // Note: EdDSA Ed25519 is deprecated for v6.
2860            (PublicKeyAlgorithm::EdDSA, Some(Curve::Ed25519), 4,
2861             Box::new(|| gen_v4_curve(Curve::Ed25519))),
2862
2863            // Modern Ed25519.
2864            (PublicKeyAlgorithm::Ed25519, None, 4,
2865             Box::new(gen_v4_ed25519)),
2866            (PublicKeyAlgorithm::Ed25519, None, 6,
2867             Box::new(gen_v6_ed25519)),
2868
2869            // Ed448.
2870            (PublicKeyAlgorithm::Ed448, None, 4,
2871             Box::new(gen_v4_ed448)),
2872            (PublicKeyAlgorithm::Ed448, None, 6,
2873             Box::new(gen_v6_ed448)),
2874
2875            // Nist.
2876            (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP256), 4,
2877             Box::new(|| gen_v4_curve(Curve::NistP256))),
2878            (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP256), 6,
2879             Box::new(|| gen_v6_curve(Curve::NistP256))),
2880            (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP384), 4,
2881             Box::new(|| gen_v4_curve(Curve::NistP384))),
2882            (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP384), 6,
2883             Box::new(|| gen_v6_curve(Curve::NistP384))),
2884            (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP521), 4,
2885             Box::new(|| gen_v4_curve(Curve::NistP521))),
2886            (PublicKeyAlgorithm::ECDSA, Some(Curve::NistP521), 6,
2887             Box::new(|| gen_v6_curve(Curve::NistP521))),
2888
2889            // Brainpool.
2890            (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP256), 4,
2891             Box::new(|| gen_v4_curve(Curve::BrainpoolP256))),
2892            (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP256), 6,
2893             Box::new(|| gen_v6_curve(Curve::BrainpoolP256))),
2894            (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP384), 4,
2895             Box::new(|| gen_v4_curve(Curve::BrainpoolP384))),
2896            (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP384), 6,
2897             Box::new(|| gen_v6_curve(Curve::BrainpoolP384))),
2898            (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP512), 4,
2899             Box::new(|| gen_v4_curve(Curve::BrainpoolP512))),
2900            (PublicKeyAlgorithm::ECDSA, Some(Curve::BrainpoolP512), 6,
2901             Box::new(|| gen_v6_curve(Curve::BrainpoolP512))),
2902
2903            // PQC signing algorithms (v6 only).
2904            (PublicKeyAlgorithm::MLDSA65_Ed25519, None, 6,
2905             Box::new(gen_v6_mldsa65_ed25519)),
2906            (PublicKeyAlgorithm::MLDSA87_Ed448, None, 6,
2907             Box::new(gen_v6_mldsa87_ed448)),
2908            (PublicKeyAlgorithm::SLHDSA128s, None, 6,
2909             Box::new(gen_v6_slhdsa128s)),
2910            (PublicKeyAlgorithm::SLHDSA128f, None, 6,
2911             Box::new(gen_v6_slhdsa128f)),
2912            (PublicKeyAlgorithm::SLHDSA256s, None, 6,
2913             Box::new(gen_v6_slhdsa256s)),
2914        ]
2915        {
2916            eprintln!("Checking algo: {}, curve: {:?}, profile: {}.",
2917                      algo, curve, profile);
2918            if ! algo.is_supported() {
2919                eprintln!("Algorithm {} not supported, skipping test.",
2920                          algo);
2921                continue;
2922            }
2923
2924            if let Some(curve) = curve.as_ref() {
2925                if ! curve.is_supported() {
2926                    eprintln!("Curve {:?} not supported, skipping test.",
2927                              curve);
2928                    continue;
2929                }
2930            }
2931
2932            let key = gen();
2933
2934            // Make sure we got the right type of key.
2935            assert_eq!(algo, key.pk_algo(),
2936                       "\n\
2937                        algo expected: {:?} ({})\n\
2938                        algo got:      {:?} ({})",
2939                       algo, u8::from(algo),
2940                       key.pk_algo(), u8::from(key.pk_algo()));
2941
2942            let got_curve = match key.mpis() {
2943                PublicKey::EdDSA { curve, .. }
2944                | PublicKey::ECDSA { curve, .. }
2945                | PublicKey::ECDH { curve, .. } =>
2946                {
2947                    Some(curve.clone())
2948                }
2949                _ => None,
2950            };
2951            assert_eq!(curve, got_curve,
2952                       "\n\
2953                        curve expected: {:?}\n\
2954                        curve got:      {:?}",
2955                       curve, got_curve);
2956
2957            assert_eq!(profile, key.version(),
2958                       "\n\
2959                        profile expected: {:?}\n\
2960                        profile got:      {:?}",
2961                       profile, key.version());
2962
2963            let mut pair = key.clone().into_keypair().unwrap();
2964            let hash = HashAlgorithm::default();
2965
2966            // Sign.
2967            let ctx = hash.context().unwrap().for_signature(profile);
2968            let sig = SignatureBuilder::new(SignatureType::Binary)
2969                .sign_hash(&mut pair, ctx).unwrap();
2970
2971            // Verify.
2972            let ctx = hash.context().unwrap().for_signature(profile);
2973            sig.verify_hash(&key, ctx).unwrap();
2974
2975            // Verify that a wrong digest is rejected.
2976            let mut ctx = hash.context().unwrap().for_signature(profile);
2977            ctx.update(b"tampered");
2978            assert!(sig.verify_hash(&key, ctx).is_err(),
2979                    "Tampered {:?} v{} signature should be rejected",
2980                    algo, profile);
2981        }
2982    }
2983
2984    #[test]
2985    fn primary_key_encrypt_decrypt() -> Result<()> {
2986        key_encrypt_decrypt::<PrimaryRole>()
2987    }
2988
2989    #[test]
2990    fn subkey_encrypt_decrypt() -> Result<()> {
2991        key_encrypt_decrypt::<SubordinateRole>()
2992    }
2993
2994    fn key_encrypt_decrypt<R>() -> Result<()>
2995    where
2996        R: KeyRole + PartialEq,
2997    {
2998        let mut g = quickcheck::Gen::new(256);
2999        let p: Password = Vec::<u8>::arbitrary(&mut g).into();
3000
3001        let check = |key: Key<SecretParts, R>| -> Result<()> {
3002            let encrypted = key.clone().encrypt_secret(&p)?;
3003            let decrypted = encrypted.decrypt_secret(&p)?;
3004            assert_eq!(key, decrypted);
3005            Ok(())
3006        };
3007
3008        use crate::types::Curve::*;
3009        for curve in vec![NistP256, NistP384, NistP521, Ed25519] {
3010            if ! curve.is_supported() {
3011                eprintln!("Skipping unsupported {}", curve);
3012                continue;
3013            }
3014
3015            let key: Key4<_, R>
3016                = Key4::generate_ecc(true, curve.clone())?;
3017            check(key.into())?;
3018
3019            let key: Key6<_, R>
3020                = Key6::generate_ecc(true, curve.clone())?;
3021            check(key.into())?;
3022        }
3023
3024        for bits in vec![2048, 3072] {
3025            if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
3026                eprintln!("Skipping unsupported RSA");
3027                continue;
3028            }
3029
3030            let key: Key4<_, R>
3031                = Key4::generate_rsa(bits)?;
3032            check(key.into())?;
3033
3034            let key: Key6<_, R>
3035                = Key6::generate_rsa(bits)?;
3036            check(key.into())?;
3037        }
3038
3039        Ok(())
3040    }
3041
3042    quickcheck! {
3043        fn roundtrip_public(p: Key<PublicParts, UnspecifiedRole>) -> bool {
3044            use crate::parse::Parse;
3045            use crate::serialize::MarshalInto;
3046            let buf = p.to_vec().expect("Failed to serialize key");
3047            let q = Key::from_bytes(&buf).expect("Failed to parse key").into();
3048            assert_eq!(p, q);
3049            true
3050        }
3051    }
3052
3053    #[test]
3054    fn public_serialization_drops_secret_material() -> Result<()> {
3055        use crate::serialize::Serialize;
3056
3057        let (cert, _) = CertBuilder::new().generate()?;
3058        let pk = cert.primary_key().key();
3059        assert!(pk.has_secret());
3060
3061        let public = pk.parts_as_public();
3062
3063        let mut bytes = Vec::new();
3064        Packet::from(public.clone()).serialize(&mut bytes)?;
3065
3066        let p = Packet::from_bytes(&bytes)?;
3067        match p {
3068            Packet::PublicKey(key) => assert!(!key.has_secret()),
3069            _ => panic!("expected a public key packet"),
3070        }
3071
3072        Ok(())
3073    }
3074
3075    quickcheck! {
3076        fn roundtrip_secret(p: Key<SecretParts, PrimaryRole>) -> bool {
3077            use crate::parse::Parse;
3078            use crate::serialize::MarshalInto;
3079            let buf = p.to_vec().expect("Failed to serialize key");
3080            let q = Key::from_bytes(&buf).expect("Failed to parse key")
3081                .parts_into_secret().expect("No secret material")
3082                .role_into_primary();
3083            assert_eq!(p, q);
3084            true
3085        }
3086    }
3087
3088    #[test]
3089    fn parts_as_public_does_not_remove_secret_material() -> Result<()> {
3090        let (cert, _) = CertBuilder::new().generate()?;
3091        let pk = cert.primary_key().key();
3092        assert!(pk.has_secret());
3093
3094        let sk = pk.parts_as_secret()?;
3095        let public = sk.parts_as_public();
3096
3097        assert!(public.has_secret());
3098        Ok(())
3099    }
3100
3101    fn mutate_eq_discriminates_key<P, R>(key: Key<P, R>, i: usize) -> bool
3102        where P: KeyParts,
3103              R: KeyRole,
3104              Key<P, R>: Into<Packet>,
3105    {
3106        use crate::serialize::MarshalInto;
3107        let p: Packet = key.into();
3108        let mut buf = p.to_vec().unwrap();
3109        // Avoid first two bytes so that we don't change the
3110        // type and reduce the chance of changing the length.
3111        if buf.len() < 3 { return true; }
3112        let bit = i % ((buf.len() - 2) * 8) + 16;
3113        buf[bit / 8] ^= 1 << (bit % 8);
3114        let ok = match Packet::from_bytes(&buf) {
3115            Ok(q) => p != q,
3116            Err(_) => true, // Packet failed to parse.
3117        };
3118        if ! ok {
3119            eprintln!("mutate_eq_discriminates_key for ({:?}, {})", p, i);
3120        }
3121        ok
3122    }
3123
3124    // Given a packet and a position, induces a bit flip in the
3125    // serialized form, then checks that PartialEq detects that.
3126    // Recall that for packets, PartialEq is defined using the
3127    // serialized form.
3128    quickcheck! {
3129        fn mutate_eq_discriminates_pp(key: Key<PublicParts, PrimaryRole>,
3130                                      i: usize) -> bool {
3131            mutate_eq_discriminates_key(key, i)
3132        }
3133    }
3134    quickcheck! {
3135        fn mutate_eq_discriminates_ps(key: Key<PublicParts, SubordinateRole>,
3136                                      i: usize) -> bool {
3137            mutate_eq_discriminates_key(key, i)
3138        }
3139    }
3140    quickcheck! {
3141        fn mutate_eq_discriminates_sp(key: Key<SecretParts, PrimaryRole>,
3142                                      i: usize) -> bool {
3143            mutate_eq_discriminates_key(key, i)
3144        }
3145    }
3146    quickcheck! {
3147        fn mutate_eq_discriminates_ss(key: Key<SecretParts, SubordinateRole>,
3148                                      i: usize) -> bool {
3149            mutate_eq_discriminates_key(key, i)
3150        }
3151    }
3152}