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