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    HandshakeHashVariedAfterRetry,
996    /// Received an alert with an undefined level and the given [`AlertDescription`]
997    IllegalAlertLevel(u8, AlertDescription),
998    IllegalHelloRetryRequestWithEmptyCookie,
999    IllegalHelloRetryRequestWithNoChanges,
1000    IllegalHelloRetryRequestWithOfferedGroup,
1001    IllegalHelloRetryRequestWithUnofferedCipherSuite,
1002    IllegalHelloRetryRequestWithUnofferedNamedGroup,
1003    IllegalHelloRetryRequestWithUnsupportedVersion,
1004    IllegalHelloRetryRequestWithWrongSessionId,
1005    IllegalHelloRetryRequestWithInvalidEch,
1006    IllegalMiddleboxChangeCipherSpec,
1007    IllegalTlsInnerPlaintext,
1008    /// Received a warning alert with the given [`AlertDescription`]
1009    IllegalWarningAlert(AlertDescription),
1010    IncorrectBinder,
1011    IncorrectFinished,
1012    InvalidCertCompression,
1013    InvalidMaxEarlyDataSize,
1014    InvalidKeyShare,
1015    KeyEpochWithPendingFragment,
1016    KeyUpdateReceivedInQuicConnection,
1017    MessageInterleavedWithHandshakeMessage,
1018    MissingBinderInPskExtension,
1019    MissingKeyShare,
1020    MissingPskModesExtension,
1021    MissingQuicTransportParameters,
1022    NoCertificatesPresented,
1023    OfferedDuplicateCertificateCompressions,
1024    OfferedDuplicateKeyShares,
1025    OfferedEarlyDataWithOldProtocolVersion,
1026    OfferedEmptyApplicationProtocol,
1027    OfferedIncorrectCompressions,
1028    PskExtensionMustBeLast,
1029    PskExtensionWithMismatchedIdsAndBinders,
1030    RefusedToFollowHelloRetryRequest,
1031    RejectedEarlyDataInterleavedWithHandshakeMessage,
1032    ResumptionAttemptedWithVariedEms,
1033    ResumptionOfferedWithVariedCipherSuite,
1034    ResumptionOfferedWithVariedEms,
1035    ResumptionOfferedWithIncompatibleCipherSuite,
1036    SelectedDifferentCipherSuiteAfterRetry,
1037    SelectedInvalidPsk,
1038    SelectedTls12UsingTls13VersionExtension,
1039    SelectedUnofferedApplicationProtocol,
1040    SelectedUnofferedCertCompression,
1041    SelectedUnofferedCipherSuite,
1042    SelectedUnofferedCompression,
1043    SelectedUnofferedKxGroup,
1044    SelectedUnofferedPsk,
1045    ServerEchoedCompatibilitySessionId,
1046    ServerHelloMustOfferUncompressedEcPoints,
1047    ServerNameDifferedOnRetry,
1048    ServerNameMustContainOneHostName,
1049    SignedKxWithWrongAlgorithm,
1050    SignedHandshakeWithUnadvertisedSigScheme,
1051    TooManyEmptyFragments,
1052    TooManyConsecutiveHandshakeMessagesAfterHandshake,
1053    TooManyRenegotiationRequests,
1054    TooManyWarningAlertsReceived,
1055    TooMuchEarlyDataReceived,
1056    UnexpectedCleartextExtension,
1057    UnsolicitedCertExtension,
1058    UnsolicitedEncryptedExtension,
1059    UnsolicitedSctList,
1060    UnsolicitedServerHelloExtension,
1061    WrongGroupForKeyShare,
1062    UnsolicitedEchExtension,
1063}
1064
1065impl From<PeerMisbehaved> for AlertDescription {
1066    fn from(e: PeerMisbehaved) -> Self {
1067        match e {
1068            PeerMisbehaved::DisallowedEncryptedExtension
1069            | PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch
1070            | PeerMisbehaved::UnexpectedCleartextExtension
1071            | PeerMisbehaved::UnsolicitedEchExtension
1072            | PeerMisbehaved::UnsolicitedEncryptedExtension
1073            | PeerMisbehaved::UnsolicitedServerHelloExtension => Self::UnsupportedExtension,
1074
1075            PeerMisbehaved::IllegalMiddleboxChangeCipherSpec
1076            | PeerMisbehaved::KeyEpochWithPendingFragment
1077            | PeerMisbehaved::KeyUpdateReceivedInQuicConnection => Self::UnexpectedMessage,
1078
1079            PeerMisbehaved::IllegalWarningAlert(_) => Self::DecodeError,
1080
1081            PeerMisbehaved::IncorrectBinder | PeerMisbehaved::IncorrectFinished => {
1082                Self::DecryptError
1083            }
1084
1085            PeerMisbehaved::InvalidCertCompression
1086            | PeerMisbehaved::SelectedUnofferedCertCompression => Self::BadCertificate,
1087
1088            PeerMisbehaved::MissingKeyShare
1089            | PeerMisbehaved::MissingPskModesExtension
1090            | PeerMisbehaved::MissingQuicTransportParameters => Self::MissingExtension,
1091
1092            PeerMisbehaved::NoCertificatesPresented => Self::CertificateRequired,
1093
1094            _ => Self::IllegalParameter,
1095        }
1096    }
1097}
1098
1099/// The set of cases where we failed to make a connection because a peer
1100/// doesn't support a TLS version/feature we require.
1101///
1102/// This is `non_exhaustive`: we might add or stop using items here in minor
1103/// versions.
1104#[expect(missing_docs)]
1105#[non_exhaustive]
1106#[derive(Clone, Copy, Debug, PartialEq)]
1107pub enum PeerIncompatible {
1108    EcPointsExtensionRequired,
1109    ExtendedMasterSecretExtensionRequired,
1110    IncorrectCertificateTypeExtension,
1111    KeyShareExtensionRequired,
1112    MultipleRawKeys,
1113    NamedGroupsExtensionRequired,
1114    NoCertificateRequestSignatureSchemesInCommon,
1115    NoCipherSuitesInCommon,
1116    NoEcPointFormatsInCommon,
1117    NoKxGroupsInCommon,
1118    NoSignatureSchemesInCommon,
1119    NoServerNameProvided,
1120    NullCompressionRequired,
1121    ServerDoesNotSupportTls12Or13,
1122    ServerSentHelloRetryRequestWithUnknownExtension,
1123    ServerTlsVersionIsDisabledByOurConfig,
1124    SignatureAlgorithmsExtensionRequired,
1125    SupportedVersionsExtensionRequired,
1126    Tls12NotOffered,
1127    Tls12NotOfferedOrEnabled,
1128    Tls13RequiredForQuic,
1129    UncompressedEcPointsRequired,
1130    UnknownCertificateType(u8),
1131    UnsolicitedCertificateTypeExtension,
1132}
1133
1134impl From<PeerIncompatible> for AlertDescription {
1135    fn from(e: PeerIncompatible) -> Self {
1136        match e {
1137            PeerIncompatible::NullCompressionRequired => Self::IllegalParameter,
1138
1139            PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig
1140            | PeerIncompatible::SupportedVersionsExtensionRequired
1141            | PeerIncompatible::Tls12NotOffered
1142            | PeerIncompatible::Tls12NotOfferedOrEnabled
1143            | PeerIncompatible::Tls13RequiredForQuic => Self::ProtocolVersion,
1144
1145            PeerIncompatible::UnknownCertificateType(_) => Self::UnsupportedCertificate,
1146
1147            _ => Self::HandshakeFailure,
1148        }
1149    }
1150}
1151
1152/// Extended Key Usage (EKU) purpose values.
1153///
1154/// These are usually represented as OID values in the certificate's extension (if present), but
1155/// we represent the values that are most relevant to rustls as named enum variants.
1156#[non_exhaustive]
1157#[derive(Clone, Debug, Eq, PartialEq)]
1158pub enum ExtendedKeyPurpose {
1159    /// Client authentication
1160    ClientAuth,
1161    /// Server authentication
1162    ServerAuth,
1163    /// Other EKU values
1164    ///
1165    /// Represented here as a `Vec<usize>` for human readability.
1166    Other(Vec<usize>),
1167}
1168
1169impl ExtendedKeyPurpose {
1170    #[cfg(feature = "webpki")]
1171    pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
1172        let values = values.collect::<Vec<_>>();
1173        match &*values {
1174            ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
1175            ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
1176            _ => Self::Other(values),
1177        }
1178    }
1179}
1180
1181impl fmt::Display for ExtendedKeyPurpose {
1182    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1183        match self {
1184            Self::ClientAuth => write!(f, "client authentication"),
1185            Self::ServerAuth => write!(f, "server authentication"),
1186            Self::Other(values) => {
1187                for (i, value) in values.iter().enumerate() {
1188                    if i > 0 {
1189                        write!(f, ", ")?;
1190                    }
1191                    write!(f, "{value}")?;
1192                }
1193                Ok(())
1194            }
1195        }
1196    }
1197}
1198
1199/// The ways in which a certificate revocation list (CRL) can be invalid.
1200#[non_exhaustive]
1201#[derive(Debug, Clone)]
1202pub enum CertRevocationListError {
1203    /// The CRL had a bad signature from its issuer.
1204    BadSignature,
1205
1206    /// A signature inside a certificate or on a handshake was made with an unsupported algorithm.
1207    UnsupportedSignatureAlgorithm {
1208        /// The signature algorithm OID that was unsupported.
1209        signature_algorithm_id: Vec<u8>,
1210        /// Supported algorithms that were available for signature verification.
1211        supported_algorithms: Vec<AlgorithmIdentifier>,
1212    },
1213
1214    /// A signature was made with an algorithm that doesn't match the relevant public key.
1215    UnsupportedSignatureAlgorithmForPublicKey {
1216        /// The signature algorithm OID.
1217        signature_algorithm_id: Vec<u8>,
1218        /// The public key algorithm OID.
1219        public_key_algorithm_id: Vec<u8>,
1220    },
1221
1222    /// The CRL contained an invalid CRL number.
1223    InvalidCrlNumber,
1224
1225    /// The CRL contained a revoked certificate with an invalid serial number.
1226    InvalidRevokedCertSerialNumber,
1227
1228    /// The CRL issuer does not specify the cRLSign key usage.
1229    IssuerInvalidForCrl,
1230
1231    /// The CRL is invalid for some other reason.
1232    ///
1233    /// Enums holding this variant will never compare equal to each other.
1234    Other(OtherError),
1235
1236    /// The CRL is not correctly encoded.
1237    ParseError,
1238
1239    /// The CRL is not a v2 X.509 CRL.
1240    UnsupportedCrlVersion,
1241
1242    /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
1243    UnsupportedCriticalExtension,
1244
1245    /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
1246    UnsupportedDeltaCrl,
1247
1248    /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
1249    /// other than the issuer of the CRL.
1250    UnsupportedIndirectCrl,
1251
1252    /// The CRL contained a revoked certificate with an unsupported revocation reason.
1253    /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
1254    ///
1255    /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
1256    UnsupportedRevocationReason,
1257}
1258
1259impl PartialEq<Self> for CertRevocationListError {
1260    fn eq(&self, other: &Self) -> bool {
1261        use CertRevocationListError::*;
1262        match (self, other) {
1263            (BadSignature, BadSignature) => true,
1264            (
1265                UnsupportedSignatureAlgorithm {
1266                    signature_algorithm_id: left_signature_algorithm_id,
1267                    supported_algorithms: left_supported_algorithms,
1268                },
1269                UnsupportedSignatureAlgorithm {
1270                    signature_algorithm_id: right_signature_algorithm_id,
1271                    supported_algorithms: right_supported_algorithms,
1272                },
1273            ) => {
1274                (left_signature_algorithm_id, left_supported_algorithms)
1275                    == (right_signature_algorithm_id, right_supported_algorithms)
1276            }
1277            (
1278                UnsupportedSignatureAlgorithmForPublicKey {
1279                    signature_algorithm_id: left_signature_algorithm_id,
1280                    public_key_algorithm_id: left_public_key_algorithm_id,
1281                },
1282                UnsupportedSignatureAlgorithmForPublicKey {
1283                    signature_algorithm_id: right_signature_algorithm_id,
1284                    public_key_algorithm_id: right_public_key_algorithm_id,
1285                },
1286            ) => {
1287                (left_signature_algorithm_id, left_public_key_algorithm_id)
1288                    == (right_signature_algorithm_id, right_public_key_algorithm_id)
1289            }
1290            (InvalidCrlNumber, InvalidCrlNumber) => true,
1291            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
1292            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
1293            (ParseError, ParseError) => true,
1294            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
1295            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
1296            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
1297            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
1298            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
1299            _ => false,
1300        }
1301    }
1302}
1303
1304/// An error that occurred while handling Encrypted Client Hello (ECH).
1305#[non_exhaustive]
1306#[derive(Debug, Clone, Eq, PartialEq)]
1307pub enum EncryptedClientHelloError {
1308    /// The provided ECH configuration list was invalid.
1309    InvalidConfigList,
1310    /// No compatible ECH configuration.
1311    NoCompatibleConfig,
1312    /// The client configuration has server name indication (SNI) disabled.
1313    SniRequired,
1314}
1315
1316/// The server rejected the request to enable Encrypted Client Hello (ECH)
1317///
1318/// If [`RejectedEch::can_retry()`] is true, then you may use this with
1319/// [`crate::client::EchConfig::for_retry()`] to build a new `EchConfig` for a fresh client
1320/// connection that will use a compatible ECH configuration provided by the server for a retry.
1321#[non_exhaustive]
1322#[derive(Debug, Clone, PartialEq)]
1323pub struct RejectedEch {
1324    pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
1325}
1326
1327impl RejectedEch {
1328    /// Returns true if the server provided new ECH configurations to use for a fresh retry connection
1329    ///
1330    /// The `RejectedEch` error can be provided to [`crate::client::EchConfig::for_retry()`]
1331    /// to build a new `EchConfig` for a fresh client connection that will use a compatible ECH
1332    /// configuration provided by the server for a retry.
1333    pub fn can_retry(&self) -> bool {
1334        self.retry_configs.is_some()
1335    }
1336
1337    /// Returns an `EchConfigListBytes` with the server's provided retry configurations (if any)
1338    pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
1339        let Some(retry_configs) = &self.retry_configs else {
1340            return None;
1341        };
1342
1343        let mut tls_encoded_list = Vec::new();
1344        retry_configs.encode(&mut tls_encoded_list);
1345
1346        Some(EchConfigListBytes::from(tls_encoded_list))
1347    }
1348}
1349
1350fn join<T: fmt::Debug>(items: &[T]) -> String {
1351    items
1352        .iter()
1353        .map(|x| format!("{x:?}"))
1354        .collect::<Vec<String>>()
1355        .join(" or ")
1356}
1357
1358/// Describes cases of API misuse
1359///
1360/// Variants here should be sufficiently detailed that the action needed is clear.
1361#[non_exhaustive]
1362#[derive(Debug, Clone, PartialEq)]
1363pub enum ApiMisuse {
1364    /// Trying to resume a session with an unknown cipher suite.
1365    ResumingFromUnknownCipherSuite(CipherSuite),
1366
1367    /// The [`KeyingMaterialExporter`][] was already consumed.
1368    ///
1369    /// Methods that obtain an exporter (eg, [`Connection::exporter()`][]) can only
1370    /// be used once.  This error is returned on subsequent calls.
1371    ///
1372    /// [`KeyingMaterialExporter`]: crate::KeyingMaterialExporter
1373    /// [`Connection::exporter()`]: crate::Connection::exporter()
1374    ExporterAlreadyUsed,
1375
1376    /// The `context` parameter to [`KeyingMaterialExporter::derive()`][] was too long.
1377    ///
1378    /// For TLS1.2 connections (only) this parameter is limited to 64KB.
1379    ///
1380    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1381    ExporterContextTooLong,
1382
1383    /// The `output` object for [`KeyingMaterialExporter::derive()`][] was too long.
1384    ///
1385    /// For TLS1.3 connections this is limited to 255 times the hash output length.
1386    ///
1387    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1388    ExporterOutputTooLong,
1389
1390    /// The `output` object to [`KeyingMaterialExporter::derive()`][] was zero length.
1391    ///
1392    /// This doesn't make sense, so we explicitly return an error (rather than simply
1393    /// producing no output as requested.)
1394    ///
1395    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1396    ExporterOutputZeroLength,
1397
1398    /// [`Acceptor::accept()`][] called after it yielded a connection.
1399    ///
1400    /// [`Acceptor::accept()`]: crate::server::Acceptor::accept()
1401    AcceptorPolledAfterCompletion,
1402
1403    /// Incorrect sample length provided to [`quic::HeaderProtectionKey::encrypt_in_place()`][]
1404    ///
1405    /// [`quic::HeaderProtectionKey::encrypt_in_place()`]: crate::quic::HeaderProtectionKey::encrypt_in_place()
1406    InvalidQuicHeaderProtectionSampleLength,
1407
1408    /// Incorrect relation between sample length and header number length provided to
1409    /// [`quic::HeaderProtectionKey::encrypt_in_place()`][]
1410    ///
1411    /// [`quic::HeaderProtectionKey::encrypt_in_place()`]: crate::quic::HeaderProtectionKey::encrypt_in_place()
1412    InvalidQuicHeaderProtectionPacketNumberLength,
1413
1414    /// Raw keys cannot be used with TLS 1.2.
1415    InvalidSignerForProtocolVersion,
1416
1417    /// QUIC attempted with a configuration that does not support TLS1.3.
1418    QuicRequiresTls13Support,
1419
1420    /// QUIC attempted with a configuration that does not support a ciphersuite that supports QUIC.
1421    NoQuicCompatibleCipherSuites,
1422
1423    /// An empty certificate chain was provided.
1424    EmptyCertificateChain,
1425
1426    /// QUIC attempted with unsupported [`ServerConfig::max_early_data_size`][]
1427    ///
1428    /// This field must be either zero or [`u32::MAX`] for QUIC.
1429    ///
1430    /// [`ServerConfig::max_early_data_size`]: crate::server::ServerConfig::max_early_data_size
1431    QuicRestrictsMaxEarlyDataSize,
1432
1433    /// A `CryptoProvider` must have at least one cipher suite.
1434    NoCipherSuitesConfigured,
1435
1436    /// A `CryptoProvider` must have at least one key exchange group.
1437    NoKeyExchangeGroupsConfigured,
1438
1439    /// An empty list of signature verification algorithms was provided.
1440    NoSignatureVerificationAlgorithms,
1441
1442    /// ECH attempted with a configuration that does not support TLS1.3.
1443    EchRequiresTls13Support,
1444
1445    /// ECH attempted with a configuration that also supports TLS1.2.
1446    EchForbidsTls12Support,
1447
1448    /// Secret extraction operation attempted without opting-in to secret extraction.
1449    ///
1450    /// This is possible from [`Connection::dangerous_extract_secrets()`][crate::Connection::dangerous_extract_secrets].
1451    ///
1452    /// You must set [`ServerConfig::enable_secret_extraction`][crate::server::ServerConfig::enable_secret_extraction] or
1453    /// [`ClientConfig::enable_secret_extraction`][crate::client::ClientConfig::enable_secret_extraction] to true before this
1454    /// is available.
1455    SecretExtractionRequiresPriorOptIn,
1456
1457    /// Secret extraction operation attempted without first extracting all pending
1458    /// TLS data.
1459    ///
1460    /// See [`Self::SecretExtractionRequiresPriorOptIn`] for a list of the affected
1461    /// functions.  You must ensure any prior generated TLS records are extracted
1462    /// from the library before using one of these functions.
1463    SecretExtractionWithPendingSendableData,
1464
1465    /// Attempt to verify a certificate with an unsupported type.
1466    ///
1467    /// A verifier indicated support for a certificate type but then failed to verify the peer's
1468    /// identity of that type.
1469    UnverifiableCertificateType,
1470
1471    /// A verifier or resolver implementation signalled that it does not support any certificate types.
1472    NoSupportedCertificateTypes,
1473
1474    /// [`Nonce::to_array()`][] called with incorrect array size.
1475    ///
1476    /// The nonce length does not match the requested array size `N`.
1477    ///
1478    /// [`Nonce::to_array()`]: crate::crypto::cipher::Nonce::to_array()
1479    NonceArraySizeMismatch {
1480        /// The expected array size (type parameter N)
1481        expected: usize,
1482        /// The actual nonce length
1483        actual: usize,
1484    },
1485
1486    /// [`Iv::new()`][] called with a value that exceeds the maximum IV length.
1487    ///
1488    /// The IV length must not exceed [`Iv::MAX_LEN`][].
1489    ///
1490    /// [`Iv::new()`]: crate::crypto::cipher::Iv::new()
1491    /// [`Iv::MAX_LEN`]: crate::crypto::cipher::Iv::MAX_LEN
1492    IvLengthExceedsMaximum {
1493        /// The actual IV length provided
1494        actual: usize,
1495        /// The maximum allowed IV length
1496        maximum: usize,
1497    },
1498
1499    /// Calling [`ServerConnection::set_resumption_data()`] must be done before
1500    /// any resumption is offered.
1501    ///
1502    /// [`ServerConnection::set_resumption_data()`]: crate::server::ServerConnection::set_resumption_data()
1503    ResumptionDataProvidedTooLate,
1504
1505    /// [`KernelConnection::update_tx_secret()`] and associated are not available for TLS1.2 connections.
1506    ///
1507    /// [`KernelConnection::update_tx_secret()`]: crate::conn::kernel::KernelConnection::update_tx_secret()
1508    KeyUpdateNotAvailableForTls12,
1509}
1510
1511impl fmt::Display for ApiMisuse {
1512    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1513        write!(f, "{self:?}")
1514    }
1515}
1516
1517impl core::error::Error for ApiMisuse {}
1518
1519mod other_error {
1520    use core::error::Error as StdError;
1521    use core::fmt;
1522
1523    use crate::sync::Arc;
1524
1525    /// Any other error that cannot be expressed by a more specific [`Error`][super::Error]
1526    /// variant.
1527    ///
1528    /// For example, an `OtherError` could be produced by a custom crypto provider
1529    /// exposing a provider specific error.
1530    ///
1531    /// Enums holding this type will never compare equal to each other.
1532    #[derive(Debug, Clone)]
1533    pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1534
1535    impl OtherError {
1536        /// Create a new `OtherError` from any error type.
1537        pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1538            Self(Arc::new(err))
1539        }
1540    }
1541
1542    impl PartialEq<Self> for OtherError {
1543        fn eq(&self, _other: &Self) -> bool {
1544            false
1545        }
1546    }
1547
1548    impl fmt::Display for OtherError {
1549        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1550            write!(f, "{}", self.0)
1551        }
1552    }
1553
1554    impl StdError for OtherError {
1555        fn source(&self) -> Option<&(dyn StdError + 'static)> {
1556            Some(self.0.as_ref())
1557        }
1558    }
1559}
1560
1561pub use other_error::OtherError;
1562
1563/// An [`Error`] along with the (possibly encrypted) alert to send to
1564/// the peer.
1565pub struct ErrorWithAlert {
1566    /// The error
1567    pub error: Error,
1568    pub(crate) data: Vec<u8>,
1569}
1570
1571impl ErrorWithAlert {
1572    pub(crate) fn new(error: Error, send_path: &mut SendPath) -> Self {
1573        maybe_send_fatal_alert(send_path, &error);
1574        Self {
1575            error,
1576            data: send_path.sendable_tls.take_one_vec(),
1577        }
1578    }
1579
1580    /// Consume any pending TLS data.
1581    ///
1582    /// The returned buffer will contain the alert, if one is to be sent.
1583    pub fn take_tls_data(&mut self) -> Option<Vec<u8>> {
1584        match self.data.is_empty() {
1585            true => None,
1586            false => Some(mem::take(&mut self.data)),
1587        }
1588    }
1589}
1590
1591impl Deref for ErrorWithAlert {
1592    type Target = Error;
1593
1594    fn deref(&self) -> &Self::Target {
1595        &self.error
1596    }
1597}
1598
1599/// Direct conversion with no alert.
1600impl From<Error> for ErrorWithAlert {
1601    fn from(error: Error) -> Self {
1602        Self {
1603            error,
1604            data: Vec::new(),
1605        }
1606    }
1607}
1608
1609impl fmt::Debug for ErrorWithAlert {
1610    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1611        f.debug_struct("ErrorWithAlert")
1612            .field("error", &self.error)
1613            .field("data", &self.data.len())
1614            .finish_non_exhaustive()
1615    }
1616}