rustls/builder.rs
1use alloc::format;
2use core::fmt;
3use core::marker::PhantomData;
4
5use crate::client::EchMode;
6use crate::crypto::CryptoProvider;
7use crate::sync::Arc;
8use crate::time_provider::TimeProvider;
9#[cfg(doc)]
10use crate::{ClientConfig, ServerConfig};
11
12/// A [builder] for [`ServerConfig`] or [`ClientConfig`] values.
13///
14/// To get one of these, call [`ServerConfig::builder()`] or [`ClientConfig::builder()`].
15///
16/// To build a config, you must make at least two decisions (in order):
17///
18/// - How should this client or server verify certificates provided by its peer?
19/// - What certificates should this client or server present to its peer?
20///
21/// For settings besides these, see the fields of [`ServerConfig`] and [`ClientConfig`].
22///
23/// The usual choice for protocol primitives is to call
24/// [`ClientConfig::builder`]/[`ServerConfig::builder`]
25/// which will use rustls' default cryptographic provider and safe defaults for ciphersuites and
26/// protocol versions.
27///
28/// ```
29/// # #[cfg(feature = "aws-lc-rs")] {
30/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
31/// use rustls::{ClientConfig, ServerConfig};
32/// ClientConfig::builder()
33/// // ...
34/// # ;
35///
36/// ServerConfig::builder()
37/// // ...
38/// # ;
39/// # }
40/// ```
41///
42/// After choosing the `CryptoProvider`, you must choose (a) how to verify certificates and (b) what certificates
43/// (if any) to send to the peer. The methods to do this are specific to whether you're building a ClientConfig
44/// or a ServerConfig, as tracked by the [`ConfigSide`] type parameter on the various impls of ConfigBuilder.
45///
46/// A `Result<ClientConfig, Error>` or `Result<ServerConfig, Error>`is the outcome of the builder process.
47/// The error is used to report consistency problems with the configuration. For example, it's an error
48/// to have a `CryptoProvider` that has no cipher suites.
49///
50/// # ClientConfig certificate configuration
51///
52/// For a client, _certificate verification_ must be configured either by calling one of:
53/// - [`ConfigBuilder::with_root_certificates`] or
54/// - [`ConfigBuilder::dangerous()`] and [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]
55///
56/// Next, _certificate sending_ (also known as "client authentication", "mutual TLS", or "mTLS") must be configured
57/// or disabled using one of:
58/// - [`ConfigBuilder::with_no_client_auth`] - to not send client authentication (most common)
59/// - [`ConfigBuilder::with_client_auth_cert`] - to always send a specific certificate
60/// - [`ConfigBuilder::with_client_cert_resolver`] - to send a certificate chosen dynamically
61///
62/// For example:
63///
64/// ```
65/// # #[cfg(feature = "aws-lc-rs")] {
66/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
67/// # use rustls::ClientConfig;
68/// # let root_certs = rustls::RootCertStore::empty();
69/// ClientConfig::builder()
70/// .with_root_certificates(root_certs)
71/// .with_no_client_auth()
72/// .unwrap();
73/// # }
74/// ```
75///
76/// # ServerConfig certificate configuration
77///
78/// For a server, _certificate verification_ must be configured by calling one of:
79/// - [`ConfigBuilder::with_no_client_auth`] - to not require client authentication (most common)
80/// - [`ConfigBuilder::with_client_cert_verifier`] - to use a custom verifier
81///
82/// Next, _certificate sending_ must be configured by calling one of:
83/// - [`ConfigBuilder::with_single_cert`] - to send a specific certificate
84/// - [`ConfigBuilder::with_single_cert_with_ocsp`] - to send a specific certificate, plus stapled OCSP
85/// - [`ConfigBuilder::with_cert_resolver`] - to send a certificate chosen dynamically
86///
87/// For example:
88///
89/// ```no_run
90/// # #[cfg(feature = "aws-lc-rs")] {
91/// # rustls::crypto::aws_lc_rs::default_provider().install_default();
92/// # use rustls::ServerConfig;
93/// # let certs = vec![];
94/// # let private_key = pki_types::PrivateKeyDer::from(
95/// # pki_types::PrivatePkcs8KeyDer::from(vec![])
96/// # );
97/// ServerConfig::builder()
98/// .with_no_client_auth()
99/// .with_single_cert(certs, private_key)
100/// .expect("bad certificate/key/provider");
101/// # }
102/// ```
103///
104/// # Types
105///
106/// ConfigBuilder uses the [typestate] pattern to ensure at compile time that each required
107/// configuration item is provided exactly once. This is tracked in the `State` type parameter,
108/// which can have these values:
109///
110/// - [`WantsVerifier`]
111/// - [`WantsClientCert`]
112/// - [`WantsServerCert`]
113///
114/// The other type parameter is `Side`, which is either `ServerConfig` or `ClientConfig`
115/// depending on whether the ConfigBuilder was built with [`ServerConfig::builder()`] or
116/// [`ClientConfig::builder()`].
117///
118/// You won't need to write out either of these type parameters explicitly. If you write a
119/// correct chain of configuration calls they will be used automatically. If you write an
120/// incorrect chain of configuration calls you will get an error message from the compiler
121/// mentioning some of these types.
122///
123/// Additionally, ServerConfig and ClientConfig carry a private field containing a
124/// [`CryptoProvider`], from [`ClientConfig::builder_with_provider()`] or
125/// [`ServerConfig::builder_with_provider()`]. This determines which cryptographic backend
126/// is used. The default is [the process-default provider](`CryptoProvider::get_default`).
127///
128/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html
129/// [typestate]: http://cliffle.com/blog/rust-typestate/
130/// [`ServerConfig`]: crate::ServerConfig
131/// [`ServerConfig::builder`]: crate::ServerConfig::builder
132/// [`ClientConfig`]: crate::ClientConfig
133/// [`ClientConfig::builder()`]: crate::ClientConfig::builder()
134/// [`ServerConfig::builder()`]: crate::ServerConfig::builder()
135/// [`ClientConfig::builder_with_provider()`]: crate::ClientConfig::builder_with_provider()
136/// [`ServerConfig::builder_with_provider()`]: crate::ServerConfig::builder_with_provider()
137/// [`ConfigBuilder<ClientConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-3
138/// [`ConfigBuilder<ServerConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-6
139/// [`WantsClientCert`]: crate::client::WantsClientCert
140/// [`WantsServerCert`]: crate::server::WantsServerCert
141/// [`CryptoProvider::get_default`]: crate::crypto::CryptoProvider::get_default
142/// [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]: crate::client::danger::DangerousClientConfigBuilder::with_custom_certificate_verifier
143#[derive(Clone)]
144pub struct ConfigBuilder<Side: ConfigSide, State> {
145 pub(crate) state: State,
146 pub(crate) provider: Arc<CryptoProvider>,
147 pub(crate) time_provider: Arc<dyn TimeProvider>,
148 pub(crate) side: PhantomData<Side>,
149}
150
151impl<Side: ConfigSide, State> ConfigBuilder<Side, State> {
152 /// Return the crypto provider used to construct this builder.
153 pub fn crypto_provider(&self) -> &Arc<CryptoProvider> {
154 &self.provider
155 }
156}
157
158impl<Side: ConfigSide, State: fmt::Debug> fmt::Debug for ConfigBuilder<Side, State> {
159 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
160 let side_name = core::any::type_name::<Side>();
161 let (ty, _) = side_name
162 .split_once('<')
163 .unwrap_or((side_name, ""));
164 let (_, name) = ty.rsplit_once("::").unwrap_or(("", ty));
165
166 f.debug_struct(&format!("ConfigBuilder<{name}, _>",))
167 .field("state", &self.state)
168 .finish()
169 }
170}
171
172/// Config builder state where the caller must supply a verifier.
173///
174/// For more information, see the [`ConfigBuilder`] documentation.
175#[derive(Clone, Debug)]
176pub struct WantsVerifier {
177 pub(crate) client_ech_mode: Option<EchMode>,
178}
179
180/// Helper trait to abstract [`ConfigBuilder`] over building a [`ClientConfig`] or [`ServerConfig`].
181///
182/// [`ClientConfig`]: crate::ClientConfig
183/// [`ServerConfig`]: crate::ServerConfig
184pub trait ConfigSide: crate::sealed::Sealed {}
185
186impl ConfigSide for crate::ClientConfig {}
187impl ConfigSide for crate::ServerConfig {}
188
189impl crate::sealed::Sealed for crate::ClientConfig {}
190impl crate::sealed::Sealed for crate::ServerConfig {}