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