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