1#[cfg(feature = "std")]
2use alloc::sync::Arc;
3use alloc::vec::Vec;
4use core::fmt;
5
6use pki_types::CertificateRevocationListDer;
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;
17pub use client_verifier::{ClientCertVerifierBuilder, WebPkiClientVerifier};
18pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier};
19#[allow(unreachable_pub)]
21pub use verify::{
22 verify_server_cert_signed_by_trust_anchor, verify_server_name, ParsedCertificate,
23};
24pub use verify::{
25 verify_tls12_signature, verify_tls13_signature, verify_tls13_signature_with_raw_key,
26 WebPkiSupportedAlgorithms,
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 => CertificateError::NotValidYet.into(),
62 CertExpired | InvalidCertValidity => CertificateError::Expired.into(),
63 UnknownIssuer => CertificateError::UnknownIssuer.into(),
64 CertNotValidForName => CertificateError::NotValidForName.into(),
65 CertRevoked => CertificateError::Revoked.into(),
66 UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(),
67 CrlExpired => CertificateError::ExpiredRevocationList.into(),
68 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(),
69
70 InvalidSignatureForPublicKey
71 | UnsupportedSignatureAlgorithm
72 | UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature.into(),
73
74 InvalidCrlSignatureForPublicKey
75 | UnsupportedCrlSignatureAlgorithm
76 | UnsupportedCrlSignatureAlgorithmForPublicKey => {
77 CertRevocationListError::BadSignature.into()
78 }
79
80 _ => CertificateError::Other(OtherError(
81 #[cfg(feature = "std")]
82 Arc::new(error),
83 ))
84 .into(),
85 }
86}
87
88fn crl_error(e: webpki::Error) -> CertRevocationListError {
89 use webpki::Error::*;
90 match e {
91 InvalidCrlSignatureForPublicKey
92 | UnsupportedCrlSignatureAlgorithm
93 | UnsupportedCrlSignatureAlgorithmForPublicKey => CertRevocationListError::BadSignature,
94 InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
95 InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
96 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
97 MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
98 UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
99 UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
100 UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
101 UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
102 UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
103
104 _ => CertRevocationListError::Other(OtherError(
105 #[cfg(feature = "std")]
106 Arc::new(e),
107 )),
108 }
109}
110
111fn parse_crls(
112 crls: Vec<CertificateRevocationListDer<'_>>,
113) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
114 crls.iter()
115 .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
116 .collect::<Result<Vec<_>, _>>()
117 .map_err(crl_error)
118}
119
120mod tests {
121 #[test]
122 fn pki_crl_errors() {
123 use super::{pki_error, CertRevocationListError, CertificateError, Error};
124
125 assert_eq!(
127 pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
128 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
129 );
130 assert_eq!(
131 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
132 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
133 );
134 assert_eq!(
135 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
136 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
137 );
138
139 assert_eq!(
141 pki_error(webpki::Error::CertRevoked),
142 Error::InvalidCertificate(CertificateError::Revoked),
143 );
144
145 assert_eq!(
147 pki_error(webpki::Error::IssuerNotCrlSigner),
148 Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
149 );
150 }
151
152 #[test]
153 fn crl_error_from_webpki() {
154 use super::crl_error;
155 use super::CertRevocationListError::*;
156
157 let testcases = &[
158 (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
159 (
160 webpki::Error::UnsupportedCrlSignatureAlgorithm,
161 BadSignature,
162 ),
163 (
164 webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
165 BadSignature,
166 ),
167 (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
168 (
169 webpki::Error::InvalidSerialNumber,
170 InvalidRevokedCertSerialNumber,
171 ),
172 (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
173 (webpki::Error::MalformedExtensions, ParseError),
174 (webpki::Error::BadDer, ParseError),
175 (webpki::Error::BadDerTime, ParseError),
176 (
177 webpki::Error::UnsupportedCriticalExtension,
178 UnsupportedCriticalExtension,
179 ),
180 (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
181 (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
182 (
183 webpki::Error::UnsupportedIndirectCrl,
184 UnsupportedIndirectCrl,
185 ),
186 (
187 webpki::Error::UnsupportedRevocationReason,
188 UnsupportedRevocationReason,
189 ),
190 ];
191 for t in testcases {
192 assert_eq!(crl_error(t.0), t.1);
193 }
194
195 assert!(matches!(
196 crl_error(webpki::Error::NameConstraintViolation),
197 Other(..)
198 ));
199 }
200}