portable_rustls/lib.rs
1//! # Rustls - a modern TLS library - portable-rustls fork
2//!
3//! <!-- TODO(portable-rustls) CLEANUP & IMPROVE DOCUMENTATION IN GENERAL FOR THIS FORK -->
4//! <!-- TODO(portable-rustls) IMPROVE SYNCHRONIZATION OF IMPORTANT INFO WITH BEGINNING OF README.md -->
5//! <!-- (as tracked in: https://github.com/brody4hire/portable-rustls/issues/31) -->
6//! __IMPORTANT NOTICE:__ regardless of upstream __`rustls`__ project this fork is __NOT CERTIFIED__ and __NOT PEER-REVIEWED__ - USE AT YOUR OWN RISK
7//!
8//! ## RECOMMENDED USAGE
9//!
10//! <!-- TODO(portable-rustls) CLEANUP & IMPROVE NOTE FOR THIS FORK -->
11//! RECOMMENDED USAGE OF THIS FORK:
12//!
13//! Add dependency on this fork as follows in `Cargo.toml`:
14//!
15//! ```rust,ignore
16//! rustls = { package = "portable-rustls", features=[...], ... }
17//! ```
18//!
19//! Then import and use __`rustls`__ in the code as usual.
20//!
21//! (Unlike the original __`rustls`__, no features are enabled by default in this fork.)
22//!
23//! ### targets with no atomic ptr
24//!
25//! This fork supports using `Arc` from `portable-atomic-util` to support targets with no atomic ptr, with the following requirements:
26//!
27//! Must use Rust nightly toolchain.
28//!
29//! Must use the following cfg flags in `RUSTFLAGS` FOR `cargo build` (etc.):
30//! - `--cfg portable_atomic_unstable_coerce_unsized`
31//! - `--cfg unstable_portable_atomic_arc`
32//!
33//! <!-- TODO: IMPROVE & CLEAN UP DOCUMENTATION FOR THIS; ADD CARGO FEATURE(S) TO HELP AUTOMATE THIS STEP -->
34//! WHEN BUILDING FOR A TARGET WITH NO ATOMIC PTR, NEED TO ADD THE FOLLOWING DEPENDENCIES WITH SPECIFIC FEATURES ENABLED:
35//! - add `once_cell` with `portable-atomic` feature enabled
36//! - add `portable-atomic` with `critical-section` or `unsafe-assume-single-core` feature enabled - see the following for more info & requirements: <https://docs.rs/portable-atomic/latest/portable_atomic/#optional-features>
37//! - possibly more requirements in case of `portable-atomic` with `critical-section` for no-std: <https://docs.rs/critical-section/latest/critical_section/#usage-in-no-std-binaries>
38//!
39//! <!-- TODO: ADDRESS HOW TO BUILD WITH A CRYPTO PROVIDER ON A TARGET WITH NO ATOMIC PTR -->
40//! <!-- (MAYBE BUILD WITH A BUILT-IN CRYPTO PROVIDER OR MAYBE THIRD-PARTY CRYPTO PROVIDER) -->
41//! ALSO NEED TO BUILD WITH A CRYPTO PROVIDER FOR THIS CRATE TO BE USEFUL IN GENERAL.
42//!
43//! ### Additional notes
44//!
45//! FIPS support feature is removed from this fork. Any possible vestiges remaining in the API or documentation should be considered non-functional.
46//!
47//! <!-- TODO(portable-rustls) UPDATE INFO FOR THIS FORK:
48//! Rustls is a TLS library that aims to provide a good level of cryptographic security,
49//! requires no configuration to achieve that security, and provides no unsafe features or
50//! obsolete cryptography by default.
51//! - -->
52//!
53//! <!-- TODO(portable-rustls) UPDATE INFO FOR THIS FORK - MAY BE PROVIDER DEPENDENT:
54//! Rustls implements TLS1.2 and TLS1.3 for both clients and servers. See [the full
55//! list of protocol features](manual::_04_features).
56//! - -->
57//!
58//! ## General usage
59//!
60//! NOTE: Most of the general usage information below comes directly from the upstream __`rustls`__ project.
61//!
62//! <!-- TODO(portable-rustls) CLEAN UP - AVOID ALL CAPS for emphasis -->
63//! Any major discrepancies from upstream __`rustls`__ are noted __in bold__ or with ALL CAPS.
64//!
65//! ### Platform support
66//!
67//! While Rustls itself is platform independent, there are some additional platform requirements
68//! for the built-in providers.
69//!
70//! [`aws-lc-rs`] is commonly used as the provider that implements the cryptography in TLS.
71//! See [the aws-lc-rs FAQ][aws-lc-rs-platforms-faq] for more details of the
72//! platform/architecture support constraints in aws-lc-rs.
73//!
74//! [`ring`] is also available via the `ring` crate feature: see
75//! [the supported `ring` target platforms][ring-target-platforms].
76//!
77//! By providing a custom instance of the [`crypto::CryptoProvider`] struct, you
78//! can replace all cryptography dependencies of rustls. This is a route to being portable
79//! to a wider set of architectures and environments, or compliance requirements. See the
80//! [`crypto::CryptoProvider`] documentation for more details.
81//!
82//! <!-- N/A FOR THIS FORK & ALSO MISSING AN UPDATE RECENTLY CONTRIBUTED TO UPSTREAM RUSTLS:
83//! Specifying `default-features = false` when depending on rustls will remove the
84//! dependency on aws-lc-rs.
85//! - -->
86//!
87//! <!-- TODO UPDATE THIS INFO OR ADD REFERENCE TO MSRV FROM BADGE - ALREADY UPDATED IN UPSTREAM RUSTLS PROJECT
88//! Rustls requires Rust 1.63 or later. It has an optional dependency on zlib-rs which requires 1.75 or later.
89//! - -->
90//!
91//! [ring-target-platforms]: https://github.com/briansmith/ring/blob/2e8363b433fa3b3962c877d9ed2e9145612f3160/include/ring-core/target.h#L18-L64
92//! [`crypto::CryptoProvider`]: crate::crypto::CryptoProvider
93//! [`ring`]: https://crates.io/crates/ring
94//! [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
95//! [`aws-lc-rs`]: https://crates.io/crates/aws-lc-rs
96//!
97//! ### Cryptography providers
98//!
99//! <!-- NOT ALL IS CORRECT FOR THIS FORK:
100//! Since Rustls 0.22 it has been possible to choose the provider of the cryptographic primitives
101//! that Rustls uses. This may be appealing if you have specific platform, compliance or feature
102//! requirements that aren't met by the default provider, [`aws-lc-rs`].
103//! - -->
104//!
105//! <!-- TODO: NEEDS IMPROVEMENT REF: https://github.com/brody4hire/portable-rustls/issues/36 -->
106//! __NOTICE: It is required to choose the provider of the cryptographic primitives that this library uses in this fork.__
107//!
108//! This be done by selecting the default provider (see the [`crypto::CryptoProvider`] documentation) or MORE DYNAMICALLY...
109//!
110//! Users that wish to customize the provider in use MORE DYNAMICALLY can do so when constructing `ClientConfig`
111//! and `ServerConfig` instances using the `with_crypto_provider` method on the respective config
112//! builder types. See the [`crypto::CryptoProvider`] documentation for more details.
113//!
114//! #### Built-in providers
115//!
116//! Rustls ships with two built-in providers controlled by associated crate features,
117//! __which are both optional in this fork__:
118//!
119//! * [`aws-lc-rs`] - available with the `aws-lc-rs` crate feature enabled.
120//! * [`ring`] - available with the `ring` crate feature enabled.
121//!
122//! See the documentation for [`crypto::CryptoProvider`] for details on how providers are
123//! selected.
124//!
125//! #### Third-party providers
126//!
127//! <!-- TODO(portable-rustls) CLEANUP THIS NOTICE & IMPROVE THE INFO HERE: -->
128//! NOTICE: ANY THIRD-PARTY PROVIDER WOULD NEED TO BE ADAPTED TO WORK DIRECTLY WITH THIS FORK OF RUSTLS.
129//!
130//! The community has also started developing third-party providers for Rustls:
131//!
132//! * [`rustls-mbedtls-provider`] - a provider that uses [`mbedtls`] for cryptography.
133//! * [`rustls-openssl`] - a provider that uses [OpenSSL] for cryptography.
134//! * [`boring-rustls-provider`] - a work-in-progress provider that uses [`boringssl`] for
135//! cryptography.
136//! * [`rustls-rustcrypto`] - an experimental provider that uses the crypto primitives
137//! from [`RustCrypto`] for cryptography.
138//! * [`rustls-symcrypt`] - a provider that uses Microsoft's [SymCrypt] library.
139//! * [`rustls-wolfcrypt-provider`] - a work-in-progress provider that uses [`wolfCrypt`] for cryptography.
140//!
141//! [`rustls-mbedtls-provider`]: https://github.com/fortanix/rustls-mbedtls-provider
142//! [`mbedtls`]: https://github.com/Mbed-TLS/mbedtls
143//! [`rustls-openssl`]: https://github.com/tofay/rustls-openssl
144//! [OpenSSL]: https://openssl-library.org/
145//! [`rustls-symcrypt`]: https://github.com/microsoft/rustls-symcrypt
146//! [SymCrypt]: https://github.com/microsoft/SymCrypt
147//! [`boring-rustls-provider`]: https://github.com/janrueth/boring-rustls-provider
148//! [`boringssl`]: https://github.com/google/boringssl
149//! [`rustls-rustcrypto`]: https://github.com/RustCrypto/rustls-rustcrypto
150//! [`RustCrypto`]: https://github.com/RustCrypto
151//! [`rustls-wolfcrypt-provider`]: https://github.com/wolfSSL/rustls-wolfcrypt-provider
152//! [`wolfCrypt`]: https://www.wolfssl.com/products/wolfcrypt
153//!
154//! #### Custom provider
155//!
156//! <!-- TODO(portable-rustls) UPDATE INFO BELOW AS MAY BE NEEDED FOR THIS FORK -->
157//!
158//! There is a simple example of writing your own provider in the [`custom provider example`].
159//! This example implements a minimal provider using parts of the [`RustCrypto`]
160//! ecosystem.
161//!
162//! As described above, it is (highly) recommended to add dependency on this fork as follows in `Cargo.toml`
163//! as done in the [`custom provider example`] in this fork:
164//!
165//! >```rust,ignore
166//! >rustls = { package = "portable-rustls", features=[...], ... }
167//! >```
168//!
169//! See the [Making a custom CryptoProvider] section of the documentation for more information
170//! on this topic.
171//!
172//! <!-- TODO `custom provider example` reference text is updated in this fork to improve consistency - TODO contribute update to upstream RUSTLS -->
173//! [`custom provider example`]: https://github.com/brody4hire/portable-rustls/tree/main-develop-head/provider-example/
174//! [`RustCrypto`]: https://github.com/RustCrypto
175//! [Making a custom CryptoProvider]: https://docs.rs/portable-rustls/latest/portable_rustls/crypto/struct.CryptoProvider.html#making-a-custom-cryptoprovider
176//!
177//! ## Design overview
178//!
179//! Rustls is a low-level library. If your goal is to make HTTPS connections you may prefer
180//! to use a library built on top of Rustls like [hyper] or [ureq].
181//!
182//! [hyper]: https://crates.io/crates/hyper
183//! [ureq]: https://crates.io/crates/ureq
184//!
185//! ### Rustls does not take care of network IO
186//! It doesn't make or accept TCP connections, or do DNS, or read or write files.
187//!
188//! Our [examples] directory contains demos that show how to handle I/O using the
189//! [`stream::Stream`] helper, as well as more complex asynchronous I/O using [`mio`].
190//! If you're already using Tokio for an async runtime you may prefer to use [`tokio-rustls`] instead
191//! of interacting with rustls directly.
192//!
193//! [examples]: https://github.com/brody4hire/portable-rustls/tree/main-develop-head/examples
194//! [`tokio-rustls`]: https://github.com/rustls/tokio-rustls
195//!
196//! ### Rustls provides encrypted pipes
197//! These are the [`ServerConnection`] and [`ClientConnection`] types. You supply raw TLS traffic
198//! on the left (via the [`read_tls()`] and [`write_tls()`] methods) and then read/write the
199//! plaintext on the right:
200//!
201//! [`read_tls()`]: Connection::read_tls
202//! [`write_tls()`]: Connection::read_tls
203//!
204//! ```text
205//! TLS Plaintext
206//! === =========
207//! read_tls() +-----------------------+ reader() as io::Read
208//! | |
209//! +---------> ClientConnection +--------->
210//! | or |
211//! <---------+ ServerConnection <---------+
212//! | |
213//! write_tls() +-----------------------+ writer() as io::Write
214//! ```
215//!
216//! ### Rustls takes care of server certificate verification
217//! You do not need to provide anything other than a set of root certificates to trust.
218//! Certificate verification cannot be turned off or disabled in the main API.
219//!
220//! ## Getting started
221//! This is the minimum you need to do to make a TLS client connection.
222//!
223//! First we load some root certificates. These are used to authenticate the server.
224//! The simplest way is to depend on the [`webpki_roots`] crate which contains
225//! the Mozilla set of root certificates.
226//!
227//! ```rust,no_run
228//! # #[cfg(feature = "aws-lc-rs")] {
229//! # use portable_rustls as rustls; // DOC IMPORT WORKAROUND for this fork
230//! let root_store = rustls::RootCertStore::from_iter(
231//! webpki_roots::TLS_SERVER_ROOTS
232//! .iter()
233//! .cloned(),
234//! );
235//! # }
236//! ```
237//!
238//! [`webpki_roots`]: https://crates.io/crates/webpki-roots
239//!
240//! Next, we make a `ClientConfig`. You're likely to make one of these per process,
241//! and use it for all connections made by that process.
242//!
243//! ```rust,no_run
244//! # #[cfg(feature = "aws_lc_rs")] {
245//! # use portable_rustls as rustls; // DOC IMPORT WORKAROUND for this fork
246//! # let root_store: rustls::RootCertStore = panic!();
247//! let config = rustls::ClientConfig::builder()
248//! .with_root_certificates(root_store)
249//! .with_no_client_auth();
250//! # }
251//! ```
252//!
253//! Now we can make a connection. You need to provide the server's hostname so we
254//! know what to expect to find in the server's certificate.
255//!
256//! ```rust
257//! # #[cfg(feature = "aws_lc_rs")] {
258//! # use portable_rustls as rustls; // DOC IMPORT WORKAROUND for this fork
259//! # use webpki;
260//! # use std::sync::Arc;
261//! # rustls::crypto::aws_lc_rs::default_provider().install_default();
262//! # let root_store = rustls::RootCertStore::from_iter(
263//! # webpki_roots::TLS_SERVER_ROOTS
264//! # .iter()
265//! # .cloned(),
266//! # );
267//! # let config = rustls::ClientConfig::builder()
268//! # .with_root_certificates(root_store)
269//! # .with_no_client_auth();
270//! let rc_config = Arc::new(config);
271//! let example_com = "example.com".try_into().unwrap();
272//! let mut client = rustls::ClientConnection::new(rc_config, example_com);
273//! # }
274//! ```
275//!
276//! Now you should do appropriate IO for the `client` object. If `client.wants_read()` yields
277//! true, you should call `client.read_tls()` when the underlying connection has data.
278//! Likewise, if `client.wants_write()` yields true, you should call `client.write_tls()`
279//! when the underlying connection is able to send data. You should continue doing this
280//! as long as the connection is valid.
281//!
282//! The return types of `read_tls()` and `write_tls()` only tell you if the IO worked. No
283//! parsing or processing of the TLS messages is done. After each `read_tls()` you should
284//! therefore call `client.process_new_packets()` which parses and processes the messages.
285//! Any error returned from `process_new_packets` is fatal to the connection, and will tell you
286//! why. For example, if the server's certificate is expired `process_new_packets` will
287//! return `Err(InvalidCertificate(Expired))`. From this point on,
288//! `process_new_packets` will not do any new work and will return that error continually.
289//!
290//! You can extract newly received data by calling `client.reader()` (which implements the
291//! `io::Read` trait). You can send data to the peer by calling `client.writer()` (which
292//! implements `io::Write` trait). Note that `client.writer().write()` buffers data you
293//! send if the TLS connection is not yet established: this is useful for writing (say) a
294//! HTTP request, but this is buffered so avoid large amounts of data.
295//!
296//! The following code uses a fictional socket IO API for illustration, and does not handle
297//! errors.
298//!
299//! ```rust,no_run
300//! # #[cfg(feature = "aws_lc_rs")] {
301//! # use portable_rustls as rustls; // DOC IMPORT WORKAROUND for this fork
302//! # let mut client = rustls::ClientConnection::new(panic!(), panic!()).unwrap();
303//! # struct Socket { }
304//! # impl Socket {
305//! # fn ready_for_write(&self) -> bool { false }
306//! # fn ready_for_read(&self) -> bool { false }
307//! # fn wait_for_something_to_happen(&self) { }
308//! # }
309//! #
310//! # use std::io::{Read, Write, Result};
311//! # impl Read for Socket {
312//! # fn read(&mut self, buf: &mut [u8]) -> Result<usize> { panic!() }
313//! # }
314//! # impl Write for Socket {
315//! # fn write(&mut self, buf: &[u8]) -> Result<usize> { panic!() }
316//! # fn flush(&mut self) -> Result<()> { panic!() }
317//! # }
318//! #
319//! # fn connect(_address: &str, _port: u16) -> Socket {
320//! # panic!();
321//! # }
322//! use std::io;
323//! use rustls::Connection;
324//!
325//! client.writer().write(b"GET / HTTP/1.0\r\n\r\n").unwrap();
326//! let mut socket = connect("example.com", 443);
327//! loop {
328//! if client.wants_read() && socket.ready_for_read() {
329//! client.read_tls(&mut socket).unwrap();
330//! client.process_new_packets().unwrap();
331//!
332//! let mut plaintext = Vec::new();
333//! client.reader().read_to_end(&mut plaintext).unwrap();
334//! io::stdout().write(&plaintext).unwrap();
335//! }
336//!
337//! if client.wants_write() && socket.ready_for_write() {
338//! client.write_tls(&mut socket).unwrap();
339//! }
340//!
341//! socket.wait_for_something_to_happen();
342//! }
343//! # }
344//! ```
345//!
346//! # Examples
347//!
348//! You can find several client and server examples of varying complexity in the [examples]
349//! directory, including [`tlsserver-mio`](https://github.com/brody4hire/portable-rustls/blob/main-develop-head/examples/src/bin/tlsserver-mio.rs)
350//! and [`tlsclient-mio`](https://github.com/brody4hire/portable-rustls/blob/main-develop-head/examples/src/bin/tlsclient-mio.rs)
351//! \- full worked examples using [`mio`].
352//!
353//! [`mio`]: https://docs.rs/mio/latest/mio/
354//!
355//! # Crate features and options
356//!
357//! ## Crate features
358//! Here's a list of what features are exposed by the rustls crate and what
359//! they mean.
360//!
361//! - `std`: enable the high-level (buffered) Connection API and other functionality
362//! which relies on the `std` library.
363//!
364//! - `aws-lc-rs`: makes the rustls crate depend on the [`aws-lc-rs`] crate.
365//! Use `rustls::crypto::aws_lc_rs::default_provider().install_default()` to
366//! use it as the default `CryptoProvider`, or provide it explicitly
367//! when making a `ClientConfig` or `ServerConfig`.
368//!
369//! Note that aws-lc-rs has additional build-time dependencies like cmake.
370//! See [the documentation](https://aws.github.io/aws-lc-rs/requirements/index.html) for details.
371//!
372//! - `ring`: makes the rustls crate depend on the *ring* crate for cryptography.
373//! Use `rustls::crypto::ring::default_provider().install_default()` to
374//! use it as the default `CryptoProvider`, or provide it explicitly
375//! when making a `ClientConfig` or `ServerConfig`.
376//!
377//! <!-- [FIPS REMOVED FROM THIS FORK]
378//! - `fips`: enable support for FIPS140-3-approved cryptography, via the [`aws-lc-rs`] crate.
379//! This feature enables the `aws-lc-rs` crate feature, which makes the rustls crate depend
380//! on [aws-lc-rs](https://github.com/aws/aws-lc-rs). It also changes the default
381//! for [`ServerConfig::require_ems`] and [`ClientConfig::require_ems`].
382//!
383//! See [manual::_06_fips] for more details.
384//! -- -->
385//!
386//! - `prefer-post-quantum`: for the [`aws-lc-rs`]-backed provider, prioritizes post-quantum secure
387//! key exchange by default (using X25519MLKEM768). This feature merely alters the order
388//! of `rustls::crypto::aws_lc_rs::DEFAULT_KX_GROUPS`. We expect to add this feature
389//! to the default set in a future minor release. See [the manual][x25519mlkem768-manual]
390//! for more details.
391//!
392//! <!-- UPDATED DESCRIPTION FOR THIS FORK -->
393//! - `custom-provider`: disables implicit use of any built-in providers
394//! (`aws-lc-rs` or `ring`), if enabled by crate features. This forces
395//! applications to manually install one, for instance, when using a custom `CryptoProvider`.
396//!
397//! - `tls12`: enable support for TLS version 1.2. Note that, due to the
398//! additive nature of Cargo features and because it is enabled by default, other crates
399//! in your dependency graph could re-enable it for your application. If you want to disable
400//! TLS 1.2 for security reasons, consider explicitly enabling TLS 1.3 only in the config
401//! builder API.
402//!
403//! - `logging`: make the rustls crate depend on the `log` crate.
404//! rustls outputs interesting protocol-level messages at `trace!` and `debug!` level,
405//! and protocol-level errors at `warn!` and `error!` level. The log messages do not
406//! contain secret key data, and so are safe to archive without affecting session security.
407//!
408//! - `read_buf`: when building with Rust Nightly, adds support for the unstable
409//! `std::io::ReadBuf` and related APIs. This reduces costs from initializing
410//! buffers. Will do nothing on non-Nightly releases.
411//!
412//! - `brotli`: uses the `brotli` crate for RFC8879 certificate compression support.
413//!
414//! - `zlib`: uses the `zlib-rs` crate for RFC8879 certificate compression support.
415//!
416//! ## Crate cfg options
417//!
418//! - `unstable_portable_atomic_arc` - configures this fork to use `Arc` from `portable_atomic_util` instead
419//! of `std::sync::Arc` - requires Rust nightly together with `portable_atomic_unstable_coerce_unsized`
420//! to build successfully.
421//!
422//! [x25519mlkem768-manual]: manual::_05_defaults#about-the-post-quantum-secure-key-exchange-x25519mlkem768
423
424// Require docs for public APIs, deny unsafe code, etc.
425#![forbid(unsafe_code, unused_must_use)]
426#![cfg_attr(not(any(read_buf, bench)), forbid(unstable_features))]
427#![warn(
428 clippy::alloc_instead_of_core,
429 clippy::clone_on_ref_ptr,
430 clippy::manual_let_else,
431 clippy::std_instead_of_core,
432 clippy::use_self,
433 clippy::upper_case_acronyms,
434 elided_lifetimes_in_paths,
435 missing_docs,
436 trivial_casts,
437 trivial_numeric_casts,
438 unreachable_pub,
439 unused_import_braces,
440 unused_extern_crates,
441 unused_qualifications
442)]
443// Relax these clippy lints:
444// - ptr_arg: this triggers on references to type aliases that are Vec
445// underneath.
446// - too_many_arguments: some things just need a lot of state, wrapping it
447// doesn't necessarily make it easier to follow what's going on
448// - new_ret_no_self: we sometimes return `Arc<Self>`, which seems fine
449// - single_component_path_imports: our top-level `use log` import causes
450// a false positive, https://github.com/rust-lang/rust-clippy/issues/5210
451// - new_without_default: for internal constructors, the indirection is not
452// helpful
453#![allow(
454 clippy::too_many_arguments,
455 clippy::new_ret_no_self,
456 clippy::ptr_arg,
457 clippy::single_component_path_imports,
458 clippy::new_without_default
459)]
460// QUICK CLIPPY WORKAROUND for `unstable_portable_atomic_arc` IN THIS FORK
461#![allow(unexpected_cfgs)]
462// Enable documentation for all features on docs.rs
463#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]
464// XXX: Because of https://github.com/rust-lang/rust/issues/54726, we cannot
465// write `#![rustversion::attr(nightly, feature(read_buf))]` here. Instead,
466// build.rs set `read_buf` for (only) Rust Nightly to get the same effect.
467//
468// All the other conditional logic in the crate could use
469// `#[rustversion::nightly]` instead of `#[cfg(read_buf)]`; `#[cfg(read_buf)]`
470// is used to avoid needing `rustversion` to be compiled twice during
471// cross-compiling.
472#![cfg_attr(read_buf, feature(read_buf))]
473#![cfg_attr(read_buf, feature(core_io_borrowed_buf))]
474#![cfg_attr(bench, feature(test))]
475#![no_std]
476
477extern crate alloc;
478// This `extern crate` plus the `#![no_std]` attribute changes the default prelude from
479// `std::prelude` to `core::prelude`. That forces one to _explicitly_ import (`use`) everything that
480// is in `std::prelude` but not in `core::prelude`. This helps maintain no-std support as even
481// developers that are not interested in, or aware of, no-std support and / or that never run
482// `cargo build --no-default-features` locally will get errors when they rely on `std::prelude` API.
483#[cfg(any(feature = "std", test))]
484extern crate std;
485
486#[cfg(doc)]
487use crate::crypto::CryptoProvider;
488
489// Import `test` sysroot crate for `Bencher` definitions.
490#[cfg(bench)]
491#[allow(unused_extern_crates)]
492extern crate test;
493
494// log for logging (optional).
495#[cfg(feature = "logging")]
496use log;
497
498#[cfg(not(feature = "logging"))]
499mod log {
500 macro_rules! trace ( ($($tt:tt)*) => {{}} );
501 macro_rules! debug ( ($($tt:tt)*) => {{}} );
502 macro_rules! error ( ($($tt:tt)*) => {{}} );
503 macro_rules! _warn ( ($($tt:tt)*) => {{}} );
504 pub(crate) use {_warn as warn, debug, error, trace};
505}
506
507#[cfg(test)]
508#[macro_use]
509mod test_macros;
510
511/// This internal `sync` module aliases the `Arc` implementation to allow downstream forks
512/// of rustls targetting architectures without atomic pointers to replace the implementation
513/// with another implementation such as `portable_atomic_util::Arc` in one central location.
514mod sync {
515 #[cfg(unstable_portable_atomic_arc)]
516 #[allow(clippy::disallowed_types)]
517 pub(crate) type Arc<T> = portable_atomic_util::Arc<T>;
518 #[cfg(not(unstable_portable_atomic_arc))]
519 #[allow(clippy::disallowed_types)]
520 pub(crate) type Arc<T> = alloc::sync::Arc<T>;
521}
522
523#[macro_use]
524mod msgs;
525mod common_state;
526pub mod compress;
527mod conn;
528/// Crypto provider interface.
529pub mod crypto;
530mod error;
531mod hash_hs;
532#[cfg(any(feature = "std", feature = "hashbrown"))]
533mod limited_cache;
534mod rand;
535mod record_layer;
536#[cfg(feature = "std")]
537mod stream;
538#[cfg(feature = "tls12")]
539mod tls12;
540mod tls13;
541mod vecbuf;
542mod verify;
543#[cfg(test)]
544mod verifybench;
545mod x509;
546#[macro_use]
547mod check;
548#[cfg(feature = "logging")]
549mod bs_debug;
550mod builder;
551mod enums;
552mod key_log;
553#[cfg(feature = "std")]
554mod key_log_file;
555mod suites;
556mod versions;
557mod webpki;
558
559/// Internal classes that are used in integration tests.
560/// The contents of this section DO NOT form part of the stable interface.
561#[allow(missing_docs)]
562#[doc(hidden)]
563pub mod internal {
564 /// Low-level TLS message parsing and encoding functions.
565 pub mod msgs {
566 pub mod base {
567 pub use crate::msgs::base::{Payload, PayloadU16};
568 }
569 pub mod codec {
570 pub use crate::msgs::codec::{Codec, Reader};
571 }
572 pub mod enums {
573 pub use crate::msgs::enums::{
574 AlertLevel, CertificateType, Compression, EchVersion, HpkeAead, HpkeKdf, HpkeKem,
575 NamedGroup,
576 };
577 }
578 pub mod fragmenter {
579 pub use crate::msgs::fragmenter::MessageFragmenter;
580 }
581 pub mod handshake {
582 pub use crate::msgs::handshake::{
583 CertificateChain, ClientExtension, ClientHelloPayload, DistinguishedName,
584 EchConfigContents, EchConfigPayload, HandshakeMessagePayload, HandshakePayload,
585 HpkeKeyConfig, HpkeSymmetricCipherSuite, KeyShareEntry, Random, ServerExtension,
586 ServerName, SessionId,
587 };
588 }
589 pub mod message {
590 pub use crate::msgs::message::{
591 Message, MessagePayload, OutboundOpaqueMessage, PlainMessage,
592 };
593 }
594 pub mod persist {
595 pub use crate::msgs::persist::ServerSessionValue;
596 }
597 }
598
599 pub use crate::tls13::key_schedule::{derive_traffic_iv, derive_traffic_key};
600
601 pub mod fuzzing {
602 pub use crate::msgs::deframer::fuzz_deframer;
603 }
604}
605
606/// Unbuffered connection API
607///
608/// This is an alternative to the [`crate::ConnectionCommon`] API that does not internally buffer
609/// TLS nor plaintext data. Instead those buffers are managed by the API user so they have
610/// control over when and how to allocate, resize and dispose of them.
611///
612/// This API is lower level than the `ConnectionCommon` API and is built around a state machine
613/// interface where the API user must handle each state to advance and complete the
614/// handshake process.
615///
616/// Like the `ConnectionCommon` API, no IO happens internally so all IO must be handled by the API
617/// user. Unlike the `ConnectionCommon` API, this API does not make use of the [`std::io::Read`] and
618/// [`std::io::Write`] traits so it's usable in no-std context.
619///
620/// The entry points into this API are [`crate::client::UnbufferedClientConnection::new`],
621/// [`crate::server::UnbufferedServerConnection::new`] and
622/// [`unbuffered::UnbufferedConnectionCommon::process_tls_records`]. The state machine API is
623/// documented in [`unbuffered::ConnectionState`].
624///
625/// # Examples
626///
627/// [`unbuffered-client`] and [`unbuffered-server`] are examples that fully exercise the API in
628/// std, non-async context.
629///
630/// [`unbuffered-client`]: https://github.com/brody4hire/portable-rustls/blob/main-develop-head/examples/src/bin/unbuffered-client.rs
631/// [`unbuffered-server`]: https://github.com/brody4hire/portable-rustls/blob/main-develop-head/examples/src/bin/unbuffered-server.rs
632pub mod unbuffered {
633 pub use crate::conn::unbuffered::{
634 AppDataRecord, ConnectionState, EncodeError, EncodeTlsData, EncryptError,
635 InsufficientSizeError, ReadEarlyData, ReadTraffic, TransmitTlsData, UnbufferedStatus,
636 WriteTraffic,
637 };
638 pub use crate::conn::UnbufferedConnectionCommon;
639}
640
641// The public interface is:
642pub use crate::builder::{ConfigBuilder, ConfigSide, WantsVerifier, WantsVersions};
643pub use crate::common_state::{CommonState, HandshakeKind, IoState, Side};
644#[cfg(feature = "std")]
645pub use crate::conn::{Connection, Reader, Writer};
646pub use crate::conn::{ConnectionCommon, SideData};
647pub use crate::enums::{
648 AlertDescription, CertificateCompressionAlgorithm, CipherSuite, ContentType, HandshakeType,
649 ProtocolVersion, SignatureAlgorithm, SignatureScheme,
650};
651pub use crate::error::{
652 CertRevocationListError, CertificateError, EncryptedClientHelloError, Error, InconsistentKeys,
653 InvalidMessage, OtherError, PeerIncompatible, PeerMisbehaved,
654};
655pub use crate::key_log::{KeyLog, NoKeyLog};
656#[cfg(feature = "std")]
657pub use crate::key_log_file::KeyLogFile;
658pub use crate::msgs::enums::NamedGroup;
659pub use crate::msgs::ffdhe_groups;
660pub use crate::msgs::handshake::DistinguishedName;
661#[cfg(feature = "std")]
662pub use crate::stream::{Stream, StreamOwned};
663pub use crate::suites::{
664 CipherSuiteCommon, ConnectionTrafficSecrets, ExtractedSecrets, SupportedCipherSuite,
665};
666#[cfg(feature = "std")]
667pub use crate::ticketer::TicketRotator;
668#[cfg(any(feature = "std", feature = "hashbrown"))] // < XXX: incorrect feature gate
669pub use crate::ticketer::TicketSwitcher;
670#[cfg(feature = "tls12")]
671pub use crate::tls12::Tls12CipherSuite;
672pub use crate::tls13::Tls13CipherSuite;
673pub use crate::verify::DigitallySignedStruct;
674pub use crate::versions::{SupportedProtocolVersion, ALL_VERSIONS, DEFAULT_VERSIONS};
675pub use crate::webpki::RootCertStore;
676
677/// Items for use in a client.
678pub mod client {
679 pub(super) mod builder;
680 mod client_conn;
681 mod common;
682 mod ech;
683 pub(super) mod handy;
684 mod hs;
685 #[cfg(feature = "tls12")]
686 mod tls12;
687 mod tls13;
688
689 pub use builder::WantsClientCert;
690 pub use client_conn::{
691 ClientConfig, ClientConnectionData, ClientSessionStore, EarlyDataError, ResolvesClientCert,
692 Resumption, Tls12Resumption, UnbufferedClientConnection,
693 };
694 #[cfg(feature = "std")]
695 pub use client_conn::{ClientConnection, WriteEarlyData};
696 pub use ech::{EchConfig, EchGreaseConfig, EchMode, EchStatus};
697 pub use handy::AlwaysResolvesClientRawPublicKeys;
698 #[cfg(any(feature = "std", feature = "hashbrown"))]
699 pub use handy::ClientSessionMemoryCache;
700
701 /// Dangerous configuration that should be audited and used with extreme care.
702 pub mod danger {
703 pub use super::builder::danger::DangerousClientConfigBuilder;
704 pub use super::client_conn::danger::DangerousClientConfig;
705 pub use crate::verify::{HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier};
706 }
707
708 pub use crate::msgs::persist::{Tls12ClientSessionValue, Tls13ClientSessionValue};
709 pub use crate::webpki::{
710 verify_server_cert_signed_by_trust_anchor, verify_server_name, ServerCertVerifierBuilder,
711 VerifierBuilderError, WebPkiServerVerifier,
712 };
713}
714
715pub use client::ClientConfig;
716#[cfg(feature = "std")]
717pub use client::ClientConnection;
718
719/// Items for use in a server.
720pub mod server {
721 pub(crate) mod builder;
722 mod common;
723 pub(crate) mod handy;
724 mod hs;
725 mod server_conn;
726 #[cfg(feature = "tls12")]
727 mod tls12;
728 mod tls13;
729
730 pub use builder::WantsServerCert;
731 #[cfg(any(feature = "std", feature = "hashbrown"))]
732 pub use handy::ResolvesServerCertUsingSni;
733 #[cfg(any(feature = "std", feature = "hashbrown"))]
734 pub use handy::ServerSessionMemoryCache;
735 pub use handy::{AlwaysResolvesServerRawPublicKeys, NoServerSessionStorage};
736 pub use server_conn::{
737 Accepted, ClientHello, ProducesTickets, ResolvesServerCert, ServerConfig,
738 ServerConnectionData, StoresServerSessions, UnbufferedServerConnection,
739 };
740 #[cfg(feature = "std")]
741 pub use server_conn::{AcceptedAlert, Acceptor, ReadEarlyData, ServerConnection};
742
743 pub use crate::verify::NoClientAuth;
744 pub use crate::webpki::{
745 ClientCertVerifierBuilder, ParsedCertificate, VerifierBuilderError, WebPkiClientVerifier,
746 };
747
748 /// Dangerous configuration that should be audited and used with extreme care.
749 pub mod danger {
750 pub use crate::verify::{ClientCertVerified, ClientCertVerifier};
751 }
752}
753
754pub use server::ServerConfig;
755#[cfg(feature = "std")]
756pub use server::ServerConnection;
757
758/// All defined protocol versions appear in this module.
759///
760/// ALL_VERSIONS is a provided as an array of all of these values.
761pub mod version {
762 #[cfg(feature = "tls12")]
763 pub use crate::versions::TLS12;
764 pub use crate::versions::TLS13;
765}
766
767/// Re-exports the contents of the [rustls-pki-types](https://docs.rs/rustls-pki-types) crate for easy access
768pub mod pki_types {
769 #[doc(no_inline)]
770 pub use pki_types::*;
771}
772
773/// Message signing interfaces.
774pub mod sign {
775 pub use crate::crypto::signer::{CertifiedKey, Signer, SigningKey, SingleCertAndKey};
776}
777
778/// APIs for implementing QUIC TLS
779pub mod quic;
780
781#[cfg(any(feature = "std", feature = "hashbrown"))] // < XXX: incorrect feature gate
782/// APIs for implementing TLS tickets
783pub mod ticketer;
784
785/// This is the rustls manual.
786pub mod manual;
787
788pub mod time_provider;
789
790/// APIs abstracting over locking primitives.
791pub mod lock;
792
793/// Polyfills for features that are not yet stabilized or available with current MSRV.
794pub(crate) mod polyfill;
795
796#[cfg(any(feature = "std", feature = "hashbrown"))]
797mod hash_map {
798 #[cfg(feature = "std")]
799 pub(crate) use std::collections::hash_map::Entry;
800 #[cfg(feature = "std")]
801 pub(crate) use std::collections::HashMap;
802
803 #[cfg(all(not(feature = "std"), feature = "hashbrown"))]
804 pub(crate) use hashbrown::hash_map::Entry;
805 #[cfg(all(not(feature = "std"), feature = "hashbrown"))]
806 pub(crate) use hashbrown::HashMap;
807}