1use alloc::sync::Arc;
2use alloc::vec::Vec;
3
4use pki_types::{CertificateDer, CertificateRevocationListDer, ServerName, UnixTime};
5use webpki::{CertRevocationList, ExpirationPolicy, RevocationCheckDepth, UnknownStatusPolicy};
6
7use crate::crypto::{CryptoProvider, WebPkiSupportedAlgorithms};
8use crate::log::trace;
9use crate::verify::{
10 DigitallySignedStruct, HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier,
11};
12use crate::webpki::verify::{
13 verify_server_cert_signed_by_trust_anchor_impl, verify_tls12_signature, verify_tls13_signature,
14 ParsedCertificate,
15};
16use crate::webpki::{parse_crls, verify_server_name, VerifierBuilderError};
17#[cfg(doc)]
18use crate::{crypto, ConfigBuilder, ServerConfig};
19use crate::{Error, RootCertStore, SignatureScheme};
20
21#[derive(Debug, Clone)]
25pub struct ServerCertVerifierBuilder {
26 roots: Arc<RootCertStore>,
27 crls: Vec<CertificateRevocationListDer<'static>>,
28 revocation_check_depth: RevocationCheckDepth,
29 unknown_revocation_policy: UnknownStatusPolicy,
30 revocation_expiration_policy: ExpirationPolicy,
31 supported_algs: WebPkiSupportedAlgorithms,
32}
33
34impl ServerCertVerifierBuilder {
35 pub(crate) fn new(
36 roots: Arc<RootCertStore>,
37 supported_algs: WebPkiSupportedAlgorithms,
38 ) -> Self {
39 Self {
40 roots,
41 crls: Vec::new(),
42 revocation_check_depth: RevocationCheckDepth::Chain,
43 unknown_revocation_policy: UnknownStatusPolicy::Deny,
44 revocation_expiration_policy: ExpirationPolicy::Ignore,
45 supported_algs,
46 }
47 }
48
49 pub fn with_crls(
53 mut self,
54 crls: impl IntoIterator<Item = CertificateRevocationListDer<'static>>,
55 ) -> Self {
56 self.crls.extend(crls);
57 self
58 }
59
60 pub fn only_check_end_entity_revocation(mut self) -> Self {
70 self.revocation_check_depth = RevocationCheckDepth::EndEntity;
71 self
72 }
73
74 pub fn allow_unknown_revocation_status(mut self) -> Self {
83 self.unknown_revocation_policy = UnknownStatusPolicy::Allow;
84 self
85 }
86
87 pub fn enforce_revocation_expiration(mut self) -> Self {
96 self.revocation_expiration_policy = ExpirationPolicy::Enforce;
97 self
98 }
99
100 pub fn build(self) -> Result<Arc<WebPkiServerVerifier>, VerifierBuilderError> {
115 if self.roots.is_empty() {
116 return Err(VerifierBuilderError::NoRootAnchors);
117 }
118
119 Ok(WebPkiServerVerifier::new(
120 self.roots,
121 parse_crls(self.crls)?,
122 self.revocation_check_depth,
123 self.unknown_revocation_policy,
124 self.revocation_expiration_policy,
125 self.supported_algs,
126 )
127 .into())
128 }
129}
130
131#[allow(unreachable_pub)]
133#[derive(Debug)]
134pub struct WebPkiServerVerifier {
135 roots: Arc<RootCertStore>,
136 crls: Vec<CertRevocationList<'static>>,
137 revocation_check_depth: RevocationCheckDepth,
138 unknown_revocation_policy: UnknownStatusPolicy,
139 revocation_expiration_policy: ExpirationPolicy,
140 supported: WebPkiSupportedAlgorithms,
141}
142
143#[allow(unreachable_pub)]
144impl WebPkiServerVerifier {
145 pub fn builder(roots: Arc<RootCertStore>) -> ServerCertVerifierBuilder {
154 Self::builder_with_provider(
155 roots,
156 Arc::clone(CryptoProvider::get_default_or_install_from_crate_features()),
157 )
158 }
159
160 pub fn builder_with_provider(
169 roots: Arc<RootCertStore>,
170 provider: Arc<CryptoProvider>,
171 ) -> ServerCertVerifierBuilder {
172 ServerCertVerifierBuilder::new(roots, provider.signature_verification_algorithms)
173 }
174
175 pub(crate) fn new_without_revocation(
178 roots: impl Into<Arc<RootCertStore>>,
179 supported_algs: WebPkiSupportedAlgorithms,
180 ) -> Self {
181 Self::new(
182 roots,
183 Vec::default(),
184 RevocationCheckDepth::Chain,
185 UnknownStatusPolicy::Allow,
186 ExpirationPolicy::Ignore,
187 supported_algs,
188 )
189 }
190
191 pub(crate) fn new(
203 roots: impl Into<Arc<RootCertStore>>,
204 crls: Vec<CertRevocationList<'static>>,
205 revocation_check_depth: RevocationCheckDepth,
206 unknown_revocation_policy: UnknownStatusPolicy,
207 revocation_expiration_policy: ExpirationPolicy,
208 supported: WebPkiSupportedAlgorithms,
209 ) -> Self {
210 Self {
211 roots: roots.into(),
212 crls,
213 revocation_check_depth,
214 unknown_revocation_policy,
215 revocation_expiration_policy,
216 supported,
217 }
218 }
219}
220
221impl ServerCertVerifier for WebPkiServerVerifier {
222 fn verify_server_cert(
233 &self,
234 end_entity: &CertificateDer<'_>,
235 intermediates: &[CertificateDer<'_>],
236 server_name: &ServerName<'_>,
237 ocsp_response: &[u8],
238 now: UnixTime,
239 ) -> Result<ServerCertVerified, Error> {
240 let cert = ParsedCertificate::try_from(end_entity)?;
241
242 let crl_refs = self.crls.iter().collect::<Vec<_>>();
243
244 let revocation = if self.crls.is_empty() {
245 None
246 } else {
247 Some(
250 webpki::RevocationOptionsBuilder::new(crl_refs.as_slice())
251 .unwrap()
254 .with_depth(self.revocation_check_depth)
255 .with_status_policy(self.unknown_revocation_policy)
256 .with_expiration_policy(self.revocation_expiration_policy)
257 .build(),
258 )
259 };
260
261 verify_server_cert_signed_by_trust_anchor_impl(
264 &cert,
265 &self.roots,
266 intermediates,
267 revocation,
268 now,
269 self.supported.all,
270 )?;
271
272 if !ocsp_response.is_empty() {
273 trace!("Unvalidated OCSP response: {:?}", ocsp_response.to_vec());
274 }
275
276 verify_server_name(&cert, server_name)?;
277 Ok(ServerCertVerified::assertion())
278 }
279
280 fn verify_tls12_signature(
281 &self,
282 message: &[u8],
283 cert: &CertificateDer<'_>,
284 dss: &DigitallySignedStruct,
285 ) -> Result<HandshakeSignatureValid, Error> {
286 verify_tls12_signature(message, cert, dss, &self.supported)
287 }
288
289 fn verify_tls13_signature(
290 &self,
291 message: &[u8],
292 cert: &CertificateDer<'_>,
293 dss: &DigitallySignedStruct,
294 ) -> Result<HandshakeSignatureValid, Error> {
295 verify_tls13_signature(message, cert, dss, &self.supported)
296 }
297
298 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
299 self.supported.supported_schemes()
300 }
301}
302
303test_for_each_provider! {
304 use std::sync::Arc;
305 use std::{vec, println};
306 use std::prelude::v1::*;
307
308 use pki_types::{CertificateDer, CertificateRevocationListDer};
309
310 use super::{VerifierBuilderError, WebPkiServerVerifier};
311 use crate::RootCertStore;
312
313 fn load_crls(crls_der: &[&[u8]]) -> Vec<CertificateRevocationListDer<'static>> {
314 crls_der
315 .iter()
316 .map(|pem_bytes| {
317 rustls_pemfile::crls(&mut &pem_bytes[..])
318 .next()
319 .unwrap()
320 .unwrap()
321 })
322 .collect()
323 }
324
325 fn test_crls() -> Vec<CertificateRevocationListDer<'static>> {
326 load_crls(&[
327 include_bytes!("../../../test-ca/ecdsa-p256/client.revoked.crl.pem").as_slice(),
328 include_bytes!("../../../test-ca/rsa-2048/client.revoked.crl.pem").as_slice(),
329 ])
330 }
331
332 fn load_roots(roots_der: &[&[u8]]) -> Arc<RootCertStore> {
333 let mut roots = RootCertStore::empty();
334 roots_der.iter().for_each(|der| {
335 roots
336 .add(CertificateDer::from(der.to_vec()))
337 .unwrap()
338 });
339 roots.into()
340 }
341
342 fn test_roots() -> Arc<RootCertStore> {
343 load_roots(&[
344 include_bytes!("../../../test-ca/ecdsa-p256/ca.der").as_slice(),
345 include_bytes!("../../../test-ca/rsa-2048/ca.der").as_slice(),
346 ])
347 }
348
349 #[test]
350 fn test_with_invalid_crls() {
351 let result = WebPkiServerVerifier::builder_with_provider(
353 test_roots(),
354 provider::default_provider().into(),
355 )
356 .with_crls(vec![CertificateRevocationListDer::from(vec![0xFF])])
357 .build();
358 assert!(matches!(result, Err(VerifierBuilderError::InvalidCrl(_))));
359 }
360
361 #[test]
362 fn test_with_crls_multiple_calls() {
363 let initial_crls = test_crls();
365 let extra_crls =
366 load_crls(&[
367 include_bytes!("../../../test-ca/eddsa/client.revoked.crl.pem").as_slice(),
368 ]);
369
370 let builder = WebPkiServerVerifier::builder_with_provider(
371 test_roots(),
372 provider::default_provider().into(),
373 )
374 .with_crls(initial_crls.clone())
375 .with_crls(extra_crls.clone());
376
377 assert_eq!(builder.crls.len(), initial_crls.len() + extra_crls.len());
379 println!("{:?}", builder);
381 builder.build().unwrap();
382 }
383
384 #[test]
385 fn test_builder_no_roots() {
386 let result = WebPkiServerVerifier::builder_with_provider(
388 RootCertStore::empty().into(),
389 provider::default_provider().into(),
390 )
391 .build();
392 assert!(matches!(result, Err(VerifierBuilderError::NoRootAnchors)));
393 }
394
395 #[test]
396 fn test_server_verifier_ee_only() {
397 let builder = WebPkiServerVerifier::builder_with_provider(
399 test_roots(),
400 provider::default_provider().into(),
401 )
402 .only_check_end_entity_revocation();
403 println!("{:?}", builder);
405 builder.build().unwrap();
406 }
407
408 #[test]
409 fn test_server_verifier_allow_unknown() {
410 let builder = WebPkiServerVerifier::builder_with_provider(
413 test_roots(),
414 provider::default_provider().into(),
415 )
416 .allow_unknown_revocation_status();
417 println!("{:?}", builder);
419 builder.build().unwrap();
420 }
421
422 #[test]
423 fn test_server_verifier_allow_unknown_ee_only() {
424 let builder = WebPkiServerVerifier::builder_with_provider(
427 test_roots(),
428 provider::default_provider().into(),
429 )
430 .allow_unknown_revocation_status()
431 .only_check_end_entity_revocation();
432 println!("{:?}", builder);
434 builder.build().unwrap();
435 }
436
437 #[test]
438 fn test_server_verifier_enforce_expiration() {
439 let builder = WebPkiServerVerifier::builder_with_provider(
442 test_roots(),
443 provider::default_provider().into(),
444 )
445 .enforce_revocation_expiration();
446 println!("{:?}", builder);
448 builder.build().unwrap();
449 }
450}