1use alloc::vec::Vec;
2use core::fmt;
3
4use pki_types::CertificateRevocationListDer;
5use webpki::{CertRevocationList, InvalidNameContext, OwnedCertRevocationList};
6
7use crate::error::{
8 CertRevocationListError, CertificateError, Error, ExtendedKeyPurpose, OtherError,
9};
10#[cfg(feature = "std")]
11use crate::sync::Arc;
12
13mod anchors;
14mod client_verifier;
15mod server_verifier;
16mod verify;
17
18pub use anchors::RootCertStore;
19pub use client_verifier::{ClientCertVerifierBuilder, WebPkiClientVerifier};
20pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier};
21#[allow(unreachable_pub)]
23pub use verify::{
24 ParsedCertificate, verify_server_cert_signed_by_trust_anchor, verify_server_name,
25};
26pub use verify::{
27 WebPkiSupportedAlgorithms, verify_tls12_signature, verify_tls13_signature,
28 verify_tls13_signature_with_raw_key,
29};
30
31#[derive(Debug, Clone)]
33#[non_exhaustive]
34pub enum VerifierBuilderError {
35 NoRootAnchors,
37 InvalidCrl(CertRevocationListError),
39}
40
41impl From<CertRevocationListError> for VerifierBuilderError {
42 fn from(value: CertRevocationListError) -> Self {
43 Self::InvalidCrl(value)
44 }
45}
46
47impl fmt::Display for VerifierBuilderError {
48 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49 match self {
50 Self::NoRootAnchors => write!(f, "no root trust anchors were provided"),
51 Self::InvalidCrl(e) => write!(f, "provided CRL could not be parsed: {e:?}"),
52 }
53 }
54}
55
56#[cfg(feature = "std")]
57impl std::error::Error for VerifierBuilderError {}
58
59fn pki_error(error: webpki::Error) -> Error {
60 use webpki::Error::*;
61 match error {
62 BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(),
63 CertNotValidYet { time, not_before } => {
64 CertificateError::NotValidYetContext { time, not_before }.into()
65 }
66 CertExpired { time, not_after } => {
67 CertificateError::ExpiredContext { time, not_after }.into()
68 }
69 InvalidCertValidity => CertificateError::Expired.into(),
70 UnknownIssuer => CertificateError::UnknownIssuer.into(),
71 CertNotValidForName(InvalidNameContext {
72 expected,
73 presented,
74 }) => CertificateError::NotValidForNameContext {
75 expected,
76 presented,
77 }
78 .into(),
79 CertRevoked => CertificateError::Revoked.into(),
80 UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(),
81 CrlExpired { time, next_update } => {
82 CertificateError::ExpiredRevocationListContext { time, next_update }.into()
83 }
84 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(),
85
86 InvalidSignatureForPublicKey => CertificateError::BadSignature.into(),
87 #[allow(deprecated)]
88 UnsupportedSignatureAlgorithm | UnsupportedSignatureAlgorithmForPublicKey => {
89 CertificateError::UnsupportedSignatureAlgorithm.into()
90 }
91 UnsupportedSignatureAlgorithmContext(cx) => {
92 CertificateError::UnsupportedSignatureAlgorithmContext {
93 signature_algorithm_id: cx.signature_algorithm_id,
94 supported_algorithms: cx.supported_algorithms,
95 }
96 .into()
97 }
98 UnsupportedSignatureAlgorithmForPublicKeyContext(cx) => {
99 CertificateError::UnsupportedSignatureAlgorithmForPublicKeyContext {
100 signature_algorithm_id: cx.signature_algorithm_id,
101 public_key_algorithm_id: cx.public_key_algorithm_id,
102 }
103 .into()
104 }
105
106 InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature.into(),
107 #[allow(deprecated)]
108 UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => {
109 CertRevocationListError::UnsupportedSignatureAlgorithm.into()
110 }
111 UnsupportedCrlSignatureAlgorithmContext(cx) => {
112 CertRevocationListError::UnsupportedSignatureAlgorithmContext {
113 signature_algorithm_id: cx.signature_algorithm_id,
114 supported_algorithms: cx.supported_algorithms,
115 }
116 .into()
117 }
118 UnsupportedCrlSignatureAlgorithmForPublicKeyContext(cx) => {
119 CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
120 signature_algorithm_id: cx.signature_algorithm_id,
121 public_key_algorithm_id: cx.public_key_algorithm_id,
122 }
123 .into()
124 }
125
126 #[allow(deprecated)]
127 RequiredEkuNotFound => CertificateError::InvalidPurpose.into(),
128 RequiredEkuNotFoundContext(webpki::RequiredEkuNotFoundContext { required, present }) => {
129 CertificateError::InvalidPurposeContext {
130 required: ExtendedKeyPurpose::for_values(required.oid_values()),
131 presented: present
132 .into_iter()
133 .map(|eku| ExtendedKeyPurpose::for_values(eku.into_iter()))
134 .collect(),
135 }
136 .into()
137 }
138
139 _ => CertificateError::Other(OtherError(
140 #[cfg(feature = "std")]
141 Arc::new(error),
142 ))
143 .into(),
144 }
145}
146
147fn crl_error(e: webpki::Error) -> CertRevocationListError {
148 use webpki::Error::*;
149 match e {
150 InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature,
151 #[allow(deprecated)]
152 UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => {
153 CertRevocationListError::UnsupportedSignatureAlgorithm
154 }
155 UnsupportedCrlSignatureAlgorithmContext(cx) => {
156 CertRevocationListError::UnsupportedSignatureAlgorithmContext {
157 signature_algorithm_id: cx.signature_algorithm_id,
158 supported_algorithms: cx.supported_algorithms,
159 }
160 }
161 UnsupportedSignatureAlgorithmForPublicKeyContext(cx) => {
162 CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
163 signature_algorithm_id: cx.signature_algorithm_id,
164 public_key_algorithm_id: cx.public_key_algorithm_id,
165 }
166 }
167 InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
168 InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
169 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
170 MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
171 UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
172 UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
173 UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
174 UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
175 UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
176
177 _ => CertRevocationListError::Other(OtherError(
178 #[cfg(feature = "std")]
179 Arc::new(e),
180 )),
181 }
182}
183
184fn parse_crls(
185 crls: Vec<CertificateRevocationListDer<'_>>,
186) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
187 crls.iter()
188 .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
189 .collect::<Result<Vec<_>, _>>()
190 .map_err(crl_error)
191}
192
193#[cfg(test)]
194mod tests {
195 use super::*;
196 use alloc::vec;
197
198 #[test]
199 fn pki_crl_errors() {
200 assert_eq!(
202 pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
203 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
204 );
205
206 #[allow(deprecated)]
207 {
208 assert_eq!(
209 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
210 Error::InvalidCertRevocationList(
211 CertRevocationListError::UnsupportedSignatureAlgorithm
212 ),
213 );
214 assert_eq!(
215 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
216 Error::InvalidCertRevocationList(
217 CertRevocationListError::UnsupportedSignatureAlgorithm
218 ),
219 );
220 }
221
222 assert_eq!(
223 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmContext(
224 webpki::UnsupportedSignatureAlgorithmContext {
225 signature_algorithm_id: vec![],
226 supported_algorithms: vec![],
227 }
228 )),
229 Error::InvalidCertRevocationList(
230 CertRevocationListError::UnsupportedSignatureAlgorithmContext {
231 signature_algorithm_id: vec![],
232 supported_algorithms: vec![],
233 }
234 )
235 );
236 assert_eq!(
237 pki_error(
238 webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKeyContext(
239 webpki::UnsupportedSignatureAlgorithmForPublicKeyContext {
240 signature_algorithm_id: vec![],
241 public_key_algorithm_id: vec![],
242 }
243 )
244 ),
245 Error::InvalidCertRevocationList(
246 CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
247 signature_algorithm_id: vec![],
248 public_key_algorithm_id: vec![],
249 }
250 )
251 );
252
253 assert_eq!(
255 pki_error(webpki::Error::CertRevoked),
256 Error::InvalidCertificate(CertificateError::Revoked),
257 );
258
259 assert_eq!(
261 pki_error(webpki::Error::IssuerNotCrlSigner),
262 Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
263 );
264 }
265
266 #[test]
267 fn crl_error_from_webpki() {
268 use CertRevocationListError::*;
269 #[allow(deprecated)]
270 let testcases = &[
271 (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
272 (
273 webpki::Error::UnsupportedCrlSignatureAlgorithm,
274 UnsupportedSignatureAlgorithm,
275 ),
276 (
277 webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
278 UnsupportedSignatureAlgorithm,
279 ),
280 (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
281 (
282 webpki::Error::InvalidSerialNumber,
283 InvalidRevokedCertSerialNumber,
284 ),
285 (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
286 (webpki::Error::MalformedExtensions, ParseError),
287 (webpki::Error::BadDer, ParseError),
288 (webpki::Error::BadDerTime, ParseError),
289 (
290 webpki::Error::UnsupportedCriticalExtension,
291 UnsupportedCriticalExtension,
292 ),
293 (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
294 (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
295 (
296 webpki::Error::UnsupportedIndirectCrl,
297 UnsupportedIndirectCrl,
298 ),
299 (
300 webpki::Error::UnsupportedRevocationReason,
301 UnsupportedRevocationReason,
302 ),
303 ];
304 for t in testcases {
305 assert_eq!(crl_error(t.0.clone()), t.1);
306 }
307
308 assert!(matches!(
309 crl_error(webpki::Error::NameConstraintViolation),
310 Other(..)
311 ));
312 }
313}