rustls/
error.rs

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