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::{
25    verify_tls12_signature, verify_tls13_signature, verify_tls13_signature_with_raw_key,
26    WebPkiSupportedAlgorithms,
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
54#[cfg(feature = "std")]
55impl std::error::Error for VerifierBuilderError {}
56
57fn pki_error(error: webpki::Error) -> Error {
58    use webpki::Error::*;
59    match error {
60        BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(),
61        CertNotValidYet => CertificateError::NotValidYet.into(),
62        CertExpired | InvalidCertValidity => CertificateError::Expired.into(),
63        UnknownIssuer => CertificateError::UnknownIssuer.into(),
64        CertNotValidForName => CertificateError::NotValidForName.into(),
65        CertRevoked => CertificateError::Revoked.into(),
66        UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(),
67        CrlExpired => CertificateError::ExpiredRevocationList.into(),
68        IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(),
69
70        InvalidSignatureForPublicKey
71        | UnsupportedSignatureAlgorithm
72        | UnsupportedSignatureAlgorithmForPublicKey => CertificateError::BadSignature.into(),
73
74        InvalidCrlSignatureForPublicKey
75        | UnsupportedCrlSignatureAlgorithm
76        | UnsupportedCrlSignatureAlgorithmForPublicKey => {
77            CertRevocationListError::BadSignature.into()
78        }
79
80        _ => CertificateError::Other(OtherError(
81            #[cfg(feature = "std")]
82            Arc::new(error),
83        ))
84        .into(),
85    }
86}
87
88fn crl_error(e: webpki::Error) -> CertRevocationListError {
89    use webpki::Error::*;
90    match e {
91        InvalidCrlSignatureForPublicKey
92        | UnsupportedCrlSignatureAlgorithm
93        | UnsupportedCrlSignatureAlgorithmForPublicKey => CertRevocationListError::BadSignature,
94        InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
95        InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
96        IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
97        MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
98        UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
99        UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
100        UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
101        UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
102        UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
103
104        _ => CertRevocationListError::Other(OtherError(
105            #[cfg(feature = "std")]
106            Arc::new(e),
107        )),
108    }
109}
110
111fn parse_crls(
112    crls: Vec<CertificateRevocationListDer<'_>>,
113) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
114    crls.iter()
115        .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
116        .collect::<Result<Vec<_>, _>>()
117        .map_err(crl_error)
118}
119
120mod tests {
121    #[test]
122    fn pki_crl_errors() {
123        use super::{pki_error, CertRevocationListError, CertificateError, Error};
124
125        // CRL signature errors should be turned into BadSignature.
126        assert_eq!(
127            pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
128            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
129        );
130        assert_eq!(
131            pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
132            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
133        );
134        assert_eq!(
135            pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
136            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
137        );
138
139        // Revoked cert errors should be turned into Revoked.
140        assert_eq!(
141            pki_error(webpki::Error::CertRevoked),
142            Error::InvalidCertificate(CertificateError::Revoked),
143        );
144
145        // Issuer not CRL signer errors should be turned into IssuerInvalidForCrl
146        assert_eq!(
147            pki_error(webpki::Error::IssuerNotCrlSigner),
148            Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
149        );
150    }
151
152    #[test]
153    fn crl_error_from_webpki() {
154        use super::crl_error;
155        use super::CertRevocationListError::*;
156
157        let testcases = &[
158            (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
159            (
160                webpki::Error::UnsupportedCrlSignatureAlgorithm,
161                BadSignature,
162            ),
163            (
164                webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
165                BadSignature,
166            ),
167            (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
168            (
169                webpki::Error::InvalidSerialNumber,
170                InvalidRevokedCertSerialNumber,
171            ),
172            (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
173            (webpki::Error::MalformedExtensions, ParseError),
174            (webpki::Error::BadDer, ParseError),
175            (webpki::Error::BadDerTime, ParseError),
176            (
177                webpki::Error::UnsupportedCriticalExtension,
178                UnsupportedCriticalExtension,
179            ),
180            (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
181            (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
182            (
183                webpki::Error::UnsupportedIndirectCrl,
184                UnsupportedIndirectCrl,
185            ),
186            (
187                webpki::Error::UnsupportedRevocationReason,
188                UnsupportedRevocationReason,
189            ),
190        ];
191        for t in testcases {
192            assert_eq!(crl_error(t.0), t.1);
193        }
194
195        assert!(matches!(
196            crl_error(webpki::Error::NameConstraintViolation),
197            Other(..)
198        ));
199    }
200}