rustls/lib.rs
1//! # Rustls - a modern TLS library
2//!
3//! Rustls is a TLS library that aims to provide a good level of cryptographic security,
4//! requires no configuration to achieve that security, and provides no unsafe features or
5//! obsolete cryptography by default.
6//!
7//! Rustls implements TLS1.2 and TLS1.3 for both clients and servers. See [the full
8//! list of protocol features](manual::_04_features).
9//!
10//! ### Platform support
11//!
12//! While Rustls itself is platform independent, it requires the use of cryptography primitives
13//! for implementing the cryptography algorithms used in TLS. In Rustls, a
14//! [`crypto::CryptoProvider`] represents a collection of crypto primitive implementations.
15//!
16//! The Rustls team recommends using the [`aws-lc-rs`] crate, which for its complete feature set
17//! and performance. See [the aws-lc-rs FAQ][aws-lc-rs-platforms-faq] for more details of the
18//! platform/architecture support constraints in aws-lc-rs.
19//!
20//! [`ring`] is also available via the `ring` crate feature: see
21//! [the supported `ring` target platforms][ring-target-platforms].
22//!
23//! By providing a custom instance of the [`crypto::CryptoProvider`] struct, you
24//! can replace all cryptography dependencies of rustls. This is a route to being portable
25//! to a wider set of architectures and environments, or compliance requirements. See the
26//! [`crypto::CryptoProvider`] documentation for more details.
27//!
28//! Rustls requires Rust 1.83 or later.
29//!
30//! [ring-target-platforms]: https://github.com/briansmith/ring/blob/2e8363b433fa3b3962c877d9ed2e9145612f3160/include/ring-core/target.h#L18-L64
31//! [`crypto::CryptoProvider`]: crate::crypto::CryptoProvider
32//! [`ring`]: https://crates.io/crates/ring
33//! [aws-lc-rs-platforms-faq]: https://aws.github.io/aws-lc-rs/faq.html#can-i-run-aws-lc-rs-on-x-platform-or-architecture
34//! [`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs
35//!
36//! ### Cryptography providers
37//!
38//! Since Rustls 0.22 it has been possible to choose the provider of the cryptographic primitives
39//! that Rustls uses. This may be appealing if you have specific platform, compliance or feature
40//! requirements.
41//!
42//! From 0.24, users must explicitly provide a crypto provider when constructing `ClientConfig` or
43//! `ServerConfig` instances. See the [`crypto::CryptoProvider`] documentation for more details.
44//!
45//! #### Built-in providers
46//!
47//! Rustls ships with two built-in providers controlled by associated crate features:
48//!
49//! * [`aws-lc-rs`] - available with the `aws-lc-rs` crate feature enabled
50//! * [`ring`] - available with the `ring` crate feature enabled
51//!
52//! See the documentation for [`crypto::CryptoProvider`] for details on how providers are
53//! selected.
54//!
55//! #### Third-party providers
56//!
57//! The community has also started developing third-party providers for Rustls:
58//!
59//! * [`boring-rustls-provider`] - a work-in-progress provider that uses [`boringssl`] for
60//! cryptography.
61//! * [`rustls-graviola`] - a provider that uses [`graviola`] for cryptography.
62//! * [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography.
63//! * [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography.
64//! * [`rustls-rustcrypto`] - an experimental provider that uses the crypto primitives
65//! from [`RustCrypto`] for cryptography.
66//! * [`rustls-symcrypt`] - a provider that uses Microsoft's [SymCrypt] library.
67//! * [`rustls-wolfcrypt-provider`] - a work-in-progress provider that uses [`wolfCrypt`] for cryptography.
68//!
69//! [`rustls-graviola`]: https://crates.io/crates/rustls-graviola
70//! [`graviola`]: https://github.com/ctz/graviola
71//! [`rustls-mbedtls-provider`]: https://github.com/fortanix/rustls-mbedtls-provider
72//! [`mbedtls`]: https://github.com/Mbed-TLS/mbedtls
73//! [`rustls-openssl`]: https://github.com/tofay/rustls-openssl
74//! [OpenSSL]: https://openssl-library.org/
75//! [`rustls-symcrypt`]: https://github.com/microsoft/rustls-symcrypt
76//! [SymCrypt]: https://github.com/microsoft/SymCrypt
77//! [`boring-rustls-provider`]: https://github.com/janrueth/boring-rustls-provider
78//! [`boringssl`]: https://github.com/google/boringssl
79//! [`rustls-rustcrypto`]: https://github.com/RustCrypto/rustls-rustcrypto
80//! [`RustCrypto`]: https://github.com/RustCrypto
81//! [`rustls-wolfcrypt-provider`]: https://github.com/wolfSSL/rustls-wolfcrypt-provider
82//! [`wolfCrypt`]: https://www.wolfssl.com/products/wolfcrypt
83//!
84//! #### Custom provider
85//!
86//! We also provide a simple example of writing your own provider in the [custom provider example].
87//! This example implements a minimal provider using parts of the [`RustCrypto`] ecosystem.
88//!
89//! See the [Making a custom CryptoProvider] section of the documentation for more information
90//! on this topic.
91//!
92//! [custom provider example]: https://github.com/rustls/rustls/tree/main/provider-example/
93//! [`RustCrypto`]: https://github.com/RustCrypto
94//! [Making a custom CryptoProvider]: https://docs.rs/rustls/latest/rustls/crypto/struct.CryptoProvider.html#making-a-custom-cryptoprovider
95//!
96//! ## Design overview
97//!
98//! Rustls is a low-level library. If your goal is to make HTTPS connections you may prefer
99//! to use a library built on top of Rustls like [hyper] or [ureq].
100//!
101//! [hyper]: https://crates.io/crates/hyper
102//! [ureq]: https://crates.io/crates/ureq
103//!
104//! ### Rustls does not take care of network IO
105//! It doesn't make or accept TCP connections, or do DNS, or read or write files.
106//!
107//! Our [examples] directory contains demos that show how to handle I/O using the
108//! [`stream::Stream`] helper, as well as more complex asynchronous I/O using [`mio`].
109//! If you're already using Tokio for an async runtime you may prefer to use [`tokio-rustls`] instead
110//! of interacting with rustls directly.
111//!
112//! [examples]: https://github.com/rustls/rustls/tree/main/examples
113//! [`tokio-rustls`]: https://github.com/rustls/tokio-rustls
114//!
115//! ### Rustls provides encrypted pipes
116//! These are the [`ServerConnection`] and [`ClientConnection`] types. You supply raw TLS traffic
117//! on the left (via the [`read_tls()`] and [`write_tls()`] methods) and then read/write the
118//! plaintext on the right:
119//!
120//! [`read_tls()`]: Connection::read_tls
121//! [`write_tls()`]: Connection::read_tls
122//!
123//! ```text
124//! TLS Plaintext
125//! === =========
126//! read_tls() +-----------------------+ reader() as io::Read
127//! | |
128//! +---------> ClientConnection +--------->
129//! | or |
130//! <---------+ ServerConnection <---------+
131//! | |
132//! write_tls() +-----------------------+ writer() as io::Write
133//! ```
134//!
135//! ### Rustls takes care of server certificate verification
136//! You do not need to provide anything other than a set of root certificates to trust.
137//! Certificate verification cannot be turned off or disabled in the main API.
138//!
139//! ## Getting started
140//! This is the minimum you need to do to make a TLS client connection.
141//!
142//! First we load some root certificates. These are used to authenticate the server.
143//! The simplest way is to depend on the [`webpki_roots`] crate which contains
144//! the Mozilla set of root certificates.
145//!
146//! ```rust,no_run
147//! # #[cfg(feature = "aws-lc-rs")] {
148//! let root_store = rustls::RootCertStore::from_iter(
149//! webpki_roots::TLS_SERVER_ROOTS
150//! .iter()
151//! .cloned(),
152//! );
153//! # }
154//! ```
155//!
156//! [`webpki_roots`]: https://crates.io/crates/webpki-roots
157//!
158//! Next, we make a `ClientConfig`. You're likely to make one of these per process,
159//! and use it for all connections made by that process.
160//!
161//! ```rust,no_run
162//! # #[cfg(feature = "aws-lc-rs")] {
163//! # use std::sync::Arc;
164//! # let root_store: rustls::RootCertStore = panic!();
165//! let config = rustls::ClientConfig::builder(Arc::new(rustls::crypto::aws_lc_rs::DEFAULT_PROVIDER))
166//! .with_root_certificates(root_store)
167//! .with_no_client_auth()
168//! .unwrap();
169//! # }
170//! ```
171//!
172//! Now we can make a connection. You need to provide the server's hostname so we
173//! know what to expect to find in the server's certificate.
174//!
175//! ```rust
176//! # #[cfg(feature = "aws-lc-rs")] {
177//! # use rustls;
178//! # use webpki;
179//! # use std::sync::Arc;
180//! # use rustls::crypto::aws_lc_rs::DEFAULT_PROVIDER;
181//! # let root_store = rustls::RootCertStore::from_iter(
182//! # webpki_roots::TLS_SERVER_ROOTS
183//! # .iter()
184//! # .cloned(),
185//! # );
186//! # let config = rustls::ClientConfig::builder(Arc::new(DEFAULT_PROVIDER))
187//! # .with_root_certificates(root_store)
188//! # .with_no_client_auth()
189//! # .unwrap();
190//! let rc_config = Arc::new(config);
191//! let example_com = "example.com".try_into().unwrap();
192//! let mut client = rustls::ClientConnection::new(rc_config, example_com);
193//! # }
194//! ```
195//!
196//! Now you should do appropriate IO for the `client` object. If `client.wants_read()` yields
197//! true, you should call `client.read_tls()` when the underlying connection has data.
198//! Likewise, if `client.wants_write()` yields true, you should call `client.write_tls()`
199//! when the underlying connection is able to send data. You should continue doing this
200//! as long as the connection is valid.
201//!
202//! The return types of `read_tls()` and `write_tls()` only tell you if the IO worked. No
203//! parsing or processing of the TLS messages is done. After each `read_tls()` you should
204//! therefore call `client.process_new_packets()` which parses and processes the messages.
205//! Any error returned from `process_new_packets` is fatal to the connection, and will tell you
206//! why. For example, if the server's certificate is expired `process_new_packets` will
207//! return `Err(InvalidCertificate(Expired))`. From this point on,
208//! `process_new_packets` will not do any new work and will return that error continually.
209//!
210//! You can extract newly received data by calling `client.reader()` (which implements the
211//! `io::Read` trait). You can send data to the peer by calling `client.writer()` (which
212//! implements `io::Write` trait). Note that `client.writer().write()` buffers data you
213//! send if the TLS connection is not yet established: this is useful for writing (say) a
214//! HTTP request, but this is buffered so avoid large amounts of data.
215//!
216//! The following code uses a fictional socket IO API for illustration, and does not handle
217//! errors.
218//!
219//! ```rust,no_run
220//! # #[cfg(feature = "aws-lc-rs")] {
221//! # let mut client = rustls::ClientConnection::new(panic!(), panic!()).unwrap();
222//! # struct Socket { }
223//! # impl Socket {
224//! # fn ready_for_write(&self) -> bool { false }
225//! # fn ready_for_read(&self) -> bool { false }
226//! # fn wait_for_something_to_happen(&self) { }
227//! # }
228//! #
229//! # use std::io::{Read, Write, Result};
230//! # impl Read for Socket {
231//! # fn read(&mut self, buf: &mut [u8]) -> Result<usize> { panic!() }
232//! # }
233//! # impl Write for Socket {
234//! # fn write(&mut self, buf: &[u8]) -> Result<usize> { panic!() }
235//! # fn flush(&mut self) -> Result<()> { panic!() }
236//! # }
237//! #
238//! # fn connect(_address: &str, _port: u16) -> Socket {
239//! # panic!();
240//! # }
241//! use std::io;
242//! use rustls::Connection;
243//!
244//! client.writer().write(b"GET / HTTP/1.0\r\n\r\n").unwrap();
245//! let mut socket = connect("example.com", 443);
246//! loop {
247//! if client.wants_read() && socket.ready_for_read() {
248//! client.read_tls(&mut socket).unwrap();
249//! client.process_new_packets().unwrap();
250//!
251//! let mut plaintext = Vec::new();
252//! client.reader().read_to_end(&mut plaintext).unwrap();
253//! io::stdout().write(&plaintext).unwrap();
254//! }
255//!
256//! if client.wants_write() && socket.ready_for_write() {
257//! client.write_tls(&mut socket).unwrap();
258//! }
259//!
260//! socket.wait_for_something_to_happen();
261//! }
262//! # }
263//! ```
264//!
265//! # Examples
266//!
267//! You can find several client and server examples of varying complexity in the [examples]
268//! directory, including [`tlsserver-mio`](https://github.com/rustls/rustls/blob/main/examples/src/bin/tlsserver-mio.rs)
269//! and [`tlsclient-mio`](https://github.com/rustls/rustls/blob/main/examples/src/bin/tlsclient-mio.rs)
270//! \- full worked examples using [`mio`].
271//!
272//! [`mio`]: https://docs.rs/mio/latest/mio/
273//!
274//! # Manual
275//!
276//! The [rustls manual](crate::manual) explains design decisions and includes how-to guidance.
277//!
278//! # Crate features
279//! Here's a list of what features are exposed by the rustls crate and what
280//! they mean.
281//!
282//! - `std` (enabled by default): enable the high-level (buffered) Connection API and other functionality
283//! which relies on the `std` library.
284//!
285//! - `aws-lc-rs`: makes the rustls crate depend on the [`aws-lc-rs`] crate.
286//! Use `rustls::crypto::aws_lc_rs::default_provider().install_default()` to
287//! use it as the default `CryptoProvider`, or provide it explicitly
288//! when making a `ClientConfig` or `ServerConfig`.
289//!
290//! Note that aws-lc-rs has additional build-time dependencies like cmake.
291//! See [the documentation](https://aws.github.io/aws-lc-rs/requirements/index.html) for details.
292//!
293//! - `ring`: makes the rustls crate depend on the *ring* crate for cryptography.
294//! Use `rustls::crypto::ring::default_provider().install_default()` to
295//! use it as the default `CryptoProvider`, or provide it explicitly
296//! when making a `ClientConfig` or `ServerConfig`.
297//!
298//! - `fips`: enable support for FIPS140-3-approved cryptography, via the [`aws-lc-rs`] crate.
299//! This feature enables the `aws-lc-rs` crate feature, which makes the rustls crate depend
300//! on [aws-lc-rs](https://github.com/aws/aws-lc-rs). It also changes the default
301//! for [`ServerConfig::require_ems`] and [`ClientConfig::require_ems`].
302//!
303//! See [manual::_06_fips] for more details.
304//!
305//! - `custom-provider`: disables implicit use of built-in providers (`aws-lc-rs` or `ring`). This forces
306//! applications to manually install one, for instance, when using a custom `CryptoProvider`.
307//!
308//! - `log` (enabled by default): make the rustls crate depend on the `log` crate.
309//! rustls outputs interesting protocol-level messages at `trace!` and `debug!` level,
310//! and protocol-level errors at `warn!` and `error!` level. The log messages do not
311//! contain secret key data, and so are safe to archive without affecting session security.
312//!
313//! - `brotli`: uses the `brotli` crate for RFC8879 certificate compression support.
314//!
315//! - `zlib`: uses the `zlib-rs` crate for RFC8879 certificate compression support.
316//!
317//! [x25519mlkem768-manual]: manual::_05_defaults#about-the-post-quantum-secure-key-exchange-x25519mlkem768
318
319// Require docs for public APIs, deny unsafe code, etc.
320#![warn(missing_docs, clippy::exhaustive_enums, clippy::exhaustive_structs)]
321#![forbid(unsafe_code, unused_must_use)]
322#![cfg_attr(not(any(bench, coverage_nightly)), forbid(unstable_features))]
323// Enable documentation for all features on docs.rs
324#![cfg_attr(rustls_docsrs, feature(doc_cfg))]
325// Enable coverage() attr for nightly coverage builds, see
326// <https://github.com/rust-lang/rust/issues/84605>
327// (`coverage_nightly` is a cfg set by `cargo-llvm-cov`)
328#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
329#![cfg_attr(bench, feature(test))]
330#![no_std]
331
332extern crate alloc;
333// This `extern crate` plus the `#![no_std]` attribute changes the default prelude from
334// `std::prelude` to `core::prelude`. That forces one to _explicitly_ import (`use`) everything that
335// is in `std::prelude` but not in `core::prelude`. This helps maintain no-std support as even
336// developers that are not interested in, or aware of, no-std support and / or that never run
337// `cargo build --no-default-features` locally will get errors when they rely on `std::prelude` API.
338#[cfg(any(feature = "std", test))]
339extern crate std;
340
341#[cfg(doc)]
342use crate::crypto::CryptoProvider;
343
344// Import `test` sysroot crate for `Bencher` definitions.
345#[cfg(bench)]
346#[expect(unused_extern_crates)]
347extern crate test;
348
349// log for logging (optional).
350#[cfg(feature = "log")]
351#[expect(clippy::single_component_path_imports)]
352use log;
353
354#[cfg(not(feature = "log"))]
355mod log {
356 macro_rules! trace ( ($($tt:tt)*) => { crate::log::_used!($($tt)*) } );
357 macro_rules! debug ( ($($tt:tt)*) => { crate::log::_used!($($tt)*) } );
358 macro_rules! error ( ($($tt:tt)*) => { crate::log::_used!($($tt)*) } );
359 macro_rules! _warn ( ($($tt:tt)*) => { crate::log::_used!($($tt)*) } );
360 macro_rules! _used ( ($($tt:tt)*) => { { let _ = format_args!($($tt)*); } } );
361 pub(crate) use {_used, _warn as warn, debug, error, trace};
362}
363
364#[cfg(test)]
365#[macro_use]
366mod test_macros;
367
368/// This internal `sync` module aliases the `Arc` implementation to allow downstream forks
369/// of rustls targeting architectures without atomic pointers to replace the implementation
370/// with another implementation such as `portable_atomic_util::Arc` in one central location.
371mod sync {
372 #[expect(clippy::disallowed_types)]
373 pub(crate) type Arc<T> = alloc::sync::Arc<T>;
374}
375
376#[expect(unnameable_types)]
377#[macro_use]
378mod msgs;
379mod common_state;
380pub mod compress;
381mod conn;
382/// Crypto provider interface.
383pub mod crypto;
384pub mod error;
385mod hash_hs;
386#[cfg(any(feature = "std", feature = "hashbrown"))]
387mod limited_cache;
388#[cfg(feature = "std")]
389mod stream;
390mod tls12;
391mod tls13;
392mod vecbuf;
393mod verify;
394#[cfg(test)]
395mod verifybench;
396mod x509;
397#[macro_use]
398mod check;
399mod bs_debug;
400mod builder;
401pub mod enums;
402mod key_log;
403#[cfg(feature = "std")]
404mod key_log_file;
405mod suites;
406mod versions;
407mod webpki;
408
409/// Internal classes that are used in integration tests.
410/// The contents of this section DO NOT form part of the stable interface.
411#[doc(hidden)]
412pub mod internal {
413 /// Low-level TLS message parsing and encoding functions.
414 pub mod msgs {
415 pub mod codec {
416 pub use crate::msgs::codec::{Codec, Reader};
417 }
418 pub mod enums {
419 pub use crate::msgs::enums::{AlertLevel, ExtensionType};
420 }
421 pub mod fragmenter {
422 pub use crate::msgs::fragmenter::MessageFragmenter;
423 }
424 pub mod message {
425 pub use crate::msgs::message::{Message, MessagePayload};
426 }
427 pub mod persist {
428 pub use crate::msgs::persist::ServerSessionValue;
429 }
430 }
431
432 pub mod fuzzing {
433 pub use crate::msgs::deframer::fuzz_deframer;
434 }
435}
436
437/// Unbuffered connection API
438///
439/// This is an alternative to the [`crate::ConnectionCommon`] API that does not internally buffer
440/// TLS nor plaintext data. Instead those buffers are managed by the API user so they have
441/// control over when and how to allocate, resize and dispose of them.
442///
443/// This API is lower level than the `ConnectionCommon` API and is built around a state machine
444/// interface where the API user must handle each state to advance and complete the
445/// handshake process.
446///
447/// Like the `ConnectionCommon` API, no IO happens internally so all IO must be handled by the API
448/// user. Unlike the `ConnectionCommon` API, this API does not make use of the [`std::io::Read`] and
449/// [`std::io::Write`] traits so it's usable in no-std context.
450///
451/// The entry points into this API are [`crate::client::UnbufferedClientConnection::new`],
452/// [`crate::server::UnbufferedServerConnection::new`] and
453/// [`unbuffered::UnbufferedConnectionCommon::process_tls_records`]. The state machine API is
454/// documented in [`unbuffered::ConnectionState`].
455///
456/// # Examples
457///
458/// [`unbuffered-client`] and [`unbuffered-server`] are examples that fully exercise the API in
459/// std, non-async context.
460///
461/// [`unbuffered-client`]: https://github.com/rustls/rustls/blob/main/examples/src/bin/unbuffered-client.rs
462/// [`unbuffered-server`]: https://github.com/rustls/rustls/blob/main/examples/src/bin/unbuffered-server.rs
463pub mod unbuffered {
464 pub use crate::conn::UnbufferedConnectionCommon;
465 pub use crate::conn::unbuffered::{
466 AppDataRecord, ConnectionState, EncodeError, EncodeTlsData, EncryptError,
467 InsufficientSizeError, ReadEarlyData, ReadTraffic, TransmitTlsData, UnbufferedStatus,
468 WriteTraffic,
469 };
470}
471
472// The public interface is:
473pub use crate::builder::{ConfigBuilder, ConfigSide, WantsVerifier};
474pub use crate::common_state::{CommonState, HandshakeKind, IoState, Side};
475#[cfg(feature = "std")]
476pub use crate::conn::{Connection, Reader, Writer};
477pub use crate::conn::{ConnectionCommon, KeyingMaterialExporter, SideData, kernel};
478pub use crate::error::Error;
479pub use crate::key_log::{KeyLog, NoKeyLog};
480#[cfg(feature = "std")]
481pub use crate::key_log_file::KeyLogFile;
482#[cfg(feature = "std")]
483pub use crate::stream::{Stream, StreamOwned};
484pub use crate::suites::{
485 CipherSuiteCommon, ConnectionTrafficSecrets, ExtractedSecrets, SupportedCipherSuite,
486};
487#[cfg(feature = "std")]
488pub use crate::ticketer::TicketRotator;
489pub use crate::tls12::Tls12CipherSuite;
490pub use crate::tls13::Tls13CipherSuite;
491pub use crate::verify::{DigitallySignedStruct, DistinguishedName, SignerPublicKey};
492pub use crate::versions::{ALL_VERSIONS, DEFAULT_VERSIONS, SupportedProtocolVersion};
493pub use crate::webpki::RootCertStore;
494
495/// Items for use in a client.
496pub mod client;
497pub use client::ClientConfig;
498#[cfg(feature = "std")]
499pub use client::ClientConnection;
500
501/// Items for use in a server.
502pub mod server;
503pub use server::ServerConfig;
504#[cfg(feature = "std")]
505pub use server::ServerConnection;
506
507/// All defined protocol versions appear in this module.
508///
509/// ALL_VERSIONS is a provided as an array of all of these values.
510pub mod version {
511 pub use crate::versions::{
512 TLS12, TLS12_VERSION, TLS13, TLS13_VERSION, Tls12Version, Tls13Version,
513 };
514}
515
516/// Re-exports the contents of the [rustls-pki-types](https://docs.rs/rustls-pki-types) crate for easy access
517pub mod pki_types {
518 #[doc(no_inline)]
519 pub use pki_types::*;
520}
521
522/// APIs for implementing QUIC TLS
523pub mod quic;
524
525/// APIs for implementing TLS tickets
526#[cfg(feature = "std")]
527pub mod ticketer;
528
529/// This is the rustls manual.
530pub mod manual;
531
532pub mod time_provider;
533
534/// APIs abstracting over locking primitives.
535pub mod lock;
536
537#[cfg(any(feature = "std", feature = "hashbrown"))]
538mod hash_map {
539 #[cfg(feature = "std")]
540 pub(crate) use std::collections::HashMap;
541 #[cfg(feature = "std")]
542 pub(crate) use std::collections::hash_map::Entry;
543
544 #[cfg(all(not(feature = "std"), feature = "hashbrown"))]
545 pub(crate) use hashbrown::HashMap;
546 #[cfg(all(not(feature = "std"), feature = "hashbrown"))]
547 pub(crate) use hashbrown::hash_map::Entry;
548}
549
550mod sealed {
551 #[expect(unnameable_types)]
552 pub trait Sealed {}
553}
554
555#[cfg(test)]
556const TEST_PROVIDERS: &[&crypto::CryptoProvider] = &[
557 #[cfg(feature = "aws-lc-rs")]
558 &crypto::aws_lc_rs::DEFAULT_PROVIDER,
559];
560
561mod core_hash_polyfill {
562 use core::hash::Hasher;
563
564 /// Working around `core::hash::Hasher` not being dyn-compatible
565 pub(super) struct DynHasher<'a>(pub(crate) &'a mut dyn Hasher);
566
567 impl Hasher for DynHasher<'_> {
568 fn finish(&self) -> u64 {
569 self.0.finish()
570 }
571
572 fn write(&mut self, bytes: &[u8]) {
573 self.0.write(bytes)
574 }
575 }
576}
577
578pub(crate) use core_hash_polyfill::DynHasher;