rustls/crypto/
mod.rs

1use alloc::borrow::Cow;
2use alloc::boxed::Box;
3use alloc::vec::Vec;
4use core::borrow::Borrow;
5use core::fmt::Debug;
6use core::ops::Deref;
7
8use pki_types::PrivateKeyDer;
9use zeroize::Zeroize;
10
11use crate::enums::ProtocolVersion;
12use crate::error::{ApiMisuse, Error};
13use crate::msgs::ffdhe_groups::FfdheGroup;
14use crate::msgs::handshake::ALL_KEY_EXCHANGE_ALGORITHMS;
15use crate::sync::Arc;
16pub use crate::webpki::{
17    WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature,
18};
19#[cfg(doc)]
20use crate::{ClientConfig, ConfigBuilder, ServerConfig, client, crypto, server};
21use crate::{NamedGroup, SupportedCipherSuite, Tls12CipherSuite, Tls13CipherSuite};
22
23/// *ring* based CryptoProvider.
24#[cfg(feature = "ring")]
25pub mod ring;
26
27/// aws-lc-rs-based CryptoProvider.
28#[cfg(feature = "aws-lc-rs")]
29pub mod aws_lc_rs;
30
31/// TLS message encryption/decryption interfaces.
32pub mod cipher;
33
34/// Hashing interfaces.
35pub mod hash;
36
37/// HMAC interfaces.
38pub mod hmac;
39
40/// Cryptography specific to TLS1.2.
41pub mod tls12;
42
43/// Cryptography specific to TLS1.3.
44pub mod tls13;
45
46/// Hybrid public key encryption (RFC 9180).
47pub mod hpke;
48
49// Message signing interfaces.
50mod signer;
51pub use signer::{
52    CertificateIdentity, Credentials, Identity, SelectedCredential, Signer, SigningKey,
53    SingleCredential, public_key_to_spki,
54};
55
56pub use crate::msgs::handshake::KeyExchangeAlgorithm;
57pub use crate::rand::GetRandomFailed;
58pub use crate::suites::CipherSuiteCommon;
59
60/// Controls core cryptography used by rustls.
61///
62/// This crate comes with two built-in options, provided as
63/// `CryptoProvider` structures:
64///
65/// - [`crypto::aws_lc_rs::DEFAULT_PROVIDER`]: (behind the `aws-lc-rs` crate feature).
66///   This provider uses the [aws-lc-rs](https://github.com/aws/aws-lc-rs)
67///   crate.  The `fips` crate feature makes this option use FIPS140-3-approved cryptography.
68/// - [`crypto::ring::DEFAULT_PROVIDER`]: (behind the `ring` crate feature).
69///   This provider uses the [*ring*](https://github.com/briansmith/ring) crate.
70///
71/// This structure provides defaults. Everything in it can be overridden at
72/// runtime by replacing field values as needed.
73///
74/// # Using the per-process default `CryptoProvider`
75///
76/// There is the concept of an implicit default provider, configured at run-time once in
77/// a given process.
78///
79/// It is used for functions like [`ClientConfig::builder()`] and [`ServerConfig::builder()`].
80///
81/// The intention is that an application can specify the [`CryptoProvider`] they wish to use
82/// once, and have that apply to the variety of places where their application does TLS
83/// (which may be wrapped inside other libraries).
84/// They should do this by calling [`CryptoProvider::install_default()`] early on.
85///
86/// To achieve this goal:
87///
88/// - _libraries_ should use [`ClientConfig::builder()`]/[`ServerConfig::builder()`]
89///   or otherwise rely on the [`CryptoProvider::get_default()`] provider.
90/// - _applications_ should call [`CryptoProvider::install_default()`] early
91///   in their `fn main()`. If _applications_ uses a custom provider based on the one built-in,
92///   they can activate the `custom-provider` feature to ensure its usage.
93///
94/// # Using a specific `CryptoProvider`
95///
96/// Supply the provider when constructing your [`ClientConfig`] or [`ServerConfig`]:
97///
98/// - [`ClientConfig::builder_with_provider()`]
99/// - [`ServerConfig::builder_with_provider()`]
100///
101/// When creating and configuring a webpki-backed client or server certificate verifier, a choice of
102/// provider is also needed to start the configuration process:
103///
104/// - [`client::WebPkiServerVerifier::builder_with_provider()`]
105/// - [`server::WebPkiClientVerifier::builder_with_provider()`]
106///
107/// If you install a custom provider and want to avoid any accidental use of a built-in provider, the feature
108/// `custom-provider` can be activated to ensure your custom provider is used everywhere
109/// and not a built-in one. This will disable any implicit use of a built-in provider.
110///
111/// # Making a custom `CryptoProvider`
112///
113/// Your goal will be to populate an instance of this `CryptoProvider` struct.
114///
115/// ## Which elements are required?
116///
117/// There is no requirement that the individual elements ([`SupportedCipherSuite`], [`SupportedKxGroup`],
118/// [`SigningKey`], etc.) come from the same crate.  It is allowed and expected that uninteresting
119/// elements would be delegated back to one of the default providers (statically) or a parent
120/// provider (dynamically).
121///
122/// For example, if we want to make a provider that just overrides key loading in the config builder
123/// API (with [`ConfigBuilder::with_single_cert`], etc.), it might look like this:
124///
125/// ```
126/// # #[cfg(feature = "aws-lc-rs")] {
127/// # use std::sync::Arc;
128/// # mod fictitious_hsm_api { pub fn load_private_key(key_der: pki_types::PrivateKeyDer<'static>) -> ! { unreachable!(); } }
129/// use rustls::crypto::aws_lc_rs;
130///
131/// pub fn provider() -> rustls::crypto::CryptoProvider {
132///   rustls::crypto::CryptoProvider{
133///     key_provider: &HsmKeyLoader,
134///     ..aws_lc_rs::DEFAULT_PROVIDER
135///   }
136/// }
137///
138/// #[derive(Debug)]
139/// struct HsmKeyLoader;
140///
141/// impl rustls::crypto::KeyProvider for HsmKeyLoader {
142///     fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Box<dyn rustls::crypto::SigningKey>, rustls::Error> {
143///          fictitious_hsm_api::load_private_key(key_der)
144///     }
145/// }
146/// # }
147/// ```
148///
149/// ## References to the individual elements
150///
151/// The elements are documented separately:
152///
153/// - **Random** - see [`crypto::SecureRandom::fill()`].
154/// - **Cipher suites** - see [`SupportedCipherSuite`], [`Tls12CipherSuite`], and
155///   [`Tls13CipherSuite`].
156/// - **Key exchange groups** - see [`crypto::SupportedKxGroup`].
157/// - **Signature verification algorithms** - see [`crypto::WebPkiSupportedAlgorithms`].
158/// - **Authentication key loading** - see [`crypto::KeyProvider::load_private_key()`] and
159///   [`SigningKey`].
160///
161/// # Example code
162///
163/// See custom [`provider-example/`] for a full client and server example that uses
164/// cryptography from the [`RustCrypto`] and [`dalek-cryptography`] projects.
165///
166/// ```shell
167/// $ cargo run --example client | head -3
168/// Current ciphersuite: TLS13_CHACHA20_POLY1305_SHA256
169/// HTTP/1.1 200 OK
170/// Content-Type: text/html; charset=utf-8
171/// Content-Length: 19899
172/// ```
173///
174/// [`provider-example/`]: https://github.com/rustls/rustls/tree/main/provider-example/
175/// [`RustCrypto`]: https://github.com/RustCrypto
176/// [`dalek-cryptography`]: https://github.com/dalek-cryptography
177///
178/// # FIPS-approved cryptography
179/// The `fips` crate feature enables use of the `aws-lc-rs` crate in FIPS mode.
180///
181/// You can verify the configuration at runtime by checking
182/// [`ServerConfig::fips()`]/[`ClientConfig::fips()`] return `true`.
183#[allow(clippy::exhaustive_structs)]
184#[derive(Debug, Clone)]
185pub struct CryptoProvider {
186    /// List of supported TLS1.2 cipher suites, in preference order -- the first element
187    /// is the highest priority.
188    ///
189    /// Note that the protocol version is negotiated before the cipher suite.
190    ///
191    /// The `Tls12CipherSuite` type carries both configuration and implementation.
192    ///
193    /// A valid `CryptoProvider` must ensure that all cipher suites are accompanied by at least
194    /// one matching key exchange group in [`CryptoProvider::kx_groups`].
195    pub tls12_cipher_suites: Cow<'static, [&'static Tls12CipherSuite]>,
196
197    /// List of supported TLS1.3 cipher suites, in preference order -- the first element
198    /// is the highest priority.
199    ///
200    /// Note that the protocol version is negotiated before the cipher suite.
201    ///
202    /// The `Tls13CipherSuite` type carries both configuration and implementation.
203    pub tls13_cipher_suites: Cow<'static, [&'static Tls13CipherSuite]>,
204
205    /// List of supported key exchange groups, in preference order -- the
206    /// first element is the highest priority.
207    ///
208    /// The first element in this list is the _default key share algorithm_,
209    /// and in TLS1.3 a key share for it is sent in the client hello.
210    ///
211    /// The `SupportedKxGroup` type carries both configuration and implementation.
212    pub kx_groups: Cow<'static, [&'static dyn SupportedKxGroup]>,
213
214    /// List of signature verification algorithms for use with webpki.
215    ///
216    /// These are used for both certificate chain verification and handshake signature verification.
217    ///
218    /// This is called by [`ConfigBuilder::with_root_certificates()`],
219    /// [`server::WebPkiClientVerifier::builder_with_provider()`] and
220    /// [`client::WebPkiServerVerifier::builder_with_provider()`].
221    pub signature_verification_algorithms: WebPkiSupportedAlgorithms,
222
223    /// Source of cryptographically secure random numbers.
224    pub secure_random: &'static dyn SecureRandom,
225
226    /// Provider for loading private [`SigningKey`]s from [`PrivateKeyDer`].
227    pub key_provider: &'static dyn KeyProvider,
228}
229
230impl CryptoProvider {
231    /// Sets this `CryptoProvider` as the default for this process.
232    ///
233    /// This can be called successfully at most once in any process execution.
234    ///
235    /// Call this early in your process to configure which provider is used for
236    /// the provider.  The configuration should happen before any use of
237    /// [`ClientConfig::builder()`] or [`ServerConfig::builder()`].
238    pub fn install_default(self) -> Result<(), Arc<Self>> {
239        static_default::install_default(self)
240    }
241}
242
243impl CryptoProvider {
244    /// Returns the default `CryptoProvider` for this process.
245    ///
246    /// This will be `None` if no default has been set yet.
247    pub fn get_default() -> Option<&'static Arc<Self>> {
248        static_default::get_default()
249    }
250
251    /// An internal function that:
252    ///
253    /// - gets the pre-installed default, or
254    /// - installs one `from_crate_features()`, or else
255    /// - panics about the need to call [`CryptoProvider::install_default()`]
256    pub(crate) fn get_default_or_install_from_crate_features() -> &'static Arc<Self> {
257        if let Some(provider) = Self::get_default() {
258            return provider;
259        }
260
261        let provider = Self::from_crate_features()
262            .expect(r###"
263Could not automatically determine the process-level CryptoProvider from Rustls crate features.
264Call CryptoProvider::install_default() before this point to select a provider manually, or make sure exactly one of the 'aws-lc-rs' and 'ring' features is enabled.
265See the documentation of the CryptoProvider type for more information.
266            "###);
267        // Ignore the error resulting from us losing a race, and accept the outcome.
268        let _ = provider.install_default();
269        Self::get_default().unwrap()
270    }
271
272    /// Returns a provider named unambiguously by rustls crate features.
273    ///
274    /// This function returns `None` if the crate features are ambiguous (ie, specify two
275    /// providers), or specify no providers, or the feature `custom-provider` is activated.
276    /// In all cases the application should explicitly specify the provider to use
277    /// with [`CryptoProvider::install_default`].
278    ///
279    /// This can be used to check if a default provider is available before
280    /// invoking functions that require an installed `CryptoProvider`, like
281    /// [`ClientConfig::builder()`] or [`ServerConfig::builder()`].
282    ///
283    /// ```rust,no_run
284    /// # use rustls::crypto::CryptoProvider;
285    /// if CryptoProvider::get_default().is_some() || CryptoProvider::from_crate_features().is_some() {
286    ///     // A default provider is available, either from the
287    ///     // process-level default or from the crate features.
288    /// }
289    /// ```
290    ///
291    /// [`ClientConfig::builder()`]: crate::ClientConfig::builder
292    /// [`ServerConfig::builder()`]: crate::ServerConfig::builder
293    pub fn from_crate_features() -> Option<Self> {
294        #[cfg(all(
295            feature = "ring",
296            not(feature = "aws-lc-rs"),
297            not(feature = "custom-provider")
298        ))]
299        {
300            return Some(ring::DEFAULT_PROVIDER);
301        }
302
303        #[cfg(all(
304            feature = "aws-lc-rs",
305            not(feature = "ring"),
306            not(feature = "custom-provider")
307        ))]
308        {
309            return Some(aws_lc_rs::DEFAULT_PROVIDER);
310        }
311
312        #[allow(unreachable_code)]
313        None
314    }
315
316    /// Returns `true` if this `CryptoProvider` is operating in FIPS mode.
317    ///
318    /// This covers only the cryptographic parts of FIPS approval.  There are
319    /// also TLS protocol-level recommendations made by NIST.  You should
320    /// prefer to call [`ClientConfig::fips()`] or [`ServerConfig::fips()`]
321    /// which take these into account.
322    pub fn fips(&self) -> bool {
323        let Self {
324            tls12_cipher_suites,
325            tls13_cipher_suites,
326            kx_groups,
327            signature_verification_algorithms,
328            secure_random,
329            key_provider,
330        } = self;
331        tls12_cipher_suites
332            .iter()
333            .all(|cs| cs.fips())
334            && tls13_cipher_suites
335                .iter()
336                .all(|cs| cs.fips())
337            && kx_groups.iter().all(|kx| kx.fips())
338            && signature_verification_algorithms.fips()
339            && secure_random.fips()
340            && key_provider.fips()
341    }
342
343    pub(crate) fn consistency_check(&self) -> Result<(), Error> {
344        if self.tls12_cipher_suites.is_empty() && self.tls13_cipher_suites.is_empty() {
345            return Err(ApiMisuse::NoCipherSuitesConfigured.into());
346        }
347
348        if self.kx_groups.is_empty() {
349            return Err(ApiMisuse::NoKeyExchangeGroupsConfigured.into());
350        }
351
352        // verifying cipher suites have matching kx groups
353        let mut supported_kx_algos = Vec::with_capacity(ALL_KEY_EXCHANGE_ALGORITHMS.len());
354        for group in self.kx_groups.iter() {
355            let kx = group.name().key_exchange_algorithm();
356            if !supported_kx_algos.contains(&kx) {
357                supported_kx_algos.push(kx);
358            }
359            // Small optimization. We don't need to go over other key exchange groups
360            // if we already cover all supported key exchange algorithms
361            if supported_kx_algos.len() == ALL_KEY_EXCHANGE_ALGORITHMS.len() {
362                break;
363            }
364        }
365
366        for cs in self.tls12_cipher_suites.iter() {
367            if supported_kx_algos.contains(&cs.kx) {
368                continue;
369            }
370            let suite_name = cs.common.suite;
371            return Err(Error::General(alloc::format!(
372                "TLS1.2 cipher suite {suite_name:?} requires {0:?} key exchange, but no {0:?}-compatible \
373                key exchange groups were present in `CryptoProvider`'s `kx_groups` field",
374                cs.kx,
375            )));
376        }
377
378        Ok(())
379    }
380
381    pub(crate) fn iter_cipher_suites(&self) -> impl Iterator<Item = SupportedCipherSuite> + '_ {
382        self.tls13_cipher_suites
383            .iter()
384            .copied()
385            .map(SupportedCipherSuite::Tls13)
386            .chain(
387                self.tls12_cipher_suites
388                    .iter()
389                    .copied()
390                    .map(SupportedCipherSuite::Tls12),
391            )
392    }
393
394    /// We support a given TLS version if at least one ciphersuite for the version
395    /// is available.
396    pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool {
397        match v {
398            ProtocolVersion::TLSv1_2 => !self.tls12_cipher_suites.is_empty(),
399            ProtocolVersion::TLSv1_3 => !self.tls13_cipher_suites.is_empty(),
400            _ => false,
401        }
402    }
403
404    pub(crate) fn find_kx_group(
405        &self,
406        name: NamedGroup,
407        version: ProtocolVersion,
408    ) -> Option<&'static dyn SupportedKxGroup> {
409        if !name.usable_for_version(version) {
410            return None;
411        }
412        self.kx_groups
413            .iter()
414            .find(|skxg| skxg.name() == name)
415            .copied()
416    }
417}
418
419impl Borrow<[&'static Tls12CipherSuite]> for CryptoProvider {
420    fn borrow(&self) -> &[&'static Tls12CipherSuite] {
421        &self.tls12_cipher_suites
422    }
423}
424
425impl Borrow<[&'static Tls13CipherSuite]> for CryptoProvider {
426    fn borrow(&self) -> &[&'static Tls13CipherSuite] {
427        &self.tls13_cipher_suites
428    }
429}
430
431/// A source of cryptographically secure randomness.
432pub trait SecureRandom: Send + Sync + Debug {
433    /// Fill the given buffer with random bytes.
434    ///
435    /// The bytes must be sourced from a cryptographically secure random number
436    /// generator seeded with good quality, secret entropy.
437    ///
438    /// This is used for all randomness required by rustls, but not necessarily
439    /// randomness required by the underlying cryptography library.  For example:
440    /// [`SupportedKxGroup::start()`] requires random material to generate
441    /// an ephemeral key exchange key, but this is not included in the interface with
442    /// rustls: it is assumed that the cryptography library provides for this itself.
443    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
444
445    /// Return `true` if this is backed by a FIPS-approved implementation.
446    fn fips(&self) -> bool {
447        false
448    }
449}
450
451/// A mechanism for loading private [`SigningKey`]s from [`PrivateKeyDer`].
452///
453/// This trait is intended to be used with private key material that is sourced from DER,
454/// such as a private-key that may be present on-disk. It is not intended to be used with
455/// keys held in hardware security modules (HSMs) or physical tokens. For these use-cases
456/// see the Rustls manual section on [customizing private key usage].
457///
458/// [customizing private key usage]: <https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#customising-private-key-usage>
459pub trait KeyProvider: Send + Sync + Debug {
460    /// Decode and validate a private signing key from `key_der`.
461    ///
462    /// This is used by [`ConfigBuilder::with_client_auth_cert()`], [`ConfigBuilder::with_single_cert()`],
463    /// and [`ConfigBuilder::with_single_cert_with_ocsp()`].  The key types and formats supported by this
464    /// function directly defines the key types and formats supported in those APIs.
465    ///
466    /// Return an error if the key type encoding is not supported, or if the key fails validation.
467    fn load_private_key(
468        &self,
469        key_der: PrivateKeyDer<'static>,
470    ) -> Result<Box<dyn SigningKey>, Error>;
471
472    /// Return `true` if this is backed by a FIPS-approved implementation.
473    ///
474    /// If this returns `true`, that must be the case for all possible key types
475    /// supported by [`KeyProvider::load_private_key()`].
476    fn fips(&self) -> bool {
477        false
478    }
479}
480
481/// A supported key exchange group.
482///
483/// This type carries both configuration and implementation. Specifically,
484/// it has a TLS-level name expressed using the [`NamedGroup`] enum, and
485/// a function which produces a [`ActiveKeyExchange`].
486///
487/// Compare with [`NamedGroup`], which carries solely a protocol identifier.
488pub trait SupportedKxGroup: Send + Sync + Debug {
489    /// Start a key exchange.
490    ///
491    /// This will prepare an ephemeral secret key in the supported group, and a corresponding
492    /// public key. The key exchange can be completed by calling [`ActiveKeyExchange::complete()`]
493    /// or discarded.
494    ///
495    /// Most implementations will want to return the `StartedKeyExchange::Single(_)` variant.
496    /// Hybrid key exchange algorithms, which are constructed from two underlying algorithms,
497    /// may wish to return `StartedKeyExchange::Hybrid(_)` variant which additionally allows
498    /// one part of the key exchange to be completed separately.  See the documentation
499    /// on [`HybridKeyExchange`] for more detail.
500    ///
501    /// # Errors
502    ///
503    /// This can fail if the random source fails during ephemeral key generation.
504    fn start(&self) -> Result<StartedKeyExchange, Error>;
505
506    /// Start and complete a key exchange, in one operation.
507    ///
508    /// The default implementation for this calls `start()` and then calls
509    /// `complete()` on the result.  This is suitable for Diffie-Hellman-like
510    /// key exchange algorithms, where there is not a data dependency between
511    /// our key share (named "pub_key" in this API) and the peer's (`peer_pub_key`).
512    ///
513    /// If there is such a data dependency (like key encapsulation mechanisms), this
514    /// function should be implemented.
515    fn start_and_complete(&self, peer_pub_key: &[u8]) -> Result<CompletedKeyExchange, Error> {
516        let kx = self.start()?.into_single();
517
518        Ok(CompletedKeyExchange {
519            group: kx.group(),
520            pub_key: kx.pub_key().to_vec(),
521            secret: kx.complete(peer_pub_key)?,
522        })
523    }
524
525    /// FFDHE group the `SupportedKxGroup` operates in, if any.
526    ///
527    /// The default implementation returns `None`, so non-FFDHE groups (the
528    /// most common) do not need to do anything.
529    ///
530    /// FFDHE groups must implement this. `rustls::ffdhe_groups` contains
531    /// suitable values to return, for example
532    /// [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
533    fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
534        None
535    }
536
537    /// Named group the SupportedKxGroup operates in.
538    ///
539    /// If the `NamedGroup` enum does not have a name for the algorithm you are implementing,
540    /// you can use [`NamedGroup::Unknown`].
541    fn name(&self) -> NamedGroup;
542
543    /// Return `true` if this is backed by a FIPS-approved implementation.
544    fn fips(&self) -> bool {
545        false
546    }
547}
548
549/// Return value from [`SupportedKxGroup::start()`].
550#[non_exhaustive]
551pub enum StartedKeyExchange {
552    /// A single [`ActiveKeyExchange`].
553    Single(Box<dyn ActiveKeyExchange>),
554    /// A [`HybridKeyExchange`] that can potentially be split.
555    Hybrid(Box<dyn HybridKeyExchange>),
556}
557
558impl StartedKeyExchange {
559    /// Collapses this object into its underlying [`ActiveKeyExchange`].
560    ///
561    /// This removes the ability to do the hybrid key exchange optimization,
562    /// but still allows the key exchange as a whole to be completed.
563    pub fn into_single(self) -> Box<dyn ActiveKeyExchange> {
564        match self {
565            Self::Single(s) => s,
566            Self::Hybrid(h) => h.into_key_exchange(),
567        }
568    }
569
570    /// Accesses the [`HybridKeyExchange`], and checks it was also usable separately.
571    ///
572    /// Returns:
573    ///
574    /// - the [`HybridKeyExchange`]
575    /// - the stand-alone `SupportedKxGroup` for the hybrid's component group.
576    ///
577    /// This returns `None` for:
578    ///
579    /// - non-hybrid groups,
580    /// - if the hybrid component group is not present in `supported`
581    /// - if the hybrid component group is not usable with `version`
582    pub(crate) fn as_hybrid_checked(
583        &self,
584        supported: &[&'static dyn SupportedKxGroup],
585        version: ProtocolVersion,
586    ) -> Option<(&dyn HybridKeyExchange, &'static dyn SupportedKxGroup)> {
587        let Self::Hybrid(hybrid) = self else {
588            return None;
589        };
590
591        let component_group = hybrid.component().0;
592        if !component_group.usable_for_version(version) {
593            return None;
594        }
595
596        supported
597            .iter()
598            .find(|g| g.name() == component_group)
599            .copied()
600            .map(|g| (hybrid.as_ref(), g))
601    }
602}
603
604impl Deref for StartedKeyExchange {
605    type Target = dyn ActiveKeyExchange;
606
607    fn deref(&self) -> &Self::Target {
608        match self {
609            Self::Single(s) => s.as_ref(),
610            Self::Hybrid(h) => h.as_key_exchange(),
611        }
612    }
613}
614
615/// An in-progress key exchange originating from a [`SupportedKxGroup`].
616pub trait ActiveKeyExchange: Send + Sync {
617    /// Completes the key exchange, given the peer's public key.
618    ///
619    /// This method must return an error if `peer_pub_key` is invalid: either
620    /// misencoded, or an invalid public key (such as, but not limited to, being
621    /// in a small order subgroup).
622    ///
623    /// If the key exchange algorithm is FFDHE, the result must be left-padded with zeros,
624    /// as required by [RFC 8446](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1)
625    /// (see [`complete_for_tls_version()`](Self::complete_for_tls_version) for more details).
626    ///
627    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
628    /// from a `&[u8]`.
629    ///
630    /// This consumes and so terminates the [`ActiveKeyExchange`].
631    fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error>;
632
633    /// Completes the key exchange for the given TLS version, given the peer's public key.
634    ///
635    /// Note that finite-field Diffie–Hellman key exchange has different requirements for the derived
636    /// shared secret in TLS 1.2 and TLS 1.3 (ECDHE key exchange is the same in TLS 1.2 and TLS 1.3):
637    ///
638    /// In TLS 1.2, the calculated secret is required to be stripped of leading zeros
639    /// [(RFC 5246)](https://www.rfc-editor.org/rfc/rfc5246#section-8.1.2).
640    ///
641    /// In TLS 1.3, the calculated secret is required to be padded with leading zeros to be the same
642    /// byte-length as the group modulus [(RFC 8446)](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1).
643    ///
644    /// The default implementation of this method delegates to [`complete()`](Self::complete) assuming it is
645    /// implemented for TLS 1.3 (i.e., for FFDHE KX, removes padding as needed). Implementers of this trait
646    /// are encouraged to just implement [`complete()`](Self::complete) assuming TLS 1.3, and let the default
647    /// implementation of this method handle TLS 1.2-specific requirements.
648    ///
649    /// This method must return an error if `peer_pub_key` is invalid: either
650    /// misencoded, or an invalid public key (such as, but not limited to, being
651    /// in a small order subgroup).
652    ///
653    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
654    /// from a `&[u8]`.
655    ///
656    /// This consumes and so terminates the [`ActiveKeyExchange`].
657    fn complete_for_tls_version(
658        self: Box<Self>,
659        peer_pub_key: &[u8],
660        tls_version: ProtocolVersion,
661    ) -> Result<SharedSecret, Error> {
662        if tls_version == ProtocolVersion::TLSv1_3 {
663            return self.complete(peer_pub_key);
664        }
665
666        let group = self.group();
667        let mut complete_res = self.complete(peer_pub_key)?;
668        if group.key_exchange_algorithm() == KeyExchangeAlgorithm::DHE {
669            complete_res.strip_leading_zeros();
670        }
671        Ok(complete_res)
672    }
673
674    /// Return the public key being used.
675    ///
676    /// For ECDHE, the encoding required is defined in
677    /// [RFC8446 section 4.2.8.2](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.2).
678    ///
679    /// For FFDHE, the encoding required is defined in
680    /// [RFC8446 section 4.2.8.1](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.1).
681    fn pub_key(&self) -> &[u8];
682
683    /// FFDHE group the `ActiveKeyExchange` is operating in.
684    ///
685    /// The default implementation returns `None`, so non-FFDHE groups (the
686    /// most common) do not need to do anything.
687    ///
688    /// FFDHE groups must implement this. `rustls::ffdhe_groups` contains
689    /// suitable values to return, for example
690    /// [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
691    fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
692        None
693    }
694
695    /// Return the group being used.
696    fn group(&self) -> NamedGroup;
697}
698
699/// An in-progress hybrid key exchange originating from a [`SupportedKxGroup`].
700///
701/// "Hybrid" means a key exchange algorithm which is constructed from two
702/// (or more) independent component algorithms. Usually one is post-quantum-secure,
703/// and the other is "classical".  See
704/// <https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/11/>
705///
706/// There is no requirement for a hybrid scheme (or any other!) to implement
707/// `HybridKeyExchange` if it is not desirable for it to be "split" like this.
708/// It only enables an optimization; described below.
709///
710/// # Background
711/// Rustls always sends a presumptive key share in its `ClientHello`, using
712/// (absent any other information) the first item in [`CryptoProvider::kx_groups`].
713/// If the server accepts the client's selection, it can complete the handshake
714/// using that key share.  If not, the server sends a `HelloRetryRequest` instructing
715/// the client to send a different key share instead.
716///
717/// This request costs an extra round trip, and wastes the key exchange computation
718/// (in [`SupportedKxGroup::start()`]) the client already did.  We would
719/// like to avoid those wastes if possible.
720///
721/// It is early days for post-quantum-secure hybrid key exchange deployment.
722/// This means (commonly) continuing to offer both the hybrid and classical
723/// key exchanges, so the handshake can be completed without a `HelloRetryRequest`
724/// for servers that support the offered hybrid or classical schemes.
725///
726/// Implementing `HybridKeyExchange` enables two optimizations:
727///
728/// 1. Sending both the hybrid and classical key shares in the `ClientHello`.
729///
730/// 2. Performing the classical key exchange setup only once.  This is important
731///    because the classical key exchange setup is relatively expensive.
732///    This optimization is permitted and described in
733///    <https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-11.html#section-3.2>
734///
735/// Both of these only happen if the classical algorithm appears separately in
736/// the client's [`CryptoProvider::kx_groups`], and if the hybrid algorithm appears
737/// first in that list.
738///
739/// # How it works
740/// This function is only called by rustls for clients.  It is called when
741/// constructing the initial `ClientHello`.  rustls follows these steps:
742///
743/// 1. If the return value is `None`, nothing further happens.
744/// 2. If the given [`NamedGroup`] does not appear in
745///    [`CryptoProvider::kx_groups`], nothing further happens.
746/// 3. The given key share is added to the `ClientHello`, after the hybrid entry.
747///
748/// Then, one of three things may happen when the server replies to the `ClientHello`:
749///
750/// 1. The server sends a `HelloRetryRequest`.  Everything is thrown away and
751///    we start again.
752/// 2. The server agrees to our hybrid key exchange: rustls calls
753///    [`ActiveKeyExchange::complete()`] consuming `self`.
754/// 3. The server agrees to our classical key exchange: rustls calls
755///    [`HybridKeyExchange::complete_component()`] which
756///    discards the hybrid key data, and completes just the classical key exchange.
757pub trait HybridKeyExchange: ActiveKeyExchange {
758    /// Returns the [`NamedGroup`] and public key "share" for the component.
759    fn component(&self) -> (NamedGroup, &[u8]);
760
761    /// Completes the classical component of the key exchange, given the peer's public key.
762    ///
763    /// This method must return an error if `peer_pub_key` is invalid: either
764    /// misencoded, or an invalid public key (such as, but not limited to, being
765    /// in a small order subgroup).
766    ///
767    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
768    /// from a `&[u8]`.
769    ///
770    /// See the documentation on [`HybridKeyExchange`] for explanation.
771    fn complete_component(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error>;
772
773    /// Obtain the value as a `dyn ActiveKeyExchange`
774    fn as_key_exchange(&self) -> &(dyn ActiveKeyExchange + 'static);
775
776    /// Remove the ability to do hybrid key exchange on this object.
777    fn into_key_exchange(self: Box<Self>) -> Box<dyn ActiveKeyExchange>;
778}
779
780/// The result from [`SupportedKxGroup::start_and_complete()`].
781#[allow(clippy::exhaustive_structs)]
782pub struct CompletedKeyExchange {
783    /// Which group was used.
784    pub group: NamedGroup,
785
786    /// Our key share (sometimes a public key).
787    pub pub_key: Vec<u8>,
788
789    /// The computed shared secret.
790    pub secret: SharedSecret,
791}
792
793/// The result from [`ActiveKeyExchange::complete()`] or [`HybridKeyExchange::complete_component()`].
794pub struct SharedSecret {
795    buf: Vec<u8>,
796    offset: usize,
797}
798
799impl SharedSecret {
800    /// Returns the shared secret as a slice of bytes.
801    pub fn secret_bytes(&self) -> &[u8] {
802        &self.buf[self.offset..]
803    }
804
805    /// Removes leading zeros from `secret_bytes()` by adjusting the `offset`.
806    ///
807    /// This function does not re-allocate.
808    fn strip_leading_zeros(&mut self) {
809        let start = self
810            .secret_bytes()
811            .iter()
812            .enumerate()
813            .find(|(_i, x)| **x != 0)
814            .map(|(i, _x)| i)
815            .unwrap_or_else(|| self.secret_bytes().len());
816        self.offset += start;
817    }
818}
819
820impl Drop for SharedSecret {
821    fn drop(&mut self) {
822        self.buf.zeroize();
823    }
824}
825
826impl From<&[u8]> for SharedSecret {
827    fn from(source: &[u8]) -> Self {
828        Self {
829            buf: source.to_vec(),
830            offset: 0,
831        }
832    }
833}
834
835impl From<Vec<u8>> for SharedSecret {
836    fn from(buf: Vec<u8>) -> Self {
837        Self { buf, offset: 0 }
838    }
839}
840
841/// This function returns a [`CryptoProvider`] that uses
842/// FIPS140-3-approved cryptography.
843///
844/// Using this function expresses in your code that you require
845/// FIPS-approved cryptography, and will not compile if you make
846/// a mistake with cargo features.
847///
848/// See our [FIPS documentation](crate::manual::_06_fips) for
849/// more detail.
850///
851/// Install this as the process-default provider, like:
852///
853/// ```rust
854/// # #[cfg(feature = "fips")] {
855/// rustls::crypto::default_fips_provider().install_default()
856///     .expect("default provider already set elsewhere");
857/// # }
858/// ```
859///
860/// You can also use this explicitly, like:
861///
862/// ```rust
863/// # #[cfg(feature = "fips")] {
864/// # let root_store = rustls::RootCertStore::empty();
865/// let config = rustls::ClientConfig::builder_with_provider(
866///         rustls::crypto::default_fips_provider().into()
867///     )
868///     .with_root_certificates(root_store)
869///     .with_no_client_auth()
870///     .unwrap();
871/// # }
872/// ```
873#[cfg(all(feature = "aws-lc-rs", any(feature = "fips", rustls_docsrs)))]
874#[cfg_attr(rustls_docsrs, doc(cfg(feature = "fips")))]
875pub fn default_fips_provider() -> CryptoProvider {
876    aws_lc_rs::DEFAULT_PROVIDER
877}
878
879mod static_default {
880    #[cfg(not(feature = "std"))]
881    use alloc::boxed::Box;
882    #[cfg(feature = "std")]
883    use std::sync::OnceLock;
884
885    #[cfg(not(feature = "std"))]
886    use once_cell::race::OnceBox;
887
888    use super::CryptoProvider;
889    use crate::sync::Arc;
890
891    #[cfg(feature = "std")]
892    pub(crate) fn install_default(
893        default_provider: CryptoProvider,
894    ) -> Result<(), Arc<CryptoProvider>> {
895        PROCESS_DEFAULT_PROVIDER.set(Arc::new(default_provider))
896    }
897
898    #[cfg(not(feature = "std"))]
899    pub(crate) fn install_default(
900        default_provider: CryptoProvider,
901    ) -> Result<(), Arc<CryptoProvider>> {
902        PROCESS_DEFAULT_PROVIDER
903            .set(Box::new(Arc::new(default_provider)))
904            .map_err(|e| *e)
905    }
906
907    pub(crate) fn get_default() -> Option<&'static Arc<CryptoProvider>> {
908        PROCESS_DEFAULT_PROVIDER.get()
909    }
910
911    #[cfg(feature = "std")]
912    static PROCESS_DEFAULT_PROVIDER: OnceLock<Arc<CryptoProvider>> = OnceLock::new();
913    #[cfg(not(feature = "std"))]
914    static PROCESS_DEFAULT_PROVIDER: OnceBox<Arc<CryptoProvider>> = OnceBox::new();
915}
916
917#[cfg(test)]
918mod tests {
919    use std::vec;
920
921    use super::SharedSecret;
922
923    #[test]
924    fn test_shared_secret_strip_leading_zeros() {
925        let test_cases = [
926            (vec![0, 1], vec![1]),
927            (vec![1], vec![1]),
928            (vec![1, 0, 2], vec![1, 0, 2]),
929            (vec![0, 0, 1, 2], vec![1, 2]),
930            (vec![0, 0, 0], vec![]),
931            (vec![], vec![]),
932        ];
933        for (buf, expected) in test_cases {
934            let mut secret = SharedSecret::from(&buf[..]);
935            assert_eq!(secret.secret_bytes(), buf);
936            secret.strip_leading_zeros();
937            assert_eq!(secret.secret_bytes(), expected);
938        }
939    }
940}