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