1 | use crate::builder::{ConfigBuilder, WantsVerifier}; |
2 | use crate::client::handy; |
3 | use crate::client::{ClientConfig, ResolvesClientCert}; |
4 | use crate::crypto::CryptoProvider; |
5 | use crate::error::Error; |
6 | use crate::key_log::NoKeyLog; |
7 | use crate::msgs::handshake::CertificateChain; |
8 | use crate::webpki::{self, WebPkiServerVerifier}; |
9 | use crate::{verify, versions}; |
10 | |
11 | use super::client_conn::Resumption; |
12 | |
13 | use pki_types::{CertificateDer, PrivateKeyDer}; |
14 | |
15 | use alloc::sync::Arc; |
16 | use alloc::vec::Vec; |
17 | use core::marker::PhantomData; |
18 | |
19 | impl 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 |
72 | pub(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)] |
109 | pub struct WantsClientCert { |
110 | provider: Arc<CryptoProvider>, |
111 | versions: versions::EnabledVersions, |
112 | verifier: Arc<dyn verify::ServerCertVerifier>, |
113 | } |
114 | |
115 | impl 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 | |