1 | use alloc::format; |
2 | use alloc::vec::Vec; |
3 | use core::fmt; |
4 | use core::marker::PhantomData; |
5 | |
6 | use crate::client::EchMode; |
7 | use crate::crypto::CryptoProvider; |
8 | use crate::error::Error; |
9 | use crate::msgs::handshake::ALL_KEY_EXCHANGE_ALGORITHMS; |
10 | use crate::sync::Arc; |
11 | use crate::time_provider::TimeProvider; |
12 | use crate::versions; |
13 | #[cfg (doc)] |
14 | use 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)] |
164 | pub struct ConfigBuilder<Side: ConfigSide, State> { |
165 | pub(crate) state: State, |
166 | pub(crate) provider: Arc<CryptoProvider>, |
167 | pub(crate) time_provider: Arc<dyn TimeProvider>, |
168 | pub(crate) side: PhantomData<Side>, |
169 | } |
170 | |
171 | impl<Side: ConfigSide, State> ConfigBuilder<Side, State> { |
172 | /// Return the crypto provider used to construct this builder. |
173 | pub fn crypto_provider(&self) -> &Arc<CryptoProvider> { |
174 | &self.provider |
175 | } |
176 | } |
177 | |
178 | impl<Side: ConfigSide, State: fmt::Debug> fmt::Debug for ConfigBuilder<Side, State> { |
179 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
180 | let side_name: &'static str = core::any::type_name::<Side>(); |
181 | let (ty: &str, _) = side_name |
182 | .split_once('<' ) |
183 | .unwrap_or((side_name, "" )); |
184 | let (_, name: &str) = ty.rsplit_once("::" ).unwrap_or(("" , ty)); |
185 | |
186 | f&mut DebugStruct<'_, '_>.debug_struct(&format!("ConfigBuilder< {}, _>" , name,)) |
187 | .field(name:"state" , &self.state) |
188 | .finish() |
189 | } |
190 | } |
191 | |
192 | /// Config builder state where the caller must supply TLS protocol versions. |
193 | /// |
194 | /// For more information, see the [`ConfigBuilder`] documentation. |
195 | #[derive (Clone, Debug)] |
196 | pub struct WantsVersions {} |
197 | |
198 | impl<S: ConfigSide> ConfigBuilder<S, WantsVersions> { |
199 | /// Accept the default protocol versions: both TLS1.2 and TLS1.3 are enabled. |
200 | pub fn with_safe_default_protocol_versions( |
201 | self, |
202 | ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> { |
203 | self.with_protocol_versions(versions::DEFAULT_VERSIONS) |
204 | } |
205 | |
206 | /// Use a specific set of protocol versions. |
207 | pub fn with_protocol_versions( |
208 | self, |
209 | versions: &[&'static versions::SupportedProtocolVersion], |
210 | ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> { |
211 | let mut any_usable_suite = false; |
212 | for suite in &self.provider.cipher_suites { |
213 | if versions.contains(&suite.version()) { |
214 | any_usable_suite = true; |
215 | break; |
216 | } |
217 | } |
218 | |
219 | if !any_usable_suite { |
220 | return Err(Error::General("no usable cipher suites configured" .into())); |
221 | } |
222 | |
223 | if self.provider.kx_groups.is_empty() { |
224 | return Err(Error::General("no kx groups configured" .into())); |
225 | } |
226 | |
227 | // verifying cipher suites have matching kx groups |
228 | let mut supported_kx_algos = Vec::with_capacity(ALL_KEY_EXCHANGE_ALGORITHMS.len()); |
229 | for group in self.provider.kx_groups.iter() { |
230 | let kx = group.name().key_exchange_algorithm(); |
231 | if !supported_kx_algos.contains(&kx) { |
232 | supported_kx_algos.push(kx); |
233 | } |
234 | // Small optimization. We don't need to go over other key exchange groups |
235 | // if we already cover all supported key exchange algorithms |
236 | if supported_kx_algos.len() == ALL_KEY_EXCHANGE_ALGORITHMS.len() { |
237 | break; |
238 | } |
239 | } |
240 | |
241 | for cs in self.provider.cipher_suites.iter() { |
242 | let cs_kx = cs.key_exchange_algorithms(); |
243 | if cs_kx |
244 | .iter() |
245 | .any(|kx| supported_kx_algos.contains(kx)) |
246 | { |
247 | continue; |
248 | } |
249 | let suite_name = cs.common().suite; |
250 | return Err(Error::General(alloc::format!( |
251 | "Ciphersuite {suite_name:?} requires {cs_kx:?} key exchange, but no {cs_kx:?}-compatible \ |
252 | key exchange groups were present in `CryptoProvider`'s `kx_groups` field" , |
253 | ))); |
254 | } |
255 | |
256 | Ok(ConfigBuilder { |
257 | state: WantsVerifier { |
258 | versions: versions::EnabledVersions::new(versions), |
259 | client_ech_mode: None, |
260 | }, |
261 | provider: self.provider, |
262 | time_provider: self.time_provider, |
263 | side: self.side, |
264 | }) |
265 | } |
266 | } |
267 | |
268 | /// Config builder state where the caller must supply a verifier. |
269 | /// |
270 | /// For more information, see the [`ConfigBuilder`] documentation. |
271 | #[derive (Clone, Debug)] |
272 | pub struct WantsVerifier { |
273 | pub(crate) versions: versions::EnabledVersions, |
274 | pub(crate) client_ech_mode: Option<EchMode>, |
275 | } |
276 | |
277 | /// Helper trait to abstract [`ConfigBuilder`] over building a [`ClientConfig`] or [`ServerConfig`]. |
278 | /// |
279 | /// [`ClientConfig`]: crate::ClientConfig |
280 | /// [`ServerConfig`]: crate::ServerConfig |
281 | pub trait ConfigSide: sealed::Sealed {} |
282 | |
283 | impl ConfigSide for crate::ClientConfig {} |
284 | impl ConfigSide for crate::ServerConfig {} |
285 | |
286 | mod sealed { |
287 | pub trait Sealed {} |
288 | impl Sealed for crate::ClientConfig {} |
289 | impl Sealed for crate::ServerConfig {} |
290 | } |
291 | |