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 EmptyFragment,
996 HandshakeHashVariedAfterRetry,
997 IllegalAlertLevel(u8, AlertDescription),
999 IllegalHelloRetryRequestWithEmptyCookie,
1000 IllegalHelloRetryRequestWithNoChanges,
1001 IllegalHelloRetryRequestWithOfferedGroup,
1002 IllegalHelloRetryRequestWithUnofferedCipherSuite,
1003 IllegalHelloRetryRequestWithUnofferedNamedGroup,
1004 IllegalHelloRetryRequestWithUnsupportedVersion,
1005 IllegalHelloRetryRequestWithWrongSessionId,
1006 IllegalHelloRetryRequestWithInvalidEch,
1007 IllegalMiddleboxChangeCipherSpec,
1008 IllegalTlsInnerPlaintext,
1009 IllegalWarningAlert(AlertDescription),
1011 IncorrectBinder,
1012 IncorrectFinished,
1013 InvalidCertCompression,
1014 InvalidMaxEarlyDataSize,
1015 InvalidKeyShare,
1016 KeyEpochWithPendingFragment,
1017 KeyUpdateReceivedInQuicConnection,
1018 MessageInterleavedWithHandshakeMessage,
1019 MissingBinderInPskExtension,
1020 MissingKeyShare,
1021 MissingPskModesExtension,
1022 MissingQuicTransportParameters,
1023 NoCertificatesPresented,
1024 OfferedDuplicateCertificateCompressions,
1025 OfferedDuplicateKeyShares,
1026 OfferedEarlyDataWithOldProtocolVersion,
1027 OfferedEmptyApplicationProtocol,
1028 OfferedIncorrectCompressions,
1029 PskExtensionMustBeLast,
1030 PskExtensionWithMismatchedIdsAndBinders,
1031 RefusedToFollowHelloRetryRequest,
1032 RejectedEarlyDataInterleavedWithHandshakeMessage,
1033 ResumptionAttemptedWithVariedEms,
1034 ResumptionOfferedWithVariedCipherSuite,
1035 ResumptionOfferedWithVariedEms,
1036 ResumptionOfferedWithIncompatibleCipherSuite,
1037 SelectedDifferentCipherSuiteAfterRetry,
1038 SelectedInvalidPsk,
1039 SelectedTls12UsingTls13VersionExtension,
1040 SelectedUnofferedApplicationProtocol,
1041 SelectedUnofferedCertCompression,
1042 SelectedUnofferedCipherSuite,
1043 SelectedUnofferedCompression,
1044 SelectedUnofferedKxGroup,
1045 SelectedUnofferedPsk,
1046 ServerEchoedCompatibilitySessionId,
1047 ServerHelloMustOfferUncompressedEcPoints,
1048 ServerNameDifferedOnRetry,
1049 ServerNameMustContainOneHostName,
1050 SignedKxWithWrongAlgorithm,
1051 SignedHandshakeWithUnadvertisedSigScheme,
1052 TooManyEmptyFragments,
1053 TooManyConsecutiveHandshakeMessagesAfterHandshake,
1054 TooManyRenegotiationRequests,
1055 TooManyWarningAlertsReceived,
1056 TooMuchEarlyDataReceived,
1057 UnexpectedCleartextExtension,
1058 UnsolicitedCertExtension,
1059 UnsolicitedEncryptedExtension,
1060 UnsolicitedSctList,
1061 UnsolicitedServerHelloExtension,
1062 WrongGroupForKeyShare,
1063 UnsolicitedEchExtension,
1064}
1065
1066impl From<PeerMisbehaved> for AlertDescription {
1067 fn from(e: PeerMisbehaved) -> Self {
1068 match e {
1069 PeerMisbehaved::DisallowedEncryptedExtension
1070 | PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch
1071 | PeerMisbehaved::UnexpectedCleartextExtension
1072 | PeerMisbehaved::UnsolicitedEchExtension
1073 | PeerMisbehaved::UnsolicitedEncryptedExtension
1074 | PeerMisbehaved::UnsolicitedServerHelloExtension => Self::UnsupportedExtension,
1075
1076 PeerMisbehaved::IllegalMiddleboxChangeCipherSpec
1077 | PeerMisbehaved::KeyEpochWithPendingFragment
1078 | PeerMisbehaved::KeyUpdateReceivedInQuicConnection => Self::UnexpectedMessage,
1079
1080 PeerMisbehaved::IllegalWarningAlert(_) => Self::DecodeError,
1081
1082 PeerMisbehaved::IncorrectBinder | PeerMisbehaved::IncorrectFinished => {
1083 Self::DecryptError
1084 }
1085
1086 PeerMisbehaved::InvalidCertCompression
1087 | PeerMisbehaved::SelectedUnofferedCertCompression => Self::BadCertificate,
1088
1089 PeerMisbehaved::MissingKeyShare
1090 | PeerMisbehaved::MissingPskModesExtension
1091 | PeerMisbehaved::MissingQuicTransportParameters => Self::MissingExtension,
1092
1093 PeerMisbehaved::NoCertificatesPresented => Self::CertificateRequired,
1094
1095 _ => Self::IllegalParameter,
1096 }
1097 }
1098}
1099
1100#[expect(missing_docs)]
1106#[non_exhaustive]
1107#[derive(Clone, Copy, Debug, PartialEq)]
1108pub enum PeerIncompatible {
1109 EcPointsExtensionRequired,
1110 ExtendedMasterSecretExtensionRequired,
1111 IncorrectCertificateTypeExtension,
1112 KeyShareExtensionRequired,
1113 MultipleRawKeys,
1114 NamedGroupsExtensionRequired,
1115 NoCertificateRequestSignatureSchemesInCommon,
1116 NoCipherSuitesInCommon,
1117 NoEcPointFormatsInCommon,
1118 NoKxGroupsInCommon,
1119 NoSignatureSchemesInCommon,
1120 NoServerNameProvided,
1121 NullCompressionRequired,
1122 ServerDoesNotSupportTls12Or13,
1123 ServerSentHelloRetryRequestWithUnknownExtension,
1124 ServerTlsVersionIsDisabledByOurConfig,
1125 SignatureAlgorithmsExtensionRequired,
1126 SupportedVersionsExtensionRequired,
1127 Tls12NotOffered,
1128 Tls12NotOfferedOrEnabled,
1129 Tls13RequiredForQuic,
1130 UncompressedEcPointsRequired,
1131 UnknownCertificateType(u8),
1132 UnsolicitedCertificateTypeExtension,
1133}
1134
1135impl From<PeerIncompatible> for AlertDescription {
1136 fn from(e: PeerIncompatible) -> Self {
1137 match e {
1138 PeerIncompatible::NullCompressionRequired => Self::IllegalParameter,
1139
1140 PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig
1141 | PeerIncompatible::SupportedVersionsExtensionRequired
1142 | PeerIncompatible::Tls12NotOffered
1143 | PeerIncompatible::Tls12NotOfferedOrEnabled
1144 | PeerIncompatible::Tls13RequiredForQuic => Self::ProtocolVersion,
1145
1146 PeerIncompatible::UnknownCertificateType(_) => Self::UnsupportedCertificate,
1147
1148 _ => Self::HandshakeFailure,
1149 }
1150 }
1151}
1152
1153#[non_exhaustive]
1158#[derive(Clone, Debug, Eq, PartialEq)]
1159pub enum ExtendedKeyPurpose {
1160 ClientAuth,
1162 ServerAuth,
1164 Other(Vec<usize>),
1168}
1169
1170impl ExtendedKeyPurpose {
1171 #[cfg(feature = "webpki")]
1172 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
1173 let values = values.collect::<Vec<_>>();
1174 match &*values {
1175 ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
1176 ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
1177 _ => Self::Other(values),
1178 }
1179 }
1180}
1181
1182impl fmt::Display for ExtendedKeyPurpose {
1183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1184 match self {
1185 Self::ClientAuth => write!(f, "client authentication"),
1186 Self::ServerAuth => write!(f, "server authentication"),
1187 Self::Other(values) => {
1188 for (i, value) in values.iter().enumerate() {
1189 if i > 0 {
1190 write!(f, ", ")?;
1191 }
1192 write!(f, "{value}")?;
1193 }
1194 Ok(())
1195 }
1196 }
1197 }
1198}
1199
1200#[non_exhaustive]
1202#[derive(Debug, Clone)]
1203pub enum CertRevocationListError {
1204 BadSignature,
1206
1207 UnsupportedSignatureAlgorithm {
1209 signature_algorithm_id: Vec<u8>,
1211 supported_algorithms: Vec<AlgorithmIdentifier>,
1213 },
1214
1215 UnsupportedSignatureAlgorithmForPublicKey {
1217 signature_algorithm_id: Vec<u8>,
1219 public_key_algorithm_id: Vec<u8>,
1221 },
1222
1223 InvalidCrlNumber,
1225
1226 InvalidRevokedCertSerialNumber,
1228
1229 IssuerInvalidForCrl,
1231
1232 Other(OtherError),
1236
1237 ParseError,
1239
1240 UnsupportedCrlVersion,
1242
1243 UnsupportedCriticalExtension,
1245
1246 UnsupportedDeltaCrl,
1248
1249 UnsupportedIndirectCrl,
1252
1253 UnsupportedRevocationReason,
1258}
1259
1260impl PartialEq<Self> for CertRevocationListError {
1261 fn eq(&self, other: &Self) -> bool {
1262 use CertRevocationListError::*;
1263 match (self, other) {
1264 (BadSignature, BadSignature) => true,
1265 (
1266 UnsupportedSignatureAlgorithm {
1267 signature_algorithm_id: left_signature_algorithm_id,
1268 supported_algorithms: left_supported_algorithms,
1269 },
1270 UnsupportedSignatureAlgorithm {
1271 signature_algorithm_id: right_signature_algorithm_id,
1272 supported_algorithms: right_supported_algorithms,
1273 },
1274 ) => {
1275 (left_signature_algorithm_id, left_supported_algorithms)
1276 == (right_signature_algorithm_id, right_supported_algorithms)
1277 }
1278 (
1279 UnsupportedSignatureAlgorithmForPublicKey {
1280 signature_algorithm_id: left_signature_algorithm_id,
1281 public_key_algorithm_id: left_public_key_algorithm_id,
1282 },
1283 UnsupportedSignatureAlgorithmForPublicKey {
1284 signature_algorithm_id: right_signature_algorithm_id,
1285 public_key_algorithm_id: right_public_key_algorithm_id,
1286 },
1287 ) => {
1288 (left_signature_algorithm_id, left_public_key_algorithm_id)
1289 == (right_signature_algorithm_id, right_public_key_algorithm_id)
1290 }
1291 (InvalidCrlNumber, InvalidCrlNumber) => true,
1292 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
1293 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
1294 (ParseError, ParseError) => true,
1295 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
1296 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
1297 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
1298 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
1299 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
1300 _ => false,
1301 }
1302 }
1303}
1304
1305#[non_exhaustive]
1307#[derive(Debug, Clone, Eq, PartialEq)]
1308pub enum EncryptedClientHelloError {
1309 InvalidConfigList,
1311 NoCompatibleConfig,
1313 SniRequired,
1315}
1316
1317#[non_exhaustive]
1323#[derive(Debug, Clone, PartialEq)]
1324pub struct RejectedEch {
1325 pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
1326}
1327
1328impl RejectedEch {
1329 pub fn can_retry(&self) -> bool {
1335 self.retry_configs.is_some()
1336 }
1337
1338 pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
1340 let Some(retry_configs) = &self.retry_configs else {
1341 return None;
1342 };
1343
1344 let mut tls_encoded_list = Vec::new();
1345 retry_configs.encode(&mut tls_encoded_list);
1346
1347 Some(EchConfigListBytes::from(tls_encoded_list))
1348 }
1349}
1350
1351fn join<T: fmt::Debug>(items: &[T]) -> String {
1352 items
1353 .iter()
1354 .map(|x| format!("{x:?}"))
1355 .collect::<Vec<String>>()
1356 .join(" or ")
1357}
1358
1359#[non_exhaustive]
1363#[derive(Debug, Clone, PartialEq)]
1364pub enum ApiMisuse {
1365 ResumingFromUnknownCipherSuite(CipherSuite),
1367
1368 ExporterAlreadyUsed,
1376
1377 ExporterContextTooLong,
1383
1384 ExporterOutputTooLong,
1390
1391 ExporterOutputZeroLength,
1398
1399 AcceptorPolledAfterCompletion,
1405
1406 InvalidQuicHeaderProtectionSampleLength,
1410
1411 InvalidQuicHeaderProtectionPacketNumberLength,
1416
1417 InvalidSignerForProtocolVersion,
1419
1420 QuicRequiresTls13Support,
1422
1423 NoQuicCompatibleCipherSuites,
1425
1426 EmptyCertificateChain,
1428
1429 QuicRestrictsMaxEarlyDataSize,
1435
1436 NoCipherSuitesConfigured,
1438
1439 NoKeyExchangeGroupsConfigured,
1441
1442 NoSignatureVerificationAlgorithms,
1444
1445 EchRequiresTls13Support,
1447
1448 EchForbidsTls12Support,
1450
1451 SecretExtractionRequiresPriorOptIn,
1459
1460 SecretExtractionWithPendingSendableData,
1467
1468 UnverifiableCertificateType,
1473
1474 NoSupportedCertificateTypes,
1476
1477 NonceArraySizeMismatch {
1483 expected: usize,
1485 actual: usize,
1487 },
1488
1489 IvLengthExceedsMaximum {
1496 actual: usize,
1498 maximum: usize,
1500 },
1501
1502 ResumptionDataProvidedTooLate,
1507
1508 KeyUpdateNotAvailableForTls12,
1512}
1513
1514impl fmt::Display for ApiMisuse {
1515 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1516 write!(f, "{self:?}")
1517 }
1518}
1519
1520impl core::error::Error for ApiMisuse {}
1521
1522mod other_error {
1523 use core::error::Error as StdError;
1524 use core::fmt;
1525
1526 use crate::sync::Arc;
1527
1528 #[derive(Debug, Clone)]
1536 pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1537
1538 impl OtherError {
1539 pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1541 Self(Arc::new(err))
1542 }
1543 }
1544
1545 impl PartialEq<Self> for OtherError {
1546 fn eq(&self, _other: &Self) -> bool {
1547 false
1548 }
1549 }
1550
1551 impl fmt::Display for OtherError {
1552 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1553 write!(f, "{}", self.0)
1554 }
1555 }
1556
1557 impl StdError for OtherError {
1558 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1559 Some(self.0.as_ref())
1560 }
1561 }
1562}
1563
1564pub use other_error::OtherError;
1565
1566pub struct ErrorWithAlert {
1569 pub error: Error,
1571 pub(crate) data: Vec<u8>,
1572}
1573
1574impl ErrorWithAlert {
1575 pub(crate) fn new(error: Error, send_path: &mut SendPath) -> Self {
1576 maybe_send_fatal_alert(send_path, &error);
1577 Self {
1578 error,
1579 data: send_path.sendable_tls.take_one_vec(),
1580 }
1581 }
1582
1583 pub fn take_tls_data(&mut self) -> Option<Vec<u8>> {
1587 match self.data.is_empty() {
1588 true => None,
1589 false => Some(mem::take(&mut self.data)),
1590 }
1591 }
1592}
1593
1594impl Deref for ErrorWithAlert {
1595 type Target = Error;
1596
1597 fn deref(&self) -> &Self::Target {
1598 &self.error
1599 }
1600}
1601
1602impl From<Error> for ErrorWithAlert {
1604 fn from(error: Error) -> Self {
1605 Self {
1606 error,
1607 data: Vec::new(),
1608 }
1609 }
1610}
1611
1612impl fmt::Debug for ErrorWithAlert {
1613 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1614 f.debug_struct("ErrorWithAlert")
1615 .field("error", &self.error)
1616 .field("data", &self.data.len())
1617 .finish_non_exhaustive()
1618 }
1619}