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