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