rustls/
builder.rs

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