/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.37/src/builder.rs
Line | Count | Source |
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 | 0 | pub fn crypto_provider(&self) -> &Arc<CryptoProvider> { |
174 | 0 | &self.provider |
175 | 0 | } |
176 | | } |
177 | | |
178 | | impl<Side: ConfigSide, State: fmt::Debug> fmt::Debug for ConfigBuilder<Side, State> { |
179 | 0 | fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { |
180 | 0 | let side_name = core::any::type_name::<Side>(); |
181 | 0 | let (ty, _) = side_name |
182 | 0 | .split_once('<') |
183 | 0 | .unwrap_or((side_name, "")); |
184 | 0 | let (_, name) = ty.rsplit_once("::").unwrap_or(("", ty)); |
185 | | |
186 | 0 | f.debug_struct(&format!("ConfigBuilder<{name}, _>",)) |
187 | 0 | .field("state", &self.state) |
188 | 0 | .finish() |
189 | 0 | } |
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 | 0 | pub fn with_safe_default_protocol_versions( |
201 | 0 | self, |
202 | 0 | ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> { |
203 | 0 | self.with_protocol_versions(versions::DEFAULT_VERSIONS) |
204 | 0 | } |
205 | | |
206 | | /// Use a specific set of protocol versions. |
207 | 0 | pub fn with_protocol_versions( |
208 | 0 | self, |
209 | 0 | versions: &[&'static versions::SupportedProtocolVersion], |
210 | 0 | ) -> Result<ConfigBuilder<S, WantsVerifier>, Error> { |
211 | 0 | let mut any_usable_suite = false; |
212 | 0 | for suite in &self.provider.cipher_suites { |
213 | 0 | if versions.contains(&suite.version()) { |
214 | 0 | any_usable_suite = true; |
215 | 0 | break; |
216 | 0 | } |
217 | | } |
218 | | |
219 | 0 | if !any_usable_suite { |
220 | 0 | return Err(Error::General("no usable cipher suites configured".into())); |
221 | 0 | } |
222 | | |
223 | 0 | if self.provider.kx_groups.is_empty() { |
224 | 0 | return Err(Error::General("no kx groups configured".into())); |
225 | 0 | } |
226 | | |
227 | | // verifying cipher suites have matching kx groups |
228 | 0 | let mut supported_kx_algos = Vec::with_capacity(ALL_KEY_EXCHANGE_ALGORITHMS.len()); |
229 | 0 | for group in self.provider.kx_groups.iter() { |
230 | 0 | let kx = group.name().key_exchange_algorithm(); |
231 | 0 | if !supported_kx_algos.contains(&kx) { |
232 | 0 | supported_kx_algos.push(kx); |
233 | 0 | } |
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 | 0 | if supported_kx_algos.len() == ALL_KEY_EXCHANGE_ALGORITHMS.len() { |
237 | 0 | break; |
238 | 0 | } |
239 | | } |
240 | | |
241 | 0 | for cs in self.provider.cipher_suites.iter() { |
242 | 0 | let cs_kx = cs.key_exchange_algorithms(); |
243 | 0 | if cs_kx |
244 | 0 | .iter() |
245 | 0 | .any(|kx| supported_kx_algos.contains(kx)) Unexecuted instantiation: <rustls::builder::ConfigBuilder<rustls::client::client_conn::ClientConfig, rustls::builder::WantsVersions>>::with_protocol_versions::{closure#0}Unexecuted instantiation: <rustls::builder::ConfigBuilder<rustls::server::server_conn::ServerConfig, rustls::builder::WantsVersions>>::with_protocol_versions::{closure#0} |
246 | | { |
247 | 0 | continue; |
248 | 0 | } |
249 | 0 | let suite_name = cs.common().suite; |
250 | 0 | return Err(Error::General(alloc::format!( |
251 | 0 | "Ciphersuite {suite_name:?} requires {cs_kx:?} key exchange, but no {cs_kx:?}-compatible \ |
252 | 0 | key exchange groups were present in `CryptoProvider`'s `kx_groups` field", |
253 | 0 | ))); |
254 | | } |
255 | | |
256 | 0 | Ok(ConfigBuilder { |
257 | 0 | state: WantsVerifier { |
258 | 0 | versions: versions::EnabledVersions::new(versions), |
259 | 0 | client_ech_mode: None, |
260 | 0 | }, |
261 | 0 | provider: self.provider, |
262 | 0 | time_provider: self.time_provider, |
263 | 0 | side: self.side, |
264 | 0 | }) |
265 | 0 | } Unexecuted instantiation: <rustls::builder::ConfigBuilder<rustls::client::client_conn::ClientConfig, rustls::builder::WantsVersions>>::with_protocol_versions Unexecuted instantiation: <rustls::builder::ConfigBuilder<rustls::server::server_conn::ServerConfig, rustls::builder::WantsVersions>>::with_protocol_versions |
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 | | } |