rustls/
error.rs

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