1use alloc::vec::Vec;
2use core::hash::{Hash, Hasher};
3
4use pki_types::CertificateRevocationListDer;
5use webpki::{CertRevocationList, ExpirationPolicy, RevocationCheckDepth, UnknownStatusPolicy};
6
7use crate::crypto::{CryptoProvider, Identity, SignatureScheme, WebPkiSupportedAlgorithms};
8use crate::error::ApiMisuse;
9use crate::sync::Arc;
10use crate::verify::{
11 HandshakeSignatureValid, ServerIdentity, ServerVerifier, SignatureVerificationInput,
12 VerifiedIdentity,
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::{ClientConfig, ConfigBuilder, crypto};
21use crate::{DynHasher, 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<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 }
130}
131
132#[derive(Debug, Hash)]
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
143impl WebPkiServerVerifier {
144 pub fn builder(roots: Arc<RootCertStore>, provider: &CryptoProvider) -> ServerVerifierBuilder {
153 ServerVerifierBuilder::new(roots, provider.signature_verification_algorithms)
154 }
155
156 pub(crate) fn new_without_revocation(
159 roots: impl Into<Arc<RootCertStore>>,
160 supported_algs: WebPkiSupportedAlgorithms,
161 ) -> Self {
162 Self::new(
163 roots,
164 Vec::default(),
165 RevocationCheckDepth::Chain,
166 UnknownStatusPolicy::Allow,
167 ExpirationPolicy::Ignore,
168 supported_algs,
169 )
170 }
171
172 pub(crate) fn new(
184 roots: impl Into<Arc<RootCertStore>>,
185 crls: Vec<CertRevocationList<'static>>,
186 revocation_check_depth: RevocationCheckDepth,
187 unknown_revocation_policy: UnknownStatusPolicy,
188 revocation_expiration_policy: ExpirationPolicy,
189 supported: WebPkiSupportedAlgorithms,
190 ) -> Self {
191 Self {
192 roots: roots.into(),
193 crls,
194 revocation_check_depth,
195 unknown_revocation_policy,
196 revocation_expiration_policy,
197 supported,
198 }
199 }
200}
201
202impl ServerVerifier for WebPkiServerVerifier {
203 fn verify_identity<'a>(
215 &self,
216 identity: &ServerIdentity<'a, '_>,
217 ) -> Result<VerifiedIdentity<'a>, Error> {
218 let certificates = match identity.identity {
219 Identity::X509(certificates) => certificates,
220 Identity::RawPublicKey(_) => {
221 return Err(ApiMisuse::UnverifiableCertificateType.into());
222 }
223 };
224
225 let cert = ParsedCertificate::try_from(&certificates.end_entity)?;
226 let crl_refs = self.crls.iter().collect::<Vec<_>>();
227 let revocation = if self.crls.is_empty() {
228 None
229 } else {
230 Some(
233 webpki::RevocationOptionsBuilder::new(crl_refs.as_slice())
234 .unwrap()
237 .with_depth(self.revocation_check_depth)
238 .with_status_policy(self.unknown_revocation_policy)
239 .with_expiration_policy(self.revocation_expiration_policy)
240 .build(),
241 )
242 };
243
244 verify_identity_signed_by_trust_anchor_impl(
247 &cert,
248 &self.roots,
249 &certificates.intermediates,
250 revocation,
251 identity.now,
252 self.supported.all,
253 )?;
254
255 verify_server_name(&cert, identity.server_name)?;
256 Ok(VerifiedIdentity::assertion(identity.identity.clone()))
257 }
258
259 fn verify_tls12_signature(
260 &self,
261 input: &SignatureVerificationInput<'_>,
262 ) -> Result<HandshakeSignatureValid, Error> {
263 verify_tls12_signature(input, &self.supported)
264 }
265
266 fn verify_tls13_signature(
267 &self,
268 input: &SignatureVerificationInput<'_>,
269 ) -> Result<HandshakeSignatureValid, Error> {
270 verify_tls13_signature(input, &self.supported)
271 }
272
273 fn supported_verify_schemes(&self) -> Vec<SignatureScheme> {
274 self.supported.supported_schemes()
275 }
276
277 fn request_ocsp_response(&self) -> bool {
278 false
279 }
280
281 fn hash_config(&self, h: &mut dyn Hasher) {
282 self.hash(&mut DynHasher(h));
283 }
284}
285
286#[cfg(test)]
287mod tests {
288 use alloc::vec::Vec;
289 use std::{println, vec};
290
291 use pki_types::pem::PemObject;
292 use pki_types::{CertificateDer, CertificateRevocationListDer};
293
294 use super::{VerifierBuilderError, WebPkiServerVerifier};
295 use crate::RootCertStore;
296 use crate::crypto::TEST_PROVIDER;
297 use crate::sync::Arc;
298
299 fn load_crls(crls_der: &[&[u8]]) -> Vec<CertificateRevocationListDer<'static>> {
300 crls_der
301 .iter()
302 .map(|pem_bytes| CertificateRevocationListDer::from_pem_slice(pem_bytes).unwrap())
303 .collect()
304 }
305
306 fn test_crls() -> Vec<CertificateRevocationListDer<'static>> {
307 load_crls(&[
308 include_bytes!("../../../test-ca/ecdsa-p256/client.revoked.crl.pem").as_slice(),
309 include_bytes!("../../../test-ca/rsa-2048/client.revoked.crl.pem").as_slice(),
310 ])
311 }
312
313 fn load_roots(roots_der: &[&[u8]]) -> Arc<RootCertStore> {
314 let mut roots = RootCertStore::empty();
315 roots_der.iter().for_each(|der| {
316 roots
317 .add(CertificateDer::from(der.to_vec()))
318 .unwrap()
319 });
320 roots.into()
321 }
322
323 fn test_roots() -> Arc<RootCertStore> {
324 load_roots(&[
325 include_bytes!("../../../test-ca/ecdsa-p256/ca.der").as_slice(),
326 include_bytes!("../../../test-ca/rsa-2048/ca.der").as_slice(),
327 ])
328 }
329
330 #[test]
331 fn test_with_invalid_crls() {
332 let result = WebPkiServerVerifier::builder(test_roots(), &TEST_PROVIDER)
334 .with_crls(vec![CertificateRevocationListDer::from(vec![0xFF])])
335 .build();
336 assert!(matches!(result, Err(VerifierBuilderError::InvalidCrl(_))));
337 }
338
339 #[test]
340 fn test_with_crls_multiple_calls() {
341 let initial_crls = test_crls();
343 let extra_crls =
344 load_crls(&[
345 include_bytes!("../../../test-ca/eddsa/client.revoked.crl.pem").as_slice(),
346 ]);
347
348 let builder = WebPkiServerVerifier::builder(test_roots(), &TEST_PROVIDER)
349 .with_crls(initial_crls.clone())
350 .with_crls(extra_crls.clone());
351
352 assert_eq!(builder.crls.len(), initial_crls.len() + extra_crls.len());
354 println!("{builder:?}");
356 builder.build().unwrap();
357 }
358
359 #[test]
360 fn test_builder_no_roots() {
361 let result =
363 WebPkiServerVerifier::builder(RootCertStore::empty().into(), &TEST_PROVIDER).build();
364 assert!(matches!(result, Err(VerifierBuilderError::NoRootAnchors)));
365 }
366
367 #[test]
368 fn test_server_verifier_ee_only() {
369 let builder = WebPkiServerVerifier::builder(test_roots(), &TEST_PROVIDER)
371 .only_check_end_entity_revocation();
372 println!("{builder:?}");
374 builder.build().unwrap();
375 }
376
377 #[test]
378 fn test_server_verifier_allow_unknown() {
379 let builder = WebPkiServerVerifier::builder(test_roots(), &TEST_PROVIDER)
382 .allow_unknown_revocation_status();
383 println!("{builder:?}");
385 builder.build().unwrap();
386 }
387
388 #[test]
389 fn test_server_verifier_allow_unknown_ee_only() {
390 let builder = WebPkiServerVerifier::builder(test_roots(), &TEST_PROVIDER)
393 .allow_unknown_revocation_status()
394 .only_check_end_entity_revocation();
395 println!("{builder:?}");
397 builder.build().unwrap();
398 }
399
400 #[test]
401 fn test_server_verifier_enforce_expiration() {
402 let builder = WebPkiServerVerifier::builder(test_roots(), &TEST_PROVIDER)
405 .enforce_revocation_expiration();
406 println!("{builder:?}");
408 builder.build().unwrap();
409 }
410}