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