1use alloc::format;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5#[cfg(feature = "std")]
6use std::time::SystemTimeError;
7
8use pki_types::{AlgorithmIdentifier, EchConfigListBytes, ServerName, UnixTime};
9use webpki::KeyUsage;
10
11use crate::enums::{AlertDescription, ContentType, HandshakeType};
12use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
13use crate::rand;
14
15#[non_exhaustive]
17#[derive(Debug, PartialEq, Clone)]
18pub enum Error {
19 InappropriateMessage {
25 expect_types: Vec<ContentType>,
27 got_type: ContentType,
29 },
30
31 InappropriateHandshakeMessage {
35 expect_types: Vec<HandshakeType>,
37 got_type: HandshakeType,
39 },
40
41 InvalidEncryptedClientHello(EncryptedClientHelloError),
43
44 InvalidMessage(InvalidMessage),
46
47 NoCertificatesPresented,
49
50 UnsupportedNameType,
52
53 DecryptError,
55
56 EncryptError,
59
60 PeerIncompatible(PeerIncompatible),
63
64 PeerMisbehaved(PeerMisbehaved),
67
68 AlertReceived(AlertDescription),
70
71 InvalidCertificate(CertificateError),
76
77 InvalidCertRevocationList(CertRevocationListError),
79
80 General(String),
82
83 FailedToGetCurrentTime,
85
86 FailedToGetRandomBytes,
88
89 HandshakeNotComplete,
92
93 PeerSentOversizedRecord,
95
96 NoApplicationProtocol,
98
99 BadMaxFragmentSize,
102
103 InconsistentKeys(InconsistentKeys),
113
114 RejectedEch(RejectedEch),
121
122 Other(OtherError),
130}
131
132#[non_exhaustive]
136#[derive(Clone, Copy, Debug, Eq, PartialEq)]
137pub enum InconsistentKeys {
138 KeyMismatch,
142
143 Unknown,
147}
148
149impl From<InconsistentKeys> for Error {
150 #[inline]
151 fn from(e: InconsistentKeys) -> Self {
152 Self::InconsistentKeys(e)
153 }
154}
155
156#[non_exhaustive]
158#[derive(Debug, Clone, Copy, PartialEq)]
159pub enum InvalidMessage {
160 CertificatePayloadTooLarge,
162 HandshakePayloadTooLarge,
164 InvalidCcs,
166 InvalidContentType,
168 InvalidCertificateStatusType,
170 InvalidCertRequest,
172 InvalidDhParams,
174 InvalidEmptyPayload,
176 InvalidKeyUpdate,
178 InvalidServerName,
180 MessageTooLarge,
182 MessageTooShort,
184 MissingData(&'static str),
186 MissingKeyExchange,
188 NoSignatureSchemes,
190 TrailingData(&'static str),
192 UnexpectedMessage(&'static str),
194 UnknownProtocolVersion,
196 UnsupportedCompression,
198 UnsupportedCurveType,
200 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
202 EmptyTicketValue,
204 IllegalEmptyList(&'static str),
208 IllegalEmptyValue,
210 DuplicateExtension(u16),
212 PreSharedKeyIsNotFinalExtension,
214 UnknownHelloRetryRequestExtension,
216 UnknownCertificateExtension,
218}
219
220impl From<InvalidMessage> for Error {
221 #[inline]
222 fn from(e: InvalidMessage) -> Self {
223 Self::InvalidMessage(e)
224 }
225}
226
227impl From<InvalidMessage> for AlertDescription {
228 fn from(e: InvalidMessage) -> Self {
229 match e {
230 InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
231 InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
232 InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
233 _ => Self::DecodeError,
234 }
235 }
236}
237
238#[allow(missing_docs)]
249#[non_exhaustive]
250#[derive(Debug, PartialEq, Clone)]
251pub enum PeerMisbehaved {
252 AttemptedDowngradeToTls12WhenTls13IsSupported,
253 BadCertChainExtensions,
254 DisallowedEncryptedExtension,
255 DuplicateClientHelloExtensions,
256 DuplicateEncryptedExtensions,
257 DuplicateHelloRetryRequestExtensions,
258 DuplicateNewSessionTicketExtensions,
259 DuplicateServerHelloExtensions,
260 DuplicateServerNameTypes,
261 EarlyDataAttemptedInSecondClientHello,
262 EarlyDataExtensionWithoutResumption,
263 EarlyDataOfferedWithVariedCipherSuite,
264 HandshakeHashVariedAfterRetry,
265 IllegalHelloRetryRequestWithEmptyCookie,
266 IllegalHelloRetryRequestWithNoChanges,
267 IllegalHelloRetryRequestWithOfferedGroup,
268 IllegalHelloRetryRequestWithUnofferedCipherSuite,
269 IllegalHelloRetryRequestWithUnofferedNamedGroup,
270 IllegalHelloRetryRequestWithUnsupportedVersion,
271 IllegalHelloRetryRequestWithWrongSessionId,
272 IllegalHelloRetryRequestWithInvalidEch,
273 IllegalMiddleboxChangeCipherSpec,
274 IllegalTlsInnerPlaintext,
275 IncorrectBinder,
276 InvalidCertCompression,
277 InvalidMaxEarlyDataSize,
278 InvalidKeyShare,
279 KeyEpochWithPendingFragment,
280 KeyUpdateReceivedInQuicConnection,
281 MessageInterleavedWithHandshakeMessage,
282 MissingBinderInPskExtension,
283 MissingKeyShare,
284 MissingPskModesExtension,
285 MissingQuicTransportParameters,
286 OfferedDuplicateCertificateCompressions,
287 OfferedDuplicateKeyShares,
288 OfferedEarlyDataWithOldProtocolVersion,
289 OfferedEmptyApplicationProtocol,
290 OfferedIncorrectCompressions,
291 PskExtensionMustBeLast,
292 PskExtensionWithMismatchedIdsAndBinders,
293 RefusedToFollowHelloRetryRequest,
294 RejectedEarlyDataInterleavedWithHandshakeMessage,
295 ResumptionAttemptedWithVariedEms,
296 ResumptionOfferedWithVariedCipherSuite,
297 ResumptionOfferedWithVariedEms,
298 ResumptionOfferedWithIncompatibleCipherSuite,
299 SelectedDifferentCipherSuiteAfterRetry,
300 SelectedInvalidPsk,
301 SelectedTls12UsingTls13VersionExtension,
302 SelectedUnofferedApplicationProtocol,
303 SelectedUnofferedCertCompression,
304 SelectedUnofferedCipherSuite,
305 SelectedUnofferedCompression,
306 SelectedUnofferedKxGroup,
307 SelectedUnofferedPsk,
308 SelectedUnusableCipherSuiteForVersion,
309 ServerEchoedCompatibilitySessionId,
310 ServerHelloMustOfferUncompressedEcPoints,
311 ServerNameDifferedOnRetry,
312 ServerNameMustContainOneHostName,
313 SignedKxWithWrongAlgorithm,
314 SignedHandshakeWithUnadvertisedSigScheme,
315 TooManyEmptyFragments,
316 TooManyKeyUpdateRequests,
317 TooManyRenegotiationRequests,
318 TooManyWarningAlertsReceived,
319 TooMuchEarlyDataReceived,
320 UnexpectedCleartextExtension,
321 UnsolicitedCertExtension,
322 UnsolicitedEncryptedExtension,
323 UnsolicitedSctList,
324 UnsolicitedServerHelloExtension,
325 WrongGroupForKeyShare,
326 UnsolicitedEchExtension,
327}
328
329impl From<PeerMisbehaved> for Error {
330 #[inline]
331 fn from(e: PeerMisbehaved) -> Self {
332 Self::PeerMisbehaved(e)
333 }
334}
335
336#[allow(missing_docs)]
342#[non_exhaustive]
343#[derive(Debug, PartialEq, Clone)]
344pub enum PeerIncompatible {
345 EcPointsExtensionRequired,
346 ExtendedMasterSecretExtensionRequired,
347 IncorrectCertificateTypeExtension,
348 KeyShareExtensionRequired,
349 NamedGroupsExtensionRequired,
350 NoCertificateRequestSignatureSchemesInCommon,
351 NoCipherSuitesInCommon,
352 NoEcPointFormatsInCommon,
353 NoKxGroupsInCommon,
354 NoSignatureSchemesInCommon,
355 NullCompressionRequired,
356 ServerDoesNotSupportTls12Or13,
357 ServerSentHelloRetryRequestWithUnknownExtension,
358 ServerTlsVersionIsDisabledByOurConfig,
359 SignatureAlgorithmsExtensionRequired,
360 SupportedVersionsExtensionRequired,
361 Tls12NotOffered,
362 Tls12NotOfferedOrEnabled,
363 Tls13RequiredForQuic,
364 UncompressedEcPointsRequired,
365 UnsolicitedCertificateTypeExtension,
366}
367
368impl From<PeerIncompatible> for Error {
369 #[inline]
370 fn from(e: PeerIncompatible) -> Self {
371 Self::PeerIncompatible(e)
372 }
373}
374
375#[non_exhaustive]
383#[derive(Debug, Clone)]
384pub enum CertificateError {
385 BadEncoding,
387
388 Expired,
390
391 ExpiredContext {
396 time: UnixTime,
398 not_after: UnixTime,
400 },
401
402 NotValidYet,
404
405 NotValidYetContext {
410 time: UnixTime,
412 not_before: UnixTime,
414 },
415
416 Revoked,
418
419 UnhandledCriticalExtension,
422
423 UnknownIssuer,
425
426 UnknownRevocationStatus,
428
429 ExpiredRevocationList,
431
432 ExpiredRevocationListContext {
437 time: UnixTime,
439 next_update: UnixTime,
441 },
442
443 BadSignature,
446
447 #[deprecated(
449 since = "0.23.29",
450 note = "use `UnsupportedSignatureAlgorithmContext` instead"
451 )]
452 UnsupportedSignatureAlgorithm,
453
454 UnsupportedSignatureAlgorithmContext {
456 signature_algorithm_id: Vec<u8>,
458 supported_algorithms: Vec<AlgorithmIdentifier>,
460 },
461
462 UnsupportedSignatureAlgorithmForPublicKeyContext {
464 signature_algorithm_id: Vec<u8>,
466 public_key_algorithm_id: Vec<u8>,
468 },
469
470 NotValidForName,
473
474 NotValidForNameContext {
480 expected: ServerName<'static>,
482
483 presented: Vec<String>,
488 },
489
490 InvalidPurpose,
492
493 InvalidPurposeContext {
498 required: ExtendedKeyPurpose,
500 presented: Vec<ExtendedKeyPurpose>,
502 },
503
504 InvalidOcspResponse,
513
514 ApplicationVerificationFailure,
517
518 Other(OtherError),
529}
530
531impl PartialEq<Self> for CertificateError {
532 fn eq(&self, other: &Self) -> bool {
533 use CertificateError::*;
534 #[allow(clippy::match_like_matches_macro)]
535 match (self, other) {
536 (BadEncoding, BadEncoding) => true,
537 (Expired, Expired) => true,
538 (
539 ExpiredContext {
540 time: left_time,
541 not_after: left_not_after,
542 },
543 ExpiredContext {
544 time: right_time,
545 not_after: right_not_after,
546 },
547 ) => (left_time, left_not_after) == (right_time, right_not_after),
548 (NotValidYet, NotValidYet) => true,
549 (
550 NotValidYetContext {
551 time: left_time,
552 not_before: left_not_before,
553 },
554 NotValidYetContext {
555 time: right_time,
556 not_before: right_not_before,
557 },
558 ) => (left_time, left_not_before) == (right_time, right_not_before),
559 (Revoked, Revoked) => true,
560 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
561 (UnknownIssuer, UnknownIssuer) => true,
562 (BadSignature, BadSignature) => true,
563 #[allow(deprecated)]
564 (UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm) => true,
565 (
566 UnsupportedSignatureAlgorithmContext {
567 signature_algorithm_id: left_signature_algorithm_id,
568 supported_algorithms: left_supported_algorithms,
569 },
570 UnsupportedSignatureAlgorithmContext {
571 signature_algorithm_id: right_signature_algorithm_id,
572 supported_algorithms: right_supported_algorithms,
573 },
574 ) => {
575 (left_signature_algorithm_id, left_supported_algorithms)
576 == (right_signature_algorithm_id, right_supported_algorithms)
577 }
578 (
579 UnsupportedSignatureAlgorithmForPublicKeyContext {
580 signature_algorithm_id: left_signature_algorithm_id,
581 public_key_algorithm_id: left_public_key_algorithm_id,
582 },
583 UnsupportedSignatureAlgorithmForPublicKeyContext {
584 signature_algorithm_id: right_signature_algorithm_id,
585 public_key_algorithm_id: right_public_key_algorithm_id,
586 },
587 ) => {
588 (left_signature_algorithm_id, left_public_key_algorithm_id)
589 == (right_signature_algorithm_id, right_public_key_algorithm_id)
590 }
591 (NotValidForName, NotValidForName) => true,
592 (
593 NotValidForNameContext {
594 expected: left_expected,
595 presented: left_presented,
596 },
597 NotValidForNameContext {
598 expected: right_expected,
599 presented: right_presented,
600 },
601 ) => (left_expected, left_presented) == (right_expected, right_presented),
602 (InvalidPurpose, InvalidPurpose) => true,
603 (
604 InvalidPurposeContext {
605 required: left_required,
606 presented: left_presented,
607 },
608 InvalidPurposeContext {
609 required: right_required,
610 presented: right_presented,
611 },
612 ) => (left_required, left_presented) == (right_required, right_presented),
613 (InvalidOcspResponse, InvalidOcspResponse) => true,
614 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
615 (UnknownRevocationStatus, UnknownRevocationStatus) => true,
616 (ExpiredRevocationList, ExpiredRevocationList) => true,
617 (
618 ExpiredRevocationListContext {
619 time: left_time,
620 next_update: left_next_update,
621 },
622 ExpiredRevocationListContext {
623 time: right_time,
624 next_update: right_next_update,
625 },
626 ) => (left_time, left_next_update) == (right_time, right_next_update),
627 _ => false,
628 }
629 }
630}
631
632impl From<CertificateError> for AlertDescription {
636 fn from(e: CertificateError) -> Self {
637 use CertificateError::*;
638 match e {
639 BadEncoding
640 | UnhandledCriticalExtension
641 | NotValidForName
642 | NotValidForNameContext { .. } => Self::BadCertificate,
643 Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
647 Self::CertificateExpired
648 }
649 Revoked => Self::CertificateRevoked,
650 UnknownIssuer
653 | UnknownRevocationStatus
654 | ExpiredRevocationList
655 | ExpiredRevocationListContext { .. } => Self::UnknownCa,
656 InvalidOcspResponse => Self::BadCertificateStatusResponse,
657 #[allow(deprecated)]
658 BadSignature
659 | UnsupportedSignatureAlgorithm
660 | UnsupportedSignatureAlgorithmContext { .. }
661 | UnsupportedSignatureAlgorithmForPublicKeyContext { .. } => Self::DecryptError,
662 InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate,
663 ApplicationVerificationFailure => Self::AccessDenied,
664 Other(..) => Self::CertificateUnknown,
669 }
670 }
671}
672
673impl fmt::Display for CertificateError {
674 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
675 match self {
676 #[cfg(feature = "std")]
677 Self::NotValidForNameContext {
678 expected,
679 presented,
680 } => {
681 write!(
682 f,
683 "certificate not valid for name {:?}; certificate ",
684 expected.to_str()
685 )?;
686
687 match presented.as_slice() {
688 &[] => write!(
689 f,
690 "is not valid for any names (according to its subjectAltName extension)"
691 ),
692 [one] => write!(f, "is only valid for {one}"),
693 many => {
694 write!(f, "is only valid for ")?;
695
696 let n = many.len();
697 let all_but_last = &many[..n - 1];
698 let last = &many[n - 1];
699
700 for (i, name) in all_but_last.iter().enumerate() {
701 write!(f, "{name}")?;
702 if i < n - 2 {
703 write!(f, ", ")?;
704 }
705 }
706 write!(f, " or {last}")
707 }
708 }
709 }
710
711 Self::ExpiredContext { time, not_after } => write!(
712 f,
713 "certificate expired: verification time {} (UNIX), \
714 but certificate is not valid after {} \
715 ({} seconds ago)",
716 time.as_secs(),
717 not_after.as_secs(),
718 time.as_secs()
719 .saturating_sub(not_after.as_secs())
720 ),
721
722 Self::NotValidYetContext { time, not_before } => write!(
723 f,
724 "certificate not valid yet: verification time {} (UNIX), \
725 but certificate is not valid before {} \
726 ({} seconds in future)",
727 time.as_secs(),
728 not_before.as_secs(),
729 not_before
730 .as_secs()
731 .saturating_sub(time.as_secs())
732 ),
733
734 Self::ExpiredRevocationListContext { time, next_update } => write!(
735 f,
736 "certificate revocation list expired: \
737 verification time {} (UNIX), \
738 but CRL is not valid after {} \
739 ({} seconds ago)",
740 time.as_secs(),
741 next_update.as_secs(),
742 time.as_secs()
743 .saturating_sub(next_update.as_secs())
744 ),
745
746 Self::InvalidPurposeContext {
747 required,
748 presented,
749 } => {
750 write!(
751 f,
752 "certificate does not allow extended key usage for {required}, allows "
753 )?;
754 for (i, eku) in presented.iter().enumerate() {
755 if i > 0 {
756 write!(f, ", ")?;
757 }
758 write!(f, "{eku}")?;
759 }
760 Ok(())
761 }
762
763 other => write!(f, "{other:?}"),
764 }
765 }
766}
767
768impl From<CertificateError> for Error {
769 #[inline]
770 fn from(e: CertificateError) -> Self {
771 Self::InvalidCertificate(e)
772 }
773}
774
775#[non_exhaustive]
780#[derive(Clone, Debug, Eq, PartialEq)]
781pub enum ExtendedKeyPurpose {
782 ClientAuth,
784 ServerAuth,
786 Other(Vec<usize>),
790}
791
792impl ExtendedKeyPurpose {
793 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
794 let values = values.collect::<Vec<_>>();
795 match &*values {
796 KeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
797 KeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
798 _ => Self::Other(values),
799 }
800 }
801}
802
803impl fmt::Display for ExtendedKeyPurpose {
804 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
805 match self {
806 Self::ClientAuth => write!(f, "client authentication"),
807 Self::ServerAuth => write!(f, "server authentication"),
808 Self::Other(values) => {
809 for (i, value) in values.iter().enumerate() {
810 if i > 0 {
811 write!(f, ", ")?;
812 }
813 write!(f, "{value}")?;
814 }
815 Ok(())
816 }
817 }
818 }
819}
820
821#[non_exhaustive]
823#[derive(Debug, Clone)]
824pub enum CertRevocationListError {
825 BadSignature,
827
828 #[deprecated(
830 since = "0.23.29",
831 note = "use `UnsupportedSignatureAlgorithmContext` instead"
832 )]
833 UnsupportedSignatureAlgorithm,
834
835 UnsupportedSignatureAlgorithmContext {
837 signature_algorithm_id: Vec<u8>,
839 supported_algorithms: Vec<AlgorithmIdentifier>,
841 },
842
843 UnsupportedSignatureAlgorithmForPublicKeyContext {
845 signature_algorithm_id: Vec<u8>,
847 public_key_algorithm_id: Vec<u8>,
849 },
850
851 InvalidCrlNumber,
853
854 InvalidRevokedCertSerialNumber,
856
857 IssuerInvalidForCrl,
859
860 Other(OtherError),
864
865 ParseError,
867
868 UnsupportedCrlVersion,
870
871 UnsupportedCriticalExtension,
873
874 UnsupportedDeltaCrl,
876
877 UnsupportedIndirectCrl,
880
881 UnsupportedRevocationReason,
886}
887
888impl PartialEq<Self> for CertRevocationListError {
889 fn eq(&self, other: &Self) -> bool {
890 use CertRevocationListError::*;
891 #[allow(clippy::match_like_matches_macro)]
892 match (self, other) {
893 (BadSignature, BadSignature) => true,
894 #[allow(deprecated)]
895 (UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm) => true,
896 (
897 UnsupportedSignatureAlgorithmContext {
898 signature_algorithm_id: left_signature_algorithm_id,
899 supported_algorithms: left_supported_algorithms,
900 },
901 UnsupportedSignatureAlgorithmContext {
902 signature_algorithm_id: right_signature_algorithm_id,
903 supported_algorithms: right_supported_algorithms,
904 },
905 ) => {
906 (left_signature_algorithm_id, left_supported_algorithms)
907 == (right_signature_algorithm_id, right_supported_algorithms)
908 }
909 (
910 UnsupportedSignatureAlgorithmForPublicKeyContext {
911 signature_algorithm_id: left_signature_algorithm_id,
912 public_key_algorithm_id: left_public_key_algorithm_id,
913 },
914 UnsupportedSignatureAlgorithmForPublicKeyContext {
915 signature_algorithm_id: right_signature_algorithm_id,
916 public_key_algorithm_id: right_public_key_algorithm_id,
917 },
918 ) => {
919 (left_signature_algorithm_id, left_public_key_algorithm_id)
920 == (right_signature_algorithm_id, right_public_key_algorithm_id)
921 }
922 (InvalidCrlNumber, InvalidCrlNumber) => true,
923 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
924 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
925 (ParseError, ParseError) => true,
926 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
927 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
928 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
929 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
930 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
931 _ => false,
932 }
933 }
934}
935
936impl From<CertRevocationListError> for Error {
937 #[inline]
938 fn from(e: CertRevocationListError) -> Self {
939 Self::InvalidCertRevocationList(e)
940 }
941}
942
943#[non_exhaustive]
945#[derive(Debug, Clone, Eq, PartialEq)]
946pub enum EncryptedClientHelloError {
947 InvalidConfigList,
949 NoCompatibleConfig,
951 SniRequired,
953}
954
955impl From<EncryptedClientHelloError> for Error {
956 #[inline]
957 fn from(e: EncryptedClientHelloError) -> Self {
958 Self::InvalidEncryptedClientHello(e)
959 }
960}
961
962#[non_exhaustive]
968#[derive(Debug, Clone, PartialEq)]
969pub struct RejectedEch {
970 pub(crate) retry_configs: Option<Vec<EchConfigPayload>>,
971}
972
973impl RejectedEch {
974 pub fn can_retry(&self) -> bool {
980 self.retry_configs.is_some()
981 }
982
983 pub fn retry_configs(&self) -> Option<EchConfigListBytes<'static>> {
985 let Some(retry_configs) = &self.retry_configs else {
986 return None;
987 };
988
989 let mut tls_encoded_list = Vec::new();
990 retry_configs.encode(&mut tls_encoded_list);
991
992 Some(EchConfigListBytes::from(tls_encoded_list))
993 }
994}
995
996impl From<RejectedEch> for Error {
997 fn from(rejected_error: RejectedEch) -> Self {
998 Self::RejectedEch(rejected_error)
999 }
1000}
1001
1002fn join<T: fmt::Debug>(items: &[T]) -> String {
1003 items
1004 .iter()
1005 .map(|x| format!("{x:?}"))
1006 .collect::<Vec<String>>()
1007 .join(" or ")
1008}
1009
1010impl fmt::Display for Error {
1011 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1012 match self {
1013 Self::InappropriateMessage {
1014 expect_types,
1015 got_type,
1016 } => write!(
1017 f,
1018 "received unexpected message: got {:?} when expecting {}",
1019 got_type,
1020 join::<ContentType>(expect_types)
1021 ),
1022 Self::InappropriateHandshakeMessage {
1023 expect_types,
1024 got_type,
1025 } => write!(
1026 f,
1027 "received unexpected handshake message: got {:?} when expecting {}",
1028 got_type,
1029 join::<HandshakeType>(expect_types)
1030 ),
1031 Self::InvalidMessage(typ) => {
1032 write!(f, "received corrupt message of type {typ:?}")
1033 }
1034 Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
1035 Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
1036 Self::AlertReceived(alert) => write!(f, "received fatal alert: the peer {alert}"),
1037 Self::InvalidCertificate(err) => {
1038 write!(f, "invalid peer certificate: {err}")
1039 }
1040 Self::InvalidCertRevocationList(err) => {
1041 write!(f, "invalid certificate revocation list: {err:?}")
1042 }
1043 Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
1044 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
1045 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
1046 Self::InvalidEncryptedClientHello(err) => {
1047 write!(f, "encrypted client hello failure: {err:?}")
1048 }
1049 Self::EncryptError => write!(f, "cannot encrypt message"),
1050 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
1051 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
1052 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
1053 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
1054 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
1055 Self::BadMaxFragmentSize => {
1056 write!(f, "the supplied max_fragment_size was too small or large")
1057 }
1058 Self::InconsistentKeys(why) => {
1059 write!(f, "keys may not be consistent: {why:?}")
1060 }
1061 Self::RejectedEch(why) => {
1062 write!(
1063 f,
1064 "server rejected encrypted client hello (ECH) {} retry configs",
1065 if why.can_retry() { "with" } else { "without" }
1066 )
1067 }
1068 Self::General(err) => write!(f, "unexpected error: {err}"),
1069 Self::Other(err) => write!(f, "other error: {err}"),
1070 }
1071 }
1072}
1073
1074#[cfg(feature = "std")]
1075impl From<SystemTimeError> for Error {
1076 #[inline]
1077 fn from(_: SystemTimeError) -> Self {
1078 Self::FailedToGetCurrentTime
1079 }
1080}
1081
1082#[cfg(feature = "std")]
1083impl std::error::Error for Error {}
1084
1085impl From<rand::GetRandomFailed> for Error {
1086 fn from(_: rand::GetRandomFailed) -> Self {
1087 Self::FailedToGetRandomBytes
1088 }
1089}
1090
1091mod other_error {
1092 use core::fmt;
1093 #[cfg(feature = "std")]
1094 use std::error::Error as StdError;
1095
1096 use super::Error;
1097 #[cfg(feature = "std")]
1098 use crate::sync::Arc;
1099
1100 #[allow(clippy::exhaustive_structs)]
1107 #[derive(Debug, Clone)]
1108 pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
1109
1110 impl PartialEq<Self> for OtherError {
1111 fn eq(&self, _other: &Self) -> bool {
1112 false
1113 }
1114 }
1115
1116 impl From<OtherError> for Error {
1117 fn from(value: OtherError) -> Self {
1118 Self::Other(value)
1119 }
1120 }
1121
1122 impl fmt::Display for OtherError {
1123 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1124 #[cfg(feature = "std")]
1125 {
1126 write!(f, "{}", self.0)
1127 }
1128 #[cfg(not(feature = "std"))]
1129 {
1130 f.write_str("no further information available")
1131 }
1132 }
1133 }
1134
1135 #[cfg(feature = "std")]
1136 impl StdError for OtherError {
1137 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1138 Some(self.0.as_ref())
1139 }
1140 }
1141}
1142
1143pub use other_error::OtherError;
1144
1145use crate::msgs::codec::Codec;
1146
1147#[cfg(test)]
1148mod tests {
1149 use core::time::Duration;
1150 use std::prelude::v1::*;
1151 use std::{println, vec};
1152
1153 use pki_types::ServerName;
1154
1155 use super::{
1156 AlertDescription, CertRevocationListError, Error, InconsistentKeys, InvalidMessage,
1157 OtherError, UnixTime,
1158 };
1159 #[cfg(feature = "std")]
1160 use crate::sync::Arc;
1161
1162 #[test]
1163 fn certificate_error_equality() {
1164 use super::CertificateError::*;
1165 assert_eq!(BadEncoding, BadEncoding);
1166 assert_eq!(Expired, Expired);
1167 let context = ExpiredContext {
1168 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1169 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1170 };
1171 assert_eq!(context, context);
1172 assert_ne!(
1173 context,
1174 ExpiredContext {
1175 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1176 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1177 }
1178 );
1179 assert_ne!(
1180 context,
1181 ExpiredContext {
1182 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1183 not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1184 }
1185 );
1186 assert_eq!(NotValidYet, NotValidYet);
1187 let context = NotValidYetContext {
1188 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1189 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1190 };
1191 assert_eq!(context, context);
1192 assert_ne!(
1193 context,
1194 NotValidYetContext {
1195 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1196 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1197 }
1198 );
1199 assert_ne!(
1200 context,
1201 NotValidYetContext {
1202 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1203 not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1204 }
1205 );
1206 assert_eq!(Revoked, Revoked);
1207 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
1208 assert_eq!(UnknownIssuer, UnknownIssuer);
1209 assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
1210 assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
1211 let context = ExpiredRevocationListContext {
1212 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1213 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1214 };
1215 assert_eq!(context, context);
1216 assert_ne!(
1217 context,
1218 ExpiredRevocationListContext {
1219 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1220 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1221 }
1222 );
1223 assert_ne!(
1224 context,
1225 ExpiredRevocationListContext {
1226 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1227 next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1228 }
1229 );
1230 assert_eq!(BadSignature, BadSignature);
1231 #[allow(deprecated)]
1232 {
1233 assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm);
1234 }
1235 assert_eq!(
1236 UnsupportedSignatureAlgorithmContext {
1237 signature_algorithm_id: vec![1, 2, 3],
1238 supported_algorithms: vec![]
1239 },
1240 UnsupportedSignatureAlgorithmContext {
1241 signature_algorithm_id: vec![1, 2, 3],
1242 supported_algorithms: vec![]
1243 }
1244 );
1245 assert_eq!(
1246 UnsupportedSignatureAlgorithmForPublicKeyContext {
1247 signature_algorithm_id: vec![1, 2, 3],
1248 public_key_algorithm_id: vec![4, 5, 6]
1249 },
1250 UnsupportedSignatureAlgorithmForPublicKeyContext {
1251 signature_algorithm_id: vec![1, 2, 3],
1252 public_key_algorithm_id: vec![4, 5, 6]
1253 }
1254 );
1255 assert_eq!(NotValidForName, NotValidForName);
1256 let context = NotValidForNameContext {
1257 expected: ServerName::try_from("example.com")
1258 .unwrap()
1259 .to_owned(),
1260 presented: vec!["other.com".into()],
1261 };
1262 assert_eq!(context, context);
1263 assert_ne!(
1264 context,
1265 NotValidForNameContext {
1266 expected: ServerName::try_from("example.com")
1267 .unwrap()
1268 .to_owned(),
1269 presented: vec![]
1270 }
1271 );
1272 assert_ne!(
1273 context,
1274 NotValidForNameContext {
1275 expected: ServerName::try_from("huh.com")
1276 .unwrap()
1277 .to_owned(),
1278 presented: vec!["other.com".into()],
1279 }
1280 );
1281 assert_eq!(InvalidPurpose, InvalidPurpose);
1282 assert_eq!(
1283 ApplicationVerificationFailure,
1284 ApplicationVerificationFailure
1285 );
1286 assert_eq!(InvalidOcspResponse, InvalidOcspResponse);
1287 let other = Other(OtherError(
1288 #[cfg(feature = "std")]
1289 Arc::from(Box::from("")),
1290 ));
1291 assert_ne!(other, other);
1292 assert_ne!(BadEncoding, Expired);
1293 }
1294
1295 #[test]
1296 fn crl_error_equality() {
1297 use super::CertRevocationListError::*;
1298 assert_eq!(BadSignature, BadSignature);
1299 #[allow(deprecated)]
1300 {
1301 assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm);
1302 }
1303 assert_eq!(
1304 UnsupportedSignatureAlgorithmContext {
1305 signature_algorithm_id: vec![1, 2, 3],
1306 supported_algorithms: vec![]
1307 },
1308 UnsupportedSignatureAlgorithmContext {
1309 signature_algorithm_id: vec![1, 2, 3],
1310 supported_algorithms: vec![]
1311 }
1312 );
1313 assert_eq!(
1314 UnsupportedSignatureAlgorithmForPublicKeyContext {
1315 signature_algorithm_id: vec![1, 2, 3],
1316 public_key_algorithm_id: vec![4, 5, 6]
1317 },
1318 UnsupportedSignatureAlgorithmForPublicKeyContext {
1319 signature_algorithm_id: vec![1, 2, 3],
1320 public_key_algorithm_id: vec![4, 5, 6]
1321 }
1322 );
1323 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
1324 assert_eq!(
1325 InvalidRevokedCertSerialNumber,
1326 InvalidRevokedCertSerialNumber
1327 );
1328 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
1329 assert_eq!(ParseError, ParseError);
1330 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
1331 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
1332 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
1333 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
1334 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
1335 let other = Other(OtherError(
1336 #[cfg(feature = "std")]
1337 Arc::from(Box::from("")),
1338 ));
1339 assert_ne!(other, other);
1340 assert_ne!(BadSignature, InvalidCrlNumber);
1341 }
1342
1343 #[test]
1344 #[cfg(feature = "std")]
1345 fn other_error_equality() {
1346 let other_error = OtherError(Arc::from(Box::from("")));
1347 assert_ne!(other_error, other_error);
1348 let other: Error = other_error.into();
1349 assert_ne!(other, other);
1350 }
1351
1352 #[test]
1353 fn smoke() {
1354 use crate::enums::{AlertDescription, ContentType, HandshakeType};
1355
1356 let all = vec![
1357 Error::InappropriateMessage {
1358 expect_types: vec![ContentType::Alert],
1359 got_type: ContentType::Handshake,
1360 },
1361 Error::InappropriateHandshakeMessage {
1362 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
1363 got_type: HandshakeType::ServerHello,
1364 },
1365 Error::InvalidMessage(InvalidMessage::InvalidCcs),
1366 Error::NoCertificatesPresented,
1367 Error::DecryptError,
1368 super::PeerIncompatible::Tls12NotOffered.into(),
1369 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
1370 Error::AlertReceived(AlertDescription::ExportRestriction),
1371 super::CertificateError::Expired.into(),
1372 super::CertificateError::NotValidForNameContext {
1373 expected: ServerName::try_from("example.com")
1374 .unwrap()
1375 .to_owned(),
1376 presented: vec![],
1377 }
1378 .into(),
1379 super::CertificateError::NotValidForNameContext {
1380 expected: ServerName::try_from("example.com")
1381 .unwrap()
1382 .to_owned(),
1383 presented: vec!["DnsName(\"hello.com\")".into()],
1384 }
1385 .into(),
1386 super::CertificateError::NotValidForNameContext {
1387 expected: ServerName::try_from("example.com")
1388 .unwrap()
1389 .to_owned(),
1390 presented: vec![
1391 "DnsName(\"hello.com\")".into(),
1392 "DnsName(\"goodbye.com\")".into(),
1393 ],
1394 }
1395 .into(),
1396 super::CertificateError::NotValidYetContext {
1397 time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1398 not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1399 }
1400 .into(),
1401 super::CertificateError::ExpiredContext {
1402 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1403 not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1404 }
1405 .into(),
1406 super::CertificateError::ExpiredRevocationListContext {
1407 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1408 next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1409 }
1410 .into(),
1411 super::CertificateError::InvalidOcspResponse.into(),
1412 Error::General("undocumented error".to_string()),
1413 Error::FailedToGetCurrentTime,
1414 Error::FailedToGetRandomBytes,
1415 Error::HandshakeNotComplete,
1416 Error::PeerSentOversizedRecord,
1417 Error::NoApplicationProtocol,
1418 Error::BadMaxFragmentSize,
1419 Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
1420 Error::InconsistentKeys(InconsistentKeys::Unknown),
1421 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
1422 Error::Other(OtherError(
1423 #[cfg(feature = "std")]
1424 Arc::from(Box::from("")),
1425 )),
1426 ];
1427
1428 for err in all {
1429 println!("{err:?}:");
1430 println!(" fmt '{err}'");
1431 }
1432 }
1433
1434 #[test]
1435 fn alert_display() {
1436 println!("Review the following error messages for syntax and grammar errors:");
1437 for u in 0..=u8::MAX {
1438 let err = Error::AlertReceived(AlertDescription::from(u));
1439 println!(" - {err}");
1440 }
1441
1442 }
1444
1445 #[test]
1446 fn rand_error_mapping() {
1447 use super::rand;
1448 let err: Error = rand::GetRandomFailed.into();
1449 assert_eq!(err, Error::FailedToGetRandomBytes);
1450 }
1451
1452 #[cfg(feature = "std")]
1453 #[test]
1454 fn time_error_mapping() {
1455 use std::time::SystemTime;
1456
1457 let time_error = SystemTime::UNIX_EPOCH
1458 .duration_since(SystemTime::now())
1459 .unwrap_err();
1460 let err: Error = time_error.into();
1461 assert_eq!(err, Error::FailedToGetCurrentTime);
1462 }
1463}