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}