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