1 | use alloc::sync::Arc; |
2 | use alloc::vec::Vec; |
3 | use core::fmt; |
4 | |
5 | use pki_types::CertificateRevocationListDer; |
6 | use std::error::Error as StdError; |
7 | use webpki::{CertRevocationList, OwnedCertRevocationList}; |
8 | |
9 | use crate::error::{CertRevocationListError, CertificateError, Error, OtherError}; |
10 | |
11 | mod anchors; |
12 | mod client_verifier; |
13 | mod server_verifier; |
14 | mod verify; |
15 | |
16 | pub use anchors::RootCertStore; |
17 | |
18 | pub use client_verifier::{ClientCertVerifierBuilder, WebPkiClientVerifier}; |
19 | pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier}; |
20 | |
21 | pub use verify::{verify_tls12_signature, verify_tls13_signature, WebPkiSupportedAlgorithms}; |
22 | |
23 | // Conditionally exported from crate. |
24 | #[allow (unreachable_pub)] |
25 | pub use verify::{ |
26 | verify_server_cert_signed_by_trust_anchor, verify_server_name, ParsedCertificate, |
27 | }; |
28 | |
29 | /// An error that can occur when building a certificate verifier. |
30 | #[derive (Debug, Clone)] |
31 | #[non_exhaustive ] |
32 | pub enum VerifierBuilderError { |
33 | /// No root trust anchors were provided. |
34 | NoRootAnchors, |
35 | /// A provided CRL could not be parsed. |
36 | InvalidCrl(CertRevocationListError), |
37 | } |
38 | |
39 | impl From<CertRevocationListError> for VerifierBuilderError { |
40 | fn from(value: CertRevocationListError) -> Self { |
41 | Self::InvalidCrl(value) |
42 | } |
43 | } |
44 | |
45 | impl 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: &CertRevocationListError) => write!(f, "provided CRL could not be parsed: {:?}" , e), |
50 | } |
51 | } |
52 | } |
53 | |
54 | impl StdError for VerifierBuilderError {} |
55 | |
56 | fn pki_error(error: webpki::Error) -> Error { |
57 | use webpki::Error::*; |
58 | match error { |
59 | BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(), |
60 | CertNotValidYet => CertificateError::NotValidYet.into(), |
61 | CertExpired | InvalidCertValidity => CertificateError::Expired.into(), |
62 | UnknownIssuer => CertificateError::UnknownIssuer.into(), |
63 | CertNotValidForName => CertificateError::NotValidForName.into(), |
64 | CertRevoked => CertificateError::Revoked.into(), |
65 | UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(), |
66 | IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(), |
67 | |
68 | InvalidSignatureForPublicKey |
69 | | UnsupportedSignatureAlgorithm |
70 | | UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature.into(), |
71 | |
72 | InvalidCrlSignatureForPublicKey |
73 | | UnsupportedCrlSignatureAlgorithm |
74 | | UnsupportedCrlSignatureAlgorithmForPublicKey => { |
75 | CertRevocationListError::BadSignature.into() |
76 | } |
77 | |
78 | _ => CertificateError::Other(OtherError(Arc::new(error))).into(), |
79 | } |
80 | } |
81 | |
82 | fn crl_error(e: webpki::Error) -> CertRevocationListError { |
83 | use webpki::Error::*; |
84 | match e { |
85 | InvalidCrlSignatureForPublicKey |
86 | | UnsupportedCrlSignatureAlgorithm |
87 | | UnsupportedCrlSignatureAlgorithmForPublicKey => CertRevocationListError::BadSignature, |
88 | InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber, |
89 | InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber, |
90 | IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl, |
91 | MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError, |
92 | UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension, |
93 | UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion, |
94 | UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl, |
95 | UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl, |
96 | UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason, |
97 | |
98 | _ => CertRevocationListError::Other(OtherError(Arc::new(data:e))), |
99 | } |
100 | } |
101 | |
102 | fn parse_crls( |
103 | crls: Vec<CertificateRevocationListDer<'_>>, |
104 | ) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> { |
105 | crls.iter() |
106 | .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into)) |
107 | .collect::<Result<Vec<_>, _>>() |
108 | .map_err(op:crl_error) |
109 | } |
110 | |
111 | mod tests { |
112 | #[test ] |
113 | fn pki_crl_errors() { |
114 | use super::{pki_error, CertRevocationListError, CertificateError, Error}; |
115 | |
116 | // CRL signature errors should be turned into BadSignature. |
117 | assert_eq!( |
118 | pki_error(webpki::Error::InvalidCrlSignatureForPublicKey), |
119 | Error::InvalidCertRevocationList(CertRevocationListError::BadSignature), |
120 | ); |
121 | assert_eq!( |
122 | pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm), |
123 | Error::InvalidCertRevocationList(CertRevocationListError::BadSignature), |
124 | ); |
125 | assert_eq!( |
126 | pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey), |
127 | Error::InvalidCertRevocationList(CertRevocationListError::BadSignature), |
128 | ); |
129 | |
130 | // Revoked cert errors should be turned into Revoked. |
131 | assert_eq!( |
132 | pki_error(webpki::Error::CertRevoked), |
133 | Error::InvalidCertificate(CertificateError::Revoked), |
134 | ); |
135 | |
136 | // Issuer not CRL signer errors should be turned into IssuerInvalidForCrl |
137 | assert_eq!( |
138 | pki_error(webpki::Error::IssuerNotCrlSigner), |
139 | Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl) |
140 | ); |
141 | } |
142 | |
143 | #[test ] |
144 | fn crl_error_from_webpki() { |
145 | use super::{crl_error, CertRevocationListError::*}; |
146 | |
147 | let testcases = &[ |
148 | (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature), |
149 | ( |
150 | webpki::Error::UnsupportedCrlSignatureAlgorithm, |
151 | BadSignature, |
152 | ), |
153 | ( |
154 | webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey, |
155 | BadSignature, |
156 | ), |
157 | (webpki::Error::InvalidCrlNumber, InvalidCrlNumber), |
158 | ( |
159 | webpki::Error::InvalidSerialNumber, |
160 | InvalidRevokedCertSerialNumber, |
161 | ), |
162 | (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl), |
163 | (webpki::Error::MalformedExtensions, ParseError), |
164 | (webpki::Error::BadDer, ParseError), |
165 | (webpki::Error::BadDerTime, ParseError), |
166 | ( |
167 | webpki::Error::UnsupportedCriticalExtension, |
168 | UnsupportedCriticalExtension, |
169 | ), |
170 | (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion), |
171 | (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl), |
172 | ( |
173 | webpki::Error::UnsupportedIndirectCrl, |
174 | UnsupportedIndirectCrl, |
175 | ), |
176 | ( |
177 | webpki::Error::UnsupportedRevocationReason, |
178 | UnsupportedRevocationReason, |
179 | ), |
180 | ]; |
181 | for t in testcases { |
182 | assert_eq!(crl_error(t.0), t.1); |
183 | } |
184 | |
185 | assert!(matches!( |
186 | crl_error(webpki::Error::NameConstraintViolation), |
187 | Other(_) |
188 | )); |
189 | } |
190 | } |
191 | |