1use alloc::vec::Vec;
2use core::fmt;
3
4use pki_types::CertificateRevocationListDer;
5use webpki::{CertRevocationList, InvalidNameContext, OwnedCertRevocationList};
6
7use crate::error::{CertRevocationListError, CertificateError, Error, OtherError};
8#[cfg(feature = "std")]
9use crate::sync::Arc;
10
11mod anchors;
12mod client_verifier;
13mod server_verifier;
14mod verify;
15
16pub use anchors::RootCertStore;
17pub use client_verifier::{ClientCertVerifierBuilder, WebPkiClientVerifier};
18pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier};
19#[allow(unreachable_pub)]
21pub use verify::{
22 ParsedCertificate, verify_server_cert_signed_by_trust_anchor, verify_server_name,
23};
24pub use verify::{
25 WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature,
26 verify_tls13_signature_with_raw_key,
27};
28
29#[derive(Debug, Clone)]
31#[non_exhaustive]
32pub enum VerifierBuilderError {
33 NoRootAnchors,
35 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) => write!(f, "provided CRL could not be parsed: {:?}", e),
50 }
51 }
52}
53
54#[cfg(feature = "std")]
55impl std::error::Error for VerifierBuilderError {}
56
57fn pki_error(error: webpki::Error) -> Error {
58 use webpki::Error::*;
59 match error {
60 BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(),
61 CertNotValidYet { time, not_before } => {
62 CertificateError::NotValidYetContext { time, not_before }.into()
63 }
64 CertExpired { time, not_after } => {
65 CertificateError::ExpiredContext { time, not_after }.into()
66 }
67 InvalidCertValidity => CertificateError::Expired.into(),
68 UnknownIssuer => CertificateError::UnknownIssuer.into(),
69 CertNotValidForName(InvalidNameContext {
70 expected,
71 presented,
72 }) => CertificateError::NotValidForNameContext {
73 expected,
74 presented,
75 }
76 .into(),
77 CertRevoked => CertificateError::Revoked.into(),
78 UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(),
79 CrlExpired { time, next_update } => {
80 CertificateError::ExpiredRevocationListContext { time, next_update }.into()
81 }
82 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(),
83
84 InvalidSignatureForPublicKey
85 | UnsupportedSignatureAlgorithm
86 | UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature.into(),
87
88 InvalidCrlSignatureForPublicKey
89 | UnsupportedCrlSignatureAlgorithm
90 | UnsupportedCrlSignatureAlgorithmForPublicKey => {
91 CertRevocationListError::BadSignature.into()
92 }
93
94 RequiredEkuNotFound => CertificateError::InvalidPurpose.into(),
95
96 _ => CertificateError::Other(OtherError(
97 #[cfg(feature = "std")]
98 Arc::new(error),
99 ))
100 .into(),
101 }
102}
103
104fn crl_error(e: webpki::Error) -> CertRevocationListError {
105 use webpki::Error::*;
106 match e {
107 InvalidCrlSignatureForPublicKey
108 | UnsupportedCrlSignatureAlgorithm
109 | UnsupportedCrlSignatureAlgorithmForPublicKey => CertRevocationListError::BadSignature,
110 InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
111 InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
112 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
113 MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
114 UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
115 UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
116 UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
117 UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
118 UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
119
120 _ => CertRevocationListError::Other(OtherError(
121 #[cfg(feature = "std")]
122 Arc::new(e),
123 )),
124 }
125}
126
127fn parse_crls(
128 crls: Vec<CertificateRevocationListDer<'_>>,
129) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
130 crls.iter()
131 .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
132 .collect::<Result<Vec<_>, _>>()
133 .map_err(crl_error)
134}
135
136mod tests {
137 #[test]
138 fn pki_crl_errors() {
139 use super::{CertRevocationListError, CertificateError, Error, pki_error};
140
141 assert_eq!(
143 pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
144 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
145 );
146 assert_eq!(
147 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
148 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
149 );
150 assert_eq!(
151 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
152 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
153 );
154
155 assert_eq!(
157 pki_error(webpki::Error::CertRevoked),
158 Error::InvalidCertificate(CertificateError::Revoked),
159 );
160
161 assert_eq!(
163 pki_error(webpki::Error::IssuerNotCrlSigner),
164 Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
165 );
166 }
167
168 #[test]
169 fn crl_error_from_webpki() {
170 use super::CertRevocationListError::*;
171 use super::crl_error;
172
173 let testcases = &[
174 (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
175 (
176 webpki::Error::UnsupportedCrlSignatureAlgorithm,
177 BadSignature,
178 ),
179 (
180 webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
181 BadSignature,
182 ),
183 (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
184 (
185 webpki::Error::InvalidSerialNumber,
186 InvalidRevokedCertSerialNumber,
187 ),
188 (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
189 (webpki::Error::MalformedExtensions, ParseError),
190 (webpki::Error::BadDer, ParseError),
191 (webpki::Error::BadDerTime, ParseError),
192 (
193 webpki::Error::UnsupportedCriticalExtension,
194 UnsupportedCriticalExtension,
195 ),
196 (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
197 (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
198 (
199 webpki::Error::UnsupportedIndirectCrl,
200 UnsupportedIndirectCrl,
201 ),
202 (
203 webpki::Error::UnsupportedRevocationReason,
204 UnsupportedRevocationReason,
205 ),
206 ];
207 for t in testcases {
208 assert_eq!(crl_error(t.0.clone()), t.1);
209 }
210
211 assert!(matches!(
212 crl_error(webpki::Error::NameConstraintViolation),
213 Other(..)
214 ));
215 }
216}