Skip to main content

rustls/error/
mod.rs

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