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