rustls/
builder.rs

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