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            RSASign | DSA | ECDSA | EdDSA | Ed25519 | Ed448 =>
1793                Err(Error::InvalidOperation(
1794                    format!("{} is not an encryption algorithm", self.pk_algo())
1795                ).into()),
1796
1797            ECDH if matches!(self.mpis(),
1798                             PublicKey::ECDH { curve: Curve::Cv25519, ..}) =>
1799            {
1800                let q = match self.mpis() {
1801                    PublicKey::ECDH { q, .. } => q,
1802                    _ => unreachable!(),
1803                };
1804
1805                // Obtain the authenticated recipient public key R
1806                let R = q.decode_point(&Curve::Cv25519)?.0;
1807
1808                // Generate an ephemeral key pair {v, V=vG}
1809                // Compute the public key.
1810                let (v, VB) = Backend::x25519_generate_key()?;
1811                let VB = mpi::MPI::new_compressed_point(&VB);
1812
1813                // Compute the shared point S = vR;
1814                let S = Backend::x25519_shared_point(&v, R.try_into()?)?;
1815
1816                crate::crypto::ecdh::encrypt_wrap(
1817                    self.parts_as_public().role_as_subordinate(), data, VB, &S)
1818            },
1819
1820            RSAEncryptSign | RSAEncrypt |
1821            ElGamalEncrypt | ElGamalEncryptSign |
1822            ECDH |
1823            Private(_) | Unknown(_) => self.encrypt_backend(data),
1824        }
1825    }
1826
1827    /// Verifies the given signature.
1828    pub fn verify(&self, sig: &mpi::Signature, hash_algo: HashAlgorithm,
1829                  digest: &[u8]) -> Result<()> {
1830        use crate::crypto::backend::{Backend, interface::Asymmetric};
1831        use crate::crypto::mpi::{PublicKey, Signature};
1832
1833        fn bad(e: impl ToString) -> anyhow::Error {
1834            Error::BadSignature(e.to_string()).into()
1835        }
1836
1837        let ok = match (self.mpis(), sig) {
1838            (PublicKey::Ed25519 { a }, Signature::Ed25519 { s }) =>
1839                Backend::ed25519_verify(a, digest, s)?,
1840
1841            (PublicKey::Ed448 { a }, Signature::Ed448 { s }) =>
1842                Backend::ed448_verify(a, digest, s)?,
1843
1844            (PublicKey::EdDSA { curve, q }, Signature::EdDSA { r, s }) =>
1845              match curve {
1846                Curve::Ed25519 => {
1847                    let (public, ..) = q.decode_point(&Curve::Ed25519)?;
1848                    assert_eq!(public.len(), 32);
1849
1850                    // OpenPGP encodes R and S separately, but our
1851                    // cryptographic backends expect them to be
1852                    // concatenated.
1853                    let mut signature = Vec::with_capacity(64);
1854
1855                    // We need to zero-pad them at the front, because
1856                    // the MPI encoding drops leading zero bytes.
1857                    signature.extend_from_slice(
1858                        &r.value_padded(32).map_err(bad)?);
1859                    signature.extend_from_slice(
1860                        &s.value_padded(32).map_err(bad)?);
1861
1862                    // Let's see if we got it right.
1863                    debug_assert_eq!(signature.len(), 64);
1864
1865                    Backend::ed25519_verify(public.try_into()?,
1866                                            digest,
1867                                            &signature.as_slice().try_into()?)?
1868                },
1869                _ => return
1870                    Err(Error::UnsupportedEllipticCurve(curve.clone()).into()),
1871            },
1872
1873            (PublicKey::DSA { p, q, g, y }, Signature::DSA { r, s }) =>
1874                Backend::dsa_verify(p, q, g, y, digest, r, s)?,
1875
1876            (PublicKey::RSA { .. }, Signature::RSA { .. }) |
1877            (PublicKey::ECDSA { .. }, Signature::ECDSA { .. }) =>
1878                return self.verify_backend(sig, hash_algo, digest),
1879
1880            _ => return Err(Error::MalformedPacket(format!(
1881                "unsupported combination of key {} and signature {:?}.",
1882                self.pk_algo(), sig)).into()),
1883        };
1884
1885        if ok {
1886            Ok(())
1887        } else {
1888            Err(Error::ManipulatedMessage.into())
1889        }
1890    }
1891}
1892
1893/// Holds secret key material.
1894///
1895/// This type allows postponing the decryption of the secret key
1896/// material until it is actually needed.
1897///
1898/// If the secret key material is not encrypted with a password, then
1899/// we encrypt it in memory.  This helps protect against
1900/// [heartbleed]-style attacks where a buffer over-read allows an
1901/// attacker to read from the process's address space.  This
1902/// protection is less important for Rust programs, which are memory
1903/// safe.  However, it is essential when Sequoia is used via its FFI.
1904///
1905/// See [`crypto::mem::Encrypted`] for details.
1906///
1907/// [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed
1908/// [`crypto::mem::Encrypted`]: super::super::crypto::mem::Encrypted
1909#[derive(PartialEq, Eq, Hash, Clone, Debug)]
1910pub enum SecretKeyMaterial {
1911    /// Unencrypted secret key. Can be used as-is.
1912    Unencrypted(Unencrypted),
1913    /// The secret key is encrypted with a password.
1914    Encrypted(Encrypted),
1915}
1916
1917assert_send_and_sync!(SecretKeyMaterial);
1918
1919impl From<mpi::SecretKeyMaterial> for SecretKeyMaterial {
1920    fn from(mpis: mpi::SecretKeyMaterial) -> Self {
1921        SecretKeyMaterial::Unencrypted(mpis.into())
1922    }
1923}
1924
1925impl From<Unencrypted> for SecretKeyMaterial {
1926    fn from(key: Unencrypted) -> Self {
1927        SecretKeyMaterial::Unencrypted(key)
1928    }
1929}
1930
1931impl From<Encrypted> for SecretKeyMaterial {
1932    fn from(key: Encrypted) -> Self {
1933        SecretKeyMaterial::Encrypted(key)
1934    }
1935}
1936
1937impl SecretKeyMaterial {
1938    /// Decrypts the secret key material using `password`.
1939    ///
1940    /// The `SecretKeyMaterial` type does not know what kind of key it
1941    /// contains.  So, in order to know how many MPIs to parse, the
1942    /// public key algorithm needs to be provided explicitly.
1943    ///
1944    /// This returns an error if the secret key material is not
1945    /// encrypted or the password is incorrect.
1946    pub fn decrypt<P, R>(mut self,
1947                         key: &Key<P, R>,
1948                         password: &Password)
1949                         -> Result<Self>
1950    where
1951        P: KeyParts,
1952        R: KeyRole,
1953    {
1954        self.decrypt_in_place(key, password)?;
1955        Ok(self)
1956    }
1957
1958    /// Decrypts the secret key material using `password`.
1959    ///
1960    /// The `SecretKeyMaterial` type does not know what kind of key it
1961    /// contains.  So, in order to know how many MPIs to parse, the
1962    /// public key algorithm needs to be provided explicitly.
1963    ///
1964    /// This returns an error if the secret key material is not
1965    /// encrypted or the password is incorrect.
1966    pub fn decrypt_in_place<P, R>(&mut self,
1967                                  key: &Key<P, R>,
1968                                  password: &Password)
1969                                  -> Result<()>
1970    where
1971        P: KeyParts,
1972        R: KeyRole,
1973    {
1974        match self {
1975            SecretKeyMaterial::Encrypted(e) => {
1976                *self = e.decrypt(key, password)?.into();
1977                Ok(())
1978            }
1979            SecretKeyMaterial::Unencrypted(_) =>
1980                Err(Error::InvalidArgument(
1981                    "secret key is not encrypted".into()).into()),
1982        }
1983    }
1984
1985    /// Encrypts the secret key material using `password`.
1986    ///
1987    /// This returns an error if the secret key material is encrypted.
1988    ///
1989    /// See [`Unencrypted::encrypt`] for details.
1990    pub fn encrypt<P, R>(mut self,
1991                         key: &Key<P, R>,
1992                         password: &Password)
1993                         -> Result<Self>
1994    where
1995        P: KeyParts,
1996        R: KeyRole,
1997    {
1998        self.encrypt_in_place(key, password)?;
1999        Ok(self)
2000    }
2001
2002    /// Encrypts the secret key material using `password` with the
2003    /// given parameters.
2004    ///
2005    /// This returns an error if the secret key material is encrypted.
2006    ///
2007    /// See [`Unencrypted::encrypt_with`] for details.
2008    pub fn encrypt_with<P, R>(mut self,
2009                              key: &Key<P, R>,
2010                              s2k: S2K,
2011                              symm: SymmetricAlgorithm,
2012                              aead: Option<AEADAlgorithm>,
2013                              password: &Password)
2014                              -> Result<Self>
2015    where
2016        P: KeyParts,
2017        R: KeyRole,
2018    {
2019        self.encrypt_in_place_with(key, s2k, symm, aead, password)?;
2020        Ok(self)
2021    }
2022
2023    /// Encrypts the secret key material using `password`.
2024    ///
2025    /// This returns an error if the secret key material is encrypted.
2026    ///
2027    /// See [`Unencrypted::encrypt`] for details.
2028    pub fn encrypt_in_place<P, R>(&mut self,
2029                                  key: &Key<P, R>,
2030                                  password: &Password)
2031                                  -> Result<()>
2032    where
2033        P: KeyParts,
2034        R: KeyRole,
2035    {
2036        match self {
2037            SecretKeyMaterial::Unencrypted(ref u) => {
2038                *self = SecretKeyMaterial::Encrypted(
2039                    u.encrypt(key, password)?);
2040                Ok(())
2041            }
2042            SecretKeyMaterial::Encrypted(_) =>
2043                Err(Error::InvalidArgument(
2044                    "secret key is encrypted".into()).into()),
2045        }
2046    }
2047
2048    /// Encrypts the secret key material using `password` and the
2049    /// given parameters.
2050    ///
2051    /// This returns an error if the secret key material is encrypted.
2052    ///
2053    /// See [`Unencrypted::encrypt`] for details.
2054    pub fn encrypt_in_place_with<P, R>(&mut self,
2055                                       key: &Key<P, R>,
2056                                       s2k: S2K,
2057                                       symm: SymmetricAlgorithm,
2058                                       aead: Option<AEADAlgorithm>,
2059                                       password: &Password)
2060                                       -> Result<()>
2061    where
2062        P: KeyParts,
2063        R: KeyRole,
2064    {
2065        match self {
2066            SecretKeyMaterial::Unencrypted(ref u) => {
2067                *self = SecretKeyMaterial::Encrypted(
2068                    u.encrypt_with(key, s2k, symm, aead, password)?);
2069                Ok(())
2070            }
2071            SecretKeyMaterial::Encrypted(_) =>
2072                Err(Error::InvalidArgument(
2073                    "secret key is encrypted".into()).into()),
2074        }
2075    }
2076
2077    /// Returns whether the secret key material is encrypted.
2078    pub fn is_encrypted(&self) -> bool {
2079        match self {
2080            SecretKeyMaterial::Encrypted(_) => true,
2081            SecretKeyMaterial::Unencrypted(_) => false,
2082        }
2083    }
2084}
2085
2086/// Unencrypted secret key material.
2087///
2088/// This data structure is used by the [`SecretKeyMaterial`] enum.
2089///
2090/// Unlike an [`Encrypted`] key, this key can be used as-is.
2091///
2092/// The secret key is encrypted in memory and only decrypted on
2093/// demand.  This helps protect against [heartbleed]-style
2094/// attacks where a buffer over-read allows an attacker to read from
2095/// the process's address space.  This protection is less important
2096/// for Rust programs, which are memory safe.  However, it is
2097/// essential when Sequoia is used via its FFI.
2098///
2099/// See [`crypto::mem::Encrypted`] for details.
2100///
2101/// [heartbleed]: https://en.wikipedia.org/wiki/Heartbleed
2102/// [`crypto::mem::Encrypted`]: super::super::crypto::mem::Encrypted
2103// Note: PartialEq, Eq, and Hash on mem::Encrypted does the right
2104// thing.
2105#[derive(Clone, Debug, PartialEq, Eq, Hash)]
2106pub struct Unencrypted {
2107    /// MPIs of the secret key.
2108    mpis: mem::Encrypted,
2109}
2110
2111assert_send_and_sync!(Unencrypted);
2112
2113impl From<mpi::SecretKeyMaterial> for Unencrypted {
2114    fn from(mpis: mpi::SecretKeyMaterial) -> Self {
2115        use crate::serialize::MarshalInto;
2116        // We need to store the type.
2117        let mut plaintext = mem::Protected::new(1 + mpis.serialized_len());
2118        plaintext[0] =
2119            mpis.algo().unwrap_or(PublicKeyAlgorithm::Unknown(0)).into();
2120
2121        mpis.serialize_into(&mut plaintext[1..])
2122            .expect("MPI serialization to vec failed");
2123        Unencrypted {
2124            mpis: mem::Encrypted::new(plaintext)
2125                .expect("encrypting memory failed"),
2126        }
2127    }
2128}
2129
2130impl Unencrypted {
2131    /// Maps the given function over the secret.
2132    pub fn map<F, T>(&self, mut fun: F) -> T
2133        where F: FnMut(&mpi::SecretKeyMaterial) -> T
2134    {
2135        self.mpis.map(|plaintext| {
2136            let algo: PublicKeyAlgorithm = plaintext[0].into();
2137            let mpis = mpi::SecretKeyMaterial::from_bytes(algo, &plaintext[1..])
2138                .expect("Decrypted secret key is malformed");
2139            fun(&mpis)
2140        })
2141    }
2142
2143    /// Encrypts the secret key material using `password`.
2144    ///
2145    /// This encrypts the secret key material using AES-128/OCB and a
2146    /// key derived from the `password` using the default [`S2K`]
2147    /// scheme.
2148    pub fn encrypt<P, R>(&self,
2149                         key: &Key<P, R>,
2150                         password: &Password)
2151                         -> Result<Encrypted>
2152    where
2153        P: KeyParts,
2154        R: KeyRole,
2155    {
2156        // Pick sensible parameters according to the key version.
2157        let (s2k, symm, aead) = match key.version() {
2158            6 => (
2159                S2K::default(),
2160                SymmetricAlgorithm::AES128,
2161                Some(AEADAlgorithm::OCB),
2162            ),
2163
2164            _ => (
2165                S2K::default(),
2166                SymmetricAlgorithm::default(),
2167                None,
2168            ),
2169        };
2170
2171        self.encrypt_with(key, s2k, symm, aead, password)
2172    }
2173
2174    /// Encrypts the secret key material using `password` and the
2175    /// given parameters.
2176    pub fn encrypt_with<P, R>(&self,
2177                              key: &Key<P, R>,
2178                              s2k: S2K,
2179                              symm: SymmetricAlgorithm,
2180                              aead: Option<AEADAlgorithm>,
2181                              password: &Password)
2182                              -> Result<Encrypted>
2183    where
2184        P: KeyParts,
2185        R: KeyRole,
2186    {
2187        use std::io::Write;
2188        use crate::crypto::symmetric::Encryptor;
2189
2190        let derived_key = s2k.derive_key(password, symm.key_size()?)?;
2191        let checksum = Default::default();
2192
2193        constrain_encryption_methods(key, &s2k, symm, aead, Some(checksum))?;
2194
2195        if matches!(s2k, S2K::Argon2 { .. }) && aead.is_none() {
2196            return Err(Error::InvalidOperation(
2197                "Argon2 MUST be used with an AEAD mode".into()).into());
2198        }
2199
2200        if let Some(aead) = aead {
2201            use crate::serialize::MarshalInto;
2202
2203            let mut iv = vec![0; aead.nonce_size()?];
2204            crypto::random(&mut iv)?;
2205
2206            let schedule = Key253Schedule::new(
2207                match key.role() {
2208                    KeyRoleRT::Primary => Tag::SecretKey,
2209                    KeyRoleRT::Subordinate => Tag::SecretSubkey,
2210                    KeyRoleRT::Unspecified =>
2211                        return Err(Error::InvalidOperation(
2212                            "cannot encrypt key with unspecified role".into()).into()),
2213                },
2214                key.parts_as_public(), derived_key, symm, aead, &iv)?;
2215            let mut enc = schedule.encryptor()?;
2216
2217            // Encrypt the secret key.
2218            let esk = self.map(|mpis| -> Result<Vec<u8>> {
2219                let mut esk =
2220                    vec![0; mpis.serialized_len() + aead.digest_size()?];
2221                let secret = mpis.to_vec()?;
2222                enc.encrypt_seal(&mut esk, &secret)?;
2223                Ok(esk)
2224            })?;
2225
2226            Ok(Encrypted::new_aead(s2k, symm, aead, iv.into_boxed_slice(),
2227                                   esk.into_boxed_slice()))
2228        } else {
2229            use crypto::symmetric::{
2230                BlockCipherMode,
2231                PaddingMode,
2232            };
2233
2234            // Ciphertext is preceded by a random block.
2235            let mut trash = vec![0u8; symm.block_size()?];
2236            crypto::random(&mut trash)?;
2237
2238            let mut esk = Vec::new();
2239            let mut encryptor =
2240                Encryptor::new(symm, BlockCipherMode::CFB, PaddingMode::None,
2241                               &derived_key, None, &mut esk)?;
2242            encryptor.write_all(&trash)?;
2243            self.map(|mpis| mpis.serialize_with_checksum(&mut encryptor,
2244                                                         checksum))?;
2245            drop(encryptor);
2246
2247            Ok(Encrypted::new(s2k, symm, Some(checksum),
2248                              esk.into_boxed_slice()))
2249        }
2250    }
2251}
2252
2253/// Secret key material encrypted with a password.
2254///
2255/// This data structure is used by the [`SecretKeyMaterial`] enum.
2256///
2257#[derive(Clone, Debug)]
2258pub struct Encrypted {
2259    /// Key derivation mechanism to use.
2260    s2k: S2K,
2261    /// Symmetric algorithm used to encrypt the secret key material.
2262    algo: SymmetricAlgorithm,
2263    /// AEAD algorithm and IV used to encrypt the secret key material.
2264    aead: Option<(AEADAlgorithm, Box<[u8]>)>,
2265    /// Checksum method.
2266    checksum: Option<mpi::SecretKeyChecksum>,
2267    /// Encrypted MPIs prefixed with the IV.
2268    ///
2269    /// If we recognized the S2K object during parsing, we can
2270    /// successfully parse the data into S2K, IV, and ciphertext.
2271    /// However, if we do not recognize the S2K type, we do not know
2272    /// how large its parameters are, so we cannot cleanly parse it,
2273    /// and have to accept that the S2K's body bleeds into the rest of
2274    /// the data.
2275    ciphertext: std::result::Result<(usize, // IV length
2276                                     Box<[u8]>),    // IV + ciphertext.
2277                                    Box<[u8]>>, // S2K body + IV + ciphertext.
2278}
2279
2280assert_send_and_sync!(Encrypted);
2281
2282// Because the S2K and ciphertext cannot be cleanly separated at parse
2283// time, we need to carefully compare and hash encrypted key packets.
2284
2285impl PartialEq for Encrypted {
2286    fn eq(&self, other: &Encrypted) -> bool {
2287        self.algo == other.algo
2288            && self.aead == other.aead
2289            && self.checksum == other.checksum
2290            && match (&self.ciphertext, &other.ciphertext) {
2291                (Ok(a), Ok(b)) =>
2292                    self.s2k == other.s2k && a == b,
2293                (Err(a_raw), Err(b_raw)) => {
2294                    // Treat S2K and ciphertext as opaque blob.
2295                    // XXX: This would be nicer without the allocations.
2296                    use crate::serialize::MarshalInto;
2297                    let mut a = self.s2k.to_vec().unwrap();
2298                    let mut b = other.s2k.to_vec().unwrap();
2299                    a.extend_from_slice(a_raw);
2300                    b.extend_from_slice(b_raw);
2301                    a == b
2302                },
2303                _ => false,
2304            }
2305    }
2306}
2307
2308impl Eq for Encrypted {}
2309
2310impl std::hash::Hash for Encrypted {
2311    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
2312        self.algo.hash(state);
2313        self.aead.hash(state);
2314        self.checksum.hash(state);
2315        match &self.ciphertext {
2316            Ok(c) => {
2317                self.s2k.hash(state);
2318                c.hash(state);
2319            },
2320            Err(c) => {
2321                // Treat S2K and ciphertext as opaque blob.
2322                // XXX: This would be nicer without the allocations.
2323                use crate::serialize::MarshalInto;
2324                let mut a = self.s2k.to_vec().unwrap();
2325                a.extend_from_slice(c);
2326                a.hash(state);
2327            },
2328        }
2329    }
2330}
2331
2332impl Encrypted {
2333    /// Creates a new encrypted key object.
2334    pub fn new(s2k: S2K, algo: SymmetricAlgorithm,
2335               checksum: Option<mpi::SecretKeyChecksum>, ciphertext: Box<[u8]>)
2336        -> Self
2337    {
2338        Self::new_raw(s2k, algo, checksum, Ok((0, ciphertext)))
2339    }
2340
2341    /// Creates a new encrypted key object.
2342    pub fn new_aead(s2k: S2K,
2343                    sym_algo: SymmetricAlgorithm,
2344                    aead_algo: AEADAlgorithm,
2345                    aead_iv: Box<[u8]>,
2346                    ciphertext: Box<[u8]>)
2347                    -> Self
2348    {
2349        Encrypted {
2350            s2k,
2351            algo: sym_algo,
2352            aead: Some((aead_algo, aead_iv)),
2353            checksum: None,
2354            ciphertext: Ok((0, ciphertext)),
2355        }
2356    }
2357
2358    /// Creates a new encrypted key object.
2359    pub(crate) fn new_raw(s2k: S2K, algo: SymmetricAlgorithm,
2360                          checksum: Option<mpi::SecretKeyChecksum>,
2361                          ciphertext: std::result::Result<(usize, Box<[u8]>),
2362                                                          Box<[u8]>>)
2363        -> Self
2364    {
2365        Encrypted { s2k, algo, aead: None, checksum, ciphertext }
2366    }
2367
2368    /// Returns the key derivation mechanism.
2369    pub fn s2k(&self) -> &S2K {
2370        &self.s2k
2371    }
2372
2373    /// Returns the symmetric algorithm used to encrypt the secret
2374    /// key material.
2375    pub fn algo(&self) -> SymmetricAlgorithm {
2376        self.algo
2377    }
2378
2379    /// Returns the AEAD algorithm used to encrypt the secret key
2380    /// material.
2381    pub fn aead_algo(&self) -> Option<AEADAlgorithm> {
2382        self.aead.as_ref().map(|(a, _iv)| *a)
2383    }
2384
2385    /// Returns the AEAD IV used to encrypt the secret key material.
2386    pub fn aead_iv(&self) -> Option<&[u8]> {
2387        self.aead.as_ref().map(|(_a, iv)| &iv[..])
2388    }
2389
2390    /// Returns the checksum method used to protect the encrypted
2391    /// secret key material, if any.
2392    pub fn checksum(&self) -> Option<mpi::SecretKeyChecksum> {
2393        self.checksum
2394    }
2395
2396    /// Returns the encrypted secret key material.
2397    ///
2398    /// If the [`S2K`] mechanism is not supported by Sequoia, this
2399    /// function will fail.  Note that the information is not lost,
2400    /// but stored in the packet.  If the packet is serialized again,
2401    /// it is written out.
2402    ///
2403    ///   [`S2K`]: super::super::crypto::S2K
2404    pub fn ciphertext(&self) -> Result<&[u8]> {
2405        self.ciphertext
2406            .as_ref()
2407            .map(|(_cfb_iv_len, ciphertext)| &ciphertext[..])
2408            .map_err(|_| Error::MalformedPacket(
2409                format!("Unknown S2K: {:?}", self.s2k)).into())
2410    }
2411
2412    /// Returns the encrypted secret key material, possibly including
2413    /// the body of the S2K object.
2414    pub(crate) fn raw_ciphertext(&self) -> &[u8] {
2415        match self.ciphertext.as_ref() {
2416            Ok((_cfb_iv_len, ciphertext)) => &ciphertext[..],
2417            Err(s2k_ciphertext) => &s2k_ciphertext[..],
2418        }
2419    }
2420
2421    /// Returns the length of the CFB IV, if used.
2422    ///
2423    /// In v6 key packets, we explicitly model the length of the IV,
2424    /// but in Sequoia we store the IV and the ciphertext as one
2425    /// block, due to how bad this was modeled in v4 key packets.
2426    /// However, now that our in-core representation is less precise
2427    /// to support v4, we need to track this length to uphold our
2428    /// equality guarantee.
2429    pub(crate) fn cfb_iv_len(&self) -> usize {
2430        self.ciphertext.as_ref().ok()
2431            .map(|(cfb_iv_len, _)| *cfb_iv_len)
2432            .unwrap_or(0)
2433    }
2434
2435    /// Decrypts the secret key material using `password`.
2436    ///
2437    /// The `Encrypted` key does not know what kind of key it is, so
2438    /// the public key algorithm is needed to parse the correct number
2439    /// of MPIs.
2440    pub fn decrypt<P, R>(&self, key: &Key<P, R>, password: &Password)
2441                         -> Result<Unencrypted>
2442    where
2443        P: KeyParts,
2444        R: KeyRole,
2445    {
2446        use std::io::Read;
2447        use crate::crypto;
2448
2449        constrain_encryption_methods(
2450            key, &self.s2k, self.algo,self.aead.as_ref().map(|(a, _)| *a),
2451            self.checksum)?;
2452
2453        let derived_key = self.s2k.derive_key(password, self.algo.key_size()?)?;
2454        let ciphertext = self.ciphertext()?;
2455
2456        if let Some((aead, iv)) = &self.aead {
2457            let schedule = Key253Schedule::new(
2458                match key.role() {
2459                    KeyRoleRT::Primary => Tag::SecretKey,
2460                    KeyRoleRT::Subordinate => Tag::SecretSubkey,
2461                    KeyRoleRT::Unspecified =>
2462                        return Err(Error::InvalidOperation(
2463                            "cannot decrypt key with unspecified role".into()).into()),
2464                },
2465                key.parts_as_public(), derived_key, self.algo, *aead, iv)?;
2466            let mut dec = schedule.decryptor()?;
2467
2468            // Read the secret key.
2469            let mut secret = mem::Protected::new(
2470                ciphertext.len().saturating_sub(aead.digest_size()?));
2471            dec.decrypt_verify(&mut secret, ciphertext)?;
2472
2473            mpi::SecretKeyMaterial::from_bytes(
2474                key.pk_algo(), &secret).map(|m| m.into())
2475        } else {
2476            use crypto::symmetric::{
2477                BlockCipherMode,
2478                UnpaddingMode,
2479            };
2480
2481            let cur = buffered_reader::Memory::with_cookie(
2482                ciphertext, Default::default());
2483            let mut dec =
2484                crypto::symmetric::InternalDecryptor::new(
2485                    self.algo,
2486                    BlockCipherMode::CFB,
2487                    UnpaddingMode::None,
2488                    &derived_key,
2489                    None,
2490                    cur)?;
2491
2492            // Consume the first block.
2493            let block_size = self.algo.block_size()?;
2494            let mut trash = mem::Protected::new(block_size);
2495            dec.read_exact(&mut trash)?;
2496
2497            // Read the secret key.
2498            let mut secret = mem::Protected::new(ciphertext.len() - block_size);
2499            dec.read_exact(&mut secret)?;
2500
2501            mpi::SecretKeyMaterial::from_bytes_with_checksum(
2502                key.pk_algo(), &secret, self.checksum.unwrap_or_default())
2503                .map(|m| m.into())
2504        }
2505    }
2506}
2507
2508/// Constrains the secret key material encryption methods according to
2509/// [Section 3.7.2.1. of RFC 9580].
2510///
2511/// [Section 3.7.2.1. of RFC 9580]: https://www.rfc-editor.org/rfc/rfc9580.html#section-3.7.2.1
2512fn constrain_encryption_methods<P, R>(key: &Key<P, R>,
2513                                      s2k: &S2K,
2514                                      _symm: SymmetricAlgorithm,
2515                                      aead: Option<AEADAlgorithm>,
2516                                      checksum: Option<mpi::SecretKeyChecksum>)
2517                                      -> Result<()>
2518where
2519    P: KeyParts,
2520    R: KeyRole,
2521{
2522    #[allow(deprecated)]
2523    match s2k {
2524        S2K::Argon2 { .. } if aead.is_none() =>
2525            Err(Error::InvalidOperation(
2526                "Argon2 MUST be used with an AEAD mode".into()).into()),
2527
2528        S2K::Implicit if key.version() == 6 =>
2529            Err(Error::InvalidOperation(
2530                "Implicit S2K MUST NOT be used with v6 keys".into()).into()),
2531
2532        // Technically not forbidden, but this is a terrible idea and
2533        // I doubt that anyone depends on it.  Let's see whether we
2534        // can get away with being strict here.
2535        S2K::Simple { .. } if key.version() == 6 =>
2536            Err(Error::InvalidOperation(
2537                "Simple S2K SHOULD NOT be used with v6 keys".into()).into()),
2538
2539        _ if key.version() == 6 && aead.is_none()
2540            && checksum != Some(mpi::SecretKeyChecksum::SHA1) =>
2541            Err(Error::InvalidOperation(
2542                "Malleable CFB MUST NOT be used with v6 keys".into()).into()),
2543
2544        _ => Ok(()),
2545    }
2546}
2547
2548pub(crate) struct Key253Schedule<'a> {
2549    symm: SymmetricAlgorithm,
2550    aead: AEADAlgorithm,
2551    nonce: &'a [u8],
2552    kek: SessionKey,
2553    ad: Vec<u8>
2554}
2555
2556impl<'a> Key253Schedule<'a> {
2557    fn new<R>(tag: Tag,
2558              key: &Key<PublicParts, R>,
2559              derived_key: SessionKey,
2560              symm: SymmetricAlgorithm,
2561              aead: AEADAlgorithm,
2562              nonce: &'a [u8])
2563              -> Result<Self>
2564    where
2565        R: KeyRole,
2566    {
2567        use crate::serialize::{Marshal, MarshalInto};
2568        use crate::crypto::backend::{Backend, interface::Kdf};
2569
2570        let info = [
2571            0b1100_0000 | u8::from(tag), // Canonicalized packet type.
2572            key.version(),
2573            symm.into(),
2574            aead.into(),
2575        ];
2576        let mut kek = vec![0; symm.key_size()?].into();
2577        Backend::hkdf_sha256(&derived_key, None, &info, &mut kek)?;
2578
2579        let mut ad = Vec::with_capacity(key.serialized_len());
2580        ad.push(0b1100_0000 | u8::from(tag)); // Canonicalized packet type.
2581        key.serialize(&mut ad)?;
2582
2583        Ok(Self {
2584            symm,
2585            aead,
2586            nonce,
2587            kek,
2588            ad,
2589        })
2590    }
2591
2592    fn decryptor(&self) -> Result<crypto::aead::DecryptionContext> {
2593        self.aead.context(self.symm, &self.kek, &self.ad, self.nonce)?
2594            .for_decryption()
2595    }
2596
2597    fn encryptor(&self) -> Result<crypto::aead::EncryptionContext> {
2598        self.aead.context(self.symm, &self.kek, &self.ad, self.nonce)?
2599            .for_encryption()
2600    }
2601}
2602
2603#[cfg(test)]
2604mod tests {
2605    use crate::packet::Key;
2606    use crate::Cert;
2607    use crate::packet::key::SecretKeyMaterial;
2608    use crate::packet::Packet;
2609    use super::*;
2610    use crate::parse::Parse;
2611
2612    #[test]
2613    fn encrypted_rsa_key() {
2614        let cert = Cert::from_bytes(
2615            crate::tests::key("testy-new-encrypted-with-123.pgp")).unwrap();
2616        let key = cert.primary_key().key().clone();
2617        let (key, secret) = key.take_secret();
2618        let mut secret = secret.unwrap();
2619
2620        assert!(secret.is_encrypted());
2621        secret.decrypt_in_place(&key, &"123".into()).unwrap();
2622        assert!(!secret.is_encrypted());
2623        let (pair, _) = key.add_secret(secret);
2624        assert!(pair.has_unencrypted_secret());
2625
2626        match pair.secret() {
2627            SecretKeyMaterial::Unencrypted(ref u) => u.map(|mpis| match mpis {
2628                mpi::SecretKeyMaterial::RSA { .. } => (),
2629                _ => panic!(),
2630            }),
2631            _ => panic!(),
2632        }
2633    }
2634
2635    #[test]
2636    fn primary_key_encrypt_decrypt() -> Result<()> {
2637        key_encrypt_decrypt::<PrimaryRole>()
2638    }
2639
2640    #[test]
2641    fn subkey_encrypt_decrypt() -> Result<()> {
2642        key_encrypt_decrypt::<SubordinateRole>()
2643    }
2644
2645    fn key_encrypt_decrypt<R>() -> Result<()>
2646    where
2647        R: KeyRole + PartialEq,
2648    {
2649        let mut g = quickcheck::Gen::new(256);
2650        let p: Password = Vec::<u8>::arbitrary(&mut g).into();
2651
2652        let check = |key: Key<SecretParts, R>| -> Result<()> {
2653            let encrypted = key.clone().encrypt_secret(&p)?;
2654            let decrypted = encrypted.decrypt_secret(&p)?;
2655            assert_eq!(key, decrypted);
2656            Ok(())
2657        };
2658
2659        use crate::types::Curve::*;
2660        for curve in vec![NistP256, NistP384, NistP521, Ed25519] {
2661            if ! curve.is_supported() {
2662                eprintln!("Skipping unsupported {}", curve);
2663                continue;
2664            }
2665
2666            let key: Key4<_, R>
2667                = Key4::generate_ecc(true, curve.clone())?;
2668            check(key.into())?;
2669
2670            let key: Key6<_, R>
2671                = Key6::generate_ecc(true, curve.clone())?;
2672            check(key.into())?;
2673        }
2674
2675        for bits in vec![2048, 3072] {
2676            if ! PublicKeyAlgorithm::RSAEncryptSign.is_supported() {
2677                eprintln!("Skipping unsupported RSA");
2678                continue;
2679            }
2680
2681            let key: Key4<_, R>
2682                = Key4::generate_rsa(bits)?;
2683            check(key.into())?;
2684
2685            let key: Key6<_, R>
2686                = Key6::generate_rsa(bits)?;
2687            check(key.into())?;
2688        }
2689
2690        Ok(())
2691    }
2692
2693    quickcheck! {
2694        fn roundtrip_public(p: Key<PublicParts, UnspecifiedRole>) -> bool {
2695            use crate::parse::Parse;
2696            use crate::serialize::MarshalInto;
2697            let buf = p.to_vec().expect("Failed to serialize key");
2698            let q = Key::from_bytes(&buf).expect("Failed to parse key").into();
2699            assert_eq!(p, q);
2700            true
2701        }
2702    }
2703
2704    quickcheck! {
2705        fn roundtrip_secret(p: Key<SecretParts, PrimaryRole>) -> bool {
2706            use crate::parse::Parse;
2707            use crate::serialize::MarshalInto;
2708            let buf = p.to_vec().expect("Failed to serialize key");
2709            let q = Key::from_bytes(&buf).expect("Failed to parse key")
2710                .parts_into_secret().expect("No secret material")
2711                .role_into_primary();
2712            assert_eq!(p, q);
2713            true
2714        }
2715    }
2716
2717    fn mutate_eq_discriminates_key<P, R>(key: Key<P, R>, i: usize) -> bool
2718        where P: KeyParts,
2719              R: KeyRole,
2720              Key<P, R>: Into<Packet>,
2721    {
2722        use crate::serialize::MarshalInto;
2723        let p: Packet = key.into();
2724        let mut buf = p.to_vec().unwrap();
2725        // Avoid first two bytes so that we don't change the
2726        // type and reduce the chance of changing the length.
2727        if buf.len() < 3 { return true; }
2728        let bit = i % ((buf.len() - 2) * 8) + 16;
2729        buf[bit / 8] ^= 1 << (bit % 8);
2730        let ok = match Packet::from_bytes(&buf) {
2731            Ok(q) => p != q,
2732            Err(_) => true, // Packet failed to parse.
2733        };
2734        if ! ok {
2735            eprintln!("mutate_eq_discriminates_key for ({:?}, {})", p, i);
2736        }
2737        ok
2738    }
2739
2740    // Given a packet and a position, induces a bit flip in the
2741    // serialized form, then checks that PartialEq detects that.
2742    // Recall that for packets, PartialEq is defined using the
2743    // serialized form.
2744    quickcheck! {
2745        fn mutate_eq_discriminates_pp(key: Key<PublicParts, PrimaryRole>,
2746                                      i: usize) -> bool {
2747            mutate_eq_discriminates_key(key, i)
2748        }
2749    }
2750    quickcheck! {
2751        fn mutate_eq_discriminates_ps(key: Key<PublicParts, SubordinateRole>,
2752                                      i: usize) -> bool {
2753            mutate_eq_discriminates_key(key, i)
2754        }
2755    }
2756    quickcheck! {
2757        fn mutate_eq_discriminates_sp(key: Key<SecretParts, PrimaryRole>,
2758                                      i: usize) -> bool {
2759            mutate_eq_discriminates_key(key, i)
2760        }
2761    }
2762    quickcheck! {
2763        fn mutate_eq_discriminates_ss(key: Key<SecretParts, SubordinateRole>,
2764                                      i: usize) -> bool {
2765            mutate_eq_discriminates_key(key, i)
2766        }
2767    }
2768}