Skip to main content

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