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    /// A server [`Acceptor::accept()`][] or QUIC [`quic::Acceptor::accept()`][] called after it
1400    /// yielded a connection.
1401    ///
1402    /// [`Acceptor::accept()`]: crate::server::Acceptor::accept()
1403    /// [`quic::Acceptor::accept()`]: crate::quic::Acceptor::accept()
1404    AcceptorPolledAfterCompletion,
1405
1406    /// Incorrect sample length provided to [`quic::HeaderProtectionKey::encrypt_in_place()`][]
1407    ///
1408    /// [`quic::HeaderProtectionKey::encrypt_in_place()`]: crate::quic::HeaderProtectionKey::encrypt_in_place()
1409    InvalidQuicHeaderProtectionSampleLength,
1410
1411    /// Incorrect relation between sample length and header number length provided to
1412    /// [`quic::HeaderProtectionKey::encrypt_in_place()`][]
1413    ///
1414    /// [`quic::HeaderProtectionKey::encrypt_in_place()`]: crate::quic::HeaderProtectionKey::encrypt_in_place()
1415    InvalidQuicHeaderProtectionPacketNumberLength,
1416
1417    /// Raw keys cannot be used with TLS 1.2.
1418    InvalidSignerForProtocolVersion,
1419
1420    /// QUIC attempted with a configuration that does not support TLS1.3.
1421    QuicRequiresTls13Support,
1422
1423    /// QUIC attempted with a configuration that does not support a ciphersuite that supports QUIC.
1424    NoQuicCompatibleCipherSuites,
1425
1426    /// An empty certificate chain was provided.
1427    EmptyCertificateChain,
1428
1429    /// QUIC attempted with unsupported [`ServerConfig::max_early_data_size`][]
1430    ///
1431    /// This field must be either zero or [`u32::MAX`] for QUIC.
1432    ///
1433    /// [`ServerConfig::max_early_data_size`]: crate::server::ServerConfig::max_early_data_size
1434    QuicRestrictsMaxEarlyDataSize,
1435
1436    /// A `CryptoProvider` must have at least one cipher suite.
1437    NoCipherSuitesConfigured,
1438
1439    /// A `CryptoProvider` must have at least one key exchange group.
1440    NoKeyExchangeGroupsConfigured,
1441
1442    /// An empty list of signature verification algorithms was provided.
1443    NoSignatureVerificationAlgorithms,
1444
1445    /// ECH attempted with a configuration that does not support TLS1.3.
1446    EchRequiresTls13Support,
1447
1448    /// ECH attempted with a configuration that also supports TLS1.2.
1449    EchForbidsTls12Support,
1450
1451    /// Secret extraction operation attempted without opting-in to secret extraction.
1452    ///
1453    /// This is possible from [`Connection::dangerous_extract_secrets()`][crate::Connection::dangerous_extract_secrets].
1454    ///
1455    /// You must set [`ServerConfig::enable_secret_extraction`][crate::server::ServerConfig::enable_secret_extraction] or
1456    /// [`ClientConfig::enable_secret_extraction`][crate::client::ClientConfig::enable_secret_extraction] to true before this
1457    /// is available.
1458    SecretExtractionRequiresPriorOptIn,
1459
1460    /// Secret extraction operation attempted without first extracting all pending
1461    /// TLS data.
1462    ///
1463    /// See [`Self::SecretExtractionRequiresPriorOptIn`] for a list of the affected
1464    /// functions.  You must ensure any prior generated TLS records are extracted
1465    /// from the library before using one of these functions.
1466    SecretExtractionWithPendingSendableData,
1467
1468    /// Attempt to verify a certificate with an unsupported type.
1469    ///
1470    /// A verifier indicated support for a certificate type but then failed to verify the peer's
1471    /// identity of that type.
1472    UnverifiableCertificateType,
1473
1474    /// A verifier or resolver implementation signalled that it does not support any certificate types.
1475    NoSupportedCertificateTypes,
1476
1477    /// [`Nonce::to_array()`][] called with incorrect array size.
1478    ///
1479    /// The nonce length does not match the requested array size `N`.
1480    ///
1481    /// [`Nonce::to_array()`]: crate::crypto::cipher::Nonce::to_array()
1482    NonceArraySizeMismatch {
1483        /// The expected array size (type parameter N)
1484        expected: usize,
1485        /// The actual nonce length
1486        actual: usize,
1487    },
1488
1489    /// [`Iv::new()`][] called with a value that exceeds the maximum IV length.
1490    ///
1491    /// The IV length must not exceed [`Iv::MAX_LEN`][].
1492    ///
1493    /// [`Iv::new()`]: crate::crypto::cipher::Iv::new()
1494    /// [`Iv::MAX_LEN`]: crate::crypto::cipher::Iv::MAX_LEN
1495    IvLengthExceedsMaximum {
1496        /// The actual IV length provided
1497        actual: usize,
1498        /// The maximum allowed IV length
1499        maximum: usize,
1500    },
1501
1502    /// Calling [`ServerConnection::set_resumption_data()`] must be done before
1503    /// any resumption is offered.
1504    ///
1505    /// [`ServerConnection::set_resumption_data()`]: crate::server::ServerConnection::set_resumption_data()
1506    ResumptionDataProvidedTooLate,
1507
1508    /// [`KernelConnection::update_tx_secret()`] and associated are not available for TLS1.2 connections.
1509    ///
1510    /// [`KernelConnection::update_tx_secret()`]: crate::conn::kernel::KernelConnection::update_tx_secret()
1511    KeyUpdateNotAvailableForTls12,
1512}
1513
1514impl fmt::Display for ApiMisuse {
1515    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1516        write!(f, "{self:?}")
1517    }
1518}
1519
1520impl core::error::Error for ApiMisuse {}
1521
1522mod other_error {
1523    use core::error::Error as StdError;
1524    use core::fmt;
1525
1526    use crate::sync::Arc;
1527
1528    /// Any other error that cannot be expressed by a more specific [`Error`][super::Error]
1529    /// variant.
1530    ///
1531    /// For example, an `OtherError` could be produced by a custom crypto provider
1532    /// exposing a provider specific error.
1533    ///
1534    /// Enums holding this type will never compare equal to each other.
1535    #[derive(Debug, Clone)]
1536    pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1537
1538    impl OtherError {
1539        /// Create a new `OtherError` from any error type.
1540        pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1541            Self(Arc::new(err))
1542        }
1543    }
1544
1545    impl PartialEq<Self> for OtherError {
1546        fn eq(&self, _other: &Self) -> bool {
1547            false
1548        }
1549    }
1550
1551    impl fmt::Display for OtherError {
1552        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1553            write!(f, "{}", self.0)
1554        }
1555    }
1556
1557    impl StdError for OtherError {
1558        fn source(&self) -> Option<&(dyn StdError + 'static)> {
1559            Some(self.0.as_ref())
1560        }
1561    }
1562}
1563
1564pub use other_error::OtherError;
1565
1566/// An [`Error`] along with the (possibly encrypted) alert to send to
1567/// the peer.
1568pub struct ErrorWithAlert {
1569    /// The error
1570    pub error: Error,
1571    pub(crate) data: Vec<u8>,
1572}
1573
1574impl ErrorWithAlert {
1575    pub(crate) fn new(error: Error, send_path: &mut SendPath) -> Self {
1576        maybe_send_fatal_alert(send_path, &error);
1577        Self {
1578            error,
1579            data: send_path.sendable_tls.take_one_vec(),
1580        }
1581    }
1582
1583    /// Consume any pending TLS data.
1584    ///
1585    /// The returned buffer will contain the alert, if one is to be sent.
1586    pub fn take_tls_data(&mut self) -> Option<Vec<u8>> {
1587        match self.data.is_empty() {
1588            true => None,
1589            false => Some(mem::take(&mut self.data)),
1590        }
1591    }
1592}
1593
1594impl Deref for ErrorWithAlert {
1595    type Target = Error;
1596
1597    fn deref(&self) -> &Self::Target {
1598        &self.error
1599    }
1600}
1601
1602/// Direct conversion with no alert.
1603impl From<Error> for ErrorWithAlert {
1604    fn from(error: Error) -> Self {
1605        Self {
1606            error,
1607            data: Vec::new(),
1608        }
1609    }
1610}
1611
1612impl fmt::Debug for ErrorWithAlert {
1613    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1614        f.debug_struct("ErrorWithAlert")
1615            .field("error", &self.error)
1616            .field("data", &self.data.len())
1617            .finish_non_exhaustive()
1618    }
1619}