rustls/webpki/
mod.rs

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// Conditionally exported from crate.
22#[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/// An error that can occur when building a certificate verifier.
32#[derive(Debug, Clone)]
33#[non_exhaustive]
34pub enum VerifierBuilderError {
35    /// No root trust anchors were provided.
36    NoRootAnchors,
37    /// A provided CRL could not be parsed.
38    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 => CertificateError::BadSignature.into(),
87        UnsupportedSignatureAlgorithm | UnsupportedSignatureAlgorithmForPublicKey => {
88            CertificateError::UnsupportedSignatureAlgorithm.into()
89        }
90
91        InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature.into(),
92        UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => {
93            CertRevocationListError::UnsupportedSignatureAlgorithm.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 => CertRevocationListError::BadSignature,
121        UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => {
122            CertRevocationListError::UnsupportedSignatureAlgorithm
123        }
124        InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
125        InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
126        IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
127        MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
128        UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
129        UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
130        UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
131        UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
132        UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
133
134        _ => CertRevocationListError::Other(OtherError(
135            #[cfg(feature = "std")]
136            Arc::new(e),
137        )),
138    }
139}
140
141fn parse_crls(
142    crls: Vec<CertificateRevocationListDer<'_>>,
143) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
144    crls.iter()
145        .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
146        .collect::<Result<Vec<_>, _>>()
147        .map_err(crl_error)
148}
149
150mod tests {
151    #[test]
152    fn pki_crl_errors() {
153        use super::{CertRevocationListError, CertificateError, Error, pki_error};
154
155        // CRL signature errors should be turned into BadSignature.
156        assert_eq!(
157            pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
158            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
159        );
160        assert_eq!(
161            pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
162            Error::InvalidCertRevocationList(
163                CertRevocationListError::UnsupportedSignatureAlgorithm
164            ),
165        );
166        assert_eq!(
167            pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
168            Error::InvalidCertRevocationList(
169                CertRevocationListError::UnsupportedSignatureAlgorithm
170            ),
171        );
172
173        // Revoked cert errors should be turned into Revoked.
174        assert_eq!(
175            pki_error(webpki::Error::CertRevoked),
176            Error::InvalidCertificate(CertificateError::Revoked),
177        );
178
179        // Issuer not CRL signer errors should be turned into IssuerInvalidForCrl
180        assert_eq!(
181            pki_error(webpki::Error::IssuerNotCrlSigner),
182            Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
183        );
184    }
185
186    #[test]
187    fn crl_error_from_webpki() {
188        use super::CertRevocationListError::*;
189        use super::crl_error;
190
191        let testcases = &[
192            (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
193            (
194                webpki::Error::UnsupportedCrlSignatureAlgorithm,
195                UnsupportedSignatureAlgorithm,
196            ),
197            (
198                webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
199                UnsupportedSignatureAlgorithm,
200            ),
201            (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
202            (
203                webpki::Error::InvalidSerialNumber,
204                InvalidRevokedCertSerialNumber,
205            ),
206            (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
207            (webpki::Error::MalformedExtensions, ParseError),
208            (webpki::Error::BadDer, ParseError),
209            (webpki::Error::BadDerTime, ParseError),
210            (
211                webpki::Error::UnsupportedCriticalExtension,
212                UnsupportedCriticalExtension,
213            ),
214            (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
215            (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
216            (
217                webpki::Error::UnsupportedIndirectCrl,
218                UnsupportedIndirectCrl,
219            ),
220            (
221                webpki::Error::UnsupportedRevocationReason,
222                UnsupportedRevocationReason,
223            ),
224        ];
225        for t in testcases {
226            assert_eq!(crl_error(t.0.clone()), t.1);
227        }
228
229        assert!(matches!(
230            crl_error(webpki::Error::NameConstraintViolation),
231            Other(..)
232        ));
233    }
234}