1use arc_swap::ArcSwap;
5use fastcrypto::ed25519::Ed25519PublicKey;
6use fastcrypto::traits::ToFromBytes;
7use rustls::crypto::WebPkiSupportedAlgorithms;
8use rustls::pki_types::CertificateDer;
9use rustls::pki_types::PrivateKeyDer;
10use rustls::pki_types::ServerName;
11use rustls::pki_types::SignatureVerificationAlgorithm;
12use rustls::pki_types::TrustAnchor;
13use rustls::pki_types::UnixTime;
14use std::collections::BTreeSet;
15use std::sync::Arc;
16
17static SUPPORTED_SIG_ALGS: &[&dyn SignatureVerificationAlgorithm] = &[webpki::ring::ED25519];
18
19static SUPPORTED_ALGORITHMS: WebPkiSupportedAlgorithms = WebPkiSupportedAlgorithms {
20 all: SUPPORTED_SIG_ALGS,
21 mapping: &[(rustls::SignatureScheme::ED25519, SUPPORTED_SIG_ALGS)],
22};
23
24pub trait Allower: std::fmt::Debug + Send + Sync {
29 fn allowed(&self, key: &Ed25519PublicKey) -> bool;
31}
32
33#[derive(Debug, Clone, Default)]
35pub struct AllowAll;
36
37impl Allower for AllowAll {
38 fn allowed(&self, _: &Ed25519PublicKey) -> bool {
39 true
40 }
41}
42
43#[derive(Debug, Clone, Default)]
46pub struct AllowPublicKeys {
47 inner: Arc<ArcSwap<BTreeSet<Ed25519PublicKey>>>,
48}
49
50impl AllowPublicKeys {
51 pub fn new(allowed: BTreeSet<Ed25519PublicKey>) -> Self {
52 Self {
53 inner: Arc::new(ArcSwap::from_pointee(allowed)),
54 }
55 }
56
57 pub fn update(&self, new_allowed: BTreeSet<Ed25519PublicKey>) {
58 self.inner.store(Arc::new(new_allowed));
59 }
60}
61
62impl Allower for AllowPublicKeys {
63 fn allowed(&self, key: &Ed25519PublicKey) -> bool {
64 self.inner.load().contains(key)
65 }
66}
67
68#[derive(Clone, Debug)]
71pub struct ClientCertVerifier<A> {
72 allower: A,
73 name: String,
74}
75
76impl<A> ClientCertVerifier<A> {
77 pub fn new(allower: A, name: String) -> Self {
78 Self { allower, name }
79 }
80}
81
82impl<A: Allower + 'static> ClientCertVerifier<A> {
83 pub fn rustls_server_config(
84 self,
85 certificates: Vec<CertificateDer<'static>>,
86 private_key: PrivateKeyDer<'static>,
87 ) -> Result<rustls::ServerConfig, rustls::Error> {
88 let mut config = rustls::ServerConfig::builder_with_provider(Arc::new(
89 rustls::crypto::ring::default_provider(),
90 ))
91 .with_protocol_versions(&[&rustls::version::TLS13])?
92 .with_client_cert_verifier(std::sync::Arc::new(self))
93 .with_single_cert(certificates, private_key)?;
94 config.alpn_protocols = vec![b"h2".to_vec(), b"http/1.1".to_vec()];
95
96 Ok(config)
97 }
98}
99
100impl<A: Allower> rustls::server::danger::ClientCertVerifier for ClientCertVerifier<A> {
101 fn offer_client_auth(&self) -> bool {
102 true
103 }
104
105 fn client_auth_mandatory(&self) -> bool {
106 true
107 }
108
109 fn root_hint_subjects(&self) -> &[rustls::DistinguishedName] {
110 &[]
113 }
114
115 fn verify_client_cert(
120 &self,
121 end_entity: &CertificateDer,
122 intermediates: &[CertificateDer],
123 now: UnixTime,
124 ) -> Result<rustls::server::danger::ClientCertVerified, rustls::Error> {
125 let public_key = public_key_from_certificate(end_entity)?;
127 if !self.allower.allowed(&public_key) {
128 return Err(rustls::Error::General(format!(
129 "invalid certificate: {:?} is not in the validator set",
130 public_key,
131 )));
132 }
133
134 verify_self_signed_cert(
136 end_entity,
137 intermediates,
138 webpki::KeyUsage::client_auth(),
139 &self.name,
140 now,
141 )
142 .map(|_| rustls::server::danger::ClientCertVerified::assertion())
143 }
144
145 fn verify_tls12_signature(
146 &self,
147 message: &[u8],
148 cert: &CertificateDer<'_>,
149 dss: &rustls::DigitallySignedStruct,
150 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
151 rustls::crypto::verify_tls12_signature(message, cert, dss, &SUPPORTED_ALGORITHMS)
152 }
153
154 fn verify_tls13_signature(
155 &self,
156 message: &[u8],
157 cert: &CertificateDer<'_>,
158 dss: &rustls::DigitallySignedStruct,
159 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
160 rustls::crypto::verify_tls13_signature(message, cert, dss, &SUPPORTED_ALGORITHMS)
161 }
162
163 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
164 SUPPORTED_ALGORITHMS.supported_schemes()
165 }
166}
167
168#[derive(Clone, Debug)]
171pub struct ServerCertVerifier {
172 public_key: Ed25519PublicKey,
173 name: String,
174}
175
176impl ServerCertVerifier {
177 pub fn new(public_key: Ed25519PublicKey, name: String) -> Self {
178 Self { public_key, name }
179 }
180
181 pub fn rustls_client_config_with_client_auth(
182 self,
183 certificates: Vec<CertificateDer<'static>>,
184 private_key: PrivateKeyDer<'static>,
185 ) -> Result<rustls::ClientConfig, rustls::Error> {
186 rustls::ClientConfig::builder_with_provider(Arc::new(
187 rustls::crypto::ring::default_provider(),
188 ))
189 .with_protocol_versions(&[&rustls::version::TLS13])?
190 .dangerous()
191 .with_custom_certificate_verifier(std::sync::Arc::new(self))
192 .with_client_auth_cert(certificates, private_key)
193 }
194
195 pub fn rustls_client_config_with_no_client_auth(
196 self,
197 ) -> Result<rustls::ClientConfig, rustls::Error> {
198 Ok(rustls::ClientConfig::builder_with_provider(Arc::new(
199 rustls::crypto::ring::default_provider(),
200 ))
201 .with_protocol_versions(&[&rustls::version::TLS13])?
202 .dangerous()
203 .with_custom_certificate_verifier(std::sync::Arc::new(self))
204 .with_no_client_auth())
205 }
206}
207
208impl rustls::client::danger::ServerCertVerifier for ServerCertVerifier {
209 fn verify_server_cert(
210 &self,
211 end_entity: &CertificateDer<'_>,
212 intermediates: &[CertificateDer<'_>],
213 _server_name: &ServerName,
214 _ocsp_response: &[u8],
215 now: UnixTime,
216 ) -> Result<rustls::client::danger::ServerCertVerified, rustls::Error> {
217 let public_key = public_key_from_certificate(end_entity)?;
218 if public_key != self.public_key {
219 return Err(rustls::Error::General(format!(
220 "invalid certificate: {:?} is not the expected server public key",
221 public_key,
222 )));
223 }
224
225 verify_self_signed_cert(
226 end_entity,
227 intermediates,
228 webpki::KeyUsage::server_auth(),
229 &self.name,
230 now,
231 )
232 .map(|_| rustls::client::danger::ServerCertVerified::assertion())
233 }
234
235 fn verify_tls12_signature(
236 &self,
237 message: &[u8],
238 cert: &CertificateDer<'_>,
239 dss: &rustls::DigitallySignedStruct,
240 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
241 rustls::crypto::verify_tls12_signature(message, cert, dss, &SUPPORTED_ALGORITHMS)
242 }
243
244 fn verify_tls13_signature(
245 &self,
246 message: &[u8],
247 cert: &CertificateDer<'_>,
248 dss: &rustls::DigitallySignedStruct,
249 ) -> Result<rustls::client::danger::HandshakeSignatureValid, rustls::Error> {
250 rustls::crypto::verify_tls13_signature(message, cert, dss, &SUPPORTED_ALGORITHMS)
251 }
252
253 fn supported_verify_schemes(&self) -> Vec<rustls::SignatureScheme> {
254 SUPPORTED_ALGORITHMS.supported_schemes()
255 }
256}
257
258fn verify_self_signed_cert(
263 end_entity: &CertificateDer,
264 intermediates: &[CertificateDer],
265 usage: webpki::KeyUsage,
266 name: &str,
267 now: UnixTime,
268) -> Result<(), rustls::Error> {
269 let (cert, chain, trustroots) = prepare_for_self_signed(end_entity, intermediates)?;
272
273 let verified_cert = cert
275 .verify_for_usage(
276 SUPPORTED_SIG_ALGS,
277 &trustroots,
278 chain,
279 now,
280 usage,
281 None,
282 None,
283 )
284 .map_err(pki_error)?;
285
286 let subject_name =
288 ServerName::try_from(name).map_err(|_| rustls::Error::UnsupportedNameType)?;
289 verified_cert
290 .end_entity()
291 .verify_is_valid_for_subject_name(&subject_name)
292 .map_err(pki_error)
293}
294
295type CertChainAndRoots<'a> = (
296 webpki::EndEntityCert<'a>,
297 &'a [CertificateDer<'a>],
298 Vec<TrustAnchor<'a>>,
299);
300
301fn prepare_for_self_signed<'a>(
304 end_entity: &'a CertificateDer,
305 intermediates: &'a [CertificateDer],
306) -> Result<CertChainAndRoots<'a>, rustls::Error> {
307 let cert = webpki::EndEntityCert::try_from(end_entity).map_err(pki_error)?;
309
310 let root = webpki::anchor_from_trusted_cert(end_entity).map_err(pki_error)?;
312
313 Ok((cert, intermediates, vec![root]))
314}
315
316fn pki_error(error: webpki::Error) -> rustls::Error {
317 use webpki::Error::*;
318 match error {
319 BadDer | BadDerTime => {
320 rustls::Error::InvalidCertificate(rustls::CertificateError::BadEncoding)
321 }
322 InvalidSignatureForPublicKey
323 | UnsupportedSignatureAlgorithm
324 | UnsupportedSignatureAlgorithmForPublicKey => {
325 rustls::Error::InvalidCertificate(rustls::CertificateError::BadSignature)
326 }
327 CertNotValidForName(_) => {
328 rustls::Error::InvalidCertificate(rustls::CertificateError::NotValidForName)
329 }
330 e => rustls::Error::General(format!("invalid peer certificate: {e}")),
331 }
332}
333
334pub fn public_key_from_certificate(
336 certificate: &CertificateDer,
337) -> Result<Ed25519PublicKey, rustls::Error> {
338 use x509_parser::{certificate::X509Certificate, prelude::FromDer};
339
340 let cert = X509Certificate::from_der(certificate.as_ref())
341 .map_err(|e| rustls::Error::General(e.to_string()))?;
342 let spki = cert.1.public_key();
343 let public_key_bytes =
344 <ed25519::pkcs8::PublicKeyBytes as pkcs8::DecodePublicKey>::from_public_key_der(spki.raw)
345 .map_err(|e| rustls::Error::General(format!("invalid ed25519 public key: {e}")))?;
346
347 let public_key = Ed25519PublicKey::from_bytes(public_key_bytes.as_ref())
348 .map_err(|e| rustls::Error::General(format!("invalid ed25519 public key: {e}")))?;
349 Ok(public_key)
350}