Coverage Report

Created: 2025-05-07 06:59

/rust/registry/src/index.crates.io-6f17d22bba15001f/rustls-0.23.26/src/error.rs
Line
Count
Source (jump to first uncovered line)
1
use alloc::format;
2
use alloc::string::String;
3
use alloc::vec::Vec;
4
use core::fmt;
5
use pki_types::{ServerName, UnixTime};
6
#[cfg(feature = "std")]
7
use std::time::SystemTimeError;
8
9
use crate::enums::{AlertDescription, ContentType, HandshakeType};
10
use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
11
use crate::rand;
12
13
/// rustls reports protocol errors using this type.
14
#[non_exhaustive]
15
#[derive(Debug, PartialEq, Clone)]
16
pub enum Error {
17
    /// We received a TLS message that isn't valid right now.
18
    /// `expect_types` lists the message types we can expect right now.
19
    /// `got_type` is the type we found.  This error is typically
20
    /// caused by a buggy TLS stack (the peer or this one), a broken
21
    /// network, or an attack.
22
    InappropriateMessage {
23
        /// Which types we expected
24
        expect_types: Vec<ContentType>,
25
        /// What type we received
26
        got_type: ContentType,
27
    },
28
29
    /// We received a TLS handshake message that isn't valid right now.
30
    /// `expect_types` lists the handshake message types we can expect
31
    /// right now.  `got_type` is the type we found.
32
    InappropriateHandshakeMessage {
33
        /// Which handshake type we expected
34
        expect_types: Vec<HandshakeType>,
35
        /// What handshake type we received
36
        got_type: HandshakeType,
37
    },
38
39
    /// An error occurred while handling Encrypted Client Hello (ECH).
40
    InvalidEncryptedClientHello(EncryptedClientHelloError),
41
42
    /// The peer sent us a TLS message with invalid contents.
43
    InvalidMessage(InvalidMessage),
44
45
    /// The peer didn't give us any certificates.
46
    NoCertificatesPresented,
47
48
    /// The certificate verifier doesn't support the given type of name.
49
    UnsupportedNameType,
50
51
    /// We couldn't decrypt a message.  This is invariably fatal.
52
    DecryptError,
53
54
    /// We couldn't encrypt a message because it was larger than the allowed message size.
55
    /// This should never happen if the application is using valid record sizes.
56
    EncryptError,
57
58
    /// The peer doesn't support a protocol version/feature we require.
59
    /// The parameter gives a hint as to what version/feature it is.
60
    PeerIncompatible(PeerIncompatible),
61
62
    /// The peer deviated from the standard TLS protocol.
63
    /// The parameter gives a hint where.
64
    PeerMisbehaved(PeerMisbehaved),
65
66
    /// We received a fatal alert.  This means the peer is unhappy.
67
    AlertReceived(AlertDescription),
68
69
    /// We saw an invalid certificate.
70
    ///
71
    /// The contained error is from the certificate validation trait
72
    /// implementation.
73
    InvalidCertificate(CertificateError),
74
75
    /// A provided certificate revocation list (CRL) was invalid.
76
    InvalidCertRevocationList(CertRevocationListError),
77
78
    /// A catch-all error for unlikely errors.
79
    General(String),
80
81
    /// We failed to figure out what time it currently is.
82
    FailedToGetCurrentTime,
83
84
    /// We failed to acquire random bytes from the system.
85
    FailedToGetRandomBytes,
86
87
    /// This function doesn't work until the TLS handshake
88
    /// is complete.
89
    HandshakeNotComplete,
90
91
    /// The peer sent an oversized record/fragment.
92
    PeerSentOversizedRecord,
93
94
    /// An incoming connection did not support any known application protocol.
95
    NoApplicationProtocol,
96
97
    /// The `max_fragment_size` value supplied in configuration was too small,
98
    /// or too large.
99
    BadMaxFragmentSize,
100
101
    /// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
102
    ///
103
    /// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
104
    InconsistentKeys(InconsistentKeys),
105
106
    /// Any other error.
107
    ///
108
    /// This variant should only be used when the error is not better described by a more
109
    /// specific variant. For example, if a custom crypto provider returns a
110
    /// provider specific error.
111
    ///
112
    /// Enums holding this variant will never compare equal to each other.
113
    Other(OtherError),
114
}
115
116
/// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
117
///
118
/// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
119
#[non_exhaustive]
120
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
121
pub enum InconsistentKeys {
122
    /// The public key returned by the [`SigningKey`] does not match the public key information in the certificate.
123
    ///
124
    /// [`SigningKey`]: crate::crypto::signer::SigningKey
125
    KeyMismatch,
126
127
    /// The [`SigningKey`] cannot produce its corresponding public key.
128
    ///
129
    /// [`SigningKey`]: crate::crypto::signer::SigningKey
130
    Unknown,
131
}
132
133
impl From<InconsistentKeys> for Error {
134
    #[inline]
135
0
    fn from(e: InconsistentKeys) -> Self {
136
0
        Self::InconsistentKeys(e)
137
0
    }
138
}
139
140
/// A corrupt TLS message payload that resulted in an error.
141
#[non_exhaustive]
142
#[derive(Debug, Clone, Copy, PartialEq)]
143
144
pub enum InvalidMessage {
145
    /// A certificate payload exceeded rustls's 64KB limit
146
    CertificatePayloadTooLarge,
147
    /// An advertised message was larger then expected.
148
    HandshakePayloadTooLarge,
149
    /// The peer sent us a syntactically incorrect ChangeCipherSpec payload.
150
    InvalidCcs,
151
    /// An unknown content type was encountered during message decoding.
152
    InvalidContentType,
153
    /// A peer sent an invalid certificate status type
154
    InvalidCertificateStatusType,
155
    /// Context was incorrectly attached to a certificate request during a handshake.
156
    InvalidCertRequest,
157
    /// A peer's DH params could not be decoded
158
    InvalidDhParams,
159
    /// A message was zero-length when its record kind forbids it.
160
    InvalidEmptyPayload,
161
    /// A peer sent an unexpected key update request.
162
    InvalidKeyUpdate,
163
    /// A peer's server name could not be decoded
164
    InvalidServerName,
165
    /// A TLS message payload was larger then allowed by the specification.
166
    MessageTooLarge,
167
    /// Message is shorter than the expected length
168
    MessageTooShort,
169
    /// Missing data for the named handshake payload value
170
    MissingData(&'static str),
171
    /// A peer did not advertise its supported key exchange groups.
172
    MissingKeyExchange,
173
    /// A peer sent an empty list of signature schemes
174
    NoSignatureSchemes,
175
    /// Trailing data found for the named handshake payload value
176
    TrailingData(&'static str),
177
    /// A peer sent an unexpected message type.
178
    UnexpectedMessage(&'static str),
179
    /// An unknown TLS protocol was encountered during message decoding.
180
    UnknownProtocolVersion,
181
    /// A peer sent a non-null compression method.
182
    UnsupportedCompression,
183
    /// A peer sent an unknown elliptic curve type.
184
    UnsupportedCurveType,
185
    /// A peer sent an unsupported key exchange algorithm.
186
    UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
187
}
188
189
impl From<InvalidMessage> for Error {
190
    #[inline]
191
0
    fn from(e: InvalidMessage) -> Self {
192
0
        Self::InvalidMessage(e)
193
0
    }
194
}
195
196
#[non_exhaustive]
197
#[allow(missing_docs)]
198
#[derive(Debug, PartialEq, Clone)]
199
/// The set of cases where we failed to make a connection because we thought
200
/// the peer was misbehaving.
201
///
202
/// This is `non_exhaustive`: we might add or stop using items here in minor
203
/// versions.  We also don't document what they mean.  Generally a user of
204
/// rustls shouldn't vary its behaviour on these error codes, and there is
205
/// nothing it can do to improve matters.
206
///
207
/// Please file a bug against rustls if you see `Error::PeerMisbehaved` in
208
/// the wild.
209
pub enum PeerMisbehaved {
210
    AttemptedDowngradeToTls12WhenTls13IsSupported,
211
    BadCertChainExtensions,
212
    DisallowedEncryptedExtension,
213
    DuplicateClientHelloExtensions,
214
    DuplicateEncryptedExtensions,
215
    DuplicateHelloRetryRequestExtensions,
216
    DuplicateNewSessionTicketExtensions,
217
    DuplicateServerHelloExtensions,
218
    DuplicateServerNameTypes,
219
    EarlyDataAttemptedInSecondClientHello,
220
    EarlyDataExtensionWithoutResumption,
221
    EarlyDataOfferedWithVariedCipherSuite,
222
    HandshakeHashVariedAfterRetry,
223
    IllegalHelloRetryRequestWithEmptyCookie,
224
    IllegalHelloRetryRequestWithNoChanges,
225
    IllegalHelloRetryRequestWithOfferedGroup,
226
    IllegalHelloRetryRequestWithUnofferedCipherSuite,
227
    IllegalHelloRetryRequestWithUnofferedNamedGroup,
228
    IllegalHelloRetryRequestWithUnsupportedVersion,
229
    IllegalHelloRetryRequestWithWrongSessionId,
230
    IllegalHelloRetryRequestWithInvalidEch,
231
    IllegalMiddleboxChangeCipherSpec,
232
    IllegalTlsInnerPlaintext,
233
    IncorrectBinder,
234
    InvalidCertCompression,
235
    InvalidMaxEarlyDataSize,
236
    InvalidKeyShare,
237
    KeyEpochWithPendingFragment,
238
    KeyUpdateReceivedInQuicConnection,
239
    MessageInterleavedWithHandshakeMessage,
240
    MissingBinderInPskExtension,
241
    MissingKeyShare,
242
    MissingPskModesExtension,
243
    MissingQuicTransportParameters,
244
    OfferedDuplicateCertificateCompressions,
245
    OfferedDuplicateKeyShares,
246
    OfferedEarlyDataWithOldProtocolVersion,
247
    OfferedEmptyApplicationProtocol,
248
    OfferedIncorrectCompressions,
249
    PskExtensionMustBeLast,
250
    PskExtensionWithMismatchedIdsAndBinders,
251
    RefusedToFollowHelloRetryRequest,
252
    RejectedEarlyDataInterleavedWithHandshakeMessage,
253
    ResumptionAttemptedWithVariedEms,
254
    ResumptionOfferedWithVariedCipherSuite,
255
    ResumptionOfferedWithVariedEms,
256
    ResumptionOfferedWithIncompatibleCipherSuite,
257
    SelectedDifferentCipherSuiteAfterRetry,
258
    SelectedInvalidPsk,
259
    SelectedTls12UsingTls13VersionExtension,
260
    SelectedUnofferedApplicationProtocol,
261
    SelectedUnofferedCertCompression,
262
    SelectedUnofferedCipherSuite,
263
    SelectedUnofferedCompression,
264
    SelectedUnofferedKxGroup,
265
    SelectedUnofferedPsk,
266
    SelectedUnusableCipherSuiteForVersion,
267
    ServerEchoedCompatibilitySessionId,
268
    ServerHelloMustOfferUncompressedEcPoints,
269
    ServerNameDifferedOnRetry,
270
    ServerNameMustContainOneHostName,
271
    SignedKxWithWrongAlgorithm,
272
    SignedHandshakeWithUnadvertisedSigScheme,
273
    TooManyEmptyFragments,
274
    TooManyKeyUpdateRequests,
275
    TooManyRenegotiationRequests,
276
    TooManyWarningAlertsReceived,
277
    TooMuchEarlyDataReceived,
278
    UnexpectedCleartextExtension,
279
    UnsolicitedCertExtension,
280
    UnsolicitedEncryptedExtension,
281
    UnsolicitedSctList,
282
    UnsolicitedServerHelloExtension,
283
    WrongGroupForKeyShare,
284
    UnsolicitedEchExtension,
285
}
286
287
impl From<PeerMisbehaved> for Error {
288
    #[inline]
289
0
    fn from(e: PeerMisbehaved) -> Self {
290
0
        Self::PeerMisbehaved(e)
291
0
    }
292
}
293
294
#[non_exhaustive]
295
#[allow(missing_docs)]
296
#[derive(Debug, PartialEq, Clone)]
297
/// The set of cases where we failed to make a connection because a peer
298
/// doesn't support a TLS version/feature we require.
299
///
300
/// This is `non_exhaustive`: we might add or stop using items here in minor
301
/// versions.
302
pub enum PeerIncompatible {
303
    EcPointsExtensionRequired,
304
    ExtendedMasterSecretExtensionRequired,
305
    IncorrectCertificateTypeExtension,
306
    KeyShareExtensionRequired,
307
    NamedGroupsExtensionRequired,
308
    NoCertificateRequestSignatureSchemesInCommon,
309
    NoCipherSuitesInCommon,
310
    NoEcPointFormatsInCommon,
311
    NoKxGroupsInCommon,
312
    NoSignatureSchemesInCommon,
313
    NullCompressionRequired,
314
    ServerDoesNotSupportTls12Or13,
315
    ServerSentHelloRetryRequestWithUnknownExtension,
316
    ServerTlsVersionIsDisabledByOurConfig,
317
    SignatureAlgorithmsExtensionRequired,
318
    SupportedVersionsExtensionRequired,
319
    Tls12NotOffered,
320
    Tls12NotOfferedOrEnabled,
321
    Tls13RequiredForQuic,
322
    UncompressedEcPointsRequired,
323
    UnsolicitedCertificateTypeExtension,
324
    ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
325
}
326
327
impl From<PeerIncompatible> for Error {
328
    #[inline]
329
0
    fn from(e: PeerIncompatible) -> Self {
330
0
        Self::PeerIncompatible(e)
331
0
    }
332
}
333
334
#[non_exhaustive]
335
#[derive(Debug, Clone)]
336
/// The ways in which certificate validators can express errors.
337
///
338
/// Note that the rustls TLS protocol code interprets specifically these
339
/// error codes to send specific TLS alerts.  Therefore, if a
340
/// custom certificate validator uses incorrect errors the library as
341
/// a whole will send alerts that do not match the standard (this is usually
342
/// a minor issue, but could be misleading).
343
pub enum CertificateError {
344
    /// The certificate is not correctly encoded.
345
    BadEncoding,
346
347
    /// The current time is after the `notAfter` time in the certificate.
348
    Expired,
349
350
    /// The current time is after the `notAfter` time in the certificate.
351
    ///
352
    /// This variant is semantically the same as `Expired`, but includes
353
    /// extra data to improve error reports.
354
    ExpiredContext {
355
        /// The validation time.
356
        time: UnixTime,
357
        /// The `notAfter` time of the certificate.
358
        not_after: UnixTime,
359
    },
360
361
    /// The current time is before the `notBefore` time in the certificate.
362
    NotValidYet,
363
364
    /// The current time is before the `notBefore` time in the certificate.
365
    ///
366
    /// This variant is semantically the same as `NotValidYet`, but includes
367
    /// extra data to improve error reports.
368
    NotValidYetContext {
369
        /// The validation time.
370
        time: UnixTime,
371
        /// The `notBefore` time of the certificate.
372
        not_before: UnixTime,
373
    },
374
375
    /// The certificate has been revoked.
376
    Revoked,
377
378
    /// The certificate contains an extension marked critical, but it was
379
    /// not processed by the certificate validator.
380
    UnhandledCriticalExtension,
381
382
    /// The certificate chain is not issued by a known root certificate.
383
    UnknownIssuer,
384
385
    /// The certificate's revocation status could not be determined.
386
    UnknownRevocationStatus,
387
388
    /// The certificate's revocation status could not be determined, because the CRL is expired.
389
    ExpiredRevocationList,
390
391
    /// The certificate's revocation status could not be determined, because the CRL is expired.
392
    ///
393
    /// This variant is semantically the same as `ExpiredRevocationList`, but includes
394
    /// extra data to improve error reports.
395
    ExpiredRevocationListContext {
396
        /// The validation time.
397
        time: UnixTime,
398
        /// The nextUpdate time of the CRL.
399
        next_update: UnixTime,
400
    },
401
402
    /// A certificate is not correctly signed by the key of its alleged
403
    /// issuer.
404
    BadSignature,
405
406
    /// The subject names in an end-entity certificate do not include
407
    /// the expected name.
408
    NotValidForName,
409
410
    /// The subject names in an end-entity certificate do not include
411
    /// the expected name.
412
    ///
413
    /// This variant is semantically the same as `NotValidForName`, but includes
414
    /// extra data to improve error reports.
415
    NotValidForNameContext {
416
        /// Expected server name.
417
        expected: ServerName<'static>,
418
419
        /// The names presented in the end entity certificate.
420
        ///
421
        /// These are the subject names as present in the leaf certificate and may contain DNS names
422
        /// with or without a wildcard label as well as IP address names.
423
        presented: Vec<String>,
424
    },
425
426
    /// The certificate is being used for a different purpose than allowed.
427
    InvalidPurpose,
428
429
    /// The certificate is valid, but the handshake is rejected for other
430
    /// reasons.
431
    ApplicationVerificationFailure,
432
433
    /// Any other error.
434
    ///
435
    /// This can be used by custom verifiers to expose the underlying error
436
    /// (where they are not better described by the more specific errors
437
    /// above).
438
    ///
439
    /// It is also used by the default verifier in case its error is
440
    /// not covered by the above common cases.
441
    ///
442
    /// Enums holding this variant will never compare equal to each other.
443
    Other(OtherError),
444
}
445
446
impl PartialEq<Self> for CertificateError {
447
0
    fn eq(&self, other: &Self) -> bool {
448
        use CertificateError::*;
449
        #[allow(clippy::match_like_matches_macro)]
450
0
        match (self, other) {
451
0
            (BadEncoding, BadEncoding) => true,
452
0
            (Expired, Expired) => true,
453
            (
454
                ExpiredContext {
455
0
                    time: left_time,
456
0
                    not_after: left_not_after,
457
0
                },
458
0
                ExpiredContext {
459
0
                    time: right_time,
460
0
                    not_after: right_not_after,
461
0
                },
462
0
            ) => (left_time, left_not_after) == (right_time, right_not_after),
463
0
            (NotValidYet, NotValidYet) => true,
464
            (
465
                NotValidYetContext {
466
0
                    time: left_time,
467
0
                    not_before: left_not_before,
468
0
                },
469
0
                NotValidYetContext {
470
0
                    time: right_time,
471
0
                    not_before: right_not_before,
472
0
                },
473
0
            ) => (left_time, left_not_before) == (right_time, right_not_before),
474
0
            (Revoked, Revoked) => true,
475
0
            (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
476
0
            (UnknownIssuer, UnknownIssuer) => true,
477
0
            (BadSignature, BadSignature) => true,
478
0
            (NotValidForName, NotValidForName) => true,
479
            (
480
                NotValidForNameContext {
481
0
                    expected: left_expected,
482
0
                    presented: left_presented,
483
0
                },
484
0
                NotValidForNameContext {
485
0
                    expected: right_expected,
486
0
                    presented: right_presented,
487
0
                },
488
0
            ) => (left_expected, left_presented) == (right_expected, right_presented),
489
0
            (InvalidPurpose, InvalidPurpose) => true,
490
0
            (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
491
0
            (UnknownRevocationStatus, UnknownRevocationStatus) => true,
492
0
            (ExpiredRevocationList, ExpiredRevocationList) => true,
493
            (
494
                ExpiredRevocationListContext {
495
0
                    time: left_time,
496
0
                    next_update: left_next_update,
497
0
                },
498
0
                ExpiredRevocationListContext {
499
0
                    time: right_time,
500
0
                    next_update: right_next_update,
501
0
                },
502
0
            ) => (left_time, left_next_update) == (right_time, right_next_update),
503
0
            _ => false,
504
        }
505
0
    }
506
}
507
508
// The following mapping are heavily referenced in:
509
// * [OpenSSL Implementation](https://github.com/openssl/openssl/blob/45bb98bfa223efd3258f445ad443f878011450f0/ssl/statem/statem_lib.c#L1434)
510
// * [BoringSSL Implementation](https://github.com/google/boringssl/blob/583c60bd4bf76d61b2634a58bcda99a92de106cb/ssl/ssl_x509.cc#L1323)
511
impl From<CertificateError> for AlertDescription {
512
0
    fn from(e: CertificateError) -> Self {
513
        use CertificateError::*;
514
0
        match e {
515
            BadEncoding
516
            | UnhandledCriticalExtension
517
            | NotValidForName
518
0
            | NotValidForNameContext { .. } => Self::BadCertificate,
519
            // RFC 5246/RFC 8446
520
            // certificate_expired
521
            //  A certificate has expired or **is not currently valid**.
522
            Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
523
0
                Self::CertificateExpired
524
            }
525
0
            Revoked => Self::CertificateRevoked,
526
            // OpenSSL, BoringSSL and AWS-LC all generate an Unknown CA alert for
527
            // the case where revocation status can not be determined, so we do the same here.
528
            UnknownIssuer
529
            | UnknownRevocationStatus
530
            | ExpiredRevocationList
531
0
            | ExpiredRevocationListContext { .. } => Self::UnknownCA,
532
0
            BadSignature => Self::DecryptError,
533
0
            InvalidPurpose => Self::UnsupportedCertificate,
534
0
            ApplicationVerificationFailure => Self::AccessDenied,
535
            // RFC 5246/RFC 8446
536
            // certificate_unknown
537
            //  Some other (unspecified) issue arose in processing the
538
            //  certificate, rendering it unacceptable.
539
0
            Other(..) => Self::CertificateUnknown,
540
        }
541
0
    }
542
}
543
544
impl fmt::Display for CertificateError {
545
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546
0
        match self {
547
            #[cfg(feature = "std")]
548
            Self::NotValidForNameContext {
549
0
                expected,
550
0
                presented,
551
0
            } => {
552
0
                write!(
553
0
                    f,
554
0
                    "certificate not valid for name {:?}; certificate ",
555
0
                    expected.to_str()
556
0
                )?;
557
558
0
                match presented.as_slice() {
559
0
                    &[] => write!(
560
0
                        f,
561
0
                        "is not valid for any names (according to its subjectAltName extension)"
562
0
                    ),
563
0
                    [one] => write!(f, "is only valid for {}", one),
564
0
                    many => {
565
0
                        write!(f, "is only valid for ")?;
566
567
0
                        let n = many.len();
568
0
                        let all_but_last = &many[..n - 1];
569
0
                        let last = &many[n - 1];
570
571
0
                        for (i, name) in all_but_last.iter().enumerate() {
572
0
                            write!(f, "{}", name)?;
573
0
                            if i < n - 2 {
574
0
                                write!(f, ", ")?;
575
0
                            }
576
                        }
577
0
                        write!(f, " or {}", last)
578
                    }
579
                }
580
            }
581
582
0
            Self::ExpiredContext { time, not_after } => write!(
583
0
                f,
584
0
                "certificate expired: verification time {} (UNIX), \
585
0
                 but certificate is not valid after {} \
586
0
                 ({} seconds ago)",
587
0
                time.as_secs(),
588
0
                not_after.as_secs(),
589
0
                time.as_secs()
590
0
                    .saturating_sub(not_after.as_secs())
591
0
            ),
592
593
0
            Self::NotValidYetContext { time, not_before } => write!(
594
0
                f,
595
0
                "certificate not valid yet: verification time {} (UNIX), \
596
0
                 but certificate is not valid before {} \
597
0
                 ({} seconds in future)",
598
0
                time.as_secs(),
599
0
                not_before.as_secs(),
600
0
                not_before
601
0
                    .as_secs()
602
0
                    .saturating_sub(time.as_secs())
603
0
            ),
604
605
0
            Self::ExpiredRevocationListContext { time, next_update } => write!(
606
0
                f,
607
0
                "certificate revocation list expired: \
608
0
                 verification time {} (UNIX), \
609
0
                 but CRL is not valid after {} \
610
0
                 ({} seconds ago)",
611
0
                time.as_secs(),
612
0
                next_update.as_secs(),
613
0
                time.as_secs()
614
0
                    .saturating_sub(next_update.as_secs())
615
0
            ),
616
617
0
            other => write!(f, "{:?}", other),
618
        }
619
0
    }
620
}
621
622
impl From<CertificateError> for Error {
623
    #[inline]
624
0
    fn from(e: CertificateError) -> Self {
625
0
        Self::InvalidCertificate(e)
626
0
    }
627
}
628
629
#[non_exhaustive]
630
#[derive(Debug, Clone)]
631
/// The ways in which a certificate revocation list (CRL) can be invalid.
632
pub enum CertRevocationListError {
633
    /// The CRL had a bad, or unsupported signature from its issuer.
634
    BadSignature,
635
636
    /// The CRL contained an invalid CRL number.
637
    InvalidCrlNumber,
638
639
    /// The CRL contained a revoked certificate with an invalid serial number.
640
    InvalidRevokedCertSerialNumber,
641
642
    /// The CRL issuer does not specify the cRLSign key usage.
643
    IssuerInvalidForCrl,
644
645
    /// The CRL is invalid for some other reason.
646
    ///
647
    /// Enums holding this variant will never compare equal to each other.
648
    Other(OtherError),
649
650
    /// The CRL is not correctly encoded.
651
    ParseError,
652
653
    /// The CRL is not a v2 X.509 CRL.
654
    UnsupportedCrlVersion,
655
656
    /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
657
    UnsupportedCriticalExtension,
658
659
    /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
660
    UnsupportedDeltaCrl,
661
662
    /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
663
    /// other than the issuer of the CRL.
664
    UnsupportedIndirectCrl,
665
666
    /// The CRL contained a revoked certificate with an unsupported revocation reason.
667
    /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
668
    ///
669
    /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
670
    UnsupportedRevocationReason,
671
}
672
673
impl PartialEq<Self> for CertRevocationListError {
674
0
    fn eq(&self, other: &Self) -> bool {
675
        use CertRevocationListError::*;
676
        #[allow(clippy::match_like_matches_macro)]
677
0
        match (self, other) {
678
0
            (BadSignature, BadSignature) => true,
679
0
            (InvalidCrlNumber, InvalidCrlNumber) => true,
680
0
            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
681
0
            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
682
0
            (ParseError, ParseError) => true,
683
0
            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
684
0
            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
685
0
            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
686
0
            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
687
0
            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
688
0
            _ => false,
689
        }
690
0
    }
691
}
692
693
impl From<CertRevocationListError> for Error {
694
    #[inline]
695
0
    fn from(e: CertRevocationListError) -> Self {
696
0
        Self::InvalidCertRevocationList(e)
697
0
    }
698
}
699
700
#[non_exhaustive]
701
#[derive(Debug, Clone, Eq, PartialEq)]
702
/// An error that occurred while handling Encrypted Client Hello (ECH).
703
pub enum EncryptedClientHelloError {
704
    /// The provided ECH configuration list was invalid.
705
    InvalidConfigList,
706
    /// No compatible ECH configuration.
707
    NoCompatibleConfig,
708
    /// The client configuration has server name indication (SNI) disabled.
709
    SniRequired,
710
}
711
712
impl From<EncryptedClientHelloError> for Error {
713
    #[inline]
714
0
    fn from(e: EncryptedClientHelloError) -> Self {
715
0
        Self::InvalidEncryptedClientHello(e)
716
0
    }
717
}
718
719
0
fn join<T: fmt::Debug>(items: &[T]) -> String {
720
0
    items
721
0
        .iter()
722
0
        .map(|x| format!("{:?}", x))
Unexecuted instantiation: rustls::error::join::<rustls::enums::ContentType>::{closure#0}
Unexecuted instantiation: rustls::error::join::<rustls::enums::HandshakeType>::{closure#0}
723
0
        .collect::<Vec<String>>()
724
0
        .join(" or ")
725
0
}
Unexecuted instantiation: rustls::error::join::<rustls::enums::ContentType>
Unexecuted instantiation: rustls::error::join::<rustls::enums::HandshakeType>
726
727
impl fmt::Display for Error {
728
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
729
0
        match self {
730
            Self::InappropriateMessage {
731
0
                expect_types,
732
0
                got_type,
733
0
            } => write!(
734
0
                f,
735
0
                "received unexpected message: got {:?} when expecting {}",
736
0
                got_type,
737
0
                join::<ContentType>(expect_types)
738
0
            ),
739
            Self::InappropriateHandshakeMessage {
740
0
                expect_types,
741
0
                got_type,
742
0
            } => write!(
743
0
                f,
744
0
                "received unexpected handshake message: got {:?} when expecting {}",
745
0
                got_type,
746
0
                join::<HandshakeType>(expect_types)
747
0
            ),
748
0
            Self::InvalidMessage(typ) => {
749
0
                write!(f, "received corrupt message of type {:?}", typ)
750
            }
751
0
            Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {:?}", why),
752
0
            Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {:?}", why),
753
0
            Self::AlertReceived(alert) => write!(f, "received fatal alert: {:?}", alert),
754
0
            Self::InvalidCertificate(err) => {
755
0
                write!(f, "invalid peer certificate: {}", err)
756
            }
757
0
            Self::InvalidCertRevocationList(err) => {
758
0
                write!(f, "invalid certificate revocation list: {:?}", err)
759
            }
760
0
            Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
761
0
            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
762
0
            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
763
0
            Self::InvalidEncryptedClientHello(err) => {
764
0
                write!(f, "encrypted client hello failure: {:?}", err)
765
            }
766
0
            Self::EncryptError => write!(f, "cannot encrypt message"),
767
0
            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
768
0
            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
769
0
            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
770
0
            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
771
0
            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
772
            Self::BadMaxFragmentSize => {
773
0
                write!(f, "the supplied max_fragment_size was too small or large")
774
            }
775
0
            Self::InconsistentKeys(why) => {
776
0
                write!(f, "keys may not be consistent: {:?}", why)
777
            }
778
0
            Self::General(err) => write!(f, "unexpected error: {}", err),
779
0
            Self::Other(err) => write!(f, "other error: {}", err),
780
        }
781
0
    }
782
}
783
784
#[cfg(feature = "std")]
785
impl From<SystemTimeError> for Error {
786
    #[inline]
787
0
    fn from(_: SystemTimeError) -> Self {
788
0
        Self::FailedToGetCurrentTime
789
0
    }
790
}
791
792
#[cfg(feature = "std")]
793
impl std::error::Error for Error {}
794
795
impl From<rand::GetRandomFailed> for Error {
796
0
    fn from(_: rand::GetRandomFailed) -> Self {
797
0
        Self::FailedToGetRandomBytes
798
0
    }
799
}
800
801
mod other_error {
802
    use core::fmt;
803
    #[cfg(feature = "std")]
804
    use std::error::Error as StdError;
805
806
    use super::Error;
807
    #[cfg(feature = "std")]
808
    use crate::sync::Arc;
809
810
    /// Any other error that cannot be expressed by a more specific [`Error`] variant.
811
    ///
812
    /// For example, an `OtherError` could be produced by a custom crypto provider
813
    /// exposing a provider specific error.
814
    ///
815
    /// Enums holding this type will never compare equal to each other.
816
    #[derive(Debug, Clone)]
817
    pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
818
819
    impl PartialEq<Self> for OtherError {
820
0
        fn eq(&self, _other: &Self) -> bool {
821
0
            false
822
0
        }
823
    }
824
825
    impl From<OtherError> for Error {
826
0
        fn from(value: OtherError) -> Self {
827
0
            Self::Other(value)
828
0
        }
829
    }
830
831
    impl fmt::Display for OtherError {
832
0
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
833
0
            #[cfg(feature = "std")]
834
0
            {
835
0
                write!(f, "{}", self.0)
836
0
            }
837
0
            #[cfg(not(feature = "std"))]
838
0
            {
839
0
                f.write_str("no further information available")
840
0
            }
841
0
        }
842
    }
843
844
    #[cfg(feature = "std")]
845
    impl StdError for OtherError {
846
0
        fn source(&self) -> Option<&(dyn StdError + 'static)> {
847
0
            Some(self.0.as_ref())
848
0
        }
849
    }
850
}
851
852
pub use other_error::OtherError;
853
854
#[cfg(test)]
855
mod tests {
856
    use core::time::Duration;
857
    use std::prelude::v1::*;
858
    use std::{println, vec};
859
860
    use super::{
861
        CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError, UnixTime,
862
    };
863
    #[cfg(feature = "std")]
864
    use crate::sync::Arc;
865
    use pki_types::ServerName;
866
867
    #[test]
868
    fn certificate_error_equality() {
869
        use super::CertificateError::*;
870
        assert_eq!(BadEncoding, BadEncoding);
871
        assert_eq!(Expired, Expired);
872
        let context = ExpiredContext {
873
            time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
874
            not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
875
        };
876
        assert_eq!(context, context);
877
        assert_ne!(
878
            context,
879
            ExpiredContext {
880
                time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
881
                not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
882
            }
883
        );
884
        assert_ne!(
885
            context,
886
            ExpiredContext {
887
                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
888
                not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
889
            }
890
        );
891
        assert_eq!(NotValidYet, NotValidYet);
892
        let context = NotValidYetContext {
893
            time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
894
            not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
895
        };
896
        assert_eq!(context, context);
897
        assert_ne!(
898
            context,
899
            NotValidYetContext {
900
                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
901
                not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
902
            }
903
        );
904
        assert_ne!(
905
            context,
906
            NotValidYetContext {
907
                time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
908
                not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
909
            }
910
        );
911
        assert_eq!(Revoked, Revoked);
912
        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
913
        assert_eq!(UnknownIssuer, UnknownIssuer);
914
        assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
915
        assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
916
        let context = ExpiredRevocationListContext {
917
            time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
918
            next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
919
        };
920
        assert_eq!(context, context);
921
        assert_ne!(
922
            context,
923
            ExpiredRevocationListContext {
924
                time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
925
                next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
926
            }
927
        );
928
        assert_ne!(
929
            context,
930
            ExpiredRevocationListContext {
931
                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
932
                next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
933
            }
934
        );
935
        assert_eq!(BadSignature, BadSignature);
936
        assert_eq!(NotValidForName, NotValidForName);
937
        let context = NotValidForNameContext {
938
            expected: ServerName::try_from("example.com")
939
                .unwrap()
940
                .to_owned(),
941
            presented: vec!["other.com".into()],
942
        };
943
        assert_eq!(context, context);
944
        assert_ne!(
945
            context,
946
            NotValidForNameContext {
947
                expected: ServerName::try_from("example.com")
948
                    .unwrap()
949
                    .to_owned(),
950
                presented: vec![]
951
            }
952
        );
953
        assert_ne!(
954
            context,
955
            NotValidForNameContext {
956
                expected: ServerName::try_from("huh.com")
957
                    .unwrap()
958
                    .to_owned(),
959
                presented: vec!["other.com".into()],
960
            }
961
        );
962
        assert_eq!(InvalidPurpose, InvalidPurpose);
963
        assert_eq!(
964
            ApplicationVerificationFailure,
965
            ApplicationVerificationFailure
966
        );
967
        let other = Other(OtherError(
968
            #[cfg(feature = "std")]
969
            Arc::from(Box::from("")),
970
        ));
971
        assert_ne!(other, other);
972
        assert_ne!(BadEncoding, Expired);
973
    }
974
975
    #[test]
976
    fn crl_error_equality() {
977
        use super::CertRevocationListError::*;
978
        assert_eq!(BadSignature, BadSignature);
979
        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
980
        assert_eq!(
981
            InvalidRevokedCertSerialNumber,
982
            InvalidRevokedCertSerialNumber
983
        );
984
        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
985
        assert_eq!(ParseError, ParseError);
986
        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
987
        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
988
        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
989
        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
990
        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
991
        let other = Other(OtherError(
992
            #[cfg(feature = "std")]
993
            Arc::from(Box::from("")),
994
        ));
995
        assert_ne!(other, other);
996
        assert_ne!(BadSignature, InvalidCrlNumber);
997
    }
998
999
    #[test]
1000
    #[cfg(feature = "std")]
1001
    fn other_error_equality() {
1002
        let other_error = OtherError(Arc::from(Box::from("")));
1003
        assert_ne!(other_error, other_error);
1004
        let other: Error = other_error.into();
1005
        assert_ne!(other, other);
1006
    }
1007
1008
    #[test]
1009
    fn smoke() {
1010
        use crate::enums::{AlertDescription, ContentType, HandshakeType};
1011
1012
        let all = vec![
1013
            Error::InappropriateMessage {
1014
                expect_types: vec![ContentType::Alert],
1015
                got_type: ContentType::Handshake,
1016
            },
1017
            Error::InappropriateHandshakeMessage {
1018
                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
1019
                got_type: HandshakeType::ServerHello,
1020
            },
1021
            Error::InvalidMessage(InvalidMessage::InvalidCcs),
1022
            Error::NoCertificatesPresented,
1023
            Error::DecryptError,
1024
            super::PeerIncompatible::Tls12NotOffered.into(),
1025
            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
1026
            Error::AlertReceived(AlertDescription::ExportRestriction),
1027
            super::CertificateError::Expired.into(),
1028
            super::CertificateError::NotValidForNameContext {
1029
                expected: ServerName::try_from("example.com")
1030
                    .unwrap()
1031
                    .to_owned(),
1032
                presented: vec![],
1033
            }
1034
            .into(),
1035
            super::CertificateError::NotValidForNameContext {
1036
                expected: ServerName::try_from("example.com")
1037
                    .unwrap()
1038
                    .to_owned(),
1039
                presented: vec!["DnsName(\"hello.com\")".into()],
1040
            }
1041
            .into(),
1042
            super::CertificateError::NotValidForNameContext {
1043
                expected: ServerName::try_from("example.com")
1044
                    .unwrap()
1045
                    .to_owned(),
1046
                presented: vec![
1047
                    "DnsName(\"hello.com\")".into(),
1048
                    "DnsName(\"goodbye.com\")".into(),
1049
                ],
1050
            }
1051
            .into(),
1052
            super::CertificateError::NotValidYetContext {
1053
                time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1054
                not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1055
            }
1056
            .into(),
1057
            super::CertificateError::ExpiredContext {
1058
                time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1059
                not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1060
            }
1061
            .into(),
1062
            super::CertificateError::ExpiredRevocationListContext {
1063
                time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1064
                next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1065
            }
1066
            .into(),
1067
            Error::General("undocumented error".to_string()),
1068
            Error::FailedToGetCurrentTime,
1069
            Error::FailedToGetRandomBytes,
1070
            Error::HandshakeNotComplete,
1071
            Error::PeerSentOversizedRecord,
1072
            Error::NoApplicationProtocol,
1073
            Error::BadMaxFragmentSize,
1074
            Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
1075
            Error::InconsistentKeys(InconsistentKeys::Unknown),
1076
            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
1077
            Error::Other(OtherError(
1078
                #[cfg(feature = "std")]
1079
                Arc::from(Box::from("")),
1080
            )),
1081
        ];
1082
1083
        for err in all {
1084
            println!("{:?}:", err);
1085
            println!("  fmt '{}'", err);
1086
        }
1087
    }
1088
1089
    #[test]
1090
    fn rand_error_mapping() {
1091
        use super::rand;
1092
        let err: Error = rand::GetRandomFailed.into();
1093
        assert_eq!(err, Error::FailedToGetRandomBytes);
1094
    }
1095
1096
    #[cfg(feature = "std")]
1097
    #[test]
1098
    fn time_error_mapping() {
1099
        use std::time::SystemTime;
1100
1101
        let time_error = SystemTime::UNIX_EPOCH
1102
            .duration_since(SystemTime::now())
1103
            .unwrap_err();
1104
        let err: Error = time_error.into();
1105
        assert_eq!(err, Error::FailedToGetCurrentTime);
1106
    }
1107
}