Coverage Report

Created: 2026-02-14 06:16

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/rust/registry/src/index.crates.io-1949cf8c6b5b557f/rustls-0.23.23/src/error.rs
Line
Count
Source
1
use alloc::format;
2
use alloc::string::String;
3
use alloc::vec::Vec;
4
use core::fmt;
5
#[cfg(feature = "std")]
6
use std::time::SystemTimeError;
7
8
use crate::enums::{AlertDescription, ContentType, HandshakeType};
9
use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
10
use crate::rand;
11
12
/// rustls reports protocol errors using this type.
13
#[non_exhaustive]
14
#[derive(Debug, PartialEq, Clone)]
15
pub enum Error {
16
    /// We received a TLS message that isn't valid right now.
17
    /// `expect_types` lists the message types we can expect right now.
18
    /// `got_type` is the type we found.  This error is typically
19
    /// caused by a buggy TLS stack (the peer or this one), a broken
20
    /// network, or an attack.
21
    InappropriateMessage {
22
        /// Which types we expected
23
        expect_types: Vec<ContentType>,
24
        /// What type we received
25
        got_type: ContentType,
26
    },
27
28
    /// We received a TLS handshake message that isn't valid right now.
29
    /// `expect_types` lists the handshake message types we can expect
30
    /// right now.  `got_type` is the type we found.
31
    InappropriateHandshakeMessage {
32
        /// Which handshake type we expected
33
        expect_types: Vec<HandshakeType>,
34
        /// What handshake type we received
35
        got_type: HandshakeType,
36
    },
37
38
    /// An error occurred while handling Encrypted Client Hello (ECH).
39
    InvalidEncryptedClientHello(EncryptedClientHelloError),
40
41
    /// The peer sent us a TLS message with invalid contents.
42
    InvalidMessage(InvalidMessage),
43
44
    /// The peer didn't give us any certificates.
45
    NoCertificatesPresented,
46
47
    /// The certificate verifier doesn't support the given type of name.
48
    UnsupportedNameType,
49
50
    /// We couldn't decrypt a message.  This is invariably fatal.
51
    DecryptError,
52
53
    /// We couldn't encrypt a message because it was larger than the allowed message size.
54
    /// This should never happen if the application is using valid record sizes.
55
    EncryptError,
56
57
    /// The peer doesn't support a protocol version/feature we require.
58
    /// The parameter gives a hint as to what version/feature it is.
59
    PeerIncompatible(PeerIncompatible),
60
61
    /// The peer deviated from the standard TLS protocol.
62
    /// The parameter gives a hint where.
63
    PeerMisbehaved(PeerMisbehaved),
64
65
    /// We received a fatal alert.  This means the peer is unhappy.
66
    AlertReceived(AlertDescription),
67
68
    /// We saw an invalid certificate.
69
    ///
70
    /// The contained error is from the certificate validation trait
71
    /// implementation.
72
    InvalidCertificate(CertificateError),
73
74
    /// A provided certificate revocation list (CRL) was invalid.
75
    InvalidCertRevocationList(CertRevocationListError),
76
77
    /// A catch-all error for unlikely errors.
78
    General(String),
79
80
    /// We failed to figure out what time it currently is.
81
    FailedToGetCurrentTime,
82
83
    /// We failed to acquire random bytes from the system.
84
    FailedToGetRandomBytes,
85
86
    /// This function doesn't work until the TLS handshake
87
    /// is complete.
88
    HandshakeNotComplete,
89
90
    /// The peer sent an oversized record/fragment.
91
    PeerSentOversizedRecord,
92
93
    /// An incoming connection did not support any known application protocol.
94
    NoApplicationProtocol,
95
96
    /// The `max_fragment_size` value supplied in configuration was too small,
97
    /// or too large.
98
    BadMaxFragmentSize,
99
100
    /// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
101
    ///
102
    /// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
103
    InconsistentKeys(InconsistentKeys),
104
105
    /// Any other error.
106
    ///
107
    /// This variant should only be used when the error is not better described by a more
108
    /// specific variant. For example, if a custom crypto provider returns a
109
    /// provider specific error.
110
    ///
111
    /// Enums holding this variant will never compare equal to each other.
112
    Other(OtherError),
113
}
114
115
/// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
116
///
117
/// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
118
#[non_exhaustive]
119
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
120
pub enum InconsistentKeys {
121
    /// The public key returned by the [`SigningKey`] does not match the public key information in the certificate.
122
    ///
123
    /// [`SigningKey`]: crate::crypto::signer::SigningKey
124
    KeyMismatch,
125
126
    /// The [`SigningKey`] cannot produce its corresponding public key.
127
    ///
128
    /// [`SigningKey`]: crate::crypto::signer::SigningKey
129
    Unknown,
130
}
131
132
impl From<InconsistentKeys> for Error {
133
    #[inline]
134
0
    fn from(e: InconsistentKeys) -> Self {
135
0
        Self::InconsistentKeys(e)
136
0
    }
137
}
138
139
/// A corrupt TLS message payload that resulted in an error.
140
#[non_exhaustive]
141
#[derive(Debug, Clone, Copy, PartialEq)]
142
143
pub enum InvalidMessage {
144
    /// A certificate payload exceeded rustls's 64KB limit
145
    CertificatePayloadTooLarge,
146
    /// An advertised message was larger then expected.
147
    HandshakePayloadTooLarge,
148
    /// The peer sent us a syntactically incorrect ChangeCipherSpec payload.
149
    InvalidCcs,
150
    /// An unknown content type was encountered during message decoding.
151
    InvalidContentType,
152
    /// A peer sent an invalid certificate status type
153
    InvalidCertificateStatusType,
154
    /// Context was incorrectly attached to a certificate request during a handshake.
155
    InvalidCertRequest,
156
    /// A peer's DH params could not be decoded
157
    InvalidDhParams,
158
    /// A message was zero-length when its record kind forbids it.
159
    InvalidEmptyPayload,
160
    /// A peer sent an unexpected key update request.
161
    InvalidKeyUpdate,
162
    /// A peer's server name could not be decoded
163
    InvalidServerName,
164
    /// A TLS message payload was larger then allowed by the specification.
165
    MessageTooLarge,
166
    /// Message is shorter than the expected length
167
    MessageTooShort,
168
    /// Missing data for the named handshake payload value
169
    MissingData(&'static str),
170
    /// A peer did not advertise its supported key exchange groups.
171
    MissingKeyExchange,
172
    /// A peer sent an empty list of signature schemes
173
    NoSignatureSchemes,
174
    /// Trailing data found for the named handshake payload value
175
    TrailingData(&'static str),
176
    /// A peer sent an unexpected message type.
177
    UnexpectedMessage(&'static str),
178
    /// An unknown TLS protocol was encountered during message decoding.
179
    UnknownProtocolVersion,
180
    /// A peer sent a non-null compression method.
181
    UnsupportedCompression,
182
    /// A peer sent an unknown elliptic curve type.
183
    UnsupportedCurveType,
184
    /// A peer sent an unsupported key exchange algorithm.
185
    UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
186
}
187
188
impl From<InvalidMessage> for Error {
189
    #[inline]
190
0
    fn from(e: InvalidMessage) -> Self {
191
0
        Self::InvalidMessage(e)
192
0
    }
193
}
194
195
#[non_exhaustive]
196
#[allow(missing_docs)]
197
#[derive(Debug, PartialEq, Clone)]
198
/// The set of cases where we failed to make a connection because we thought
199
/// the peer was misbehaving.
200
///
201
/// This is `non_exhaustive`: we might add or stop using items here in minor
202
/// versions.  We also don't document what they mean.  Generally a user of
203
/// rustls shouldn't vary its behaviour on these error codes, and there is
204
/// nothing it can do to improve matters.
205
///
206
/// Please file a bug against rustls if you see `Error::PeerMisbehaved` in
207
/// the wild.
208
pub enum PeerMisbehaved {
209
    AttemptedDowngradeToTls12WhenTls13IsSupported,
210
    BadCertChainExtensions,
211
    DisallowedEncryptedExtension,
212
    DuplicateClientHelloExtensions,
213
    DuplicateEncryptedExtensions,
214
    DuplicateHelloRetryRequestExtensions,
215
    DuplicateNewSessionTicketExtensions,
216
    DuplicateServerHelloExtensions,
217
    DuplicateServerNameTypes,
218
    EarlyDataAttemptedInSecondClientHello,
219
    EarlyDataExtensionWithoutResumption,
220
    EarlyDataOfferedWithVariedCipherSuite,
221
    HandshakeHashVariedAfterRetry,
222
    IllegalHelloRetryRequestWithEmptyCookie,
223
    IllegalHelloRetryRequestWithNoChanges,
224
    IllegalHelloRetryRequestWithOfferedGroup,
225
    IllegalHelloRetryRequestWithUnofferedCipherSuite,
226
    IllegalHelloRetryRequestWithUnofferedNamedGroup,
227
    IllegalHelloRetryRequestWithUnsupportedVersion,
228
    IllegalHelloRetryRequestWithWrongSessionId,
229
    IllegalHelloRetryRequestWithInvalidEch,
230
    IllegalMiddleboxChangeCipherSpec,
231
    IllegalTlsInnerPlaintext,
232
    IncorrectBinder,
233
    InvalidCertCompression,
234
    InvalidMaxEarlyDataSize,
235
    InvalidKeyShare,
236
    KeyEpochWithPendingFragment,
237
    KeyUpdateReceivedInQuicConnection,
238
    MessageInterleavedWithHandshakeMessage,
239
    MissingBinderInPskExtension,
240
    MissingKeyShare,
241
    MissingPskModesExtension,
242
    MissingQuicTransportParameters,
243
    OfferedDuplicateCertificateCompressions,
244
    OfferedDuplicateKeyShares,
245
    OfferedEarlyDataWithOldProtocolVersion,
246
    OfferedEmptyApplicationProtocol,
247
    OfferedIncorrectCompressions,
248
    PskExtensionMustBeLast,
249
    PskExtensionWithMismatchedIdsAndBinders,
250
    RefusedToFollowHelloRetryRequest,
251
    RejectedEarlyDataInterleavedWithHandshakeMessage,
252
    ResumptionAttemptedWithVariedEms,
253
    ResumptionOfferedWithVariedCipherSuite,
254
    ResumptionOfferedWithVariedEms,
255
    ResumptionOfferedWithIncompatibleCipherSuite,
256
    SelectedDifferentCipherSuiteAfterRetry,
257
    SelectedInvalidPsk,
258
    SelectedTls12UsingTls13VersionExtension,
259
    SelectedUnofferedApplicationProtocol,
260
    SelectedUnofferedCertCompression,
261
    SelectedUnofferedCipherSuite,
262
    SelectedUnofferedCompression,
263
    SelectedUnofferedKxGroup,
264
    SelectedUnofferedPsk,
265
    SelectedUnusableCipherSuiteForVersion,
266
    ServerHelloMustOfferUncompressedEcPoints,
267
    ServerNameDifferedOnRetry,
268
    ServerNameMustContainOneHostName,
269
    SignedKxWithWrongAlgorithm,
270
    SignedHandshakeWithUnadvertisedSigScheme,
271
    TooManyEmptyFragments,
272
    TooManyKeyUpdateRequests,
273
    TooManyRenegotiationRequests,
274
    TooManyWarningAlertsReceived,
275
    TooMuchEarlyDataReceived,
276
    UnexpectedCleartextExtension,
277
    UnsolicitedCertExtension,
278
    UnsolicitedEncryptedExtension,
279
    UnsolicitedSctList,
280
    UnsolicitedServerHelloExtension,
281
    WrongGroupForKeyShare,
282
    UnsolicitedEchExtension,
283
}
284
285
impl From<PeerMisbehaved> for Error {
286
    #[inline]
287
0
    fn from(e: PeerMisbehaved) -> Self {
288
0
        Self::PeerMisbehaved(e)
289
0
    }
290
}
291
292
#[non_exhaustive]
293
#[allow(missing_docs)]
294
#[derive(Debug, PartialEq, Clone)]
295
/// The set of cases where we failed to make a connection because a peer
296
/// doesn't support a TLS version/feature we require.
297
///
298
/// This is `non_exhaustive`: we might add or stop using items here in minor
299
/// versions.
300
pub enum PeerIncompatible {
301
    EcPointsExtensionRequired,
302
    ExtendedMasterSecretExtensionRequired,
303
    IncorrectCertificateTypeExtension,
304
    KeyShareExtensionRequired,
305
    NamedGroupsExtensionRequired,
306
    NoCertificateRequestSignatureSchemesInCommon,
307
    NoCipherSuitesInCommon,
308
    NoEcPointFormatsInCommon,
309
    NoKxGroupsInCommon,
310
    NoSignatureSchemesInCommon,
311
    NullCompressionRequired,
312
    ServerDoesNotSupportTls12Or13,
313
    ServerSentHelloRetryRequestWithUnknownExtension,
314
    ServerTlsVersionIsDisabledByOurConfig,
315
    SignatureAlgorithmsExtensionRequired,
316
    SupportedVersionsExtensionRequired,
317
    Tls12NotOffered,
318
    Tls12NotOfferedOrEnabled,
319
    Tls13RequiredForQuic,
320
    UncompressedEcPointsRequired,
321
    UnsolicitedCertificateTypeExtension,
322
    ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
323
}
324
325
impl From<PeerIncompatible> for Error {
326
    #[inline]
327
0
    fn from(e: PeerIncompatible) -> Self {
328
0
        Self::PeerIncompatible(e)
329
0
    }
330
}
331
332
#[non_exhaustive]
333
#[derive(Debug, Clone)]
334
/// The ways in which certificate validators can express errors.
335
///
336
/// Note that the rustls TLS protocol code interprets specifically these
337
/// error codes to send specific TLS alerts.  Therefore, if a
338
/// custom certificate validator uses incorrect errors the library as
339
/// a whole will send alerts that do not match the standard (this is usually
340
/// a minor issue, but could be misleading).
341
pub enum CertificateError {
342
    /// The certificate is not correctly encoded.
343
    BadEncoding,
344
345
    /// The current time is after the `notAfter` time in the certificate.
346
    Expired,
347
348
    /// The current time is before the `notBefore` time in the certificate.
349
    NotValidYet,
350
351
    /// The certificate has been revoked.
352
    Revoked,
353
354
    /// The certificate contains an extension marked critical, but it was
355
    /// not processed by the certificate validator.
356
    UnhandledCriticalExtension,
357
358
    /// The certificate chain is not issued by a known root certificate.
359
    UnknownIssuer,
360
361
    /// The certificate's revocation status could not be determined.
362
    UnknownRevocationStatus,
363
364
    /// The certificate's revocation status could not be determined, because the CRL is expired.
365
    ExpiredRevocationList,
366
367
    /// A certificate is not correctly signed by the key of its alleged
368
    /// issuer.
369
    BadSignature,
370
371
    /// The subject names in an end-entity certificate do not include
372
    /// the expected name.
373
    NotValidForName,
374
375
    /// The certificate is being used for a different purpose than allowed.
376
    InvalidPurpose,
377
378
    /// The certificate is valid, but the handshake is rejected for other
379
    /// reasons.
380
    ApplicationVerificationFailure,
381
382
    /// Any other error.
383
    ///
384
    /// This can be used by custom verifiers to expose the underlying error
385
    /// (where they are not better described by the more specific errors
386
    /// above).
387
    ///
388
    /// It is also used by the default verifier in case its error is
389
    /// not covered by the above common cases.
390
    ///
391
    /// Enums holding this variant will never compare equal to each other.
392
    Other(OtherError),
393
}
394
395
impl PartialEq<Self> for CertificateError {
396
0
    fn eq(&self, other: &Self) -> bool {
397
        use CertificateError::*;
398
        #[allow(clippy::match_like_matches_macro)]
399
0
        match (self, other) {
400
0
            (BadEncoding, BadEncoding) => true,
401
0
            (Expired, Expired) => true,
402
0
            (NotValidYet, NotValidYet) => true,
403
0
            (Revoked, Revoked) => true,
404
0
            (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
405
0
            (UnknownIssuer, UnknownIssuer) => true,
406
0
            (BadSignature, BadSignature) => true,
407
0
            (NotValidForName, NotValidForName) => true,
408
0
            (InvalidPurpose, InvalidPurpose) => true,
409
0
            (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
410
0
            (ExpiredRevocationList, ExpiredRevocationList) => true,
411
0
            _ => false,
412
        }
413
0
    }
414
}
415
416
// The following mapping are heavily referenced in:
417
// * [OpenSSL Implementation](https://github.com/openssl/openssl/blob/45bb98bfa223efd3258f445ad443f878011450f0/ssl/statem/statem_lib.c#L1434)
418
// * [BoringSSL Implementation](https://github.com/google/boringssl/blob/583c60bd4bf76d61b2634a58bcda99a92de106cb/ssl/ssl_x509.cc#L1323)
419
impl From<CertificateError> for AlertDescription {
420
0
    fn from(e: CertificateError) -> Self {
421
        use CertificateError::*;
422
0
        match e {
423
0
            BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate,
424
            // RFC 5246/RFC 8446
425
            // certificate_expired
426
            //  A certificate has expired or **is not currently valid**.
427
0
            Expired | NotValidYet => Self::CertificateExpired,
428
0
            Revoked => Self::CertificateRevoked,
429
            // OpenSSL, BoringSSL and AWS-LC all generate an Unknown CA alert for
430
            // the case where revocation status can not be determined, so we do the same here.
431
0
            UnknownIssuer | UnknownRevocationStatus | ExpiredRevocationList => Self::UnknownCA,
432
0
            BadSignature => Self::DecryptError,
433
0
            InvalidPurpose => Self::UnsupportedCertificate,
434
0
            ApplicationVerificationFailure => Self::AccessDenied,
435
            // RFC 5246/RFC 8446
436
            // certificate_unknown
437
            //  Some other (unspecified) issue arose in processing the
438
            //  certificate, rendering it unacceptable.
439
0
            Other(..) => Self::CertificateUnknown,
440
        }
441
0
    }
442
}
443
444
impl From<CertificateError> for Error {
445
    #[inline]
446
0
    fn from(e: CertificateError) -> Self {
447
0
        Self::InvalidCertificate(e)
448
0
    }
449
}
450
451
#[non_exhaustive]
452
#[derive(Debug, Clone)]
453
/// The ways in which a certificate revocation list (CRL) can be invalid.
454
pub enum CertRevocationListError {
455
    /// The CRL had a bad, or unsupported signature from its issuer.
456
    BadSignature,
457
458
    /// The CRL contained an invalid CRL number.
459
    InvalidCrlNumber,
460
461
    /// The CRL contained a revoked certificate with an invalid serial number.
462
    InvalidRevokedCertSerialNumber,
463
464
    /// The CRL issuer does not specify the cRLSign key usage.
465
    IssuerInvalidForCrl,
466
467
    /// The CRL is invalid for some other reason.
468
    ///
469
    /// Enums holding this variant will never compare equal to each other.
470
    Other(OtherError),
471
472
    /// The CRL is not correctly encoded.
473
    ParseError,
474
475
    /// The CRL is not a v2 X.509 CRL.
476
    UnsupportedCrlVersion,
477
478
    /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
479
    UnsupportedCriticalExtension,
480
481
    /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
482
    UnsupportedDeltaCrl,
483
484
    /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
485
    /// other than the issuer of the CRL.
486
    UnsupportedIndirectCrl,
487
488
    /// The CRL contained a revoked certificate with an unsupported revocation reason.
489
    /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
490
    ///
491
    /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
492
    UnsupportedRevocationReason,
493
}
494
495
impl PartialEq<Self> for CertRevocationListError {
496
0
    fn eq(&self, other: &Self) -> bool {
497
        use CertRevocationListError::*;
498
        #[allow(clippy::match_like_matches_macro)]
499
0
        match (self, other) {
500
0
            (BadSignature, BadSignature) => true,
501
0
            (InvalidCrlNumber, InvalidCrlNumber) => true,
502
0
            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
503
0
            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
504
0
            (ParseError, ParseError) => true,
505
0
            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
506
0
            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
507
0
            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
508
0
            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
509
0
            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
510
0
            _ => false,
511
        }
512
0
    }
513
}
514
515
impl From<CertRevocationListError> for Error {
516
    #[inline]
517
0
    fn from(e: CertRevocationListError) -> Self {
518
0
        Self::InvalidCertRevocationList(e)
519
0
    }
520
}
521
522
#[non_exhaustive]
523
#[derive(Debug, Clone, Eq, PartialEq)]
524
/// An error that occurred while handling Encrypted Client Hello (ECH).
525
pub enum EncryptedClientHelloError {
526
    /// The provided ECH configuration list was invalid.
527
    InvalidConfigList,
528
    /// No compatible ECH configuration.
529
    NoCompatibleConfig,
530
    /// The client configuration has server name indication (SNI) disabled.
531
    SniRequired,
532
}
533
534
impl From<EncryptedClientHelloError> for Error {
535
    #[inline]
536
0
    fn from(e: EncryptedClientHelloError) -> Self {
537
0
        Self::InvalidEncryptedClientHello(e)
538
0
    }
539
}
540
541
0
fn join<T: fmt::Debug>(items: &[T]) -> String {
542
0
    items
543
0
        .iter()
544
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}
545
0
        .collect::<Vec<String>>()
546
0
        .join(" or ")
547
0
}
Unexecuted instantiation: rustls::error::join::<rustls::enums::ContentType>
Unexecuted instantiation: rustls::error::join::<rustls::enums::HandshakeType>
548
549
impl fmt::Display for Error {
550
0
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551
0
        match *self {
552
            Self::InappropriateMessage {
553
0
                ref expect_types,
554
0
                ref got_type,
555
0
            } => write!(
556
0
                f,
557
0
                "received unexpected message: got {:?} when expecting {}",
558
                got_type,
559
0
                join::<ContentType>(expect_types)
560
            ),
561
            Self::InappropriateHandshakeMessage {
562
0
                ref expect_types,
563
0
                ref got_type,
564
0
            } => write!(
565
0
                f,
566
0
                "received unexpected handshake message: got {:?} when expecting {}",
567
                got_type,
568
0
                join::<HandshakeType>(expect_types)
569
            ),
570
0
            Self::InvalidMessage(ref typ) => {
571
0
                write!(f, "received corrupt message of type {:?}", typ)
572
            }
573
0
            Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why),
574
0
            Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why),
575
0
            Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
576
0
            Self::InvalidCertificate(ref err) => {
577
0
                write!(f, "invalid peer certificate: {:?}", err)
578
            }
579
0
            Self::InvalidCertRevocationList(ref err) => {
580
0
                write!(f, "invalid certificate revocation list: {:?}", err)
581
            }
582
0
            Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
583
0
            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
584
0
            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
585
0
            Self::InvalidEncryptedClientHello(ref err) => {
586
0
                write!(f, "encrypted client hello failure: {:?}", err)
587
            }
588
0
            Self::EncryptError => write!(f, "cannot encrypt message"),
589
0
            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
590
0
            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
591
0
            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
592
0
            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
593
0
            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
594
            Self::BadMaxFragmentSize => {
595
0
                write!(f, "the supplied max_fragment_size was too small or large")
596
            }
597
0
            Self::InconsistentKeys(ref why) => {
598
0
                write!(f, "keys may not be consistent: {:?}", why)
599
            }
600
0
            Self::General(ref err) => write!(f, "unexpected error: {}", err),
601
0
            Self::Other(ref err) => write!(f, "other error: {}", err),
602
        }
603
0
    }
604
}
605
606
#[cfg(feature = "std")]
607
impl From<SystemTimeError> for Error {
608
    #[inline]
609
0
    fn from(_: SystemTimeError) -> Self {
610
0
        Self::FailedToGetCurrentTime
611
0
    }
612
}
613
614
#[cfg(feature = "std")]
615
impl std::error::Error for Error {}
616
617
impl From<rand::GetRandomFailed> for Error {
618
0
    fn from(_: rand::GetRandomFailed) -> Self {
619
0
        Self::FailedToGetRandomBytes
620
0
    }
621
}
622
623
mod other_error {
624
    use core::fmt;
625
    #[cfg(feature = "std")]
626
    use std::error::Error as StdError;
627
628
    use super::Error;
629
    #[cfg(feature = "std")]
630
    use crate::sync::Arc;
631
632
    /// Any other error that cannot be expressed by a more specific [`Error`] variant.
633
    ///
634
    /// For example, an `OtherError` could be produced by a custom crypto provider
635
    /// exposing a provider specific error.
636
    ///
637
    /// Enums holding this type will never compare equal to each other.
638
    #[derive(Debug, Clone)]
639
    pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
640
641
    impl PartialEq<Self> for OtherError {
642
0
        fn eq(&self, _other: &Self) -> bool {
643
0
            false
644
0
        }
645
    }
646
647
    impl From<OtherError> for Error {
648
0
        fn from(value: OtherError) -> Self {
649
0
            Self::Other(value)
650
0
        }
651
    }
652
653
    impl fmt::Display for OtherError {
654
0
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
655
            #[cfg(feature = "std")]
656
            {
657
0
                write!(f, "{}", self.0)
658
            }
659
            #[cfg(not(feature = "std"))]
660
            {
661
                f.write_str("no further information available")
662
            }
663
0
        }
664
    }
665
666
    #[cfg(feature = "std")]
667
    impl StdError for OtherError {
668
0
        fn source(&self) -> Option<&(dyn StdError + 'static)> {
669
0
            Some(self.0.as_ref())
670
0
        }
671
    }
672
}
673
674
pub use other_error::OtherError;
675
676
#[cfg(test)]
677
mod tests {
678
    use std::prelude::v1::*;
679
    use std::{println, vec};
680
681
    use super::{CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError};
682
    #[cfg(feature = "std")]
683
    use crate::sync::Arc;
684
685
    #[test]
686
    fn certificate_error_equality() {
687
        use super::CertificateError::*;
688
        assert_eq!(BadEncoding, BadEncoding);
689
        assert_eq!(Expired, Expired);
690
        assert_eq!(NotValidYet, NotValidYet);
691
        assert_eq!(Revoked, Revoked);
692
        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
693
        assert_eq!(UnknownIssuer, UnknownIssuer);
694
        assert_eq!(BadSignature, BadSignature);
695
        assert_eq!(NotValidForName, NotValidForName);
696
        assert_eq!(InvalidPurpose, InvalidPurpose);
697
        assert_eq!(
698
            ApplicationVerificationFailure,
699
            ApplicationVerificationFailure
700
        );
701
        let other = Other(OtherError(
702
            #[cfg(feature = "std")]
703
            Arc::from(Box::from("")),
704
        ));
705
        assert_ne!(other, other);
706
        assert_ne!(BadEncoding, Expired);
707
    }
708
709
    #[test]
710
    fn crl_error_equality() {
711
        use super::CertRevocationListError::*;
712
        assert_eq!(BadSignature, BadSignature);
713
        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
714
        assert_eq!(
715
            InvalidRevokedCertSerialNumber,
716
            InvalidRevokedCertSerialNumber
717
        );
718
        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
719
        assert_eq!(ParseError, ParseError);
720
        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
721
        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
722
        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
723
        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
724
        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
725
        let other = Other(OtherError(
726
            #[cfg(feature = "std")]
727
            Arc::from(Box::from("")),
728
        ));
729
        assert_ne!(other, other);
730
        assert_ne!(BadSignature, InvalidCrlNumber);
731
    }
732
733
    #[test]
734
    #[cfg(feature = "std")]
735
    fn other_error_equality() {
736
        let other_error = OtherError(Arc::from(Box::from("")));
737
        assert_ne!(other_error, other_error);
738
        let other: Error = other_error.into();
739
        assert_ne!(other, other);
740
    }
741
742
    #[test]
743
    fn smoke() {
744
        use crate::enums::{AlertDescription, ContentType, HandshakeType};
745
746
        let all = vec![
747
            Error::InappropriateMessage {
748
                expect_types: vec![ContentType::Alert],
749
                got_type: ContentType::Handshake,
750
            },
751
            Error::InappropriateHandshakeMessage {
752
                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
753
                got_type: HandshakeType::ServerHello,
754
            },
755
            Error::InvalidMessage(InvalidMessage::InvalidCcs),
756
            Error::NoCertificatesPresented,
757
            Error::DecryptError,
758
            super::PeerIncompatible::Tls12NotOffered.into(),
759
            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
760
            Error::AlertReceived(AlertDescription::ExportRestriction),
761
            super::CertificateError::Expired.into(),
762
            Error::General("undocumented error".to_string()),
763
            Error::FailedToGetCurrentTime,
764
            Error::FailedToGetRandomBytes,
765
            Error::HandshakeNotComplete,
766
            Error::PeerSentOversizedRecord,
767
            Error::NoApplicationProtocol,
768
            Error::BadMaxFragmentSize,
769
            Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
770
            Error::InconsistentKeys(InconsistentKeys::Unknown),
771
            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
772
            Error::Other(OtherError(
773
                #[cfg(feature = "std")]
774
                Arc::from(Box::from("")),
775
            )),
776
        ];
777
778
        for err in all {
779
            println!("{:?}:", err);
780
            println!("  fmt '{}'", err);
781
        }
782
    }
783
784
    #[test]
785
    fn rand_error_mapping() {
786
        use super::rand;
787
        let err: Error = rand::GetRandomFailed.into();
788
        assert_eq!(err, Error::FailedToGetRandomBytes);
789
    }
790
791
    #[cfg(feature = "std")]
792
    #[test]
793
    fn time_error_mapping() {
794
        use std::time::SystemTime;
795
796
        let time_error = SystemTime::UNIX_EPOCH
797
            .duration_since(SystemTime::now())
798
            .unwrap_err();
799
        let err: Error = time_error.into();
800
        assert_eq!(err, Error::FailedToGetCurrentTime);
801
    }
802
}