portable_rustls/crypto/
mod.rs

1use alloc::boxed::Box;
2use alloc::vec::Vec;
3use core::fmt::Debug;
4
5use pki_types::PrivateKeyDer;
6use zeroize::Zeroize;
7
8use crate::msgs::ffdhe_groups::FfdheGroup;
9use crate::sign::SigningKey;
10use crate::sync::Arc;
11pub use crate::webpki::{
12    verify_tls12_signature, verify_tls13_signature, verify_tls13_signature_with_raw_key,
13    WebPkiSupportedAlgorithms,
14};
15#[cfg(all(doc, feature = "tls12"))]
16use crate::Tls12CipherSuite;
17#[cfg(doc)]
18use crate::{
19    client, crypto, server, sign, ClientConfig, ConfigBuilder, ServerConfig, SupportedCipherSuite,
20    Tls13CipherSuite,
21};
22use crate::{suites, Error, NamedGroup, ProtocolVersion, SupportedProtocolVersion};
23
24/// *ring* based CryptoProvider.
25#[cfg(feature = "ring")]
26pub mod ring;
27
28/// aws-lc-rs-based CryptoProvider.
29#[cfg(feature = "aws_lc_rs")]
30pub mod aws_lc_rs;
31
32/// TLS message encryption/decryption interfaces.
33pub mod cipher;
34
35/// Hashing interfaces.
36pub mod hash;
37
38/// HMAC interfaces.
39pub mod hmac;
40
41#[cfg(feature = "tls12")]
42/// Cryptography specific to TLS1.2.
43pub mod tls12;
44
45/// Cryptography specific to TLS1.3.
46pub mod tls13;
47
48/// Hybrid public key encryption (RFC 9180).
49pub mod hpke;
50
51// Message signing interfaces. Re-exported under rustls::sign. Kept crate-internal here to
52// avoid having two import paths to the same types.
53pub(crate) mod signer;
54
55pub use crate::msgs::handshake::KeyExchangeAlgorithm;
56pub use crate::rand::GetRandomFailed;
57pub use crate::suites::CipherSuiteCommon;
58
59/// Controls core cryptography used by rustls.
60///
61/// This crate comes with two built-in options, provided as
62/// `CryptoProvider` structures:
63///
64/// - [`crypto::aws_lc_rs::default_provider`] (behind the optional `aws-lc-rs` crate feature):
65///   This provider uses the [aws-lc-rs](https://github.com/aws/aws-lc-rs)
66///   crate. <!-- FIPS REMOVED FROM THIS FORK] The `fips` crate feature makes this option use FIPS140-3-approved cryptography. -->
67/// - [`crypto::ring::default_provider`] (behind the optional `ring` crate feature):
68///   This provider uses the [*ring*](https://github.com/briansmith/ring)
69///   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 a [`crypto::CryptoProvider`] struct instance.
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 ([`ConfigBuilder::with_single_cert`] etc.), it might look like this:
124///
125/// ```
126/// # #[cfg(feature = "aws_lc_rs")] {
127/// # use portable_rustls as rustls; // DOC IMPORT WORKAROUND for this fork
128/// # use std::sync::Arc;
129/// # mod fictious_hsm_api { pub fn load_private_key(key_der: pki_types::PrivateKeyDer<'static>) -> ! { unreachable!(); } }
130/// use rustls::crypto::aws_lc_rs;
131///
132/// pub fn provider() -> rustls::crypto::CryptoProvider {
133///   rustls::crypto::CryptoProvider{
134///     key_provider: &HsmKeyLoader,
135///     ..aws_lc_rs::default_provider()
136///   }
137/// }
138///
139/// #[derive(Debug)]
140/// struct HsmKeyLoader;
141///
142/// impl rustls::crypto::KeyProvider for HsmKeyLoader {
143///     fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Arc<dyn rustls::sign::SigningKey>, rustls::Error> {
144///          fictious_hsm_api::load_private_key(key_der)
145///     }
146/// }
147/// # }
148/// ```
149///
150/// ## References to the individual elements
151///
152/// The elements are documented separately:
153///
154/// - **Random** - see [`crypto::SecureRandom::fill()`].
155/// - **Cipher suites** - see [`SupportedCipherSuite`], [`Tls12CipherSuite`], and
156///   [`Tls13CipherSuite`].
157/// - **Key exchange groups** - see [`crypto::SupportedKxGroup`].
158/// - **Signature verification algorithms** - see [`crypto::WebPkiSupportedAlgorithms`].
159/// - **Authentication key loading** - see [`crypto::KeyProvider::load_private_key()`] and
160///   [`sign::SigningKey`].
161///
162/// # Example code
163///
164/// See [provider-example/] for a full client and server example that uses
165/// cryptography from the [rust-crypto] and [dalek-cryptography] projects.
166///
167/// ```shell
168/// $ cargo run --example client | head -3
169/// Current ciphersuite: TLS13_CHACHA20_POLY1305_SHA256
170/// HTTP/1.1 200 OK
171/// Content-Type: text/html; charset=utf-8
172/// Content-Length: 19899
173/// ```
174///
175/// [provider-example/]: https://github.com/brody4hire/portable-rustls/tree/main-develop-head/provider-example/
176/// [rust-crypto]: https://github.com/rustcrypto
177/// [dalek-cryptography]: https://github.com/dalek-cryptography
178///
179/// <!-- [FIPS REMOVED FROM THIS FORK]
180/// # FIPS-approved cryptography
181/// The `fips` crate feature enables use of the `aws-lc-rs` crate in FIPS mode.
182///
183/// You can verify the configuration at runtime by checking
184/// [`ServerConfig::fips()`]/[`ClientConfig::fips()`] return `true`.
185/// - END [FIPS REMOVED FROM THIS FORK] -->
186#[derive(Debug, Clone)]
187pub struct CryptoProvider {
188    /// List of supported ciphersuites, in preference order -- the first element
189    /// is the highest priority.
190    ///
191    /// The `SupportedCipherSuite` 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 cipher_suites: Vec<suites::SupportedCipherSuite>,
196
197    /// List of supported key exchange groups, in preference order -- the
198    /// first element is the highest priority.
199    ///
200    /// The first element in this list is the _default key share algorithm_,
201    /// and in TLS1.3 a key share for it is sent in the client hello.
202    ///
203    /// The `SupportedKxGroup` type carries both configuration and implementation.
204    pub kx_groups: Vec<&'static dyn SupportedKxGroup>,
205
206    /// List of signature verification algorithms for use with webpki.
207    ///
208    /// These are used for both certificate chain verification and handshake signature verification.
209    ///
210    /// This is called by [`ConfigBuilder::with_root_certificates()`],
211    /// [`server::WebPkiClientVerifier::builder_with_provider()`] and
212    /// [`client::WebPkiServerVerifier::builder_with_provider()`].
213    pub signature_verification_algorithms: WebPkiSupportedAlgorithms,
214
215    /// Source of cryptographically secure random numbers.
216    pub secure_random: &'static dyn SecureRandom,
217
218    /// Provider for loading private [SigningKey]s from [PrivateKeyDer].
219    pub key_provider: &'static dyn KeyProvider,
220}
221
222impl CryptoProvider {
223    /// Sets this `CryptoProvider` as the default for this process.
224    ///
225    /// This can be called successfully at most once in any process execution.
226    ///
227    /// Call this early in your process to configure which provider is used for
228    /// the provider.  The configuration should happen before any use of
229    /// [`ClientConfig::builder()`] or [`ServerConfig::builder()`].
230    pub fn install_default(self) -> Result<(), Arc<Self>> {
231        static_default::install_default(self)
232    }
233
234    /// Returns the default `CryptoProvider` for this process.
235    ///
236    /// This will be `None` if no default has been set yet.
237    pub fn get_default() -> Option<&'static Arc<Self>> {
238        static_default::get_default()
239    }
240
241    /// An internal function that:
242    ///
243    /// - gets the pre-installed default, or
244    /// - installs one `from_crate_features()`, or else
245    /// - panics about the need to call [`CryptoProvider::install_default()`]
246    pub(crate) fn get_default_or_install_from_crate_features() -> &'static Arc<Self> {
247        if let Some(provider) = Self::get_default() {
248            return provider;
249        }
250
251        let provider = Self::from_crate_features()
252            .expect("no process-level CryptoProvider available -- call CryptoProvider::install_default() before this point");
253        // Ignore the error resulting from us losing a race, and accept the outcome.
254        let _ = provider.install_default();
255        Self::get_default().unwrap()
256    }
257
258    /// Returns a provider named unambiguously by rustls crate features.
259    ///
260    /// This function returns `None` if the crate features are ambiguous (ie, specify two
261    /// providers), or specify no providers, or the feature `custom-provider` is activated.
262    /// In all cases the application should explicitly specify the provider to use
263    /// with [`CryptoProvider::install_default`].
264    fn from_crate_features() -> Option<Self> {
265        #[cfg(all(
266            feature = "ring",
267            not(feature = "aws_lc_rs"),
268            not(feature = "custom-provider")
269        ))]
270        {
271            return Some(ring::default_provider());
272        }
273
274        #[cfg(all(
275            feature = "aws_lc_rs",
276            not(feature = "ring"),
277            not(feature = "custom-provider")
278        ))]
279        {
280            return Some(aws_lc_rs::default_provider());
281        }
282
283        #[allow(unreachable_code)]
284        None
285    }
286
287    /// Returns `true` if this `CryptoProvider` is operating in FIPS mode.
288    ///
289    /// This covers only the cryptographic parts of FIPS approval.  There are
290    /// also TLS protocol-level recommendations made by NIST.  You should
291    /// prefer to call [`ClientConfig::fips()`] or [`ServerConfig::fips()`]
292    /// which take these into account.
293    #[cfg(unstable_api_not_supported)] // [FIPS REMOVED FROM THIS FORK]
294    pub fn fips(&self) -> bool {
295        let Self {
296            cipher_suites,
297            kx_groups,
298            signature_verification_algorithms,
299            secure_random,
300            key_provider,
301        } = self;
302        cipher_suites.iter().all(|cs| cs.fips())
303            && kx_groups.iter().all(|kx| kx.fips())
304            && signature_verification_algorithms.fips()
305            && secure_random.fips()
306            && key_provider.fips()
307    }
308}
309
310/// A source of cryptographically secure randomness.
311pub trait SecureRandom: Send + Sync + Debug {
312    /// Fill the given buffer with random bytes.
313    ///
314    /// The bytes must be sourced from a cryptographically secure random number
315    /// generator seeded with good quality, secret entropy.
316    ///
317    /// This is used for all randomness required by rustls, but not necessarily
318    /// randomness required by the underlying cryptography library.  For example:
319    /// [`SupportedKxGroup::start()`] requires random material to generate
320    /// an ephemeral key exchange key, but this is not included in the interface with
321    /// rustls: it is assumed that the cryptography library provides for this itself.
322    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
323
324    /// Return `true` if this is backed by a FIPS-approved implementation.
325    #[cfg(unstable_api_not_supported)] // [FIPS REMOVED FROM THIS FORK]
326    fn fips(&self) -> bool {
327        false
328    }
329}
330
331/// A mechanism for loading private [SigningKey]s from [PrivateKeyDer].
332///
333/// This trait is intended to be used with private key material that is sourced from DER,
334/// such as a private-key that may be present on-disk. It is not intended to be used with
335/// keys held in hardware security modules (HSMs) or physical tokens. For these use-cases
336/// see the Rustls manual section on [customizing private key usage].
337///
338/// [customizing private key usage]: <https://docs.rs/portable-rustls/latest/portable_rustls/manual/_03_howto/index.html#customising-private-key-usage>
339pub trait KeyProvider: Send + Sync + Debug {
340    /// Decode and validate a private signing key from `key_der`.
341    ///
342    /// This is used by [`ConfigBuilder::with_client_auth_cert()`], [`ConfigBuilder::with_single_cert()`],
343    /// and [`ConfigBuilder::with_single_cert_with_ocsp()`].  The key types and formats supported by this
344    /// function directly defines the key types and formats supported in those APIs.
345    ///
346    /// Return an error if the key type encoding is not supported, or if the key fails validation.
347    fn load_private_key(
348        &self,
349        key_der: PrivateKeyDer<'static>,
350    ) -> Result<Arc<dyn SigningKey>, Error>;
351
352    /// Return `true` if this is backed by a FIPS-approved implementation.
353    ///
354    /// If this returns `true`, that must be the case for all possible key types
355    /// supported by [`KeyProvider::load_private_key()`].
356    #[cfg(unstable_api_not_supported)] // [FIPS REMOVED FROM THIS FORK]
357    fn fips(&self) -> bool {
358        false
359    }
360}
361
362/// A supported key exchange group.
363///
364/// This type carries both configuration and implementation. Specifically,
365/// it has a TLS-level name expressed using the [`NamedGroup`] enum, and
366/// a function which produces a [`ActiveKeyExchange`].
367///
368/// Compare with [`NamedGroup`], which carries solely a protocol identifier.
369pub trait SupportedKxGroup: Send + Sync + Debug {
370    /// Start a key exchange.
371    ///
372    /// This will prepare an ephemeral secret key in the supported group, and a corresponding
373    /// public key. The key exchange can be completed by calling [ActiveKeyExchange#complete]
374    /// or discarded.
375    ///
376    /// # Errors
377    ///
378    /// This can fail if the random source fails during ephemeral key generation.
379    fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error>;
380
381    /// Start and complete a key exchange, in one operation.
382    ///
383    /// The default implementation for this calls `start()` and then calls
384    /// `complete()` on the result.  This is suitable for Diffie-Hellman-like
385    /// key exchange algorithms, where there is not a data dependency between
386    /// our key share (named "pub_key" in this API) and the peer's (`peer_pub_key`).
387    ///
388    /// If there is such a data dependency (like key encapsulation mechanisms), this
389    /// function should be implemented.
390    fn start_and_complete(&self, peer_pub_key: &[u8]) -> Result<CompletedKeyExchange, Error> {
391        let kx = self.start()?;
392
393        Ok(CompletedKeyExchange {
394            group: kx.group(),
395            pub_key: kx.pub_key().to_vec(),
396            secret: kx.complete(peer_pub_key)?,
397        })
398    }
399
400    /// FFDHE group the `SupportedKxGroup` operates in.
401    ///
402    /// Return `None` if this group is not a FFDHE one.
403    ///
404    /// The default implementation calls `FfdheGroup::from_named_group`: this function
405    /// is extremely linker-unfriendly so it is recommended all key exchange implementers
406    /// provide this function.
407    ///
408    /// `rustls::ffdhe_groups` contains suitable values to return from this,
409    /// for example [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
410    fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
411        #[allow(deprecated)]
412        FfdheGroup::from_named_group(self.name())
413    }
414
415    /// Named group the SupportedKxGroup operates in.
416    ///
417    /// If the `NamedGroup` enum does not have a name for the algorithm you are implementing,
418    /// you can use [`NamedGroup::Unknown`].
419    fn name(&self) -> NamedGroup;
420
421    /// Return `true` if this is backed by a FIPS-approved implementation.
422    #[cfg(unstable_api_not_supported)] // [FIPS REMOVED FROM THIS FORK]
423    fn fips(&self) -> bool {
424        false
425    }
426
427    /// Return `true` if this should be offered/selected with the given version.
428    ///
429    /// The default implementation returns true for all versions.
430    fn usable_for_version(&self, _version: ProtocolVersion) -> bool {
431        true
432    }
433}
434
435/// An in-progress key exchange originating from a [`SupportedKxGroup`].
436pub trait ActiveKeyExchange: Send + Sync {
437    /// Completes the key exchange, given the peer's public key.
438    ///
439    /// This method must return an error if `peer_pub_key` is invalid: either
440    /// mis-encoded, or an invalid public key (such as, but not limited to, being
441    /// in a small order subgroup).
442    ///
443    /// If the key exchange algorithm is FFDHE, the result must be left-padded with zeros,
444    /// as required by [RFC 8446](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1)
445    /// (see [`complete_for_tls_version()`](Self::complete_for_tls_version) for more details).
446    ///
447    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
448    /// from a `&[u8]`.
449    ///
450    /// This consumes and so terminates the [`ActiveKeyExchange`].
451    fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error>;
452
453    /// Completes the key exchange for the given TLS version, given the peer's public key.
454    ///
455    /// Note that finite-field Diffie–Hellman key exchange has different requirements for the derived
456    /// shared secret in TLS 1.2 and TLS 1.3 (ECDHE key exchange is the same in TLS 1.2 and TLS 1.3):
457    ///
458    /// In TLS 1.2, the calculated secret is required to be stripped of leading zeros
459    /// [(RFC 5246)](https://www.rfc-editor.org/rfc/rfc5246#section-8.1.2).
460    ///
461    /// In TLS 1.3, the calculated secret is required to be padded with leading zeros to be the same
462    /// byte-length as the group modulus [(RFC 8446)](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1).
463    ///
464    /// The default implementation of this method delegates to [`complete()`](Self::complete) assuming it is
465    /// implemented for TLS 1.3 (i.e., for FFDHE KX, removes padding as needed). Implementers of this trait
466    /// are encouraged to just implement [`complete()`](Self::complete) assuming TLS 1.3, and let the default
467    /// implementation of this method handle TLS 1.2-specific requirements.
468    ///
469    /// This method must return an error if `peer_pub_key` is invalid: either
470    /// mis-encoded, or an invalid public key (such as, but not limited to, being
471    /// in a small order subgroup).
472    ///
473    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
474    /// from a `&[u8]`.
475    ///
476    /// This consumes and so terminates the [`ActiveKeyExchange`].
477    fn complete_for_tls_version(
478        self: Box<Self>,
479        peer_pub_key: &[u8],
480        tls_version: &SupportedProtocolVersion,
481    ) -> Result<SharedSecret, Error> {
482        if tls_version.version != ProtocolVersion::TLSv1_2 {
483            return self.complete(peer_pub_key);
484        }
485
486        let group = self.group();
487        let mut complete_res = self.complete(peer_pub_key)?;
488        if group.key_exchange_algorithm() == KeyExchangeAlgorithm::DHE {
489            complete_res.strip_leading_zeros();
490        }
491        Ok(complete_res)
492    }
493
494    /// For hybrid key exchanges, returns the [`NamedGroup`] and key share
495    /// for the classical half of this key exchange.
496    ///
497    /// There is no requirement for a hybrid scheme (or any other!) to implement
498    /// `hybrid_component()`. It only enables an optimization; described below.
499    ///
500    /// "Hybrid" means a key exchange algorithm which is constructed from two
501    /// (or more) independent component algorithms. Usually one is post-quantum-secure,
502    /// and the other is "classical".  See
503    /// <https://datatracker.ietf.org/doc/draft-ietf-tls-hybrid-design/11/>
504    ///
505    /// # Background
506    /// Rustls always sends a presumptive key share in its `ClientHello`, using
507    /// (absent any other information) the first item in [`CryptoProvider::kx_groups`].
508    /// If the server accepts the client's selection, it can complete the handshake
509    /// using that key share.  If not, the server sends a `HelloRetryRequest` instructing
510    /// the client to send a different key share instead.
511    ///
512    /// This request costs an extra round trip, and wastes the key exchange computation
513    /// (in [`SupportedKxGroup::start()`]) the client already did.  We would
514    /// like to avoid those wastes if possible.
515    ///
516    /// It is early days for post-quantum-secure hybrid key exchange deployment.
517    /// This means (commonly) continuing to offer both the hybrid and classical
518    /// key exchanges, so the handshake can be completed without a `HelloRetryRequest`
519    /// for servers that support the offered hybrid or classical schemes.
520    ///
521    /// Implementing `hybrid_component()` enables two optimizations:
522    ///
523    /// 1. Sending both the hybrid and classical key shares in the `ClientHello`.
524    ///
525    /// 2. Performing the classical key exchange setup only once.  This is important
526    ///    because the classical key exchange setup is relatively expensive.
527    ///    This optimization is permitted and described in
528    ///    <https://www.ietf.org/archive/id/draft-ietf-tls-hybrid-design-11.html#section-3.2>
529    ///
530    /// Both of these only happen if the classical algorithm appears separately in
531    /// the client's [`CryptoProvider::kx_groups`], and if the hybrid algorithm appears
532    /// first in that list.
533    ///
534    /// # How it works
535    /// This function is only called by rustls for clients.  It is called when
536    /// constructing the initial `ClientHello`.  rustls follows these steps:
537    ///
538    /// 1. If the return value is `None`, nothing further happens.
539    /// 2. If the given [`NamedGroup`] does not appear in
540    ///    [`CryptoProvider::kx_groups`], nothing further happens.
541    /// 3. The given key share is added to the `ClientHello`, after the hybrid entry.
542    ///
543    /// Then, one of three things may happen when the server replies to the `ClientHello`:
544    ///
545    /// 1. The server sends a `HelloRetryRequest`.  Everything is thrown away and
546    ///    we start again.
547    /// 2. The server agrees to our hybrid key exchange: rustls calls
548    ///    [`ActiveKeyExchange::complete()`] consuming `self`.
549    /// 3. The server agrees to our classical key exchange: rustls calls
550    ///    [`ActiveKeyExchange::complete_hybrid_component()`] which
551    ///    discards the hybrid key data, and completes just the classical key exchange.
552    fn hybrid_component(&self) -> Option<(NamedGroup, &[u8])> {
553        None
554    }
555
556    /// Completes the classical component of the key exchange, given the peer's public key.
557    ///
558    /// This is only called if `hybrid_component` returns `Some(_)`.
559    ///
560    /// This method must return an error if `peer_pub_key` is invalid: either
561    /// mis-encoded, or an invalid public key (such as, but not limited to, being
562    /// in a small order subgroup).
563    ///
564    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
565    /// from a `&[u8]`.
566    ///
567    /// See the documentation on [`Self::hybrid_component()`] for explanation.
568    fn complete_hybrid_component(
569        self: Box<Self>,
570        _peer_pub_key: &[u8],
571    ) -> Result<SharedSecret, Error> {
572        unreachable!("only called if `hybrid_component()` implemented")
573    }
574
575    /// Return the public key being used.
576    ///
577    /// For ECDHE, the encoding required is defined in
578    /// [RFC8446 section 4.2.8.2](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.2).
579    ///
580    /// For FFDHE, the encoding required is defined in
581    /// [RFC8446 section 4.2.8.1](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.1).
582    fn pub_key(&self) -> &[u8];
583
584    /// FFDHE group the `ActiveKeyExchange` is operating in.
585    ///
586    /// Return `None` if this group is not a FFDHE one.
587    ///
588    /// The default implementation calls `FfdheGroup::from_named_group`: this function
589    /// is extremely linker-unfriendly so it is recommended all key exchange implementers
590    /// provide this function.
591    ///
592    /// `rustls::ffdhe_groups` contains suitable values to return from this,
593    /// for example [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
594    fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
595        #[allow(deprecated)]
596        FfdheGroup::from_named_group(self.group())
597    }
598
599    /// Return the group being used.
600    fn group(&self) -> NamedGroup;
601}
602
603/// The result from [`SupportedKxGroup::start_and_complete()`].
604pub struct CompletedKeyExchange {
605    /// Which group was used.
606    pub group: NamedGroup,
607
608    /// Our key share (sometimes a public key).
609    pub pub_key: Vec<u8>,
610
611    /// The computed shared secret.
612    pub secret: SharedSecret,
613}
614
615/// The result from [`ActiveKeyExchange::complete`] or [`ActiveKeyExchange::complete_hybrid_component`].
616pub struct SharedSecret {
617    buf: Vec<u8>,
618    offset: usize,
619}
620
621impl SharedSecret {
622    /// Returns the shared secret as a slice of bytes.
623    pub fn secret_bytes(&self) -> &[u8] {
624        &self.buf[self.offset..]
625    }
626
627    /// Removes leading zeros from `secret_bytes()` by adjusting the `offset`.
628    ///
629    /// This function does not re-allocate.
630    fn strip_leading_zeros(&mut self) {
631        let start = self
632            .secret_bytes()
633            .iter()
634            .enumerate()
635            .find(|(_i, x)| **x != 0)
636            .map(|(i, _x)| i)
637            .unwrap_or(self.secret_bytes().len());
638        self.offset += start;
639    }
640}
641
642impl Drop for SharedSecret {
643    fn drop(&mut self) {
644        self.buf.zeroize();
645    }
646}
647
648impl From<&[u8]> for SharedSecret {
649    fn from(source: &[u8]) -> Self {
650        Self {
651            buf: source.to_vec(),
652            offset: 0,
653        }
654    }
655}
656
657impl From<Vec<u8>> for SharedSecret {
658    fn from(buf: Vec<u8>) -> Self {
659        Self { buf, offset: 0 }
660    }
661}
662
663// [FIPS REMOVED FROM THIS FORK]
664// /// This function returns a [`CryptoProvider`] that uses
665// /// FIPS140-3-approved cryptography.
666// ...
667// pub fn default_fips_provider() ...
668
669mod static_default {
670    #[cfg(not(feature = "std"))]
671    use alloc::boxed::Box;
672    #[cfg(feature = "std")]
673    use std::sync::OnceLock;
674
675    #[cfg(not(feature = "std"))]
676    use once_cell::race::OnceBox;
677
678    use super::CryptoProvider;
679    use crate::sync::Arc;
680
681    #[cfg(feature = "std")]
682    pub(crate) fn install_default(
683        default_provider: CryptoProvider,
684    ) -> Result<(), Arc<CryptoProvider>> {
685        PROCESS_DEFAULT_PROVIDER.set(Arc::new(default_provider))
686    }
687
688    #[cfg(not(feature = "std"))]
689    pub(crate) fn install_default(
690        default_provider: CryptoProvider,
691    ) -> Result<(), Arc<CryptoProvider>> {
692        PROCESS_DEFAULT_PROVIDER
693            .set(Box::new(Arc::new(default_provider)))
694            .map_err(|e| *e)
695    }
696
697    pub(crate) fn get_default() -> Option<&'static Arc<CryptoProvider>> {
698        PROCESS_DEFAULT_PROVIDER.get()
699    }
700
701    #[cfg(feature = "std")]
702    static PROCESS_DEFAULT_PROVIDER: OnceLock<Arc<CryptoProvider>> = OnceLock::new();
703    #[cfg(not(feature = "std"))]
704    static PROCESS_DEFAULT_PROVIDER: OnceBox<Arc<CryptoProvider>> = OnceBox::new();
705}
706
707#[cfg(test)]
708mod tests {
709    use std::vec;
710
711    use super::SharedSecret;
712
713    #[test]
714    fn test_shared_secret_strip_leading_zeros() {
715        let test_cases = [
716            (vec![0, 1], vec![1]),
717            (vec![1], vec![1]),
718            (vec![1, 0, 2], vec![1, 0, 2]),
719            (vec![0, 0, 1, 2], vec![1, 2]),
720            (vec![0, 0, 0], vec![]),
721            (vec![], vec![]),
722        ];
723        for (buf, expected) in test_cases {
724            let mut secret = SharedSecret::from(&buf[..]);
725            assert_eq!(secret.secret_bytes(), buf);
726            secret.strip_leading_zeros();
727            assert_eq!(secret.secret_bytes(), expected);
728        }
729    }
730}