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