Coverage Report

Created: 2026-01-15 06:51

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.35/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 super::*;
196
    use alloc::vec;
197
198
    #[test]
199
    fn pki_crl_errors() {
200
        // CRL signature errors should be turned into BadSignature.
201
        assert_eq!(
202
            pki_error(webpki::Error::InvalidCrlSignatureForPublicKey),
203
            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
204
        );
205
206
        #[allow(deprecated)]
207
        {
208
            assert_eq!(
209
                pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithm),
210
                Error::InvalidCertRevocationList(
211
                    CertRevocationListError::UnsupportedSignatureAlgorithm
212
                ),
213
            );
214
            assert_eq!(
215
                pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey),
216
                Error::InvalidCertRevocationList(
217
                    CertRevocationListError::UnsupportedSignatureAlgorithm
218
                ),
219
            );
220
        }
221
222
        assert_eq!(
223
            pki_error(webpki::Error::UnsupportedCrlSignatureAlgorithmContext(
224
                webpki::UnsupportedSignatureAlgorithmContext {
225
                    signature_algorithm_id: vec![],
226
                    supported_algorithms: vec![],
227
                }
228
            )),
229
            Error::InvalidCertRevocationList(
230
                CertRevocationListError::UnsupportedSignatureAlgorithmContext {
231
                    signature_algorithm_id: vec![],
232
                    supported_algorithms: vec![],
233
                }
234
            )
235
        );
236
        assert_eq!(
237
            pki_error(
238
                webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKeyContext(
239
                    webpki::UnsupportedSignatureAlgorithmForPublicKeyContext {
240
                        signature_algorithm_id: vec![],
241
                        public_key_algorithm_id: vec![],
242
                    }
243
                )
244
            ),
245
            Error::InvalidCertRevocationList(
246
                CertRevocationListError::UnsupportedSignatureAlgorithmForPublicKeyContext {
247
                    signature_algorithm_id: vec![],
248
                    public_key_algorithm_id: vec![],
249
                }
250
            )
251
        );
252
253
        // Revoked cert errors should be turned into Revoked.
254
        assert_eq!(
255
            pki_error(webpki::Error::CertRevoked),
256
            Error::InvalidCertificate(CertificateError::Revoked),
257
        );
258
259
        // Issuer not CRL signer errors should be turned into IssuerInvalidForCrl
260
        assert_eq!(
261
            pki_error(webpki::Error::IssuerNotCrlSigner),
262
            Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
263
        );
264
    }
265
266
    #[test]
267
    fn crl_error_from_webpki() {
268
        use CertRevocationListError::*;
269
        #[allow(deprecated)]
270
        let testcases = &[
271
            (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
272
            (
273
                webpki::Error::UnsupportedCrlSignatureAlgorithm,
274
                UnsupportedSignatureAlgorithm,
275
            ),
276
            (
277
                webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
278
                UnsupportedSignatureAlgorithm,
279
            ),
280
            (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
281
            (
282
                webpki::Error::InvalidSerialNumber,
283
                InvalidRevokedCertSerialNumber,
284
            ),
285
            (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
286
            (webpki::Error::MalformedExtensions, ParseError),
287
            (webpki::Error::BadDer, ParseError),
288
            (webpki::Error::BadDerTime, ParseError),
289
            (
290
                webpki::Error::UnsupportedCriticalExtension,
291
                UnsupportedCriticalExtension,
292
            ),
293
            (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
294
            (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
295
            (
296
                webpki::Error::UnsupportedIndirectCrl,
297
                UnsupportedIndirectCrl,
298
            ),
299
            (
300
                webpki::Error::UnsupportedRevocationReason,
301
                UnsupportedRevocationReason,
302
            ),
303
        ];
304
        for t in testcases {
305
            assert_eq!(crl_error(t.0.clone()), t.1);
306
        }
307
308
        assert!(matches!(
309
            crl_error(webpki::Error::NameConstraintViolation),
310
            Other(..)
311
        ));
312
    }
313
}