Coverage Report

Created: 2025-10-29 07:05

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-webpki-0.102.8/src/error.rs
Line
Count
Source
1
// Copyright 2015 Brian Smith.
2
//
3
// Permission to use, copy, modify, and/or distribute this software for any
4
// purpose with or without fee is hereby granted, provided that the above
5
// copyright notice and this permission notice appear in all copies.
6
//
7
// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES
8
// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
9
// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR
10
// ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
11
// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
12
// ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
13
// OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14
15
use core::fmt;
16
use core::ops::ControlFlow;
17
18
/// An error that occurs during certificate validation or name validation.
19
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
20
#[non_exhaustive]
21
pub enum Error {
22
    /// The encoding of some ASN.1 DER-encoded item is invalid.
23
    BadDer,
24
25
    /// The encoding of an ASN.1 DER-encoded time is invalid.
26
    BadDerTime,
27
28
    /// A CA certificate is being used as an end-entity certificate.
29
    CaUsedAsEndEntity,
30
31
    /// The certificate is expired; i.e. the time it is being validated for is
32
    /// later than the certificate's notAfter time.
33
    CertExpired,
34
35
    /// The certificate is not valid for the name it is being validated for.
36
    CertNotValidForName,
37
38
    /// The certificate is not valid yet; i.e. the time it is being validated
39
    /// for is earlier than the certificate's notBefore time.
40
    CertNotValidYet,
41
42
    /// The certificate, or one of its issuers, has been revoked.
43
    CertRevoked,
44
45
    /// The CRL is expired; i.e. the verification time is not before the time
46
    /// in the CRL nextUpdate field.
47
    CrlExpired,
48
49
    /// An end-entity certificate is being used as a CA certificate.
50
    EndEntityUsedAsCa,
51
52
    /// An X.509 extension is invalid.
53
    ExtensionValueInvalid,
54
55
    /// The certificate validity period (notBefore, notAfter) is invalid; e.g.
56
    /// the notAfter time is earlier than the notBefore time.
57
    InvalidCertValidity,
58
59
    /// A CRL number extension was invalid:
60
    ///  - it was mis-encoded
61
    ///  - it was negative
62
    ///  - it was too long
63
    InvalidCrlNumber,
64
65
    /// A iPAddress name constraint was invalid:
66
    /// - it had a sparse network mask (ie, cannot be written in CIDR form).
67
    /// - it was too long or short
68
    InvalidNetworkMaskConstraint,
69
70
    /// A serial number was invalid:
71
    ///  - it was misencoded
72
    ///  - it was negative
73
    ///  - it was too long
74
    InvalidSerialNumber,
75
76
    /// The CRL signature is invalid for the issuer's public key.
77
    InvalidCrlSignatureForPublicKey,
78
79
    /// The signature is invalid for the given public key.
80
    InvalidSignatureForPublicKey,
81
82
    /// A CRL was signed by an issuer that has a KeyUsage bitstring that does not include
83
    /// the cRLSign key usage bit.
84
    IssuerNotCrlSigner,
85
86
    /// A presented or reference DNS identifier was malformed, potentially
87
    /// containing invalid characters or invalid labels.
88
    MalformedDnsIdentifier,
89
90
    /// The certificate extensions are malformed.
91
    ///
92
    /// In particular, webpki requires the DNS name(s) be in the subjectAltName
93
    /// extension as required by the CA/Browser Forum Baseline Requirements
94
    /// and as recommended by RFC6125.
95
    MalformedExtensions,
96
97
    /// A name constraint was malformed, potentially containing invalid characters or
98
    /// invalid labels.
99
    MalformedNameConstraint,
100
101
    /// The maximum number of name constraint comparisons has been reached.
102
    MaximumNameConstraintComparisonsExceeded,
103
104
    /// The maximum number of internal path building calls has been reached. Path complexity is too great.
105
    MaximumPathBuildCallsExceeded,
106
107
    /// The path search was terminated because it became too deep.
108
    MaximumPathDepthExceeded,
109
110
    /// The maximum number of signature checks has been reached. Path complexity is too great.
111
    MaximumSignatureChecksExceeded,
112
113
    /// The certificate violates one or more name constraints.
114
    NameConstraintViolation,
115
116
    /// The certificate violates one or more path length constraints.
117
    PathLenConstraintViolated,
118
119
    /// The certificate is not valid for the Extended Key Usage for which it is
120
    /// being validated.
121
    RequiredEkuNotFound,
122
123
    /// The algorithm in the TBSCertificate "signature" field of a certificate
124
    /// does not match the algorithm in the signature of the certificate.
125
    SignatureAlgorithmMismatch,
126
127
    /// Trailing data was found while parsing DER-encoded input for the named type.
128
    TrailingData(DerTypeId),
129
130
    /// A valid issuer for the certificate could not be found.
131
    UnknownIssuer,
132
133
    /// The certificate's revocation status could not be determined.
134
    UnknownRevocationStatus,
135
136
    /// The certificate is not a v3 X.509 certificate.
137
    ///
138
    /// This error may be also reported if the certificate version field
139
    /// is malformed.
140
    UnsupportedCertVersion,
141
142
    /// The certificate contains an unsupported critical extension.
143
    UnsupportedCriticalExtension,
144
145
    /// The CRL contains an issuing distribution point with no distribution point name,
146
    /// or a distribution point name relative to an issuer.
147
    UnsupportedCrlIssuingDistributionPoint,
148
149
    /// The CRL is not a v2 X.509 CRL.
150
    ///
151
    /// The RFC 5280 web PKI profile mandates only version 2 be used. See section
152
    /// 5.1.2.1 for more information.
153
    ///
154
    /// This error may also be reported if the CRL version field is malformed.
155
    UnsupportedCrlVersion,
156
157
    /// The CRL is an unsupported "delta" CRL.
158
    UnsupportedDeltaCrl,
159
160
    /// The CRL contains unsupported "indirect" entries.
161
    UnsupportedIndirectCrl,
162
163
    /// The `ServerName` contained an unsupported type of value.
164
    UnsupportedNameType,
165
166
    /// The revocation reason is not in the set of supported revocation reasons.
167
    UnsupportedRevocationReason,
168
169
    /// The CRL is partitioned by revocation reasons.
170
    UnsupportedRevocationReasonsPartitioning,
171
172
    /// The signature algorithm for a signature over a CRL is not in the set of supported
173
    /// signature algorithms given.
174
    UnsupportedCrlSignatureAlgorithm,
175
176
    /// The signature algorithm for a signature is not in the set of supported
177
    /// signature algorithms given.
178
    UnsupportedSignatureAlgorithm,
179
180
    /// The CRL signature's algorithm does not match the algorithm of the issuer
181
    /// public key it is being validated for. This may be because the public key
182
    /// algorithm's OID isn't recognized (e.g. DSA), or the public key
183
    /// algorithm's parameters don't match the supported parameters for that
184
    /// algorithm (e.g. ECC keys for unsupported curves), or the public key
185
    /// algorithm and the signature algorithm simply don't match (e.g.
186
    /// verifying an RSA signature with an ECC public key).
187
    UnsupportedCrlSignatureAlgorithmForPublicKey,
188
189
    /// The signature's algorithm does not match the algorithm of the public
190
    /// key it is being validated for. This may be because the public key
191
    /// algorithm's OID isn't recognized (e.g. DSA), or the public key
192
    /// algorithm's parameters don't match the supported parameters for that
193
    /// algorithm (e.g. ECC keys for unsupported curves), or the public key
194
    /// algorithm and the signature algorithm simply don't match (e.g.
195
    /// verifying an RSA signature with an ECC public key).
196
    UnsupportedSignatureAlgorithmForPublicKey,
197
}
198
199
impl Error {
200
    // Compare the Error with the new error by rank, returning the higher rank of the two as
201
    // the most specific error.
202
0
    pub(crate) fn most_specific(self, new: Self) -> Self {
203
        // Assign an error a numeric value ranking it by specificity.
204
0
        if self.rank() >= new.rank() {
205
0
            self
206
        } else {
207
0
            new
208
        }
209
0
    }
210
211
    // Return a numeric indication of how specific the error is, where an error with a higher rank
212
    // is considered more useful to an end user than an error with a lower rank. This is used by
213
    // Error::most_specific to compare two errors in order to return which is more specific.
214
    #[allow(clippy::as_conversions)] // We won't exceed u32 errors.
215
0
    pub(crate) fn rank(&self) -> u32 {
216
0
        match &self {
217
            // Errors related to certificate validity
218
0
            Self::CertNotValidYet | Self::CertExpired => 290,
219
0
            Self::CertNotValidForName => 280,
220
0
            Self::CertRevoked | Self::UnknownRevocationStatus | Self::CrlExpired => 270,
221
0
            Self::InvalidCrlSignatureForPublicKey | Self::InvalidSignatureForPublicKey => 260,
222
0
            Self::SignatureAlgorithmMismatch => 250,
223
0
            Self::RequiredEkuNotFound => 240,
224
0
            Self::NameConstraintViolation => 230,
225
0
            Self::PathLenConstraintViolated => 220,
226
0
            Self::CaUsedAsEndEntity | Self::EndEntityUsedAsCa => 210,
227
0
            Self::IssuerNotCrlSigner => 200,
228
229
            // Errors related to supported features used in an invalid way.
230
0
            Self::InvalidCertValidity => 190,
231
0
            Self::InvalidNetworkMaskConstraint => 180,
232
0
            Self::InvalidSerialNumber => 170,
233
0
            Self::InvalidCrlNumber => 160,
234
235
            // Errors related to unsupported features.
236
            Self::UnsupportedCrlSignatureAlgorithmForPublicKey
237
0
            | Self::UnsupportedSignatureAlgorithmForPublicKey => 150,
238
0
            Self::UnsupportedCrlSignatureAlgorithm | Self::UnsupportedSignatureAlgorithm => 140,
239
0
            Self::UnsupportedCriticalExtension => 130,
240
0
            Self::UnsupportedCertVersion => 130,
241
0
            Self::UnsupportedCrlVersion => 120,
242
0
            Self::UnsupportedDeltaCrl => 110,
243
0
            Self::UnsupportedIndirectCrl => 100,
244
0
            Self::UnsupportedNameType => 95,
245
0
            Self::UnsupportedRevocationReason => 90,
246
0
            Self::UnsupportedRevocationReasonsPartitioning => 80,
247
0
            Self::UnsupportedCrlIssuingDistributionPoint => 70,
248
0
            Self::MaximumPathDepthExceeded => 61,
249
250
            // Errors related to malformed data.
251
0
            Self::MalformedDnsIdentifier => 60,
252
0
            Self::MalformedNameConstraint => 50,
253
0
            Self::MalformedExtensions | Self::TrailingData(_) => 40,
254
0
            Self::ExtensionValueInvalid => 30,
255
256
            // Generic DER errors.
257
0
            Self::BadDerTime => 20,
258
0
            Self::BadDer => 10,
259
260
            // Special case errors - not subject to ranking.
261
0
            Self::MaximumSignatureChecksExceeded => 0,
262
0
            Self::MaximumPathBuildCallsExceeded => 0,
263
0
            Self::MaximumNameConstraintComparisonsExceeded => 0,
264
265
            // Default catch all error - should be renamed in the future.
266
0
            Self::UnknownIssuer => 0,
267
        }
268
0
    }
269
270
    /// Returns true for errors that should be considered fatal during path building. Errors of
271
    /// this class should halt any further path building and be returned immediately.
272
    #[inline]
273
0
    pub(crate) fn is_fatal(&self) -> bool {
274
0
        matches!(
275
0
            self,
276
            Self::MaximumSignatureChecksExceeded
277
                | Self::MaximumPathBuildCallsExceeded
278
                | Self::MaximumNameConstraintComparisonsExceeded
279
        )
280
0
    }
281
}
282
283
impl From<Error> for ControlFlow<Error, Error> {
284
0
    fn from(value: Error) -> Self {
285
0
        match value {
286
            // If an error is fatal, we've exhausted the potential for continued search.
287
0
            err if err.is_fatal() => Self::Break(err),
288
            // Otherwise we've rejected one candidate chain, but may continue to search for others.
289
0
            err => Self::Continue(err),
290
        }
291
0
    }
292
}
293
294
impl fmt::Display for Error {
295
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
296
0
        write!(f, "{:?}", self)
297
0
    }
298
}
299
300
#[cfg(feature = "std")]
301
impl ::std::error::Error for Error {}
302
303
/// Trailing data was found while parsing DER-encoded input for the named type.
304
#[allow(missing_docs)]
305
#[non_exhaustive]
306
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
307
pub enum DerTypeId {
308
    BitString,
309
    Bool,
310
    Certificate,
311
    CertificateExtensions,
312
    CertificateTbsCertificate,
313
    CertRevocationList,
314
    CertRevocationListExtension,
315
    CrlDistributionPoint,
316
    CommonNameInner,
317
    CommonNameOuter,
318
    DistributionPointName,
319
    Extension,
320
    GeneralName,
321
    RevocationReason,
322
    Signature,
323
    SignatureAlgorithm,
324
    SignedData,
325
    SubjectPublicKeyInfo,
326
    Time,
327
    TrustAnchorV1,
328
    TrustAnchorV1TbsCertificate,
329
    U8,
330
    RevokedCertificate,
331
    RevokedCertificateExtension,
332
    RevokedCertEntry,
333
    IssuingDistributionPoint,
334
}