1use alloc::format;
4use alloc::string::String;
5use alloc::vec::Vec;
6use core::fmt;
7#[cfg(feature = "std")]
8use std::time::SystemTimeError;
9
10use pki_types::{AlgorithmIdentifier, EchConfigListBytes, ServerName, UnixTime};
11use webpki::ExtendedKeyUsage;
12
13use crate::crypto::kx::KeyExchangeAlgorithm;
14use crate::crypto::{GetRandomFailed, InconsistentKeys};
15use crate::enums::{ContentType, HandshakeType};
16use crate::msgs::codec::Codec;
17use crate::msgs::handshake::EchConfigPayload;
18
19#[cfg(test)]
20mod tests;
21
22#[non_exhaustive]
24#[derive(Debug, PartialEq, Clone)]
25pub enum Error {
26 InappropriateMessage {
32 expect_types: Vec<ContentType>,
34 got_type: ContentType,
36 },
37
38 InappropriateHandshakeMessage {
42 expect_types: Vec<HandshakeType>,
44 got_type: HandshakeType,
46 },
47
48 InvalidEncryptedClientHello(EncryptedClientHelloError),
50
51 InvalidMessage(InvalidMessage),
53
54 UnsupportedNameType,
56
57 DecryptError,
59
60 EncryptError,
63
64 PeerIncompatible(PeerIncompatible),
67
68 PeerMisbehaved(PeerMisbehaved),
71
72 AlertReceived(AlertDescription),
74
75 InvalidCertificate(CertificateError),
80
81 InvalidCertRevocationList(CertRevocationListError),
83
84 General(String),
86
87 FailedToGetCurrentTime,
89
90 FailedToGetRandomBytes,
92
93 HandshakeNotComplete,
96
97 PeerSentOversizedRecord,
99
100 NoApplicationProtocol,
102
103 NoSuitableCertificate,
105
106 BadMaxFragmentSize,
109
110 InconsistentKeys(InconsistentKeys),
120
121 RejectedEch(RejectedEch),
128
129 Unreachable(&'static str),
133
134 ApiMisuse(ApiMisuse),
146
147 Other(OtherError),
155}
156
157impl TryFrom<&Error> for AlertDescription {
161 type Error = ();
162
163 fn try_from(error: &Error) -> Result<Self, Self::Error> {
164 Ok(match error {
165 Error::DecryptError => Self::BadRecordMac,
166 Error::InappropriateMessage { .. } | Error::InappropriateHandshakeMessage { .. } => {
167 Self::UnexpectedMessage
168 }
169 Error::InvalidCertificate(e) => Self::from(e),
170 Error::InvalidMessage(e) => Self::from(*e),
171 Error::NoApplicationProtocol => Self::NoApplicationProtocol,
172 Error::PeerMisbehaved(e) => Self::from(*e),
173 Error::PeerIncompatible(e) => Self::from(*e),
174 Error::PeerSentOversizedRecord => Self::RecordOverflow,
175 Error::RejectedEch(_) => Self::EncryptedClientHelloRequired,
176
177 _ => return Err(()),
178 })
179 }
180}
181
182impl fmt::Display for Error {
183 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
184 match self {
185 Self::InappropriateMessage {
186 expect_types,
187 got_type,
188 } => write!(
189 f,
190 "received unexpected message: got {:?} when expecting {}",
191 got_type,
192 join::<ContentType>(expect_types)
193 ),
194 Self::InappropriateHandshakeMessage {
195 expect_types,
196 got_type,
197 } => write!(
198 f,
199 "received unexpected handshake message: got {:?} when expecting {}",
200 got_type,
201 join::<HandshakeType>(expect_types)
202 ),
203 Self::InvalidMessage(typ) => {
204 write!(f, "received corrupt message of type {typ:?}")
205 }
206 Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
207 Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
208 Self::AlertReceived(alert) => write!(f, "received fatal alert: the peer {alert}"),
209 Self::InvalidCertificate(err) => {
210 write!(f, "invalid peer certificate: {err}")
211 }
212 Self::InvalidCertRevocationList(err) => {
213 write!(f, "invalid certificate revocation list: {err:?}")
214 }
215 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
216 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
217 Self::InvalidEncryptedClientHello(err) => {
218 write!(f, "encrypted client hello failure: {err:?}")
219 }
220 Self::EncryptError => write!(f, "cannot encrypt message"),
221 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
222 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
223 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
224 Self::NoSuitableCertificate => write!(f, "no suitable certificate found"),
225 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
226 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
227 Self::BadMaxFragmentSize => {
228 write!(f, "the supplied max_fragment_size was too small or large")
229 }
230 Self::InconsistentKeys(why) => {
231 write!(f, "keys may not be consistent: {why:?}")
232 }
233 Self::RejectedEch(why) => {
234 write!(
235 f,
236 "server rejected encrypted client hello (ECH) {} retry configs",
237 if why.can_retry() { "with" } else { "without" }
238 )
239 }
240 Self::General(err) => write!(f, "unexpected error: {err}"),
241 Self::Unreachable(err) => write!(
242 f,
243 "unreachable condition: {err} (please file a bug in rustls)"
244 ),
245 Self::ApiMisuse(why) => write!(f, "API misuse: {why:?}"),
246 Self::Other(err) => write!(f, "other error: {err}"),
247 }
248 }
249}
250
251impl From<CertificateError> for Error {
252 #[inline]
253 fn from(e: CertificateError) -> Self {
254 Self::InvalidCertificate(e)
255 }
256}
257
258impl From<InvalidMessage> for Error {
259 #[inline]
260 fn from(e: InvalidMessage) -> Self {
261 Self::InvalidMessage(e)
262 }
263}
264
265impl From<PeerMisbehaved> for Error {
266 #[inline]
267 fn from(e: PeerMisbehaved) -> Self {
268 Self::PeerMisbehaved(e)
269 }
270}
271
272impl From<PeerIncompatible> for Error {
273 #[inline]
274 fn from(e: PeerIncompatible) -> Self {
275 Self::PeerIncompatible(e)
276 }
277}
278
279impl From<CertRevocationListError> for Error {
280 #[inline]
281 fn from(e: CertRevocationListError) -> Self {
282 Self::InvalidCertRevocationList(e)
283 }
284}
285
286impl From<EncryptedClientHelloError> for Error {
287 #[inline]
288 fn from(e: EncryptedClientHelloError) -> Self {
289 Self::InvalidEncryptedClientHello(e)
290 }
291}
292
293impl From<RejectedEch> for Error {
294 fn from(rejected_error: RejectedEch) -> Self {
295 Self::RejectedEch(rejected_error)
296 }
297}
298
299impl From<ApiMisuse> for Error {
300 fn from(e: ApiMisuse) -> Self {
301 Self::ApiMisuse(e)
302 }
303}
304
305impl From<OtherError> for Error {
306 fn from(value: OtherError) -> Self {
307 Self::Other(value)
308 }
309}
310
311impl From<InconsistentKeys> for Error {
312 #[inline]
313 fn from(e: InconsistentKeys) -> Self {
314 Self::InconsistentKeys(e)
315 }
316}
317
318#[cfg(feature = "std")]
319impl From<SystemTimeError> for Error {
320 #[inline]
321 fn from(_: SystemTimeError) -> Self {
322 Self::FailedToGetCurrentTime
323 }
324}
325
326impl From<GetRandomFailed> for Error {
327 fn from(_: GetRandomFailed) -> Self {
328 Self::FailedToGetRandomBytes
329 }
330}
331
332impl core::error::Error for Error {}
333
334#[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 #[cfg(feature = "std")]
624 Self::NotValidForNameContext {
625 expected,
626 presented,
627 } => {
628 write!(
629 f,
630 "certificate not valid for name {:?}; certificate ",
631 expected.to_str()
632 )?;
633
634 match presented.as_slice() {
635 &[] => write!(
636 f,
637 "is not valid for any names (according to its subjectAltName extension)"
638 ),
639 [one] => write!(f, "is only valid for {one}"),
640 many => {
641 write!(f, "is only valid for ")?;
642
643 let n = many.len();
644 let all_but_last = &many[..n - 1];
645 let last = &many[n - 1];
646
647 for (i, name) in all_but_last.iter().enumerate() {
648 write!(f, "{name}")?;
649 if i < n - 2 {
650 write!(f, ", ")?;
651 }
652 }
653 write!(f, " or {last}")
654 }
655 }
656 }
657
658 Self::ExpiredContext { time, not_after } => write!(
659 f,
660 "certificate expired: verification time {} (UNIX), \
661 but certificate is not valid after {} \
662 ({} seconds ago)",
663 time.as_secs(),
664 not_after.as_secs(),
665 time.as_secs()
666 .saturating_sub(not_after.as_secs())
667 ),
668
669 Self::NotValidYetContext { time, not_before } => write!(
670 f,
671 "certificate not valid yet: verification time {} (UNIX), \
672 but certificate is not valid before {} \
673 ({} seconds in future)",
674 time.as_secs(),
675 not_before.as_secs(),
676 not_before
677 .as_secs()
678 .saturating_sub(time.as_secs())
679 ),
680
681 Self::ExpiredRevocationListContext { time, next_update } => write!(
682 f,
683 "certificate revocation list expired: \
684 verification time {} (UNIX), \
685 but CRL is not valid after {} \
686 ({} seconds ago)",
687 time.as_secs(),
688 next_update.as_secs(),
689 time.as_secs()
690 .saturating_sub(next_update.as_secs())
691 ),
692
693 Self::InvalidPurposeContext {
694 required,
695 presented,
696 } => {
697 write!(
698 f,
699 "certificate does not allow extended key usage for {required}, allows "
700 )?;
701 for (i, eku) in presented.iter().enumerate() {
702 if i > 0 {
703 write!(f, ", ")?;
704 }
705 write!(f, "{eku}")?;
706 }
707 Ok(())
708 }
709
710 Self::Other(other) => write!(f, "{other}"),
711
712 other => write!(f, "{other:?}"),
713 }
714 }
715}
716
717enum_builder! {
718 #[repr(u8)]
722 pub enum AlertDescription {
723 CloseNotify => 0x00,
724 UnexpectedMessage => 0x0a,
725 BadRecordMac => 0x14,
726 DecryptionFailed => 0x15,
727 RecordOverflow => 0x16,
728 DecompressionFailure => 0x1e,
729 HandshakeFailure => 0x28,
730 NoCertificate => 0x29,
731 BadCertificate => 0x2a,
732 UnsupportedCertificate => 0x2b,
733 CertificateRevoked => 0x2c,
734 CertificateExpired => 0x2d,
735 CertificateUnknown => 0x2e,
736 IllegalParameter => 0x2f,
737 UnknownCa => 0x30,
738 AccessDenied => 0x31,
739 DecodeError => 0x32,
740 DecryptError => 0x33,
741 ExportRestriction => 0x3c,
742 ProtocolVersion => 0x46,
743 InsufficientSecurity => 0x47,
744 InternalError => 0x50,
745 InappropriateFallback => 0x56,
746 UserCanceled => 0x5a,
747 NoRenegotiation => 0x64,
748 MissingExtension => 0x6d,
749 UnsupportedExtension => 0x6e,
750 CertificateUnobtainable => 0x6f,
751 UnrecognizedName => 0x70,
752 BadCertificateStatusResponse => 0x71,
753 BadCertificateHashValue => 0x72,
754 UnknownPskIdentity => 0x73,
755 CertificateRequired => 0x74,
756 NoApplicationProtocol => 0x78,
757 EncryptedClientHelloRequired => 0x79, }
759}
760
761impl fmt::Display for AlertDescription {
762 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
763 match self {
768 Self::CloseNotify => write!(f, "cleanly closed the connection"),
770
771 Self::UnexpectedMessage => write!(f, "received an unexpected message"),
774 Self::BadRecordMac => write!(f, "failed to verify a message"),
775 Self::RecordOverflow => write!(f, "rejected an over-length message"),
776 Self::IllegalParameter => write!(
777 f,
778 "rejected a message because a field was incorrect or inconsistent"
779 ),
780 Self::DecodeError => write!(f, "failed to decode a message"),
781 Self::DecryptError => {
782 write!(f, "failed to perform a handshake cryptographic operation")
783 }
784 Self::InappropriateFallback => {
785 write!(f, "detected an attempted version downgrade")
786 }
787 Self::MissingExtension => {
788 write!(f, "required a specific extension that was not provided")
789 }
790 Self::UnsupportedExtension => write!(f, "rejected an unsolicited extension"),
791
792 Self::DecryptionFailed => write!(f, "failed to decrypt a message"),
795 Self::DecompressionFailure => write!(f, "failed to decompress a message"),
796 Self::NoCertificate => write!(f, "found no certificate"),
797 Self::ExportRestriction => write!(f, "refused due to export restrictions"),
798 Self::NoRenegotiation => write!(f, "rejected an attempt at renegotiation"),
799 Self::CertificateUnobtainable => {
800 write!(f, "failed to retrieve its certificate")
801 }
802 Self::BadCertificateHashValue => {
803 write!(f, "rejected the `certificate_hash` extension")
804 }
805
806 Self::HandshakeFailure => write!(
810 f,
811 "failed to negotiate an acceptable set of security parameters"
812 ),
813 Self::ProtocolVersion => write!(f, "did not support a suitable TLS version"),
814 Self::InsufficientSecurity => {
815 write!(f, "required a higher security level than was offered")
816 }
817
818 Self::BadCertificate => {
821 write!(
822 f,
823 "rejected the certificate as corrupt or incorrectly signed"
824 )
825 }
826 Self::UnsupportedCertificate => {
827 write!(f, "did not support the certificate")
828 }
829 Self::CertificateRevoked => write!(f, "found the certificate to be revoked"),
830 Self::CertificateExpired => write!(f, "found the certificate to be expired"),
831 Self::CertificateUnknown => {
832 write!(f, "rejected the certificate for an unspecified reason")
833 }
834 Self::UnknownCa => write!(f, "found the certificate was not issued by a trusted CA"),
835 Self::BadCertificateStatusResponse => {
836 write!(f, "rejected the certificate status response")
837 }
838 Self::AccessDenied => write!(f, "denied access"),
840 Self::CertificateRequired => write!(f, "required a client certificate"),
842
843 Self::InternalError => write!(f, "encountered an internal error"),
844 Self::UserCanceled => write!(f, "canceled the handshake"),
845
846 Self::UnrecognizedName => {
848 write!(f, "did not recognize a name in the `server_name` extension")
849 }
850
851 Self::UnknownPskIdentity => {
854 write!(f, "did not recognize any offered PSK identity")
855 }
856
857 Self::NoApplicationProtocol => write!(
860 f,
861 "did not support any of the offered application protocols"
862 ),
863
864 Self::EncryptedClientHelloRequired => {
867 write!(f, "required use of encrypted client hello")
868 }
869
870 Self::Unknown(n) => write!(f, "sent an unknown alert (0x{n:02x?})"),
871 }
872 }
873}
874
875#[non_exhaustive]
877#[derive(Debug, Clone, Copy, PartialEq)]
878pub enum InvalidMessage {
879 CertificatePayloadTooLarge,
881 HandshakePayloadTooLarge,
883 InvalidCcs,
885 InvalidContentType,
887 InvalidCertificateStatusType,
889 InvalidCertRequest,
891 InvalidDhParams,
893 InvalidEmptyPayload,
895 InvalidKeyUpdate,
897 InvalidServerName,
899 MessageTooLarge,
901 MessageTooShort,
903 MissingData(&'static str),
905 MissingKeyExchange,
907 NoSignatureSchemes,
909 TrailingData(&'static str),
911 UnexpectedMessage(&'static str),
913 UnknownProtocolVersion,
915 UnsupportedCompression,
917 UnsupportedCurveType,
919 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
921 EmptyTicketValue,
923 IllegalEmptyList(&'static str),
927 IllegalEmptyValue,
929 DuplicateExtension(u16),
931 PreSharedKeyIsNotFinalExtension,
933 UnknownHelloRetryRequestExtension,
935 UnknownCertificateExtension,
937}
938
939impl From<InvalidMessage> for AlertDescription {
940 fn from(e: InvalidMessage) -> Self {
941 match e {
942 InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
943 InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
944 InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
945 InvalidMessage::CertificatePayloadTooLarge => Self::BadCertificate,
946 _ => Self::DecodeError,
947 }
948 }
949}
950
951#[expect(missing_docs)]
962#[non_exhaustive]
963#[derive(Clone, Copy, Debug, PartialEq)]
964pub enum PeerMisbehaved {
965 AttemptedDowngradeToTls12WhenTls13IsSupported,
966 BadCertChainExtensions,
967 DisallowedEncryptedExtension,
968 DuplicateClientHelloExtensions,
969 DuplicateEncryptedExtensions,
970 DuplicateHelloRetryRequestExtensions,
971 DuplicateNewSessionTicketExtensions,
972 DuplicateServerHelloExtensions,
973 DuplicateServerNameTypes,
974 EarlyDataAttemptedInSecondClientHello,
975 EarlyDataExtensionWithoutResumption,
976 EarlyDataOfferedWithVariedCipherSuite,
977 HandshakeHashVariedAfterRetry,
978 IllegalAlertLevel(u8, AlertDescription),
980 IllegalHelloRetryRequestWithEmptyCookie,
981 IllegalHelloRetryRequestWithNoChanges,
982 IllegalHelloRetryRequestWithOfferedGroup,
983 IllegalHelloRetryRequestWithUnofferedCipherSuite,
984 IllegalHelloRetryRequestWithUnofferedNamedGroup,
985 IllegalHelloRetryRequestWithUnsupportedVersion,
986 IllegalHelloRetryRequestWithWrongSessionId,
987 IllegalHelloRetryRequestWithInvalidEch,
988 IllegalMiddleboxChangeCipherSpec,
989 IllegalTlsInnerPlaintext,
990 IllegalWarningAlert(AlertDescription),
992 IncorrectBinder,
993 IncorrectFinished,
994 InvalidCertCompression,
995 InvalidMaxEarlyDataSize,
996 InvalidKeyShare,
997 KeyEpochWithPendingFragment,
998 KeyUpdateReceivedInQuicConnection,
999 MessageInterleavedWithHandshakeMessage,
1000 MissingBinderInPskExtension,
1001 MissingKeyShare,
1002 MissingPskModesExtension,
1003 MissingQuicTransportParameters,
1004 NoCertificatesPresented,
1005 OfferedDuplicateCertificateCompressions,
1006 OfferedDuplicateKeyShares,
1007 OfferedEarlyDataWithOldProtocolVersion,
1008 OfferedEmptyApplicationProtocol,
1009 OfferedIncorrectCompressions,
1010 PskExtensionMustBeLast,
1011 PskExtensionWithMismatchedIdsAndBinders,
1012 RefusedToFollowHelloRetryRequest,
1013 RejectedEarlyDataInterleavedWithHandshakeMessage,
1014 ResumptionAttemptedWithVariedEms,
1015 ResumptionOfferedWithVariedCipherSuite,
1016 ResumptionOfferedWithVariedEms,
1017 ResumptionOfferedWithIncompatibleCipherSuite,
1018 SelectedDifferentCipherSuiteAfterRetry,
1019 SelectedInvalidPsk,
1020 SelectedTls12UsingTls13VersionExtension,
1021 SelectedUnofferedApplicationProtocol,
1022 SelectedUnofferedCertCompression,
1023 SelectedUnofferedCipherSuite,
1024 SelectedUnofferedCompression,
1025 SelectedUnofferedKxGroup,
1026 SelectedUnofferedPsk,
1027 ServerEchoedCompatibilitySessionId,
1028 ServerHelloMustOfferUncompressedEcPoints,
1029 ServerNameDifferedOnRetry,
1030 ServerNameMustContainOneHostName,
1031 SignedKxWithWrongAlgorithm,
1032 SignedHandshakeWithUnadvertisedSigScheme,
1033 TooManyEmptyFragments,
1034 TooManyKeyUpdateRequests,
1035 TooManyRenegotiationRequests,
1036 TooManyWarningAlertsReceived,
1037 TooMuchEarlyDataReceived,
1038 UnexpectedCleartextExtension,
1039 UnsolicitedCertExtension,
1040 UnsolicitedEncryptedExtension,
1041 UnsolicitedSctList,
1042 UnsolicitedServerHelloExtension,
1043 WrongGroupForKeyShare,
1044 UnsolicitedEchExtension,
1045}
1046
1047impl From<PeerMisbehaved> for AlertDescription {
1048 fn from(e: PeerMisbehaved) -> Self {
1049 match e {
1050 PeerMisbehaved::DisallowedEncryptedExtension
1051 | PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch
1052 | PeerMisbehaved::UnexpectedCleartextExtension
1053 | PeerMisbehaved::UnsolicitedEchExtension
1054 | PeerMisbehaved::UnsolicitedEncryptedExtension
1055 | PeerMisbehaved::UnsolicitedServerHelloExtension => Self::UnsupportedExtension,
1056
1057 PeerMisbehaved::IllegalMiddleboxChangeCipherSpec
1058 | PeerMisbehaved::KeyEpochWithPendingFragment
1059 | PeerMisbehaved::KeyUpdateReceivedInQuicConnection => Self::UnexpectedMessage,
1060
1061 PeerMisbehaved::IllegalWarningAlert(_) => Self::DecodeError,
1062
1063 PeerMisbehaved::IncorrectBinder | PeerMisbehaved::IncorrectFinished => {
1064 Self::DecryptError
1065 }
1066
1067 PeerMisbehaved::InvalidCertCompression
1068 | PeerMisbehaved::SelectedUnofferedCertCompression => Self::BadCertificate,
1069
1070 PeerMisbehaved::MissingKeyShare
1071 | PeerMisbehaved::MissingPskModesExtension
1072 | PeerMisbehaved::MissingQuicTransportParameters => Self::MissingExtension,
1073
1074 PeerMisbehaved::NoCertificatesPresented => Self::CertificateRequired,
1075
1076 _ => Self::IllegalParameter,
1077 }
1078 }
1079}
1080
1081#[expect(missing_docs)]
1087#[non_exhaustive]
1088#[derive(Clone, Copy, Debug, PartialEq)]
1089pub enum PeerIncompatible {
1090 EcPointsExtensionRequired,
1091 ExtendedMasterSecretExtensionRequired,
1092 IncorrectCertificateTypeExtension,
1093 KeyShareExtensionRequired,
1094 MultipleRawKeys,
1095 NamedGroupsExtensionRequired,
1096 NoCertificateRequestSignatureSchemesInCommon,
1097 NoCipherSuitesInCommon,
1098 NoEcPointFormatsInCommon,
1099 NoKxGroupsInCommon,
1100 NoSignatureSchemesInCommon,
1101 NoServerNameProvided,
1102 NullCompressionRequired,
1103 ServerDoesNotSupportTls12Or13,
1104 ServerSentHelloRetryRequestWithUnknownExtension,
1105 ServerTlsVersionIsDisabledByOurConfig,
1106 SignatureAlgorithmsExtensionRequired,
1107 SupportedVersionsExtensionRequired,
1108 Tls12NotOffered,
1109 Tls12NotOfferedOrEnabled,
1110 Tls13RequiredForQuic,
1111 UncompressedEcPointsRequired,
1112 UnknownCertificateType(u8),
1113 UnsolicitedCertificateTypeExtension,
1114}
1115
1116impl From<PeerIncompatible> for AlertDescription {
1117 fn from(e: PeerIncompatible) -> Self {
1118 match e {
1119 PeerIncompatible::NullCompressionRequired => Self::IllegalParameter,
1120
1121 PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig
1122 | PeerIncompatible::SupportedVersionsExtensionRequired
1123 | PeerIncompatible::Tls12NotOffered
1124 | PeerIncompatible::Tls12NotOfferedOrEnabled
1125 | PeerIncompatible::Tls13RequiredForQuic => Self::ProtocolVersion,
1126
1127 PeerIncompatible::UnknownCertificateType(_) => Self::UnsupportedCertificate,
1128
1129 _ => Self::HandshakeFailure,
1130 }
1131 }
1132}
1133
1134#[non_exhaustive]
1139#[derive(Clone, Debug, Eq, PartialEq)]
1140pub enum ExtendedKeyPurpose {
1141 ClientAuth,
1143 ServerAuth,
1145 Other(Vec<usize>),
1149}
1150
1151impl ExtendedKeyPurpose {
1152 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
1153 let values = values.collect::<Vec<_>>();
1154 match &*values {
1155 ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
1156 ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
1157 _ => Self::Other(values),
1158 }
1159 }
1160}
1161
1162impl fmt::Display for ExtendedKeyPurpose {
1163 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1164 match self {
1165 Self::ClientAuth => write!(f, "client authentication"),
1166 Self::ServerAuth => write!(f, "server authentication"),
1167 Self::Other(values) => {
1168 for (i, value) in values.iter().enumerate() {
1169 if i > 0 {
1170 write!(f, ", ")?;
1171 }
1172 write!(f, "{value}")?;
1173 }
1174 Ok(())
1175 }
1176 }
1177 }
1178}
1179
1180#[non_exhaustive]
1182#[derive(Debug, Clone)]
1183pub enum CertRevocationListError {
1184 BadSignature,
1186
1187 UnsupportedSignatureAlgorithm {
1189 signature_algorithm_id: Vec<u8>,
1191 supported_algorithms: Vec<AlgorithmIdentifier>,
1193 },
1194
1195 UnsupportedSignatureAlgorithmForPublicKey {
1197 signature_algorithm_id: Vec<u8>,
1199 public_key_algorithm_id: Vec<u8>,
1201 },
1202
1203 InvalidCrlNumber,
1205
1206 InvalidRevokedCertSerialNumber,
1208
1209 IssuerInvalidForCrl,
1211
1212 Other(OtherError),
1216
1217 ParseError,
1219
1220 UnsupportedCrlVersion,
1222
1223 UnsupportedCriticalExtension,
1225
1226 UnsupportedDeltaCrl,
1228
1229 UnsupportedIndirectCrl,
1232
1233 UnsupportedRevocationReason,
1238}
1239
1240impl PartialEq<Self> for CertRevocationListError {
1241 fn eq(&self, other: &Self) -> bool {
1242 use CertRevocationListError::*;
1243 match (self, other) {
1244 (BadSignature, BadSignature) => true,
1245 (
1246 UnsupportedSignatureAlgorithm {
1247 signature_algorithm_id: left_signature_algorithm_id,
1248 supported_algorithms: left_supported_algorithms,
1249 },
1250 UnsupportedSignatureAlgorithm {
1251 signature_algorithm_id: right_signature_algorithm_id,
1252 supported_algorithms: right_supported_algorithms,
1253 },
1254 ) => {
1255 (left_signature_algorithm_id, left_supported_algorithms)
1256 == (right_signature_algorithm_id, right_supported_algorithms)
1257 }
1258 (
1259 UnsupportedSignatureAlgorithmForPublicKey {
1260 signature_algorithm_id: left_signature_algorithm_id,
1261 public_key_algorithm_id: left_public_key_algorithm_id,
1262 },
1263 UnsupportedSignatureAlgorithmForPublicKey {
1264 signature_algorithm_id: right_signature_algorithm_id,
1265 public_key_algorithm_id: right_public_key_algorithm_id,
1266 },
1267 ) => {
1268 (left_signature_algorithm_id, left_public_key_algorithm_id)
1269 == (right_signature_algorithm_id, right_public_key_algorithm_id)
1270 }
1271 (InvalidCrlNumber, InvalidCrlNumber) => true,
1272 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
1273 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
1274 (ParseError, ParseError) => true,
1275 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
1276 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
1277 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
1278 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
1279 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
1280 _ => false,
1281 }
1282 }
1283}
1284
1285#[non_exhaustive]
1287#[derive(Debug, Clone, Eq, PartialEq)]
1288pub enum EncryptedClientHelloError {
1289 InvalidConfigList,
1291 NoCompatibleConfig,
1293 SniRequired,
1295}
1296
1297#[non_exhaustive]
1303#[derive(Debug, Clone, PartialEq)]
1304pub struct RejectedEch {
1305 pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
1306}
1307
1308impl RejectedEch {
1309 pub fn can_retry(&self) -> bool {
1315 self.retry_configs.is_some()
1316 }
1317
1318 pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
1320 let Some(retry_configs) = &self.retry_configs else {
1321 return None;
1322 };
1323
1324 let mut tls_encoded_list = Vec::new();
1325 retry_configs.encode(&mut tls_encoded_list);
1326
1327 Some(EchConfigListBytes::from(tls_encoded_list))
1328 }
1329}
1330
1331fn join<T: fmt::Debug>(items: &[T]) -> String {
1332 items
1333 .iter()
1334 .map(|x| format!("{x:?}"))
1335 .collect::<Vec<String>>()
1336 .join(" or ")
1337}
1338
1339#[non_exhaustive]
1343#[derive(Debug, Clone, PartialEq)]
1344pub enum ApiMisuse {
1345 ExporterAlreadyUsed,
1353
1354 ExporterContextTooLong,
1360
1361 ExporterOutputTooLong,
1367
1368 ExporterOutputZeroLength,
1375
1376 AcceptorPolledAfterCompletion,
1380
1381 InvalidQuicHeaderProtectionSampleLength,
1385
1386 InvalidQuicHeaderProtectionPacketNumberLength,
1391
1392 InvalidSignerForProtocolVersion,
1394
1395 QuicRequiresTls13Support,
1397
1398 NoQuicCompatibleCipherSuites,
1400
1401 EmptyCertificateChain,
1403
1404 QuicRestrictsMaxEarlyDataSize,
1410
1411 NoCipherSuitesConfigured,
1413
1414 NoKeyExchangeGroupsConfigured,
1416
1417 NoSignatureVerificationAlgorithms,
1419
1420 EchRequiresTls13Support,
1422
1423 EchForbidsTls12Support,
1425
1426 SecretExtractionRequiresPriorOptIn,
1439
1440 SecretExtractionWithPendingSendableData,
1447
1448 UnverifiableCertificateType,
1453
1454 NoSupportedCertificateTypes,
1456
1457 NonceArraySizeMismatch {
1463 expected: usize,
1465 actual: usize,
1467 },
1468
1469 IvLengthExceedsMaximum {
1476 actual: usize,
1478 maximum: usize,
1480 },
1481}
1482
1483impl fmt::Display for ApiMisuse {
1484 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1485 write!(f, "{self:?}")
1486 }
1487}
1488
1489impl core::error::Error for ApiMisuse {}
1490
1491mod other_error {
1492 use core::error::Error as StdError;
1493 use core::fmt;
1494
1495 use crate::sync::Arc;
1496
1497 #[derive(Debug, Clone)]
1505 pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1506
1507 impl OtherError {
1508 pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1510 Self(Arc::new(err))
1511 }
1512 }
1513
1514 impl PartialEq<Self> for OtherError {
1515 fn eq(&self, _other: &Self) -> bool {
1516 false
1517 }
1518 }
1519
1520 impl fmt::Display for OtherError {
1521 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1522 #[cfg(feature = "std")]
1523 {
1524 write!(f, "{}", self.0)
1525 }
1526 #[cfg(not(feature = "std"))]
1527 {
1528 f.write_str("no further information available")
1529 }
1530 }
1531 }
1532
1533 impl StdError for OtherError {
1534 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1535 Some(self.0.as_ref())
1536 }
1537 }
1538}
1539
1540pub use other_error::OtherError;