rustls/error/
mod.rs

1//! Error types used throughout rustls.
2
3use alloc::format;
4use alloc::string::String;
5use alloc::vec::Vec;
6use core::fmt;
7#[cfg(feature = "std")]
8use std::time::SystemTimeError;
9
10use pki_types::{AlgorithmIdentifier, EchConfigListBytes, ServerName, UnixTime};
11use webpki::ExtendedKeyUsage;
12
13use crate::crypto::kx::KeyExchangeAlgorithm;
14use crate::crypto::{GetRandomFailed, InconsistentKeys};
15use crate::enums::{ContentType, HandshakeType};
16use crate::msgs::codec::Codec;
17use crate::msgs::handshake::EchConfigPayload;
18
19#[cfg(test)]
20mod tests;
21
22/// rustls reports protocol errors using this type.
23#[non_exhaustive]
24#[derive(Debug, PartialEq, Clone)]
25pub enum Error {
26    /// We received a TLS message that isn't valid right now.
27    /// `expect_types` lists the message types we can expect right now.
28    /// `got_type` is the type we found.  This error is typically
29    /// caused by a buggy TLS stack (the peer or this one), a broken
30    /// network, or an attack.
31    InappropriateMessage {
32        /// Which types we expected
33        expect_types: Vec<ContentType>,
34        /// What type we received
35        got_type: ContentType,
36    },
37
38    /// We received a TLS handshake message that isn't valid right now.
39    /// `expect_types` lists the handshake message types we can expect
40    /// right now.  `got_type` is the type we found.
41    InappropriateHandshakeMessage {
42        /// Which handshake type we expected
43        expect_types: Vec<HandshakeType>,
44        /// What handshake type we received
45        got_type: HandshakeType,
46    },
47
48    /// An error occurred while handling Encrypted Client Hello (ECH).
49    InvalidEncryptedClientHello(EncryptedClientHelloError),
50
51    /// The peer sent us a TLS message with invalid contents.
52    InvalidMessage(InvalidMessage),
53
54    /// The certificate verifier doesn't support the given type of name.
55    UnsupportedNameType,
56
57    /// We couldn't decrypt a message.  This is invariably fatal.
58    DecryptError,
59
60    /// We couldn't encrypt a message because it was larger than the allowed message size.
61    /// This should never happen if the application is using valid record sizes.
62    EncryptError,
63
64    /// The peer doesn't support a protocol version/feature we require.
65    /// The parameter gives a hint as to what version/feature it is.
66    PeerIncompatible(PeerIncompatible),
67
68    /// The peer deviated from the standard TLS protocol.
69    /// The parameter gives a hint where.
70    PeerMisbehaved(PeerMisbehaved),
71
72    /// We received a fatal alert.  This means the peer is unhappy.
73    AlertReceived(AlertDescription),
74
75    /// We saw an invalid certificate.
76    ///
77    /// The contained error is from the certificate validation trait
78    /// implementation.
79    InvalidCertificate(CertificateError),
80
81    /// A provided certificate revocation list (CRL) was invalid.
82    InvalidCertRevocationList(CertRevocationListError),
83
84    /// A catch-all error for unlikely errors.
85    General(String),
86
87    /// We failed to figure out what time it currently is.
88    FailedToGetCurrentTime,
89
90    /// We failed to acquire random bytes from the system.
91    FailedToGetRandomBytes,
92
93    /// This function doesn't work until the TLS handshake
94    /// is complete.
95    HandshakeNotComplete,
96
97    /// The peer sent an oversized record/fragment.
98    PeerSentOversizedRecord,
99
100    /// An incoming connection did not support any known application protocol.
101    NoApplicationProtocol,
102
103    /// The server certificate resolver didn't find an appropriate certificate.
104    NoSuitableCertificate,
105
106    /// The `max_fragment_size` value supplied in configuration was too small,
107    /// or too large.
108    BadMaxFragmentSize,
109
110    /// Specific failure cases from [`Credentials::new()`] or a
111    /// [`crate::crypto::SigningKey`] that cannot produce a corresponding public key.
112    ///
113    /// If encountered while building a [`Credentials`], consider if
114    /// [`Credentials::new_unchecked()`] might be appropriate for your use case.
115    ///
116    /// [`Credentials::new()`]: crate::crypto::Credentials::new()
117    /// [`Credentials`]: crate::crypto::Credentials
118    /// [`Credentials::new_unchecked()`]: crate::crypto::Credentials::new_unchecked()
119    InconsistentKeys(InconsistentKeys),
120
121    /// The server rejected encrypted client hello (ECH) negotiation
122    ///
123    /// It may have returned new ECH configurations that could be used to retry negotiation
124    /// with a fresh connection.
125    ///
126    /// See [`RejectedEch::can_retry()`] and [`crate::client::EchConfig::for_retry()`].
127    RejectedEch(RejectedEch),
128
129    /// Errors of this variant should never be produced by the library.
130    ///
131    /// Please file a bug if you see one.
132    Unreachable(&'static str),
133
134    /// The caller misused the API
135    ///
136    /// Generally we try to make error cases like this unnecessary by embedding
137    /// the constraints in the type system, so misuses simply do not compile.  But,
138    /// for cases where that is not possible or exceptionally costly, we return errors
139    /// of this variant.
140    ///
141    /// This only results from the ordering, dependencies or parameter values of calls,
142    /// so (assuming parameter values are fixed) these can be determined and fixed by
143    /// reading the code.  They are never caused by the values of untrusted data, or
144    /// other non-determinism.
145    ApiMisuse(ApiMisuse),
146
147    /// Any other error.
148    ///
149    /// This variant should only be used when the error is not better described by a more
150    /// specific variant. For example, if a custom crypto provider returns a
151    /// provider specific error.
152    ///
153    /// Enums holding this variant will never compare equal to each other.
154    Other(OtherError),
155}
156
157/// Determine which alert should be sent for a given error.
158///
159/// If this mapping fails, no alert is sent.
160impl TryFrom<&Error> for AlertDescription {
161    type Error = ();
162
163    fn try_from(error: &Error) -> Result<Self, Self::Error> {
164        Ok(match error {
165            Error::DecryptError => Self::BadRecordMac,
166            Error::InappropriateMessage { .. } | Error::InappropriateHandshakeMessage { .. } => {
167                Self::UnexpectedMessage
168            }
169            Error::InvalidCertificate(e) => Self::from(e),
170            Error::InvalidMessage(e) => Self::from(*e),
171            Error::NoApplicationProtocol => Self::NoApplicationProtocol,
172            Error::PeerMisbehaved(e) => Self::from(*e),
173            Error::PeerIncompatible(e) => Self::from(*e),
174            Error::PeerSentOversizedRecord => Self::RecordOverflow,
175            Error::RejectedEch(_) => Self::EncryptedClientHelloRequired,
176
177            _ => return Err(()),
178        })
179    }
180}
181
182impl fmt::Display for Error {
183    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184        match self {
185            Self::InappropriateMessage {
186                expect_types,
187                got_type,
188            } => write!(
189                f,
190                "received unexpected message: got {:?} when expecting {}",
191                got_type,
192                join::<ContentType>(expect_types)
193            ),
194            Self::InappropriateHandshakeMessage {
195                expect_types,
196                got_type,
197            } => write!(
198                f,
199                "received unexpected handshake message: got {:?} when expecting {}",
200                got_type,
201                join::<HandshakeType>(expect_types)
202            ),
203            Self::InvalidMessage(typ) => {
204                write!(f, "received corrupt message of type {typ:?}")
205            }
206            Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
207            Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
208            Self::AlertReceived(alert) => write!(f, "received fatal alert: the peer {alert}"),
209            Self::InvalidCertificate(err) => {
210                write!(f, "invalid peer certificate: {err}")
211            }
212            Self::InvalidCertRevocationList(err) => {
213                write!(f, "invalid certificate revocation list: {err:?}")
214            }
215            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
216            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
217            Self::InvalidEncryptedClientHello(err) => {
218                write!(f, "encrypted client hello failure: {err:?}")
219            }
220            Self::EncryptError => write!(f, "cannot encrypt message"),
221            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
222            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
223            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
224            Self::NoSuitableCertificate => write!(f, "no suitable certificate found"),
225            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
226            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
227            Self::BadMaxFragmentSize => {
228                write!(f, "the supplied max_fragment_size was too small or large")
229            }
230            Self::InconsistentKeys(why) => {
231                write!(f, "keys may not be consistent: {why:?}")
232            }
233            Self::RejectedEch(why) => {
234                write!(
235                    f,
236                    "server rejected encrypted client hello (ECH) {} retry configs",
237                    if why.can_retry() { "with" } else { "without" }
238                )
239            }
240            Self::General(err) => write!(f, "unexpected error: {err}"),
241            Self::Unreachable(err) => write!(
242                f,
243                "unreachable condition: {err} (please file a bug in rustls)"
244            ),
245            Self::ApiMisuse(why) => write!(f, "API misuse: {why:?}"),
246            Self::Other(err) => write!(f, "other error: {err}"),
247        }
248    }
249}
250
251impl From<CertificateError> for Error {
252    #[inline]
253    fn from(e: CertificateError) -> Self {
254        Self::InvalidCertificate(e)
255    }
256}
257
258impl From<InvalidMessage> for Error {
259    #[inline]
260    fn from(e: InvalidMessage) -> Self {
261        Self::InvalidMessage(e)
262    }
263}
264
265impl From<PeerMisbehaved> for Error {
266    #[inline]
267    fn from(e: PeerMisbehaved) -> Self {
268        Self::PeerMisbehaved(e)
269    }
270}
271
272impl From<PeerIncompatible> for Error {
273    #[inline]
274    fn from(e: PeerIncompatible) -> Self {
275        Self::PeerIncompatible(e)
276    }
277}
278
279impl From<CertRevocationListError> for Error {
280    #[inline]
281    fn from(e: CertRevocationListError) -> Self {
282        Self::InvalidCertRevocationList(e)
283    }
284}
285
286impl From<EncryptedClientHelloError> for Error {
287    #[inline]
288    fn from(e: EncryptedClientHelloError) -> Self {
289        Self::InvalidEncryptedClientHello(e)
290    }
291}
292
293impl From<RejectedEch> for Error {
294    fn from(rejected_error: RejectedEch) -> Self {
295        Self::RejectedEch(rejected_error)
296    }
297}
298
299impl From<ApiMisuse> for Error {
300    fn from(e: ApiMisuse) -> Self {
301        Self::ApiMisuse(e)
302    }
303}
304
305impl From<OtherError> for Error {
306    fn from(value: OtherError) -> Self {
307        Self::Other(value)
308    }
309}
310
311impl From<InconsistentKeys> for Error {
312    #[inline]
313    fn from(e: InconsistentKeys) -> Self {
314        Self::InconsistentKeys(e)
315    }
316}
317
318#[cfg(feature = "std")]
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            #[cfg(feature = "std")]
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    /// The `Unknown` item is used when processing unrecognized ordinals.
721    #[repr(u8)]
722    pub enum AlertDescription {
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/draft-ietf-tls-esni-18#section-11.2
758    }
759}
760
761impl fmt::Display for AlertDescription {
762    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
763        // these should be:
764        // - in past tense
765        // - be syntactically correct if prefaced with 'the peer' to describe
766        //   received alerts
767        match self {
768            // this is normal.
769            Self::CloseNotify => write!(f, "cleanly closed the connection"),
770
771            // these are abnormal.  they are usually symptomatic of an interop failure.
772            // please file a bug report.
773            Self::UnexpectedMessage => write!(f, "received an unexpected message"),
774            Self::BadRecordMac => write!(f, "failed to verify a message"),
775            Self::RecordOverflow => write!(f, "rejected an over-length message"),
776            Self::IllegalParameter => write!(
777                f,
778                "rejected a message because a field was incorrect or inconsistent"
779            ),
780            Self::DecodeError => write!(f, "failed to decode a message"),
781            Self::DecryptError => {
782                write!(f, "failed to perform a handshake cryptographic operation")
783            }
784            Self::InappropriateFallback => {
785                write!(f, "detected an attempted version downgrade")
786            }
787            Self::MissingExtension => {
788                write!(f, "required a specific extension that was not provided")
789            }
790            Self::UnsupportedExtension => write!(f, "rejected an unsolicited extension"),
791
792            // these are deprecated by TLS1.3 and should be very rare (but possible
793            // with TLS1.2 or earlier peers)
794            Self::DecryptionFailed => write!(f, "failed to decrypt a message"),
795            Self::DecompressionFailure => write!(f, "failed to decompress a message"),
796            Self::NoCertificate => write!(f, "found no certificate"),
797            Self::ExportRestriction => write!(f, "refused due to export restrictions"),
798            Self::NoRenegotiation => write!(f, "rejected an attempt at renegotiation"),
799            Self::CertificateUnobtainable => {
800                write!(f, "failed to retrieve its certificate")
801            }
802            Self::BadCertificateHashValue => {
803                write!(f, "rejected the `certificate_hash` extension")
804            }
805
806            // this is fairly normal. it means a server cannot choose compatible parameters
807            // given our offer.  please use ssllabs.com or similar to investigate what parameters
808            // the server supports.
809            Self::HandshakeFailure => write!(
810                f,
811                "failed to negotiate an acceptable set of security parameters"
812            ),
813            Self::ProtocolVersion => write!(f, "did not support a suitable TLS version"),
814            Self::InsufficientSecurity => {
815                write!(f, "required a higher security level than was offered")
816            }
817
818            // these usually indicate a local misconfiguration, either in certificate selection
819            // or issuance.
820            Self::BadCertificate => {
821                write!(
822                    f,
823                    "rejected the certificate as corrupt or incorrectly signed"
824                )
825            }
826            Self::UnsupportedCertificate => {
827                write!(f, "did not support the certificate")
828            }
829            Self::CertificateRevoked => write!(f, "found the certificate to be revoked"),
830            Self::CertificateExpired => write!(f, "found the certificate to be expired"),
831            Self::CertificateUnknown => {
832                write!(f, "rejected the certificate for an unspecified reason")
833            }
834            Self::UnknownCa => write!(f, "found the certificate was not issued by a trusted CA"),
835            Self::BadCertificateStatusResponse => {
836                write!(f, "rejected the certificate status response")
837            }
838            // typically this means client authentication is required, in TLS1.2...
839            Self::AccessDenied => write!(f, "denied access"),
840            // and in TLS1.3...
841            Self::CertificateRequired => write!(f, "required a client certificate"),
842
843            Self::InternalError => write!(f, "encountered an internal error"),
844            Self::UserCanceled => write!(f, "canceled the handshake"),
845
846            // rejection of SNI (uncommon; usually servers behave as if it was not sent)
847            Self::UnrecognizedName => {
848                write!(f, "did not recognize a name in the `server_name` extension")
849            }
850
851            // rejection of PSK connections (NYI in this library); indicates a local
852            // misconfiguration.
853            Self::UnknownPskIdentity => {
854                write!(f, "did not recognize any offered PSK identity")
855            }
856
857            // rejection of ALPN (varying levels of support, but missing support is
858            // often dangerous if the peers fail to agree on the same protocol)
859            Self::NoApplicationProtocol => write!(
860                f,
861                "did not support any of the offered application protocols"
862            ),
863
864            // ECH requirement by clients, see
865            // <https://datatracker.ietf.org/doc/draft-ietf-tls-esni/25/>
866            Self::EncryptedClientHelloRequired => {
867                write!(f, "required use of encrypted client hello")
868            }
869
870            Self::Unknown(n) => write!(f, "sent an unknown alert (0x{n:02x?})"),
871        }
872    }
873}
874
875/// A corrupt TLS message payload that resulted in an error.
876#[non_exhaustive]
877#[derive(Debug, Clone, Copy, PartialEq)]
878pub enum InvalidMessage {
879    /// A certificate payload exceeded rustls's 64KB limit
880    CertificatePayloadTooLarge,
881    /// An advertised message was larger then expected.
882    HandshakePayloadTooLarge,
883    /// The peer sent us a syntactically incorrect ChangeCipherSpec payload.
884    InvalidCcs,
885    /// An unknown content type was encountered during message decoding.
886    InvalidContentType,
887    /// A peer sent an invalid certificate status type
888    InvalidCertificateStatusType,
889    /// Context was incorrectly attached to a certificate request during a handshake.
890    InvalidCertRequest,
891    /// A peer's DH params could not be decoded
892    InvalidDhParams,
893    /// A message was zero-length when its record kind forbids it.
894    InvalidEmptyPayload,
895    /// A peer sent an unexpected key update request.
896    InvalidKeyUpdate,
897    /// A peer's server name could not be decoded
898    InvalidServerName,
899    /// A TLS message payload was larger then allowed by the specification.
900    MessageTooLarge,
901    /// Message is shorter than the expected length
902    MessageTooShort,
903    /// Missing data for the named handshake payload value
904    MissingData(&'static str),
905    /// A peer did not advertise its supported key exchange groups.
906    MissingKeyExchange,
907    /// A peer sent an empty list of signature schemes
908    NoSignatureSchemes,
909    /// Trailing data found for the named handshake payload value
910    TrailingData(&'static str),
911    /// A peer sent an unexpected message type.
912    UnexpectedMessage(&'static str),
913    /// An unknown TLS protocol was encountered during message decoding.
914    UnknownProtocolVersion,
915    /// A peer sent a non-null compression method.
916    UnsupportedCompression,
917    /// A peer sent an unknown elliptic curve type.
918    UnsupportedCurveType,
919    /// A peer sent an unsupported key exchange algorithm.
920    UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
921    /// A server sent an empty ticket
922    EmptyTicketValue,
923    /// A peer sent an empty list of items, but a non-empty list is required.
924    ///
925    /// The argument names the context.
926    IllegalEmptyList(&'static str),
927    /// A peer sent an empty value, but a non-empty value is required.
928    IllegalEmptyValue,
929    /// A peer sent a message where a given extension type was repeated
930    DuplicateExtension(u16),
931    /// A peer sent a message with a PSK offer extension in wrong position
932    PreSharedKeyIsNotFinalExtension,
933    /// A server sent a HelloRetryRequest with an unknown extension
934    UnknownHelloRetryRequestExtension,
935    /// The peer sent a TLS1.3 Certificate with an unknown extension
936    UnknownCertificateExtension,
937}
938
939impl From<InvalidMessage> for AlertDescription {
940    fn from(e: InvalidMessage) -> Self {
941        match e {
942            InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
943            InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
944            InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
945            InvalidMessage::CertificatePayloadTooLarge => Self::BadCertificate,
946            _ => Self::DecodeError,
947        }
948    }
949}
950
951/// The set of cases where we failed to make a connection because we thought
952/// the peer was misbehaving.
953///
954/// This is `non_exhaustive`: we might add or stop using items here in minor
955/// versions.  We also don't document what they mean.  Generally a user of
956/// rustls shouldn't vary its behaviour on these error codes, and there is
957/// nothing it can do to improve matters.
958///
959/// Please file a bug against rustls if you see `Error::PeerMisbehaved` in
960/// the wild.
961#[expect(missing_docs)]
962#[non_exhaustive]
963#[derive(Clone, Copy, Debug, PartialEq)]
964pub enum PeerMisbehaved {
965    AttemptedDowngradeToTls12WhenTls13IsSupported,
966    BadCertChainExtensions,
967    DisallowedEncryptedExtension,
968    DuplicateClientHelloExtensions,
969    DuplicateEncryptedExtensions,
970    DuplicateHelloRetryRequestExtensions,
971    DuplicateNewSessionTicketExtensions,
972    DuplicateServerHelloExtensions,
973    DuplicateServerNameTypes,
974    EarlyDataAttemptedInSecondClientHello,
975    EarlyDataExtensionWithoutResumption,
976    EarlyDataOfferedWithVariedCipherSuite,
977    HandshakeHashVariedAfterRetry,
978    /// Received an alert with an undefined level and the given [`AlertDescription`]
979    IllegalAlertLevel(u8, AlertDescription),
980    IllegalHelloRetryRequestWithEmptyCookie,
981    IllegalHelloRetryRequestWithNoChanges,
982    IllegalHelloRetryRequestWithOfferedGroup,
983    IllegalHelloRetryRequestWithUnofferedCipherSuite,
984    IllegalHelloRetryRequestWithUnofferedNamedGroup,
985    IllegalHelloRetryRequestWithUnsupportedVersion,
986    IllegalHelloRetryRequestWithWrongSessionId,
987    IllegalHelloRetryRequestWithInvalidEch,
988    IllegalMiddleboxChangeCipherSpec,
989    IllegalTlsInnerPlaintext,
990    /// Received a warning alert with the given [`AlertDescription`]
991    IllegalWarningAlert(AlertDescription),
992    IncorrectBinder,
993    IncorrectFinished,
994    InvalidCertCompression,
995    InvalidMaxEarlyDataSize,
996    InvalidKeyShare,
997    KeyEpochWithPendingFragment,
998    KeyUpdateReceivedInQuicConnection,
999    MessageInterleavedWithHandshakeMessage,
1000    MissingBinderInPskExtension,
1001    MissingKeyShare,
1002    MissingPskModesExtension,
1003    MissingQuicTransportParameters,
1004    NoCertificatesPresented,
1005    OfferedDuplicateCertificateCompressions,
1006    OfferedDuplicateKeyShares,
1007    OfferedEarlyDataWithOldProtocolVersion,
1008    OfferedEmptyApplicationProtocol,
1009    OfferedIncorrectCompressions,
1010    PskExtensionMustBeLast,
1011    PskExtensionWithMismatchedIdsAndBinders,
1012    RefusedToFollowHelloRetryRequest,
1013    RejectedEarlyDataInterleavedWithHandshakeMessage,
1014    ResumptionAttemptedWithVariedEms,
1015    ResumptionOfferedWithVariedCipherSuite,
1016    ResumptionOfferedWithVariedEms,
1017    ResumptionOfferedWithIncompatibleCipherSuite,
1018    SelectedDifferentCipherSuiteAfterRetry,
1019    SelectedInvalidPsk,
1020    SelectedTls12UsingTls13VersionExtension,
1021    SelectedUnofferedApplicationProtocol,
1022    SelectedUnofferedCertCompression,
1023    SelectedUnofferedCipherSuite,
1024    SelectedUnofferedCompression,
1025    SelectedUnofferedKxGroup,
1026    SelectedUnofferedPsk,
1027    ServerEchoedCompatibilitySessionId,
1028    ServerHelloMustOfferUncompressedEcPoints,
1029    ServerNameDifferedOnRetry,
1030    ServerNameMustContainOneHostName,
1031    SignedKxWithWrongAlgorithm,
1032    SignedHandshakeWithUnadvertisedSigScheme,
1033    TooManyEmptyFragments,
1034    TooManyKeyUpdateRequests,
1035    TooManyRenegotiationRequests,
1036    TooManyWarningAlertsReceived,
1037    TooMuchEarlyDataReceived,
1038    UnexpectedCleartextExtension,
1039    UnsolicitedCertExtension,
1040    UnsolicitedEncryptedExtension,
1041    UnsolicitedSctList,
1042    UnsolicitedServerHelloExtension,
1043    WrongGroupForKeyShare,
1044    UnsolicitedEchExtension,
1045}
1046
1047impl From<PeerMisbehaved> for AlertDescription {
1048    fn from(e: PeerMisbehaved) -> Self {
1049        match e {
1050            PeerMisbehaved::DisallowedEncryptedExtension
1051            | PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch
1052            | PeerMisbehaved::UnexpectedCleartextExtension
1053            | PeerMisbehaved::UnsolicitedEchExtension
1054            | PeerMisbehaved::UnsolicitedEncryptedExtension
1055            | PeerMisbehaved::UnsolicitedServerHelloExtension => Self::UnsupportedExtension,
1056
1057            PeerMisbehaved::IllegalMiddleboxChangeCipherSpec
1058            | PeerMisbehaved::KeyEpochWithPendingFragment
1059            | PeerMisbehaved::KeyUpdateReceivedInQuicConnection => Self::UnexpectedMessage,
1060
1061            PeerMisbehaved::IllegalWarningAlert(_) => Self::DecodeError,
1062
1063            PeerMisbehaved::IncorrectBinder | PeerMisbehaved::IncorrectFinished => {
1064                Self::DecryptError
1065            }
1066
1067            PeerMisbehaved::InvalidCertCompression
1068            | PeerMisbehaved::SelectedUnofferedCertCompression => Self::BadCertificate,
1069
1070            PeerMisbehaved::MissingKeyShare
1071            | PeerMisbehaved::MissingPskModesExtension
1072            | PeerMisbehaved::MissingQuicTransportParameters => Self::MissingExtension,
1073
1074            PeerMisbehaved::NoCertificatesPresented => Self::CertificateRequired,
1075
1076            _ => Self::IllegalParameter,
1077        }
1078    }
1079}
1080
1081/// The set of cases where we failed to make a connection because a peer
1082/// doesn't support a TLS version/feature we require.
1083///
1084/// This is `non_exhaustive`: we might add or stop using items here in minor
1085/// versions.
1086#[expect(missing_docs)]
1087#[non_exhaustive]
1088#[derive(Clone, Copy, Debug, PartialEq)]
1089pub enum PeerIncompatible {
1090    EcPointsExtensionRequired,
1091    ExtendedMasterSecretExtensionRequired,
1092    IncorrectCertificateTypeExtension,
1093    KeyShareExtensionRequired,
1094    MultipleRawKeys,
1095    NamedGroupsExtensionRequired,
1096    NoCertificateRequestSignatureSchemesInCommon,
1097    NoCipherSuitesInCommon,
1098    NoEcPointFormatsInCommon,
1099    NoKxGroupsInCommon,
1100    NoSignatureSchemesInCommon,
1101    NoServerNameProvided,
1102    NullCompressionRequired,
1103    ServerDoesNotSupportTls12Or13,
1104    ServerSentHelloRetryRequestWithUnknownExtension,
1105    ServerTlsVersionIsDisabledByOurConfig,
1106    SignatureAlgorithmsExtensionRequired,
1107    SupportedVersionsExtensionRequired,
1108    Tls12NotOffered,
1109    Tls12NotOfferedOrEnabled,
1110    Tls13RequiredForQuic,
1111    UncompressedEcPointsRequired,
1112    UnknownCertificateType(u8),
1113    UnsolicitedCertificateTypeExtension,
1114}
1115
1116impl From<PeerIncompatible> for AlertDescription {
1117    fn from(e: PeerIncompatible) -> Self {
1118        match e {
1119            PeerIncompatible::NullCompressionRequired => Self::IllegalParameter,
1120
1121            PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig
1122            | PeerIncompatible::SupportedVersionsExtensionRequired
1123            | PeerIncompatible::Tls12NotOffered
1124            | PeerIncompatible::Tls12NotOfferedOrEnabled
1125            | PeerIncompatible::Tls13RequiredForQuic => Self::ProtocolVersion,
1126
1127            PeerIncompatible::UnknownCertificateType(_) => Self::UnsupportedCertificate,
1128
1129            _ => Self::HandshakeFailure,
1130        }
1131    }
1132}
1133
1134/// Extended Key Usage (EKU) purpose values.
1135///
1136/// These are usually represented as OID values in the certificate's extension (if present), but
1137/// we represent the values that are most relevant to rustls as named enum variants.
1138#[non_exhaustive]
1139#[derive(Clone, Debug, Eq, PartialEq)]
1140pub enum ExtendedKeyPurpose {
1141    /// Client authentication
1142    ClientAuth,
1143    /// Server authentication
1144    ServerAuth,
1145    /// Other EKU values
1146    ///
1147    /// Represented here as a `Vec<usize>` for human readability.
1148    Other(Vec<usize>),
1149}
1150
1151impl ExtendedKeyPurpose {
1152    pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
1153        let values = values.collect::<Vec<_>>();
1154        match &*values {
1155            ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
1156            ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
1157            _ => Self::Other(values),
1158        }
1159    }
1160}
1161
1162impl fmt::Display for ExtendedKeyPurpose {
1163    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1164        match self {
1165            Self::ClientAuth => write!(f, "client authentication"),
1166            Self::ServerAuth => write!(f, "server authentication"),
1167            Self::Other(values) => {
1168                for (i, value) in values.iter().enumerate() {
1169                    if i > 0 {
1170                        write!(f, ", ")?;
1171                    }
1172                    write!(f, "{value}")?;
1173                }
1174                Ok(())
1175            }
1176        }
1177    }
1178}
1179
1180/// The ways in which a certificate revocation list (CRL) can be invalid.
1181#[non_exhaustive]
1182#[derive(Debug, Clone)]
1183pub enum CertRevocationListError {
1184    /// The CRL had a bad signature from its issuer.
1185    BadSignature,
1186
1187    /// A signature inside a certificate or on a handshake was made with an unsupported algorithm.
1188    UnsupportedSignatureAlgorithm {
1189        /// The signature algorithm OID that was unsupported.
1190        signature_algorithm_id: Vec<u8>,
1191        /// Supported algorithms that were available for signature verification.
1192        supported_algorithms: Vec<AlgorithmIdentifier>,
1193    },
1194
1195    /// A signature was made with an algorithm that doesn't match the relevant public key.
1196    UnsupportedSignatureAlgorithmForPublicKey {
1197        /// The signature algorithm OID.
1198        signature_algorithm_id: Vec<u8>,
1199        /// The public key algorithm OID.
1200        public_key_algorithm_id: Vec<u8>,
1201    },
1202
1203    /// The CRL contained an invalid CRL number.
1204    InvalidCrlNumber,
1205
1206    /// The CRL contained a revoked certificate with an invalid serial number.
1207    InvalidRevokedCertSerialNumber,
1208
1209    /// The CRL issuer does not specify the cRLSign key usage.
1210    IssuerInvalidForCrl,
1211
1212    /// The CRL is invalid for some other reason.
1213    ///
1214    /// Enums holding this variant will never compare equal to each other.
1215    Other(OtherError),
1216
1217    /// The CRL is not correctly encoded.
1218    ParseError,
1219
1220    /// The CRL is not a v2 X.509 CRL.
1221    UnsupportedCrlVersion,
1222
1223    /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
1224    UnsupportedCriticalExtension,
1225
1226    /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
1227    UnsupportedDeltaCrl,
1228
1229    /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
1230    /// other than the issuer of the CRL.
1231    UnsupportedIndirectCrl,
1232
1233    /// The CRL contained a revoked certificate with an unsupported revocation reason.
1234    /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
1235    ///
1236    /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
1237    UnsupportedRevocationReason,
1238}
1239
1240impl PartialEq<Self> for CertRevocationListError {
1241    fn eq(&self, other: &Self) -> bool {
1242        use CertRevocationListError::*;
1243        match (self, other) {
1244            (BadSignature, BadSignature) => true,
1245            (
1246                UnsupportedSignatureAlgorithm {
1247                    signature_algorithm_id: left_signature_algorithm_id,
1248                    supported_algorithms: left_supported_algorithms,
1249                },
1250                UnsupportedSignatureAlgorithm {
1251                    signature_algorithm_id: right_signature_algorithm_id,
1252                    supported_algorithms: right_supported_algorithms,
1253                },
1254            ) => {
1255                (left_signature_algorithm_id, left_supported_algorithms)
1256                    == (right_signature_algorithm_id, right_supported_algorithms)
1257            }
1258            (
1259                UnsupportedSignatureAlgorithmForPublicKey {
1260                    signature_algorithm_id: left_signature_algorithm_id,
1261                    public_key_algorithm_id: left_public_key_algorithm_id,
1262                },
1263                UnsupportedSignatureAlgorithmForPublicKey {
1264                    signature_algorithm_id: right_signature_algorithm_id,
1265                    public_key_algorithm_id: right_public_key_algorithm_id,
1266                },
1267            ) => {
1268                (left_signature_algorithm_id, left_public_key_algorithm_id)
1269                    == (right_signature_algorithm_id, right_public_key_algorithm_id)
1270            }
1271            (InvalidCrlNumber, InvalidCrlNumber) => true,
1272            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
1273            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
1274            (ParseError, ParseError) => true,
1275            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
1276            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
1277            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
1278            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
1279            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
1280            _ => false,
1281        }
1282    }
1283}
1284
1285/// An error that occurred while handling Encrypted Client Hello (ECH).
1286#[non_exhaustive]
1287#[derive(Debug, Clone, Eq, PartialEq)]
1288pub enum EncryptedClientHelloError {
1289    /// The provided ECH configuration list was invalid.
1290    InvalidConfigList,
1291    /// No compatible ECH configuration.
1292    NoCompatibleConfig,
1293    /// The client configuration has server name indication (SNI) disabled.
1294    SniRequired,
1295}
1296
1297/// The server rejected the request to enable Encrypted Client Hello (ECH)
1298///
1299/// If [`RejectedEch::can_retry()`] is true, then you may use this with
1300/// [`crate::client::EchConfig::for_retry()`] to build a new `EchConfig` for a fresh client
1301/// connection that will use a compatible ECH configuration provided by the server for a retry.
1302#[non_exhaustive]
1303#[derive(Debug, Clone, PartialEq)]
1304pub struct RejectedEch {
1305    pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
1306}
1307
1308impl RejectedEch {
1309    /// Returns true if the server provided new ECH configurations to use for a fresh retry connection
1310    ///
1311    /// The `RejectedEch` error can be provided to [`crate::client::EchConfig::for_retry()`]
1312    /// to build a new `EchConfig` for a fresh client connection that will use a compatible ECH
1313    /// configuration provided by the server for a retry.
1314    pub fn can_retry(&self) -> bool {
1315        self.retry_configs.is_some()
1316    }
1317
1318    /// Returns an `EchConfigListBytes` with the server's provided retry configurations (if any)
1319    pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
1320        let Some(retry_configs) = &self.retry_configs else {
1321            return None;
1322        };
1323
1324        let mut tls_encoded_list = Vec::new();
1325        retry_configs.encode(&mut tls_encoded_list);
1326
1327        Some(EchConfigListBytes::from(tls_encoded_list))
1328    }
1329}
1330
1331fn join<T: fmt::Debug>(items: &[T]) -> String {
1332    items
1333        .iter()
1334        .map(|x| format!("{x:?}"))
1335        .collect::<Vec<String>>()
1336        .join(" or ")
1337}
1338
1339/// Describes cases of API misuse
1340///
1341/// Variants here should be sufficiently detailed that the action needed is clear.
1342#[non_exhaustive]
1343#[derive(Debug, Clone, PartialEq)]
1344pub enum ApiMisuse {
1345    /// The [`KeyingMaterialExporter`][] was already consumed.
1346    ///
1347    /// Methods that obtain an exporter (eg, [`ConnectionCommon::exporter()`][]) can only
1348    /// be used once.  This error is returned on subsequent calls.
1349    ///
1350    /// [`KeyingMaterialExporter`]: crate::KeyingMaterialExporter
1351    /// [`ConnectionCommon::exporter()`]: crate::ConnectionCommon::exporter()
1352    ExporterAlreadyUsed,
1353
1354    /// The `context` parameter to [`KeyingMaterialExporter::derive()`][] was too long.
1355    ///
1356    /// For TLS1.2 connections (only) this parameter is limited to 64KB.
1357    ///
1358    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1359    ExporterContextTooLong,
1360
1361    /// The `output` object for [`KeyingMaterialExporter::derive()`][] was too long.
1362    ///
1363    /// For TLS1.3 connections this is limited to 255 times the hash output length.
1364    ///
1365    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1366    ExporterOutputTooLong,
1367
1368    /// The `output` object to [`KeyingMaterialExporter::derive()`][] was zero length.
1369    ///
1370    /// This doesn't make sense, so we explicitly return an error (rather than simply
1371    /// producing no output as requested.)
1372    ///
1373    /// [`KeyingMaterialExporter::derive()`]: crate::KeyingMaterialExporter::derive()
1374    ExporterOutputZeroLength,
1375
1376    /// [`Acceptor::accept()`][] called after it yielded a connection.
1377    ///
1378    /// [`Acceptor::accept()`]: crate::server::Acceptor::accept()
1379    AcceptorPolledAfterCompletion,
1380
1381    /// Incorrect sample length provided to [`quic::HeaderProtectionKey::encrypt_in_place()`][]
1382    ///
1383    /// [`quic::HeaderProtectionKey::encrypt_in_place()`]: crate::quic::HeaderProtectionKey::encrypt_in_place()
1384    InvalidQuicHeaderProtectionSampleLength,
1385
1386    /// Incorrect relation between sample length and header number length provided to
1387    /// [`quic::HeaderProtectionKey::encrypt_in_place()`][]
1388    ///
1389    /// [`quic::HeaderProtectionKey::encrypt_in_place()`]: crate::quic::HeaderProtectionKey::encrypt_in_place()
1390    InvalidQuicHeaderProtectionPacketNumberLength,
1391
1392    /// Raw keys cannot be used with TLS 1.2.
1393    InvalidSignerForProtocolVersion,
1394
1395    /// QUIC attempted with a configuration that does not support TLS1.3.
1396    QuicRequiresTls13Support,
1397
1398    /// QUIC attempted with a configuration that does not support a ciphersuite that supports QUIC.
1399    NoQuicCompatibleCipherSuites,
1400
1401    /// An empty certificate chain was provided.
1402    EmptyCertificateChain,
1403
1404    /// QUIC attempted with unsupported [`ServerConfig::max_early_data_size`][]
1405    ///
1406    /// This field must be either zero or [`u32::MAX`] for QUIC.
1407    ///
1408    /// [`ServerConfig::max_early_data_size`]: crate::server::ServerConfig::max_early_data_size
1409    QuicRestrictsMaxEarlyDataSize,
1410
1411    /// A `CryptoProvider` must have at least one cipher suite.
1412    NoCipherSuitesConfigured,
1413
1414    /// A `CryptoProvider` must have at least one key exchange group.
1415    NoKeyExchangeGroupsConfigured,
1416
1417    /// An empty list of signature verification algorithms was provided.
1418    NoSignatureVerificationAlgorithms,
1419
1420    /// ECH attempted with a configuration that does not support TLS1.3.
1421    EchRequiresTls13Support,
1422
1423    /// ECH attempted with a configuration that also supports TLS1.2.
1424    EchForbidsTls12Support,
1425
1426    /// Secret extraction operation attempted without opting-in to secret extraction.
1427    ///
1428    /// This is possible from:
1429    ///
1430    /// - [`ClientConnection::dangerous_extract_secrets()`][crate::client::ClientConnection::dangerous_extract_secrets]
1431    /// - [`ServerConnection::dangerous_extract_secrets()`][crate::server::ServerConnection::dangerous_extract_secrets]
1432    /// - [`ClientConnection::dangerous_into_kernel_connection()`][crate::client::UnbufferedClientConnection::dangerous_into_kernel_connection]
1433    /// - [`ServerConnection::dangerous_into_kernel_connection()`][crate::server::UnbufferedServerConnection::dangerous_into_kernel_connection]
1434    ///
1435    /// You must set [`ServerConfig::enable_secret_extraction`][crate::server::ServerConfig::enable_secret_extraction] or
1436    /// [`ClientConfig::enable_secret_extraction`][crate::client::ClientConfig::enable_secret_extraction] to true before calling
1437    /// these functions.
1438    SecretExtractionRequiresPriorOptIn,
1439
1440    /// Secret extraction operation attempted without first extracting all pending
1441    /// TLS data.
1442    ///
1443    /// See [`Self::SecretExtractionRequiresPriorOptIn`] for a list of the affected
1444    /// functions.  You must ensure any prior generated TLS records are extracted
1445    /// from the library before using one of these functions.
1446    SecretExtractionWithPendingSendableData,
1447
1448    /// Attempt to verify a certificate with an unsupported type.
1449    ///
1450    /// A verifier indicated support for a certificate type but then failed to verify the peer's
1451    /// identity of that type.
1452    UnverifiableCertificateType,
1453
1454    /// A verifier or resolver implementation signalled that it does not support any certificate types.
1455    NoSupportedCertificateTypes,
1456
1457    /// [`Nonce::to_array()`][] called with incorrect array size.
1458    ///
1459    /// The nonce length does not match the requested array size `N`.
1460    ///
1461    /// [`Nonce::to_array()`]: crate::crypto::cipher::Nonce::to_array()
1462    NonceArraySizeMismatch {
1463        /// The expected array size (type parameter N)
1464        expected: usize,
1465        /// The actual nonce length
1466        actual: usize,
1467    },
1468
1469    /// [`Iv::new()`][] called with a value that exceeds the maximum IV length.
1470    ///
1471    /// The IV length must not exceed [`Iv::MAX_LEN`][].
1472    ///
1473    /// [`Iv::new()`]: crate::crypto::cipher::Iv::new()
1474    /// [`Iv::MAX_LEN`]: crate::crypto::cipher::Iv::MAX_LEN
1475    IvLengthExceedsMaximum {
1476        /// The actual IV length provided
1477        actual: usize,
1478        /// The maximum allowed IV length
1479        maximum: usize,
1480    },
1481}
1482
1483impl fmt::Display for ApiMisuse {
1484    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1485        write!(f, "{self:?}")
1486    }
1487}
1488
1489impl core::error::Error for ApiMisuse {}
1490
1491mod other_error {
1492    use core::error::Error as StdError;
1493    use core::fmt;
1494
1495    use crate::sync::Arc;
1496
1497    /// Any other error that cannot be expressed by a more specific [`Error`][super::Error]
1498    /// variant.
1499    ///
1500    /// For example, an `OtherError` could be produced by a custom crypto provider
1501    /// exposing a provider specific error.
1502    ///
1503    /// Enums holding this type will never compare equal to each other.
1504    #[derive(Debug, Clone)]
1505    pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1506
1507    impl OtherError {
1508        /// Create a new `OtherError` from any error type.
1509        pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1510            Self(Arc::new(err))
1511        }
1512    }
1513
1514    impl PartialEq<Self> for OtherError {
1515        fn eq(&self, _other: &Self) -> bool {
1516            false
1517        }
1518    }
1519
1520    impl fmt::Display for OtherError {
1521        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1522            #[cfg(feature = "std")]
1523            {
1524                write!(f, "{}", self.0)
1525            }
1526            #[cfg(not(feature = "std"))]
1527            {
1528                f.write_str("no further information available")
1529            }
1530        }
1531    }
1532
1533    impl StdError for OtherError {
1534        fn source(&self) -> Option<&(dyn StdError + 'static)> {
1535            Some(self.0.as_ref())
1536        }
1537    }
1538}
1539
1540pub use other_error::OtherError;