1use crate::builder::{ConfigBuilder, WantsVerifier};
2use crate::client::handy;
3use crate::client::{ClientConfig, ResolvesClientCert};
4use crate::crypto::CryptoProvider;
5use crate::error::Error;
6use crate::key_log::NoKeyLog;
7use crate::msgs::handshake::CertificateChain;
8use crate::webpki::{self, WebPkiServerVerifier};
9use crate::{verify, versions};
10
11use super::client_conn::Resumption;
12
13use pki_types::{CertificateDer, PrivateKeyDer};
14
15use alloc::sync::Arc;
16use alloc::vec::Vec;
17use core::marker::PhantomData;
18
19impl ConfigBuilder<ClientConfig, WantsVerifier> {
20 /// Choose how to verify server certificates.
21 ///
22 /// Using this function does not configure revocation. If you wish to
23 /// configure revocation, instead use:
24 ///
25 /// ```diff
26 /// - .with_root_certificates(root_store)
27 /// + .with_webpki_verifier(
28 /// + WebPkiServerVerifier::builder_with_provider(root_store, crypto_provider)
29 /// + .with_crls(...)
30 /// + .build()?
31 /// + )
32 /// ```
33 pub fn with_root_certificates(
34 self,
35 root_store: impl Into<Arc<webpki::RootCertStore>>,
36 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
37 let algorithms = self
38 .state
39 .provider
40 .signature_verification_algorithms;
41 self.with_webpki_verifier(
42 WebPkiServerVerifier::new_without_revocation(root_store, algorithms).into(),
43 )
44 }
45
46 /// Choose how to verify server certificates using a webpki verifier.
47 ///
48 /// See [`webpki::WebPkiServerVerifier::builder`] and
49 /// [`webpki::WebPkiServerVerifier::builder_with_provider`] for more information.
50 pub fn with_webpki_verifier(
51 self,
52 verifier: Arc<WebPkiServerVerifier>,
53 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
54 ConfigBuilder {
55 state: WantsClientCert {
56 provider: self.state.provider,
57 versions: self.state.versions,
58 verifier,
59 },
60 side: PhantomData,
61 }
62 }
63
64 /// Access configuration options whose use is dangerous and requires
65 /// extra care.
66 pub fn dangerous(self) -> danger::DangerousClientConfigBuilder {
67 danger::DangerousClientConfigBuilder { cfg: self }
68 }
69}
70
71/// Container for unsafe APIs
72pub(super) mod danger {
73 use alloc::sync::Arc;
74 use core::marker::PhantomData;
75
76 use crate::client::WantsClientCert;
77 use crate::{verify, ClientConfig, ConfigBuilder, WantsVerifier};
78
79 /// Accessor for dangerous configuration options.
80 #[derive(Debug)]
81 pub struct DangerousClientConfigBuilder {
82 /// The underlying ClientConfigBuilder
83 pub cfg: ConfigBuilder<ClientConfig, WantsVerifier>,
84 }
85
86 impl DangerousClientConfigBuilder {
87 /// Set a custom certificate verifier.
88 pub fn with_custom_certificate_verifier(
89 self,
90 verifier: Arc<dyn verify::ServerCertVerifier>,
91 ) -> ConfigBuilder<ClientConfig, WantsClientCert> {
92 ConfigBuilder {
93 state: WantsClientCert {
94 provider: self.cfg.state.provider,
95 versions: self.cfg.state.versions,
96 verifier,
97 },
98 side: PhantomData,
99 }
100 }
101 }
102}
103
104/// A config builder state where the caller needs to supply whether and how to provide a client
105/// certificate.
106///
107/// For more information, see the [`ConfigBuilder`] documentation.
108#[derive(Clone)]
109pub struct WantsClientCert {
110 provider: Arc<CryptoProvider>,
111 versions: versions::EnabledVersions,
112 verifier: Arc<dyn verify::ServerCertVerifier>,
113}
114
115impl ConfigBuilder<ClientConfig, WantsClientCert> {
116 /// Sets a single certificate chain and matching private key for use
117 /// in client authentication.
118 ///
119 /// `cert_chain` is a vector of DER-encoded certificates.
120 /// `key_der` is a DER-encoded private key as PKCS#1, PKCS#8, or SEC1. The
121 /// `aws-lc-rs` and `ring` [`CryptoProvider`]s support all three encodings,
122 /// but other `CryptoProviders` may not.
123 ///
124 /// This function fails if `key_der` is invalid.
125 pub fn with_client_auth_cert(
126 self,
127 cert_chain: Vec<CertificateDer<'static>>,
128 key_der: PrivateKeyDer<'static>,
129 ) -> Result<ClientConfig, Error> {
130 let private_key = self
131 .state
132 .provider
133 .key_provider
134 .load_private_key(key_der)?;
135 let resolver =
136 handy::AlwaysResolvesClientCert::new(private_key, CertificateChain(cert_chain))?;
137 Ok(self.with_client_cert_resolver(Arc::new(resolver)))
138 }
139
140 /// Do not support client auth.
141 pub fn with_no_client_auth(self) -> ClientConfig {
142 self.with_client_cert_resolver(Arc::new(handy::FailResolveClientCert {}))
143 }
144
145 /// Sets a custom [`ResolvesClientCert`].
146 pub fn with_client_cert_resolver(
147 self,
148 client_auth_cert_resolver: Arc<dyn ResolvesClientCert>,
149 ) -> ClientConfig {
150 ClientConfig {
151 provider: self.state.provider,
152 alpn_protocols: Vec::new(),
153 resumption: Resumption::default(),
154 max_fragment_size: None,
155 client_auth_cert_resolver,
156 versions: self.state.versions,
157 enable_sni: true,
158 verifier: self.state.verifier,
159 key_log: Arc::new(NoKeyLog {}),
160 enable_secret_extraction: false,
161 enable_early_data: false,
162 }
163 }
164}
165