1use alloc::format;
4use alloc::string::String;
5use alloc::vec::Vec;
6use core::ops::Deref;
7use core::{fmt, mem};
8use std::time::SystemTimeError;
9
10use pki_types::{AlgorithmIdentifier, EchConfigListBytes, ServerName, UnixTime};
11#[cfg(feature = "webpki")]
12use webpki::ExtendedKeyUsage;
13
14use crate::common_state::{SendPath, maybe_send_fatal_alert};
15use crate::crypto::kx::KeyExchangeAlgorithm;
16use crate::crypto::{CipherSuite, GetRandomFailed, InconsistentKeys};
17use crate::enums::{ContentType, HandshakeType};
18use crate::msgs::{Codec, EchConfigPayload};
19
20#[cfg(test)]
21mod tests;
22
23#[non_exhaustive]
25#[derive(Debug, PartialEq, Clone)]
26pub enum Error {
27 InappropriateMessage {
33 expect_types: Vec<ContentType>,
35 got_type: ContentType,
37 },
38
39 InappropriateHandshakeMessage {
43 expect_types: Vec<HandshakeType>,
45 got_type: HandshakeType,
47 },
48
49 InvalidEncryptedClientHello(EncryptedClientHelloError),
51
52 InvalidMessage(InvalidMessage),
54
55 UnsupportedNameType,
57
58 DecryptError,
60
61 EncryptError,
64
65 PeerIncompatible(PeerIncompatible),
68
69 PeerMisbehaved(PeerMisbehaved),
72
73 AlertReceived(AlertDescription),
75
76 InvalidCertificate(CertificateError),
81
82 InvalidCertRevocationList(CertRevocationListError),
84
85 General(String),
87
88 FailedToGetCurrentTime,
90
91 FailedToGetRandomBytes,
93
94 HandshakeNotComplete,
97
98 PeerSentOversizedRecord,
100
101 NoApplicationProtocol,
103
104 NoSuitableCertificate,
106
107 BadMaxFragmentSize,
110
111 InconsistentKeys(InconsistentKeys),
121
122 RejectedEch(RejectedEch),
129
130 Unreachable(&'static str),
134
135 ApiMisuse(ApiMisuse),
147
148 Other(OtherError),
156}
157
158impl TryFrom<&Error> for AlertDescription {
162 type Error = ();
163
164 fn try_from(error: &Error) -> Result<Self, Self::Error> {
165 Ok(match error {
166 Error::DecryptError => Self::BadRecordMac,
167 Error::InappropriateMessage { .. } | Error::InappropriateHandshakeMessage { .. } => {
168 Self::UnexpectedMessage
169 }
170 Error::InvalidCertificate(e) => Self::from(e),
171 Error::InvalidMessage(e) => Self::from(*e),
172 Error::NoApplicationProtocol => Self::NoApplicationProtocol,
173 Error::PeerMisbehaved(e) => Self::from(*e),
174 Error::PeerIncompatible(e) => Self::from(*e),
175 Error::PeerSentOversizedRecord => Self::RecordOverflow,
176 Error::RejectedEch(_) => Self::EncryptedClientHelloRequired,
177
178 _ => return Err(()),
179 })
180 }
181}
182
183impl fmt::Display for Error {
184 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
185 match self {
186 Self::InappropriateMessage {
187 expect_types,
188 got_type,
189 } => write!(
190 f,
191 "received unexpected message: got {:?} when expecting {}",
192 got_type,
193 join::<ContentType>(expect_types)
194 ),
195 Self::InappropriateHandshakeMessage {
196 expect_types,
197 got_type,
198 } => write!(
199 f,
200 "received unexpected handshake message: got {:?} when expecting {}",
201 got_type,
202 join::<HandshakeType>(expect_types)
203 ),
204 Self::InvalidMessage(typ) => {
205 write!(f, "received corrupt message of type {typ:?}")
206 }
207 Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
208 Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
209 Self::AlertReceived(alert) => write!(f, "received fatal alert: the peer {alert}"),
210 Self::InvalidCertificate(err) => {
211 write!(f, "invalid peer certificate: {err}")
212 }
213 Self::InvalidCertRevocationList(err) => {
214 write!(f, "invalid certificate revocation list: {err:?}")
215 }
216 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
217 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
218 Self::InvalidEncryptedClientHello(err) => {
219 write!(f, "encrypted client hello failure: {err:?}")
220 }
221 Self::EncryptError => write!(f, "cannot encrypt message"),
222 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
223 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
224 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
225 Self::NoSuitableCertificate => write!(f, "no suitable certificate found"),
226 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
227 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
228 Self::BadMaxFragmentSize => {
229 write!(f, "the supplied max_fragment_size was too small or large")
230 }
231 Self::InconsistentKeys(why) => {
232 write!(f, "keys may not be consistent: {why:?}")
233 }
234 Self::RejectedEch(why) => {
235 write!(
236 f,
237 "server rejected encrypted client hello (ECH) {} retry configs",
238 if why.can_retry() { "with" } else { "without" }
239 )
240 }
241 Self::General(err) => write!(f, "unexpected error: {err}"),
242 Self::Unreachable(err) => write!(
243 f,
244 "unreachable condition: {err} (please file a bug in rustls)"
245 ),
246 Self::ApiMisuse(why) => write!(f, "API misuse: {why:?}"),
247 Self::Other(err) => write!(f, "other error: {err}"),
248 }
249 }
250}
251
252impl From<CertificateError> for Error {
253 #[inline]
254 fn from(e: CertificateError) -> Self {
255 Self::InvalidCertificate(e)
256 }
257}
258
259impl From<InvalidMessage> for Error {
260 #[inline]
261 fn from(e: InvalidMessage) -> Self {
262 Self::InvalidMessage(e)
263 }
264}
265
266impl From<PeerMisbehaved> for Error {
267 #[inline]
268 fn from(e: PeerMisbehaved) -> Self {
269 Self::PeerMisbehaved(e)
270 }
271}
272
273impl From<PeerIncompatible> for Error {
274 #[inline]
275 fn from(e: PeerIncompatible) -> Self {
276 Self::PeerIncompatible(e)
277 }
278}
279
280impl From<CertRevocationListError> for Error {
281 #[inline]
282 fn from(e: CertRevocationListError) -> Self {
283 Self::InvalidCertRevocationList(e)
284 }
285}
286
287impl From<EncryptedClientHelloError> for Error {
288 #[inline]
289 fn from(e: EncryptedClientHelloError) -> Self {
290 Self::InvalidEncryptedClientHello(e)
291 }
292}
293
294impl From<RejectedEch> for Error {
295 fn from(rejected_error: RejectedEch) -> Self {
296 Self::RejectedEch(rejected_error)
297 }
298}
299
300impl From<ApiMisuse> for Error {
301 fn from(e: ApiMisuse) -> Self {
302 Self::ApiMisuse(e)
303 }
304}
305
306impl From<OtherError> for Error {
307 fn from(value: OtherError) -> Self {
308 Self::Other(value)
309 }
310}
311
312impl From<InconsistentKeys> for Error {
313 #[inline]
314 fn from(e: InconsistentKeys) -> Self {
315 Self::InconsistentKeys(e)
316 }
317}
318
319impl From<SystemTimeError> for Error {
320 #[inline]
321 fn from(_: SystemTimeError) -> Self {
322 Self::FailedToGetCurrentTime
323 }
324}
325
326impl From<GetRandomFailed> for Error {
327 fn from(_: GetRandomFailed) -> Self {
328 Self::FailedToGetRandomBytes
329 }
330}
331
332impl core::error::Error for Error {}
333
334#[non_exhaustive]
342#[derive(Debug, Clone)]
343pub enum CertificateError {
344 BadEncoding,
346
347 Expired,
349
350 ExpiredContext {
355 time: UnixTime,
357 not_after: UnixTime,
359 },
360
361 NotValidYet,
363
364 NotValidYetContext {
369 time: UnixTime,
371 not_before: UnixTime,
373 },
374
375 Revoked,
377
378 UnhandledCriticalExtension,
381
382 UnknownIssuer,
384
385 UnknownRevocationStatus,
387
388 ExpiredRevocationList,
390
391 ExpiredRevocationListContext {
396 time: UnixTime,
398 next_update: UnixTime,
400 },
401
402 BadSignature,
405
406 UnsupportedSignatureAlgorithm {
408 signature_algorithm_id: Vec<u8>,
410 supported_algorithms: Vec<AlgorithmIdentifier>,
412 },
413
414 UnsupportedSignatureAlgorithmForPublicKey {
416 signature_algorithm_id: Vec<u8>,
418 public_key_algorithm_id: Vec<u8>,
420 },
421
422 NotValidForName,
425
426 NotValidForNameContext {
432 expected: ServerName<'static>,
434
435 presented: Vec<String>,
440 },
441
442 InvalidPurpose,
444
445 InvalidPurposeContext {
450 required: ExtendedKeyPurpose,
452 presented: Vec<ExtendedKeyPurpose>,
454 },
455
456 InvalidOcspResponse,
465
466 ApplicationVerificationFailure,
469
470 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
581impl 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 Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
596 Self::CertificateExpired
597 }
598 Revoked => Self::CertificateRevoked,
599 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 Other(..) => Self::CertificateUnknown,
616 }
617 }
618}
619
620impl fmt::Display for CertificateError {
621 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
622 match self {
623 Self::NotValidForNameContext {
624 expected,
625 presented,
626 } => {
627 write!(
628 f,
629 "certificate not valid for name {:?}; certificate ",
630 expected.to_str()
631 )?;
632
633 match presented.as_slice() {
634 &[] => write!(
635 f,
636 "is not valid for any names (according to its subjectAltName extension)"
637 ),
638 [one] => write!(f, "is only valid for {one}"),
639 many => {
640 write!(f, "is only valid for ")?;
641
642 let n = many.len();
643 let all_but_last = &many[..n - 1];
644 let last = &many[n - 1];
645
646 for (i, name) in all_but_last.iter().enumerate() {
647 write!(f, "{name}")?;
648 if i < n - 2 {
649 write!(f, ", ")?;
650 }
651 }
652 write!(f, " or {last}")
653 }
654 }
655 }
656
657 Self::ExpiredContext { time, not_after } => write!(
658 f,
659 "certificate expired: verification time {} (UNIX), \
660 but certificate is not valid after {} \
661 ({} seconds ago)",
662 time.as_secs(),
663 not_after.as_secs(),
664 time.as_secs()
665 .saturating_sub(not_after.as_secs())
666 ),
667
668 Self::NotValidYetContext { time, not_before } => write!(
669 f,
670 "certificate not valid yet: verification time {} (UNIX), \
671 but certificate is not valid before {} \
672 ({} seconds in future)",
673 time.as_secs(),
674 not_before.as_secs(),
675 not_before
676 .as_secs()
677 .saturating_sub(time.as_secs())
678 ),
679
680 Self::ExpiredRevocationListContext { time, next_update } => write!(
681 f,
682 "certificate revocation list expired: \
683 verification time {} (UNIX), \
684 but CRL is not valid after {} \
685 ({} seconds ago)",
686 time.as_secs(),
687 next_update.as_secs(),
688 time.as_secs()
689 .saturating_sub(next_update.as_secs())
690 ),
691
692 Self::InvalidPurposeContext {
693 required,
694 presented,
695 } => {
696 write!(
697 f,
698 "certificate does not allow extended key usage for {required}, allows "
699 )?;
700 for (i, eku) in presented.iter().enumerate() {
701 if i > 0 {
702 write!(f, ", ")?;
703 }
704 write!(f, "{eku}")?;
705 }
706 Ok(())
707 }
708
709 Self::Other(other) => write!(f, "{other}"),
710
711 other => write!(f, "{other:?}"),
712 }
713 }
714}
715
716enum_builder! {
717 #[repr(u8)]
721 pub enum AlertDescription {
722 CloseNotify => 0x00,
723 UnexpectedMessage => 0x0a,
724 BadRecordMac => 0x14,
725 DecryptionFailed => 0x15,
726 RecordOverflow => 0x16,
727 DecompressionFailure => 0x1e,
728 HandshakeFailure => 0x28,
729 NoCertificate => 0x29,
730 BadCertificate => 0x2a,
731 UnsupportedCertificate => 0x2b,
732 CertificateRevoked => 0x2c,
733 CertificateExpired => 0x2d,
734 CertificateUnknown => 0x2e,
735 IllegalParameter => 0x2f,
736 UnknownCa => 0x30,
737 AccessDenied => 0x31,
738 DecodeError => 0x32,
739 DecryptError => 0x33,
740 ExportRestriction => 0x3c,
741 ProtocolVersion => 0x46,
742 InsufficientSecurity => 0x47,
743 InternalError => 0x50,
744 InappropriateFallback => 0x56,
745 UserCanceled => 0x5a,
746 NoRenegotiation => 0x64,
747 MissingExtension => 0x6d,
748 UnsupportedExtension => 0x6e,
749 CertificateUnobtainable => 0x6f,
750 UnrecognizedName => 0x70,
751 BadCertificateStatusResponse => 0x71,
752 BadCertificateHashValue => 0x72,
753 UnknownPskIdentity => 0x73,
754 CertificateRequired => 0x74,
755 NoApplicationProtocol => 0x78,
756 EncryptedClientHelloRequired => 0x79, }
758}
759
760impl fmt::Display for AlertDescription {
761 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
762 match self {
767 Self::CloseNotify => write!(f, "cleanly closed the connection"),
769
770 Self::UnexpectedMessage => write!(f, "received an unexpected message"),
773 Self::BadRecordMac => write!(f, "failed to verify a message"),
774 Self::RecordOverflow => write!(f, "rejected an over-length message"),
775 Self::IllegalParameter => write!(
776 f,
777 "rejected a message because a field was incorrect or inconsistent"
778 ),
779 Self::DecodeError => write!(f, "failed to decode a message"),
780 Self::DecryptError => {
781 write!(f, "failed to perform a handshake cryptographic operation")
782 }
783 Self::InappropriateFallback => {
784 write!(f, "detected an attempted version downgrade")
785 }
786 Self::MissingExtension => {
787 write!(f, "required a specific extension that was not provided")
788 }
789 Self::UnsupportedExtension => write!(f, "rejected an unsolicited extension"),
790
791 Self::DecryptionFailed => write!(f, "failed to decrypt a message"),
794 Self::DecompressionFailure => write!(f, "failed to decompress a message"),
795 Self::NoCertificate => write!(f, "found no certificate"),
796 Self::ExportRestriction => write!(f, "refused due to export restrictions"),
797 Self::NoRenegotiation => write!(f, "rejected an attempt at renegotiation"),
798 Self::CertificateUnobtainable => {
799 write!(f, "failed to retrieve its certificate")
800 }
801 Self::BadCertificateHashValue => {
802 write!(f, "rejected the `certificate_hash` extension")
803 }
804
805 Self::HandshakeFailure => write!(
809 f,
810 "failed to negotiate an acceptable set of security parameters"
811 ),
812 Self::ProtocolVersion => write!(f, "did not support a suitable TLS version"),
813 Self::InsufficientSecurity => {
814 write!(f, "required a higher security level than was offered")
815 }
816
817 Self::BadCertificate => {
820 write!(
821 f,
822 "rejected the certificate as corrupt or incorrectly signed"
823 )
824 }
825 Self::UnsupportedCertificate => {
826 write!(f, "did not support the certificate")
827 }
828 Self::CertificateRevoked => write!(f, "found the certificate to be revoked"),
829 Self::CertificateExpired => write!(f, "found the certificate to be expired"),
830 Self::CertificateUnknown => {
831 write!(f, "rejected the certificate for an unspecified reason")
832 }
833 Self::UnknownCa => write!(f, "found the certificate was not issued by a trusted CA"),
834 Self::BadCertificateStatusResponse => {
835 write!(f, "rejected the certificate status response")
836 }
837 Self::AccessDenied => write!(f, "denied access"),
839 Self::CertificateRequired => write!(f, "required a client certificate"),
841
842 Self::InternalError => write!(f, "encountered an internal error"),
843 Self::UserCanceled => write!(f, "canceled the handshake"),
844
845 Self::UnrecognizedName => {
847 write!(f, "did not recognize a name in the `server_name` extension")
848 }
849
850 Self::UnknownPskIdentity => {
853 write!(f, "did not recognize any offered PSK identity")
854 }
855
856 Self::NoApplicationProtocol => write!(
859 f,
860 "did not support any of the offered application protocols"
861 ),
862
863 Self::EncryptedClientHelloRequired => {
866 write!(f, "required use of encrypted client hello")
867 }
868
869 Self::Unknown(n) => write!(f, "sent an unknown alert (0x{n:02x?})"),
870 }
871 }
872}
873
874#[non_exhaustive]
876#[derive(Debug, Clone, Copy, PartialEq)]
877pub enum InvalidMessage {
878 CertificatePayloadTooLarge,
880 HandshakePayloadTooLarge,
882 InvalidCcs,
884 InvalidContentType,
886 InvalidCertificateStatusType,
888 InvalidCertRequest,
890 InvalidDhParams,
892 InvalidEmptyPayload,
894 InvalidKeyUpdate,
896 InvalidServerName,
898 MessageTooLarge,
900 MessageTooShort,
902 MissingData(&'static str),
904 MissingKeyExchange,
906 NoSignatureSchemes,
908 TrailingData(&'static str),
910 UnexpectedMessage(&'static str),
912 UnknownProtocolVersion,
914 UnsupportedCompression,
916 UnsupportedCurveType,
918 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
920 EmptyTicketValue,
922 IllegalEmptyList(&'static str),
926 DuplicateExtension(u16),
928 PreSharedKeyIsNotFinalExtension,
930 UnknownHelloRetryRequestExtension,
932 UnknownCertificateExtension,
934}
935
936impl From<InvalidMessage> for AlertDescription {
937 fn from(e: InvalidMessage) -> Self {
938 match e {
939 InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
940 InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
941 InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
942 InvalidMessage::CertificatePayloadTooLarge => Self::BadCertificate,
943 _ => Self::DecodeError,
944 }
945 }
946}
947
948#[expect(missing_docs)]
959#[non_exhaustive]
960#[derive(Clone, Copy, Debug, PartialEq)]
961pub enum PeerMisbehaved {
962 AttemptedDowngradeToTls12WhenTls13IsSupported,
963 BadCertChainExtensions,
964 DisallowedEncryptedExtension,
965 DuplicateClientHelloExtensions,
966 DuplicateEncryptedExtensions,
967 DuplicateHelloRetryRequestExtensions,
968 DuplicateNewSessionTicketExtensions,
969 DuplicateServerHelloExtensions,
970 DuplicateServerNameTypes,
971 EarlyDataAttemptedInSecondClientHello,
972 EarlyDataExtensionWithoutResumption,
973 EarlyDataOfferedWithVariedCipherSuite,
974 HandshakeHashVariedAfterRetry,
975 IllegalAlertLevel(u8, AlertDescription),
977 IllegalHelloRetryRequestWithEmptyCookie,
978 IllegalHelloRetryRequestWithNoChanges,
979 IllegalHelloRetryRequestWithOfferedGroup,
980 IllegalHelloRetryRequestWithUnofferedCipherSuite,
981 IllegalHelloRetryRequestWithUnofferedNamedGroup,
982 IllegalHelloRetryRequestWithUnsupportedVersion,
983 IllegalHelloRetryRequestWithWrongSessionId,
984 IllegalHelloRetryRequestWithInvalidEch,
985 IllegalMiddleboxChangeCipherSpec,
986 IllegalTlsInnerPlaintext,
987 IllegalWarningAlert(AlertDescription),
989 IncorrectBinder,
990 IncorrectFinished,
991 InvalidCertCompression,
992 InvalidMaxEarlyDataSize,
993 InvalidKeyShare,
994 KeyEpochWithPendingFragment,
995 KeyUpdateReceivedInQuicConnection,
996 MessageInterleavedWithHandshakeMessage,
997 MissingBinderInPskExtension,
998 MissingKeyShare,
999 MissingPskModesExtension,
1000 MissingQuicTransportParameters,
1001 NoCertificatesPresented,
1002 OfferedDuplicateCertificateCompressions,
1003 OfferedDuplicateKeyShares,
1004 OfferedEarlyDataWithOldProtocolVersion,
1005 OfferedEmptyApplicationProtocol,
1006 OfferedIncorrectCompressions,
1007 PskExtensionMustBeLast,
1008 PskExtensionWithMismatchedIdsAndBinders,
1009 RefusedToFollowHelloRetryRequest,
1010 RejectedEarlyDataInterleavedWithHandshakeMessage,
1011 ResumptionAttemptedWithVariedEms,
1012 ResumptionOfferedWithVariedCipherSuite,
1013 ResumptionOfferedWithVariedEms,
1014 ResumptionOfferedWithIncompatibleCipherSuite,
1015 SelectedDifferentCipherSuiteAfterRetry,
1016 SelectedInvalidPsk,
1017 SelectedTls12UsingTls13VersionExtension,
1018 SelectedUnofferedApplicationProtocol,
1019 SelectedUnofferedCertCompression,
1020 SelectedUnofferedCipherSuite,
1021 SelectedUnofferedCompression,
1022 SelectedUnofferedKxGroup,
1023 SelectedUnofferedPsk,
1024 ServerEchoedCompatibilitySessionId,
1025 ServerHelloMustOfferUncompressedEcPoints,
1026 ServerNameDifferedOnRetry,
1027 ServerNameMustContainOneHostName,
1028 SignedKxWithWrongAlgorithm,
1029 SignedHandshakeWithUnadvertisedSigScheme,
1030 TooManyEmptyFragments,
1031 TooManyKeyUpdateRequests,
1032 TooManyRenegotiationRequests,
1033 TooManyWarningAlertsReceived,
1034 TooMuchEarlyDataReceived,
1035 UnexpectedCleartextExtension,
1036 UnsolicitedCertExtension,
1037 UnsolicitedEncryptedExtension,
1038 UnsolicitedSctList,
1039 UnsolicitedServerHelloExtension,
1040 WrongGroupForKeyShare,
1041 UnsolicitedEchExtension,
1042}
1043
1044impl From<PeerMisbehaved> for AlertDescription {
1045 fn from(e: PeerMisbehaved) -> Self {
1046 match e {
1047 PeerMisbehaved::DisallowedEncryptedExtension
1048 | PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch
1049 | PeerMisbehaved::UnexpectedCleartextExtension
1050 | PeerMisbehaved::UnsolicitedEchExtension
1051 | PeerMisbehaved::UnsolicitedEncryptedExtension
1052 | PeerMisbehaved::UnsolicitedServerHelloExtension => Self::UnsupportedExtension,
1053
1054 PeerMisbehaved::IllegalMiddleboxChangeCipherSpec
1055 | PeerMisbehaved::KeyEpochWithPendingFragment
1056 | PeerMisbehaved::KeyUpdateReceivedInQuicConnection => Self::UnexpectedMessage,
1057
1058 PeerMisbehaved::IllegalWarningAlert(_) => Self::DecodeError,
1059
1060 PeerMisbehaved::IncorrectBinder | PeerMisbehaved::IncorrectFinished => {
1061 Self::DecryptError
1062 }
1063
1064 PeerMisbehaved::InvalidCertCompression
1065 | PeerMisbehaved::SelectedUnofferedCertCompression => Self::BadCertificate,
1066
1067 PeerMisbehaved::MissingKeyShare
1068 | PeerMisbehaved::MissingPskModesExtension
1069 | PeerMisbehaved::MissingQuicTransportParameters => Self::MissingExtension,
1070
1071 PeerMisbehaved::NoCertificatesPresented => Self::CertificateRequired,
1072
1073 _ => Self::IllegalParameter,
1074 }
1075 }
1076}
1077
1078#[expect(missing_docs)]
1084#[non_exhaustive]
1085#[derive(Clone, Copy, Debug, PartialEq)]
1086pub enum PeerIncompatible {
1087 EcPointsExtensionRequired,
1088 ExtendedMasterSecretExtensionRequired,
1089 IncorrectCertificateTypeExtension,
1090 KeyShareExtensionRequired,
1091 MultipleRawKeys,
1092 NamedGroupsExtensionRequired,
1093 NoCertificateRequestSignatureSchemesInCommon,
1094 NoCipherSuitesInCommon,
1095 NoEcPointFormatsInCommon,
1096 NoKxGroupsInCommon,
1097 NoSignatureSchemesInCommon,
1098 NoServerNameProvided,
1099 NullCompressionRequired,
1100 ServerDoesNotSupportTls12Or13,
1101 ServerSentHelloRetryRequestWithUnknownExtension,
1102 ServerTlsVersionIsDisabledByOurConfig,
1103 SignatureAlgorithmsExtensionRequired,
1104 SupportedVersionsExtensionRequired,
1105 Tls12NotOffered,
1106 Tls12NotOfferedOrEnabled,
1107 Tls13RequiredForQuic,
1108 UncompressedEcPointsRequired,
1109 UnknownCertificateType(u8),
1110 UnsolicitedCertificateTypeExtension,
1111}
1112
1113impl From<PeerIncompatible> for AlertDescription {
1114 fn from(e: PeerIncompatible) -> Self {
1115 match e {
1116 PeerIncompatible::NullCompressionRequired => Self::IllegalParameter,
1117
1118 PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig
1119 | PeerIncompatible::SupportedVersionsExtensionRequired
1120 | PeerIncompatible::Tls12NotOffered
1121 | PeerIncompatible::Tls12NotOfferedOrEnabled
1122 | PeerIncompatible::Tls13RequiredForQuic => Self::ProtocolVersion,
1123
1124 PeerIncompatible::UnknownCertificateType(_) => Self::UnsupportedCertificate,
1125
1126 _ => Self::HandshakeFailure,
1127 }
1128 }
1129}
1130
1131#[non_exhaustive]
1136#[derive(Clone, Debug, Eq, PartialEq)]
1137pub enum ExtendedKeyPurpose {
1138 ClientAuth,
1140 ServerAuth,
1142 Other(Vec<usize>),
1146}
1147
1148impl ExtendedKeyPurpose {
1149 #[cfg(feature = "webpki")]
1150 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
1151 let values = values.collect::<Vec<_>>();
1152 match &*values {
1153 ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
1154 ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
1155 _ => Self::Other(values),
1156 }
1157 }
1158}
1159
1160impl fmt::Display for ExtendedKeyPurpose {
1161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1162 match self {
1163 Self::ClientAuth => write!(f, "client authentication"),
1164 Self::ServerAuth => write!(f, "server authentication"),
1165 Self::Other(values) => {
1166 for (i, value) in values.iter().enumerate() {
1167 if i > 0 {
1168 write!(f, ", ")?;
1169 }
1170 write!(f, "{value}")?;
1171 }
1172 Ok(())
1173 }
1174 }
1175 }
1176}
1177
1178#[non_exhaustive]
1180#[derive(Debug, Clone)]
1181pub enum CertRevocationListError {
1182 BadSignature,
1184
1185 UnsupportedSignatureAlgorithm {
1187 signature_algorithm_id: Vec<u8>,
1189 supported_algorithms: Vec<AlgorithmIdentifier>,
1191 },
1192
1193 UnsupportedSignatureAlgorithmForPublicKey {
1195 signature_algorithm_id: Vec<u8>,
1197 public_key_algorithm_id: Vec<u8>,
1199 },
1200
1201 InvalidCrlNumber,
1203
1204 InvalidRevokedCertSerialNumber,
1206
1207 IssuerInvalidForCrl,
1209
1210 Other(OtherError),
1214
1215 ParseError,
1217
1218 UnsupportedCrlVersion,
1220
1221 UnsupportedCriticalExtension,
1223
1224 UnsupportedDeltaCrl,
1226
1227 UnsupportedIndirectCrl,
1230
1231 UnsupportedRevocationReason,
1236}
1237
1238impl PartialEq<Self> for CertRevocationListError {
1239 fn eq(&self, other: &Self) -> bool {
1240 use CertRevocationListError::*;
1241 match (self, other) {
1242 (BadSignature, BadSignature) => true,
1243 (
1244 UnsupportedSignatureAlgorithm {
1245 signature_algorithm_id: left_signature_algorithm_id,
1246 supported_algorithms: left_supported_algorithms,
1247 },
1248 UnsupportedSignatureAlgorithm {
1249 signature_algorithm_id: right_signature_algorithm_id,
1250 supported_algorithms: right_supported_algorithms,
1251 },
1252 ) => {
1253 (left_signature_algorithm_id, left_supported_algorithms)
1254 == (right_signature_algorithm_id, right_supported_algorithms)
1255 }
1256 (
1257 UnsupportedSignatureAlgorithmForPublicKey {
1258 signature_algorithm_id: left_signature_algorithm_id,
1259 public_key_algorithm_id: left_public_key_algorithm_id,
1260 },
1261 UnsupportedSignatureAlgorithmForPublicKey {
1262 signature_algorithm_id: right_signature_algorithm_id,
1263 public_key_algorithm_id: right_public_key_algorithm_id,
1264 },
1265 ) => {
1266 (left_signature_algorithm_id, left_public_key_algorithm_id)
1267 == (right_signature_algorithm_id, right_public_key_algorithm_id)
1268 }
1269 (InvalidCrlNumber, InvalidCrlNumber) => true,
1270 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
1271 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
1272 (ParseError, ParseError) => true,
1273 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
1274 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
1275 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
1276 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
1277 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
1278 _ => false,
1279 }
1280 }
1281}
1282
1283#[non_exhaustive]
1285#[derive(Debug, Clone, Eq, PartialEq)]
1286pub enum EncryptedClientHelloError {
1287 InvalidConfigList,
1289 NoCompatibleConfig,
1291 SniRequired,
1293}
1294
1295#[non_exhaustive]
1301#[derive(Debug, Clone, PartialEq)]
1302pub struct RejectedEch {
1303 pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
1304}
1305
1306impl RejectedEch {
1307 pub fn can_retry(&self) -> bool {
1313 self.retry_configs.is_some()
1314 }
1315
1316 pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
1318 let Some(retry_configs) = &self.retry_configs else {
1319 return None;
1320 };
1321
1322 let mut tls_encoded_list = Vec::new();
1323 retry_configs.encode(&mut tls_encoded_list);
1324
1325 Some(EchConfigListBytes::from(tls_encoded_list))
1326 }
1327}
1328
1329fn join<T: fmt::Debug>(items: &[T]) -> String {
1330 items
1331 .iter()
1332 .map(|x| format!("{x:?}"))
1333 .collect::<Vec<String>>()
1334 .join(" or ")
1335}
1336
1337#[non_exhaustive]
1341#[derive(Debug, Clone, PartialEq)]
1342pub enum ApiMisuse {
1343 ResumingFromUnknownCipherSuite(CipherSuite),
1345
1346 ExporterAlreadyUsed,
1354
1355 ExporterContextTooLong,
1361
1362 ExporterOutputTooLong,
1368
1369 ExporterOutputZeroLength,
1376
1377 AcceptorPolledAfterCompletion,
1381
1382 InvalidQuicHeaderProtectionSampleLength,
1386
1387 InvalidQuicHeaderProtectionPacketNumberLength,
1392
1393 InvalidSignerForProtocolVersion,
1395
1396 QuicRequiresTls13Support,
1398
1399 NoQuicCompatibleCipherSuites,
1401
1402 EmptyCertificateChain,
1404
1405 QuicRestrictsMaxEarlyDataSize,
1411
1412 NoCipherSuitesConfigured,
1414
1415 NoKeyExchangeGroupsConfigured,
1417
1418 NoSignatureVerificationAlgorithms,
1420
1421 EchRequiresTls13Support,
1423
1424 EchForbidsTls12Support,
1426
1427 SecretExtractionRequiresPriorOptIn,
1438
1439 SecretExtractionWithPendingSendableData,
1446
1447 UnverifiableCertificateType,
1452
1453 NoSupportedCertificateTypes,
1455
1456 NonceArraySizeMismatch {
1462 expected: usize,
1464 actual: usize,
1466 },
1467
1468 IvLengthExceedsMaximum {
1475 actual: usize,
1477 maximum: usize,
1479 },
1480
1481 ResumptionDataProvidedTooLate,
1486
1487 KeyUpdateNotAvailableForTls12,
1491}
1492
1493impl fmt::Display for ApiMisuse {
1494 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1495 write!(f, "{self:?}")
1496 }
1497}
1498
1499impl core::error::Error for ApiMisuse {}
1500
1501mod other_error {
1502 use core::error::Error as StdError;
1503 use core::fmt;
1504
1505 use crate::sync::Arc;
1506
1507 #[derive(Debug, Clone)]
1515 pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1516
1517 impl OtherError {
1518 pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1520 Self(Arc::new(err))
1521 }
1522 }
1523
1524 impl PartialEq<Self> for OtherError {
1525 fn eq(&self, _other: &Self) -> bool {
1526 false
1527 }
1528 }
1529
1530 impl fmt::Display for OtherError {
1531 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1532 write!(f, "{}", self.0)
1533 }
1534 }
1535
1536 impl StdError for OtherError {
1537 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1538 Some(self.0.as_ref())
1539 }
1540 }
1541}
1542
1543pub use other_error::OtherError;
1544
1545pub struct ErrorWithAlert {
1548 pub error: Error,
1550 pub(crate) data: Vec<u8>,
1551}
1552
1553impl ErrorWithAlert {
1554 pub(crate) fn new(error: Error, send_path: &mut SendPath) -> Self {
1555 maybe_send_fatal_alert(send_path, &error);
1556 Self {
1557 error,
1558 data: send_path.sendable_tls.take_one_vec(),
1559 }
1560 }
1561
1562 pub fn take_tls_data(&mut self) -> Option<Vec<u8>> {
1566 match self.data.is_empty() {
1567 true => None,
1568 false => Some(mem::take(&mut self.data)),
1569 }
1570 }
1571}
1572
1573impl Deref for ErrorWithAlert {
1574 type Target = Error;
1575
1576 fn deref(&self) -> &Self::Target {
1577 &self.error
1578 }
1579}
1580
1581impl From<Error> for ErrorWithAlert {
1583 fn from(error: Error) -> Self {
1584 Self {
1585 error,
1586 data: Vec::new(),
1587 }
1588 }
1589}
1590
1591impl fmt::Debug for ErrorWithAlert {
1592 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1593 f.debug_struct("ErrorWithAlert")
1594 .field("error", &self.error)
1595 .field("data", &self.data.len())
1596 .finish_non_exhaustive()
1597 }
1598}