rustls/
error.rs

1use alloc::format;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5#[cfg(feature = "std")]
6use std::time::SystemTimeError;
7
8use crate::enums::{AlertDescription, ContentType, HandshakeType};
9use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
10use crate::rand;
11
12/// rustls reports protocol errors using this type.
13#[non_exhaustive]
14#[derive(Debug, PartialEq, Clone)]
15pub 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`].
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`].
116///
117/// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
118#[non_exhaustive]
119#[derive(Clone, Copy, Debug, Eq, PartialEq)]
120pub 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
132impl From<InconsistentKeys> for Error {
133    #[inline]
134    fn from(e: InconsistentKeys) -> Self {
135        Self::InconsistentKeys(e)
136    }
137}
138
139/// A corrupt TLS message payload that resulted in an error.
140#[non_exhaustive]
141#[derive(Debug, Clone, Copy, PartialEq)]
142
143pub 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
188impl From<InvalidMessage> for Error {
189    #[inline]
190    fn from(e: InvalidMessage) -> Self {
191        Self::InvalidMessage(e)
192    }
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.
208pub 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
285impl From<PeerMisbehaved> for Error {
286    #[inline]
287    fn from(e: PeerMisbehaved) -> Self {
288        Self::PeerMisbehaved(e)
289    }
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.
300pub enum PeerIncompatible {
301    EcPointsExtensionRequired,
302    ExtendedMasterSecretExtensionRequired,
303    KeyShareExtensionRequired,
304    NamedGroupsExtensionRequired,
305    NoCertificateRequestSignatureSchemesInCommon,
306    NoCipherSuitesInCommon,
307    NoEcPointFormatsInCommon,
308    NoKxGroupsInCommon,
309    NoSignatureSchemesInCommon,
310    NullCompressionRequired,
311    ServerDoesNotSupportTls12Or13,
312    ServerSentHelloRetryRequestWithUnknownExtension,
313    ServerTlsVersionIsDisabledByOurConfig,
314    SignatureAlgorithmsExtensionRequired,
315    SupportedVersionsExtensionRequired,
316    Tls12NotOffered,
317    Tls12NotOfferedOrEnabled,
318    Tls13RequiredForQuic,
319    UncompressedEcPointsRequired,
320    ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
321}
322
323impl From<PeerIncompatible> for Error {
324    #[inline]
325    fn from(e: PeerIncompatible) -> Self {
326        Self::PeerIncompatible(e)
327    }
328}
329
330#[non_exhaustive]
331#[derive(Debug, Clone)]
332/// The ways in which certificate validators can express errors.
333///
334/// Note that the rustls TLS protocol code interprets specifically these
335/// error codes to send specific TLS alerts.  Therefore, if a
336/// custom certificate validator uses incorrect errors the library as
337/// a whole will send alerts that do not match the standard (this is usually
338/// a minor issue, but could be misleading).
339pub enum CertificateError {
340    /// The certificate is not correctly encoded.
341    BadEncoding,
342
343    /// The current time is after the `notAfter` time in the certificate.
344    Expired,
345
346    /// The current time is before the `notBefore` time in the certificate.
347    NotValidYet,
348
349    /// The certificate has been revoked.
350    Revoked,
351
352    /// The certificate contains an extension marked critical, but it was
353    /// not processed by the certificate validator.
354    UnhandledCriticalExtension,
355
356    /// The certificate chain is not issued by a known root certificate.
357    UnknownIssuer,
358
359    /// The certificate's revocation status could not be determined.
360    UnknownRevocationStatus,
361
362    /// The certificate's revocation status could not be determined, because the CRL is expired.
363    ExpiredRevocationList,
364
365    /// A certificate is not correctly signed by the key of its alleged
366    /// issuer.
367    BadSignature,
368
369    /// The subject names in an end-entity certificate do not include
370    /// the expected name.
371    NotValidForName,
372
373    /// The certificate is being used for a different purpose than allowed.
374    InvalidPurpose,
375
376    /// The certificate is valid, but the handshake is rejected for other
377    /// reasons.
378    ApplicationVerificationFailure,
379
380    /// Any other error.
381    ///
382    /// This can be used by custom verifiers to expose the underlying error
383    /// (where they are not better described by the more specific errors
384    /// above).
385    ///
386    /// It is also used by the default verifier in case its error is
387    /// not covered by the above common cases.
388    ///
389    /// Enums holding this variant will never compare equal to each other.
390    Other(OtherError),
391}
392
393impl PartialEq<Self> for CertificateError {
394    fn eq(&self, other: &Self) -> bool {
395        use CertificateError::*;
396        #[allow(clippy::match_like_matches_macro)]
397        match (self, other) {
398            (BadEncoding, BadEncoding) => true,
399            (Expired, Expired) => true,
400            (NotValidYet, NotValidYet) => true,
401            (Revoked, Revoked) => true,
402            (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
403            (UnknownIssuer, UnknownIssuer) => true,
404            (BadSignature, BadSignature) => true,
405            (NotValidForName, NotValidForName) => true,
406            (InvalidPurpose, InvalidPurpose) => true,
407            (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
408            (ExpiredRevocationList, ExpiredRevocationList) => true,
409            _ => false,
410        }
411    }
412}
413
414// The following mapping are heavily referenced in:
415// * [OpenSSL Implementation](https://github.com/openssl/openssl/blob/45bb98bfa223efd3258f445ad443f878011450f0/ssl/statem/statem_lib.c#L1434)
416// * [BoringSSL Implementation](https://github.com/google/boringssl/blob/583c60bd4bf76d61b2634a58bcda99a92de106cb/ssl/ssl_x509.cc#L1323)
417impl From<CertificateError> for AlertDescription {
418    fn from(e: CertificateError) -> Self {
419        use CertificateError::*;
420        match e {
421            BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate,
422            // RFC 5246/RFC 8446
423            // certificate_expired
424            //  A certificate has expired or **is not currently valid**.
425            Expired | NotValidYet => Self::CertificateExpired,
426            Revoked => Self::CertificateRevoked,
427            // OpenSSL, BoringSSL and AWS-LC all generate an Unknown CA alert for
428            // the case where revocation status can not be determined, so we do the same here.
429            UnknownIssuer | UnknownRevocationStatus | ExpiredRevocationList => Self::UnknownCA,
430            BadSignature => Self::DecryptError,
431            InvalidPurpose => Self::UnsupportedCertificate,
432            ApplicationVerificationFailure => Self::AccessDenied,
433            // RFC 5246/RFC 8446
434            // certificate_unknown
435            //  Some other (unspecified) issue arose in processing the
436            //  certificate, rendering it unacceptable.
437            Other(..) => Self::CertificateUnknown,
438        }
439    }
440}
441
442impl From<CertificateError> for Error {
443    #[inline]
444    fn from(e: CertificateError) -> Self {
445        Self::InvalidCertificate(e)
446    }
447}
448
449#[non_exhaustive]
450#[derive(Debug, Clone)]
451/// The ways in which a certificate revocation list (CRL) can be invalid.
452pub enum CertRevocationListError {
453    /// The CRL had a bad, or unsupported signature from its issuer.
454    BadSignature,
455
456    /// The CRL contained an invalid CRL number.
457    InvalidCrlNumber,
458
459    /// The CRL contained a revoked certificate with an invalid serial number.
460    InvalidRevokedCertSerialNumber,
461
462    /// The CRL issuer does not specify the cRLSign key usage.
463    IssuerInvalidForCrl,
464
465    /// The CRL is invalid for some other reason.
466    ///
467    /// Enums holding this variant will never compare equal to each other.
468    Other(OtherError),
469
470    /// The CRL is not correctly encoded.
471    ParseError,
472
473    /// The CRL is not a v2 X.509 CRL.
474    UnsupportedCrlVersion,
475
476    /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
477    UnsupportedCriticalExtension,
478
479    /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
480    UnsupportedDeltaCrl,
481
482    /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
483    /// other than the issuer of the CRL.
484    UnsupportedIndirectCrl,
485
486    /// The CRL contained a revoked certificate with an unsupported revocation reason.
487    /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
488    ///
489    /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
490    UnsupportedRevocationReason,
491}
492
493impl PartialEq<Self> for CertRevocationListError {
494    fn eq(&self, other: &Self) -> bool {
495        use CertRevocationListError::*;
496        #[allow(clippy::match_like_matches_macro)]
497        match (self, other) {
498            (BadSignature, BadSignature) => true,
499            (InvalidCrlNumber, InvalidCrlNumber) => true,
500            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
501            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
502            (ParseError, ParseError) => true,
503            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
504            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
505            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
506            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
507            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
508            _ => false,
509        }
510    }
511}
512
513impl From<CertRevocationListError> for Error {
514    #[inline]
515    fn from(e: CertRevocationListError) -> Self {
516        Self::InvalidCertRevocationList(e)
517    }
518}
519
520#[non_exhaustive]
521#[derive(Debug, Clone, Eq, PartialEq)]
522/// An error that occurred while handling Encrypted Client Hello (ECH).
523pub enum EncryptedClientHelloError {
524    /// The provided ECH configuration list was invalid.
525    InvalidConfigList,
526    /// No compatible ECH configuration.
527    NoCompatibleConfig,
528    /// The client configuration has server name indication (SNI) disabled.
529    SniRequired,
530}
531
532impl From<EncryptedClientHelloError> for Error {
533    #[inline]
534    fn from(e: EncryptedClientHelloError) -> Self {
535        Self::InvalidEncryptedClientHello(e)
536    }
537}
538
539fn join<T: fmt::Debug>(items: &[T]) -> String {
540    items
541        .iter()
542        .map(|x| format!("{:?}", x))
543        .collect::<Vec<String>>()
544        .join(" or ")
545}
546
547impl fmt::Display for Error {
548    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549        match *self {
550            Self::InappropriateMessage {
551                ref expect_types,
552                ref got_type,
553            } => write!(
554                f,
555                "received unexpected message: got {:?} when expecting {}",
556                got_type,
557                join::<ContentType>(expect_types)
558            ),
559            Self::InappropriateHandshakeMessage {
560                ref expect_types,
561                ref got_type,
562            } => write!(
563                f,
564                "received unexpected handshake message: got {:?} when expecting {}",
565                got_type,
566                join::<HandshakeType>(expect_types)
567            ),
568            Self::InvalidMessage(ref typ) => {
569                write!(f, "received corrupt message of type {:?}", typ)
570            }
571            Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why),
572            Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why),
573            Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
574            Self::InvalidCertificate(ref err) => {
575                write!(f, "invalid peer certificate: {:?}", err)
576            }
577            Self::InvalidCertRevocationList(ref err) => {
578                write!(f, "invalid certificate revocation list: {:?}", err)
579            }
580            Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
581            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
582            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
583            Self::InvalidEncryptedClientHello(ref err) => {
584                write!(f, "encrypted client hello failure: {:?}", err)
585            }
586            Self::EncryptError => write!(f, "cannot encrypt message"),
587            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
588            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
589            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
590            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
591            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
592            Self::BadMaxFragmentSize => {
593                write!(f, "the supplied max_fragment_size was too small or large")
594            }
595            Self::InconsistentKeys(ref why) => {
596                write!(f, "keys may not be consistent: {:?}", why)
597            }
598            Self::General(ref err) => write!(f, "unexpected error: {}", err),
599            Self::Other(ref err) => write!(f, "other error: {}", err),
600        }
601    }
602}
603
604#[cfg(feature = "std")]
605impl From<SystemTimeError> for Error {
606    #[inline]
607    fn from(_: SystemTimeError) -> Self {
608        Self::FailedToGetCurrentTime
609    }
610}
611
612#[cfg(feature = "std")]
613impl std::error::Error for Error {}
614
615impl From<rand::GetRandomFailed> for Error {
616    fn from(_: rand::GetRandomFailed) -> Self {
617        Self::FailedToGetRandomBytes
618    }
619}
620
621mod other_error {
622    #[cfg(feature = "std")]
623    use alloc::sync::Arc;
624    use core::fmt;
625    #[cfg(feature = "std")]
626    use std::error::Error as StdError;
627
628    use super::Error;
629
630    /// Any other error that cannot be expressed by a more specific [`Error`] variant.
631    ///
632    /// For example, an `OtherError` could be produced by a custom crypto provider
633    /// exposing a provider specific error.
634    ///
635    /// Enums holding this type will never compare equal to each other.
636    #[derive(Debug, Clone)]
637    pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
638
639    impl PartialEq<Self> for OtherError {
640        fn eq(&self, _other: &Self) -> bool {
641            false
642        }
643    }
644
645    impl From<OtherError> for Error {
646        fn from(value: OtherError) -> Self {
647            Self::Other(value)
648        }
649    }
650
651    impl fmt::Display for OtherError {
652        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653            #[cfg(feature = "std")]
654            {
655                write!(f, "{}", self.0)
656            }
657            #[cfg(not(feature = "std"))]
658            {
659                f.write_str("no further information available")
660            }
661        }
662    }
663
664    #[cfg(feature = "std")]
665    impl StdError for OtherError {
666        fn source(&self) -> Option<&(dyn StdError + 'static)> {
667            Some(self.0.as_ref())
668        }
669    }
670}
671
672pub use other_error::OtherError;
673
674#[cfg(test)]
675mod tests {
676    use std::prelude::v1::*;
677    use std::{println, vec};
678
679    use super::{Error, InconsistentKeys, InvalidMessage};
680    use crate::error::{CertRevocationListError, OtherError};
681
682    #[test]
683    fn certificate_error_equality() {
684        use super::CertificateError::*;
685        assert_eq!(BadEncoding, BadEncoding);
686        assert_eq!(Expired, Expired);
687        assert_eq!(NotValidYet, NotValidYet);
688        assert_eq!(Revoked, Revoked);
689        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
690        assert_eq!(UnknownIssuer, UnknownIssuer);
691        assert_eq!(BadSignature, BadSignature);
692        assert_eq!(NotValidForName, NotValidForName);
693        assert_eq!(InvalidPurpose, InvalidPurpose);
694        assert_eq!(
695            ApplicationVerificationFailure,
696            ApplicationVerificationFailure
697        );
698        let other = Other(OtherError(
699            #[cfg(feature = "std")]
700            alloc::sync::Arc::from(Box::from("")),
701        ));
702        assert_ne!(other, other);
703        assert_ne!(BadEncoding, Expired);
704    }
705
706    #[test]
707    fn crl_error_equality() {
708        use super::CertRevocationListError::*;
709        assert_eq!(BadSignature, BadSignature);
710        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
711        assert_eq!(
712            InvalidRevokedCertSerialNumber,
713            InvalidRevokedCertSerialNumber
714        );
715        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
716        assert_eq!(ParseError, ParseError);
717        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
718        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
719        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
720        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
721        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
722        let other = Other(OtherError(
723            #[cfg(feature = "std")]
724            alloc::sync::Arc::from(Box::from("")),
725        ));
726        assert_ne!(other, other);
727        assert_ne!(BadSignature, InvalidCrlNumber);
728    }
729
730    #[test]
731    #[cfg(feature = "std")]
732    fn other_error_equality() {
733        let other_error = OtherError(alloc::sync::Arc::from(Box::from("")));
734        assert_ne!(other_error, other_error);
735        let other: Error = other_error.into();
736        assert_ne!(other, other);
737    }
738
739    #[test]
740    fn smoke() {
741        use crate::enums::{AlertDescription, ContentType, HandshakeType};
742
743        let all = vec![
744            Error::InappropriateMessage {
745                expect_types: vec![ContentType::Alert],
746                got_type: ContentType::Handshake,
747            },
748            Error::InappropriateHandshakeMessage {
749                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
750                got_type: HandshakeType::ServerHello,
751            },
752            Error::InvalidMessage(InvalidMessage::InvalidCcs),
753            Error::NoCertificatesPresented,
754            Error::DecryptError,
755            super::PeerIncompatible::Tls12NotOffered.into(),
756            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
757            Error::AlertReceived(AlertDescription::ExportRestriction),
758            super::CertificateError::Expired.into(),
759            Error::General("undocumented error".to_string()),
760            Error::FailedToGetCurrentTime,
761            Error::FailedToGetRandomBytes,
762            Error::HandshakeNotComplete,
763            Error::PeerSentOversizedRecord,
764            Error::NoApplicationProtocol,
765            Error::BadMaxFragmentSize,
766            Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
767            Error::InconsistentKeys(InconsistentKeys::Unknown),
768            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
769            Error::Other(OtherError(
770                #[cfg(feature = "std")]
771                alloc::sync::Arc::from(Box::from("")),
772            )),
773        ];
774
775        for err in all {
776            println!("{:?}:", err);
777            println!("  fmt '{}'", err);
778        }
779    }
780
781    #[test]
782    fn rand_error_mapping() {
783        use super::rand;
784        let err: Error = rand::GetRandomFailed.into();
785        assert_eq!(err, Error::FailedToGetRandomBytes);
786    }
787
788    #[cfg(feature = "std")]
789    #[test]
790    fn time_error_mapping() {
791        use std::time::SystemTime;
792
793        let time_error = SystemTime::UNIX_EPOCH
794            .duration_since(SystemTime::now())
795            .unwrap_err();
796        let err: Error = time_error.into();
797        assert_eq!(err, Error::FailedToGetCurrentTime);
798    }
799}