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::maybe_send_fatal_alert;
15use crate::conn::SendPath;
16use crate::crypto::kx::KeyExchangeAlgorithm;
17use crate::crypto::{CipherSuite, GetRandomFailed, InconsistentKeys};
18use crate::enums::{ContentType, HandshakeType};
19use crate::msgs::{Codec, EchConfigPayload};
20
21#[cfg(test)]
22mod tests;
23
24#[non_exhaustive]
26#[derive(Debug, PartialEq, Clone)]
27pub enum Error {
28 InappropriateMessage {
34 expect_types: Vec<ContentType>,
36 got_type: ContentType,
38 },
39
40 InappropriateHandshakeMessage {
44 expect_types: Vec<HandshakeType>,
46 got_type: HandshakeType,
48 },
49
50 InvalidEncryptedClientHello(EncryptedClientHelloError),
52
53 InvalidMessage(InvalidMessage),
55
56 UnsupportedNameType,
58
59 DecryptError,
61
62 EncryptError,
65
66 PeerIncompatible(PeerIncompatible),
69
70 PeerMisbehaved(PeerMisbehaved),
73
74 AlertReceived(AlertDescription),
76
77 InvalidCertificate(CertificateError),
82
83 InvalidCertRevocationList(CertRevocationListError),
85
86 General(String),
88
89 FailedToGetCurrentTime,
91
92 FailedToGetRandomBytes,
94
95 HandshakeNotComplete,
98
99 PeerSentOversizedRecord,
101
102 NoApplicationProtocol,
104
105 NoSuitableCertificate,
107
108 BadMaxFragmentSize,
111
112 InconsistentKeys(InconsistentKeys),
122
123 RejectedEch(RejectedEch),
130
131 Unreachable(&'static str),
135
136 ApiMisuse(ApiMisuse),
148
149 Other(OtherError),
157}
158
159impl TryFrom<&Error> for AlertDescription {
163 type Error = ();
164
165 fn try_from(error: &Error) -> Result<Self, Self::Error> {
166 Ok(match error {
167 Error::DecryptError => Self::BadRecordMac,
168 Error::InappropriateMessage { .. } | Error::InappropriateHandshakeMessage { .. } => {
169 Self::UnexpectedMessage
170 }
171 Error::InvalidCertificate(e) => Self::from(e),
172 Error::InvalidMessage(e) => Self::from(*e),
173 Error::NoApplicationProtocol => Self::NoApplicationProtocol,
174 Error::PeerMisbehaved(e) => Self::from(*e),
175 Error::PeerIncompatible(e) => Self::from(*e),
176 Error::PeerSentOversizedRecord => Self::RecordOverflow,
177 Error::RejectedEch(_) => Self::EncryptedClientHelloRequired,
178
179 _ => return Err(()),
180 })
181 }
182}
183
184impl fmt::Display for Error {
185 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
186 match self {
187 Self::InappropriateMessage {
188 expect_types,
189 got_type,
190 } => write!(
191 f,
192 "received unexpected message: got {:?} when expecting {}",
193 got_type,
194 join::<ContentType>(expect_types)
195 ),
196 Self::InappropriateHandshakeMessage {
197 expect_types,
198 got_type,
199 } => write!(
200 f,
201 "received unexpected handshake message: got {:?} when expecting {}",
202 got_type,
203 join::<HandshakeType>(expect_types)
204 ),
205 Self::InvalidMessage(typ) => {
206 write!(f, "received corrupt message of type {typ:?}")
207 }
208 Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
209 Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
210 Self::AlertReceived(alert) => write!(f, "received fatal alert: the peer {alert}"),
211 Self::InvalidCertificate(err) => {
212 write!(f, "invalid peer certificate: {err}")
213 }
214 Self::InvalidCertRevocationList(err) => {
215 write!(f, "invalid certificate revocation list: {err:?}")
216 }
217 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
218 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
219 Self::InvalidEncryptedClientHello(err) => {
220 write!(f, "encrypted client hello failure: {err:?}")
221 }
222 Self::EncryptError => write!(f, "cannot encrypt message"),
223 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
224 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
225 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
226 Self::NoSuitableCertificate => write!(f, "no suitable certificate found"),
227 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
228 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
229 Self::BadMaxFragmentSize => {
230 write!(f, "the supplied max_fragment_size was too small or large")
231 }
232 Self::InconsistentKeys(why) => {
233 write!(f, "keys may not be consistent: {why:?}")
234 }
235 Self::RejectedEch(why) => {
236 write!(
237 f,
238 "server rejected encrypted client hello (ECH) {} retry configs",
239 if why.can_retry() { "with" } else { "without" }
240 )
241 }
242 Self::General(err) => write!(f, "unexpected error: {err}"),
243 Self::Unreachable(err) => write!(
244 f,
245 "unreachable condition: {err} (please file a bug in rustls)"
246 ),
247 Self::ApiMisuse(why) => write!(f, "API misuse: {why:?}"),
248 Self::Other(err) => write!(f, "other error: {err}"),
249 }
250 }
251}
252
253impl From<CertificateError> for Error {
254 #[inline]
255 fn from(e: CertificateError) -> Self {
256 Self::InvalidCertificate(e)
257 }
258}
259
260impl From<InvalidMessage> for Error {
261 #[inline]
262 fn from(e: InvalidMessage) -> Self {
263 Self::InvalidMessage(e)
264 }
265}
266
267impl From<PeerMisbehaved> for Error {
268 #[inline]
269 fn from(e: PeerMisbehaved) -> Self {
270 Self::PeerMisbehaved(e)
271 }
272}
273
274impl From<PeerIncompatible> for Error {
275 #[inline]
276 fn from(e: PeerIncompatible) -> Self {
277 Self::PeerIncompatible(e)
278 }
279}
280
281impl From<CertRevocationListError> for Error {
282 #[inline]
283 fn from(e: CertRevocationListError) -> Self {
284 Self::InvalidCertRevocationList(e)
285 }
286}
287
288impl From<EncryptedClientHelloError> for Error {
289 #[inline]
290 fn from(e: EncryptedClientHelloError) -> Self {
291 Self::InvalidEncryptedClientHello(e)
292 }
293}
294
295impl From<RejectedEch> for Error {
296 fn from(rejected_error: RejectedEch) -> Self {
297 Self::RejectedEch(rejected_error)
298 }
299}
300
301impl From<ApiMisuse> for Error {
302 fn from(e: ApiMisuse) -> Self {
303 Self::ApiMisuse(e)
304 }
305}
306
307impl From<OtherError> for Error {
308 fn from(value: OtherError) -> Self {
309 Self::Other(value)
310 }
311}
312
313impl From<InconsistentKeys> for Error {
314 #[inline]
315 fn from(e: InconsistentKeys) -> Self {
316 Self::InconsistentKeys(e)
317 }
318}
319
320impl From<SystemTimeError> for Error {
321 #[inline]
322 fn from(_: SystemTimeError) -> Self {
323 Self::FailedToGetCurrentTime
324 }
325}
326
327impl From<GetRandomFailed> for Error {
328 fn from(_: GetRandomFailed) -> Self {
329 Self::FailedToGetRandomBytes
330 }
331}
332
333impl core::error::Error for Error {}
334
335#[non_exhaustive]
343#[derive(Debug, Clone)]
344pub enum CertificateError {
345 BadEncoding,
347
348 Expired,
350
351 ExpiredContext {
356 time: UnixTime,
358 not_after: UnixTime,
360 },
361
362 NotValidYet,
364
365 NotValidYetContext {
370 time: UnixTime,
372 not_before: UnixTime,
374 },
375
376 Revoked,
378
379 UnhandledCriticalExtension,
382
383 UnknownIssuer,
385
386 UnknownRevocationStatus,
388
389 ExpiredRevocationList,
391
392 ExpiredRevocationListContext {
397 time: UnixTime,
399 next_update: UnixTime,
401 },
402
403 BadSignature,
406
407 UnsupportedSignatureAlgorithm {
409 signature_algorithm_id: Vec<u8>,
411 supported_algorithms: Vec<AlgorithmIdentifier>,
413 },
414
415 UnsupportedSignatureAlgorithmForPublicKey {
417 signature_algorithm_id: Vec<u8>,
419 public_key_algorithm_id: Vec<u8>,
421 },
422
423 NotValidForName,
426
427 NotValidForNameContext {
433 expected: ServerName<'static>,
435
436 presented: Vec<String>,
441 },
442
443 InvalidPurpose,
445
446 InvalidPurposeContext {
451 required: ExtendedKeyPurpose,
453 presented: Vec<ExtendedKeyPurpose>,
455 },
456
457 InvalidOcspResponse,
466
467 ApplicationVerificationFailure,
470
471 Other(OtherError),
482}
483
484impl PartialEq<Self> for CertificateError {
485 fn eq(&self, other: &Self) -> bool {
486 use CertificateError::*;
487 match (self, other) {
488 (BadEncoding, BadEncoding) => true,
489 (Expired, Expired) => true,
490 (
491 ExpiredContext {
492 time: left_time,
493 not_after: left_not_after,
494 },
495 ExpiredContext {
496 time: right_time,
497 not_after: right_not_after,
498 },
499 ) => (left_time, left_not_after) == (right_time, right_not_after),
500 (NotValidYet, NotValidYet) => true,
501 (
502 NotValidYetContext {
503 time: left_time,
504 not_before: left_not_before,
505 },
506 NotValidYetContext {
507 time: right_time,
508 not_before: right_not_before,
509 },
510 ) => (left_time, left_not_before) == (right_time, right_not_before),
511 (Revoked, Revoked) => true,
512 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
513 (UnknownIssuer, UnknownIssuer) => true,
514 (BadSignature, BadSignature) => true,
515 (
516 UnsupportedSignatureAlgorithm {
517 signature_algorithm_id: left_signature_algorithm_id,
518 supported_algorithms: left_supported_algorithms,
519 },
520 UnsupportedSignatureAlgorithm {
521 signature_algorithm_id: right_signature_algorithm_id,
522 supported_algorithms: right_supported_algorithms,
523 },
524 ) => {
525 (left_signature_algorithm_id, left_supported_algorithms)
526 == (right_signature_algorithm_id, right_supported_algorithms)
527 }
528 (
529 UnsupportedSignatureAlgorithmForPublicKey {
530 signature_algorithm_id: left_signature_algorithm_id,
531 public_key_algorithm_id: left_public_key_algorithm_id,
532 },
533 UnsupportedSignatureAlgorithmForPublicKey {
534 signature_algorithm_id: right_signature_algorithm_id,
535 public_key_algorithm_id: right_public_key_algorithm_id,
536 },
537 ) => {
538 (left_signature_algorithm_id, left_public_key_algorithm_id)
539 == (right_signature_algorithm_id, right_public_key_algorithm_id)
540 }
541 (NotValidForName, NotValidForName) => true,
542 (
543 NotValidForNameContext {
544 expected: left_expected,
545 presented: left_presented,
546 },
547 NotValidForNameContext {
548 expected: right_expected,
549 presented: right_presented,
550 },
551 ) => (left_expected, left_presented) == (right_expected, right_presented),
552 (InvalidPurpose, InvalidPurpose) => true,
553 (
554 InvalidPurposeContext {
555 required: left_required,
556 presented: left_presented,
557 },
558 InvalidPurposeContext {
559 required: right_required,
560 presented: right_presented,
561 },
562 ) => (left_required, left_presented) == (right_required, right_presented),
563 (InvalidOcspResponse, InvalidOcspResponse) => true,
564 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
565 (UnknownRevocationStatus, UnknownRevocationStatus) => true,
566 (ExpiredRevocationList, ExpiredRevocationList) => true,
567 (
568 ExpiredRevocationListContext {
569 time: left_time,
570 next_update: left_next_update,
571 },
572 ExpiredRevocationListContext {
573 time: right_time,
574 next_update: right_next_update,
575 },
576 ) => (left_time, left_next_update) == (right_time, right_next_update),
577 _ => false,
578 }
579 }
580}
581
582impl From<&CertificateError> for AlertDescription {
586 fn from(e: &CertificateError) -> Self {
587 use CertificateError::*;
588 match e {
589 BadEncoding
590 | UnhandledCriticalExtension
591 | NotValidForName
592 | NotValidForNameContext { .. } => Self::BadCertificate,
593 Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
597 Self::CertificateExpired
598 }
599 Revoked => Self::CertificateRevoked,
600 UnknownIssuer
603 | UnknownRevocationStatus
604 | ExpiredRevocationList
605 | ExpiredRevocationListContext { .. } => Self::UnknownCa,
606 InvalidOcspResponse => Self::BadCertificateStatusResponse,
607 BadSignature
608 | UnsupportedSignatureAlgorithm { .. }
609 | UnsupportedSignatureAlgorithmForPublicKey { .. } => Self::DecryptError,
610 InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate,
611 ApplicationVerificationFailure => Self::AccessDenied,
612 Other(..) => Self::CertificateUnknown,
617 }
618 }
619}
620
621impl fmt::Display for CertificateError {
622 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
623 match self {
624 Self::NotValidForNameContext {
625 expected,
626 presented,
627 } => {
628 write!(
629 f,
630 "certificate not valid for name {:?}; certificate ",
631 expected.to_str()
632 )?;
633
634 match presented.as_slice() {
635 &[] => write!(
636 f,
637 "is not valid for any names (according to its subjectAltName extension)"
638 ),
639 [one] => write!(f, "is only valid for {one}"),
640 many => {
641 write!(f, "is only valid for ")?;
642
643 let n = many.len();
644 let all_but_last = &many[..n - 1];
645 let last = &many[n - 1];
646
647 for (i, name) in all_but_last.iter().enumerate() {
648 write!(f, "{name}")?;
649 if i < n - 2 {
650 write!(f, ", ")?;
651 }
652 }
653 write!(f, " or {last}")
654 }
655 }
656 }
657
658 Self::ExpiredContext { time, not_after } => write!(
659 f,
660 "certificate expired: verification time {} (UNIX), \
661 but certificate is not valid after {} \
662 ({} seconds ago)",
663 time.as_secs(),
664 not_after.as_secs(),
665 time.as_secs()
666 .saturating_sub(not_after.as_secs())
667 ),
668
669 Self::NotValidYetContext { time, not_before } => write!(
670 f,
671 "certificate not valid yet: verification time {} (UNIX), \
672 but certificate is not valid before {} \
673 ({} seconds in future)",
674 time.as_secs(),
675 not_before.as_secs(),
676 not_before
677 .as_secs()
678 .saturating_sub(time.as_secs())
679 ),
680
681 Self::ExpiredRevocationListContext { time, next_update } => write!(
682 f,
683 "certificate revocation list expired: \
684 verification time {} (UNIX), \
685 but CRL is not valid after {} \
686 ({} seconds ago)",
687 time.as_secs(),
688 next_update.as_secs(),
689 time.as_secs()
690 .saturating_sub(next_update.as_secs())
691 ),
692
693 Self::InvalidPurposeContext {
694 required,
695 presented,
696 } => {
697 write!(
698 f,
699 "certificate does not allow extended key usage for {required}, allows "
700 )?;
701 for (i, eku) in presented.iter().enumerate() {
702 if i > 0 {
703 write!(f, ", ")?;
704 }
705 write!(f, "{eku}")?;
706 }
707 Ok(())
708 }
709
710 Self::Other(other) => write!(f, "{other}"),
711
712 other => write!(f, "{other:?}"),
713 }
714 }
715}
716
717enum_builder! {
718 pub struct AlertDescription(pub u8);
721
722 enum AlertDescriptionName {
723 CloseNotify => 0x00,
724 UnexpectedMessage => 0x0a,
725 BadRecordMac => 0x14,
726 DecryptionFailed => 0x15,
727 RecordOverflow => 0x16,
728 DecompressionFailure => 0x1e,
729 HandshakeFailure => 0x28,
730 NoCertificate => 0x29,
731 BadCertificate => 0x2a,
732 UnsupportedCertificate => 0x2b,
733 CertificateRevoked => 0x2c,
734 CertificateExpired => 0x2d,
735 CertificateUnknown => 0x2e,
736 IllegalParameter => 0x2f,
737 UnknownCa => 0x30,
738 AccessDenied => 0x31,
739 DecodeError => 0x32,
740 DecryptError => 0x33,
741 ExportRestriction => 0x3c,
742 ProtocolVersion => 0x46,
743 InsufficientSecurity => 0x47,
744 InternalError => 0x50,
745 InappropriateFallback => 0x56,
746 UserCanceled => 0x5a,
747 NoRenegotiation => 0x64,
748 MissingExtension => 0x6d,
749 UnsupportedExtension => 0x6e,
750 CertificateUnobtainable => 0x6f,
751 UnrecognizedName => 0x70,
752 BadCertificateStatusResponse => 0x71,
753 BadCertificateHashValue => 0x72,
754 UnknownPskIdentity => 0x73,
755 CertificateRequired => 0x74,
756 NoApplicationProtocol => 0x78,
757 EncryptedClientHelloRequired => 0x79, }
759}
760
761impl fmt::Display for AlertDescription {
762 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
763 let Ok(known) = AlertDescriptionName::try_from(*self) else {
764 return write!(f, "sent an unknown alert (0x{:02x?})", self.0);
765 };
766
767 match known {
772 AlertDescriptionName::CloseNotify => write!(f, "cleanly closed the connection"),
774
775 AlertDescriptionName::UnexpectedMessage => write!(f, "received an unexpected message"),
778 AlertDescriptionName::BadRecordMac => write!(f, "failed to verify a message"),
779 AlertDescriptionName::RecordOverflow => write!(f, "rejected an over-length message"),
780 AlertDescriptionName::IllegalParameter => write!(
781 f,
782 "rejected a message because a field was incorrect or inconsistent"
783 ),
784 AlertDescriptionName::DecodeError => write!(f, "failed to decode a message"),
785 AlertDescriptionName::DecryptError => {
786 write!(f, "failed to perform a handshake cryptographic operation")
787 }
788 AlertDescriptionName::InappropriateFallback => {
789 write!(f, "detected an attempted version downgrade")
790 }
791 AlertDescriptionName::MissingExtension => {
792 write!(f, "required a specific extension that was not provided")
793 }
794 AlertDescriptionName::UnsupportedExtension => {
795 write!(f, "rejected an unsolicited extension")
796 }
797
798 AlertDescriptionName::DecryptionFailed => write!(f, "failed to decrypt a message"),
801 AlertDescriptionName::DecompressionFailure => {
802 write!(f, "failed to decompress a message")
803 }
804 AlertDescriptionName::NoCertificate => write!(f, "found no certificate"),
805 AlertDescriptionName::ExportRestriction => {
806 write!(f, "refused due to export restrictions")
807 }
808 AlertDescriptionName::NoRenegotiation => {
809 write!(f, "rejected an attempt at renegotiation")
810 }
811 AlertDescriptionName::CertificateUnobtainable => {
812 write!(f, "failed to retrieve its certificate")
813 }
814 AlertDescriptionName::BadCertificateHashValue => {
815 write!(f, "rejected the `certificate_hash` extension")
816 }
817
818 AlertDescriptionName::HandshakeFailure => write!(
822 f,
823 "failed to negotiate an acceptable set of security parameters"
824 ),
825 AlertDescriptionName::ProtocolVersion => {
826 write!(f, "did not support a suitable TLS version")
827 }
828 AlertDescriptionName::InsufficientSecurity => {
829 write!(f, "required a higher security level than was offered")
830 }
831
832 AlertDescriptionName::BadCertificate => {
835 write!(
836 f,
837 "rejected the certificate as corrupt or incorrectly signed"
838 )
839 }
840 AlertDescriptionName::UnsupportedCertificate => {
841 write!(f, "did not support the certificate")
842 }
843 AlertDescriptionName::CertificateRevoked => {
844 write!(f, "found the certificate to be revoked")
845 }
846 AlertDescriptionName::CertificateExpired => {
847 write!(f, "found the certificate to be expired")
848 }
849 AlertDescriptionName::CertificateUnknown => {
850 write!(f, "rejected the certificate for an unspecified reason")
851 }
852 AlertDescriptionName::UnknownCa => {
853 write!(f, "found the certificate was not issued by a trusted CA")
854 }
855 AlertDescriptionName::BadCertificateStatusResponse => {
856 write!(f, "rejected the certificate status response")
857 }
858 AlertDescriptionName::AccessDenied => write!(f, "denied access"),
860 AlertDescriptionName::CertificateRequired => {
862 write!(f, "required a client certificate")
863 }
864
865 AlertDescriptionName::InternalError => write!(f, "encountered an internal error"),
866 AlertDescriptionName::UserCanceled => write!(f, "canceled the handshake"),
867
868 AlertDescriptionName::UnrecognizedName => {
870 write!(f, "did not recognize a name in the `server_name` extension")
871 }
872
873 AlertDescriptionName::UnknownPskIdentity => {
876 write!(f, "did not recognize any offered PSK identity")
877 }
878
879 AlertDescriptionName::NoApplicationProtocol => write!(
882 f,
883 "did not support any of the offered application protocols"
884 ),
885
886 AlertDescriptionName::EncryptedClientHelloRequired => {
889 write!(f, "required use of encrypted client hello")
890 }
891 }
892 }
893}
894
895#[non_exhaustive]
897#[derive(Debug, Clone, Copy, PartialEq)]
898pub enum InvalidMessage {
899 CertificatePayloadTooLarge,
901 HandshakePayloadTooLarge,
903 InvalidCcs,
905 InvalidContentType,
907 InvalidCertificateStatusType,
909 InvalidCertRequest,
911 InvalidDhParams,
913 InvalidEmptyPayload,
915 InvalidKeyUpdate,
917 InvalidServerName,
919 MessageTooLarge,
921 MessageTooShort,
923 MissingData(&'static str),
925 MissingKeyExchange,
927 NoSignatureSchemes,
929 TrailingData(&'static str),
931 UnexpectedMessage(&'static str),
933 UnknownProtocolVersion,
935 UnsupportedCompression,
937 UnsupportedCurveType,
939 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
941 EmptyTicketValue,
943 IllegalEmptyList(&'static str),
947 DuplicateExtension(u16),
949 PreSharedKeyIsNotFinalExtension,
951 UnknownHelloRetryRequestExtension,
953 UnknownCertificateExtension,
955}
956
957impl From<InvalidMessage> for AlertDescription {
958 fn from(e: InvalidMessage) -> Self {
959 match e {
960 InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
961 InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
962 InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
963 InvalidMessage::CertificatePayloadTooLarge => Self::BadCertificate,
964 _ => Self::DecodeError,
965 }
966 }
967}
968
969#[expect(missing_docs)]
980#[non_exhaustive]
981#[derive(Clone, Copy, Debug, PartialEq)]
982pub enum PeerMisbehaved {
983 AttemptedDowngradeToTls12WhenTls13IsSupported,
984 BadCertChainExtensions,
985 DisallowedEncryptedExtension,
986 DuplicateClientHelloExtensions,
987 DuplicateEncryptedExtensions,
988 DuplicateHelloRetryRequestExtensions,
989 DuplicateNewSessionTicketExtensions,
990 DuplicateServerHelloExtensions,
991 DuplicateServerNameTypes,
992 EarlyDataAttemptedInSecondClientHello,
993 EarlyDataExtensionWithoutResumption,
994 EarlyDataOfferedWithVariedCipherSuite,
995 HandshakeHashVariedAfterRetry,
996 IllegalAlertLevel(u8, AlertDescription),
998 IllegalHelloRetryRequestWithEmptyCookie,
999 IllegalHelloRetryRequestWithNoChanges,
1000 IllegalHelloRetryRequestWithOfferedGroup,
1001 IllegalHelloRetryRequestWithUnofferedCipherSuite,
1002 IllegalHelloRetryRequestWithUnofferedNamedGroup,
1003 IllegalHelloRetryRequestWithUnsupportedVersion,
1004 IllegalHelloRetryRequestWithWrongSessionId,
1005 IllegalHelloRetryRequestWithInvalidEch,
1006 IllegalMiddleboxChangeCipherSpec,
1007 IllegalTlsInnerPlaintext,
1008 IllegalWarningAlert(AlertDescription),
1010 IncorrectBinder,
1011 IncorrectFinished,
1012 InvalidCertCompression,
1013 InvalidMaxEarlyDataSize,
1014 InvalidKeyShare,
1015 KeyEpochWithPendingFragment,
1016 KeyUpdateReceivedInQuicConnection,
1017 MessageInterleavedWithHandshakeMessage,
1018 MissingBinderInPskExtension,
1019 MissingKeyShare,
1020 MissingPskModesExtension,
1021 MissingQuicTransportParameters,
1022 NoCertificatesPresented,
1023 OfferedDuplicateCertificateCompressions,
1024 OfferedDuplicateKeyShares,
1025 OfferedEarlyDataWithOldProtocolVersion,
1026 OfferedEmptyApplicationProtocol,
1027 OfferedIncorrectCompressions,
1028 PskExtensionMustBeLast,
1029 PskExtensionWithMismatchedIdsAndBinders,
1030 RefusedToFollowHelloRetryRequest,
1031 RejectedEarlyDataInterleavedWithHandshakeMessage,
1032 ResumptionAttemptedWithVariedEms,
1033 ResumptionOfferedWithVariedCipherSuite,
1034 ResumptionOfferedWithVariedEms,
1035 ResumptionOfferedWithIncompatibleCipherSuite,
1036 SelectedDifferentCipherSuiteAfterRetry,
1037 SelectedInvalidPsk,
1038 SelectedTls12UsingTls13VersionExtension,
1039 SelectedUnofferedApplicationProtocol,
1040 SelectedUnofferedCertCompression,
1041 SelectedUnofferedCipherSuite,
1042 SelectedUnofferedCompression,
1043 SelectedUnofferedKxGroup,
1044 SelectedUnofferedPsk,
1045 ServerEchoedCompatibilitySessionId,
1046 ServerHelloMustOfferUncompressedEcPoints,
1047 ServerNameDifferedOnRetry,
1048 ServerNameMustContainOneHostName,
1049 SignedKxWithWrongAlgorithm,
1050 SignedHandshakeWithUnadvertisedSigScheme,
1051 TooManyEmptyFragments,
1052 TooManyConsecutiveHandshakeMessagesAfterHandshake,
1053 TooManyRenegotiationRequests,
1054 TooManyWarningAlertsReceived,
1055 TooMuchEarlyDataReceived,
1056 UnexpectedCleartextExtension,
1057 UnsolicitedCertExtension,
1058 UnsolicitedEncryptedExtension,
1059 UnsolicitedSctList,
1060 UnsolicitedServerHelloExtension,
1061 WrongGroupForKeyShare,
1062 UnsolicitedEchExtension,
1063}
1064
1065impl From<PeerMisbehaved> for AlertDescription {
1066 fn from(e: PeerMisbehaved) -> Self {
1067 match e {
1068 PeerMisbehaved::DisallowedEncryptedExtension
1069 | PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch
1070 | PeerMisbehaved::UnexpectedCleartextExtension
1071 | PeerMisbehaved::UnsolicitedEchExtension
1072 | PeerMisbehaved::UnsolicitedEncryptedExtension
1073 | PeerMisbehaved::UnsolicitedServerHelloExtension => Self::UnsupportedExtension,
1074
1075 PeerMisbehaved::IllegalMiddleboxChangeCipherSpec
1076 | PeerMisbehaved::KeyEpochWithPendingFragment
1077 | PeerMisbehaved::KeyUpdateReceivedInQuicConnection => Self::UnexpectedMessage,
1078
1079 PeerMisbehaved::IllegalWarningAlert(_) => Self::DecodeError,
1080
1081 PeerMisbehaved::IncorrectBinder | PeerMisbehaved::IncorrectFinished => {
1082 Self::DecryptError
1083 }
1084
1085 PeerMisbehaved::InvalidCertCompression
1086 | PeerMisbehaved::SelectedUnofferedCertCompression => Self::BadCertificate,
1087
1088 PeerMisbehaved::MissingKeyShare
1089 | PeerMisbehaved::MissingPskModesExtension
1090 | PeerMisbehaved::MissingQuicTransportParameters => Self::MissingExtension,
1091
1092 PeerMisbehaved::NoCertificatesPresented => Self::CertificateRequired,
1093
1094 _ => Self::IllegalParameter,
1095 }
1096 }
1097}
1098
1099#[expect(missing_docs)]
1105#[non_exhaustive]
1106#[derive(Clone, Copy, Debug, PartialEq)]
1107pub enum PeerIncompatible {
1108 EcPointsExtensionRequired,
1109 ExtendedMasterSecretExtensionRequired,
1110 IncorrectCertificateTypeExtension,
1111 KeyShareExtensionRequired,
1112 MultipleRawKeys,
1113 NamedGroupsExtensionRequired,
1114 NoCertificateRequestSignatureSchemesInCommon,
1115 NoCipherSuitesInCommon,
1116 NoEcPointFormatsInCommon,
1117 NoKxGroupsInCommon,
1118 NoSignatureSchemesInCommon,
1119 NoServerNameProvided,
1120 NullCompressionRequired,
1121 ServerDoesNotSupportTls12Or13,
1122 ServerSentHelloRetryRequestWithUnknownExtension,
1123 ServerTlsVersionIsDisabledByOurConfig,
1124 SignatureAlgorithmsExtensionRequired,
1125 SupportedVersionsExtensionRequired,
1126 Tls12NotOffered,
1127 Tls12NotOfferedOrEnabled,
1128 Tls13RequiredForQuic,
1129 UncompressedEcPointsRequired,
1130 UnknownCertificateType(u8),
1131 UnsolicitedCertificateTypeExtension,
1132}
1133
1134impl From<PeerIncompatible> for AlertDescription {
1135 fn from(e: PeerIncompatible) -> Self {
1136 match e {
1137 PeerIncompatible::NullCompressionRequired => Self::IllegalParameter,
1138
1139 PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig
1140 | PeerIncompatible::SupportedVersionsExtensionRequired
1141 | PeerIncompatible::Tls12NotOffered
1142 | PeerIncompatible::Tls12NotOfferedOrEnabled
1143 | PeerIncompatible::Tls13RequiredForQuic => Self::ProtocolVersion,
1144
1145 PeerIncompatible::UnknownCertificateType(_) => Self::UnsupportedCertificate,
1146
1147 _ => Self::HandshakeFailure,
1148 }
1149 }
1150}
1151
1152#[non_exhaustive]
1157#[derive(Clone, Debug, Eq, PartialEq)]
1158pub enum ExtendedKeyPurpose {
1159 ClientAuth,
1161 ServerAuth,
1163 Other(Vec<usize>),
1167}
1168
1169impl ExtendedKeyPurpose {
1170 #[cfg(feature = "webpki")]
1171 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
1172 let values = values.collect::<Vec<_>>();
1173 match &*values {
1174 ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
1175 ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
1176 _ => Self::Other(values),
1177 }
1178 }
1179}
1180
1181impl fmt::Display for ExtendedKeyPurpose {
1182 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1183 match self {
1184 Self::ClientAuth => write!(f, "client authentication"),
1185 Self::ServerAuth => write!(f, "server authentication"),
1186 Self::Other(values) => {
1187 for (i, value) in values.iter().enumerate() {
1188 if i > 0 {
1189 write!(f, ", ")?;
1190 }
1191 write!(f, "{value}")?;
1192 }
1193 Ok(())
1194 }
1195 }
1196 }
1197}
1198
1199#[non_exhaustive]
1201#[derive(Debug, Clone)]
1202pub enum CertRevocationListError {
1203 BadSignature,
1205
1206 UnsupportedSignatureAlgorithm {
1208 signature_algorithm_id: Vec<u8>,
1210 supported_algorithms: Vec<AlgorithmIdentifier>,
1212 },
1213
1214 UnsupportedSignatureAlgorithmForPublicKey {
1216 signature_algorithm_id: Vec<u8>,
1218 public_key_algorithm_id: Vec<u8>,
1220 },
1221
1222 InvalidCrlNumber,
1224
1225 InvalidRevokedCertSerialNumber,
1227
1228 IssuerInvalidForCrl,
1230
1231 Other(OtherError),
1235
1236 ParseError,
1238
1239 UnsupportedCrlVersion,
1241
1242 UnsupportedCriticalExtension,
1244
1245 UnsupportedDeltaCrl,
1247
1248 UnsupportedIndirectCrl,
1251
1252 UnsupportedRevocationReason,
1257}
1258
1259impl PartialEq<Self> for CertRevocationListError {
1260 fn eq(&self, other: &Self) -> bool {
1261 use CertRevocationListError::*;
1262 match (self, other) {
1263 (BadSignature, BadSignature) => true,
1264 (
1265 UnsupportedSignatureAlgorithm {
1266 signature_algorithm_id: left_signature_algorithm_id,
1267 supported_algorithms: left_supported_algorithms,
1268 },
1269 UnsupportedSignatureAlgorithm {
1270 signature_algorithm_id: right_signature_algorithm_id,
1271 supported_algorithms: right_supported_algorithms,
1272 },
1273 ) => {
1274 (left_signature_algorithm_id, left_supported_algorithms)
1275 == (right_signature_algorithm_id, right_supported_algorithms)
1276 }
1277 (
1278 UnsupportedSignatureAlgorithmForPublicKey {
1279 signature_algorithm_id: left_signature_algorithm_id,
1280 public_key_algorithm_id: left_public_key_algorithm_id,
1281 },
1282 UnsupportedSignatureAlgorithmForPublicKey {
1283 signature_algorithm_id: right_signature_algorithm_id,
1284 public_key_algorithm_id: right_public_key_algorithm_id,
1285 },
1286 ) => {
1287 (left_signature_algorithm_id, left_public_key_algorithm_id)
1288 == (right_signature_algorithm_id, right_public_key_algorithm_id)
1289 }
1290 (InvalidCrlNumber, InvalidCrlNumber) => true,
1291 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
1292 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
1293 (ParseError, ParseError) => true,
1294 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
1295 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
1296 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
1297 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
1298 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
1299 _ => false,
1300 }
1301 }
1302}
1303
1304#[non_exhaustive]
1306#[derive(Debug, Clone, Eq, PartialEq)]
1307pub enum EncryptedClientHelloError {
1308 InvalidConfigList,
1310 NoCompatibleConfig,
1312 SniRequired,
1314}
1315
1316#[non_exhaustive]
1322#[derive(Debug, Clone, PartialEq)]
1323pub struct RejectedEch {
1324 pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
1325}
1326
1327impl RejectedEch {
1328 pub fn can_retry(&self) -> bool {
1334 self.retry_configs.is_some()
1335 }
1336
1337 pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
1339 let Some(retry_configs) = &self.retry_configs else {
1340 return None;
1341 };
1342
1343 let mut tls_encoded_list = Vec::new();
1344 retry_configs.encode(&mut tls_encoded_list);
1345
1346 Some(EchConfigListBytes::from(tls_encoded_list))
1347 }
1348}
1349
1350fn join<T: fmt::Debug>(items: &[T]) -> String {
1351 items
1352 .iter()
1353 .map(|x| format!("{x:?}"))
1354 .collect::<Vec<String>>()
1355 .join(" or ")
1356}
1357
1358#[non_exhaustive]
1362#[derive(Debug, Clone, PartialEq)]
1363pub enum ApiMisuse {
1364 ResumingFromUnknownCipherSuite(CipherSuite),
1366
1367 ExporterAlreadyUsed,
1375
1376 ExporterContextTooLong,
1382
1383 ExporterOutputTooLong,
1389
1390 ExporterOutputZeroLength,
1397
1398 AcceptorPolledAfterCompletion,
1402
1403 InvalidQuicHeaderProtectionSampleLength,
1407
1408 InvalidQuicHeaderProtectionPacketNumberLength,
1413
1414 InvalidSignerForProtocolVersion,
1416
1417 QuicRequiresTls13Support,
1419
1420 NoQuicCompatibleCipherSuites,
1422
1423 EmptyCertificateChain,
1425
1426 QuicRestrictsMaxEarlyDataSize,
1432
1433 NoCipherSuitesConfigured,
1435
1436 NoKeyExchangeGroupsConfigured,
1438
1439 NoSignatureVerificationAlgorithms,
1441
1442 EchRequiresTls13Support,
1444
1445 EchForbidsTls12Support,
1447
1448 SecretExtractionRequiresPriorOptIn,
1456
1457 SecretExtractionWithPendingSendableData,
1464
1465 UnverifiableCertificateType,
1470
1471 NoSupportedCertificateTypes,
1473
1474 NonceArraySizeMismatch {
1480 expected: usize,
1482 actual: usize,
1484 },
1485
1486 IvLengthExceedsMaximum {
1493 actual: usize,
1495 maximum: usize,
1497 },
1498
1499 ResumptionDataProvidedTooLate,
1504
1505 KeyUpdateNotAvailableForTls12,
1509}
1510
1511impl fmt::Display for ApiMisuse {
1512 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1513 write!(f, "{self:?}")
1514 }
1515}
1516
1517impl core::error::Error for ApiMisuse {}
1518
1519mod other_error {
1520 use core::error::Error as StdError;
1521 use core::fmt;
1522
1523 use crate::sync::Arc;
1524
1525 #[derive(Debug, Clone)]
1533 pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1534
1535 impl OtherError {
1536 pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1538 Self(Arc::new(err))
1539 }
1540 }
1541
1542 impl PartialEq<Self> for OtherError {
1543 fn eq(&self, _other: &Self) -> bool {
1544 false
1545 }
1546 }
1547
1548 impl fmt::Display for OtherError {
1549 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1550 write!(f, "{}", self.0)
1551 }
1552 }
1553
1554 impl StdError for OtherError {
1555 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1556 Some(self.0.as_ref())
1557 }
1558 }
1559}
1560
1561pub use other_error::OtherError;
1562
1563pub struct ErrorWithAlert {
1566 pub error: Error,
1568 pub(crate) data: Vec<u8>,
1569}
1570
1571impl ErrorWithAlert {
1572 pub(crate) fn new(error: Error, send_path: &mut SendPath) -> Self {
1573 maybe_send_fatal_alert(send_path, &error);
1574 Self {
1575 error,
1576 data: send_path.sendable_tls.take_one_vec(),
1577 }
1578 }
1579
1580 pub fn take_tls_data(&mut self) -> Option<Vec<u8>> {
1584 match self.data.is_empty() {
1585 true => None,
1586 false => Some(mem::take(&mut self.data)),
1587 }
1588 }
1589}
1590
1591impl Deref for ErrorWithAlert {
1592 type Target = Error;
1593
1594 fn deref(&self) -> &Self::Target {
1595 &self.error
1596 }
1597}
1598
1599impl From<Error> for ErrorWithAlert {
1601 fn from(error: Error) -> Self {
1602 Self {
1603 error,
1604 data: Vec::new(),
1605 }
1606 }
1607}
1608
1609impl fmt::Debug for ErrorWithAlert {
1610 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1611 f.debug_struct("ErrorWithAlert")
1612 .field("error", &self.error)
1613 .field("data", &self.data.len())
1614 .finish_non_exhaustive()
1615 }
1616}