rustls/
error.rs

1//! Error types used throughout rustls.
2
3use alloc::format;
4use alloc::string::String;
5use alloc::vec::Vec;
6use core::fmt;
7#[cfg(feature = "std")]
8use std::time::SystemTimeError;
9
10use pki_types::{AlgorithmIdentifier, EchConfigListBytes, ServerName, UnixTime};
11use webpki::ExtendedKeyUsage;
12
13use crate::enums::{AlertDescription, ContentType, HandshakeType};
14use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
15use crate::rand;
16
17/// rustls reports protocol errors using this type.
18#[non_exhaustive]
19#[derive(Debug, PartialEq, Clone)]
20pub enum Error {
21    /// We received a TLS message that isn't valid right now.
22    /// `expect_types` lists the message types we can expect right now.
23    /// `got_type` is the type we found.  This error is typically
24    /// caused by a buggy TLS stack (the peer or this one), a broken
25    /// network, or an attack.
26    InappropriateMessage {
27        /// Which types we expected
28        expect_types: Vec<ContentType>,
29        /// What type we received
30        got_type: ContentType,
31    },
32
33    /// We received a TLS handshake message that isn't valid right now.
34    /// `expect_types` lists the handshake message types we can expect
35    /// right now.  `got_type` is the type we found.
36    InappropriateHandshakeMessage {
37        /// Which handshake type we expected
38        expect_types: Vec<HandshakeType>,
39        /// What handshake type we received
40        got_type: HandshakeType,
41    },
42
43    /// An error occurred while handling Encrypted Client Hello (ECH).
44    InvalidEncryptedClientHello(EncryptedClientHelloError),
45
46    /// The peer sent us a TLS message with invalid contents.
47    InvalidMessage(InvalidMessage),
48
49    /// The certificate verifier doesn't support the given type of name.
50    UnsupportedNameType,
51
52    /// We couldn't decrypt a message.  This is invariably fatal.
53    DecryptError,
54
55    /// We couldn't encrypt a message because it was larger than the allowed message size.
56    /// This should never happen if the application is using valid record sizes.
57    EncryptError,
58
59    /// The peer doesn't support a protocol version/feature we require.
60    /// The parameter gives a hint as to what version/feature it is.
61    PeerIncompatible(PeerIncompatible),
62
63    /// The peer deviated from the standard TLS protocol.
64    /// The parameter gives a hint where.
65    PeerMisbehaved(PeerMisbehaved),
66
67    /// We received a fatal alert.  This means the peer is unhappy.
68    AlertReceived(AlertDescription),
69
70    /// We saw an invalid certificate.
71    ///
72    /// The contained error is from the certificate validation trait
73    /// implementation.
74    InvalidCertificate(CertificateError),
75
76    /// A provided certificate revocation list (CRL) was invalid.
77    InvalidCertRevocationList(CertRevocationListError),
78
79    /// A catch-all error for unlikely errors.
80    General(String),
81
82    /// We failed to figure out what time it currently is.
83    FailedToGetCurrentTime,
84
85    /// We failed to acquire random bytes from the system.
86    FailedToGetRandomBytes,
87
88    /// This function doesn't work until the TLS handshake
89    /// is complete.
90    HandshakeNotComplete,
91
92    /// The peer sent an oversized record/fragment.
93    PeerSentOversizedRecord,
94
95    /// An incoming connection did not support any known application protocol.
96    NoApplicationProtocol,
97
98    /// The server certificate resolver didn't find an appropriate certificate.
99    NoSuitableCertificate,
100
101    /// The `max_fragment_size` value supplied in configuration was too small,
102    /// or too large.
103    BadMaxFragmentSize,
104
105    /// Specific failure cases from [`Credentials::new()`] or a
106    /// [`crate::crypto::SigningKey`] that cannot produce a corresponding public key.
107    ///
108    /// If encountered while building a [`Credentials`], consider if
109    /// [`Credentials::new_unchecked()`] might be appropriate for your use case.
110    ///
111    /// [`Credentials::new()`]: crate::crypto::Credentials::new()
112    /// [`Credentials`]: crate::crypto::Credentials
113    /// [`Credentials::new_unchecked()`]: crate::crypto::Credentials::new_unchecked()
114    InconsistentKeys(InconsistentKeys),
115
116    /// The server rejected encrypted client hello (ECH) negotiation
117    ///
118    /// It may have returned new ECH configurations that could be used to retry negotiation
119    /// with a fresh connection.
120    ///
121    /// See [`RejectedEch::can_retry()`] and [`crate::client::EchConfig::for_retry()`].
122    RejectedEch(RejectedEch),
123
124    /// Errors of this variant should never be produced by the library.
125    ///
126    /// Please file a bug if you see one.
127    Unreachable(&'static str),
128
129    /// The caller misused the API
130    ///
131    /// Generally we try to make error cases like this unnecessary by embedding
132    /// the constraints in the type system, so misuses simply do not compile.  But,
133    /// for cases where that is not possible or exceptionally costly, we return errors
134    /// of this variant.
135    ///
136    /// This only results from the ordering, dependencies or parameter values of calls,
137    /// so (assuming parameter values are fixed) these can be determined and fixed by
138    /// reading the code.  They are never caused by the values of untrusted data, or
139    /// other non-determinism.
140    ApiMisuse(ApiMisuse),
141
142    /// Any other error.
143    ///
144    /// This variant should only be used when the error is not better described by a more
145    /// specific variant. For example, if a custom crypto provider returns a
146    /// provider specific error.
147    ///
148    /// Enums holding this variant will never compare equal to each other.
149    Other(OtherError),
150}
151
152/// Specific failure cases from [`Credentials::new()`] or a [`crate::crypto::SigningKey`] that cannot produce a corresponding public key.
153///
154/// [`Credentials::new()`]: crate::crypto::Credentials::new()
155#[non_exhaustive]
156#[derive(Clone, Copy, Debug, Eq, PartialEq)]
157pub enum InconsistentKeys {
158    /// The public key returned by the [`SigningKey`] does not match the public key information in the certificate.
159    ///
160    /// [`SigningKey`]: crate::crypto::SigningKey
161    KeyMismatch,
162
163    /// The [`SigningKey`] cannot produce its corresponding public key.
164    ///
165    /// [`SigningKey`]: crate::crypto::SigningKey
166    Unknown,
167}
168
169impl From<InconsistentKeys> for Error {
170    #[inline]
171    fn from(e: InconsistentKeys) -> Self {
172        Self::InconsistentKeys(e)
173    }
174}
175
176/// A corrupt TLS message payload that resulted in an error.
177#[non_exhaustive]
178#[derive(Debug, Clone, Copy, PartialEq)]
179pub enum InvalidMessage {
180    /// A certificate payload exceeded rustls's 64KB limit
181    CertificatePayloadTooLarge,
182    /// An advertised message was larger then expected.
183    HandshakePayloadTooLarge,
184    /// The peer sent us a syntactically incorrect ChangeCipherSpec payload.
185    InvalidCcs,
186    /// An unknown content type was encountered during message decoding.
187    InvalidContentType,
188    /// A peer sent an invalid certificate status type
189    InvalidCertificateStatusType,
190    /// Context was incorrectly attached to a certificate request during a handshake.
191    InvalidCertRequest,
192    /// A peer's DH params could not be decoded
193    InvalidDhParams,
194    /// A message was zero-length when its record kind forbids it.
195    InvalidEmptyPayload,
196    /// A peer sent an unexpected key update request.
197    InvalidKeyUpdate,
198    /// A peer's server name could not be decoded
199    InvalidServerName,
200    /// A TLS message payload was larger then allowed by the specification.
201    MessageTooLarge,
202    /// Message is shorter than the expected length
203    MessageTooShort,
204    /// Missing data for the named handshake payload value
205    MissingData(&'static str),
206    /// A peer did not advertise its supported key exchange groups.
207    MissingKeyExchange,
208    /// A peer sent an empty list of signature schemes
209    NoSignatureSchemes,
210    /// Trailing data found for the named handshake payload value
211    TrailingData(&'static str),
212    /// A peer sent an unexpected message type.
213    UnexpectedMessage(&'static str),
214    /// An unknown TLS protocol was encountered during message decoding.
215    UnknownProtocolVersion,
216    /// A peer sent a non-null compression method.
217    UnsupportedCompression,
218    /// A peer sent an unknown elliptic curve type.
219    UnsupportedCurveType,
220    /// A peer sent an unsupported key exchange algorithm.
221    UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
222    /// A server sent an empty ticket
223    EmptyTicketValue,
224    /// A peer sent an empty list of items, but a non-empty list is required.
225    ///
226    /// The argument names the context.
227    IllegalEmptyList(&'static str),
228    /// A peer sent an empty value, but a non-empty value is required.
229    IllegalEmptyValue,
230    /// A peer sent a message where a given extension type was repeated
231    DuplicateExtension(u16),
232    /// A peer sent a message with a PSK offer extension in wrong position
233    PreSharedKeyIsNotFinalExtension,
234    /// A server sent a HelloRetryRequest with an unknown extension
235    UnknownHelloRetryRequestExtension,
236    /// The peer sent a TLS1.3 Certificate with an unknown extension
237    UnknownCertificateExtension,
238}
239
240impl From<InvalidMessage> for Error {
241    #[inline]
242    fn from(e: InvalidMessage) -> Self {
243        Self::InvalidMessage(e)
244    }
245}
246
247impl From<InvalidMessage> for AlertDescription {
248    fn from(e: InvalidMessage) -> Self {
249        match e {
250            InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
251            InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
252            InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
253            _ => Self::DecodeError,
254        }
255    }
256}
257
258/// The set of cases where we failed to make a connection because we thought
259/// the peer was misbehaving.
260///
261/// This is `non_exhaustive`: we might add or stop using items here in minor
262/// versions.  We also don't document what they mean.  Generally a user of
263/// rustls shouldn't vary its behaviour on these error codes, and there is
264/// nothing it can do to improve matters.
265///
266/// Please file a bug against rustls if you see `Error::PeerMisbehaved` in
267/// the wild.
268#[allow(missing_docs)]
269#[non_exhaustive]
270#[derive(Debug, PartialEq, Clone)]
271pub enum PeerMisbehaved {
272    AttemptedDowngradeToTls12WhenTls13IsSupported,
273    BadCertChainExtensions,
274    DisallowedEncryptedExtension,
275    DuplicateClientHelloExtensions,
276    DuplicateEncryptedExtensions,
277    DuplicateHelloRetryRequestExtensions,
278    DuplicateNewSessionTicketExtensions,
279    DuplicateServerHelloExtensions,
280    DuplicateServerNameTypes,
281    EarlyDataAttemptedInSecondClientHello,
282    EarlyDataExtensionWithoutResumption,
283    EarlyDataOfferedWithVariedCipherSuite,
284    HandshakeHashVariedAfterRetry,
285    IllegalHelloRetryRequestWithEmptyCookie,
286    IllegalHelloRetryRequestWithNoChanges,
287    IllegalHelloRetryRequestWithOfferedGroup,
288    IllegalHelloRetryRequestWithUnofferedCipherSuite,
289    IllegalHelloRetryRequestWithUnofferedNamedGroup,
290    IllegalHelloRetryRequestWithUnsupportedVersion,
291    IllegalHelloRetryRequestWithWrongSessionId,
292    IllegalHelloRetryRequestWithInvalidEch,
293    IllegalMiddleboxChangeCipherSpec,
294    IllegalTlsInnerPlaintext,
295    IncorrectBinder,
296    InvalidCertCompression,
297    InvalidMaxEarlyDataSize,
298    InvalidKeyShare,
299    KeyEpochWithPendingFragment,
300    KeyUpdateReceivedInQuicConnection,
301    MessageInterleavedWithHandshakeMessage,
302    MissingBinderInPskExtension,
303    MissingKeyShare,
304    MissingPskModesExtension,
305    MissingQuicTransportParameters,
306    NoCertificatesPresented,
307    OfferedDuplicateCertificateCompressions,
308    OfferedDuplicateKeyShares,
309    OfferedEarlyDataWithOldProtocolVersion,
310    OfferedEmptyApplicationProtocol,
311    OfferedIncorrectCompressions,
312    PskExtensionMustBeLast,
313    PskExtensionWithMismatchedIdsAndBinders,
314    RefusedToFollowHelloRetryRequest,
315    RejectedEarlyDataInterleavedWithHandshakeMessage,
316    ResumptionAttemptedWithVariedEms,
317    ResumptionOfferedWithVariedCipherSuite,
318    ResumptionOfferedWithVariedEms,
319    ResumptionOfferedWithIncompatibleCipherSuite,
320    SelectedDifferentCipherSuiteAfterRetry,
321    SelectedInvalidPsk,
322    SelectedTls12UsingTls13VersionExtension,
323    SelectedUnofferedApplicationProtocol,
324    SelectedUnofferedCertCompression,
325    SelectedUnofferedCipherSuite,
326    SelectedUnofferedCompression,
327    SelectedUnofferedKxGroup,
328    SelectedUnofferedPsk,
329    ServerEchoedCompatibilitySessionId,
330    ServerHelloMustOfferUncompressedEcPoints,
331    ServerNameDifferedOnRetry,
332    ServerNameMustContainOneHostName,
333    SignedKxWithWrongAlgorithm,
334    SignedHandshakeWithUnadvertisedSigScheme,
335    TooManyEmptyFragments,
336    TooManyKeyUpdateRequests,
337    TooManyRenegotiationRequests,
338    TooManyWarningAlertsReceived,
339    TooMuchEarlyDataReceived,
340    UnexpectedCleartextExtension,
341    UnsolicitedCertExtension,
342    UnsolicitedEncryptedExtension,
343    UnsolicitedSctList,
344    UnsolicitedServerHelloExtension,
345    WrongGroupForKeyShare,
346    UnsolicitedEchExtension,
347}
348
349impl From<PeerMisbehaved> for Error {
350    #[inline]
351    fn from(e: PeerMisbehaved) -> Self {
352        Self::PeerMisbehaved(e)
353    }
354}
355
356/// The set of cases where we failed to make a connection because a peer
357/// doesn't support a TLS version/feature we require.
358///
359/// This is `non_exhaustive`: we might add or stop using items here in minor
360/// versions.
361#[allow(missing_docs)]
362#[non_exhaustive]
363#[derive(Debug, PartialEq, Clone)]
364pub enum PeerIncompatible {
365    EcPointsExtensionRequired,
366    ExtendedMasterSecretExtensionRequired,
367    IncorrectCertificateTypeExtension,
368    KeyShareExtensionRequired,
369    MultipleRawKeys,
370    NamedGroupsExtensionRequired,
371    NoCertificateRequestSignatureSchemesInCommon,
372    NoCipherSuitesInCommon,
373    NoEcPointFormatsInCommon,
374    NoKxGroupsInCommon,
375    NoSignatureSchemesInCommon,
376    NoServerNameProvided,
377    NullCompressionRequired,
378    ServerDoesNotSupportTls12Or13,
379    ServerSentHelloRetryRequestWithUnknownExtension,
380    ServerTlsVersionIsDisabledByOurConfig,
381    SignatureAlgorithmsExtensionRequired,
382    SupportedVersionsExtensionRequired,
383    Tls12NotOffered,
384    Tls12NotOfferedOrEnabled,
385    Tls13RequiredForQuic,
386    UncompressedEcPointsRequired,
387    UnknownCertificateType(u8),
388    UnsolicitedCertificateTypeExtension,
389}
390
391impl From<PeerIncompatible> for Error {
392    #[inline]
393    fn from(e: PeerIncompatible) -> Self {
394        Self::PeerIncompatible(e)
395    }
396}
397
398/// The ways in which certificate validators can express errors.
399///
400/// Note that the rustls TLS protocol code interprets specifically these
401/// error codes to send specific TLS alerts.  Therefore, if a
402/// custom certificate validator uses incorrect errors the library as
403/// a whole will send alerts that do not match the standard (this is usually
404/// a minor issue, but could be misleading).
405#[non_exhaustive]
406#[derive(Debug, Clone)]
407pub enum CertificateError {
408    /// The certificate is not correctly encoded.
409    BadEncoding,
410
411    /// The current time is after the `notAfter` time in the certificate.
412    Expired,
413
414    /// The current time is after the `notAfter` time in the certificate.
415    ///
416    /// This variant is semantically the same as `Expired`, but includes
417    /// extra data to improve error reports.
418    ExpiredContext {
419        /// The validation time.
420        time: UnixTime,
421        /// The `notAfter` time of the certificate.
422        not_after: UnixTime,
423    },
424
425    /// The current time is before the `notBefore` time in the certificate.
426    NotValidYet,
427
428    /// The current time is before the `notBefore` time in the certificate.
429    ///
430    /// This variant is semantically the same as `NotValidYet`, but includes
431    /// extra data to improve error reports.
432    NotValidYetContext {
433        /// The validation time.
434        time: UnixTime,
435        /// The `notBefore` time of the certificate.
436        not_before: UnixTime,
437    },
438
439    /// The certificate has been revoked.
440    Revoked,
441
442    /// The certificate contains an extension marked critical, but it was
443    /// not processed by the certificate validator.
444    UnhandledCriticalExtension,
445
446    /// The certificate chain is not issued by a known root certificate.
447    UnknownIssuer,
448
449    /// The certificate's revocation status could not be determined.
450    UnknownRevocationStatus,
451
452    /// The certificate's revocation status could not be determined, because the CRL is expired.
453    ExpiredRevocationList,
454
455    /// The certificate's revocation status could not be determined, because the CRL is expired.
456    ///
457    /// This variant is semantically the same as `ExpiredRevocationList`, but includes
458    /// extra data to improve error reports.
459    ExpiredRevocationListContext {
460        /// The validation time.
461        time: UnixTime,
462        /// The nextUpdate time of the CRL.
463        next_update: UnixTime,
464    },
465
466    /// A certificate is not correctly signed by the key of its alleged
467    /// issuer.
468    BadSignature,
469
470    /// A signature inside a certificate or on a handshake was made with an unsupported algorithm.
471    UnsupportedSignatureAlgorithm {
472        /// The signature algorithm OID that was unsupported.
473        signature_algorithm_id: Vec<u8>,
474        /// Supported algorithms that were available for signature verification.
475        supported_algorithms: Vec<AlgorithmIdentifier>,
476    },
477
478    /// A signature was made with an algorithm that doesn't match the relevant public key.
479    UnsupportedSignatureAlgorithmForPublicKey {
480        /// The signature algorithm OID.
481        signature_algorithm_id: Vec<u8>,
482        /// The public key algorithm OID.
483        public_key_algorithm_id: Vec<u8>,
484    },
485
486    /// The subject names in an end-entity certificate do not include
487    /// the expected name.
488    NotValidForName,
489
490    /// The subject names in an end-entity certificate do not include
491    /// the expected name.
492    ///
493    /// This variant is semantically the same as `NotValidForName`, but includes
494    /// extra data to improve error reports.
495    NotValidForNameContext {
496        /// Expected server name.
497        expected: ServerName<'static>,
498
499        /// The names presented in the end entity certificate.
500        ///
501        /// These are the subject names as present in the leaf certificate and may contain DNS names
502        /// with or without a wildcard label as well as IP address names.
503        presented: Vec<String>,
504    },
505
506    /// The certificate is being used for a different purpose than allowed.
507    InvalidPurpose,
508
509    /// The certificate is being used for a different purpose than allowed.
510    ///
511    /// This variant is semantically the same as `InvalidPurpose`, but includes
512    /// extra data to improve error reports.
513    InvalidPurposeContext {
514        /// Extended key purpose that was required by the application.
515        required: ExtendedKeyPurpose,
516        /// Extended key purposes that were presented in the peer's certificate.
517        presented: Vec<ExtendedKeyPurpose>,
518    },
519
520    /// The OCSP response provided to the verifier was invalid.
521    ///
522    /// This should be returned from [`ServerVerifier::verify_identity()`]
523    /// when a verifier checks its `ocsp_response` parameter and finds it invalid.
524    ///
525    /// This maps to [`AlertDescription::BadCertificateStatusResponse`].
526    ///
527    /// [`ServerVerifier::verify_identity()`]: crate::client::danger::ServerVerifier::verify_identity
528    InvalidOcspResponse,
529
530    /// The certificate is valid, but the handshake is rejected for other
531    /// reasons.
532    ApplicationVerificationFailure,
533
534    /// Any other error.
535    ///
536    /// This can be used by custom verifiers to expose the underlying error
537    /// (where they are not better described by the more specific errors
538    /// above).
539    ///
540    /// It is also used by the default verifier in case its error is
541    /// not covered by the above common cases.
542    ///
543    /// Enums holding this variant will never compare equal to each other.
544    Other(OtherError),
545}
546
547impl PartialEq<Self> for CertificateError {
548    fn eq(&self, other: &Self) -> bool {
549        use CertificateError::*;
550        #[allow(clippy::match_like_matches_macro)]
551        match (self, other) {
552            (BadEncoding, BadEncoding) => true,
553            (Expired, Expired) => true,
554            (
555                ExpiredContext {
556                    time: left_time,
557                    not_after: left_not_after,
558                },
559                ExpiredContext {
560                    time: right_time,
561                    not_after: right_not_after,
562                },
563            ) => (left_time, left_not_after) == (right_time, right_not_after),
564            (NotValidYet, NotValidYet) => true,
565            (
566                NotValidYetContext {
567                    time: left_time,
568                    not_before: left_not_before,
569                },
570                NotValidYetContext {
571                    time: right_time,
572                    not_before: right_not_before,
573                },
574            ) => (left_time, left_not_before) == (right_time, right_not_before),
575            (Revoked, Revoked) => true,
576            (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
577            (UnknownIssuer, UnknownIssuer) => true,
578            (BadSignature, BadSignature) => true,
579            (
580                UnsupportedSignatureAlgorithm {
581                    signature_algorithm_id: left_signature_algorithm_id,
582                    supported_algorithms: left_supported_algorithms,
583                },
584                UnsupportedSignatureAlgorithm {
585                    signature_algorithm_id: right_signature_algorithm_id,
586                    supported_algorithms: right_supported_algorithms,
587                },
588            ) => {
589                (left_signature_algorithm_id, left_supported_algorithms)
590                    == (right_signature_algorithm_id, right_supported_algorithms)
591            }
592            (
593                UnsupportedSignatureAlgorithmForPublicKey {
594                    signature_algorithm_id: left_signature_algorithm_id,
595                    public_key_algorithm_id: left_public_key_algorithm_id,
596                },
597                UnsupportedSignatureAlgorithmForPublicKey {
598                    signature_algorithm_id: right_signature_algorithm_id,
599                    public_key_algorithm_id: right_public_key_algorithm_id,
600                },
601            ) => {
602                (left_signature_algorithm_id, left_public_key_algorithm_id)
603                    == (right_signature_algorithm_id, right_public_key_algorithm_id)
604            }
605            (NotValidForName, NotValidForName) => true,
606            (
607                NotValidForNameContext {
608                    expected: left_expected,
609                    presented: left_presented,
610                },
611                NotValidForNameContext {
612                    expected: right_expected,
613                    presented: right_presented,
614                },
615            ) => (left_expected, left_presented) == (right_expected, right_presented),
616            (InvalidPurpose, InvalidPurpose) => true,
617            (
618                InvalidPurposeContext {
619                    required: left_required,
620                    presented: left_presented,
621                },
622                InvalidPurposeContext {
623                    required: right_required,
624                    presented: right_presented,
625                },
626            ) => (left_required, left_presented) == (right_required, right_presented),
627            (InvalidOcspResponse, InvalidOcspResponse) => true,
628            (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
629            (UnknownRevocationStatus, UnknownRevocationStatus) => true,
630            (ExpiredRevocationList, ExpiredRevocationList) => true,
631            (
632                ExpiredRevocationListContext {
633                    time: left_time,
634                    next_update: left_next_update,
635                },
636                ExpiredRevocationListContext {
637                    time: right_time,
638                    next_update: right_next_update,
639                },
640            ) => (left_time, left_next_update) == (right_time, right_next_update),
641            _ => false,
642        }
643    }
644}
645
646// The following mapping are heavily referenced in:
647// * [OpenSSL Implementation](https://github.com/openssl/openssl/blob/45bb98bfa223efd3258f445ad443f878011450f0/ssl/statem/statem_lib.c#L1434)
648// * [BoringSSL Implementation](https://github.com/google/boringssl/blob/583c60bd4bf76d61b2634a58bcda99a92de106cb/ssl/ssl_x509.cc#L1323)
649impl From<CertificateError> for AlertDescription {
650    fn from(e: CertificateError) -> Self {
651        use CertificateError::*;
652        match e {
653            BadEncoding
654            | UnhandledCriticalExtension
655            | NotValidForName
656            | NotValidForNameContext { .. } => Self::BadCertificate,
657            // RFC 5246/RFC 8446
658            // certificate_expired
659            //  A certificate has expired or **is not currently valid**.
660            Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
661                Self::CertificateExpired
662            }
663            Revoked => Self::CertificateRevoked,
664            // OpenSSL, BoringSSL and AWS-LC all generate an Unknown CA alert for
665            // the case where revocation status can not be determined, so we do the same here.
666            UnknownIssuer
667            | UnknownRevocationStatus
668            | ExpiredRevocationList
669            | ExpiredRevocationListContext { .. } => Self::UnknownCa,
670            InvalidOcspResponse => Self::BadCertificateStatusResponse,
671            BadSignature
672            | UnsupportedSignatureAlgorithm { .. }
673            | UnsupportedSignatureAlgorithmForPublicKey { .. } => Self::DecryptError,
674            InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate,
675            ApplicationVerificationFailure => Self::AccessDenied,
676            // RFC 5246/RFC 8446
677            // certificate_unknown
678            //  Some other (unspecified) issue arose in processing the
679            //  certificate, rendering it unacceptable.
680            Other(..) => Self::CertificateUnknown,
681        }
682    }
683}
684
685impl fmt::Display for CertificateError {
686    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
687        match self {
688            #[cfg(feature = "std")]
689            Self::NotValidForNameContext {
690                expected,
691                presented,
692            } => {
693                write!(
694                    f,
695                    "certificate not valid for name {:?}; certificate ",
696                    expected.to_str()
697                )?;
698
699                match presented.as_slice() {
700                    &[] => write!(
701                        f,
702                        "is not valid for any names (according to its subjectAltName extension)"
703                    ),
704                    [one] => write!(f, "is only valid for {one}"),
705                    many => {
706                        write!(f, "is only valid for ")?;
707
708                        let n = many.len();
709                        let all_but_last = &many[..n - 1];
710                        let last = &many[n - 1];
711
712                        for (i, name) in all_but_last.iter().enumerate() {
713                            write!(f, "{name}")?;
714                            if i < n - 2 {
715                                write!(f, ", ")?;
716                            }
717                        }
718                        write!(f, " or {last}")
719                    }
720                }
721            }
722
723            Self::ExpiredContext { time, not_after } => write!(
724                f,
725                "certificate expired: verification time {} (UNIX), \
726                 but certificate is not valid after {} \
727                 ({} seconds ago)",
728                time.as_secs(),
729                not_after.as_secs(),
730                time.as_secs()
731                    .saturating_sub(not_after.as_secs())
732            ),
733
734            Self::NotValidYetContext { time, not_before } => write!(
735                f,
736                "certificate not valid yet: verification time {} (UNIX), \
737                 but certificate is not valid before {} \
738                 ({} seconds in future)",
739                time.as_secs(),
740                not_before.as_secs(),
741                not_before
742                    .as_secs()
743                    .saturating_sub(time.as_secs())
744            ),
745
746            Self::ExpiredRevocationListContext { time, next_update } => write!(
747                f,
748                "certificate revocation list expired: \
749                 verification time {} (UNIX), \
750                 but CRL is not valid after {} \
751                 ({} seconds ago)",
752                time.as_secs(),
753                next_update.as_secs(),
754                time.as_secs()
755                    .saturating_sub(next_update.as_secs())
756            ),
757
758            Self::InvalidPurposeContext {
759                required,
760                presented,
761            } => {
762                write!(
763                    f,
764                    "certificate does not allow extended key usage for {required}, allows "
765                )?;
766                for (i, eku) in presented.iter().enumerate() {
767                    if i > 0 {
768                        write!(f, ", ")?;
769                    }
770                    write!(f, "{eku}")?;
771                }
772                Ok(())
773            }
774
775            Self::Other(other) => write!(f, "{other}"),
776
777            other => write!(f, "{other:?}"),
778        }
779    }
780}
781
782impl From<CertificateError> for Error {
783    #[inline]
784    fn from(e: CertificateError) -> Self {
785        Self::InvalidCertificate(e)
786    }
787}
788
789/// Extended Key Usage (EKU) purpose values.
790///
791/// These are usually represented as OID values in the certificate's extension (if present), but
792/// we represent the values that are most relevant to rustls as named enum variants.
793#[non_exhaustive]
794#[derive(Clone, Debug, Eq, PartialEq)]
795pub enum ExtendedKeyPurpose {
796    /// Client authentication
797    ClientAuth,
798    /// Server authentication
799    ServerAuth,
800    /// Other EKU values
801    ///
802    /// Represented here as a `Vec<usize>` for human readability.
803    Other(Vec<usize>),
804}
805
806impl ExtendedKeyPurpose {
807    pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
808        let values = values.collect::<Vec<_>>();
809        match &*values {
810            ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
811            ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
812            _ => Self::Other(values),
813        }
814    }
815}
816
817impl fmt::Display for ExtendedKeyPurpose {
818    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
819        match self {
820            Self::ClientAuth => write!(f, "client authentication"),
821            Self::ServerAuth => write!(f, "server authentication"),
822            Self::Other(values) => {
823                for (i, value) in values.iter().enumerate() {
824                    if i > 0 {
825                        write!(f, ", ")?;
826                    }
827                    write!(f, "{value}")?;
828                }
829                Ok(())
830            }
831        }
832    }
833}
834
835/// The ways in which a certificate revocation list (CRL) can be invalid.
836#[non_exhaustive]
837#[derive(Debug, Clone)]
838pub enum CertRevocationListError {
839    /// The CRL had a bad signature from its issuer.
840    BadSignature,
841
842    /// A signature inside a certificate or on a handshake was made with an unsupported algorithm.
843    UnsupportedSignatureAlgorithm {
844        /// The signature algorithm OID that was unsupported.
845        signature_algorithm_id: Vec<u8>,
846        /// Supported algorithms that were available for signature verification.
847        supported_algorithms: Vec<AlgorithmIdentifier>,
848    },
849
850    /// A signature was made with an algorithm that doesn't match the relevant public key.
851    UnsupportedSignatureAlgorithmForPublicKey {
852        /// The signature algorithm OID.
853        signature_algorithm_id: Vec<u8>,
854        /// The public key algorithm OID.
855        public_key_algorithm_id: Vec<u8>,
856    },
857
858    /// The CRL contained an invalid CRL number.
859    InvalidCrlNumber,
860
861    /// The CRL contained a revoked certificate with an invalid serial number.
862    InvalidRevokedCertSerialNumber,
863
864    /// The CRL issuer does not specify the cRLSign key usage.
865    IssuerInvalidForCrl,
866
867    /// The CRL is invalid for some other reason.
868    ///
869    /// Enums holding this variant will never compare equal to each other.
870    Other(OtherError),
871
872    /// The CRL is not correctly encoded.
873    ParseError,
874
875    /// The CRL is not a v2 X.509 CRL.
876    UnsupportedCrlVersion,
877
878    /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
879    UnsupportedCriticalExtension,
880
881    /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
882    UnsupportedDeltaCrl,
883
884    /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
885    /// other than the issuer of the CRL.
886    UnsupportedIndirectCrl,
887
888    /// The CRL contained a revoked certificate with an unsupported revocation reason.
889    /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
890    ///
891    /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
892    UnsupportedRevocationReason,
893}
894
895impl PartialEq<Self> for CertRevocationListError {
896    fn eq(&self, other: &Self) -> bool {
897        use CertRevocationListError::*;
898        #[allow(clippy::match_like_matches_macro)]
899        match (self, other) {
900            (BadSignature, BadSignature) => true,
901            (
902                UnsupportedSignatureAlgorithm {
903                    signature_algorithm_id: left_signature_algorithm_id,
904                    supported_algorithms: left_supported_algorithms,
905                },
906                UnsupportedSignatureAlgorithm {
907                    signature_algorithm_id: right_signature_algorithm_id,
908                    supported_algorithms: right_supported_algorithms,
909                },
910            ) => {
911                (left_signature_algorithm_id, left_supported_algorithms)
912                    == (right_signature_algorithm_id, right_supported_algorithms)
913            }
914            (
915                UnsupportedSignatureAlgorithmForPublicKey {
916                    signature_algorithm_id: left_signature_algorithm_id,
917                    public_key_algorithm_id: left_public_key_algorithm_id,
918                },
919                UnsupportedSignatureAlgorithmForPublicKey {
920                    signature_algorithm_id: right_signature_algorithm_id,
921                    public_key_algorithm_id: right_public_key_algorithm_id,
922                },
923            ) => {
924                (left_signature_algorithm_id, left_public_key_algorithm_id)
925                    == (right_signature_algorithm_id, right_public_key_algorithm_id)
926            }
927            (InvalidCrlNumber, InvalidCrlNumber) => true,
928            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
929            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
930            (ParseError, ParseError) => true,
931            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
932            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
933            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
934            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
935            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
936            _ => false,
937        }
938    }
939}
940
941impl From<CertRevocationListError> for Error {
942    #[inline]
943    fn from(e: CertRevocationListError) -> Self {
944        Self::InvalidCertRevocationList(e)
945    }
946}
947
948/// An error that occurred while handling Encrypted Client Hello (ECH).
949#[non_exhaustive]
950#[derive(Debug, Clone, Eq, PartialEq)]
951pub enum EncryptedClientHelloError {
952    /// The provided ECH configuration list was invalid.
953    InvalidConfigList,
954    /// No compatible ECH configuration.
955    NoCompatibleConfig,
956    /// The client configuration has server name indication (SNI) disabled.
957    SniRequired,
958}
959
960impl From<EncryptedClientHelloError> for Error {
961    #[inline]
962    fn from(e: EncryptedClientHelloError) -> Self {
963        Self::InvalidEncryptedClientHello(e)
964    }
965}
966
967/// The server rejected the request to enable Encrypted Client Hello (ECH)
968///
969/// If [`RejectedEch::can_retry()`] is true, then you may use this with
970/// [`crate::client::EchConfig::for_retry()`] to build a new `EchConfig` for a fresh client
971/// connection that will use a compatible ECH configuration provided by the server for a retry.
972#[non_exhaustive]
973#[derive(Debug, Clone, PartialEq)]
974pub struct RejectedEch {
975    pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
976}
977
978impl RejectedEch {
979    /// Returns true if the server provided new ECH configurations to use for a fresh retry connection
980    ///
981    /// The `RejectedEch` error can be provided to [`crate::client::EchConfig::for_retry()`]
982    /// to build a new `EchConfig` for a fresh client connection that will use a compatible ECH
983    /// configuration provided by the server for a retry.
984    pub fn can_retry(&self) -> bool {
985        self.retry_configs.is_some()
986    }
987
988    /// Returns an `EchConfigListBytes` with the server's provided retry configurations (if any)
989    pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
990        let Some(retry_configs) = &self.retry_configs else {
991            return None;
992        };
993
994        let mut tls_encoded_list = Vec::new();
995        retry_configs.encode(&mut tls_encoded_list);
996
997        Some(EchConfigListBytes::from(tls_encoded_list))
998    }
999}
1000
1001impl From<RejectedEch> for Error {
1002    fn from(rejected_error: RejectedEch) -> Self {
1003        Self::RejectedEch(rejected_error)
1004    }
1005}
1006
1007fn join<T: fmt::Debug>(items: &[T]) -> String {
1008    items
1009        .iter()
1010        .map(|x| format!("{x:?}"))
1011        .collect::<Vec<String>>()
1012        .join(" or ")
1013}
1014
1015impl fmt::Display for Error {
1016    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1017        match self {
1018            Self::InappropriateMessage {
1019                expect_types,
1020                got_type,
1021            } => write!(
1022                f,
1023                "received unexpected message: got {:?} when expecting {}",
1024                got_type,
1025                join::<ContentType>(expect_types)
1026            ),
1027            Self::InappropriateHandshakeMessage {
1028                expect_types,
1029                got_type,
1030            } => write!(
1031                f,
1032                "received unexpected handshake message: got {:?} when expecting {}",
1033                got_type,
1034                join::<HandshakeType>(expect_types)
1035            ),
1036            Self::InvalidMessage(typ) => {
1037                write!(f, "received corrupt message of type {typ:?}")
1038            }
1039            Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
1040            Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
1041            Self::AlertReceived(alert) => write!(f, "received fatal alert: the peer {alert}"),
1042            Self::InvalidCertificate(err) => {
1043                write!(f, "invalid peer certificate: {err}")
1044            }
1045            Self::InvalidCertRevocationList(err) => {
1046                write!(f, "invalid certificate revocation list: {err:?}")
1047            }
1048            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
1049            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
1050            Self::InvalidEncryptedClientHello(err) => {
1051                write!(f, "encrypted client hello failure: {err:?}")
1052            }
1053            Self::EncryptError => write!(f, "cannot encrypt message"),
1054            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
1055            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
1056            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
1057            Self::NoSuitableCertificate => write!(f, "no suitable certificate found"),
1058            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
1059            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
1060            Self::BadMaxFragmentSize => {
1061                write!(f, "the supplied max_fragment_size was too small or large")
1062            }
1063            Self::InconsistentKeys(why) => {
1064                write!(f, "keys may not be consistent: {why:?}")
1065            }
1066            Self::RejectedEch(why) => {
1067                write!(
1068                    f,
1069                    "server rejected encrypted client hello (ECH) {} retry configs",
1070                    if why.can_retry() { "with" } else { "without" }
1071                )
1072            }
1073            Self::General(err) => write!(f, "unexpected error: {err}"),
1074            Self::Unreachable(err) => write!(
1075                f,
1076                "unreachable condition: {err} (please file a bug in rustls)"
1077            ),
1078            Self::ApiMisuse(why) => write!(f, "API misuse: {why:?}"),
1079            Self::Other(err) => write!(f, "other error: {err}"),
1080        }
1081    }
1082}
1083
1084#[cfg(feature = "std")]
1085impl From<SystemTimeError> for Error {
1086    #[inline]
1087    fn from(_: SystemTimeError) -> Self {
1088        Self::FailedToGetCurrentTime
1089    }
1090}
1091
1092impl core::error::Error for Error {}
1093
1094impl From<rand::GetRandomFailed> for Error {
1095    fn from(_: rand::GetRandomFailed) -> Self {
1096        Self::FailedToGetRandomBytes
1097    }
1098}
1099
1100/// Describes cases of API misuse
1101///
1102/// Variants here should be sufficiently detailed that the action needed is clear.
1103#[non_exhaustive]
1104#[derive(Debug, Clone, PartialEq)]
1105pub enum ApiMisuse {
1106    /// The [`KeyingMaterialExporter`][] was already consumed.
1107    ///
1108    /// Methods that obtain an exporter (eg, [`ConnectionCommon::exporter()`][]) can only
1109    /// be used once.  This error is returned on subsequent calls.
1110    ///
1111    /// [`KeyingMaterialExporter`]: crate::KeyingMaterialExporter
1112    /// [`ConnectionCommon::exporter()`]: crate::ConnectionCommon::exporter()
1113    ExporterAlreadyUsed,
1114
1115    /// The `context` parameter to [`KeyingMaterialExporter::derive()`][] was too long.
1116    ///
1117    /// For TLS1.2 connections (only) this parameter is limited to 64KB.
1118    ///
1119    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1120    ExporterContextTooLong,
1121
1122    /// The `output` object for [`KeyingMaterialExporter::derive()`][] was too long.
1123    ///
1124    /// For TLS1.3 connections this is limited to 255 times the hash output length.
1125    ///
1126    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1127    ExporterOutputTooLong,
1128
1129    /// The `output` object to [`KeyingMaterialExporter::derive()`][] was zero length.
1130    ///
1131    /// This doesn't make sense, so we explicitly return an error (rather than simply
1132    /// producing no output as requested.)
1133    ///
1134    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1135    ExporterOutputZeroLength,
1136
1137    /// [`Acceptor::accept()`][] called after it yielded a connection.
1138    ///
1139    /// [`Acceptor::accept()`]: crate::server::Acceptor::accept()
1140    AcceptorPolledAfterCompletion,
1141
1142    /// Incorrect sample length provided to [`quic::HeaderProtectionKey::encrypt_in_place()`][]
1143    ///
1144    /// [`quic::HeaderProtectionKey::encrypt_in_place()`]: crate::quic::HeaderProtectionKey::encrypt_in_place()
1145    InvalidQuicHeaderProtectionSampleLength,
1146
1147    /// Incorrect relation between sample length and header number length provided to
1148    /// [`quic::HeaderProtectionKey::encrypt_in_place()`][]
1149    ///
1150    /// [`quic::HeaderProtectionKey::encrypt_in_place()`]: crate::quic::HeaderProtectionKey::encrypt_in_place()
1151    InvalidQuicHeaderProtectionPacketNumberLength,
1152
1153    /// Raw keys cannot be used with TLS 1.2.
1154    InvalidSignerForProtocolVersion,
1155
1156    /// QUIC attempted with a configuration that does not support TLS1.3.
1157    QuicRequiresTls13Support,
1158
1159    /// QUIC attempted with a configuration that does not support a ciphersuite that supports QUIC.
1160    NoQuicCompatibleCipherSuites,
1161
1162    /// An empty certificate chain was provided.
1163    EmptyCertificateChain,
1164
1165    /// QUIC attempted with unsupported [`ServerConfig::max_early_data_size`][]
1166    ///
1167    /// This field must be either zero or [`u32::MAX`] for QUIC.
1168    ///
1169    /// [`ServerConfig::max_early_data_size`]: crate::server::ServerConfig::max_early_data_size
1170    QuicRestrictsMaxEarlyDataSize,
1171
1172    /// A `CryptoProvider` must have at least one cipher suite.
1173    NoCipherSuitesConfigured,
1174
1175    /// A `CryptoProvider` must have at least one key exchange group.
1176    NoKeyExchangeGroupsConfigured,
1177
1178    /// An empty list of signature verification algorithms was provided.
1179    NoSignatureVerificationAlgorithms,
1180
1181    /// ECH attempted with a configuration that does not support TLS1.3.
1182    EchRequiresTls13Support,
1183
1184    /// ECH attempted with a configuration that also supports TLS1.2.
1185    EchForbidsTls12Support,
1186
1187    /// Secret extraction operation attempted without opting-in to secret extraction.
1188    ///
1189    /// This is possible from:
1190    ///
1191    /// - [`ClientConnection::dangerous_extract_secrets()`][crate::client::ClientConnection::dangerous_extract_secrets]
1192    /// - [`ServerConnection::dangerous_extract_secrets()`][crate::server::ServerConnection::dangerous_extract_secrets]
1193    /// - [`ClientConnection::dangerous_into_kernel_connection()`][crate::client::UnbufferedClientConnection::dangerous_into_kernel_connection]
1194    /// - [`ServerConnection::dangerous_into_kernel_connection()`][crate::server::UnbufferedServerConnection::dangerous_into_kernel_connection]
1195    ///
1196    /// You must set [`ServerConfig::enable_secret_extraction`][crate::server::ServerConfig::enable_secret_extraction] or
1197    /// [`ClientConfig::enable_secret_extraction`][crate::client::ClientConfig::enable_secret_extraction] to true before calling
1198    /// these functions.
1199    SecretExtractionRequiresPriorOptIn,
1200
1201    /// Secret extraction operation attempted without first extracting all pending
1202    /// TLS data.
1203    ///
1204    /// See [`Self::SecretExtractionRequiresPriorOptIn`] for a list of the affected
1205    /// functions.  You must ensure any prior generated TLS records are extracted
1206    /// from the library before using one of these functions.
1207    SecretExtractionWithPendingSendableData,
1208
1209    /// Attempt to verify a certificate with an unsupported type.
1210    ///
1211    /// A verifier indicated support for a certificate type but then failed to verify the peer's
1212    /// identity of that type.
1213    UnverifiableCertificateType,
1214
1215    /// A verifier or resolver implementation signalled that it does not support any certificate types.
1216    NoSupportedCertificateTypes,
1217}
1218
1219impl fmt::Display for ApiMisuse {
1220    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1221        write!(f, "{self:?}")
1222    }
1223}
1224
1225impl core::error::Error for ApiMisuse {}
1226
1227impl From<ApiMisuse> for Error {
1228    fn from(e: ApiMisuse) -> Self {
1229        Self::ApiMisuse(e)
1230    }
1231}
1232
1233mod other_error {
1234    use core::error::Error as StdError;
1235    use core::fmt;
1236
1237    use super::Error;
1238    use crate::sync::Arc;
1239
1240    /// Any other error that cannot be expressed by a more specific [`Error`] variant.
1241    ///
1242    /// For example, an `OtherError` could be produced by a custom crypto provider
1243    /// exposing a provider specific error.
1244    ///
1245    /// Enums holding this type will never compare equal to each other.
1246    #[allow(clippy::exhaustive_structs)]
1247    #[derive(Debug, Clone)]
1248    pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1249
1250    impl OtherError {
1251        /// Create a new `OtherError` from any error type.
1252        pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1253            Self(Arc::new(err))
1254        }
1255    }
1256
1257    impl PartialEq<Self> for OtherError {
1258        fn eq(&self, _other: &Self) -> bool {
1259            false
1260        }
1261    }
1262
1263    impl From<OtherError> for Error {
1264        fn from(value: OtherError) -> Self {
1265            Self::Other(value)
1266        }
1267    }
1268
1269    impl fmt::Display for OtherError {
1270        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1271            #[cfg(feature = "std")]
1272            {
1273                write!(f, "{}", self.0)
1274            }
1275            #[cfg(not(feature = "std"))]
1276            {
1277                f.write_str("no further information available")
1278            }
1279        }
1280    }
1281
1282    impl StdError for OtherError {
1283        fn source(&self) -> Option<&(dyn StdError + 'static)> {
1284            Some(self.0.as_ref())
1285        }
1286    }
1287}
1288
1289pub use other_error::OtherError;
1290
1291use crate::msgs::codec::Codec;
1292
1293#[cfg(test)]
1294mod tests {
1295    use core::time::Duration;
1296    use std::prelude::v1::*;
1297    use std::{println, vec};
1298
1299    use pki_types::ServerName;
1300
1301    use super::{
1302        AlertDescription, CertRevocationListError, Error, InconsistentKeys, InvalidMessage,
1303        OtherError, UnixTime,
1304    };
1305
1306    #[test]
1307    fn certificate_error_equality() {
1308        use super::CertificateError::*;
1309        assert_eq!(BadEncoding, BadEncoding);
1310        assert_eq!(Expired, Expired);
1311        let context = ExpiredContext {
1312            time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1313            not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1314        };
1315        assert_eq!(context, context);
1316        assert_ne!(
1317            context,
1318            ExpiredContext {
1319                time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1320                not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1321            }
1322        );
1323        assert_ne!(
1324            context,
1325            ExpiredContext {
1326                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1327                not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1328            }
1329        );
1330        assert_eq!(NotValidYet, NotValidYet);
1331        let context = NotValidYetContext {
1332            time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1333            not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1334        };
1335        assert_eq!(context, context);
1336        assert_ne!(
1337            context,
1338            NotValidYetContext {
1339                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1340                not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1341            }
1342        );
1343        assert_ne!(
1344            context,
1345            NotValidYetContext {
1346                time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1347                not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1348            }
1349        );
1350        assert_eq!(Revoked, Revoked);
1351        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
1352        assert_eq!(UnknownIssuer, UnknownIssuer);
1353        assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
1354        assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
1355        let context = ExpiredRevocationListContext {
1356            time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1357            next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1358        };
1359        assert_eq!(context, context);
1360        assert_ne!(
1361            context,
1362            ExpiredRevocationListContext {
1363                time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1364                next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1365            }
1366        );
1367        assert_ne!(
1368            context,
1369            ExpiredRevocationListContext {
1370                time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1371                next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1372            }
1373        );
1374        assert_eq!(BadSignature, BadSignature);
1375        assert_eq!(
1376            UnsupportedSignatureAlgorithm {
1377                signature_algorithm_id: vec![1, 2, 3],
1378                supported_algorithms: vec![]
1379            },
1380            UnsupportedSignatureAlgorithm {
1381                signature_algorithm_id: vec![1, 2, 3],
1382                supported_algorithms: vec![]
1383            }
1384        );
1385        assert_eq!(
1386            UnsupportedSignatureAlgorithmForPublicKey {
1387                signature_algorithm_id: vec![1, 2, 3],
1388                public_key_algorithm_id: vec![4, 5, 6]
1389            },
1390            UnsupportedSignatureAlgorithmForPublicKey {
1391                signature_algorithm_id: vec![1, 2, 3],
1392                public_key_algorithm_id: vec![4, 5, 6]
1393            }
1394        );
1395        assert_eq!(NotValidForName, NotValidForName);
1396        let context = NotValidForNameContext {
1397            expected: ServerName::try_from("example.com")
1398                .unwrap()
1399                .to_owned(),
1400            presented: vec!["other.com".into()],
1401        };
1402        assert_eq!(context, context);
1403        assert_ne!(
1404            context,
1405            NotValidForNameContext {
1406                expected: ServerName::try_from("example.com")
1407                    .unwrap()
1408                    .to_owned(),
1409                presented: vec![]
1410            }
1411        );
1412        assert_ne!(
1413            context,
1414            NotValidForNameContext {
1415                expected: ServerName::try_from("huh.com")
1416                    .unwrap()
1417                    .to_owned(),
1418                presented: vec!["other.com".into()],
1419            }
1420        );
1421        assert_eq!(InvalidPurpose, InvalidPurpose);
1422        assert_eq!(
1423            ApplicationVerificationFailure,
1424            ApplicationVerificationFailure
1425        );
1426        assert_eq!(InvalidOcspResponse, InvalidOcspResponse);
1427        let other = Other(OtherError::new(TestError));
1428        assert_ne!(other, other);
1429        assert_ne!(BadEncoding, Expired);
1430    }
1431
1432    #[test]
1433    fn crl_error_equality() {
1434        use super::CertRevocationListError::*;
1435        assert_eq!(BadSignature, BadSignature);
1436        assert_eq!(
1437            UnsupportedSignatureAlgorithm {
1438                signature_algorithm_id: vec![1, 2, 3],
1439                supported_algorithms: vec![]
1440            },
1441            UnsupportedSignatureAlgorithm {
1442                signature_algorithm_id: vec![1, 2, 3],
1443                supported_algorithms: vec![]
1444            }
1445        );
1446        assert_eq!(
1447            UnsupportedSignatureAlgorithmForPublicKey {
1448                signature_algorithm_id: vec![1, 2, 3],
1449                public_key_algorithm_id: vec![4, 5, 6]
1450            },
1451            UnsupportedSignatureAlgorithmForPublicKey {
1452                signature_algorithm_id: vec![1, 2, 3],
1453                public_key_algorithm_id: vec![4, 5, 6]
1454            }
1455        );
1456        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
1457        assert_eq!(
1458            InvalidRevokedCertSerialNumber,
1459            InvalidRevokedCertSerialNumber
1460        );
1461        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
1462        assert_eq!(ParseError, ParseError);
1463        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
1464        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
1465        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
1466        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
1467        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
1468        let other = Other(OtherError::new(TestError));
1469        assert_ne!(other, other);
1470        assert_ne!(BadSignature, InvalidCrlNumber);
1471    }
1472
1473    #[test]
1474    #[cfg(feature = "std")]
1475    fn other_error_equality() {
1476        let other_error = OtherError::new(TestError);
1477        assert_ne!(other_error, other_error);
1478        let other: Error = other_error.into();
1479        assert_ne!(other, other);
1480    }
1481
1482    #[test]
1483    fn smoke() {
1484        use crate::enums::{AlertDescription, ContentType, HandshakeType};
1485
1486        let all = vec![
1487            Error::InappropriateMessage {
1488                expect_types: vec![ContentType::Alert],
1489                got_type: ContentType::Handshake,
1490            },
1491            Error::InappropriateHandshakeMessage {
1492                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
1493                got_type: HandshakeType::ServerHello,
1494            },
1495            Error::InvalidMessage(InvalidMessage::InvalidCcs),
1496            Error::DecryptError,
1497            super::PeerIncompatible::Tls12NotOffered.into(),
1498            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
1499            Error::AlertReceived(AlertDescription::ExportRestriction),
1500            super::CertificateError::Expired.into(),
1501            super::CertificateError::NotValidForNameContext {
1502                expected: ServerName::try_from("example.com")
1503                    .unwrap()
1504                    .to_owned(),
1505                presented: vec![],
1506            }
1507            .into(),
1508            super::CertificateError::NotValidForNameContext {
1509                expected: ServerName::try_from("example.com")
1510                    .unwrap()
1511                    .to_owned(),
1512                presented: vec!["DnsName(\"hello.com\")".into()],
1513            }
1514            .into(),
1515            super::CertificateError::NotValidForNameContext {
1516                expected: ServerName::try_from("example.com")
1517                    .unwrap()
1518                    .to_owned(),
1519                presented: vec![
1520                    "DnsName(\"hello.com\")".into(),
1521                    "DnsName(\"goodbye.com\")".into(),
1522                ],
1523            }
1524            .into(),
1525            super::CertificateError::NotValidYetContext {
1526                time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1527                not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1528            }
1529            .into(),
1530            super::CertificateError::ExpiredContext {
1531                time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1532                not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1533            }
1534            .into(),
1535            super::CertificateError::ExpiredRevocationListContext {
1536                time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1537                next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1538            }
1539            .into(),
1540            super::CertificateError::InvalidOcspResponse.into(),
1541            Error::General("undocumented error".to_string()),
1542            Error::FailedToGetCurrentTime,
1543            Error::FailedToGetRandomBytes,
1544            Error::HandshakeNotComplete,
1545            Error::PeerSentOversizedRecord,
1546            Error::NoApplicationProtocol,
1547            Error::BadMaxFragmentSize,
1548            Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
1549            Error::InconsistentKeys(InconsistentKeys::Unknown),
1550            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
1551            Error::Unreachable("smoke"),
1552            super::ApiMisuse::ExporterAlreadyUsed.into(),
1553            Error::Other(OtherError::new(TestError)),
1554        ];
1555
1556        for err in all {
1557            println!("{err:?}:");
1558            println!("  fmt '{err}'");
1559        }
1560    }
1561
1562    #[derive(Debug)]
1563    struct TestError;
1564
1565    impl core::fmt::Display for TestError {
1566        fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1567            write!(f, "test error")
1568        }
1569    }
1570
1571    impl core::error::Error for TestError {}
1572
1573    #[test]
1574    fn alert_display() {
1575        println!("Review the following error messages for syntax and grammar errors:");
1576        for u in 0..=u8::MAX {
1577            let err = Error::AlertReceived(AlertDescription::from(u));
1578            println!(" - {err}");
1579        }
1580
1581        // pipe the output of this test to `llm` for a quick check of these...
1582    }
1583
1584    #[test]
1585    fn rand_error_mapping() {
1586        use super::rand;
1587        let err: Error = rand::GetRandomFailed.into();
1588        assert_eq!(err, Error::FailedToGetRandomBytes);
1589    }
1590
1591    #[cfg(feature = "std")]
1592    #[test]
1593    fn time_error_mapping() {
1594        use std::time::SystemTime;
1595
1596        let time_error = SystemTime::UNIX_EPOCH
1597            .duration_since(SystemTime::now())
1598            .unwrap_err();
1599        let err: Error = time_error.into();
1600        assert_eq!(err, Error::FailedToGetCurrentTime);
1601    }
1602}