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
87 | UnsupportedSignatureAlgorithm
88 | UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature.into(),
89
90 InvalidCrlSignatureForPublicKey
91 | UnsupportedCrlSignatureAlgorithm
92 | UnsupportedCrlSignatureAlgorithmForPublicKey => {
93 CertRevocationListError::BadSignature.into()
94 }
95
96 #[allow(deprecated)]
97 RequiredEkuNotFound => CertificateError::InvalidPurpose.into(),
98 RequiredEkuNotFoundContext(webpki::RequiredEkuNotFoundContext { required, present }) => {
99 CertificateError::InvalidPurposeContext {
100 required: ExtendedKeyPurpose::for_values(required.oid_values()),
101 presented: present
102 .into_iter()
103 .map(|eku| ExtendedKeyPurpose::for_values(eku.into_iter()))
104 .collect(),
105 }
106 .into()
107 }
108
109 _ => CertificateError::Other(OtherError(
110 #[cfg(feature = "std")]
111 Arc::new(error),
112 ))
113 .into(),
114 }
115}
116
117fn crl_error(e: webpki::Error) -> CertRevocationListError {
118 use webpki::Error::*;
119 match e {
120 InvalidCrlSignatureForPublicKey
121 | UnsupportedCrlSignatureAlgorithm
122 | UnsupportedCrlSignatureAlgorithmForPublicKey => CertRevocationListError::BadSignature,
123 InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
124 InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
125 IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
126 MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
127 UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
128 UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
129 UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
130 UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
131 UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
132
133 _ => CertRevocationListError::Other(OtherError(
134 #[cfg(feature = "std")]
135 Arc::new(e),
136 )),
137 }
138}
139
140fn parse_crls(
141 crls: Vec<CertificateRevocationListDer<'_>>,
142) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
143 crls.iter()
144 .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
145 .collect::<Result<Vec<_>, _>>()
146 .map_err(crl_error)
147}
148
149mod tests {
150 #[test]
151 fn pki_crl_errors() {
152 use super::{CertRevocationListError, CertificateError, Error, pki_error};
153
154 assert_eq!(
156 pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
157 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
158 );
159 assert_eq!(
160 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
161 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
162 );
163 assert_eq!(
164 pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
165 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
166 );
167
168 assert_eq!(
170 pki_error(webpki::Error::CertRevoked),
171 Error::InvalidCertificate(CertificateError::Revoked),
172 );
173
174 assert_eq!(
176 pki_error(webpki::Error::IssuerNotCrlSigner),
177 Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
178 );
179 }
180
181 #[test]
182 fn crl_error_from_webpki() {
183 use super::CertRevocationListError::*;
184 use super::crl_error;
185
186 let testcases = &[
187 (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
188 (
189 webpki::Error::UnsupportedCrlSignatureAlgorithm,
190 BadSignature,
191 ),
192 (
193 webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
194 BadSignature,
195 ),
196 (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
197 (
198 webpki::Error::InvalidSerialNumber,
199 InvalidRevokedCertSerialNumber,
200 ),
201 (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
202 (webpki::Error::MalformedExtensions, ParseError),
203 (webpki::Error::BadDer, ParseError),
204 (webpki::Error::BadDerTime, ParseError),
205 (
206 webpki::Error::UnsupportedCriticalExtension,
207 UnsupportedCriticalExtension,
208 ),
209 (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
210 (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
211 (
212 webpki::Error::UnsupportedIndirectCrl,
213 UnsupportedIndirectCrl,
214 ),
215 (
216 webpki::Error::UnsupportedRevocationReason,
217 UnsupportedRevocationReason,
218 ),
219 ];
220 for t in testcases {
221 assert_eq!(crl_error(t.0.clone()), t.1);
222 }
223
224 assert!(matches!(
225 crl_error(webpki::Error::NameConstraintViolation),
226 Other(..)
227 ));
228 }
229}