rustls/crypto/
mod.rs

1use alloc::boxed::Box;
2use alloc::sync::Arc;
3use alloc::vec::Vec;
4use core::fmt::Debug;
5
6#[cfg(not(feature = "std"))]
7use once_cell::race::OnceBox;
8#[cfg(feature = "std")]
9use once_cell::sync::OnceCell;
10use pki_types::PrivateKeyDer;
11use zeroize::Zeroize;
12
13use crate::msgs::ffdhe_groups::FfdheGroup;
14use crate::sign::SigningKey;
15pub use crate::webpki::{
16    verify_tls12_signature, verify_tls13_signature, WebPkiSupportedAlgorithms,
17};
18#[cfg(all(doc, feature = "tls12"))]
19use crate::Tls12CipherSuite;
20#[cfg(doc)]
21use crate::{
22    client, crypto, server, sign, ClientConfig, ConfigBuilder, ServerConfig, SupportedCipherSuite,
23    Tls13CipherSuite,
24};
25use crate::{suites, Error, NamedGroup, ProtocolVersion, SupportedProtocolVersion};
26
27/// *ring* based CryptoProvider.
28#[cfg(feature = "ring")]
29pub mod ring;
30
31/// aws-lc-rs-based CryptoProvider.
32#[cfg(feature = "aws_lc_rs")]
33pub mod aws_lc_rs;
34
35/// TLS message encryption/decryption interfaces.
36pub mod cipher;
37
38/// Hashing interfaces.
39pub mod hash;
40
41/// HMAC interfaces.
42pub mod hmac;
43
44#[cfg(feature = "tls12")]
45/// Cryptography specific to TLS1.2.
46pub mod tls12;
47
48/// Cryptography specific to TLS1.3.
49pub mod tls13;
50
51/// Hybrid public key encryption (RFC 9180).
52pub mod hpke;
53
54// Message signing interfaces. Re-exported under rustls::sign. Kept crate-internal here to
55// avoid having two import paths to the same types.
56pub(crate) mod signer;
57
58pub use crate::msgs::handshake::KeyExchangeAlgorithm;
59pub use crate::rand::GetRandomFailed;
60pub use crate::suites::CipherSuiteCommon;
61
62/// Controls core cryptography used by rustls.
63///
64/// This crate comes with two built-in options, provided as
65/// `CryptoProvider` structures:
66///
67/// - [`crypto::aws_lc_rs::default_provider`]: (behind the `aws_lc_rs` feature,
68///   which is enabled by default).  This provider uses the [aws-lc-rs](https://github.com/aws/aws-lc-rs)
69///   crate.  The `fips` crate feature makes this option use FIPS140-3-approved cryptography.
70/// - [`crypto::ring::default_provider`]: (behind the `ring` crate feature, which
71///   is optional).  This provider uses the [*ring*](https://github.com/briansmith/ring)
72///   crate.
73///
74/// This structure provides defaults. Everything in it can be overridden at
75/// runtime by replacing field values as needed.
76///
77/// # Using the per-process default `CryptoProvider`
78///
79/// There is the concept of an implicit default provider, configured at run-time once in
80/// a given process.
81///
82/// It is used for functions like [`ClientConfig::builder()`] and [`ServerConfig::builder()`].
83///
84/// The intention is that an application can specify the [`CryptoProvider`] they wish to use
85/// once, and have that apply to the variety of places where their application does TLS
86/// (which may be wrapped inside other libraries).
87/// They should do this by calling [`CryptoProvider::install_default()`] early on.
88///
89/// To achieve this goal:
90///
91/// - _libraries_ should use [`ClientConfig::builder()`]/[`ServerConfig::builder()`]
92///   or otherwise rely on the [`CryptoProvider::get_default()`] provider.
93/// - _applications_ should call [`CryptoProvider::install_default()`] early
94///   in their `fn main()`. If _applications_ uses a custom provider based on the one built-in,
95///   they can activate the `custom-provider` feature to ensure its usage.
96///
97/// # Using a specific `CryptoProvider`
98///
99/// Supply the provider when constructing your [`ClientConfig`] or [`ServerConfig`]:
100///
101/// - [`ClientConfig::builder_with_provider()`]
102/// - [`ServerConfig::builder_with_provider()`]
103///
104/// When creating and configuring a webpki-backed client or server certificate verifier, a choice of
105/// provider is also needed to start the configuration process:
106///
107/// - [`client::WebPkiServerVerifier::builder_with_provider()`]
108/// - [`server::WebPkiClientVerifier::builder_with_provider()`]
109///
110/// If you install a custom provider and want to avoid any accidental use of a built-in provider, the feature
111/// `custom-provider` can be activated to ensure your custom provider is used everywhere
112/// and not a built-in one. This will disable any implicit use of a built-in provider.
113///
114/// # Making a custom `CryptoProvider`
115///
116/// Your goal will be to populate a [`crypto::CryptoProvider`] struct instance.
117///
118/// ## Which elements are required?
119///
120/// There is no requirement that the individual elements (`SupportedCipherSuite`, `SupportedKxGroup`,
121/// `SigningKey`, etc.) come from the same crate.  It is allowed and expected that uninteresting
122/// elements would be delegated back to one of the default providers (statically) or a parent
123/// provider (dynamically).
124///
125/// For example, if we want to make a provider that just overrides key loading in the config builder
126/// API ([`ConfigBuilder::with_single_cert`] etc.), it might look like this:
127///
128/// ```
129/// # #[cfg(feature = "aws_lc_rs")] {
130/// # use std::sync::Arc;
131/// # mod fictious_hsm_api { pub fn load_private_key(key_der: pki_types::PrivateKeyDer<'static>) -> ! { unreachable!(); } }
132/// use rustls::crypto::aws_lc_rs;
133///
134/// pub fn provider() -> rustls::crypto::CryptoProvider {
135///   rustls::crypto::CryptoProvider{
136///     key_provider: &HsmKeyLoader,
137///     ..aws_lc_rs::default_provider()
138///   }
139/// }
140///
141/// #[derive(Debug)]
142/// struct HsmKeyLoader;
143///
144/// impl rustls::crypto::KeyProvider for HsmKeyLoader {
145///     fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Arc<dyn rustls::sign::SigningKey>, rustls::Error> {
146///          fictious_hsm_api::load_private_key(key_der)
147///     }
148/// }
149/// # }
150/// ```
151///
152/// ## References to the individual elements
153///
154/// The elements are documented separately:
155///
156/// - **Random** - see [`crypto::SecureRandom::fill()`].
157/// - **Cipher suites** - see [`SupportedCipherSuite`], [`Tls12CipherSuite`], and
158///   [`Tls13CipherSuite`].
159/// - **Key exchange groups** - see [`crypto::SupportedKxGroup`].
160/// - **Signature verification algorithms** - see [`crypto::WebPkiSupportedAlgorithms`].
161/// - **Authentication key loading** - see [`crypto::KeyProvider::load_private_key()`] and
162///   [`sign::SigningKey`].
163///
164/// # Example code
165///
166/// See [provider-example/] for a full client and server example that uses
167/// cryptography from the [rust-crypto] and [dalek-cryptography] projects.
168///
169/// ```shell
170/// $ cargo run --example client | head -3
171/// Current ciphersuite: TLS13_CHACHA20_POLY1305_SHA256
172/// HTTP/1.1 200 OK
173/// Content-Type: text/html; charset=utf-8
174/// Content-Length: 19899
175/// ```
176///
177/// [provider-example/]: https://github.com/rustls/rustls/tree/main/provider-example/
178/// [rust-crypto]: https://github.com/rustcrypto
179/// [dalek-cryptography]: https://github.com/dalek-cryptography
180///
181/// # FIPS-approved cryptography
182/// The `fips` crate feature enables use of the `aws-lc-rs` crate in FIPS mode.
183///
184/// You can verify the configuration at runtime by checking
185/// [`ServerConfig::fips()`]/[`ClientConfig::fips()`] return `true`.
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    #[cfg(feature = "std")]
231    pub fn install_default(self) -> Result<(), Arc<Self>> {
232        PROCESS_DEFAULT_PROVIDER.set(Arc::new(self))
233    }
234
235    /// Sets this `CryptoProvider` as the default for this process.
236    ///
237    /// This can be called successfully at most once in any process execution.
238    ///
239    /// Call this early in your process to configure which provider is used for
240    /// the provider.  The configuration should happen before any use of
241    /// [`ClientConfig::builder()`] or [`ServerConfig::builder()`].
242    #[cfg(not(feature = "std"))]
243    pub fn install_default(self) -> Result<(), Box<Arc<Self>>> {
244        PROCESS_DEFAULT_PROVIDER.set(Box::new(Arc::new(self)))
245    }
246
247    /// Returns the default `CryptoProvider` for this process.
248    ///
249    /// This will be `None` if no default has been set yet.
250    pub fn get_default() -> Option<&'static Arc<Self>> {
251        PROCESS_DEFAULT_PROVIDER.get()
252    }
253
254    /// An internal function that:
255    ///
256    /// - gets the pre-installed default, or
257    /// - installs one `from_crate_features()`, or else
258    /// - panics about the need to call [`CryptoProvider::install_default()`]
259    pub(crate) fn get_default_or_install_from_crate_features() -> &'static Arc<Self> {
260        if let Some(provider) = Self::get_default() {
261            return provider;
262        }
263
264        let provider = Self::from_crate_features()
265            .expect("no process-level CryptoProvider available -- call CryptoProvider::install_default() before this point");
266        // Ignore the error resulting from us losing a race, and accept the outcome.
267        let _ = provider.install_default();
268        Self::get_default().unwrap()
269    }
270
271    /// Returns a provider named unambiguously by rustls crate features.
272    ///
273    /// This function returns `None` if the crate features are ambiguous (ie, specify two
274    /// providers), or specify no providers, or the feature `custom-provider` is activated.
275    /// In all cases the application should explicitly specify the provider to use
276    /// with [`CryptoProvider::install_default`].
277    fn from_crate_features() -> Option<Self> {
278        #[cfg(all(
279            feature = "ring",
280            not(feature = "aws_lc_rs"),
281            not(feature = "custom-provider")
282        ))]
283        {
284            return Some(ring::default_provider());
285        }
286
287        #[cfg(all(
288            feature = "aws_lc_rs",
289            not(feature = "ring"),
290            not(feature = "custom-provider")
291        ))]
292        {
293            return Some(aws_lc_rs::default_provider());
294        }
295
296        #[allow(unreachable_code)]
297        None
298    }
299
300    /// Returns `true` if this `CryptoProvider` is operating in FIPS mode.
301    ///
302    /// This covers only the cryptographic parts of FIPS approval.  There are
303    /// also TLS protocol-level recommendations made by NIST.  You should
304    /// prefer to call [`ClientConfig::fips()`] or [`ServerConfig::fips()`]
305    /// which take these into account.
306    pub fn fips(&self) -> bool {
307        let Self {
308            cipher_suites,
309            kx_groups,
310            signature_verification_algorithms,
311            secure_random,
312            key_provider,
313        } = self;
314        cipher_suites.iter().all(|cs| cs.fips())
315            && kx_groups.iter().all(|kx| kx.fips())
316            && signature_verification_algorithms.fips()
317            && secure_random.fips()
318            && key_provider.fips()
319    }
320}
321
322#[cfg(feature = "std")]
323static PROCESS_DEFAULT_PROVIDER: OnceCell<Arc<CryptoProvider>> = OnceCell::new();
324#[cfg(not(feature = "std"))]
325static PROCESS_DEFAULT_PROVIDER: OnceBox<Arc<CryptoProvider>> = OnceBox::new();
326
327/// A source of cryptographically secure randomness.
328pub trait SecureRandom: Send + Sync + Debug {
329    /// Fill the given buffer with random bytes.
330    ///
331    /// The bytes must be sourced from a cryptographically secure random number
332    /// generator seeded with good quality, secret entropy.
333    ///
334    /// This is used for all randomness required by rustls, but not necessarily
335    /// randomness required by the underlying cryptography library.  For example:
336    /// [`SupportedKxGroup::start()`] requires random material to generate
337    /// an ephemeral key exchange key, but this is not included in the interface with
338    /// rustls: it is assumed that the cryptography library provides for this itself.
339    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
340
341    /// Return `true` if this is backed by a FIPS-approved implementation.
342    fn fips(&self) -> bool {
343        false
344    }
345}
346
347/// A mechanism for loading private [SigningKey]s from [PrivateKeyDer].
348///
349/// This trait is intended to be used with private key material that is sourced from DER,
350/// such as a private-key that may be present on-disk. It is not intended to be used with
351/// keys held in hardware security modules (HSMs) or physical tokens. For these use-cases
352/// see the Rustls manual section on [customizing private key usage].
353///
354/// [customizing private key usage]: <https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#customising-private-key-usage>
355pub trait KeyProvider: Send + Sync + Debug {
356    /// Decode and validate a private signing key from `key_der`.
357    ///
358    /// This is used by [`ConfigBuilder::with_client_auth_cert()`], [`ConfigBuilder::with_single_cert()`],
359    /// and [`ConfigBuilder::with_single_cert_with_ocsp()`].  The key types and formats supported by this
360    /// function directly defines the key types and formats supported in those APIs.
361    ///
362    /// Return an error if the key type encoding is not supported, or if the key fails validation.
363    fn load_private_key(
364        &self,
365        key_der: PrivateKeyDer<'static>,
366    ) -> Result<Arc<dyn SigningKey>, Error>;
367
368    /// Return `true` if this is backed by a FIPS-approved implementation.
369    ///
370    /// If this returns `true`, that must be the case for all possible key types
371    /// supported by [`KeyProvider::load_private_key()`].
372    fn fips(&self) -> bool {
373        false
374    }
375}
376
377/// A supported key exchange group.
378///
379/// This type carries both configuration and implementation. Specifically,
380/// it has a TLS-level name expressed using the [`NamedGroup`] enum, and
381/// a function which produces a [`ActiveKeyExchange`].
382///
383/// Compare with [`NamedGroup`], which carries solely a protocol identifier.
384pub trait SupportedKxGroup: Send + Sync + Debug {
385    /// Start a key exchange.
386    ///
387    /// This will prepare an ephemeral secret key in the supported group, and a corresponding
388    /// public key. The key exchange can be completed by calling [ActiveKeyExchange#complete]
389    /// or discarded.
390    ///
391    /// # Errors
392    ///
393    /// This can fail if the random source fails during ephemeral key generation.
394    fn start(&self) -> Result<Box<dyn ActiveKeyExchange>, Error>;
395
396    /// Start and complete a key exchange, in one operation.
397    ///
398    /// The default implementation for this calls `start()` and then calls
399    /// `complete()` on the result.  This is suitable for Diffie-Hellman-like
400    /// key exchange algorithms, where there is not a data dependency between
401    /// our key share (named "pub_key" in this API) and the peer's (`peer_pub_key`).
402    ///
403    /// If there is such a data dependency (like key encapsulation mechanisms), this
404    /// function should be implemented.
405    fn start_and_complete(&self, peer_pub_key: &[u8]) -> Result<CompletedKeyExchange, Error> {
406        let kx = self.start()?;
407
408        Ok(CompletedKeyExchange {
409            group: kx.group(),
410            pub_key: kx.pub_key().to_vec(),
411            secret: kx.complete(peer_pub_key)?,
412        })
413    }
414
415    /// FFDHE group the `SupportedKxGroup` operates in.
416    ///
417    /// Return `None` if this group is not a FFDHE one.
418    ///
419    /// The default implementation calls `FfdheGroup::from_named_group`: this function
420    /// is extremely linker-unfriendly so it is recommended all key exchange implementers
421    /// provide this function.
422    ///
423    /// `rustls::ffdhe_groups` contains suitable values to return from this,
424    /// for example [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
425    fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
426        #[allow(deprecated)]
427        FfdheGroup::from_named_group(self.name())
428    }
429
430    /// Named group the SupportedKxGroup operates in.
431    ///
432    /// If the `NamedGroup` enum does not have a name for the algorithm you are implementing,
433    /// you can use [`NamedGroup::Unknown`].
434    fn name(&self) -> NamedGroup;
435
436    /// Return `true` if this is backed by a FIPS-approved implementation.
437    fn fips(&self) -> bool {
438        false
439    }
440}
441
442/// An in-progress key exchange originating from a [`SupportedKxGroup`].
443pub trait ActiveKeyExchange: Send + Sync {
444    /// Completes the key exchange, given the peer's public key.
445    ///
446    /// This method must return an error if `peer_pub_key` is invalid: either
447    /// mis-encoded, or an invalid public key (such as, but not limited to, being
448    /// in a small order subgroup).
449    ///
450    /// If the key exchange algorithm is FFDHE, the result must be left-padded with zeros,
451    /// as required by [RFC 8446](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1)
452    /// (see [`complete_for_tls_version()`](Self::complete_for_tls_version) for more details).
453    ///
454    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
455    /// from a `&[u8]`.
456    ///
457    /// This consumes and so terminates the [`ActiveKeyExchange`].
458    fn complete(self: Box<Self>, peer_pub_key: &[u8]) -> Result<SharedSecret, Error>;
459
460    /// Completes the key exchange for the given TLS version, given the peer's public key.
461    ///
462    /// Note that finite-field Diffie–Hellman key exchange has different requirements for the derived
463    /// shared secret in TLS 1.2 and TLS 1.3 (ECDHE key exchange is the same in TLS 1.2 and TLS 1.3):
464    ///
465    /// In TLS 1.2, the calculated secret is required to be stripped of leading zeros
466    /// [(RFC 5246)](https://www.rfc-editor.org/rfc/rfc5246#section-8.1.2).
467    ///
468    /// In TLS 1.3, the calculated secret is required to be padded with leading zeros to be the same
469    /// byte-length as the group modulus [(RFC 8446)](https://www.rfc-editor.org/rfc/rfc8446#section-7.4.1).
470    ///
471    /// The default implementation of this method delegates to [`complete()`](Self::complete) assuming it is
472    /// implemented for TLS 1.3 (i.e., for FFDHE KX, removes padding as needed). Implementers of this trait
473    /// are encouraged to just implement [`complete()`](Self::complete) assuming TLS 1.3, and let the default
474    /// implementation of this method handle TLS 1.2-specific requirements.
475    ///
476    /// This method must return an error if `peer_pub_key` is invalid: either
477    /// mis-encoded, or an invalid public key (such as, but not limited to, being
478    /// in a small order subgroup).
479    ///
480    /// The shared secret is returned as a [`SharedSecret`] which can be constructed
481    /// from a `&[u8]`.
482    ///
483    /// This consumes and so terminates the [`ActiveKeyExchange`].
484    fn complete_for_tls_version(
485        self: Box<Self>,
486        peer_pub_key: &[u8],
487        tls_version: &SupportedProtocolVersion,
488    ) -> Result<SharedSecret, Error> {
489        if tls_version.version != ProtocolVersion::TLSv1_2 {
490            return self.complete(peer_pub_key);
491        }
492
493        let group = self.group();
494        let mut complete_res = self.complete(peer_pub_key)?;
495        if group.key_exchange_algorithm() == KeyExchangeAlgorithm::DHE {
496            complete_res.strip_leading_zeros();
497        }
498        Ok(complete_res)
499    }
500
501    /// Return the public key being used.
502    ///
503    /// For ECDHE, the encoding required is defined in
504    /// [RFC8446 section 4.2.8.2](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.2).
505    ///
506    /// For FFDHE, the encoding required is defined in
507    /// [RFC8446 section 4.2.8.1](https://www.rfc-editor.org/rfc/rfc8446#section-4.2.8.1).
508    fn pub_key(&self) -> &[u8];
509
510    /// FFDHE group the `ActiveKeyExchange` is operating in.
511    ///
512    /// Return `None` if this group is not a FFDHE one.
513    ///
514    /// The default implementation calls `FfdheGroup::from_named_group`: this function
515    /// is extremely linker-unfriendly so it is recommended all key exchange implementers
516    /// provide this function.
517    ///
518    /// `rustls::ffdhe_groups` contains suitable values to return from this,
519    /// for example [`rustls::ffdhe_groups::FFDHE2048`][crate::ffdhe_groups::FFDHE2048].
520    fn ffdhe_group(&self) -> Option<FfdheGroup<'static>> {
521        #[allow(deprecated)]
522        FfdheGroup::from_named_group(self.group())
523    }
524
525    /// Return the group being used.
526    fn group(&self) -> NamedGroup;
527}
528
529/// The result from [`SupportedKxGroup::start_and_complete()`].
530pub struct CompletedKeyExchange {
531    /// Which group was used.
532    pub group: NamedGroup,
533
534    /// Our key share (sometimes a public key).
535    pub pub_key: Vec<u8>,
536
537    /// The computed shared secret.
538    pub secret: SharedSecret,
539}
540
541/// The result from [`ActiveKeyExchange::complete`].
542pub struct SharedSecret {
543    buf: Vec<u8>,
544    offset: usize,
545}
546
547impl SharedSecret {
548    /// Returns the shared secret as a slice of bytes.
549    pub fn secret_bytes(&self) -> &[u8] {
550        &self.buf[self.offset..]
551    }
552
553    /// Removes leading zeros from `secret_bytes()` by adjusting the `offset`.
554    ///
555    /// This function does not re-allocate.
556    fn strip_leading_zeros(&mut self) {
557        let start = self
558            .secret_bytes()
559            .iter()
560            .enumerate()
561            .find(|(_i, x)| **x != 0)
562            .map(|(i, _x)| i)
563            .unwrap_or(self.secret_bytes().len());
564        self.offset += start;
565    }
566}
567
568impl Drop for SharedSecret {
569    fn drop(&mut self) {
570        self.buf.zeroize();
571    }
572}
573
574impl From<&[u8]> for SharedSecret {
575    fn from(source: &[u8]) -> Self {
576        Self {
577            buf: source.to_vec(),
578            offset: 0,
579        }
580    }
581}
582
583/// This function returns a [`CryptoProvider`] that uses
584/// FIPS140-3-approved cryptography.
585///
586/// Using this function expresses in your code that you require
587/// FIPS-approved cryptography, and will not compile if you make
588/// a mistake with cargo features.
589///
590/// See our [FIPS documentation](crate::manual::_06_fips) for
591/// more detail.
592///
593/// Install this as the process-default provider, like:
594///
595/// ```rust
596/// # #[cfg(feature = "fips")] {
597/// rustls::crypto::default_fips_provider().install_default()
598///     .expect("default provider already set elsewhere");
599/// # }
600/// ```
601///
602/// You can also use this explicitly, like:
603///
604/// ```rust
605/// # #[cfg(feature = "fips")] {
606/// # let root_store = rustls::RootCertStore::empty();
607/// let config = rustls::ClientConfig::builder_with_provider(
608///         rustls::crypto::default_fips_provider().into()
609///     )
610///     .with_safe_default_protocol_versions()
611///     .unwrap()
612///     .with_root_certificates(root_store)
613///     .with_no_client_auth();
614/// # }
615/// ```
616#[cfg(all(feature = "aws_lc_rs", any(feature = "fips", docsrs)))]
617#[cfg_attr(docsrs, doc(cfg(feature = "fips")))]
618pub fn default_fips_provider() -> CryptoProvider {
619    aws_lc_rs::default_provider()
620}
621
622#[cfg(test)]
623mod tests {
624    use std::vec;
625
626    use super::SharedSecret;
627
628    #[test]
629    fn test_shared_secret_strip_leading_zeros() {
630        let test_cases = [
631            (vec![0, 1], vec![1]),
632            (vec![1], vec![1]),
633            (vec![1, 0, 2], vec![1, 0, 2]),
634            (vec![0, 0, 1, 2], vec![1, 2]),
635            (vec![0, 0, 0], vec![]),
636            (vec![], vec![]),
637        ];
638        for (buf, expected) in test_cases {
639            let mut secret = SharedSecret::from(&buf[..]);
640            assert_eq!(secret.secret_bytes(), buf);
641            secret.strip_leading_zeros();
642            assert_eq!(secret.secret_bytes(), expected);
643        }
644    }
645}