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};
11#[cfg(feature = "webpki")]
12use webpki::ExtendedKeyUsage;
13
14use crate::crypto::kx::KeyExchangeAlgorithm;
15use crate::crypto::{GetRandomFailed, InconsistentKeys};
16use crate::enums::{ContentType, HandshakeType};
17use crate::msgs::{Codec, 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 DuplicateExtension(u16),
929 PreSharedKeyIsNotFinalExtension,
931 UnknownHelloRetryRequestExtension,
933 UnknownCertificateExtension,
935}
936
937impl From<InvalidMessage> for AlertDescription {
938 fn from(e: InvalidMessage) -> Self {
939 match e {
940 InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
941 InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
942 InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
943 InvalidMessage::CertificatePayloadTooLarge => Self::BadCertificate,
944 _ => Self::DecodeError,
945 }
946 }
947}
948
949#[expect(missing_docs)]
960#[non_exhaustive]
961#[derive(Clone, Copy, Debug, PartialEq)]
962pub enum PeerMisbehaved {
963 AttemptedDowngradeToTls12WhenTls13IsSupported,
964 BadCertChainExtensions,
965 DisallowedEncryptedExtension,
966 DuplicateClientHelloExtensions,
967 DuplicateEncryptedExtensions,
968 DuplicateHelloRetryRequestExtensions,
969 DuplicateNewSessionTicketExtensions,
970 DuplicateServerHelloExtensions,
971 DuplicateServerNameTypes,
972 EarlyDataAttemptedInSecondClientHello,
973 EarlyDataExtensionWithoutResumption,
974 EarlyDataOfferedWithVariedCipherSuite,
975 HandshakeHashVariedAfterRetry,
976 IllegalAlertLevel(u8, AlertDescription),
978 IllegalHelloRetryRequestWithEmptyCookie,
979 IllegalHelloRetryRequestWithNoChanges,
980 IllegalHelloRetryRequestWithOfferedGroup,
981 IllegalHelloRetryRequestWithUnofferedCipherSuite,
982 IllegalHelloRetryRequestWithUnofferedNamedGroup,
983 IllegalHelloRetryRequestWithUnsupportedVersion,
984 IllegalHelloRetryRequestWithWrongSessionId,
985 IllegalHelloRetryRequestWithInvalidEch,
986 IllegalMiddleboxChangeCipherSpec,
987 IllegalTlsInnerPlaintext,
988 IllegalWarningAlert(AlertDescription),
990 IncorrectBinder,
991 IncorrectFinished,
992 InvalidCertCompression,
993 InvalidMaxEarlyDataSize,
994 InvalidKeyShare,
995 KeyEpochWithPendingFragment,
996 KeyUpdateReceivedInQuicConnection,
997 MessageInterleavedWithHandshakeMessage,
998 MissingBinderInPskExtension,
999 MissingKeyShare,
1000 MissingPskModesExtension,
1001 MissingQuicTransportParameters,
1002 NoCertificatesPresented,
1003 OfferedDuplicateCertificateCompressions,
1004 OfferedDuplicateKeyShares,
1005 OfferedEarlyDataWithOldProtocolVersion,
1006 OfferedEmptyApplicationProtocol,
1007 OfferedIncorrectCompressions,
1008 PskExtensionMustBeLast,
1009 PskExtensionWithMismatchedIdsAndBinders,
1010 RefusedToFollowHelloRetryRequest,
1011 RejectedEarlyDataInterleavedWithHandshakeMessage,
1012 ResumptionAttemptedWithVariedEms,
1013 ResumptionOfferedWithVariedCipherSuite,
1014 ResumptionOfferedWithVariedEms,
1015 ResumptionOfferedWithIncompatibleCipherSuite,
1016 SelectedDifferentCipherSuiteAfterRetry,
1017 SelectedInvalidPsk,
1018 SelectedTls12UsingTls13VersionExtension,
1019 SelectedUnofferedApplicationProtocol,
1020 SelectedUnofferedCertCompression,
1021 SelectedUnofferedCipherSuite,
1022 SelectedUnofferedCompression,
1023 SelectedUnofferedKxGroup,
1024 SelectedUnofferedPsk,
1025 ServerEchoedCompatibilitySessionId,
1026 ServerHelloMustOfferUncompressedEcPoints,
1027 ServerNameDifferedOnRetry,
1028 ServerNameMustContainOneHostName,
1029 SignedKxWithWrongAlgorithm,
1030 SignedHandshakeWithUnadvertisedSigScheme,
1031 TooManyEmptyFragments,
1032 TooManyKeyUpdateRequests,
1033 TooManyRenegotiationRequests,
1034 TooManyWarningAlertsReceived,
1035 TooMuchEarlyDataReceived,
1036 UnexpectedCleartextExtension,
1037 UnsolicitedCertExtension,
1038 UnsolicitedEncryptedExtension,
1039 UnsolicitedSctList,
1040 UnsolicitedServerHelloExtension,
1041 WrongGroupForKeyShare,
1042 UnsolicitedEchExtension,
1043}
1044
1045impl From<PeerMisbehaved> for AlertDescription {
1046 fn from(e: PeerMisbehaved) -> Self {
1047 match e {
1048 PeerMisbehaved::DisallowedEncryptedExtension
1049 | PeerMisbehaved::IllegalHelloRetryRequestWithInvalidEch
1050 | PeerMisbehaved::UnexpectedCleartextExtension
1051 | PeerMisbehaved::UnsolicitedEchExtension
1052 | PeerMisbehaved::UnsolicitedEncryptedExtension
1053 | PeerMisbehaved::UnsolicitedServerHelloExtension => Self::UnsupportedExtension,
1054
1055 PeerMisbehaved::IllegalMiddleboxChangeCipherSpec
1056 | PeerMisbehaved::KeyEpochWithPendingFragment
1057 | PeerMisbehaved::KeyUpdateReceivedInQuicConnection => Self::UnexpectedMessage,
1058
1059 PeerMisbehaved::IllegalWarningAlert(_) => Self::DecodeError,
1060
1061 PeerMisbehaved::IncorrectBinder | PeerMisbehaved::IncorrectFinished => {
1062 Self::DecryptError
1063 }
1064
1065 PeerMisbehaved::InvalidCertCompression
1066 | PeerMisbehaved::SelectedUnofferedCertCompression => Self::BadCertificate,
1067
1068 PeerMisbehaved::MissingKeyShare
1069 | PeerMisbehaved::MissingPskModesExtension
1070 | PeerMisbehaved::MissingQuicTransportParameters => Self::MissingExtension,
1071
1072 PeerMisbehaved::NoCertificatesPresented => Self::CertificateRequired,
1073
1074 _ => Self::IllegalParameter,
1075 }
1076 }
1077}
1078
1079#[expect(missing_docs)]
1085#[non_exhaustive]
1086#[derive(Clone, Copy, Debug, PartialEq)]
1087pub enum PeerIncompatible {
1088 EcPointsExtensionRequired,
1089 ExtendedMasterSecretExtensionRequired,
1090 IncorrectCertificateTypeExtension,
1091 KeyShareExtensionRequired,
1092 MultipleRawKeys,
1093 NamedGroupsExtensionRequired,
1094 NoCertificateRequestSignatureSchemesInCommon,
1095 NoCipherSuitesInCommon,
1096 NoEcPointFormatsInCommon,
1097 NoKxGroupsInCommon,
1098 NoSignatureSchemesInCommon,
1099 NoServerNameProvided,
1100 NullCompressionRequired,
1101 ServerDoesNotSupportTls12Or13,
1102 ServerSentHelloRetryRequestWithUnknownExtension,
1103 ServerTlsVersionIsDisabledByOurConfig,
1104 SignatureAlgorithmsExtensionRequired,
1105 SupportedVersionsExtensionRequired,
1106 Tls12NotOffered,
1107 Tls12NotOfferedOrEnabled,
1108 Tls13RequiredForQuic,
1109 UncompressedEcPointsRequired,
1110 UnknownCertificateType(u8),
1111 UnsolicitedCertificateTypeExtension,
1112}
1113
1114impl From<PeerIncompatible> for AlertDescription {
1115 fn from(e: PeerIncompatible) -> Self {
1116 match e {
1117 PeerIncompatible::NullCompressionRequired => Self::IllegalParameter,
1118
1119 PeerIncompatible::ServerTlsVersionIsDisabledByOurConfig
1120 | PeerIncompatible::SupportedVersionsExtensionRequired
1121 | PeerIncompatible::Tls12NotOffered
1122 | PeerIncompatible::Tls12NotOfferedOrEnabled
1123 | PeerIncompatible::Tls13RequiredForQuic => Self::ProtocolVersion,
1124
1125 PeerIncompatible::UnknownCertificateType(_) => Self::UnsupportedCertificate,
1126
1127 _ => Self::HandshakeFailure,
1128 }
1129 }
1130}
1131
1132#[non_exhaustive]
1137#[derive(Clone, Debug, Eq, PartialEq)]
1138pub enum ExtendedKeyPurpose {
1139 ClientAuth,
1141 ServerAuth,
1143 Other(Vec<usize>),
1147}
1148
1149impl ExtendedKeyPurpose {
1150 #[cfg(feature = "webpki")]
1151 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
1152 let values = values.collect::<Vec<_>>();
1153 match &*values {
1154 ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
1155 ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
1156 _ => Self::Other(values),
1157 }
1158 }
1159}
1160
1161impl fmt::Display for ExtendedKeyPurpose {
1162 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1163 match self {
1164 Self::ClientAuth => write!(f, "client authentication"),
1165 Self::ServerAuth => write!(f, "server authentication"),
1166 Self::Other(values) => {
1167 for (i, value) in values.iter().enumerate() {
1168 if i > 0 {
1169 write!(f, ", ")?;
1170 }
1171 write!(f, "{value}")?;
1172 }
1173 Ok(())
1174 }
1175 }
1176 }
1177}
1178
1179#[non_exhaustive]
1181#[derive(Debug, Clone)]
1182pub enum CertRevocationListError {
1183 BadSignature,
1185
1186 UnsupportedSignatureAlgorithm {
1188 signature_algorithm_id: Vec<u8>,
1190 supported_algorithms: Vec<AlgorithmIdentifier>,
1192 },
1193
1194 UnsupportedSignatureAlgorithmForPublicKey {
1196 signature_algorithm_id: Vec<u8>,
1198 public_key_algorithm_id: Vec<u8>,
1200 },
1201
1202 InvalidCrlNumber,
1204
1205 InvalidRevokedCertSerialNumber,
1207
1208 IssuerInvalidForCrl,
1210
1211 Other(OtherError),
1215
1216 ParseError,
1218
1219 UnsupportedCrlVersion,
1221
1222 UnsupportedCriticalExtension,
1224
1225 UnsupportedDeltaCrl,
1227
1228 UnsupportedIndirectCrl,
1231
1232 UnsupportedRevocationReason,
1237}
1238
1239impl PartialEq<Self> for CertRevocationListError {
1240 fn eq(&self, other: &Self) -> bool {
1241 use CertRevocationListError::*;
1242 match (self, other) {
1243 (BadSignature, BadSignature) => true,
1244 (
1245 UnsupportedSignatureAlgorithm {
1246 signature_algorithm_id: left_signature_algorithm_id,
1247 supported_algorithms: left_supported_algorithms,
1248 },
1249 UnsupportedSignatureAlgorithm {
1250 signature_algorithm_id: right_signature_algorithm_id,
1251 supported_algorithms: right_supported_algorithms,
1252 },
1253 ) => {
1254 (left_signature_algorithm_id, left_supported_algorithms)
1255 == (right_signature_algorithm_id, right_supported_algorithms)
1256 }
1257 (
1258 UnsupportedSignatureAlgorithmForPublicKey {
1259 signature_algorithm_id: left_signature_algorithm_id,
1260 public_key_algorithm_id: left_public_key_algorithm_id,
1261 },
1262 UnsupportedSignatureAlgorithmForPublicKey {
1263 signature_algorithm_id: right_signature_algorithm_id,
1264 public_key_algorithm_id: right_public_key_algorithm_id,
1265 },
1266 ) => {
1267 (left_signature_algorithm_id, left_public_key_algorithm_id)
1268 == (right_signature_algorithm_id, right_public_key_algorithm_id)
1269 }
1270 (InvalidCrlNumber, InvalidCrlNumber) => true,
1271 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
1272 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
1273 (ParseError, ParseError) => true,
1274 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
1275 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
1276 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
1277 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
1278 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
1279 _ => false,
1280 }
1281 }
1282}
1283
1284#[non_exhaustive]
1286#[derive(Debug, Clone, Eq, PartialEq)]
1287pub enum EncryptedClientHelloError {
1288 InvalidConfigList,
1290 NoCompatibleConfig,
1292 SniRequired,
1294}
1295
1296#[non_exhaustive]
1302#[derive(Debug, Clone, PartialEq)]
1303pub struct RejectedEch {
1304 pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
1305}
1306
1307impl RejectedEch {
1308 pub fn can_retry(&self) -> bool {
1314 self.retry_configs.is_some()
1315 }
1316
1317 pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
1319 let Some(retry_configs) = &self.retry_configs else {
1320 return None;
1321 };
1322
1323 let mut tls_encoded_list = Vec::new();
1324 retry_configs.encode(&mut tls_encoded_list);
1325
1326 Some(EchConfigListBytes::from(tls_encoded_list))
1327 }
1328}
1329
1330fn join<T: fmt::Debug>(items: &[T]) -> String {
1331 items
1332 .iter()
1333 .map(|x| format!("{x:?}"))
1334 .collect::<Vec<String>>()
1335 .join(" or ")
1336}
1337
1338#[non_exhaustive]
1342#[derive(Debug, Clone, PartialEq)]
1343pub enum ApiMisuse {
1344 ExporterAlreadyUsed,
1352
1353 ExporterContextTooLong,
1359
1360 ExporterOutputTooLong,
1366
1367 ExporterOutputZeroLength,
1374
1375 AcceptorPolledAfterCompletion,
1379
1380 InvalidQuicHeaderProtectionSampleLength,
1384
1385 InvalidQuicHeaderProtectionPacketNumberLength,
1390
1391 InvalidSignerForProtocolVersion,
1393
1394 QuicRequiresTls13Support,
1396
1397 NoQuicCompatibleCipherSuites,
1399
1400 EmptyCertificateChain,
1402
1403 QuicRestrictsMaxEarlyDataSize,
1409
1410 NoCipherSuitesConfigured,
1412
1413 NoKeyExchangeGroupsConfigured,
1415
1416 NoSignatureVerificationAlgorithms,
1418
1419 EchRequiresTls13Support,
1421
1422 EchForbidsTls12Support,
1424
1425 SecretExtractionRequiresPriorOptIn,
1438
1439 SecretExtractionWithPendingSendableData,
1446
1447 UnverifiableCertificateType,
1452
1453 NoSupportedCertificateTypes,
1455
1456 NonceArraySizeMismatch {
1462 expected: usize,
1464 actual: usize,
1466 },
1467
1468 IvLengthExceedsMaximum {
1475 actual: usize,
1477 maximum: usize,
1479 },
1480
1481 ResumptionDataProvidedTooLate,
1486}
1487
1488impl fmt::Display for ApiMisuse {
1489 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1490 write!(f, "{self:?}")
1491 }
1492}
1493
1494impl core::error::Error for ApiMisuse {}
1495
1496mod other_error {
1497 use core::error::Error as StdError;
1498 use core::fmt;
1499
1500 use crate::sync::Arc;
1501
1502 #[derive(Debug, Clone)]
1510 pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1511
1512 impl OtherError {
1513 pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1515 Self(Arc::new(err))
1516 }
1517 }
1518
1519 impl PartialEq<Self> for OtherError {
1520 fn eq(&self, _other: &Self) -> bool {
1521 false
1522 }
1523 }
1524
1525 impl fmt::Display for OtherError {
1526 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1527 #[cfg(feature = "std")]
1528 {
1529 write!(f, "{}", self.0)
1530 }
1531 #[cfg(not(feature = "std"))]
1532 {
1533 f.write_str("no further information available")
1534 }
1535 }
1536 }
1537
1538 impl StdError for OtherError {
1539 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1540 Some(self.0.as_ref())
1541 }
1542 }
1543}
1544
1545pub use other_error::OtherError;