rustls/webpki/
mod.rs

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// Conditionally exported from crate.
20#[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/// An error that can occur when building a certificate verifier.
27#[derive(Debug, Clone)]
28#[non_exhaustive]
29pub enum VerifierBuilderError {
30    /// No root trust anchors were provided.
31    NoRootAnchors,
32    /// A provided CRL could not be parsed.
33    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        // CRL signature errors should be turned into BadSignature.
123        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        // Revoked cert errors should be turned into Revoked.
137        assert_eq!(
138            pki_error(webpki::Error::CertRevoked),
139            Error::InvalidCertificate(CertificateError::Revoked),
140        );
141
142        // Issuer not CRL signer errors should be turned into IssuerInvalidForCrl
143        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}