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::enums::{AlertDescription, ContentType, HandshakeType};
14use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
15use crate::rand;
16
17#[non_exhaustive]
19#[derive(Debug, PartialEq, Clone)]
20pub enum Error {
21 InappropriateMessage {
27 expect_types: Vec<ContentType>,
29 got_type: ContentType,
31 },
32
33 InappropriateHandshakeMessage {
37 expect_types: Vec<HandshakeType>,
39 got_type: HandshakeType,
41 },
42
43 InvalidEncryptedClientHello(EncryptedClientHelloError),
45
46 InvalidMessage(InvalidMessage),
48
49 UnsupportedNameType,
51
52 DecryptError,
54
55 EncryptError,
58
59 PeerIncompatible(PeerIncompatible),
62
63 PeerMisbehaved(PeerMisbehaved),
66
67 AlertReceived(AlertDescription),
69
70 InvalidCertificate(CertificateError),
75
76 InvalidCertRevocationList(CertRevocationListError),
78
79 General(String),
81
82 FailedToGetCurrentTime,
84
85 FailedToGetRandomBytes,
87
88 HandshakeNotComplete,
91
92 PeerSentOversizedRecord,
94
95 NoApplicationProtocol,
97
98 NoSuitableCertificate,
100
101 BadMaxFragmentSize,
104
105 InconsistentKeys(InconsistentKeys),
115
116 RejectedEch(RejectedEch),
123
124 Unreachable(&'static str),
128
129 ApiMisuse(ApiMisuse),
141
142 Other(OtherError),
150}
151
152#[non_exhaustive]
156#[derive(Clone, Copy, Debug, Eq, PartialEq)]
157pub enum InconsistentKeys {
158 KeyMismatch,
162
163 Unknown,
167}
168
169impl From<InconsistentKeys> for Error {
170 #[inline]
171 fn from(e: InconsistentKeys) -> Self {
172 Self::InconsistentKeys(e)
173 }
174}
175
176#[non_exhaustive]
178#[derive(Debug, Clone, Copy, PartialEq)]
179pub enum InvalidMessage {
180 CertificatePayloadTooLarge,
182 HandshakePayloadTooLarge,
184 InvalidCcs,
186 InvalidContentType,
188 InvalidCertificateStatusType,
190 InvalidCertRequest,
192 InvalidDhParams,
194 InvalidEmptyPayload,
196 InvalidKeyUpdate,
198 InvalidServerName,
200 MessageTooLarge,
202 MessageTooShort,
204 MissingData(&'static str),
206 MissingKeyExchange,
208 NoSignatureSchemes,
210 TrailingData(&'static str),
212 UnexpectedMessage(&'static str),
214 UnknownProtocolVersion,
216 UnsupportedCompression,
218 UnsupportedCurveType,
220 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
222 EmptyTicketValue,
224 IllegalEmptyList(&'static str),
228 IllegalEmptyValue,
230 DuplicateExtension(u16),
232 PreSharedKeyIsNotFinalExtension,
234 UnknownHelloRetryRequestExtension,
236 UnknownCertificateExtension,
238}
239
240impl From<InvalidMessage> for Error {
241 #[inline]
242 fn from(e: InvalidMessage) -> Self {
243 Self::InvalidMessage(e)
244 }
245}
246
247impl From<InvalidMessage> for AlertDescription {
248 fn from(e: InvalidMessage) -> Self {
249 match e {
250 InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
251 InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
252 InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
253 _ => Self::DecodeError,
254 }
255 }
256}
257
258#[allow(missing_docs)]
269#[non_exhaustive]
270#[derive(Debug, PartialEq, Clone)]
271pub enum PeerMisbehaved {
272 AttemptedDowngradeToTls12WhenTls13IsSupported,
273 BadCertChainExtensions,
274 DisallowedEncryptedExtension,
275 DuplicateClientHelloExtensions,
276 DuplicateEncryptedExtensions,
277 DuplicateHelloRetryRequestExtensions,
278 DuplicateNewSessionTicketExtensions,
279 DuplicateServerHelloExtensions,
280 DuplicateServerNameTypes,
281 EarlyDataAttemptedInSecondClientHello,
282 EarlyDataExtensionWithoutResumption,
283 EarlyDataOfferedWithVariedCipherSuite,
284 HandshakeHashVariedAfterRetry,
285 IllegalHelloRetryRequestWithEmptyCookie,
286 IllegalHelloRetryRequestWithNoChanges,
287 IllegalHelloRetryRequestWithOfferedGroup,
288 IllegalHelloRetryRequestWithUnofferedCipherSuite,
289 IllegalHelloRetryRequestWithUnofferedNamedGroup,
290 IllegalHelloRetryRequestWithUnsupportedVersion,
291 IllegalHelloRetryRequestWithWrongSessionId,
292 IllegalHelloRetryRequestWithInvalidEch,
293 IllegalMiddleboxChangeCipherSpec,
294 IllegalTlsInnerPlaintext,
295 IncorrectBinder,
296 InvalidCertCompression,
297 InvalidMaxEarlyDataSize,
298 InvalidKeyShare,
299 KeyEpochWithPendingFragment,
300 KeyUpdateReceivedInQuicConnection,
301 MessageInterleavedWithHandshakeMessage,
302 MissingBinderInPskExtension,
303 MissingKeyShare,
304 MissingPskModesExtension,
305 MissingQuicTransportParameters,
306 NoCertificatesPresented,
307 OfferedDuplicateCertificateCompressions,
308 OfferedDuplicateKeyShares,
309 OfferedEarlyDataWithOldProtocolVersion,
310 OfferedEmptyApplicationProtocol,
311 OfferedIncorrectCompressions,
312 PskExtensionMustBeLast,
313 PskExtensionWithMismatchedIdsAndBinders,
314 RefusedToFollowHelloRetryRequest,
315 RejectedEarlyDataInterleavedWithHandshakeMessage,
316 ResumptionAttemptedWithVariedEms,
317 ResumptionOfferedWithVariedCipherSuite,
318 ResumptionOfferedWithVariedEms,
319 ResumptionOfferedWithIncompatibleCipherSuite,
320 SelectedDifferentCipherSuiteAfterRetry,
321 SelectedInvalidPsk,
322 SelectedTls12UsingTls13VersionExtension,
323 SelectedUnofferedApplicationProtocol,
324 SelectedUnofferedCertCompression,
325 SelectedUnofferedCipherSuite,
326 SelectedUnofferedCompression,
327 SelectedUnofferedKxGroup,
328 SelectedUnofferedPsk,
329 ServerEchoedCompatibilitySessionId,
330 ServerHelloMustOfferUncompressedEcPoints,
331 ServerNameDifferedOnRetry,
332 ServerNameMustContainOneHostName,
333 SignedKxWithWrongAlgorithm,
334 SignedHandshakeWithUnadvertisedSigScheme,
335 TooManyEmptyFragments,
336 TooManyKeyUpdateRequests,
337 TooManyRenegotiationRequests,
338 TooManyWarningAlertsReceived,
339 TooMuchEarlyDataReceived,
340 UnexpectedCleartextExtension,
341 UnsolicitedCertExtension,
342 UnsolicitedEncryptedExtension,
343 UnsolicitedSctList,
344 UnsolicitedServerHelloExtension,
345 WrongGroupForKeyShare,
346 UnsolicitedEchExtension,
347}
348
349impl From<PeerMisbehaved> for Error {
350 #[inline]
351 fn from(e: PeerMisbehaved) -> Self {
352 Self::PeerMisbehaved(e)
353 }
354}
355
356#[allow(missing_docs)]
362#[non_exhaustive]
363#[derive(Debug, PartialEq, Clone)]
364pub enum PeerIncompatible {
365 EcPointsExtensionRequired,
366 ExtendedMasterSecretExtensionRequired,
367 IncorrectCertificateTypeExtension,
368 KeyShareExtensionRequired,
369 MultipleRawKeys,
370 NamedGroupsExtensionRequired,
371 NoCertificateRequestSignatureSchemesInCommon,
372 NoCipherSuitesInCommon,
373 NoEcPointFormatsInCommon,
374 NoKxGroupsInCommon,
375 NoSignatureSchemesInCommon,
376 NoServerNameProvided,
377 NullCompressionRequired,
378 ServerDoesNotSupportTls12Or13,
379 ServerSentHelloRetryRequestWithUnknownExtension,
380 ServerTlsVersionIsDisabledByOurConfig,
381 SignatureAlgorithmsExtensionRequired,
382 SupportedVersionsExtensionRequired,
383 Tls12NotOffered,
384 Tls12NotOfferedOrEnabled,
385 Tls13RequiredForQuic,
386 UncompressedEcPointsRequired,
387 UnknownCertificateType(u8),
388 UnsolicitedCertificateTypeExtension,
389}
390
391impl From<PeerIncompatible> for Error {
392 #[inline]
393 fn from(e: PeerIncompatible) -> Self {
394 Self::PeerIncompatible(e)
395 }
396}
397
398#[non_exhaustive]
406#[derive(Debug, Clone)]
407pub enum CertificateError {
408 BadEncoding,
410
411 Expired,
413
414 ExpiredContext {
419 time: UnixTime,
421 not_after: UnixTime,
423 },
424
425 NotValidYet,
427
428 NotValidYetContext {
433 time: UnixTime,
435 not_before: UnixTime,
437 },
438
439 Revoked,
441
442 UnhandledCriticalExtension,
445
446 UnknownIssuer,
448
449 UnknownRevocationStatus,
451
452 ExpiredRevocationList,
454
455 ExpiredRevocationListContext {
460 time: UnixTime,
462 next_update: UnixTime,
464 },
465
466 BadSignature,
469
470 UnsupportedSignatureAlgorithm {
472 signature_algorithm_id: Vec<u8>,
474 supported_algorithms: Vec<AlgorithmIdentifier>,
476 },
477
478 UnsupportedSignatureAlgorithmForPublicKey {
480 signature_algorithm_id: Vec<u8>,
482 public_key_algorithm_id: Vec<u8>,
484 },
485
486 NotValidForName,
489
490 NotValidForNameContext {
496 expected: ServerName<'static>,
498
499 presented: Vec<String>,
504 },
505
506 InvalidPurpose,
508
509 InvalidPurposeContext {
514 required: ExtendedKeyPurpose,
516 presented: Vec<ExtendedKeyPurpose>,
518 },
519
520 InvalidOcspResponse,
529
530 ApplicationVerificationFailure,
533
534 Other(OtherError),
545}
546
547impl PartialEq<Self> for CertificateError {
548 fn eq(&self, other: &Self) -> bool {
549 use CertificateError::*;
550 #[allow(clippy::match_like_matches_macro)]
551 match (self, other) {
552 (BadEncoding, BadEncoding) => true,
553 (Expired, Expired) => true,
554 (
555 ExpiredContext {
556 time: left_time,
557 not_after: left_not_after,
558 },
559 ExpiredContext {
560 time: right_time,
561 not_after: right_not_after,
562 },
563 ) => (left_time, left_not_after) == (right_time, right_not_after),
564 (NotValidYet, NotValidYet) => true,
565 (
566 NotValidYetContext {
567 time: left_time,
568 not_before: left_not_before,
569 },
570 NotValidYetContext {
571 time: right_time,
572 not_before: right_not_before,
573 },
574 ) => (left_time, left_not_before) == (right_time, right_not_before),
575 (Revoked, Revoked) => true,
576 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
577 (UnknownIssuer, UnknownIssuer) => true,
578 (BadSignature, BadSignature) => true,
579 (
580 UnsupportedSignatureAlgorithm {
581 signature_algorithm_id: left_signature_algorithm_id,
582 supported_algorithms: left_supported_algorithms,
583 },
584 UnsupportedSignatureAlgorithm {
585 signature_algorithm_id: right_signature_algorithm_id,
586 supported_algorithms: right_supported_algorithms,
587 },
588 ) => {
589 (left_signature_algorithm_id, left_supported_algorithms)
590 == (right_signature_algorithm_id, right_supported_algorithms)
591 }
592 (
593 UnsupportedSignatureAlgorithmForPublicKey {
594 signature_algorithm_id: left_signature_algorithm_id,
595 public_key_algorithm_id: left_public_key_algorithm_id,
596 },
597 UnsupportedSignatureAlgorithmForPublicKey {
598 signature_algorithm_id: right_signature_algorithm_id,
599 public_key_algorithm_id: right_public_key_algorithm_id,
600 },
601 ) => {
602 (left_signature_algorithm_id, left_public_key_algorithm_id)
603 == (right_signature_algorithm_id, right_public_key_algorithm_id)
604 }
605 (NotValidForName, NotValidForName) => true,
606 (
607 NotValidForNameContext {
608 expected: left_expected,
609 presented: left_presented,
610 },
611 NotValidForNameContext {
612 expected: right_expected,
613 presented: right_presented,
614 },
615 ) => (left_expected, left_presented) == (right_expected, right_presented),
616 (InvalidPurpose, InvalidPurpose) => true,
617 (
618 InvalidPurposeContext {
619 required: left_required,
620 presented: left_presented,
621 },
622 InvalidPurposeContext {
623 required: right_required,
624 presented: right_presented,
625 },
626 ) => (left_required, left_presented) == (right_required, right_presented),
627 (InvalidOcspResponse, InvalidOcspResponse) => true,
628 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
629 (UnknownRevocationStatus, UnknownRevocationStatus) => true,
630 (ExpiredRevocationList, ExpiredRevocationList) => true,
631 (
632 ExpiredRevocationListContext {
633 time: left_time,
634 next_update: left_next_update,
635 },
636 ExpiredRevocationListContext {
637 time: right_time,
638 next_update: right_next_update,
639 },
640 ) => (left_time, left_next_update) == (right_time, right_next_update),
641 _ => false,
642 }
643 }
644}
645
646impl From<CertificateError> for AlertDescription {
650 fn from(e: CertificateError) -> Self {
651 use CertificateError::*;
652 match e {
653 BadEncoding
654 | UnhandledCriticalExtension
655 | NotValidForName
656 | NotValidForNameContext { .. } => Self::BadCertificate,
657 Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
661 Self::CertificateExpired
662 }
663 Revoked => Self::CertificateRevoked,
664 UnknownIssuer
667 | UnknownRevocationStatus
668 | ExpiredRevocationList
669 | ExpiredRevocationListContext { .. } => Self::UnknownCa,
670 InvalidOcspResponse => Self::BadCertificateStatusResponse,
671 BadSignature
672 | UnsupportedSignatureAlgorithm { .. }
673 | UnsupportedSignatureAlgorithmForPublicKey { .. } => Self::DecryptError,
674 InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate,
675 ApplicationVerificationFailure => Self::AccessDenied,
676 Other(..) => Self::CertificateUnknown,
681 }
682 }
683}
684
685impl fmt::Display for CertificateError {
686 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
687 match self {
688 #[cfg(feature = "std")]
689 Self::NotValidForNameContext {
690 expected,
691 presented,
692 } => {
693 write!(
694 f,
695 "certificate not valid for name {:?}; certificate ",
696 expected.to_str()
697 )?;
698
699 match presented.as_slice() {
700 &[] => write!(
701 f,
702 "is not valid for any names (according to its subjectAltName extension)"
703 ),
704 [one] => write!(f, "is only valid for {one}"),
705 many => {
706 write!(f, "is only valid for ")?;
707
708 let n = many.len();
709 let all_but_last = &many[..n - 1];
710 let last = &many[n - 1];
711
712 for (i, name) in all_but_last.iter().enumerate() {
713 write!(f, "{name}")?;
714 if i < n - 2 {
715 write!(f, ", ")?;
716 }
717 }
718 write!(f, " or {last}")
719 }
720 }
721 }
722
723 Self::ExpiredContext { time, not_after } => write!(
724 f,
725 "certificate expired: verification time {} (UNIX), \
726 but certificate is not valid after {} \
727 ({} seconds ago)",
728 time.as_secs(),
729 not_after.as_secs(),
730 time.as_secs()
731 .saturating_sub(not_after.as_secs())
732 ),
733
734 Self::NotValidYetContext { time, not_before } => write!(
735 f,
736 "certificate not valid yet: verification time {} (UNIX), \
737 but certificate is not valid before {} \
738 ({} seconds in future)",
739 time.as_secs(),
740 not_before.as_secs(),
741 not_before
742 .as_secs()
743 .saturating_sub(time.as_secs())
744 ),
745
746 Self::ExpiredRevocationListContext { time, next_update } => write!(
747 f,
748 "certificate revocation list expired: \
749 verification time {} (UNIX), \
750 but CRL is not valid after {} \
751 ({} seconds ago)",
752 time.as_secs(),
753 next_update.as_secs(),
754 time.as_secs()
755 .saturating_sub(next_update.as_secs())
756 ),
757
758 Self::InvalidPurposeContext {
759 required,
760 presented,
761 } => {
762 write!(
763 f,
764 "certificate does not allow extended key usage for {required}, allows "
765 )?;
766 for (i, eku) in presented.iter().enumerate() {
767 if i > 0 {
768 write!(f, ", ")?;
769 }
770 write!(f, "{eku}")?;
771 }
772 Ok(())
773 }
774
775 Self::Other(other) => write!(f, "{other}"),
776
777 other => write!(f, "{other:?}"),
778 }
779 }
780}
781
782impl From<CertificateError> for Error {
783 #[inline]
784 fn from(e: CertificateError) -> Self {
785 Self::InvalidCertificate(e)
786 }
787}
788
789#[non_exhaustive]
794#[derive(Clone, Debug, Eq, PartialEq)]
795pub enum ExtendedKeyPurpose {
796 ClientAuth,
798 ServerAuth,
800 Other(Vec<usize>),
804}
805
806impl ExtendedKeyPurpose {
807 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
808 let values = values.collect::<Vec<_>>();
809 match &*values {
810 ExtendedKeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
811 ExtendedKeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
812 _ => Self::Other(values),
813 }
814 }
815}
816
817impl fmt::Display for ExtendedKeyPurpose {
818 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
819 match self {
820 Self::ClientAuth => write!(f, "client authentication"),
821 Self::ServerAuth => write!(f, "server authentication"),
822 Self::Other(values) => {
823 for (i, value) in values.iter().enumerate() {
824 if i > 0 {
825 write!(f, ", ")?;
826 }
827 write!(f, "{value}")?;
828 }
829 Ok(())
830 }
831 }
832 }
833}
834
835#[non_exhaustive]
837#[derive(Debug, Clone)]
838pub enum CertRevocationListError {
839 BadSignature,
841
842 UnsupportedSignatureAlgorithm {
844 signature_algorithm_id: Vec<u8>,
846 supported_algorithms: Vec<AlgorithmIdentifier>,
848 },
849
850 UnsupportedSignatureAlgorithmForPublicKey {
852 signature_algorithm_id: Vec<u8>,
854 public_key_algorithm_id: Vec<u8>,
856 },
857
858 InvalidCrlNumber,
860
861 InvalidRevokedCertSerialNumber,
863
864 IssuerInvalidForCrl,
866
867 Other(OtherError),
871
872 ParseError,
874
875 UnsupportedCrlVersion,
877
878 UnsupportedCriticalExtension,
880
881 UnsupportedDeltaCrl,
883
884 UnsupportedIndirectCrl,
887
888 UnsupportedRevocationReason,
893}
894
895impl PartialEq<Self> for CertRevocationListError {
896 fn eq(&self, other: &Self) -> bool {
897 use CertRevocationListError::*;
898 #[allow(clippy::match_like_matches_macro)]
899 match (self, other) {
900 (BadSignature, BadSignature) => true,
901 (
902 UnsupportedSignatureAlgorithm {
903 signature_algorithm_id: left_signature_algorithm_id,
904 supported_algorithms: left_supported_algorithms,
905 },
906 UnsupportedSignatureAlgorithm {
907 signature_algorithm_id: right_signature_algorithm_id,
908 supported_algorithms: right_supported_algorithms,
909 },
910 ) => {
911 (left_signature_algorithm_id, left_supported_algorithms)
912 == (right_signature_algorithm_id, right_supported_algorithms)
913 }
914 (
915 UnsupportedSignatureAlgorithmForPublicKey {
916 signature_algorithm_id: left_signature_algorithm_id,
917 public_key_algorithm_id: left_public_key_algorithm_id,
918 },
919 UnsupportedSignatureAlgorithmForPublicKey {
920 signature_algorithm_id: right_signature_algorithm_id,
921 public_key_algorithm_id: right_public_key_algorithm_id,
922 },
923 ) => {
924 (left_signature_algorithm_id, left_public_key_algorithm_id)
925 == (right_signature_algorithm_id, right_public_key_algorithm_id)
926 }
927 (InvalidCrlNumber, InvalidCrlNumber) => true,
928 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
929 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
930 (ParseError, ParseError) => true,
931 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
932 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
933 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
934 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
935 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
936 _ => false,
937 }
938 }
939}
940
941impl From<CertRevocationListError> for Error {
942 #[inline]
943 fn from(e: CertRevocationListError) -> Self {
944 Self::InvalidCertRevocationList(e)
945 }
946}
947
948#[non_exhaustive]
950#[derive(Debug, Clone, Eq, PartialEq)]
951pub enum EncryptedClientHelloError {
952 InvalidConfigList,
954 NoCompatibleConfig,
956 SniRequired,
958}
959
960impl From<EncryptedClientHelloError> for Error {
961 #[inline]
962 fn from(e: EncryptedClientHelloError) -> Self {
963 Self::InvalidEncryptedClientHello(e)
964 }
965}
966
967#[non_exhaustive]
973#[derive(Debug, Clone, PartialEq)]
974pub struct RejectedEch {
975 pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
976}
977
978impl RejectedEch {
979 pub fn can_retry(&self) -> bool {
985 self.retry_configs.is_some()
986 }
987
988 pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
990 let Some(retry_configs) = &self.retry_configs else {
991 return None;
992 };
993
994 let mut tls_encoded_list = Vec::new();
995 retry_configs.encode(&mut tls_encoded_list);
996
997 Some(EchConfigListBytes::from(tls_encoded_list))
998 }
999}
1000
1001impl From<RejectedEch> for Error {
1002 fn from(rejected_error: RejectedEch) -> Self {
1003 Self::RejectedEch(rejected_error)
1004 }
1005}
1006
1007fn join<T: fmt::Debug>(items: &[T]) -> String {
1008 items
1009 .iter()
1010 .map(|x| format!("{x:?}"))
1011 .collect::<Vec<String>>()
1012 .join(" or ")
1013}
1014
1015impl fmt::Display for Error {
1016 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1017 match self {
1018 Self::InappropriateMessage {
1019 expect_types,
1020 got_type,
1021 } => write!(
1022 f,
1023 "received unexpected message: got {:?} when expecting {}",
1024 got_type,
1025 join::<ContentType>(expect_types)
1026 ),
1027 Self::InappropriateHandshakeMessage {
1028 expect_types,
1029 got_type,
1030 } => write!(
1031 f,
1032 "received unexpected handshake message: got {:?} when expecting {}",
1033 got_type,
1034 join::<HandshakeType>(expect_types)
1035 ),
1036 Self::InvalidMessage(typ) => {
1037 write!(f, "received corrupt message of type {typ:?}")
1038 }
1039 Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
1040 Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
1041 Self::AlertReceived(alert) => write!(f, "received fatal alert: the peer {alert}"),
1042 Self::InvalidCertificate(err) => {
1043 write!(f, "invalid peer certificate: {err}")
1044 }
1045 Self::InvalidCertRevocationList(err) => {
1046 write!(f, "invalid certificate revocation list: {err:?}")
1047 }
1048 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
1049 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
1050 Self::InvalidEncryptedClientHello(err) => {
1051 write!(f, "encrypted client hello failure: {err:?}")
1052 }
1053 Self::EncryptError => write!(f, "cannot encrypt message"),
1054 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
1055 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
1056 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
1057 Self::NoSuitableCertificate => write!(f, "no suitable certificate found"),
1058 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
1059 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
1060 Self::BadMaxFragmentSize => {
1061 write!(f, "the supplied max_fragment_size was too small or large")
1062 }
1063 Self::InconsistentKeys(why) => {
1064 write!(f, "keys may not be consistent: {why:?}")
1065 }
1066 Self::RejectedEch(why) => {
1067 write!(
1068 f,
1069 "server rejected encrypted client hello (ECH) {} retry configs",
1070 if why.can_retry() { "with" } else { "without" }
1071 )
1072 }
1073 Self::General(err) => write!(f, "unexpected error: {err}"),
1074 Self::Unreachable(err) => write!(
1075 f,
1076 "unreachable condition: {err} (please file a bug in rustls)"
1077 ),
1078 Self::ApiMisuse(why) => write!(f, "API misuse: {why:?}"),
1079 Self::Other(err) => write!(f, "other error: {err}"),
1080 }
1081 }
1082}
1083
1084#[cfg(feature = "std")]
1085impl From<SystemTimeError> for Error {
1086 #[inline]
1087 fn from(_: SystemTimeError) -> Self {
1088 Self::FailedToGetCurrentTime
1089 }
1090}
1091
1092impl core::error::Error for Error {}
1093
1094impl From<rand::GetRandomFailed> for Error {
1095 fn from(_: rand::GetRandomFailed) -> Self {
1096 Self::FailedToGetRandomBytes
1097 }
1098}
1099
1100#[non_exhaustive]
1104#[derive(Debug, Clone, PartialEq)]
1105pub enum ApiMisuse {
1106 ExporterAlreadyUsed,
1114
1115 ExporterContextTooLong,
1121
1122 ExporterOutputTooLong,
1128
1129 ExporterOutputZeroLength,
1136
1137 AcceptorPolledAfterCompletion,
1141
1142 InvalidQuicHeaderProtectionSampleLength,
1146
1147 InvalidQuicHeaderProtectionPacketNumberLength,
1152
1153 InvalidSignerForProtocolVersion,
1155
1156 QuicRequiresTls13Support,
1158
1159 NoQuicCompatibleCipherSuites,
1161
1162 EmptyCertificateChain,
1164
1165 QuicRestrictsMaxEarlyDataSize,
1171
1172 NoCipherSuitesConfigured,
1174
1175 NoKeyExchangeGroupsConfigured,
1177
1178 NoSignatureVerificationAlgorithms,
1180
1181 EchRequiresTls13Support,
1183
1184 EchForbidsTls12Support,
1186
1187 SecretExtractionRequiresPriorOptIn,
1200
1201 SecretExtractionWithPendingSendableData,
1208
1209 UnverifiableCertificateType,
1214
1215 NoSupportedCertificateTypes,
1217}
1218
1219impl fmt::Display for ApiMisuse {
1220 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1221 write!(f, "{self:?}")
1222 }
1223}
1224
1225impl core::error::Error for ApiMisuse {}
1226
1227impl From<ApiMisuse> for Error {
1228 fn from(e: ApiMisuse) -> Self {
1229 Self::ApiMisuse(e)
1230 }
1231}
1232
1233mod other_error {
1234 use core::error::Error as StdError;
1235 use core::fmt;
1236
1237 use super::Error;
1238 use crate::sync::Arc;
1239
1240 #[allow(clippy::exhaustive_structs)]
1247 #[derive(Debug, Clone)]
1248 pub struct OtherError(Arc<dyn StdError + Send + Sync>);
1249
1250 impl OtherError {
1251 pub fn new(err: impl StdError + Send + Sync + 'static) -> Self {
1253 Self(Arc::new(err))
1254 }
1255 }
1256
1257 impl PartialEq<Self> for OtherError {
1258 fn eq(&self, _other: &Self) -> bool {
1259 false
1260 }
1261 }
1262
1263 impl From<OtherError> for Error {
1264 fn from(value: OtherError) -> Self {
1265 Self::Other(value)
1266 }
1267 }
1268
1269 impl fmt::Display for OtherError {
1270 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1271 #[cfg(feature = "std")]
1272 {
1273 write!(f, "{}", self.0)
1274 }
1275 #[cfg(not(feature = "std"))]
1276 {
1277 f.write_str("no further information available")
1278 }
1279 }
1280 }
1281
1282 impl StdError for OtherError {
1283 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1284 Some(self.0.as_ref())
1285 }
1286 }
1287}
1288
1289pub use other_error::OtherError;
1290
1291use crate::msgs::codec::Codec;
1292
1293#[cfg(test)]
1294mod tests {
1295 use core::time::Duration;
1296 use std::prelude::v1::*;
1297 use std::{println, vec};
1298
1299 use pki_types::ServerName;
1300
1301 use super::{
1302 AlertDescription, CertRevocationListError, Error, InconsistentKeys, InvalidMessage,
1303 OtherError, UnixTime,
1304 };
1305
1306 #[test]
1307 fn certificate_error_equality() {
1308 use super::CertificateError::*;
1309 assert_eq!(BadEncoding, BadEncoding);
1310 assert_eq!(Expired, Expired);
1311 let context = ExpiredContext {
1312 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1313 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1314 };
1315 assert_eq!(context, context);
1316 assert_ne!(
1317 context,
1318 ExpiredContext {
1319 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1320 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1321 }
1322 );
1323 assert_ne!(
1324 context,
1325 ExpiredContext {
1326 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1327 not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1328 }
1329 );
1330 assert_eq!(NotValidYet, NotValidYet);
1331 let context = NotValidYetContext {
1332 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1333 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1334 };
1335 assert_eq!(context, context);
1336 assert_ne!(
1337 context,
1338 NotValidYetContext {
1339 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1340 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1341 }
1342 );
1343 assert_ne!(
1344 context,
1345 NotValidYetContext {
1346 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1347 not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1348 }
1349 );
1350 assert_eq!(Revoked, Revoked);
1351 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
1352 assert_eq!(UnknownIssuer, UnknownIssuer);
1353 assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
1354 assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
1355 let context = ExpiredRevocationListContext {
1356 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1357 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1358 };
1359 assert_eq!(context, context);
1360 assert_ne!(
1361 context,
1362 ExpiredRevocationListContext {
1363 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1364 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1365 }
1366 );
1367 assert_ne!(
1368 context,
1369 ExpiredRevocationListContext {
1370 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1371 next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1372 }
1373 );
1374 assert_eq!(BadSignature, BadSignature);
1375 assert_eq!(
1376 UnsupportedSignatureAlgorithm {
1377 signature_algorithm_id: vec![1, 2, 3],
1378 supported_algorithms: vec![]
1379 },
1380 UnsupportedSignatureAlgorithm {
1381 signature_algorithm_id: vec![1, 2, 3],
1382 supported_algorithms: vec![]
1383 }
1384 );
1385 assert_eq!(
1386 UnsupportedSignatureAlgorithmForPublicKey {
1387 signature_algorithm_id: vec![1, 2, 3],
1388 public_key_algorithm_id: vec![4, 5, 6]
1389 },
1390 UnsupportedSignatureAlgorithmForPublicKey {
1391 signature_algorithm_id: vec![1, 2, 3],
1392 public_key_algorithm_id: vec![4, 5, 6]
1393 }
1394 );
1395 assert_eq!(NotValidForName, NotValidForName);
1396 let context = NotValidForNameContext {
1397 expected: ServerName::try_from("example.com")
1398 .unwrap()
1399 .to_owned(),
1400 presented: vec!["other.com".into()],
1401 };
1402 assert_eq!(context, context);
1403 assert_ne!(
1404 context,
1405 NotValidForNameContext {
1406 expected: ServerName::try_from("example.com")
1407 .unwrap()
1408 .to_owned(),
1409 presented: vec![]
1410 }
1411 );
1412 assert_ne!(
1413 context,
1414 NotValidForNameContext {
1415 expected: ServerName::try_from("huh.com")
1416 .unwrap()
1417 .to_owned(),
1418 presented: vec!["other.com".into()],
1419 }
1420 );
1421 assert_eq!(InvalidPurpose, InvalidPurpose);
1422 assert_eq!(
1423 ApplicationVerificationFailure,
1424 ApplicationVerificationFailure
1425 );
1426 assert_eq!(InvalidOcspResponse, InvalidOcspResponse);
1427 let other = Other(OtherError::new(TestError));
1428 assert_ne!(other, other);
1429 assert_ne!(BadEncoding, Expired);
1430 }
1431
1432 #[test]
1433 fn crl_error_equality() {
1434 use super::CertRevocationListError::*;
1435 assert_eq!(BadSignature, BadSignature);
1436 assert_eq!(
1437 UnsupportedSignatureAlgorithm {
1438 signature_algorithm_id: vec![1, 2, 3],
1439 supported_algorithms: vec![]
1440 },
1441 UnsupportedSignatureAlgorithm {
1442 signature_algorithm_id: vec![1, 2, 3],
1443 supported_algorithms: vec![]
1444 }
1445 );
1446 assert_eq!(
1447 UnsupportedSignatureAlgorithmForPublicKey {
1448 signature_algorithm_id: vec![1, 2, 3],
1449 public_key_algorithm_id: vec![4, 5, 6]
1450 },
1451 UnsupportedSignatureAlgorithmForPublicKey {
1452 signature_algorithm_id: vec![1, 2, 3],
1453 public_key_algorithm_id: vec![4, 5, 6]
1454 }
1455 );
1456 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
1457 assert_eq!(
1458 InvalidRevokedCertSerialNumber,
1459 InvalidRevokedCertSerialNumber
1460 );
1461 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
1462 assert_eq!(ParseError, ParseError);
1463 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
1464 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
1465 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
1466 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
1467 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
1468 let other = Other(OtherError::new(TestError));
1469 assert_ne!(other, other);
1470 assert_ne!(BadSignature, InvalidCrlNumber);
1471 }
1472
1473 #[test]
1474 #[cfg(feature = "std")]
1475 fn other_error_equality() {
1476 let other_error = OtherError::new(TestError);
1477 assert_ne!(other_error, other_error);
1478 let other: Error = other_error.into();
1479 assert_ne!(other, other);
1480 }
1481
1482 #[test]
1483 fn smoke() {
1484 use crate::enums::{AlertDescription, ContentType, HandshakeType};
1485
1486 let all = vec![
1487 Error::InappropriateMessage {
1488 expect_types: vec![ContentType::Alert],
1489 got_type: ContentType::Handshake,
1490 },
1491 Error::InappropriateHandshakeMessage {
1492 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
1493 got_type: HandshakeType::ServerHello,
1494 },
1495 Error::InvalidMessage(InvalidMessage::InvalidCcs),
1496 Error::DecryptError,
1497 super::PeerIncompatible::Tls12NotOffered.into(),
1498 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
1499 Error::AlertReceived(AlertDescription::ExportRestriction),
1500 super::CertificateError::Expired.into(),
1501 super::CertificateError::NotValidForNameContext {
1502 expected: ServerName::try_from("example.com")
1503 .unwrap()
1504 .to_owned(),
1505 presented: vec![],
1506 }
1507 .into(),
1508 super::CertificateError::NotValidForNameContext {
1509 expected: ServerName::try_from("example.com")
1510 .unwrap()
1511 .to_owned(),
1512 presented: vec!["DnsName(\"hello.com\")".into()],
1513 }
1514 .into(),
1515 super::CertificateError::NotValidForNameContext {
1516 expected: ServerName::try_from("example.com")
1517 .unwrap()
1518 .to_owned(),
1519 presented: vec![
1520 "DnsName(\"hello.com\")".into(),
1521 "DnsName(\"goodbye.com\")".into(),
1522 ],
1523 }
1524 .into(),
1525 super::CertificateError::NotValidYetContext {
1526 time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1527 not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1528 }
1529 .into(),
1530 super::CertificateError::ExpiredContext {
1531 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1532 not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1533 }
1534 .into(),
1535 super::CertificateError::ExpiredRevocationListContext {
1536 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1537 next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1538 }
1539 .into(),
1540 super::CertificateError::InvalidOcspResponse.into(),
1541 Error::General("undocumented error".to_string()),
1542 Error::FailedToGetCurrentTime,
1543 Error::FailedToGetRandomBytes,
1544 Error::HandshakeNotComplete,
1545 Error::PeerSentOversizedRecord,
1546 Error::NoApplicationProtocol,
1547 Error::BadMaxFragmentSize,
1548 Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
1549 Error::InconsistentKeys(InconsistentKeys::Unknown),
1550 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
1551 Error::Unreachable("smoke"),
1552 super::ApiMisuse::ExporterAlreadyUsed.into(),
1553 Error::Other(OtherError::new(TestError)),
1554 ];
1555
1556 for err in all {
1557 println!("{err:?}:");
1558 println!(" fmt '{err}'");
1559 }
1560 }
1561
1562 #[derive(Debug)]
1563 struct TestError;
1564
1565 impl core::fmt::Display for TestError {
1566 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
1567 write!(f, "test error")
1568 }
1569 }
1570
1571 impl core::error::Error for TestError {}
1572
1573 #[test]
1574 fn alert_display() {
1575 println!("Review the following error messages for syntax and grammar errors:");
1576 for u in 0..=u8::MAX {
1577 let err = Error::AlertReceived(AlertDescription::from(u));
1578 println!(" - {err}");
1579 }
1580
1581 }
1583
1584 #[test]
1585 fn rand_error_mapping() {
1586 use super::rand;
1587 let err: Error = rand::GetRandomFailed.into();
1588 assert_eq!(err, Error::FailedToGetRandomBytes);
1589 }
1590
1591 #[cfg(feature = "std")]
1592 #[test]
1593 fn time_error_mapping() {
1594 use std::time::SystemTime;
1595
1596 let time_error = SystemTime::UNIX_EPOCH
1597 .duration_since(SystemTime::now())
1598 .unwrap_err();
1599 let err: Error = time_error.into();
1600 assert_eq!(err, Error::FailedToGetCurrentTime);
1601 }
1602}