1use alloc::vec::Vec;
2use core::marker::PhantomData;
3
4use pki_types::{CertificateDer, PrivateKeyDer};
5
6use super::client_conn::Resumption;
7use crate::builder::{ConfigBuilder, WantsVerifier};
8use crate::client::{ClientConfig, EchMode, ResolvesClientCert, handy};
9use crate::error::Error;
10use crate::key_log::NoKeyLog;
11use crate::sign::{CertifiedKey, SingleCertAndKey};
12use crate::sync::Arc;
13use crate::versions::TLS13;
14use crate::webpki::{self, WebPkiServerVerifier};
15use crate::{WantsVersions, compress, verify, versions};
16
17impl ConfigBuilder<ClientConfig, WantsVersions> {
18 /// Enable Encrypted Client Hello (ECH) in the given mode.
19 ///
20 /// This implicitly selects TLS 1.3 as the only supported protocol version to meet the
21 /// requirement to support ECH.
22 ///
23 /// The `ClientConfig` that will be produced by this builder will be specific to the provided
24 /// [`crate::client::EchConfig`] and may not be appropriate for all connections made by the program.
25 /// In this case the configuration should only be shared by connections intended for domains
26 /// that offer the provided [`crate::client::EchConfig`] in their DNS zone.
27 pub fn with_ech(
28 self,
29 mode: EchMode,
30 ) -> Result<ConfigBuilder<ClientConfig, WantsVerifier>, Error> {
31 let mut res: ConfigBuilder = self.with_protocol_versions(&[&TLS13][..])?;
32 res.state.client_ech_mode = Some(mode);
33 Ok(res)
34 }
35}
36
37impl ConfigBuilder<ClientConfig, WantsVerifier> {
38 /// Choose how to verify server certificates.
39 ///
40 /// Using this function does not configure revocation. If you wish to
41 /// configure revocation, instead use:
42 ///
43 /// ```diff
44 /// - .with_root_certificates(root_store)
45 /// + .with_webpki_verifier(
46 /// + WebPkiServerVerifier::builder_with_provider(root_store, crypto_provider)
47 /// + .with_crls(...)
48 /// + .build()?
49 /// + )
50 /// ```
51 pub fn with_root_certificates(
52 self,
53 root_store: impl Into<Arc<webpki::RootCertStore>>,
54 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
55 let algorithms = self
56 .provider
57 .signature_verification_algorithms;
58 self.with_webpki_verifier(
59 WebPkiServerVerifier::new_without_revocation(root_store, algorithms).into(),
60 )
61 }
62
63 /// Choose how to verify server certificates using a webpki verifier.
64 ///
65 /// See [`webpki::WebPkiServerVerifier::builder`] and
66 /// [`webpki::WebPkiServerVerifier::builder_with_provider`] for more information.
67 pub fn with_webpki_verifier(
68 self,
69 verifier: Arc<WebPkiServerVerifier>,
70 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
71 ConfigBuilder {
72 state: WantsClientCert {
73 versions: self.state.versions,
74 verifier,
75 client_ech_mode: self.state.client_ech_mode,
76 },
77 provider: self.provider,
78 time_provider: self.time_provider,
79 side: PhantomData,
80 }
81 }
82
83 /// Access configuration options whose use is dangerous and requires
84 /// extra care.
85 pub fn dangerous(self) -> danger::DangerousClientConfigBuilder {
86 danger::DangerousClientConfigBuilder { cfg: self }
87 }
88}
89
90/// Container for unsafe APIs
91pub(super) mod danger {
92 use core::marker::PhantomData;
93
94 use crate::client::WantsClientCert;
95 use crate::sync::Arc;
96 use crate::{ClientConfig, ConfigBuilder, WantsVerifier, verify};
97
98 /// Accessor for dangerous configuration options.
99 #[derive(Debug)]
100 pub struct DangerousClientConfigBuilder {
101 /// The underlying ClientConfigBuilder
102 pub cfg: ConfigBuilder<ClientConfig, WantsVerifier>,
103 }
104
105 impl DangerousClientConfigBuilder {
106 /// Set a custom certificate verifier.
107 pub fn with_custom_certificate_verifier(
108 self,
109 verifier: Arc<dyn verify::ServerCertVerifier>,
110 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
111 ConfigBuilder {
112 state: WantsClientCert {
113 versions: self.cfg.state.versions,
114 verifier,
115 client_ech_mode: self.cfg.state.client_ech_mode,
116 },
117 provider: self.cfg.provider,
118 time_provider: self.cfg.time_provider,
119 side: PhantomData,
120 }
121 }
122 }
123}
124
125/// A config builder state where the caller needs to supply whether and how to provide a client
126/// certificate.
127///
128/// For more information, see the [`ConfigBuilder`] documentation.
129#[derive(Clone)]
130pub struct WantsClientCert {
131 versions: versions::EnabledVersions,
132 verifier: Arc<dyn verify::ServerCertVerifier>,
133 client_ech_mode: Option<EchMode>,
134}
135
136impl ConfigBuilder<ClientConfig, WantsClientCert> {
137 /// Sets a single certificate chain and matching private key for use
138 /// in client authentication.
139 ///
140 /// `cert_chain` is a vector of DER-encoded certificates.
141 /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
142 /// `aws-lc-rs` and `ring` [`CryptoProvider`][crate::CryptoProvider]s support
143 /// all three encodings, but other `CryptoProviders` may not.
144 ///
145 /// This function fails if `key_der` is invalid.
146 pub fn with_client_auth_cert(
147 self,
148 cert_chain: Vec<CertificateDer<'static>>,
149 key_der: PrivateKeyDer<'static>,
150 ) -> Result<ClientConfig, Error> {
151 let certified_key = CertifiedKey::from_der(cert_chain, key_der, &self.provider)?;
152 Ok(self.with_client_cert_resolver(Arc::new(SingleCertAndKey::from(certified_key))))
153 }
154
155 /// Do not support client auth.
156 pub fn with_no_client_auth(self) -> ClientConfig {
157 self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
158 }
159
160 /// Sets a custom [`ResolvesClientCert`].
161 pub fn with_client_cert_resolver(
162 self,
163 client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
164 ) -> ClientConfig {
165 ClientConfig {
166 provider: self.provider,
167 alpn_protocols: Vec::new(),
168 resumption: Resumption::default(),
169 max_fragment_size: None,
170 client_auth_cert_resolver,
171 versions: self.state.versions,
172 enable_sni: true,
173 verifier: self.state.verifier,
174 key_log: Arc::new(NoKeyLog {}),
175 enable_secret_extraction: false,
176 enable_early_data: false,
177 #[cfg(feature = "tls12")]
178 require_ems: cfg!(feature = "fips"),
179 time_provider: self.time_provider,
180 cert_compressors: compress::default_cert_compressors().to_vec(),
181 cert_compression_cache: Arc::new(compress::CompressionCache::default()),
182 cert_decompressors: compress::default_cert_decompressors().to_vec(),
183 ech_mode: self.state.client_ech_mode,
184 }
185 }
186}
187