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::{verify_tls12_signature, verify_tls13_signature, WebPkiSupportedAlgorithms};
25
26#[derive(Debug, Clone)]
28#[non_exhaustive]
29pub enum VerifierBuilderError {
30 NoRootAnchors,
32 InvalidCrl(CertRevocationListError),
34}
35
36impl From<CertRevocationListError> for VerifierBuilderError {
37 fn from(value: CertRevocationListError) -> Self {
38 Self::InvalidCrl(value)
39 }
40}
41
42impl fmt::Display for VerifierBuilderError {
43 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
44 match self {
45 Self::NoRootAnchors => write!(f, "no root trust anchors were provided"),
46 Self::InvalidCrl(e) => write!(f, "provided CRL could not be parsed: {:?}", e),
47 }
48 }
49}
50
51#[cfg(feature = "std")]
52impl std::error::Error for VerifierBuilderError {}
53
54fn pki_error(error: webpki::Error) -> Error {
55 use webpki::Error::*;
56 match error {
57 BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(),
58 CertNotValidYet => CertificateError::NotValidYet.into(),
59 CertExpired | InvalidCertValidity => CertificateError::Expired.into(),
60 UnknownIssuer => CertificateError::UnknownIssuer.into(),
61 CertNotValidForName => CertificateError::NotValidForName.into(),
62 CertRevoked => CertificateError::Revoked.into(),
63 UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(),
64 CrlExpired => CertificateError::ExpiredRevocationList.into(),
65 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(),
66
67 InvalidSignatureForPublicKey
68 | UnsupportedSignatureAlgorithm
69 | UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature.into(),
70
71 InvalidCrlSignatureForPublicKey
72 | UnsupportedCrlSignatureAlgorithm
73 | UnsupportedCrlSignatureAlgorithmForPublicKey => {
74 CertRevocationListError::BadSignature.into()
75 }
76
77 _ => CertificateError::Other(OtherError(
78 #[cfg(feature = "std")]
79 Arc::new(error),
80 ))
81 .into(),
82 }
83}
84
85fn crl_error(e: webpki::Error) -> CertRevocationListError {
86 use webpki::Error::*;
87 match e {
88 InvalidCrlSignatureForPublicKey
89 | UnsupportedCrlSignatureAlgorithm
90 | UnsupportedCrlSignatureAlgorithmForPublicKey => CertRevocationListError::BadSignature,
91 InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
92 InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
93 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
94 MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
95 UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
96 UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
97 UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
98 UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
99 UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
100
101 _ => CertRevocationListError::Other(OtherError(
102 #[cfg(feature = "std")]
103 Arc::new(e),
104 )),
105 }
106}
107
108fn parse_crls(
109 crls: Vec<CertificateRevocationListDer<'_>>,
110) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
111 crls.iter()
112 .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
113 .collect::<Result<Vec<_>, _>>()
114 .map_err(crl_error)
115}
116
117mod tests {
118 #[test]
119 fn pki_crl_errors() {
120 use super::{pki_error, CertRevocationListError, CertificateError, Error};
121
122 assert_eq!(
124 pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
125 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
126 );
127 assert_eq!(
128 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
129 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
130 );
131 assert_eq!(
132 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
133 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
134 );
135
136 assert_eq!(
138 pki_error(webpki::Error::CertRevoked),
139 Error::InvalidCertificate(CertificateError::Revoked),
140 );
141
142 assert_eq!(
144 pki_error(webpki::Error::IssuerNotCrlSigner),
145 Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
146 );
147 }
148
149 #[test]
150 fn crl_error_from_webpki() {
151 use super::crl_error;
152 use super::CertRevocationListError::*;
153
154 let testcases = &[
155 (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
156 (
157 webpki::Error::UnsupportedCrlSignatureAlgorithm,
158 BadSignature,
159 ),
160 (
161 webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
162 BadSignature,
163 ),
164 (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
165 (
166 webpki::Error::InvalidSerialNumber,
167 InvalidRevokedCertSerialNumber,
168 ),
169 (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
170 (webpki::Error::MalformedExtensions, ParseError),
171 (webpki::Error::BadDer, ParseError),
172 (webpki::Error::BadDerTime, ParseError),
173 (
174 webpki::Error::UnsupportedCriticalExtension,
175 UnsupportedCriticalExtension,
176 ),
177 (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
178 (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
179 (
180 webpki::Error::UnsupportedIndirectCrl,
181 UnsupportedIndirectCrl,
182 ),
183 (
184 webpki::Error::UnsupportedRevocationReason,
185 UnsupportedRevocationReason,
186 ),
187 ];
188 for t in testcases {
189 assert_eq!(crl_error(t.0), t.1);
190 }
191
192 assert!(matches!(
193 crl_error(webpki::Error::NameConstraintViolation),
194 Other(..)
195 ));
196 }
197}