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