rustls/
error.rs

1use alloc::format;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5use pki_types::{ServerName, UnixTime};
6#[cfg(feature = "std")]
7use std::time::SystemTimeError;
8
9use crate::enums::{AlertDescription, ContentType, HandshakeType};
10use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
11use crate::rand;
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    /// An error occurred while handling Encrypted Client Hello (ECH).
40    InvalidEncryptedClientHello(EncryptedClientHelloError),
41
42    /// The peer sent us a TLS message with invalid contents.
43    InvalidMessage(InvalidMessage),
44
45    /// The peer didn't give us any certificates.
46    NoCertificatesPresented,
47
48    /// The certificate verifier doesn't support the given type of name.
49    UnsupportedNameType,
50
51    /// We couldn't decrypt a message.  This is invariably fatal.
52    DecryptError,
53
54    /// We couldn't encrypt a message because it was larger than the allowed message size.
55    /// This should never happen if the application is using valid record sizes.
56    EncryptError,
57
58    /// The peer doesn't support a protocol version/feature we require.
59    /// The parameter gives a hint as to what version/feature it is.
60    PeerIncompatible(PeerIncompatible),
61
62    /// The peer deviated from the standard TLS protocol.
63    /// The parameter gives a hint where.
64    PeerMisbehaved(PeerMisbehaved),
65
66    /// We received a fatal alert.  This means the peer is unhappy.
67    AlertReceived(AlertDescription),
68
69    /// We saw an invalid certificate.
70    ///
71    /// The contained error is from the certificate validation trait
72    /// implementation.
73    InvalidCertificate(CertificateError),
74
75    /// A provided certificate revocation list (CRL) was invalid.
76    InvalidCertRevocationList(CertRevocationListError),
77
78    /// A catch-all error for unlikely errors.
79    General(String),
80
81    /// We failed to figure out what time it currently is.
82    FailedToGetCurrentTime,
83
84    /// We failed to acquire random bytes from the system.
85    FailedToGetRandomBytes,
86
87    /// This function doesn't work until the TLS handshake
88    /// is complete.
89    HandshakeNotComplete,
90
91    /// The peer sent an oversized record/fragment.
92    PeerSentOversizedRecord,
93
94    /// An incoming connection did not support any known application protocol.
95    NoApplicationProtocol,
96
97    /// The `max_fragment_size` value supplied in configuration was too small,
98    /// or too large.
99    BadMaxFragmentSize,
100
101    /// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
102    ///
103    /// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
104    InconsistentKeys(InconsistentKeys),
105
106    /// Any other error.
107    ///
108    /// This variant should only be used when the error is not better described by a more
109    /// specific variant. For example, if a custom crypto provider returns a
110    /// provider specific error.
111    ///
112    /// Enums holding this variant will never compare equal to each other.
113    Other(OtherError),
114}
115
116/// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
117///
118/// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
119#[non_exhaustive]
120#[derive(Clone, Copy, Debug, Eq, PartialEq)]
121pub enum InconsistentKeys {
122    /// The public key returned by the [`SigningKey`] does not match the public key information in the certificate.
123    ///
124    /// [`SigningKey`]: crate::crypto::signer::SigningKey
125    KeyMismatch,
126
127    /// The [`SigningKey`] cannot produce its corresponding public key.
128    ///
129    /// [`SigningKey`]: crate::crypto::signer::SigningKey
130    Unknown,
131}
132
133impl From<InconsistentKeys> for Error {
134    #[inline]
135    fn from(e: InconsistentKeys) -> Self {
136        Self::InconsistentKeys(e)
137    }
138}
139
140/// A corrupt TLS message payload that resulted in an error.
141#[non_exhaustive]
142#[derive(Debug, Clone, Copy, PartialEq)]
143
144pub enum InvalidMessage {
145    /// A certificate payload exceeded rustls's 64KB limit
146    CertificatePayloadTooLarge,
147    /// An advertised message was larger then expected.
148    HandshakePayloadTooLarge,
149    /// The peer sent us a syntactically incorrect ChangeCipherSpec payload.
150    InvalidCcs,
151    /// An unknown content type was encountered during message decoding.
152    InvalidContentType,
153    /// A peer sent an invalid certificate status type
154    InvalidCertificateStatusType,
155    /// Context was incorrectly attached to a certificate request during a handshake.
156    InvalidCertRequest,
157    /// A peer's DH params could not be decoded
158    InvalidDhParams,
159    /// A message was zero-length when its record kind forbids it.
160    InvalidEmptyPayload,
161    /// A peer sent an unexpected key update request.
162    InvalidKeyUpdate,
163    /// A peer's server name could not be decoded
164    InvalidServerName,
165    /// A TLS message payload was larger then allowed by the specification.
166    MessageTooLarge,
167    /// Message is shorter than the expected length
168    MessageTooShort,
169    /// Missing data for the named handshake payload value
170    MissingData(&'static str),
171    /// A peer did not advertise its supported key exchange groups.
172    MissingKeyExchange,
173    /// A peer sent an empty list of signature schemes
174    NoSignatureSchemes,
175    /// Trailing data found for the named handshake payload value
176    TrailingData(&'static str),
177    /// A peer sent an unexpected message type.
178    UnexpectedMessage(&'static str),
179    /// An unknown TLS protocol was encountered during message decoding.
180    UnknownProtocolVersion,
181    /// A peer sent a non-null compression method.
182    UnsupportedCompression,
183    /// A peer sent an unknown elliptic curve type.
184    UnsupportedCurveType,
185    /// A peer sent an unsupported key exchange algorithm.
186    UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
187}
188
189impl From<InvalidMessage> for Error {
190    #[inline]
191    fn from(e: InvalidMessage) -> Self {
192        Self::InvalidMessage(e)
193    }
194}
195
196#[non_exhaustive]
197#[allow(missing_docs)]
198#[derive(Debug, PartialEq, Clone)]
199/// The set of cases where we failed to make a connection because we thought
200/// the peer was misbehaving.
201///
202/// This is `non_exhaustive`: we might add or stop using items here in minor
203/// versions.  We also don't document what they mean.  Generally a user of
204/// rustls shouldn't vary its behaviour on these error codes, and there is
205/// nothing it can do to improve matters.
206///
207/// Please file a bug against rustls if you see `Error::PeerMisbehaved` in
208/// the wild.
209pub enum PeerMisbehaved {
210    AttemptedDowngradeToTls12WhenTls13IsSupported,
211    BadCertChainExtensions,
212    DisallowedEncryptedExtension,
213    DuplicateClientHelloExtensions,
214    DuplicateEncryptedExtensions,
215    DuplicateHelloRetryRequestExtensions,
216    DuplicateNewSessionTicketExtensions,
217    DuplicateServerHelloExtensions,
218    DuplicateServerNameTypes,
219    EarlyDataAttemptedInSecondClientHello,
220    EarlyDataExtensionWithoutResumption,
221    EarlyDataOfferedWithVariedCipherSuite,
222    HandshakeHashVariedAfterRetry,
223    IllegalHelloRetryRequestWithEmptyCookie,
224    IllegalHelloRetryRequestWithNoChanges,
225    IllegalHelloRetryRequestWithOfferedGroup,
226    IllegalHelloRetryRequestWithUnofferedCipherSuite,
227    IllegalHelloRetryRequestWithUnofferedNamedGroup,
228    IllegalHelloRetryRequestWithUnsupportedVersion,
229    IllegalHelloRetryRequestWithWrongSessionId,
230    IllegalHelloRetryRequestWithInvalidEch,
231    IllegalMiddleboxChangeCipherSpec,
232    IllegalTlsInnerPlaintext,
233    IncorrectBinder,
234    InvalidCertCompression,
235    InvalidMaxEarlyDataSize,
236    InvalidKeyShare,
237    KeyEpochWithPendingFragment,
238    KeyUpdateReceivedInQuicConnection,
239    MessageInterleavedWithHandshakeMessage,
240    MissingBinderInPskExtension,
241    MissingKeyShare,
242    MissingPskModesExtension,
243    MissingQuicTransportParameters,
244    OfferedDuplicateCertificateCompressions,
245    OfferedDuplicateKeyShares,
246    OfferedEarlyDataWithOldProtocolVersion,
247    OfferedEmptyApplicationProtocol,
248    OfferedIncorrectCompressions,
249    PskExtensionMustBeLast,
250    PskExtensionWithMismatchedIdsAndBinders,
251    RefusedToFollowHelloRetryRequest,
252    RejectedEarlyDataInterleavedWithHandshakeMessage,
253    ResumptionAttemptedWithVariedEms,
254    ResumptionOfferedWithVariedCipherSuite,
255    ResumptionOfferedWithVariedEms,
256    ResumptionOfferedWithIncompatibleCipherSuite,
257    SelectedDifferentCipherSuiteAfterRetry,
258    SelectedInvalidPsk,
259    SelectedTls12UsingTls13VersionExtension,
260    SelectedUnofferedApplicationProtocol,
261    SelectedUnofferedCertCompression,
262    SelectedUnofferedCipherSuite,
263    SelectedUnofferedCompression,
264    SelectedUnofferedKxGroup,
265    SelectedUnofferedPsk,
266    SelectedUnusableCipherSuiteForVersion,
267    ServerEchoedCompatibilitySessionId,
268    ServerHelloMustOfferUncompressedEcPoints,
269    ServerNameDifferedOnRetry,
270    ServerNameMustContainOneHostName,
271    SignedKxWithWrongAlgorithm,
272    SignedHandshakeWithUnadvertisedSigScheme,
273    TooManyEmptyFragments,
274    TooManyKeyUpdateRequests,
275    TooManyRenegotiationRequests,
276    TooManyWarningAlertsReceived,
277    TooMuchEarlyDataReceived,
278    UnexpectedCleartextExtension,
279    UnsolicitedCertExtension,
280    UnsolicitedEncryptedExtension,
281    UnsolicitedSctList,
282    UnsolicitedServerHelloExtension,
283    WrongGroupForKeyShare,
284    UnsolicitedEchExtension,
285}
286
287impl From<PeerMisbehaved> for Error {
288    #[inline]
289    fn from(e: PeerMisbehaved) -> Self {
290        Self::PeerMisbehaved(e)
291    }
292}
293
294#[non_exhaustive]
295#[allow(missing_docs)]
296#[derive(Debug, PartialEq, Clone)]
297/// The set of cases where we failed to make a connection because a peer
298/// doesn't support a TLS version/feature we require.
299///
300/// This is `non_exhaustive`: we might add or stop using items here in minor
301/// versions.
302pub enum PeerIncompatible {
303    EcPointsExtensionRequired,
304    ExtendedMasterSecretExtensionRequired,
305    IncorrectCertificateTypeExtension,
306    KeyShareExtensionRequired,
307    NamedGroupsExtensionRequired,
308    NoCertificateRequestSignatureSchemesInCommon,
309    NoCipherSuitesInCommon,
310    NoEcPointFormatsInCommon,
311    NoKxGroupsInCommon,
312    NoSignatureSchemesInCommon,
313    NullCompressionRequired,
314    ServerDoesNotSupportTls12Or13,
315    ServerSentHelloRetryRequestWithUnknownExtension,
316    ServerTlsVersionIsDisabledByOurConfig,
317    SignatureAlgorithmsExtensionRequired,
318    SupportedVersionsExtensionRequired,
319    Tls12NotOffered,
320    Tls12NotOfferedOrEnabled,
321    Tls13RequiredForQuic,
322    UncompressedEcPointsRequired,
323    UnsolicitedCertificateTypeExtension,
324    ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
325}
326
327impl From<PeerIncompatible> for Error {
328    #[inline]
329    fn from(e: PeerIncompatible) -> Self {
330        Self::PeerIncompatible(e)
331    }
332}
333
334#[non_exhaustive]
335#[derive(Debug, Clone)]
336/// The ways in which certificate validators can express errors.
337///
338/// Note that the rustls TLS protocol code interprets specifically these
339/// error codes to send specific TLS alerts.  Therefore, if a
340/// custom certificate validator uses incorrect errors the library as
341/// a whole will send alerts that do not match the standard (this is usually
342/// a minor issue, but could be misleading).
343pub enum CertificateError {
344    /// The certificate is not correctly encoded.
345    BadEncoding,
346
347    /// The current time is after the `notAfter` time in the certificate.
348    Expired,
349
350    /// The current time is after the `notAfter` time in the certificate.
351    ///
352    /// This variant is semantically the same as `Expired`, but includes
353    /// extra data to improve error reports.
354    ExpiredContext {
355        /// The validation time.
356        time: UnixTime,
357        /// The `notAfter` time of the certificate.
358        not_after: UnixTime,
359    },
360
361    /// The current time is before the `notBefore` time in the certificate.
362    NotValidYet,
363
364    /// The current time is before the `notBefore` time in the certificate.
365    ///
366    /// This variant is semantically the same as `NotValidYet`, but includes
367    /// extra data to improve error reports.
368    NotValidYetContext {
369        /// The validation time.
370        time: UnixTime,
371        /// The `notBefore` time of the certificate.
372        not_before: UnixTime,
373    },
374
375    /// The certificate has been revoked.
376    Revoked,
377
378    /// The certificate contains an extension marked critical, but it was
379    /// not processed by the certificate validator.
380    UnhandledCriticalExtension,
381
382    /// The certificate chain is not issued by a known root certificate.
383    UnknownIssuer,
384
385    /// The certificate's revocation status could not be determined.
386    UnknownRevocationStatus,
387
388    /// The certificate's revocation status could not be determined, because the CRL is expired.
389    ExpiredRevocationList,
390
391    /// The certificate's revocation status could not be determined, because the CRL is expired.
392    ///
393    /// This variant is semantically the same as `ExpiredRevocationList`, but includes
394    /// extra data to improve error reports.
395    ExpiredRevocationListContext {
396        /// The validation time.
397        time: UnixTime,
398        /// The nextUpdate time of the CRL.
399        next_update: UnixTime,
400    },
401
402    /// A certificate is not correctly signed by the key of its alleged
403    /// issuer.
404    BadSignature,
405
406    /// The subject names in an end-entity certificate do not include
407    /// the expected name.
408    NotValidForName,
409
410    /// The subject names in an end-entity certificate do not include
411    /// the expected name.
412    ///
413    /// This variant is semantically the same as `NotValidForName`, but includes
414    /// extra data to improve error reports.
415    NotValidForNameContext {
416        /// Expected server name.
417        expected: ServerName<'static>,
418
419        /// The names presented in the end entity certificate.
420        ///
421        /// These are the subject names as present in the leaf certificate and may contain DNS names
422        /// with or without a wildcard label as well as IP address names.
423        presented: Vec<String>,
424    },
425
426    /// The certificate is being used for a different purpose than allowed.
427    InvalidPurpose,
428
429    /// The certificate is valid, but the handshake is rejected for other
430    /// reasons.
431    ApplicationVerificationFailure,
432
433    /// Any other error.
434    ///
435    /// This can be used by custom verifiers to expose the underlying error
436    /// (where they are not better described by the more specific errors
437    /// above).
438    ///
439    /// It is also used by the default verifier in case its error is
440    /// not covered by the above common cases.
441    ///
442    /// Enums holding this variant will never compare equal to each other.
443    Other(OtherError),
444}
445
446impl PartialEq<Self> for CertificateError {
447    fn eq(&self, other: &Self) -> bool {
448        use CertificateError::*;
449        #[allow(clippy::match_like_matches_macro)]
450        match (self, other) {
451            (BadEncoding, BadEncoding) => true,
452            (Expired, Expired) => true,
453            (
454                ExpiredContext {
455                    time: left_time,
456                    not_after: left_not_after,
457                },
458                ExpiredContext {
459                    time: right_time,
460                    not_after: right_not_after,
461                },
462            ) => (left_time, left_not_after) == (right_time, right_not_after),
463            (NotValidYet, NotValidYet) => true,
464            (
465                NotValidYetContext {
466                    time: left_time,
467                    not_before: left_not_before,
468                },
469                NotValidYetContext {
470                    time: right_time,
471                    not_before: right_not_before,
472                },
473            ) => (left_time, left_not_before) == (right_time, right_not_before),
474            (Revoked, Revoked) => true,
475            (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
476            (UnknownIssuer, UnknownIssuer) => true,
477            (BadSignature, BadSignature) => true,
478            (NotValidForName, NotValidForName) => true,
479            (
480                NotValidForNameContext {
481                    expected: left_expected,
482                    presented: left_presented,
483                },
484                NotValidForNameContext {
485                    expected: right_expected,
486                    presented: right_presented,
487                },
488            ) => (left_expected, left_presented) == (right_expected, right_presented),
489            (InvalidPurpose, InvalidPurpose) => true,
490            (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
491            (UnknownRevocationStatus, UnknownRevocationStatus) => true,
492            (ExpiredRevocationList, ExpiredRevocationList) => true,
493            (
494                ExpiredRevocationListContext {
495                    time: left_time,
496                    next_update: left_next_update,
497                },
498                ExpiredRevocationListContext {
499                    time: right_time,
500                    next_update: right_next_update,
501                },
502            ) => (left_time, left_next_update) == (right_time, right_next_update),
503            _ => false,
504        }
505    }
506}
507
508// The following mapping are heavily referenced in:
509// * [OpenSSL Implementation](https://github.com/openssl/openssl/blob/45bb98bfa223efd3258f445ad443f878011450f0/ssl/statem/statem_lib.c#L1434)
510// * [BoringSSL Implementation](https://github.com/google/boringssl/blob/583c60bd4bf76d61b2634a58bcda99a92de106cb/ssl/ssl_x509.cc#L1323)
511impl From<CertificateError> for AlertDescription {
512    fn from(e: CertificateError) -> Self {
513        use CertificateError::*;
514        match e {
515            BadEncoding
516            | UnhandledCriticalExtension
517            | NotValidForName
518            | NotValidForNameContext { .. } => Self::BadCertificate,
519            // RFC 5246/RFC 8446
520            // certificate_expired
521            //  A certificate has expired or **is not currently valid**.
522            Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
523                Self::CertificateExpired
524            }
525            Revoked => Self::CertificateRevoked,
526            // OpenSSL, BoringSSL and AWS-LC all generate an Unknown CA alert for
527            // the case where revocation status can not be determined, so we do the same here.
528            UnknownIssuer
529            | UnknownRevocationStatus
530            | ExpiredRevocationList
531            | ExpiredRevocationListContext { .. } => Self::UnknownCA,
532            BadSignature => Self::DecryptError,
533            InvalidPurpose => Self::UnsupportedCertificate,
534            ApplicationVerificationFailure => Self::AccessDenied,
535            // RFC 5246/RFC 8446
536            // certificate_unknown
537            //  Some other (unspecified) issue arose in processing the
538            //  certificate, rendering it unacceptable.
539            Other(..) => Self::CertificateUnknown,
540        }
541    }
542}
543
544impl fmt::Display for CertificateError {
545    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546        match self {
547            #[cfg(feature = "std")]
548            Self::NotValidForNameContext {
549                expected,
550                presented,
551            } => {
552                write!(
553                    f,
554                    "certificate not valid for name {:?}; certificate ",
555                    expected.to_str()
556                )?;
557
558                match presented.as_slice() {
559                    &[] => write!(
560                        f,
561                        "is not valid for any names (according to its subjectAltName extension)"
562                    ),
563                    [one] => write!(f, "is only valid for {}", one),
564                    many => {
565                        write!(f, "is only valid for ")?;
566
567                        let n = many.len();
568                        let all_but_last = &many[..n - 1];
569                        let last = &many[n - 1];
570
571                        for (i, name) in all_but_last.iter().enumerate() {
572                            write!(f, "{}", name)?;
573                            if i < n - 2 {
574                                write!(f, ", ")?;
575                            }
576                        }
577                        write!(f, " or {}", last)
578                    }
579                }
580            }
581
582            Self::ExpiredContext { time, not_after } => write!(
583                f,
584                "certificate expired: verification time {} (UNIX), \
585                 but certificate is not valid after {} \
586                 ({} seconds ago)",
587                time.as_secs(),
588                not_after.as_secs(),
589                time.as_secs()
590                    .saturating_sub(not_after.as_secs())
591            ),
592
593            Self::NotValidYetContext { time, not_before } => write!(
594                f,
595                "certificate not valid yet: verification time {} (UNIX), \
596                 but certificate is not valid before {} \
597                 ({} seconds in future)",
598                time.as_secs(),
599                not_before.as_secs(),
600                not_before
601                    .as_secs()
602                    .saturating_sub(time.as_secs())
603            ),
604
605            Self::ExpiredRevocationListContext { time, next_update } => write!(
606                f,
607                "certificate revocation list expired: \
608                 verification time {} (UNIX), \
609                 but CRL is not valid after {} \
610                 ({} seconds ago)",
611                time.as_secs(),
612                next_update.as_secs(),
613                time.as_secs()
614                    .saturating_sub(next_update.as_secs())
615            ),
616
617            other => write!(f, "{:?}", other),
618        }
619    }
620}
621
622impl From<CertificateError> for Error {
623    #[inline]
624    fn from(e: CertificateError) -> Self {
625        Self::InvalidCertificate(e)
626    }
627}
628
629#[non_exhaustive]
630#[derive(Debug, Clone)]
631/// The ways in which a certificate revocation list (CRL) can be invalid.
632pub enum CertRevocationListError {
633    /// The CRL had a bad, or unsupported signature from its issuer.
634    BadSignature,
635
636    /// The CRL contained an invalid CRL number.
637    InvalidCrlNumber,
638
639    /// The CRL contained a revoked certificate with an invalid serial number.
640    InvalidRevokedCertSerialNumber,
641
642    /// The CRL issuer does not specify the cRLSign key usage.
643    IssuerInvalidForCrl,
644
645    /// The CRL is invalid for some other reason.
646    ///
647    /// Enums holding this variant will never compare equal to each other.
648    Other(OtherError),
649
650    /// The CRL is not correctly encoded.
651    ParseError,
652
653    /// The CRL is not a v2 X.509 CRL.
654    UnsupportedCrlVersion,
655
656    /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
657    UnsupportedCriticalExtension,
658
659    /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
660    UnsupportedDeltaCrl,
661
662    /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
663    /// other than the issuer of the CRL.
664    UnsupportedIndirectCrl,
665
666    /// The CRL contained a revoked certificate with an unsupported revocation reason.
667    /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
668    ///
669    /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
670    UnsupportedRevocationReason,
671}
672
673impl PartialEq<Self> for CertRevocationListError {
674    fn eq(&self, other: &Self) -> bool {
675        use CertRevocationListError::*;
676        #[allow(clippy::match_like_matches_macro)]
677        match (self, other) {
678            (BadSignature, BadSignature) => true,
679            (InvalidCrlNumber, InvalidCrlNumber) => true,
680            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
681            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
682            (ParseError, ParseError) => true,
683            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
684            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
685            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
686            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
687            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
688            _ => false,
689        }
690    }
691}
692
693impl From<CertRevocationListError> for Error {
694    #[inline]
695    fn from(e: CertRevocationListError) -> Self {
696        Self::InvalidCertRevocationList(e)
697    }
698}
699
700#[non_exhaustive]
701#[derive(Debug, Clone, Eq, PartialEq)]
702/// An error that occurred while handling Encrypted Client Hello (ECH).
703pub enum EncryptedClientHelloError {
704    /// The provided ECH configuration list was invalid.
705    InvalidConfigList,
706    /// No compatible ECH configuration.
707    NoCompatibleConfig,
708    /// The client configuration has server name indication (SNI) disabled.
709    SniRequired,
710}
711
712impl From<EncryptedClientHelloError> for Error {
713    #[inline]
714    fn from(e: EncryptedClientHelloError) -> Self {
715        Self::InvalidEncryptedClientHello(e)
716    }
717}
718
719fn join<T: fmt::Debug>(items: &[T]) -> String {
720    items
721        .iter()
722        .map(|x| format!("{:?}", x))
723        .collect::<Vec<String>>()
724        .join(" or ")
725}
726
727impl fmt::Display for Error {
728    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
729        match self {
730            Self::InappropriateMessage {
731                expect_types,
732                got_type,
733            } => write!(
734                f,
735                "received unexpected message: got {:?} when expecting {}",
736                got_type,
737                join::<ContentType>(expect_types)
738            ),
739            Self::InappropriateHandshakeMessage {
740                expect_types,
741                got_type,
742            } => write!(
743                f,
744                "received unexpected handshake message: got {:?} when expecting {}",
745                got_type,
746                join::<HandshakeType>(expect_types)
747            ),
748            Self::InvalidMessage(typ) => {
749                write!(f, "received corrupt message of type {:?}", typ)
750            }
751            Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {:?}", why),
752            Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {:?}", why),
753            Self::AlertReceived(alert) => write!(f, "received fatal alert: {:?}", alert),
754            Self::InvalidCertificate(err) => {
755                write!(f, "invalid peer certificate: {}", err)
756            }
757            Self::InvalidCertRevocationList(err) => {
758                write!(f, "invalid certificate revocation list: {:?}", err)
759            }
760            Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
761            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
762            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
763            Self::InvalidEncryptedClientHello(err) => {
764                write!(f, "encrypted client hello failure: {:?}", err)
765            }
766            Self::EncryptError => write!(f, "cannot encrypt message"),
767            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
768            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
769            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
770            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
771            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
772            Self::BadMaxFragmentSize => {
773                write!(f, "the supplied max_fragment_size was too small or large")
774            }
775            Self::InconsistentKeys(why) => {
776                write!(f, "keys may not be consistent: {:?}", why)
777            }
778            Self::General(err) => write!(f, "unexpected error: {}", err),
779            Self::Other(err) => write!(f, "other error: {}", err),
780        }
781    }
782}
783
784#[cfg(feature = "std")]
785impl From<SystemTimeError> for Error {
786    #[inline]
787    fn from(_: SystemTimeError) -> Self {
788        Self::FailedToGetCurrentTime
789    }
790}
791
792#[cfg(feature = "std")]
793impl std::error::Error for Error {}
794
795impl From<rand::GetRandomFailed> for Error {
796    fn from(_: rand::GetRandomFailed) -> Self {
797        Self::FailedToGetRandomBytes
798    }
799}
800
801mod other_error {
802    use core::fmt;
803    #[cfg(feature = "std")]
804    use std::error::Error as StdError;
805
806    use super::Error;
807    #[cfg(feature = "std")]
808    use crate::sync::Arc;
809
810    /// Any other error that cannot be expressed by a more specific [`Error`] variant.
811    ///
812    /// For example, an `OtherError` could be produced by a custom crypto provider
813    /// exposing a provider specific error.
814    ///
815    /// Enums holding this type will never compare equal to each other.
816    #[derive(Debug, Clone)]
817    pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
818
819    impl PartialEq<Self> for OtherError {
820        fn eq(&self, _other: &Self) -> bool {
821            false
822        }
823    }
824
825    impl From<OtherError> for Error {
826        fn from(value: OtherError) -> Self {
827            Self::Other(value)
828        }
829    }
830
831    impl fmt::Display for OtherError {
832        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
833            #[cfg(feature = "std")]
834            {
835                write!(f, "{}", self.0)
836            }
837            #[cfg(not(feature = "std"))]
838            {
839                f.write_str("no further information available")
840            }
841        }
842    }
843
844    #[cfg(feature = "std")]
845    impl StdError for OtherError {
846        fn source(&self) -> Option<&(dyn StdError + 'static)> {
847            Some(self.0.as_ref())
848        }
849    }
850}
851
852pub use other_error::OtherError;
853
854#[cfg(test)]
855mod tests {
856    use core::time::Duration;
857    use std::prelude::v1::*;
858    use std::{println, vec};
859
860    use super::{
861        CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError, UnixTime,
862    };
863    #[cfg(feature = "std")]
864    use crate::sync::Arc;
865    use pki_types::ServerName;
866
867    #[test]
868    fn certificate_error_equality() {
869        use super::CertificateError::*;
870        assert_eq!(BadEncoding, BadEncoding);
871        assert_eq!(Expired, Expired);
872        let context = ExpiredContext {
873            time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
874            not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
875        };
876        assert_eq!(context, context);
877        assert_ne!(
878            context,
879            ExpiredContext {
880                time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
881                not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
882            }
883        );
884        assert_ne!(
885            context,
886            ExpiredContext {
887                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
888                not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
889            }
890        );
891        assert_eq!(NotValidYet, NotValidYet);
892        let context = NotValidYetContext {
893            time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
894            not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
895        };
896        assert_eq!(context, context);
897        assert_ne!(
898            context,
899            NotValidYetContext {
900                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
901                not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
902            }
903        );
904        assert_ne!(
905            context,
906            NotValidYetContext {
907                time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
908                not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
909            }
910        );
911        assert_eq!(Revoked, Revoked);
912        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
913        assert_eq!(UnknownIssuer, UnknownIssuer);
914        assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
915        assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
916        let context = ExpiredRevocationListContext {
917            time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
918            next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
919        };
920        assert_eq!(context, context);
921        assert_ne!(
922            context,
923            ExpiredRevocationListContext {
924                time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
925                next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
926            }
927        );
928        assert_ne!(
929            context,
930            ExpiredRevocationListContext {
931                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
932                next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
933            }
934        );
935        assert_eq!(BadSignature, BadSignature);
936        assert_eq!(NotValidForName, NotValidForName);
937        let context = NotValidForNameContext {
938            expected: ServerName::try_from("example.com")
939                .unwrap()
940                .to_owned(),
941            presented: vec!["other.com".into()],
942        };
943        assert_eq!(context, context);
944        assert_ne!(
945            context,
946            NotValidForNameContext {
947                expected: ServerName::try_from("example.com")
948                    .unwrap()
949                    .to_owned(),
950                presented: vec![]
951            }
952        );
953        assert_ne!(
954            context,
955            NotValidForNameContext {
956                expected: ServerName::try_from("huh.com")
957                    .unwrap()
958                    .to_owned(),
959                presented: vec!["other.com".into()],
960            }
961        );
962        assert_eq!(InvalidPurpose, InvalidPurpose);
963        assert_eq!(
964            ApplicationVerificationFailure,
965            ApplicationVerificationFailure
966        );
967        let other = Other(OtherError(
968            #[cfg(feature = "std")]
969            Arc::from(Box::from("")),
970        ));
971        assert_ne!(other, other);
972        assert_ne!(BadEncoding, Expired);
973    }
974
975    #[test]
976    fn crl_error_equality() {
977        use super::CertRevocationListError::*;
978        assert_eq!(BadSignature, BadSignature);
979        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
980        assert_eq!(
981            InvalidRevokedCertSerialNumber,
982            InvalidRevokedCertSerialNumber
983        );
984        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
985        assert_eq!(ParseError, ParseError);
986        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
987        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
988        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
989        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
990        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
991        let other = Other(OtherError(
992            #[cfg(feature = "std")]
993            Arc::from(Box::from("")),
994        ));
995        assert_ne!(other, other);
996        assert_ne!(BadSignature, InvalidCrlNumber);
997    }
998
999    #[test]
1000    #[cfg(feature = "std")]
1001    fn other_error_equality() {
1002        let other_error = OtherError(Arc::from(Box::from("")));
1003        assert_ne!(other_error, other_error);
1004        let other: Error = other_error.into();
1005        assert_ne!(other, other);
1006    }
1007
1008    #[test]
1009    fn smoke() {
1010        use crate::enums::{AlertDescription, ContentType, HandshakeType};
1011
1012        let all = vec![
1013            Error::InappropriateMessage {
1014                expect_types: vec![ContentType::Alert],
1015                got_type: ContentType::Handshake,
1016            },
1017            Error::InappropriateHandshakeMessage {
1018                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
1019                got_type: HandshakeType::ServerHello,
1020            },
1021            Error::InvalidMessage(InvalidMessage::InvalidCcs),
1022            Error::NoCertificatesPresented,
1023            Error::DecryptError,
1024            super::PeerIncompatible::Tls12NotOffered.into(),
1025            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
1026            Error::AlertReceived(AlertDescription::ExportRestriction),
1027            super::CertificateError::Expired.into(),
1028            super::CertificateError::NotValidForNameContext {
1029                expected: ServerName::try_from("example.com")
1030                    .unwrap()
1031                    .to_owned(),
1032                presented: vec![],
1033            }
1034            .into(),
1035            super::CertificateError::NotValidForNameContext {
1036                expected: ServerName::try_from("example.com")
1037                    .unwrap()
1038                    .to_owned(),
1039                presented: vec!["DnsName(\"hello.com\")".into()],
1040            }
1041            .into(),
1042            super::CertificateError::NotValidForNameContext {
1043                expected: ServerName::try_from("example.com")
1044                    .unwrap()
1045                    .to_owned(),
1046                presented: vec![
1047                    "DnsName(\"hello.com\")".into(),
1048                    "DnsName(\"goodbye.com\")".into(),
1049                ],
1050            }
1051            .into(),
1052            super::CertificateError::NotValidYetContext {
1053                time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1054                not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1055            }
1056            .into(),
1057            super::CertificateError::ExpiredContext {
1058                time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1059                not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1060            }
1061            .into(),
1062            super::CertificateError::ExpiredRevocationListContext {
1063                time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1064                next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1065            }
1066            .into(),
1067            Error::General("undocumented error".to_string()),
1068            Error::FailedToGetCurrentTime,
1069            Error::FailedToGetRandomBytes,
1070            Error::HandshakeNotComplete,
1071            Error::PeerSentOversizedRecord,
1072            Error::NoApplicationProtocol,
1073            Error::BadMaxFragmentSize,
1074            Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
1075            Error::InconsistentKeys(InconsistentKeys::Unknown),
1076            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
1077            Error::Other(OtherError(
1078                #[cfg(feature = "std")]
1079                Arc::from(Box::from("")),
1080            )),
1081        ];
1082
1083        for err in all {
1084            println!("{:?}:", err);
1085            println!("  fmt '{}'", err);
1086        }
1087    }
1088
1089    #[test]
1090    fn rand_error_mapping() {
1091        use super::rand;
1092        let err: Error = rand::GetRandomFailed.into();
1093        assert_eq!(err, Error::FailedToGetRandomBytes);
1094    }
1095
1096    #[cfg(feature = "std")]
1097    #[test]
1098    fn time_error_mapping() {
1099        use std::time::SystemTime;
1100
1101        let time_error = SystemTime::UNIX_EPOCH
1102            .duration_since(SystemTime::now())
1103            .unwrap_err();
1104        let err: Error = time_error.into();
1105        assert_eq!(err, Error::FailedToGetCurrentTime);
1106    }
1107}