1use alloc::vec::Vec;
2
3use pki_types::CertificateRevocationListDer;
4use webpki::{CertRevocationList, ExpirationPolicy, RevocationCheckDepth, UnknownStatusPolicy};
5
6use crate::crypto::{CryptoProvider, Identity, WebPkiSupportedAlgorithms};
7use crate::enums::SignatureScheme;
8use crate::error::ApiMisuse;
9use crate::sync::Arc;
10use crate::verify::{
11 HandshakeSignatureValid, PeerVerified, ServerIdentity, ServerVerifier,
12 SignatureVerificationInput,
13};
14use crate::webpki::verify::{
15 ParsedCertificate, verify_identity_signed_by_trust_anchor_impl, verify_tls12_signature,
16 verify_tls13_signature,
17};
18use crate::webpki::{VerifierBuilderError, parse_crls, verify_server_name};
19#[cfg(doc)]
20use crate::{ConfigBuilder, ServerConfig, crypto};
21use crate::{Error, RootCertStore};
22
23#[derive(Debug, Clone)]
27pub struct ServerVerifierBuilder {
28 roots: Arc<RootCertStore>,
29 crls: Vec<CertificateRevocationListDer<'static>>,
30 revocation_check_depth: RevocationCheckDepth,
31 unknown_revocation_policy: UnknownStatusPolicy,
32 revocation_expiration_policy: ExpirationPolicy,
33 supported_algs: WebPkiSupportedAlgorithms,
34}
35
36impl ServerVerifierBuilder {
37 pub(crate) fn new(
38 roots: Arc<RootCertStore>,
39 supported_algs: WebPkiSupportedAlgorithms,
40 ) -> Self {
41 Self {
42 roots,
43 crls: Vec::new(),
44 revocation_check_depth: RevocationCheckDepth::Chain,
45 unknown_revocation_policy: UnknownStatusPolicy::Deny,
46 revocation_expiration_policy: ExpirationPolicy::Ignore,
47 supported_algs,
48 }
49 }
50
51 pub fn with_crls(
55 mut self,
56 crls: impl IntoIterator<Item = CertificateRevocationListDer<'static>>,
57 ) -> Self {
58 self.crls.extend(crls);
59 self
60 }
61
62 pub fn only_check_end_entity_revocation(mut self) -> Self {
72 self.revocation_check_depth = RevocationCheckDepth::EndEntity;
73 self
74 }
75
76 pub fn allow_unknown_revocation_status(mut self) -> Self {
85 self.unknown_revocation_policy = UnknownStatusPolicy::Allow;
86 self
87 }
88
89 pub fn enforce_revocation_expiration(mut self) -> Self {
98 self.revocation_expiration_policy = ExpirationPolicy::Enforce;
99 self
100 }
101
102 pub fn build(self) -> Result<Arc<WebPkiServerVerifier>, VerifierBuilderError> {
117 if self.roots.is_empty() {
118 return Err(VerifierBuilderError::NoRootAnchors);
119 }
120
121 Ok(WebPkiServerVerifier::new(
122 self.roots,
123 parse_crls(self.crls)?,
124 self.revocation_check_depth,
125 self.unknown_revocation_policy,
126 self.revocation_expiration_policy,
127 self.supported_algs,
128 )
129 .into())
130 }
131}
132
133#[allow(unreachable_pub)]
135#[derive(Debug)]
136pub struct WebPkiServerVerifier {
137 roots: Arc<RootCertStore>,
138 crls: Vec<CertRevocationList<'static>>,
139 revocation_check_depth: RevocationCheckDepth,
140 unknown_revocation_policy: UnknownStatusPolicy,
141 revocation_expiration_policy: ExpirationPolicy,
142 supported: WebPkiSupportedAlgorithms,
143}
144
145#[allow(unreachable_pub)]
146impl WebPkiServerVerifier {
147 pub fn builder(roots: Arc<RootCertStore>) -> ServerVerifierBuilder {
156 Self::builder_with_provider(
157 roots,
158 CryptoProvider::get_default_or_install_from_crate_features(),
159 )
160 }
161
162 pub fn builder_with_provider(
171 roots: Arc<RootCertStore>,
172 provider: &CryptoProvider,
173 ) -> ServerVerifierBuilder {
174 ServerVerifierBuilder::new(roots, provider.signature_verification_algorithms)
175 }
176
177 pub(crate) fn new_without_revocation(
180 roots: impl Into<Arc<RootCertStore>>,
181 supported_algs: WebPkiSupportedAlgorithms,
182 ) -> Self {
183 Self::new(
184 roots,
185 Vec::default(),
186 RevocationCheckDepth::Chain,
187 UnknownStatusPolicy::Allow,
188 ExpirationPolicy::Ignore,
189 supported_algs,
190 )
191 }
192
193 pub(crate) fn new(
205 roots: impl Into<Arc<RootCertStore>>,
206 crls: Vec<CertRevocationList<'static>>,
207 revocation_check_depth: RevocationCheckDepth,
208 unknown_revocation_policy: UnknownStatusPolicy,
209 revocation_expiration_policy: ExpirationPolicy,
210 supported: WebPkiSupportedAlgorithms,
211 ) -> Self {
212 Self {
213 roots: roots.into(),
214 crls,
215 revocation_check_depth,
216 unknown_revocation_policy,
217 revocation_expiration_policy,
218 supported,
219 }
220 }
221}
222
223impl ServerVerifier for WebPkiServerVerifier {
224 fn verify_identity(&self, identity: &ServerIdentity<'_>) -> Result<PeerVerified, Error> {
235 let certificates = match identity.identity {
236 Identity::X509(certificates) => certificates,
237 Identity::RawPublicKey(_) => {
238 return Err(ApiMisuse::UnverifiableCertificateType.into());
239 }
240 };
241
242 let cert = ParsedCertificate::try_from(&certificates.end_entity)?;
243 let crl_refs = self.crls.iter().collect::<Vec<_>>();
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_identity_signed_by_trust_anchor_impl(
264 &cert,
265 &self.roots,
266 &certificates.intermediates,
267 revocation,
268 identity.now,
269 self.supported.all,
270 )?;
271
272 verify_server_name(&cert, identity.server_name)?;
273 Ok(PeerVerified::assertion())
274 }
275
276 fn verify_tls12_signature(
277 &self,
278 input: &SignatureVerificationInput<'_>,
279 ) -> Result<HandshakeSignatureValid, Error> {
280 verify_tls12_signature(input, &self.supported)
281 }
282
283 fn verify_tls13_signature(
284 &self,
285 input: &SignatureVerificationInput<'_>,
286 ) -> Result<HandshakeSignatureValid, Error> {
287 verify_tls13_signature(input, &self.supported)
288 }
289
290 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
291 self.supported.supported_schemes()
292 }
293
294 fn request_ocsp_response(&self) -> bool {
295 false
296 }
297}
298
299#[cfg(test)]
300#[macro_rules_attribute::apply(test_for_each_provider)]
301mod tests {
302 use std::prelude::v1::*;
303 use std::{println, vec};
304
305 use pki_types::pem::PemObject;
306 use pki_types::{CertificateDer, CertificateRevocationListDer};
307
308 use super::{VerifierBuilderError, WebPkiServerVerifier, provider};
309 use crate::RootCertStore;
310 use crate::sync::Arc;
311
312 fn load_crls(crls_der: &[&[u8]]) -> Vec<CertificateRevocationListDer<'static>> {
313 crls_der
314 .iter()
315 .map(|pem_bytes| CertificateRevocationListDer::from_pem_slice(pem_bytes).unwrap())
316 .collect()
317 }
318
319 fn test_crls() -> Vec<CertificateRevocationListDer<'static>> {
320 load_crls(&[
321 include_bytes!("../../../test-ca/ecdsa-p256/client.revoked.crl.pem").as_slice(),
322 include_bytes!("../../../test-ca/rsa-2048/client.revoked.crl.pem").as_slice(),
323 ])
324 }
325
326 fn load_roots(roots_der: &[&[u8]]) -> Arc<RootCertStore> {
327 let mut roots = RootCertStore::empty();
328 roots_der.iter().for_each(|der| {
329 roots
330 .add(CertificateDer::from(der.to_vec()))
331 .unwrap()
332 });
333 roots.into()
334 }
335
336 fn test_roots() -> Arc<RootCertStore> {
337 load_roots(&[
338 include_bytes!("../../../test-ca/ecdsa-p256/ca.der").as_slice(),
339 include_bytes!("../../../test-ca/rsa-2048/ca.der").as_slice(),
340 ])
341 }
342
343 #[test]
344 fn test_with_invalid_crls() {
345 let result =
347 WebPkiServerVerifier::builder_with_provider(test_roots(), &provider::DEFAULT_PROVIDER)
348 .with_crls(vec![CertificateRevocationListDer::from(vec![0xFF])])
349 .build();
350 assert!(matches!(result, Err(VerifierBuilderError::InvalidCrl(_))));
351 }
352
353 #[test]
354 fn test_with_crls_multiple_calls() {
355 let initial_crls = test_crls();
357 let extra_crls =
358 load_crls(&[
359 include_bytes!("../../../test-ca/eddsa/client.revoked.crl.pem").as_slice(),
360 ]);
361
362 let builder =
363 WebPkiServerVerifier::builder_with_provider(test_roots(), &provider::DEFAULT_PROVIDER)
364 .with_crls(initial_crls.clone())
365 .with_crls(extra_crls.clone());
366
367 assert_eq!(builder.crls.len(), initial_crls.len() + extra_crls.len());
369 println!("{builder:?}");
371 builder.build().unwrap();
372 }
373
374 #[test]
375 fn test_builder_no_roots() {
376 let result = WebPkiServerVerifier::builder_with_provider(
378 RootCertStore::empty().into(),
379 &provider::DEFAULT_PROVIDER,
380 )
381 .build();
382 assert!(matches!(result, Err(VerifierBuilderError::NoRootAnchors)));
383 }
384
385 #[test]
386 fn test_server_verifier_ee_only() {
387 let builder =
389 WebPkiServerVerifier::builder_with_provider(test_roots(), &provider::DEFAULT_PROVIDER)
390 .only_check_end_entity_revocation();
391 println!("{builder:?}");
393 builder.build().unwrap();
394 }
395
396 #[test]
397 fn test_server_verifier_allow_unknown() {
398 let builder =
401 WebPkiServerVerifier::builder_with_provider(test_roots(), &provider::DEFAULT_PROVIDER)
402 .allow_unknown_revocation_status();
403 println!("{builder:?}");
405 builder.build().unwrap();
406 }
407
408 #[test]
409 fn test_server_verifier_allow_unknown_ee_only() {
410 let builder =
413 WebPkiServerVerifier::builder_with_provider(test_roots(), &provider::DEFAULT_PROVIDER)
414 .allow_unknown_revocation_status()
415 .only_check_end_entity_revocation();
416 println!("{builder:?}");
418 builder.build().unwrap();
419 }
420
421 #[test]
422 fn test_server_verifier_enforce_expiration() {
423 let builder =
426 WebPkiServerVerifier::builder_with_provider(test_roots(), &provider::DEFAULT_PROVIDER)
427 .enforce_revocation_expiration();
428 println!("{builder:?}");
430 builder.build().unwrap();
431 }
432}