Coverage Report

Created: 2026-05-16 06:09

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.40/src/webpki/mod.rs
Line
Count
Source
1
use alloc::vec::Vec;
2
use core::fmt;
3
4
use pki_types::CertificateRevocationListDer;
5
use webpki::{CertRevocationList, InvalidNameContext, OwnedCertRevocationList};
6
7
use crate::error::{
8
    CertRevocationListError, CertificateError, Error, ExtendedKeyPurpose, OtherError,
9
};
10
#[cfg(feature = "std")]
11
use crate::sync::Arc;
12
13
mod anchors;
14
mod client_verifier;
15
mod server_verifier;
16
mod verify;
17
18
pub use anchors::RootCertStore;
19
pub use client_verifier::{ClientCertVerifierBuilder, WebPkiClientVerifier};
20
pub use server_verifier::{ServerCertVerifierBuilder, WebPkiServerVerifier};
21
// Conditionally exported from crate.
22
#[allow(unreachable_pub)]
23
pub use verify::{
24
    ParsedCertificate, verify_server_cert_signed_by_trust_anchor, verify_server_name,
25
};
26
pub 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]
34
pub enum VerifierBuilderError {
35
    /// No root trust anchors were provided.
36
    NoRootAnchors,
37
    /// A provided CRL could not be parsed.
38
    InvalidCrl(CertRevocationListError),
39
}
40
41
impl From<CertRevocationListError> for VerifierBuilderError {
42
0
    fn from(value: CertRevocationListError) -> Self {
43
0
        Self::InvalidCrl(value)
44
0
    }
45
}
46
47
impl fmt::Display for VerifierBuilderError {
48
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
49
0
        match self {
50
0
            Self::NoRootAnchors => write!(f, "no root trust anchors were provided"),
51
0
            Self::InvalidCrl(e) => write!(f, "provided CRL could not be parsed: {e:?}"),
52
        }
53
0
    }
54
}
55
56
#[cfg(feature = "std")]
57
impl std::error::Error for VerifierBuilderError {}
58
59
0
fn pki_error(error: webpki::Error) -> Error {
60
    use webpki::Error::*;
61
0
    match error {
62
0
        BadDer | BadDerTime | TrailingData(_) => CertificateError::BadEncoding.into(),
63
0
        CertNotValidYet { time, not_before } => {
64
0
            CertificateError::NotValidYetContext { time, not_before }.into()
65
        }
66
0
        CertExpired { time, not_after } => {
67
0
            CertificateError::ExpiredContext { time, not_after }.into()
68
        }
69
0
        InvalidCertValidity => CertificateError::Expired.into(),
70
0
        UnknownIssuer => CertificateError::UnknownIssuer.into(),
71
        CertNotValidForName(InvalidNameContext {
72
0
            expected,
73
0
            presented,
74
0
        }) => CertificateError::NotValidForNameContext {
75
0
            expected,
76
0
            presented,
77
0
        }
78
0
        .into(),
79
0
        CertRevoked => CertificateError::Revoked.into(),
80
0
        UnknownRevocationStatus => CertificateError::UnknownRevocationStatus.into(),
81
0
        CrlExpired { time, next_update } => {
82
0
            CertificateError::ExpiredRevocationListContext { time, next_update }.into()
83
        }
84
0
        IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl.into(),
85
86
0
        InvalidSignatureForPublicKey => CertificateError::BadSignature.into(),
87
        #[allow(deprecated)]
88
        UnsupportedSignatureAlgorithm | UnsupportedSignatureAlgorithmForPublicKey => {
89
0
            CertificateError::UnsupportedSignatureAlgorithm.into()
90
        }
91
0
        UnsupportedSignatureAlgorithmContext(cx) => {
92
0
            CertificateError::UnsupportedSignatureAlgorithmContext {
93
0
                signature_algorithm_id: cx.signature_algorithm_id,
94
0
                supported_algorithms: cx.supported_algorithms,
95
0
            }
96
0
            .into()
97
        }
98
0
        UnsupportedSignatureAlgorithmForPublicKeyContext(cx) => {
99
0
            CertificateError::UnsupportedSignatureAlgorithmForPublicKeyContext {
100
0
                signature_algorithm_id: cx.signature_algorithm_id,
101
0
                public_key_algorithm_id: cx.public_key_algorithm_id,
102
0
            }
103
0
            .into()
104
        }
105
106
0
        InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature.into(),
107
        #[allow(deprecated)]
108
        UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => {
109
0
            CertRevocationListError::UnsupportedSignatureAlgorithm.into()
110
        }
111
0
        UnsupportedCrlSignatureAlgorithmContext(cx) => {
112
0
            CertRevocationListError::UnsupportedSignatureAlgorithmContext {
113
0
                signature_algorithm_id: cx.signature_algorithm_id,
114
0
                supported_algorithms: cx.supported_algorithms,
115
0
            }
116
0
            .into()
117
        }
118
0
        UnsupportedCrlSignatureAlgorithmForPublicKeyContext(cx) => {
119
0
            CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
120
0
                signature_algorithm_id: cx.signature_algorithm_id,
121
0
                public_key_algorithm_id: cx.public_key_algorithm_id,
122
0
            }
123
0
            .into()
124
        }
125
126
        #[allow(deprecated)]
127
0
        RequiredEkuNotFound => CertificateError::InvalidPurpose.into(),
128
0
        RequiredEkuNotFoundContext(webpki::RequiredEkuNotFoundContext { required, present }) => {
129
            CertificateError::InvalidPurposeContext {
130
0
                required: ExtendedKeyPurpose::for_values(required.oid_values()),
131
0
                presented: present
132
0
                    .into_iter()
133
0
                    .map(|eku| ExtendedKeyPurpose::for_values(eku.into_iter()))
134
0
                    .collect(),
135
            }
136
0
            .into()
137
        }
138
139
0
        _ => CertificateError::Other(OtherError(
140
0
            #[cfg(feature = "std")]
141
0
            Arc::new(error),
142
0
        ))
143
0
        .into(),
144
    }
145
0
}
146
147
0
fn crl_error(e: webpki::Error) -> CertRevocationListError {
148
    use webpki::Error::*;
149
0
    match e {
150
0
        InvalidCrlSignatureForPublicKey => CertRevocationListError::BadSignature,
151
        #[allow(deprecated)]
152
        UnsupportedCrlSignatureAlgorithm | UnsupportedCrlSignatureAlgorithmForPublicKey => {
153
0
            CertRevocationListError::UnsupportedSignatureAlgorithm
154
        }
155
0
        UnsupportedCrlSignatureAlgorithmContext(cx) => {
156
0
            CertRevocationListError::UnsupportedSignatureAlgorithmContext {
157
0
                signature_algorithm_id: cx.signature_algorithm_id,
158
0
                supported_algorithms: cx.supported_algorithms,
159
0
            }
160
        }
161
0
        UnsupportedSignatureAlgorithmForPublicKeyContext(cx) => {
162
0
            CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
163
0
                signature_algorithm_id: cx.signature_algorithm_id,
164
0
                public_key_algorithm_id: cx.public_key_algorithm_id,
165
0
            }
166
        }
167
0
        InvalidCrlNumber => CertRevocationListError::InvalidCrlNumber,
168
0
        InvalidSerialNumber => CertRevocationListError::InvalidRevokedCertSerialNumber,
169
0
        IssuerNotCrlSigner => CertRevocationListError::IssuerInvalidForCrl,
170
0
        MalformedExtensions | BadDer | BadDerTime => CertRevocationListError::ParseError,
171
0
        UnsupportedCriticalExtension => CertRevocationListError::UnsupportedCriticalExtension,
172
0
        UnsupportedCrlVersion => CertRevocationListError::UnsupportedCrlVersion,
173
0
        UnsupportedDeltaCrl => CertRevocationListError::UnsupportedDeltaCrl,
174
0
        UnsupportedIndirectCrl => CertRevocationListError::UnsupportedIndirectCrl,
175
0
        UnsupportedRevocationReason => CertRevocationListError::UnsupportedRevocationReason,
176
177
0
        _ => CertRevocationListError::Other(OtherError(
178
0
            #[cfg(feature = "std")]
179
0
            Arc::new(e),
180
0
        )),
181
    }
182
0
}
183
184
0
fn parse_crls(
185
0
    crls: Vec<CertificateRevocationListDer<'_>>,
186
0
) -> Result<Vec<CertRevocationList<'_>>, CertRevocationListError> {
187
0
    crls.iter()
188
0
        .map(|der| OwnedCertRevocationList::from_der(der.as_ref()).map(Into::into))
189
0
        .collect::<Result<Vec<_>, _>>()
190
0
        .map_err(crl_error)
191
0
}
192
193
#[cfg(test)]
194
mod tests {
195
    use alloc::vec;
196
197
    use super::*;
198
199
    #[test]
200
    fn pki_crl_errors() {
201
        // CRL signature errors should be turned into BadSignature.
202
        assert_eq!(
203
            pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
204
            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
205
        );
206
207
        #[allow(deprecated)]
208
        {
209
            assert_eq!(
210
                pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
211
                Error::InvalidCertRevocationList(
212
                    CertRevocationListError::UnsupportedSignatureAlgorithm
213
                ),
214
            );
215
            assert_eq!(
216
                pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
217
                Error::InvalidCertRevocationList(
218
                    CertRevocationListError::UnsupportedSignatureAlgorithm
219
                ),
220
            );
221
        }
222
223
        assert_eq!(
224
            pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmContext(
225
                webpki::UnsupportedSignatureAlgorithmContext {
226
                    signature_algorithm_id: vec![],
227
                    supported_algorithms: vec![],
228
                }
229
            )),
230
            Error::InvalidCertRevocationList(
231
                CertRevocationListError::UnsupportedSignatureAlgorithmContext {
232
                    signature_algorithm_id: vec![],
233
                    supported_algorithms: vec![],
234
                }
235
            )
236
        );
237
        assert_eq!(
238
            pki_error(
239
                webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKeyContext(
240
                    webpki::UnsupportedSignatureAlgorithmForPublicKeyContext {
241
                        signature_algorithm_id: vec![],
242
                        public_key_algorithm_id: vec![],
243
                    }
244
                )
245
            ),
246
            Error::InvalidCertRevocationList(
247
                CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
248
                    signature_algorithm_id: vec![],
249
                    public_key_algorithm_id: vec![],
250
                }
251
            )
252
        );
253
254
        // Revoked cert errors should be turned into Revoked.
255
        assert_eq!(
256
            pki_error(webpki::Error::CertRevoked),
257
            Error::InvalidCertificate(CertificateError::Revoked),
258
        );
259
260
        // Issuer not CRL signer errors should be turned into IssuerInvalidForCrl
261
        assert_eq!(
262
            pki_error(webpki::Error::IssuerNotCrlSigner),
263
            Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
264
        );
265
    }
266
267
    #[test]
268
    fn crl_error_from_webpki() {
269
        use CertRevocationListError::*;
270
        #[allow(deprecated)]
271
        let testcases = &[
272
            (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
273
            (
274
                webpki::Error::UnsupportedCrlSignatureAlgorithm,
275
                UnsupportedSignatureAlgorithm,
276
            ),
277
            (
278
                webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
279
                UnsupportedSignatureAlgorithm,
280
            ),
281
            (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
282
            (
283
                webpki::Error::InvalidSerialNumber,
284
                InvalidRevokedCertSerialNumber,
285
            ),
286
            (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
287
            (webpki::Error::MalformedExtensions, ParseError),
288
            (webpki::Error::BadDer, ParseError),
289
            (webpki::Error::BadDerTime, ParseError),
290
            (
291
                webpki::Error::UnsupportedCriticalExtension,
292
                UnsupportedCriticalExtension,
293
            ),
294
            (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
295
            (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
296
            (
297
                webpki::Error::UnsupportedIndirectCrl,
298
                UnsupportedIndirectCrl,
299
            ),
300
            (
301
                webpki::Error::UnsupportedRevocationReason,
302
                UnsupportedRevocationReason,
303
            ),
304
        ];
305
        for t in testcases {
306
            assert_eq!(crl_error(t.0.clone()), t.1);
307
        }
308
309
        assert!(matches!(
310
            crl_error(webpki::Error::NameConstraintViolation),
311
            Other(..)
312
        ));
313
    }
314
}