1use alloc::sync::Arc;
2use alloc::vec::Vec;
3use core::marker::PhantomData;
4
5use pki_types::{CertificateDer, PrivateKeyDer};
6
7use super::client_conn::Resumption;
8use crate::builder::{ConfigBuilder, WantsVerifier};
9use crate::client::{handy, ClientConfig, EchMode, ResolvesClientCert};
10use crate::crypto::CryptoProvider;
11use crate::error::Error;
12use crate::key_log::NoKeyLog;
13use crate::msgs::handshake::CertificateChain;
14use crate::time_provider::TimeProvider;
15use crate::versions::TLS13;
16use crate::webpki::{self, WebPkiServerVerifier};
17use crate::{compress, verify, versions, WantsVersions};
18
19impl ConfigBuilder<ClientConfig, WantsVersions> {
20 pub fn with_ech(
30 self,
31 mode: EchMode,
32 ) -> Result<ConfigBuilder<ClientConfig, WantsVerifier>, Error> {
33 let mut res = self.with_protocol_versions(&[&TLS13][..])?;
34 res.state.client_ech_mode = Some(mode);
35 Ok(res)
36 }
37}
38
39impl ConfigBuilder<ClientConfig, WantsVerifier> {
40 pub fn with_root_certificates(
54 self,
55 root_store: impl Into<Arc<webpki::RootCertStore>>,
56 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
57 let algorithms = self
58 .state
59 .provider
60 .signature_verification_algorithms;
61 self.with_webpki_verifier(
62 WebPkiServerVerifier::new_without_revocation(root_store, algorithms).into(),
63 )
64 }
65
66 pub fn with_webpki_verifier(
71 self,
72 verifier: Arc<WebPkiServerVerifier>,
73 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
74 ConfigBuilder {
75 state: WantsClientCert {
76 provider: self.state.provider,
77 versions: self.state.versions,
78 verifier,
79 time_provider: self.state.time_provider,
80 client_ech_mode: self.state.client_ech_mode,
81 },
82 side: PhantomData,
83 }
84 }
85
86 pub fn dangerous(self) -> danger::DangerousClientConfigBuilder {
89 danger::DangerousClientConfigBuilder { cfg: self }
90 }
91}
92
93pub(super) mod danger {
95 use alloc::sync::Arc;
96 use core::marker::PhantomData;
97
98 use crate::client::WantsClientCert;
99 use crate::{verify, ClientConfig, ConfigBuilder, WantsVerifier};
100
101 #[derive(Debug)]
103 pub struct DangerousClientConfigBuilder {
104 pub cfg: ConfigBuilder<ClientConfig, WantsVerifier>,
106 }
107
108 impl DangerousClientConfigBuilder {
109 pub fn with_custom_certificate_verifier(
111 self,
112 verifier: Arc<dyn verify::ServerCertVerifier>,
113 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
114 ConfigBuilder {
115 state: WantsClientCert {
116 provider: self.cfg.state.provider,
117 versions: self.cfg.state.versions,
118 verifier,
119 time_provider: self.cfg.state.time_provider,
120 client_ech_mode: self.cfg.state.client_ech_mode,
121 },
122 side: PhantomData,
123 }
124 }
125 }
126}
127
128#[derive(Clone)]
133pub struct WantsClientCert {
134 provider: Arc<CryptoProvider>,
135 versions: versions::EnabledVersions,
136 verifier: Arc<dyn verify::ServerCertVerifier>,
137 time_provider: Arc<dyn TimeProvider>,
138 client_ech_mode: Option<EchMode>,
139}
140
141impl ConfigBuilder<ClientConfig, WantsClientCert> {
142 pub fn with_client_auth_cert(
152 self,
153 cert_chain: Vec<CertificateDer<'static>>,
154 key_der: PrivateKeyDer<'static>,
155 ) -> Result<ClientConfig, Error> {
156 let private_key = self
157 .state
158 .provider
159 .key_provider
160 .load_private_key(key_der)?;
161 let resolver =
162 handy::AlwaysResolvesClientCert::new(private_key, CertificateChain(cert_chain))?;
163 Ok(self.with_client_cert_resolver(Arc::new(resolver)))
164 }
165
166 pub fn with_no_client_auth(self) -> ClientConfig {
168 self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
169 }
170
171 pub fn with_client_cert_resolver(
173 self,
174 client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
175 ) -> ClientConfig {
176 ClientConfig {
177 provider: self.state.provider,
178 alpn_protocols: Vec::new(),
179 resumption: Resumption::default(),
180 max_fragment_size: None,
181 client_auth_cert_resolver,
182 versions: self.state.versions,
183 enable_sni: true,
184 verifier: self.state.verifier,
185 key_log: Arc::new(NoKeyLog {}),
186 enable_secret_extraction: false,
187 enable_early_data: false,
188 #[cfg(feature = "tls12")]
189 require_ems: cfg!(feature = "fips"),
190 time_provider: self.state.time_provider,
191 cert_compressors: compress::default_cert_compressors().to_vec(),
192 cert_compression_cache: Arc::new(compress::CompressionCache::default()),
193 cert_decompressors: compress::default_cert_decompressors().to_vec(),
194 ech_mode: self.state.client_ech_mode,
195 }
196 }
197}