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`] 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)]
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    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
325impl From<PeerIncompatible> for Error {
326    #[inline]
327    fn from(e: PeerIncompatible) -> Self {
328        Self::PeerIncompatible(e)
329    }
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).
341pub 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
395impl PartialEq<Self> for CertificateError {
396    fn eq(&self, other: &Self) -> bool {
397        use CertificateError::*;
398        #[allow(clippy::match_like_matches_macro)]
399        match (self, other) {
400            (BadEncoding, BadEncoding) => true,
401            (Expired, Expired) => true,
402            (NotValidYet, NotValidYet) => true,
403            (Revoked, Revoked) => true,
404            (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
405            (UnknownIssuer, UnknownIssuer) => true,
406            (BadSignature, BadSignature) => true,
407            (NotValidForName, NotValidForName) => true,
408            (InvalidPurpose, InvalidPurpose) => true,
409            (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
410            (ExpiredRevocationList, ExpiredRevocationList) => true,
411            _ => false,
412        }
413    }
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)
419impl From<CertificateError> for AlertDescription {
420    fn from(e: CertificateError) -> Self {
421        use CertificateError::*;
422        match e {
423            BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate,
424            // RFC 5246/RFC 8446
425            // certificate_expired
426            //  A certificate has expired or **is not currently valid**.
427            Expired | NotValidYet => Self::CertificateExpired,
428            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            UnknownIssuer | UnknownRevocationStatus | ExpiredRevocationList => Self::UnknownCA,
432            BadSignature => Self::DecryptError,
433            InvalidPurpose => Self::UnsupportedCertificate,
434            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            Other(..) => Self::CertificateUnknown,
440        }
441    }
442}
443
444impl From<CertificateError> for Error {
445    #[inline]
446    fn from(e: CertificateError) -> Self {
447        Self::InvalidCertificate(e)
448    }
449}
450
451#[non_exhaustive]
452#[derive(Debug, Clone)]
453/// The ways in which a certificate revocation list (CRL) can be invalid.
454pub 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
495impl PartialEq<Self> for CertRevocationListError {
496    fn eq(&self, other: &Self) -> bool {
497        use CertRevocationListError::*;
498        #[allow(clippy::match_like_matches_macro)]
499        match (self, other) {
500            (BadSignature, BadSignature) => true,
501            (InvalidCrlNumber, InvalidCrlNumber) => true,
502            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
503            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
504            (ParseError, ParseError) => true,
505            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
506            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
507            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
508            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
509            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
510            _ => false,
511        }
512    }
513}
514
515impl From<CertRevocationListError> for Error {
516    #[inline]
517    fn from(e: CertRevocationListError) -> Self {
518        Self::InvalidCertRevocationList(e)
519    }
520}
521
522#[non_exhaustive]
523#[derive(Debug, Clone, Eq, PartialEq)]
524/// An error that occurred while handling Encrypted Client Hello (ECH).
525pub 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
534impl From<EncryptedClientHelloError> for Error {
535    #[inline]
536    fn from(e: EncryptedClientHelloError) -> Self {
537        Self::InvalidEncryptedClientHello(e)
538    }
539}
540
541fn join<T: fmt::Debug>(items: &[T]) -> String {
542    items
543        .iter()
544        .map(|x| format!("{:?}", x))
545        .collect::<Vec<String>>()
546        .join(" or ")
547}
548
549impl fmt::Display for Error {
550    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551        match *self {
552            Self::InappropriateMessage {
553                ref expect_types,
554                ref got_type,
555            } => write!(
556                f,
557                "received unexpected message: got {:?} when expecting {}",
558                got_type,
559                join::<ContentType>(expect_types)
560            ),
561            Self::InappropriateHandshakeMessage {
562                ref expect_types,
563                ref got_type,
564            } => write!(
565                f,
566                "received unexpected handshake message: got {:?} when expecting {}",
567                got_type,
568                join::<HandshakeType>(expect_types)
569            ),
570            Self::InvalidMessage(ref typ) => {
571                write!(f, "received corrupt message of type {:?}", typ)
572            }
573            Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why),
574            Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why),
575            Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
576            Self::InvalidCertificate(ref err) => {
577                write!(f, "invalid peer certificate: {:?}", err)
578            }
579            Self::InvalidCertRevocationList(ref err) => {
580                write!(f, "invalid certificate revocation list: {:?}", err)
581            }
582            Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
583            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
584            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
585            Self::InvalidEncryptedClientHello(ref err) => {
586                write!(f, "encrypted client hello failure: {:?}", err)
587            }
588            Self::EncryptError => write!(f, "cannot encrypt message"),
589            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
590            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
591            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
592            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
593            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
594            Self::BadMaxFragmentSize => {
595                write!(f, "the supplied max_fragment_size was too small or large")
596            }
597            Self::InconsistentKeys(ref why) => {
598                write!(f, "keys may not be consistent: {:?}", why)
599            }
600            Self::General(ref err) => write!(f, "unexpected error: {}", err),
601            Self::Other(ref err) => write!(f, "other error: {}", err),
602        }
603    }
604}
605
606#[cfg(feature = "std")]
607impl From<SystemTimeError> for Error {
608    #[inline]
609    fn from(_: SystemTimeError) -> Self {
610        Self::FailedToGetCurrentTime
611    }
612}
613
614#[cfg(feature = "std")]
615impl std::error::Error for Error {}
616
617impl From<rand::GetRandomFailed> for Error {
618    fn from(_: rand::GetRandomFailed) -> Self {
619        Self::FailedToGetRandomBytes
620    }
621}
622
623mod other_error {
624    #[cfg(feature = "std")]
625    use alloc::sync::Arc;
626    use core::fmt;
627    #[cfg(feature = "std")]
628    use std::error::Error as StdError;
629
630    use super::Error;
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        fn eq(&self, _other: &Self) -> bool {
643            false
644        }
645    }
646
647    impl From<OtherError> for Error {
648        fn from(value: OtherError) -> Self {
649            Self::Other(value)
650        }
651    }
652
653    impl fmt::Display for OtherError {
654        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
655            #[cfg(feature = "std")]
656            {
657                write!(f, "{}", self.0)
658            }
659            #[cfg(not(feature = "std"))]
660            {
661                f.write_str("no further information available")
662            }
663        }
664    }
665
666    #[cfg(feature = "std")]
667    impl StdError for OtherError {
668        fn source(&self) -> Option<&(dyn StdError + 'static)> {
669            Some(self.0.as_ref())
670        }
671    }
672}
673
674pub use other_error::OtherError;
675
676#[cfg(test)]
677mod tests {
678    use std::prelude::v1::*;
679    use std::{println, vec};
680
681    use super::{CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError};
682
683    #[test]
684    fn certificate_error_equality() {
685        use super::CertificateError::*;
686        assert_eq!(BadEncoding, BadEncoding);
687        assert_eq!(Expired, Expired);
688        assert_eq!(NotValidYet, NotValidYet);
689        assert_eq!(Revoked, Revoked);
690        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
691        assert_eq!(UnknownIssuer, UnknownIssuer);
692        assert_eq!(BadSignature, BadSignature);
693        assert_eq!(NotValidForName, NotValidForName);
694        assert_eq!(InvalidPurpose, InvalidPurpose);
695        assert_eq!(
696            ApplicationVerificationFailure,
697            ApplicationVerificationFailure
698        );
699        let other = Other(OtherError(
700            #[cfg(feature = "std")]
701            alloc::sync::Arc::from(Box::from("")),
702        ));
703        assert_ne!(other, other);
704        assert_ne!(BadEncoding, Expired);
705    }
706
707    #[test]
708    fn crl_error_equality() {
709        use super::CertRevocationListError::*;
710        assert_eq!(BadSignature, BadSignature);
711        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
712        assert_eq!(
713            InvalidRevokedCertSerialNumber,
714            InvalidRevokedCertSerialNumber
715        );
716        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
717        assert_eq!(ParseError, ParseError);
718        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
719        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
720        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
721        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
722        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
723        let other = Other(OtherError(
724            #[cfg(feature = "std")]
725            alloc::sync::Arc::from(Box::from("")),
726        ));
727        assert_ne!(other, other);
728        assert_ne!(BadSignature, InvalidCrlNumber);
729    }
730
731    #[test]
732    #[cfg(feature = "std")]
733    fn other_error_equality() {
734        let other_error = OtherError(alloc::sync::Arc::from(Box::from("")));
735        assert_ne!(other_error, other_error);
736        let other: Error = other_error.into();
737        assert_ne!(other, other);
738    }
739
740    #[test]
741    fn smoke() {
742        use crate::enums::{AlertDescription, ContentType, HandshakeType};
743
744        let all = vec![
745            Error::InappropriateMessage {
746                expect_types: vec![ContentType::Alert],
747                got_type: ContentType::Handshake,
748            },
749            Error::InappropriateHandshakeMessage {
750                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
751                got_type: HandshakeType::ServerHello,
752            },
753            Error::InvalidMessage(InvalidMessage::InvalidCcs),
754            Error::NoCertificatesPresented,
755            Error::DecryptError,
756            super::PeerIncompatible::Tls12NotOffered.into(),
757            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
758            Error::AlertReceived(AlertDescription::ExportRestriction),
759            super::CertificateError::Expired.into(),
760            Error::General("undocumented error".to_string()),
761            Error::FailedToGetCurrentTime,
762            Error::FailedToGetRandomBytes,
763            Error::HandshakeNotComplete,
764            Error::PeerSentOversizedRecord,
765            Error::NoApplicationProtocol,
766            Error::BadMaxFragmentSize,
767            Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
768            Error::InconsistentKeys(InconsistentKeys::Unknown),
769            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
770            Error::Other(OtherError(
771                #[cfg(feature = "std")]
772                alloc::sync::Arc::from(Box::from("")),
773            )),
774        ];
775
776        for err in all {
777            println!("{:?}:", err);
778            println!("  fmt '{}'", err);
779        }
780    }
781
782    #[test]
783    fn rand_error_mapping() {
784        use super::rand;
785        let err: Error = rand::GetRandomFailed.into();
786        assert_eq!(err, Error::FailedToGetRandomBytes);
787    }
788
789    #[cfg(feature = "std")]
790    #[test]
791    fn time_error_mapping() {
792        use std::time::SystemTime;
793
794        let time_error = SystemTime::UNIX_EPOCH
795            .duration_since(SystemTime::now())
796            .unwrap_err();
797        let err: Error = time_error.into();
798        assert_eq!(err, Error::FailedToGetCurrentTime);
799    }
800}