Skip to main content

rustls/crypto/
mod.rs

1use alloc::borrow::Cow;
2use alloc::boxed::Box;
3use alloc::vec::Vec;
4use core::borrow::Borrow;
5use core::fmt::{self, Debug};
6use core::hash::{Hash, Hasher};
7use core::time::Duration;
8
9use pki_types::{FipsStatus, PrivateKeyDer, SignatureVerificationAlgorithm};
10
11use crate::enums::ProtocolVersion;
12#[cfg(feature = "webpki")]
13use crate::error::PeerMisbehaved;
14use crate::error::{ApiMisuse, Error};
15use crate::msgs::ALL_KEY_EXCHANGE_ALGORITHMS;
16use crate::sync::Arc;
17#[cfg(feature = "webpki")]
18pub use crate::webpki::{verify_tls12_signature, verify_tls13_signature};
19#[cfg(doc)]
20use crate::{ClientConfig, ConfigBuilder, ServerConfig, client, crypto, server};
21use crate::{SupportedCipherSuite, Tls12CipherSuite, Tls13CipherSuite};
22
23/// TLS message encryption/decryption interfaces.
24pub mod cipher;
25
26mod enums;
27pub use enums::{CipherSuite, HashAlgorithm, SignatureAlgorithm, SignatureScheme};
28
29/// Hashing interfaces.
30pub mod hash;
31
32/// HMAC interfaces.
33pub mod hmac;
34
35/// Key exchange interfaces.
36pub mod kx;
37use kx::{NamedGroup, SupportedKxGroup};
38
39/// Cryptography specific to TLS1.2.
40pub mod tls12;
41
42/// Cryptography specific to TLS1.3.
43pub mod tls13;
44
45/// Hybrid public key encryption (RFC 9180).
46pub mod hpke;
47
48#[cfg(any(doc, test))]
49pub(crate) mod test_provider;
50#[cfg(test)]
51pub(crate) use test_provider::TEST_PROVIDER;
52#[cfg(doc)]
53#[doc(hidden)]
54pub use test_provider::TEST_PROVIDER;
55#[cfg(all(test, any(target_arch = "aarch64", target_arch = "x86_64")))]
56pub(crate) use test_provider::TLS13_TEST_SUITE;
57
58// Message signing interfaces.
59mod signer;
60pub use signer::{
61    CertificateIdentity, Credentials, Identity, InconsistentKeys, SelectedCredential, Signer,
62    SigningKey, SingleCredential, public_key_to_spki,
63};
64
65pub use crate::suites::CipherSuiteCommon;
66
67/// Controls core cryptography used by rustls.
68///
69/// This structure provides defaults. Everything in it can be overridden at
70/// runtime by replacing field values as needed.
71///
72/// # Using the per-process default `CryptoProvider`
73///
74/// If it is hard to pass a specific `CryptoProvider` to all callers that need to establish
75/// TLS connections, you can store a per-process `CryptoProvider` default via
76/// [`CryptoProvider::install_default()`]. When initializing a `ClientConfig` or `ServerConfig` via
77/// [`ClientConfig::builder()`] or [`ServerConfig::builder()`], you can obtain the installed
78/// provider via [`CryptoProvider::get_default()`].
79///
80/// The intention is that an application can specify the [`CryptoProvider`] they wish to use
81/// once, and have that apply to the variety of places where their application does TLS
82/// (which may be wrapped inside other libraries).
83/// They should do this by calling [`CryptoProvider::install_default()`] early on.
84///
85/// To achieve this goal:
86///
87/// - _libraries_ should use [`ClientConfig::builder()`]/[`ServerConfig::builder()`]
88///   or otherwise rely on the [`CryptoProvider::get_default()`] provider.
89/// - _applications_ should call [`CryptoProvider::install_default()`] early
90///   in their `fn main()`.
91///
92/// # Using a specific `CryptoProvider`
93///
94/// Supply the provider when constructing your [`ClientConfig`] or [`ServerConfig`]:
95///
96/// - [`ClientConfig::builder()`][crate::ClientConfig::builder()]
97/// - [`ServerConfig::builder()`][crate::ServerConfig::builder()]
98///
99/// When creating and configuring a webpki-backed client or server certificate verifier, a choice of
100/// provider is also needed to start the configuration process:
101///
102/// - [`WebPkiServerVerifier::builder()`][crate::client::WebPkiServerVerifier::builder()]
103/// - [`WebPkiClientVerifier::builder()`][crate::server::WebPkiClientVerifier::builder()]
104///
105/// # Making a custom `CryptoProvider`
106///
107/// Your goal will be to populate an instance of this `CryptoProvider` struct.
108///
109/// ## Which elements are required?
110///
111/// There is no requirement that the individual elements ([`SupportedCipherSuite`], [`SupportedKxGroup`],
112/// [`SigningKey`], etc.) come from the same crate.  It is allowed and expected that uninteresting
113/// elements would be delegated back to one of the default providers (statically) or a parent
114/// provider (dynamically).
115///
116/// For example, if we want to make a provider that just overrides key loading in the config builder
117/// API (with [`ConfigBuilder::with_single_cert`], etc.), it might look like this:
118///
119/// ```
120/// # #[cfg(feature = "aws-lc-rs")] {
121/// # use std::sync::Arc;
122/// # mod fictitious_hsm_api { pub fn load_private_key(key_der: pki_types::PrivateKeyDer<'static>) -> ! { unreachable!(); } }
123/// use rustls::crypto::aws_lc_rs;
124///
125/// pub fn provider() -> rustls::crypto::CryptoProvider {
126///   rustls::crypto::CryptoProvider{
127///     key_provider: &HsmKeyLoader,
128///     ..aws_lc_rs::DEFAULT_PROVIDER
129///   }
130/// }
131///
132/// #[derive(Debug)]
133/// struct HsmKeyLoader;
134///
135/// impl rustls::crypto::KeyProvider for HsmKeyLoader {
136///     fn load_private_key(&self, key_der: pki_types::PrivateKeyDer<'static>) -> Result<Box<dyn rustls::crypto::SigningKey>, rustls::Error> {
137///          fictitious_hsm_api::load_private_key(key_der)
138///     }
139/// }
140/// # }
141/// ```
142///
143/// ## References to the individual elements
144///
145/// The elements are documented separately:
146///
147/// - **Random** - see [`SecureRandom::fill()`].
148/// - **Cipher suites** - see [`SupportedCipherSuite`], [`Tls12CipherSuite`], and
149///   [`Tls13CipherSuite`].
150/// - **Key exchange groups** - see [`SupportedKxGroup`].
151/// - **Signature verification algorithms** - see [`WebPkiSupportedAlgorithms`].
152/// - **Authentication key loading** - see [`KeyProvider::load_private_key()`] and
153///   [`SigningKey`].
154///
155/// # Example code
156///
157/// See custom [`provider-example/`] for a full client and server example that uses
158/// cryptography from the [`RustCrypto`] and [`dalek-cryptography`] projects.
159///
160/// ```shell
161/// $ cargo run --example client | head -3
162/// Current ciphersuite: TLS13_CHACHA20_POLY1305_SHA256
163/// HTTP/1.1 200 OK
164/// Content-Type: text/html; charset=utf-8
165/// Content-Length: 19899
166/// ```
167///
168/// [`provider-example/`]: https://github.com/rustls/rustls/tree/main/provider-example/
169/// [`RustCrypto`]: https://github.com/RustCrypto
170/// [`dalek-cryptography`]: https://github.com/dalek-cryptography
171///
172/// # FIPS-approved cryptography
173///
174/// Each element of a `CryptoProvider` may be implemented using FIPS-approved cryptography,
175/// and the FIPS status of the overall provider is derived from the status of its elements.
176/// Call [`CryptoProvider::fips()`] to determine the FIPS status of a given provider.
177///
178/// You can verify the configuration at runtime by checking
179/// [`ServerConfig::fips()`]/[`ClientConfig::fips()`] return `true`.
180#[expect(clippy::exhaustive_structs)]
181#[derive(Debug, Clone)]
182pub struct CryptoProvider {
183    /// List of supported TLS1.2 cipher suites, in preference order -- the first element
184    /// is the highest priority.
185    ///
186    /// Note that the protocol version is negotiated before the cipher suite.
187    ///
188    /// The `Tls12CipherSuite` type carries both configuration and implementation.
189    ///
190    /// A valid `CryptoProvider` must ensure that all cipher suites are accompanied by at least
191    /// one matching key exchange group in [`CryptoProvider::kx_groups`].
192    pub tls12_cipher_suites: Cow<'static, [&'static Tls12CipherSuite]>,
193
194    /// List of supported TLS1.3 cipher suites, in preference order -- the first element
195    /// is the highest priority.
196    ///
197    /// Note that the protocol version is negotiated before the cipher suite.
198    ///
199    /// The `Tls13CipherSuite` type carries both configuration and implementation.
200    pub tls13_cipher_suites: Cow<'static, [&'static Tls13CipherSuite]>,
201
202    /// List of supported key exchange groups, in preference order -- the
203    /// first element is the highest priority.
204    ///
205    /// The first element in this list is the _default key share algorithm_,
206    /// and in TLS1.3 a key share for it is sent in the client hello.
207    ///
208    /// The `SupportedKxGroup` type carries both configuration and implementation.
209    pub kx_groups: Cow<'static, [&'static dyn SupportedKxGroup]>,
210
211    /// List of signature verification algorithms for use with webpki.
212    ///
213    /// These are used for both certificate chain verification and handshake signature verification.
214    ///
215    /// This is called by [`ConfigBuilder::with_root_certificates()`],
216    /// [`server::WebPkiClientVerifier::builder()`] and
217    /// [`client::WebPkiServerVerifier::builder()`].
218    pub signature_verification_algorithms: WebPkiSupportedAlgorithms,
219
220    /// Source of cryptographically secure random numbers.
221    pub secure_random: &'static dyn SecureRandom,
222
223    /// Provider for loading private [`SigningKey`]s from [`PrivateKeyDer`].
224    pub key_provider: &'static dyn KeyProvider,
225
226    /// Provider for creating [`TicketProducer`]s for stateless session resumption.
227    pub ticketer_factory: &'static dyn TicketerFactory,
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    /// After calling this, other callers can obtain a reference to the installed
236    /// default via [`CryptoProvider::get_default()`].
237    pub fn install_default(self) -> Result<(), Arc<Self>> {
238        static_default::install_default(self)
239    }
240}
241
242impl CryptoProvider {
243    /// Returns the default `CryptoProvider` for this process.
244    ///
245    /// This will be `None` if no default has been set yet.
246    pub fn get_default() -> Option<&'static Arc<Self>> {
247        static_default::get_default()
248    }
249
250    /// Return the FIPS validation status for this `CryptoProvider`.
251    ///
252    /// This covers only the cryptographic parts of FIPS approval.  There are
253    /// also TLS protocol-level recommendations made by NIST.  You should
254    /// prefer to call [`ClientConfig::fips()`] or [`ServerConfig::fips()`]
255    /// which take these into account.
256    pub fn fips(&self) -> FipsStatus {
257        let Self {
258            tls12_cipher_suites,
259            tls13_cipher_suites,
260            kx_groups,
261            signature_verification_algorithms,
262            secure_random,
263            key_provider,
264            ticketer_factory,
265        } = self;
266
267        let mut status = Ord::min(
268            signature_verification_algorithms.fips(),
269            secure_random.fips(),
270        );
271        status = Ord::min(status, key_provider.fips());
272        status = Ord::min(status, ticketer_factory.fips());
273        for cs in tls12_cipher_suites.iter() {
274            status = Ord::min(status, cs.fips());
275        }
276        for cs in tls13_cipher_suites.iter() {
277            status = Ord::min(status, cs.fips());
278        }
279        for kx in kx_groups.iter() {
280            status = Ord::min(status, kx.fips());
281        }
282
283        status
284    }
285
286    pub(crate) fn consistency_check(&self) -> Result<(), Error> {
287        if self.tls12_cipher_suites.is_empty() && self.tls13_cipher_suites.is_empty() {
288            return Err(ApiMisuse::NoCipherSuitesConfigured.into());
289        }
290
291        if self.kx_groups.is_empty() {
292            return Err(ApiMisuse::NoKeyExchangeGroupsConfigured.into());
293        }
294
295        // verifying cipher suites have matching kx groups
296        let mut supported_kx_algos = Vec::with_capacity(ALL_KEY_EXCHANGE_ALGORITHMS.len());
297        for group in self.kx_groups.iter() {
298            let kx = group.name().key_exchange_algorithm();
299            if !supported_kx_algos.contains(&kx) {
300                supported_kx_algos.push(kx);
301            }
302            // Small optimization. We don't need to go over other key exchange groups
303            // if we already cover all supported key exchange algorithms
304            if supported_kx_algos.len() == ALL_KEY_EXCHANGE_ALGORITHMS.len() {
305                break;
306            }
307        }
308
309        for cs in self.tls12_cipher_suites.iter() {
310            if supported_kx_algos.contains(&cs.kx) {
311                continue;
312            }
313            let suite_name = cs.common.suite;
314            return Err(Error::General(alloc::format!(
315                "TLS1.2 cipher suite {suite_name:?} requires {0:?} key exchange, but no {0:?}-compatible \
316                key exchange groups were present in `CryptoProvider`'s `kx_groups` field",
317                cs.kx,
318            )));
319        }
320
321        Ok(())
322    }
323
324    pub(crate) fn iter_cipher_suites(&self) -> impl Iterator<Item = SupportedCipherSuite> + '_ {
325        self.tls13_cipher_suites
326            .iter()
327            .copied()
328            .map(SupportedCipherSuite::Tls13)
329            .chain(
330                self.tls12_cipher_suites
331                    .iter()
332                    .copied()
333                    .map(SupportedCipherSuite::Tls12),
334            )
335    }
336
337    /// We support a given TLS version if at least one ciphersuite for the version
338    /// is available.
339    pub(crate) fn supports_version(&self, v: ProtocolVersion) -> bool {
340        match v {
341            ProtocolVersion::TLSv1_2 => !self.tls12_cipher_suites.is_empty(),
342            ProtocolVersion::TLSv1_3 => !self.tls13_cipher_suites.is_empty(),
343            _ => false,
344        }
345    }
346
347    pub(crate) fn find_kx_group(
348        &self,
349        name: NamedGroup,
350        version: ProtocolVersion,
351    ) -> Option<&'static dyn SupportedKxGroup> {
352        if !name.usable_for_version(version) {
353            return None;
354        }
355        self.kx_groups
356            .iter()
357            .find(|skxg| skxg.name() == name)
358            .copied()
359    }
360}
361
362impl Borrow<[&'static Tls12CipherSuite]> for CryptoProvider {
363    fn borrow(&self) -> &[&'static Tls12CipherSuite] {
364        &self.tls12_cipher_suites
365    }
366}
367
368impl Borrow<[&'static Tls13CipherSuite]> for CryptoProvider {
369    fn borrow(&self) -> &[&'static Tls13CipherSuite] {
370        &self.tls13_cipher_suites
371    }
372}
373
374/// Describes which `webpki` signature verification algorithms are supported and
375/// how they map to TLS [`SignatureScheme`]s.
376#[expect(clippy::exhaustive_structs)]
377#[derive(Clone, Copy)]
378pub struct WebPkiSupportedAlgorithms {
379    /// A list of all supported signature verification algorithms.
380    ///
381    /// Used for verifying certificate chains.
382    ///
383    /// The order of this list is not significant.
384    pub all: &'static [&'static dyn SignatureVerificationAlgorithm],
385
386    /// A mapping from TLS `SignatureScheme`s to matching webpki signature verification algorithms.
387    ///
388    /// This is one (`SignatureScheme`) to many ([`SignatureVerificationAlgorithm`]) because
389    /// (depending on the protocol version) there is not necessary a 1-to-1 mapping.
390    ///
391    /// For TLS1.2, all `SignatureVerificationAlgorithm`s are tried in sequence.
392    ///
393    /// For TLS1.3, only the first is tried.
394    ///
395    /// The supported schemes in this mapping is communicated to the peer and the order is significant.
396    /// The first mapping is our highest preference.
397    pub mapping: &'static [(
398        SignatureScheme,
399        &'static [&'static dyn SignatureVerificationAlgorithm],
400    )],
401}
402
403impl WebPkiSupportedAlgorithms {
404    /// Return all the `scheme` items in `mapping`, maintaining order.
405    pub fn supported_schemes(&self) -> Vec<SignatureScheme> {
406        self.mapping
407            .iter()
408            .map(|item| item.0)
409            .collect()
410    }
411
412    /// Return the FIPS validation status of this implementation.
413    pub fn fips(&self) -> FipsStatus {
414        let algs = self
415            .all
416            .iter()
417            .map(|alg| alg.fips_status())
418            .min();
419        let mapped = self
420            .mapping
421            .iter()
422            .flat_map(|(_, algs)| algs.iter().map(|alg| alg.fips_status()))
423            .min();
424
425        match (algs, mapped) {
426            (Some(algs), Some(mapped)) => Ord::min(algs, mapped),
427            (Some(status), None) | (None, Some(status)) => status,
428            (None, None) => FipsStatus::Unvalidated,
429        }
430    }
431
432    /// Return the first item in `mapping` that matches `scheme`.
433    #[cfg(feature = "webpki")]
434    pub(crate) fn convert_scheme(
435        &self,
436        scheme: SignatureScheme,
437    ) -> Result<&[&'static dyn SignatureVerificationAlgorithm], Error> {
438        self.mapping
439            .iter()
440            .filter_map(|item| if item.0 == scheme { Some(item.1) } else { None })
441            .next()
442            .ok_or_else(|| PeerMisbehaved::SignedHandshakeWithUnadvertisedSigScheme.into())
443    }
444}
445
446impl Debug for WebPkiSupportedAlgorithms {
447    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
448        write!(f, "WebPkiSupportedAlgorithms {{ all: [ .. ], mapping: ")?;
449        f.debug_list()
450            .entries(self.mapping.iter().map(|item| item.0))
451            .finish()?;
452        write!(f, " }}")
453    }
454}
455
456impl Hash for WebPkiSupportedAlgorithms {
457    fn hash<H: Hasher>(&self, state: &mut H) {
458        let Self { all, mapping } = self;
459
460        write_algs(state, all);
461        state.write_usize(mapping.len());
462        for (scheme, algs) in *mapping {
463            state.write_u16(u16::from(*scheme));
464            write_algs(state, algs);
465        }
466
467        fn write_algs<H: Hasher>(
468            state: &mut H,
469            algs: &[&'static dyn SignatureVerificationAlgorithm],
470        ) {
471            state.write_usize(algs.len());
472            for alg in algs {
473                state.write(alg.public_key_alg_id().as_ref());
474                state.write(alg.signature_alg_id().as_ref());
475            }
476        }
477    }
478}
479
480pub(crate) mod rand {
481    use super::{GetRandomFailed, SecureRandom};
482
483    /// Make an array of size `N` containing random material.
484    pub(crate) fn random_array<const N: usize>(
485        secure_random: &dyn SecureRandom,
486    ) -> Result<[u8; N], GetRandomFailed> {
487        let mut v = [0; N];
488        secure_random.fill(&mut v)?;
489        Ok(v)
490    }
491
492    /// Return a uniformly random [`u32`].
493    pub(crate) fn random_u32(secure_random: &dyn SecureRandom) -> Result<u32, GetRandomFailed> {
494        Ok(u32::from_be_bytes(random_array(secure_random)?))
495    }
496
497    /// Return a uniformly random [`u16`].
498    pub(crate) fn random_u16(secure_random: &dyn SecureRandom) -> Result<u16, GetRandomFailed> {
499        Ok(u16::from_be_bytes(random_array(secure_random)?))
500    }
501}
502
503/// Random material generation failed.
504#[expect(clippy::exhaustive_structs)]
505#[derive(Debug)]
506pub struct GetRandomFailed;
507
508/// A source of cryptographically secure randomness.
509pub trait SecureRandom: Send + Sync + Debug {
510    /// Fill the given buffer with random bytes.
511    ///
512    /// The bytes must be sourced from a cryptographically secure random number
513    /// generator seeded with good quality, secret entropy.
514    ///
515    /// This is used for all randomness required by rustls, but not necessarily
516    /// randomness required by the underlying cryptography library.  For example:
517    /// [`SupportedKxGroup::start()`] requires random material to generate
518    /// an ephemeral key exchange key, but this is not included in the interface with
519    /// rustls: it is assumed that the cryptography library provides for this itself.
520    fn fill(&self, buf: &mut [u8]) -> Result<(), GetRandomFailed>;
521
522    /// Return the FIPS validation status of this implementation.
523    fn fips(&self) -> FipsStatus {
524        FipsStatus::Unvalidated
525    }
526}
527
528/// A mechanism for loading private [`SigningKey`]s from [`PrivateKeyDer`].
529///
530/// This trait is intended to be used with private key material that is sourced from DER,
531/// such as a private-key that may be present on-disk. It is not intended to be used with
532/// keys held in hardware security modules (HSMs) or physical tokens. For these use-cases
533/// see the Rustls manual section on [customizing private key usage].
534///
535/// [customizing private key usage]: <https://docs.rs/rustls/latest/rustls/manual/_03_howto/index.html#customising-private-key-usage>
536pub trait KeyProvider: Send + Sync + Debug {
537    /// Decode and validate a private signing key from `key_der`.
538    ///
539    /// This is used by [`ConfigBuilder::with_client_auth_cert()`], [`ConfigBuilder::with_single_cert()`],
540    /// and [`ConfigBuilder::with_single_cert_with_ocsp()`].  The key types and formats supported by this
541    /// function directly defines the key types and formats supported in those APIs.
542    ///
543    /// Return an error if the key type encoding is not supported, or if the key fails validation.
544    fn load_private_key(
545        &self,
546        key_der: PrivateKeyDer<'static>,
547    ) -> Result<Box<dyn SigningKey>, Error>;
548
549    /// Return the FIPS validation status for this key provider.
550    ///
551    /// The returned status must cover all possible key types supported by
552    /// [`KeyProvider::load_private_key()`].
553    fn fips(&self) -> FipsStatus {
554        FipsStatus::Unvalidated
555    }
556}
557
558/// A factory that builds [`TicketProducer`]s.
559///
560/// These can be used in [`ServerConfig::ticketer`] to enable stateless resumption.
561///
562/// [`ServerConfig::ticketer`]: crate::server::ServerConfig::ticketer
563pub trait TicketerFactory: Debug + Send + Sync {
564    /// Build a new `TicketProducer`.
565    fn ticketer(&self) -> Result<Arc<dyn TicketProducer>, Error>;
566
567    /// Return the FIPS validation status of ticketers produced from here.
568    fn fips(&self) -> FipsStatus {
569        FipsStatus::Unvalidated
570    }
571}
572
573/// A trait for the ability to encrypt and decrypt tickets.
574pub trait TicketProducer: Debug + Send + Sync {
575    /// Encrypt and authenticate `plain`, returning the resulting
576    /// ticket.  Return None if `plain` cannot be encrypted for
577    /// some reason: an empty ticket will be sent and the connection
578    /// will continue.
579    fn encrypt(&self, plain: &[u8]) -> Option<Vec<u8>>;
580
581    /// Decrypt `cipher`, validating its authenticity protection
582    /// and recovering the plaintext.  `cipher` is fully attacker
583    /// controlled, so this decryption must be side-channel free,
584    /// panic-proof, and otherwise bullet-proof.  If the decryption
585    /// fails, return None.
586    fn decrypt(&self, cipher: &[u8]) -> Option<Vec<u8>>;
587
588    /// Returns the lifetime of tickets produced now.
589    /// The lifetime is provided as a hint to clients that the
590    /// ticket will not be useful after the given time.
591    ///
592    /// This lifetime must be implemented by key rolling and
593    /// erasure, *not* by storing a lifetime in the ticket.
594    ///
595    /// The objective is to limit damage to forward secrecy caused
596    /// by tickets, not just limiting their lifetime.
597    fn lifetime(&self) -> Duration;
598}
599
600mod static_default {
601    #[cfg(not(feature = "std"))]
602    use alloc::boxed::Box;
603    #[cfg(feature = "std")]
604    use std::sync::OnceLock;
605
606    #[cfg(not(feature = "std"))]
607    use once_cell::race::OnceBox;
608
609    use super::CryptoProvider;
610    use crate::sync::Arc;
611
612    #[cfg(feature = "std")]
613    pub(crate) fn install_default(
614        default_provider: CryptoProvider,
615    ) -> Result<(), Arc<CryptoProvider>> {
616        PROCESS_DEFAULT_PROVIDER.set(Arc::new(default_provider))
617    }
618
619    #[cfg(not(feature = "std"))]
620    pub(crate) fn install_default(
621        default_provider: CryptoProvider,
622    ) -> Result<(), Arc<CryptoProvider>> {
623        PROCESS_DEFAULT_PROVIDER
624            .set(Box::new(Arc::new(default_provider)))
625            .map_err(|e| *e)
626    }
627
628    pub(crate) fn get_default() -> Option<&'static Arc<CryptoProvider>> {
629        PROCESS_DEFAULT_PROVIDER.get()
630    }
631
632    #[cfg(feature = "std")]
633    static PROCESS_DEFAULT_PROVIDER: OnceLock<Arc<CryptoProvider>> = OnceLock::new();
634    #[cfg(not(feature = "std"))]
635    static PROCESS_DEFAULT_PROVIDER: OnceBox<Arc<CryptoProvider>> = OnceBox::new();
636}
637
638#[cfg(test)]
639#[track_caller]
640pub(crate) fn tls13_suite(
641    suite: CipherSuite,
642    provider: &CryptoProvider,
643) -> &'static Tls13CipherSuite {
644    provider
645        .tls13_cipher_suites
646        .iter()
647        .find(|cs| cs.common.suite == suite)
648        .unwrap()
649}
650
651#[cfg(test)]
652#[track_caller]
653pub(crate) fn tls12_suite(
654    suite: CipherSuite,
655    provider: &CryptoProvider,
656) -> &'static Tls12CipherSuite {
657    provider
658        .tls12_cipher_suites
659        .iter()
660        .find(|cs| cs.common.suite == suite)
661        .unwrap()
662}
663
664#[cfg(test)]
665#[track_caller]
666pub(crate) fn tls13_only(provider: CryptoProvider) -> CryptoProvider {
667    CryptoProvider {
668        tls12_cipher_suites: Cow::default(),
669        ..provider
670    }
671}
672
673#[cfg(test)]
674#[track_caller]
675pub(crate) fn tls12_only(provider: CryptoProvider) -> CryptoProvider {
676    CryptoProvider {
677        tls13_cipher_suites: Cow::default(),
678        ..provider
679    }
680}