1use alloc::sync::Arc;
2use alloc::vec::Vec;
3
4use pki_types::{CertificateDer, CertificateRevocationListDer, ServerName, UnixTime};
5use webpki::{CertRevocationList, RevocationCheckDepth, UnknownStatusPolicy};
6
7use crate::crypto::{CryptoProvider, WebPkiSupportedAlgorithms};
8#[cfg(feature = "logging")]
9use crate::log::trace;
10use crate::verify::{
11 DigitallySignedStruct, HandshakeSignatureValid, ServerCertVerified, ServerCertVerifier,
12};
13use crate::webpki::verify::{
14 verify_server_cert_signed_by_trust_anchor_impl, verify_tls12_signature, verify_tls13_signature,
15 ParsedCertificate,
16};
17use crate::webpki::{parse_crls, verify_server_name, VerifierBuilderError};
18#[cfg(doc)]
19use crate::{crypto, ConfigBuilder, ServerConfig};
20use crate::{Error, RootCertStore, SignatureScheme};
21
22#[derive(Debug, Clone)]
26pub struct ServerCertVerifierBuilder {
27 roots: Arc<RootCertStore>,
28 crls: Vec<CertificateRevocationListDer<'static>>,
29 revocation_check_depth: RevocationCheckDepth,
30 unknown_revocation_policy: UnknownStatusPolicy,
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 supported_algs,
45 }
46 }
47
48 pub fn with_crls(
52 mut self,
53 crls: impl IntoIterator<Item = CertificateRevocationListDer<'static>>,
54 ) -> Self {
55 self.crls.extend(crls);
56 self
57 }
58
59 pub fn only_check_end_entity_revocation(mut self) -> Self {
69 self.revocation_check_depth = RevocationCheckDepth::EndEntity;
70 self
71 }
72
73 pub fn allow_unknown_revocation_status(mut self) -> Self {
82 self.unknown_revocation_policy = UnknownStatusPolicy::Allow;
83 self
84 }
85
86 pub fn build(self) -> Result<Arc<WebPkiServerVerifier>, VerifierBuilderError> {
101 if self.roots.is_empty() {
102 return Err(VerifierBuilderError::NoRootAnchors);
103 }
104
105 Ok(WebPkiServerVerifier::new(
106 self.roots,
107 parse_crls(self.crls)?,
108 self.revocation_check_depth,
109 self.unknown_revocation_policy,
110 self.supported_algs,
111 )
112 .into())
113 }
114}
115
116#[allow(unreachable_pub)]
118#[derive(Debug)]
119pub struct WebPkiServerVerifier {
120 roots: Arc<RootCertStore>,
121 crls: Vec<CertRevocationList<'static>>,
122 revocation_check_depth: RevocationCheckDepth,
123 unknown_revocation_policy: UnknownStatusPolicy,
124 supported: WebPkiSupportedAlgorithms,
125}
126
127#[allow(unreachable_pub)]
128impl WebPkiServerVerifier {
129 pub fn builder(roots: Arc<RootCertStore>) -> ServerCertVerifierBuilder {
138 Self::builder_with_provider(
139 roots,
140 Arc::clone(CryptoProvider::get_default_or_install_from_crate_features()),
141 )
142 }
143
144 pub fn builder_with_provider(
153 roots: Arc<RootCertStore>,
154 provider: Arc<CryptoProvider>,
155 ) -> ServerCertVerifierBuilder {
156 ServerCertVerifierBuilder::new(roots, provider.signature_verification_algorithms)
157 }
158
159 pub(crate) fn new_without_revocation(
162 roots: impl Into<Arc<RootCertStore>>,
163 supported_algs: WebPkiSupportedAlgorithms,
164 ) -> Self {
165 Self::new(
166 roots,
167 Vec::default(),
168 RevocationCheckDepth::Chain,
169 UnknownStatusPolicy::Allow,
170 supported_algs,
171 )
172 }
173
174 pub(crate) fn new(
186 roots: impl Into<Arc<RootCertStore>>,
187 crls: Vec<CertRevocationList<'static>>,
188 revocation_check_depth: RevocationCheckDepth,
189 unknown_revocation_policy: UnknownStatusPolicy,
190 supported: WebPkiSupportedAlgorithms,
191 ) -> Self {
192 Self {
193 roots: roots.into(),
194 crls,
195 revocation_check_depth,
196 unknown_revocation_policy,
197 supported,
198 }
199 }
200}
201
202impl ServerCertVerifier for WebPkiServerVerifier {
203 fn verify_server_cert(
214 &self,
215 end_entity: &CertificateDer<'_>,
216 intermediates: &[CertificateDer<'_>],
217 server_name: &ServerName<'_>,
218 ocsp_response: &[u8],
219 now: UnixTime,
220 ) -> Result<ServerCertVerified, Error> {
221 let cert = ParsedCertificate::try_from(end_entity)?;
222
223 let crl_refs = self.crls.iter().collect::<Vec<_>>();
224
225 let revocation = if self.crls.is_empty() {
226 None
227 } else {
228 Some(
231 webpki::RevocationOptionsBuilder::new(crl_refs.as_slice())
232 .unwrap()
235 .with_depth(self.revocation_check_depth)
236 .with_status_policy(self.unknown_revocation_policy)
237 .build(),
238 )
239 };
240
241 verify_server_cert_signed_by_trust_anchor_impl(
244 &cert,
245 &self.roots,
246 intermediates,
247 revocation,
248 now,
249 self.supported.all,
250 )?;
251
252 if !ocsp_response.is_empty() {
253 trace!("Unvalidated OCSP response: {:?}", ocsp_response.to_vec());
254 }
255
256 verify_server_name(&cert, server_name)?;
257 Ok(ServerCertVerified::assertion())
258 }
259
260 fn verify_tls12_signature(
261 &self,
262 message: &[u8],
263 cert: &CertificateDer<'_>,
264 dss: &DigitallySignedStruct,
265 ) -> Result<HandshakeSignatureValid, Error> {
266 verify_tls12_signature(message, cert, dss, &self.supported)
267 }
268
269 fn verify_tls13_signature(
270 &self,
271 message: &[u8],
272 cert: &CertificateDer<'_>,
273 dss: &DigitallySignedStruct,
274 ) -> Result<HandshakeSignatureValid, Error> {
275 verify_tls13_signature(message, cert, dss, &self.supported)
276 }
277
278 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
279 self.supported.supported_schemes()
280 }
281}
282
283test_for_each_provider! {
284 use std::sync::Arc;
285 use std::{vec, println};
286 use std::prelude::v1::*;
287
288 use pki_types::{CertificateDer, CertificateRevocationListDer};
289
290 use super::{VerifierBuilderError, WebPkiServerVerifier};
291 use crate::RootCertStore;
292
293 fn load_crls(crls_der: &[&[u8]]) -> Vec<CertificateRevocationListDer<'static>> {
294 crls_der
295 .iter()
296 .map(|pem_bytes| {
297 rustls_pemfile::crls(&mut &pem_bytes[..])
298 .next()
299 .unwrap()
300 .unwrap()
301 })
302 .collect()
303 }
304
305 fn test_crls() -> Vec<CertificateRevocationListDer<'static>> {
306 load_crls(&[
307 include_bytes!("../../../test-ca/ecdsa-p256/client.revoked.crl.pem").as_slice(),
308 include_bytes!("../../../test-ca/rsa/client.revoked.crl.pem").as_slice(),
309 ])
310 }
311
312 fn load_roots(roots_der: &[&[u8]]) -> Arc<RootCertStore> {
313 let mut roots = RootCertStore::empty();
314 roots_der.iter().for_each(|der| {
315 roots
316 .add(CertificateDer::from(der.to_vec()))
317 .unwrap()
318 });
319 roots.into()
320 }
321
322 fn test_roots() -> Arc<RootCertStore> {
323 load_roots(&[
324 include_bytes!("../../../test-ca/ecdsa-p256/ca.der").as_slice(),
325 include_bytes!("../../../test-ca/rsa/ca.der").as_slice(),
326 ])
327 }
328
329 #[test]
330 fn test_with_invalid_crls() {
331 let result = WebPkiServerVerifier::builder_with_provider(
333 test_roots(),
334 provider::default_provider().into(),
335 )
336 .with_crls(vec![CertificateRevocationListDer::from(vec![0xFF])])
337 .build();
338 assert!(matches!(result, Err(VerifierBuilderError::InvalidCrl(_))));
339 }
340
341 #[test]
342 fn test_with_crls_multiple_calls() {
343 let initial_crls = test_crls();
345 let extra_crls =
346 load_crls(&[
347 include_bytes!("../../../test-ca/eddsa/client.revoked.crl.pem").as_slice(),
348 ]);
349
350 let builder = WebPkiServerVerifier::builder_with_provider(
351 test_roots(),
352 provider::default_provider().into(),
353 )
354 .with_crls(initial_crls.clone())
355 .with_crls(extra_crls.clone());
356
357 assert_eq!(builder.crls.len(), initial_crls.len() + extra_crls.len());
359 println!("{:?}", builder);
361 builder.build().unwrap();
362 }
363
364 #[test]
365 fn test_builder_no_roots() {
366 let result = WebPkiServerVerifier::builder_with_provider(
368 RootCertStore::empty().into(),
369 provider::default_provider().into(),
370 )
371 .build();
372 assert!(matches!(result, Err(VerifierBuilderError::NoRootAnchors)));
373 }
374
375 #[test]
376 fn test_server_verifier_ee_only() {
377 let builder = WebPkiServerVerifier::builder_with_provider(
379 test_roots(),
380 provider::default_provider().into(),
381 )
382 .only_check_end_entity_revocation();
383 println!("{:?}", builder);
385 builder.build().unwrap();
386 }
387
388 #[test]
389 fn test_server_verifier_allow_unknown() {
390 let builder = WebPkiServerVerifier::builder_with_provider(
393 test_roots(),
394 provider::default_provider().into(),
395 )
396 .allow_unknown_revocation_status();
397 println!("{:?}", builder);
399 builder.build().unwrap();
400 }
401
402 #[test]
403 fn test_server_verifier_allow_unknown_ee_only() {
404 let builder = WebPkiServerVerifier::builder_with_provider(
407 test_roots(),
408 provider::default_provider().into(),
409 )
410 .allow_unknown_revocation_status()
411 .only_check_end_entity_revocation();
412 println!("{:?}", builder);
414 builder.build().unwrap();
415 }
416}