1use crate::crypto::CryptoProvider;
2use crate::error::Error;
3use crate::versions;
4
5use alloc::format;
6use core::fmt;
7use core::marker::PhantomData;
8use std::sync::Arc;
9
10#[cfg(doc)]
11use crate::{ClientConfig, ServerConfig};
12
13/// A [builder] for [`ServerConfig`] or [`ClientConfig`] values.
14///
15/// To get one of these, call [`ServerConfig::builder()`] or [`ClientConfig::builder()`].
16///
17/// To build a config, you must make at least two decisions (in order):
18///
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 usual choice for protocol primitives is to call
25/// [`ClientConfig::builder`]/[`ServerConfig::builder`]
26/// which will use rustls' default cryptographic provider and safe defaults for ciphersuites and
27/// supported protocol versions.
28///
29/// ```
30/// # #[cfg(feature = "ring")] {
31/// use rustls::{ClientConfig, ServerConfig};
32/// ClientConfig::builder()
33/// // ...
34/// # ;
35///
36/// ServerConfig::builder()
37/// // ...
38/// # ;
39/// # }
40/// ```
41///
42/// You may also override the choice of protocol versions:
43///
44/// ```no_run
45/// # #[cfg(feature = "ring")] {
46/// # use rustls::ServerConfig;
47/// ServerConfig::builder_with_protocol_versions(&[&rustls::version::TLS13])
48/// // ...
49/// # ;
50/// # }
51/// ```
52///
53/// Overriding the default cryptographic provider introduces a `Result` that must be unwrapped,
54/// because the config builder checks for consistency of the choices made. For instance, it's an error to
55/// configure only TLS 1.2 cipher suites while specifying that TLS 1.3 should be the only supported protocol
56/// version.
57///
58/// If you configure a smaller set of protocol primitives than the default, you may get a smaller binary,
59/// since the code for the unused ones can be optimized away at link time.
60///
61/// After choosing protocol primitives, you must choose (a) how to verify certificates and (b) what certificates
62/// (if any) to send to the peer. The methods to do this are specific to whether you're building a ClientConfig
63/// or a ServerConfig, as tracked by the [`ConfigSide`] type parameter on the various impls of ConfigBuilder.
64///
65/// # ClientConfig certificate configuration
66///
67/// For a client, _certificate verification_ must be configured either by calling one of:
68/// - [`ConfigBuilder::with_root_certificates`] or
69/// - [`ConfigBuilder::dangerous()`] and [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]
70///
71/// Next, _certificate sending_ (also known as "client authentication", "mutual TLS", or "mTLS") must be configured
72/// or disabled using one of:
73/// - [`ConfigBuilder::with_no_client_auth`] - to not send client authentication (most common)
74/// - [`ConfigBuilder::with_client_auth_cert`] - to always send a specific certificate
75/// - [`ConfigBuilder::with_client_cert_resolver`] - to send a certificate chosen dynamically
76///
77/// For example:
78///
79/// ```
80/// # #[cfg(feature = "ring")] {
81/// # use rustls::ClientConfig;
82/// # let root_certs = rustls::RootCertStore::empty();
83/// ClientConfig::builder()
84/// .with_root_certificates(root_certs)
85/// .with_no_client_auth();
86/// # }
87/// ```
88///
89/// # ServerConfig certificate configuration
90///
91/// For a server, _certificate verification_ must be configured by calling one of:
92/// - [`ConfigBuilder::with_no_client_auth`] - to not require client authentication (most common)
93/// - [`ConfigBuilder::with_client_cert_verifier`] - to use a custom verifier
94///
95/// Next, _certificate sending_ must be configured by calling one of:
96/// - [`ConfigBuilder::with_single_cert`] - to send a specific certificate
97/// - [`ConfigBuilder::with_single_cert_with_ocsp`] - to send a specific certificate, plus stapled OCSP
98/// - [`ConfigBuilder::with_cert_resolver`] - to send a certificate chosen dynamically
99///
100/// For example:
101///
102/// ```no_run
103/// # #[cfg(feature = "ring")] {
104/// # use rustls::ServerConfig;
105/// # let certs = vec![];
106/// # let private_key = pki_types::PrivateKeyDer::from(
107/// # pki_types::PrivatePkcs8KeyDer::from(vec![])
108/// # );
109/// ServerConfig::builder()
110/// .with_no_client_auth()
111/// .with_single_cert(certs, private_key)
112/// .expect("bad certificate/key");
113/// # }
114/// ```
115///
116/// # Types
117///
118/// ConfigBuilder uses the [typestate] pattern to ensure at compile time that each required
119/// configuration item is provided exactly once. This is tracked in the `State` type parameter,
120/// which can have these values:
121///
122/// - [`WantsVersions`]
123/// - [`WantsVerifier`]
124/// - [`WantsClientCert`]
125/// - [`WantsServerCert`]
126///
127/// The other type parameter is `Side`, which is either `ServerConfig` or `ClientConfig`
128/// depending on whether the ConfigBuilder was built with [`ServerConfig::builder()`] or
129/// [`ClientConfig::builder()`].
130///
131/// You won't need to write out either of these type parameters explicitly. If you write a
132/// correct chain of configuration calls they will be used automatically. If you write an
133/// incorrect chain of configuration calls you will get an error message from the compiler
134/// mentioning some of these types.
135///
136/// Additionally, ServerConfig and ClientConfig carry a private field containing a
137/// [`CryptoProvider`], from [`ClientConfig::builder_with_provider()`] or
138/// [`ServerConfig::builder_with_provider()`]. This determines which cryptographic backend
139/// is used. The default is [`ring::provider`].
140///
141/// [builder]: https://rust-unofficial.github.io/patterns/patterns/creational/builder.html
142/// [typestate]: http://cliffle.com/blog/rust-typestate/
143/// [`ServerConfig`]: crate::ServerConfig
144/// [`ServerConfig::builder`]: crate::ServerConfig::builder
145/// [`ClientConfig`]: crate::ClientConfig
146/// [`ClientConfig::builder()`]: crate::ClientConfig::builder()
147/// [`ServerConfig::builder()`]: crate::ServerConfig::builder()
148/// [`ClientConfig::builder_with_provider()`]: crate::ClientConfig::builder_with_provider()
149/// [`ServerConfig::builder_with_provider()`]: crate::ServerConfig::builder_with_provider()
150/// [`ConfigBuilder<ClientConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-3
151/// [`ConfigBuilder<ServerConfig, WantsVerifier>`]: struct.ConfigBuilder.html#impl-6
152/// [`WantsClientCert`]: crate::client::WantsClientCert
153/// [`WantsServerCert`]: crate::server::WantsServerCert
154/// [`ring::provider`]: crate::crypto::ring::default_provider
155/// [`DangerousClientConfigBuilder::with_custom_certificate_verifier`]: crate::client::danger::DangerousClientConfigBuilder::with_custom_certificate_verifier
156#[derive(Clone)]
157pub struct ConfigBuilder<Side: ConfigSide, State> {
158 pub(crate) state: State,
159 pub(crate) side: PhantomData<Side>,
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: &str = core::any::type_name::<Side>();
165 let (ty: &str, _) = side_name
166 .split_once('<')
167 .unwrap_or((side_name, ""));
168 let (_, name: &str) = ty.rsplit_once("::").unwrap_or(("", ty));
169
170 f&mut DebugStruct<'_, '_>.debug_struct(&format!("ConfigBuilder<{}, _>", name,))
171 .field(name:"state", &self.state)
172 .finish()
173 }
174}
175
176/// Config builder state where the caller must supply TLS protocol versions.
177///
178/// For more information, see the [`ConfigBuilder`] documentation.
179#[derive(Clone, Debug)]
180pub struct WantsVersions {
181 pub(crate) provider: Arc<CryptoProvider>,
182}
183
184impl<S: ConfigSide> ConfigBuilder<S, WantsVersions> {
185 /// Accept the default protocol versions: both TLS1.2 and TLS1.3 are enabled.
186 pub fn with_safe_default_protocol_versions(
187 self,
188 ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> {
189 self.with_protocol_versions(versions::DEFAULT_VERSIONS)
190 }
191
192 /// Use a specific set of protocol versions.
193 pub fn with_protocol_versions(
194 self,
195 versions: &[&'static versions::SupportedProtocolVersion],
196 ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> {
197 let mut any_usable_suite = false;
198 for suite in &self.state.provider.cipher_suites {
199 if versions.contains(&suite.version()) {
200 any_usable_suite = true;
201 break;
202 }
203 }
204
205 if !any_usable_suite {
206 return Err(Error::General("no usable cipher suites configured".into()));
207 }
208
209 if self.state.provider.kx_groups.is_empty() {
210 return Err(Error::General("no kx groups configured".into()));
211 }
212
213 Ok(ConfigBuilder {
214 state: WantsVerifier {
215 provider: self.state.provider,
216 versions: versions::EnabledVersions::new(versions),
217 },
218 side: self.side,
219 })
220 }
221}
222
223/// Config builder state where the caller must supply a verifier.
224///
225/// For more information, see the [`ConfigBuilder`] documentation.
226#[derive(Clone, Debug)]
227pub struct WantsVerifier {
228 pub(crate) provider: Arc<CryptoProvider>,
229 pub(crate) versions: versions::EnabledVersions,
230}
231
232/// Helper trait to abstract [`ConfigBuilder`] over building a [`ClientConfig`] or [`ServerConfig`].
233///
234/// [`ClientConfig`]: crate::ClientConfig
235/// [`ServerConfig`]: crate::ServerConfig
236pub trait ConfigSide: sealed::Sealed {}
237
238impl ConfigSide for crate::ClientConfig {}
239impl ConfigSide for crate::ServerConfig {}
240
241mod sealed {
242 pub trait Sealed {}
243 impl Sealed for crate::ClientConfig {}
244 impl Sealed for crate::ServerConfig {}
245}
246