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//! [`crypto::CryptoProvider`]: crate::crypto::CryptoProvider
22//!
23//! ### Cryptography providers
24//!
25//! Since Rustls 0.22 it has been possible to choose the provider of the cryptographic primitives
26//! that Rustls uses. This may be appealing if you have specific platform, compliance or feature
27//! requirements.
28//!
29//! From 0.24, users must explicitly provide a crypto provider when constructing `ClientConfig` or
30//! `ServerConfig` instances. See the [`crypto::CryptoProvider`] documentation for more details.
31//!
32//! #### First-party providers
33//!
34//! The Rustls project currently maintains two cryptography providers:
35//!
36//! * [`rustls-aws-lc-rs`] - a provider that uses the [`aws-lc-rs`] crate for cryptography.
37//! While this provider can be harder to build on [some platforms][aws-lc-rs-platforms-faq], it provides excellent
38//! performance and a complete feature set (including post-quantum algorithms).
39//! * [`rustls-ring`] - a provider that uses the [`ring`] crate for cryptography. This
40//! provider is easier to build on a variety of platforms, but has a more limited feature set
41//! (for example, it does not support post-quantum algorithms).
42//!
43//! The Rustls team recommends using the [`rustls-aws-lc-rs`] crate for its complete feature set
44//! and performance. See [the aws-lc-rs FAQ][aws-lc-rs-platforms-faq] for more details of the
45//! platform/architecture support constraints in aws-lc-rs.
46//!
47//! See the documentation for [`crypto::CryptoProvider`] for details on how providers are
48//! selected.
49//!
50//! (For rustls versions prior to 0.24, both of these providers were shipped as part of the rustls
51//! crate, and Cargo features were used to select the preferred provider. The `aws-lc-rs` feature
52//! was enabled by default.)
53//!
54//! [`rustls-aws-lc-rs`]: https://crates.io/crates/rustls-aws-lc-rs
55//! [`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs
56//! [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
57//! [`rustls-ring`]: https://crates.io/crates/rustls-ring
58//! [`ring`]: https://crates.io/crates/ring
59//!
60//! #### Third-party providers
61//!
62//! The community has also started developing third-party providers for Rustls:
63//!
64//! * [`boring-rustls-provider`] - a work-in-progress provider that uses [`boringssl`] for
65//! cryptography.
66//! * [`rustls-ccm`] - adds AES-CCM cipher suites (TLS 1.2 and 1.3) using [`RustCrypto`], for IoT/constrained-device protocols (IEEE 2030.5, Matter, RFC 7925).
67//! * [`rustls-graviola`] - a provider that uses [`graviola`] for cryptography.
68//! * [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography.
69//! * [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography.
70//! * [`rustls-rustcrypto`] - an experimental provider that uses the crypto primitives
71//! from [`RustCrypto`] for cryptography.
72//! * [`rustls-symcrypt`] - a provider that uses Microsoft's [SymCrypt] library.
73//! * [`rustls-wolfcrypt-provider`] - a work-in-progress provider that uses [`wolfCrypt`] for cryptography.
74//!
75//! [`rustls-ccm`]: https://github.com/jsulmont/rustls-ccm
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//! See the [Making a custom CryptoProvider] section of the documentation for more information
92//! on this topic.
93//!
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//! `rustls_util::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 [`TlsInputBuffer`] supplied to [`process_new_packets()`], and [`write_tls()`] methods)
118//! and then read/write the plaintext on the right:
119//!
120//! [`write_tls()`]: Connection::write_tls
121//! [`process_new_packets()`]: Connection::process_new_packets
122//!
123//! ```text
124//! TLS Plaintext
125//! === =========
126//! process_new_packets() +-----------------------+ 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//! let root_store = rustls::RootCertStore::from_iter(
148//! webpki_roots::TLS_SERVER_ROOTS
149//! .iter()
150//! .cloned(),
151//! );
152//! ```
153//!
154//! [`webpki_roots`]: https://crates.io/crates/webpki-roots
155//!
156//! Next, we make a `ClientConfig`. You're likely to make one of these per process,
157//! and use it for all connections made by that process.
158//!
159//! ```rust,no_run
160//! # let DEFAULT_PROVIDER = rustls::crypto::CryptoProvider::get_default().unwrap().clone();
161//! # let root_store: rustls::RootCertStore = panic!();
162//! let config = rustls::ClientConfig::builder(DEFAULT_PROVIDER)
163//! .with_root_certificates(root_store)
164//! .with_no_client_auth()
165//! .unwrap();
166//! ```
167//!
168//! Now we can make a connection. You need to provide the server's hostname so we
169//! know what to expect to find in the server's certificate.
170//!
171//! ```rust,no_run
172//! # use rustls;
173//! # use webpki;
174//! # use std::sync::Arc;
175//! # let DEFAULT_PROVIDER = rustls::crypto::CryptoProvider::get_default().unwrap().clone();
176//! # let root_store = rustls::RootCertStore::from_iter(
177//! # webpki_roots::TLS_SERVER_ROOTS
178//! # .iter()
179//! # .cloned(),
180//! # );
181//! # let client_config = Arc::new(rustls::ClientConfig::builder(DEFAULT_PROVIDER)
182//! # .with_root_certificates(root_store)
183//! # .with_no_client_auth()
184//! # .unwrap());
185//!
186//! let example_com = "example.com".try_into().unwrap();
187//! let mut output = Vec::new();
188//! let mut client = client_config.connect(example_com)
189//! .build(&mut output)
190//! .unwrap();
191//! ```
192//!
193//! Now you should do appropriate IO for the `client` object. Operations that produce TLS
194//! data to send to the peer -- such as `build()` above and `client.process_new_packets()` --
195//! append it to the `Vec<u8>` you pass; write those bytes to the underlying connection
196//! whenever it is able to send data. If `client.wants_read()` yields true, you should
197//! call `client.process_new_packets()` with the data from the underlying connection.
198//! You should continue doing this as long as the connection is valid.
199//!
200//! `process_new_packets()` will yield a [`MessageHandler`], which can be used to read all
201//! buffered messages at once (via [`MessageHandler::handle_all()`]) or one at a time (via
202//! [`MessageHandler::next_payload()`]). Any error returned from either of these methods is fatal
203//! to the connection, and will tell you why. For example, if the server's certificate is expired
204//! `process_new_packets()` will return `Err(InvalidCertificate(Expired))`. From this point on,
205//! future calls to `MessageHandler` methods will do nothing and yield the same error.
206//!
207//! Newly received data is available by copying from the `Payload` data returned by
208//! `next_payload()` or written into the given buffer by `handle_all()`. You can send data
209//! to the peer by calling `client.write_tls()`, which encrypts it into TLS records appended
210//! to your output buffer. Note that this is only possible once the handshake has completed.
211//!
212//! The following code uses a fictional socket IO API for illustration, and does not handle
213//! errors.
214//!
215//! ```rust,no_run
216//! # let mut client: rustls::ClientConnection = panic!();
217//! # let mut output: Vec<u8> = Vec::new();
218//! # struct Socket { }
219//! # impl Socket {
220//! # fn ready_for_write(&self) -> bool { false }
221//! # fn ready_for_read(&self) -> bool { false }
222//! # fn wait_for_something_to_happen(&self) { }
223//! # }
224//! #
225//! # use std::io::{Read, Write, Result};
226//! # impl Read for Socket {
227//! # fn read(&mut self, buf: &mut [u8]) -> Result<usize> { panic!() }
228//! # }
229//! # impl Write for Socket {
230//! # fn write(&mut self, buf: &[u8]) -> Result<usize> { panic!() }
231//! # fn flush(&mut self) -> Result<()> { panic!() }
232//! # }
233//! #
234//! # fn connect(_address: &str, _port: u16) -> Socket {
235//! # panic!();
236//! # }
237//! use std::io;
238//! use rustls::{Connection, VecInput};
239//!
240//! let mut socket = connect("example.com", 443);
241//! let mut input = VecInput::default();
242//! let mut sent_request = false;
243//! loop {
244//! if client.wants_read() && socket.ready_for_read() {
245//! input.read(&mut socket).unwrap();
246//! let mut plaintext = Vec::new();
247//! client
248//! .process_new_packets(&mut input, &mut output)
249//! .handle_all(&mut plaintext)
250//! .unwrap();
251//! io::stdout().write(&plaintext).unwrap();
252//! }
253//!
254//! if !sent_request && !client.is_handshaking() {
255//! client.write_tls(b"GET / HTTP/1.0\r\n\r\n".into(), &mut output).unwrap();
256//! sent_request = true;
257//! }
258//!
259//! if !output.is_empty() && socket.ready_for_write() {
260//! let written = socket.write(&output).unwrap();
261//! output.drain(..written);
262//! }
263//!
264//! socket.wait_for_something_to_happen();
265//! }
266//! ```
267//!
268//! # Examples
269//!
270//! You can find several client and server examples of varying complexity in the [examples]
271//! directory, including [`tlsserver-mio`](https://github.com/rustls/rustls/blob/main/examples/src/bin/tlsserver-mio.rs)
272//! and [`tlsclient-mio`](https://github.com/rustls/rustls/blob/main/examples/src/bin/tlsclient-mio.rs)
273//! \- full worked examples using [`mio`].
274//!
275//! [`mio`]: https://docs.rs/mio/latest/mio/
276//!
277//! # Manual
278//!
279//! The [rustls manual](crate::manual) explains design decisions and includes how-to guidance.
280//!
281//! # Crate features
282//! Here's a list of what features are exposed by the rustls crate and what
283//! they mean.
284//!
285//! - `tracing` (enabled by default): make the rustls crate depend on the `tracing` crate,
286//! rustls outputs interesting protocol-level messages at `trace!` and `debug!` level,
287//! and protocol-level errors at `warn!` and `error!` level. The log messages do not
288//! contain secret key data, and so are safe to archive without affecting session security.
289//!
290//! To use this with the `log` crate (as used by rustls 0.23 and previous) you should take
291//! a dependency on the `tracing` crate and activate its `log` or `log-always` feature.
292//!
293//! - `webpki` (enabled by default): make the rustls crate depend on the `rustls-webpki` crate, which
294//! is used by default to provide built-in certificate verification. Without this feature, users must
295//! provide certificate verification themselves.
296//!
297//! - `brotli`: uses the `brotli` crate for RFC 8879 certificate compression support.
298//!
299//! - `zlib`: uses the `zlib-rs` crate for RFC 8879 certificate compression support.
300//!
301//! [x25519mlkem768-manual]: manual::_05_defaults#about-the-post-quantum-secure-key-exchange-x25519mlkem768
302
303// Require docs for public APIs, deny unsafe code, etc.
304#![warn(missing_docs, clippy::exhaustive_enums, clippy::exhaustive_structs)]
305#![forbid(unsafe_code, unused_must_use)]
306#![cfg_attr(not(any(bench, coverage_nightly)), forbid(unstable_features))]
307// Enable documentation for all features on docs.rs
308#![cfg_attr(rustls_docsrs, feature(doc_cfg))]
309// Enable coverage() attr for nightly coverage builds, see
310// <https://github.com/rust-lang/rust/issues/84605>
311// (`coverage_nightly` is a cfg set by `cargo-llvm-cov`)
312#![cfg_attr(coverage_nightly, feature(coverage_attribute))]
313#![cfg_attr(bench, feature(test))]
314#![no_std]
315
316extern crate alloc;
317// This `extern crate` plus the `#![no_std]` attribute changes the default prelude from
318// `std::prelude` to `core::prelude`. That forces one to _explicitly_ import (`use`) everything that
319// is in `std::prelude` but not in `core::prelude`. This helps maintain no-std support as even
320// developers that are not interested in, or aware of, no-std support and / or that never run
321// `cargo build --no-default-features` locally will get errors when they rely on `std::prelude` API.
322extern crate std;
323
324#[cfg(doc)]
325use crate::crypto::CryptoProvider;
326
327// Import `test` sysroot crate for `Bencher` definitions.
328#[cfg(bench)]
329#[allow(unused_extern_crates)]
330extern crate test;
331
332#[cfg(feature = "tracing")]
333#[expect(clippy::single_component_path_imports)]
334use tracing;
335
336#[cfg(not(feature = "tracing"))]
337mod tracing {
338 macro_rules! trace ( ($($tt:tt)*) => { crate::tracing::_used!($($tt)*) } );
339 macro_rules! debug ( ($($tt:tt)*) => { crate::tracing::_used!($($tt)*) } );
340 macro_rules! error ( ($($tt:tt)*) => { crate::tracing::_used!($($tt)*) } );
341 macro_rules! _warn ( ($($tt:tt)*) => { crate::tracing::_used!($($tt)*) } );
342 macro_rules! _used ( ($($tt:tt)*) => { { let _ = format_args!($($tt)*); } } );
343 pub(crate) use _used;
344 pub(crate) use _warn as warn;
345 pub(crate) use debug;
346 pub(crate) use error;
347 pub(crate) use trace;
348}
349
350/// This internal `sync` module aliases the `Arc` implementation to allow downstream forks
351/// of rustls targeting architectures without atomic pointers to replace the implementation
352/// with another implementation such as `portable_atomic_util::Arc` in one central location.
353mod sync {
354 #[expect(clippy::disallowed_types)]
355 pub(crate) type Arc<T> = alloc::sync::Arc<T>;
356}
357
358#[expect(unnameable_types)]
359#[macro_use]
360mod msgs;
361mod common_state;
362pub mod compress;
363mod conn;
364/// Crypto provider interface.
365pub mod crypto;
366pub mod error;
367mod hash_hs;
368mod limited_cache;
369mod tls12;
370mod tls13;
371mod vecbuf;
372mod verify;
373mod x509;
374#[macro_use]
375mod check;
376mod bs_debug;
377mod builder;
378pub mod enums;
379mod key_log;
380mod suites;
381mod versions;
382#[cfg(feature = "webpki")]
383mod webpki;
384
385/// Internal classes that are used in integration tests.
386/// The contents of this section DO NOT form part of the stable interface.
387#[doc(hidden)]
388pub mod internal {
389 pub use crate::msgs::fuzzing;
390}
391
392// The public interface is:
393pub use crate::builder::{ConfigBuilder, ConfigSide, WantsVerifier};
394pub use crate::common_state::{CommonState, ConnectionOutputs, HandshakeKind, Protocol};
395pub use crate::conn::{
396 Connection, IoState, KeyingMaterialExporter, MessageHandler, SideData, SliceInput,
397 TlsInputBuffer, VecInput, kernel,
398};
399/// Types related to "split" mode.
400///
401/// See [`split::SplitConnection`] for more information.
402pub mod split {
403 pub use crate::conn::split::{
404 FlushSender, ReceiveTraffic, ReceiveTrafficState, ReceivedApplicationData, SendTraffic,
405 SplitConnection,
406 };
407}
408pub use crate::error::Error;
409pub use crate::key_log::{KeyLog, NoKeyLog};
410pub use crate::suites::{
411 CipherSuiteCommon, ConnectionTrafficSecrets, ExtractedSecrets, SupportedCipherSuite,
412};
413pub use crate::ticketer::TicketRotator;
414pub use crate::tls12::Tls12CipherSuite;
415pub use crate::tls13::Tls13CipherSuite;
416pub use crate::verify::{DigitallySignedStruct, DistinguishedName, SignerPublicKey};
417pub use crate::versions::{ALL_VERSIONS, DEFAULT_VERSIONS, SupportedProtocolVersion};
418#[cfg(feature = "webpki")]
419pub use crate::webpki::RootCertStore;
420
421/// Items for use in a client.
422pub mod client;
423pub use client::{ClientConfig, ClientConnection};
424
425/// Items for use in a server.
426pub mod server;
427pub use server::{ServerConfig, ServerConnection};
428
429/// All defined protocol versions appear in this module.
430///
431/// ALL_VERSIONS is provided as an array of all of these values.
432pub mod version {
433 pub use crate::versions::{
434 TLS12, TLS12_VERSION, TLS13, TLS13_VERSION, Tls12Version, Tls13Version,
435 };
436}
437
438/// Re-exports the contents of the [rustls-pki-types](https://docs.rs/rustls-pki-types) crate for easy access
439pub mod pki_types {
440 #[doc(no_inline)]
441 pub use pki_types::*;
442}
443
444/// APIs for implementing QUIC TLS
445pub mod quic;
446
447/// APIs for implementing TLS tickets
448pub mod ticketer;
449
450/// This is the rustls manual.
451pub mod manual;
452
453pub mod time_provider;
454
455/// APIs abstracting over locking primitives.
456pub mod lock;
457
458mod hash_map {
459 pub(crate) use std::collections::HashMap;
460 pub(crate) use std::collections::hash_map::Entry;
461}
462
463mod sealed {
464 #[expect(unnameable_types)]
465 pub trait Sealed {}
466}
467
468mod core_hash_polyfill {
469 use core::hash::Hasher;
470
471 /// Working around `core::hash::Hasher` not being dyn-compatible
472 pub(super) struct DynHasher<'a>(pub(crate) &'a mut dyn Hasher);
473
474 impl Hasher for DynHasher<'_> {
475 fn finish(&self) -> u64 {
476 self.0.finish()
477 }
478
479 fn write(&mut self, bytes: &[u8]) {
480 self.0.write(bytes)
481 }
482 }
483}
484
485pub(crate) use core_hash_polyfill::DynHasher;