1use alloc::sync::Arc;
2use alloc::vec::Vec;
3use core::fmt;
4
5use pki_types::CertificateRevocationListDer;
6use std::error::Error as StdError;
7use webpki::{CertRevocationList, OwnedCertRevocationList};
8
9use crate::error::{CertRevocationListError, CertificateError, Error, OtherError};
10
11mod anchors;
12mod client_verifier;
13mod server_verifier;
14mod verify;
15
16pub use anchors::RootCertStore;
17
18pub use client_verifier::{ClientCertVerifierBuilder, WebPkiClientVerifier};
19pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier};
20
21pub use verify::{verify_tls12_signature, verify_tls13_signature, WebPkiSupportedAlgorithms};
22
23// Conditionally exported from crate.
24#[allow(unreachable_pub)]
25pub use verify::{
26 verify_server_cert_signed_by_trust_anchor, verify_server_name, ParsedCertificate,
27};
28
29/// An error that can occur when building a certificate verifier.
30#[derive(Debug, Clone)]
31#[non_exhaustive]
32pub enum VerifierBuilderError {
33 /// No root trust anchors were provided.
34 NoRootAnchors,
35 /// A provided CRL could not be parsed.
36 InvalidCrl(CertRevocationListError),
37}
38
39impl From<CertRevocationListError> for VerifierBuilderError {
40 fn from(value: CertRevocationListError) -> Self {
41 Self::InvalidCrl(value)
42 }
43}
44
45impl fmt::Display for VerifierBuilderError {
46 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47 match self {
48 Self::NoRootAnchors => write!(f, "no root trust anchors were provided"),
49 Self::InvalidCrl(e: &CertRevocationListError) => write!(f, "provided CRL could not be parsed: {:?}", e),
50 }
51 }
52}
53
54impl StdError for VerifierBuilderError {}
55
56fn pki_error(error: webpki::Error) -> Error {
57 use webpki::Error::*;
58 match error {
59 BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(),
60 CertNotValidYet => CertificateError::NotValidYet.into(),
61 CertExpired | InvalidCertValidity => CertificateError::Expired.into(),
62 UnknownIssuer => CertificateError::UnknownIssuer.into(),
63 CertNotValidForName => CertificateError::NotValidForName.into(),
64 CertRevoked => CertificateError::Revoked.into(),
65 UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(),
66 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(),
67
68 InvalidSignatureForPublicKey
69 | UnsupportedSignatureAlgorithm
70 | UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature.into(),
71
72 InvalidCrlSignatureForPublicKey
73 | UnsupportedCrlSignatureAlgorithm
74 | UnsupportedCrlSignatureAlgorithmForPublicKey => {
75 CertRevocationListError::BadSignature.into()
76 }
77
78 _ => CertificateError::Other(OtherError(Arc::new(error))).into(),
79 }
80}
81
82fn crl_error(e: webpki::Error) -> CertRevocationListError {
83 use webpki::Error::*;
84 match e {
85 InvalidCrlSignatureForPublicKey
86 | UnsupportedCrlSignatureAlgorithm
87 | UnsupportedCrlSignatureAlgorithmForPublicKey => CertRevocationListError::BadSignature,
88 InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
89 InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
90 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
91 MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
92 UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
93 UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
94 UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
95 UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
96 UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
97
98 _ => CertRevocationListError::Other(OtherError(Arc::new(data:e))),
99 }
100}
101
102fn parse_crls(
103 crls: Vec<CertificateRevocationListDer<'_>>,
104) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
105 crls.iter()
106 .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
107 .collect::<Result<Vec<_>, _>>()
108 .map_err(op:crl_error)
109}
110
111mod tests {
112 #[test]
113 fn pki_crl_errors() {
114 use super::{pki_error, CertRevocationListError, CertificateError, Error};
115
116 // CRL signature errors should be turned into BadSignature.
117 assert_eq!(
118 pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
119 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
120 );
121 assert_eq!(
122 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
123 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
124 );
125 assert_eq!(
126 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
127 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
128 );
129
130 // Revoked cert errors should be turned into Revoked.
131 assert_eq!(
132 pki_error(webpki::Error::CertRevoked),
133 Error::InvalidCertificate(CertificateError::Revoked),
134 );
135
136 // Issuer not CRL signer errors should be turned into IssuerInvalidForCrl
137 assert_eq!(
138 pki_error(webpki::Error::IssuerNotCrlSigner),
139 Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
140 );
141 }
142
143 #[test]
144 fn crl_error_from_webpki() {
145 use super::{crl_error, CertRevocationListError::*};
146
147 let testcases = &[
148 (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
149 (
150 webpki::Error::UnsupportedCrlSignatureAlgorithm,
151 BadSignature,
152 ),
153 (
154 webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
155 BadSignature,
156 ),
157 (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
158 (
159 webpki::Error::InvalidSerialNumber,
160 InvalidRevokedCertSerialNumber,
161 ),
162 (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
163 (webpki::Error::MalformedExtensions, ParseError),
164 (webpki::Error::BadDer, ParseError),
165 (webpki::Error::BadDerTime, ParseError),
166 (
167 webpki::Error::UnsupportedCriticalExtension,
168 UnsupportedCriticalExtension,
169 ),
170 (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
171 (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
172 (
173 webpki::Error::UnsupportedIndirectCrl,
174 UnsupportedIndirectCrl,
175 ),
176 (
177 webpki::Error::UnsupportedRevocationReason,
178 UnsupportedRevocationReason,
179 ),
180 ];
181 for t in testcases {
182 assert_eq!(crl_error(t.0), t.1);
183 }
184
185 assert!(matches!(
186 crl_error(webpki::Error::NameConstraintViolation),
187 Other(_)
188 ));
189 }
190}
191