rustls/webpki/
mod.rs

1use alloc::sync::Arc;
2use alloc::vec::Vec;
3use core::fmt;
4
5use pki_types::CertificateRevocationListDer;
6use std::error::Error as StdError;
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;
17
18pub use client_verifier::{ClientCertVerifierBuilder, WebPkiClientVerifier};
19pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier};
20
21pub use verify::{verify_tls12_signature, verify_tls13_signature, WebPkiSupportedAlgorithms};
22
23// Conditionally exported from crate.
24#[allow(unreachable_pub)]
25pub 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]
32pub enum VerifierBuilderError {
33    /// No root trust anchors were provided.
34    NoRootAnchors,
35    /// A provided CRL could not be parsed.
36    InvalidCrl(CertRevocationListError),
37}
38
39impl From<CertRevocationListError> for VerifierBuilderError {
40    fn from(value: CertRevocationListError) -> Self {
41        Self::InvalidCrl(value)
42    }
43}
44
45impl 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) => write!(f, "provided CRL could not be parsed: {:?}", e),
50        }
51    }
52}
53
54impl StdError for VerifierBuilderError {}
55
56fn 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
82fn 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(e))),
99    }
100}
101
102fn 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(crl_error)
109}
110
111mod 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}