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::error::Error;
11use crate::key_log::NoKeyLog;
12use crate::msgs::handshake::CertificateChain;
13use crate::versions::TLS13;
14use crate::webpki::{self, WebPkiServerVerifier};
15use crate::{compress, verify, versions, WantsVersions};
16
17impl ConfigBuilder<ClientConfig, WantsVersions> {
18 pub fn with_ech(
28 self,
29 mode: EchMode,
30 ) -> Result<ConfigBuilder<ClientConfig, WantsVerifier>, Error> {
31 let mut res = self.with_protocol_versions(&[&TLS13][..])?;
32 res.state.client_ech_mode = Some(mode);
33 Ok(res)
34 }
35}
36
37impl ConfigBuilder<ClientConfig, WantsVerifier> {
38 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 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 pub fn dangerous(self) -> danger::DangerousClientConfigBuilder {
86 danger::DangerousClientConfigBuilder { cfg: self }
87 }
88}
89
90pub(super) mod danger {
92 use alloc::sync::Arc;
93 use core::marker::PhantomData;
94
95 use crate::client::WantsClientCert;
96 use crate::{verify, ClientConfig, ConfigBuilder, WantsVerifier};
97
98 #[derive(Debug)]
100 pub struct DangerousClientConfigBuilder {
101 pub cfg: ConfigBuilder<ClientConfig, WantsVerifier>,
103 }
104
105 impl DangerousClientConfigBuilder {
106 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#[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 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 private_key = self
152 .provider
153 .key_provider
154 .load_private_key(key_der)?;
155 let resolver =
156 handy::AlwaysResolvesClientCert::new(private_key, CertificateChain(cert_chain))?;
157 Ok(self.with_client_cert_resolver(Arc::new(resolver)))
158 }
159
160 pub fn with_no_client_auth(self) -> ClientConfig {
162 self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
163 }
164
165 pub fn with_client_cert_resolver(
167 self,
168 client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
169 ) -> ClientConfig {
170 ClientConfig {
171 provider: self.provider,
172 alpn_protocols: Vec::new(),
173 resumption: Resumption::default(),
174 max_fragment_size: None,
175 client_auth_cert_resolver,
176 versions: self.state.versions,
177 enable_sni: true,
178 verifier: self.state.verifier,
179 key_log: Arc::new(NoKeyLog {}),
180 enable_secret_extraction: false,
181 enable_early_data: false,
182 #[cfg(feature = "tls12")]
183 require_ems: cfg!(feature = "fips"),
184 time_provider: self.time_provider,
185 cert_compressors: compress::default_cert_compressors().to_vec(),
186 cert_compression_cache: Arc::new(compress::CompressionCache::default()),
187 cert_decompressors: compress::default_cert_decompressors().to_vec(),
188 ech_mode: self.state.client_ech_mode,
189 }
190 }
191}