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, 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),
107
108 Other(OtherError),
116}
117
118#[non_exhaustive]
122#[derive(Clone, Copy, Debug, Eq, PartialEq)]
123pub enum InconsistentKeys {
124 KeyMismatch,
128
129 Unknown,
133}
134
135impl From<InconsistentKeys> for Error {
136 #[inline]
137 fn from(e: InconsistentKeys) -> Self {
138 Self::InconsistentKeys(e)
139 }
140}
141
142#[non_exhaustive]
144#[derive(Debug, Clone, Copy, PartialEq)]
145pub enum InvalidMessage {
146 CertificatePayloadTooLarge,
148 HandshakePayloadTooLarge,
150 InvalidCcs,
152 InvalidContentType,
154 InvalidCertificateStatusType,
156 InvalidCertRequest,
158 InvalidDhParams,
160 InvalidEmptyPayload,
162 InvalidKeyUpdate,
164 InvalidServerName,
166 MessageTooLarge,
168 MessageTooShort,
170 MissingData(&'static str),
172 MissingKeyExchange,
174 NoSignatureSchemes,
176 TrailingData(&'static str),
178 UnexpectedMessage(&'static str),
180 UnknownProtocolVersion,
182 UnsupportedCompression,
184 UnsupportedCurveType,
186 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
188 EmptyTicketValue,
190 IllegalEmptyList(&'static str),
194 IllegalEmptyValue,
196 DuplicateExtension(u16),
198 PreSharedKeyIsNotFinalExtension,
200 UnknownHelloRetryRequestExtension,
202 UnknownCertificateExtension,
204}
205
206impl From<InvalidMessage> for Error {
207 #[inline]
208 fn from(e: InvalidMessage) -> Self {
209 Self::InvalidMessage(e)
210 }
211}
212
213impl From<InvalidMessage> for AlertDescription {
214 fn from(e: InvalidMessage) -> Self {
215 match e {
216 InvalidMessage::PreSharedKeyIsNotFinalExtension => Self::IllegalParameter,
217 InvalidMessage::DuplicateExtension(_) => Self::IllegalParameter,
218 InvalidMessage::UnknownHelloRetryRequestExtension => Self::UnsupportedExtension,
219 _ => Self::DecodeError,
220 }
221 }
222}
223
224#[non_exhaustive]
225#[allow(missing_docs)]
226#[derive(Debug, PartialEq, Clone)]
227pub enum PeerMisbehaved {
238 AttemptedDowngradeToTls12WhenTls13IsSupported,
239 BadCertChainExtensions,
240 CipherSuiteDifferedOnRetry,
241 DisallowedEncryptedExtension,
242 DuplicateClientHelloExtensions,
243 DuplicateEncryptedExtensions,
244 DuplicateHelloRetryRequestExtensions,
245 DuplicateNewSessionTicketExtensions,
246 DuplicateServerHelloExtensions,
247 DuplicateServerNameTypes,
248 EarlyDataAttemptedInSecondClientHello,
249 EarlyDataExtensionWithoutResumption,
250 EarlyDataOfferedWithVariedCipherSuite,
251 EchAcceptanceVariedAfterRetry,
252 HandshakeHashVariedAfterRetry,
253 IllegalHelloRetryRequestWithEmptyCookie,
254 IllegalHelloRetryRequestWithNoChanges,
255 IllegalHelloRetryRequestWithOfferedGroup,
256 IllegalHelloRetryRequestWithUnofferedCipherSuite,
257 IllegalHelloRetryRequestWithUnofferedNamedGroup,
258 IllegalHelloRetryRequestWithUnsupportedVersion,
259 IllegalHelloRetryRequestWithWrongSessionId,
260 IllegalHelloRetryRequestWithInvalidEch,
261 IllegalMiddleboxChangeCipherSpec,
262 IllegalTlsInnerPlaintext,
263 IncorrectBinder,
264 InvalidCertCompression,
265 InvalidMaxEarlyDataSize,
266 InvalidKeyShare,
267 KeyEpochWithPendingFragment,
268 KeyUpdateReceivedInQuicConnection,
269 MessageInterleavedWithHandshakeMessage,
270 MissingBinderInPskExtension,
271 MissingKeyShare,
272 MissingPskExtensionInSecondClientHello,
273 MissingPskModesExtension,
274 MissingQuicTransportParameters,
275 OfferedDuplicateCertificateCompressions,
276 OfferedDuplicateKeyShares,
277 OfferedEarlyDataWithOldProtocolVersion,
278 OfferedEmptyApplicationProtocol,
279 OfferedIncorrectCompressions,
280 PskExtensionMustBeLast,
281 PskExtensionWithMismatchedIdsAndBinders,
282 RefusedToFollowHelloRetryRequest,
283 RejectedEarlyDataInterleavedWithHandshakeMessage,
284 ResumptionAttemptedWithVariedEms,
285 ResumptionOfferedWithVariedCipherSuite,
286 ResumptionOfferedWithVariedEms,
287 ResumptionOfferedWithIncompatibleCipherSuite,
288 SelectedDifferentCipherSuiteAfterRetry,
289 SelectedInvalidPsk,
290 SelectedTls12UsingTls13VersionExtension,
291 SelectedUnofferedApplicationProtocol,
292 SelectedUnofferedCertCompression,
293 SelectedUnofferedCipherSuite,
294 SelectedUnofferedCompression,
295 SelectedUnofferedKxGroup,
296 SelectedUnofferedPsk,
297 SelectedUnusableCipherSuiteForVersion,
298 ServerEchoedCompatibilitySessionId,
299 ServerHelloMustOfferUncompressedEcPoints,
300 ServerNameDifferedOnRetry,
301 ServerNameMustContainOneHostName,
302 SignedKxWithWrongAlgorithm,
303 SignedHandshakeWithUnadvertisedSigScheme,
304 TooManyEmptyFragments,
305 TooManyKeyUpdateRequests,
306 TooManyRenegotiationRequests,
307 TooManyWarningAlertsReceived,
308 TooMuchEarlyDataReceived,
309 UnexpectedCleartextExtension,
310 UnsolicitedCertExtension,
311 UnsolicitedEncryptedExtension,
312 UnsolicitedSctList,
313 UnsolicitedServerHelloExtension,
314 WrongGroupForKeyShare,
315 UnsolicitedEchExtension,
316}
317
318impl From<PeerMisbehaved> for Error {
319 #[inline]
320 fn from(e: PeerMisbehaved) -> Self {
321 Self::PeerMisbehaved(e)
322 }
323}
324
325#[non_exhaustive]
326#[allow(missing_docs)]
327#[derive(Debug, PartialEq, Clone)]
328pub enum PeerIncompatible {
334 EcPointsExtensionRequired,
335 ExtendedMasterSecretExtensionRequired,
336 IncorrectCertificateTypeExtension,
337 KeyShareExtensionRequired,
338 NamedGroupsExtensionRequired,
339 NoCertificateRequestSignatureSchemesInCommon,
340 NoCipherSuitesInCommon,
341 NoEcPointFormatsInCommon,
342 NoKxGroupsInCommon,
343 NoSignatureSchemesInCommon,
344 NullCompressionRequired,
345 ServerDoesNotSupportTls12Or13,
346 ServerSentHelloRetryRequestWithUnknownExtension,
347 ServerTlsVersionIsDisabledByOurConfig,
348 SignatureAlgorithmsExtensionRequired,
349 SupportedVersionsExtensionRequired,
350 Tls12NotOffered,
351 Tls12NotOfferedOrEnabled,
352 Tls13RequiredForQuic,
353 UncompressedEcPointsRequired,
354 UnsolicitedCertificateTypeExtension,
355 ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
356}
357
358impl From<PeerIncompatible> for Error {
359 #[inline]
360 fn from(e: PeerIncompatible) -> Self {
361 Self::PeerIncompatible(e)
362 }
363}
364
365#[non_exhaustive]
366#[derive(Debug, Clone)]
367pub enum CertificateError {
375 BadEncoding,
377
378 Expired,
380
381 ExpiredContext {
386 time: UnixTime,
388 not_after: UnixTime,
390 },
391
392 NotValidYet,
394
395 NotValidYetContext {
400 time: UnixTime,
402 not_before: UnixTime,
404 },
405
406 Revoked,
408
409 UnhandledCriticalExtension,
412
413 UnknownIssuer,
415
416 UnknownRevocationStatus,
418
419 ExpiredRevocationList,
421
422 ExpiredRevocationListContext {
427 time: UnixTime,
429 next_update: UnixTime,
431 },
432
433 BadSignature,
436
437 #[deprecated(
439 since = "0.23.29",
440 note = "use `UnsupportedSignatureAlgorithmContext` instead"
441 )]
442 UnsupportedSignatureAlgorithm,
443
444 UnsupportedSignatureAlgorithmContext {
446 signature_algorithm_id: Vec<u8>,
448 supported_algorithms: Vec<AlgorithmIdentifier>,
450 },
451
452 UnsupportedSignatureAlgorithmForPublicKeyContext {
454 signature_algorithm_id: Vec<u8>,
456 public_key_algorithm_id: Vec<u8>,
458 },
459
460 NotValidForName,
463
464 NotValidForNameContext {
470 expected: ServerName<'static>,
472
473 presented: Vec<String>,
478 },
479
480 InvalidPurpose,
482
483 InvalidPurposeContext {
488 required: ExtendedKeyPurpose,
490 presented: Vec<ExtendedKeyPurpose>,
492 },
493
494 InvalidOcspResponse,
503
504 ApplicationVerificationFailure,
507
508 Other(OtherError),
519}
520
521impl PartialEq<Self> for CertificateError {
522 fn eq(&self, other: &Self) -> bool {
523 use CertificateError::*;
524 #[allow(clippy::match_like_matches_macro)]
525 match (self, other) {
526 (BadEncoding, BadEncoding) => true,
527 (Expired, Expired) => true,
528 (
529 ExpiredContext {
530 time: left_time,
531 not_after: left_not_after,
532 },
533 ExpiredContext {
534 time: right_time,
535 not_after: right_not_after,
536 },
537 ) => (left_time, left_not_after) == (right_time, right_not_after),
538 (NotValidYet, NotValidYet) => true,
539 (
540 NotValidYetContext {
541 time: left_time,
542 not_before: left_not_before,
543 },
544 NotValidYetContext {
545 time: right_time,
546 not_before: right_not_before,
547 },
548 ) => (left_time, left_not_before) == (right_time, right_not_before),
549 (Revoked, Revoked) => true,
550 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
551 (UnknownIssuer, UnknownIssuer) => true,
552 (BadSignature, BadSignature) => true,
553 #[allow(deprecated)]
554 (UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm) => true,
555 (
556 UnsupportedSignatureAlgorithmContext {
557 signature_algorithm_id: left_signature_algorithm_id,
558 supported_algorithms: left_supported_algorithms,
559 },
560 UnsupportedSignatureAlgorithmContext {
561 signature_algorithm_id: right_signature_algorithm_id,
562 supported_algorithms: right_supported_algorithms,
563 },
564 ) => {
565 (left_signature_algorithm_id, left_supported_algorithms)
566 == (right_signature_algorithm_id, right_supported_algorithms)
567 }
568 (
569 UnsupportedSignatureAlgorithmForPublicKeyContext {
570 signature_algorithm_id: left_signature_algorithm_id,
571 public_key_algorithm_id: left_public_key_algorithm_id,
572 },
573 UnsupportedSignatureAlgorithmForPublicKeyContext {
574 signature_algorithm_id: right_signature_algorithm_id,
575 public_key_algorithm_id: right_public_key_algorithm_id,
576 },
577 ) => {
578 (left_signature_algorithm_id, left_public_key_algorithm_id)
579 == (right_signature_algorithm_id, right_public_key_algorithm_id)
580 }
581 (NotValidForName, NotValidForName) => true,
582 (
583 NotValidForNameContext {
584 expected: left_expected,
585 presented: left_presented,
586 },
587 NotValidForNameContext {
588 expected: right_expected,
589 presented: right_presented,
590 },
591 ) => (left_expected, left_presented) == (right_expected, right_presented),
592 (InvalidPurpose, InvalidPurpose) => true,
593 (
594 InvalidPurposeContext {
595 required: left_required,
596 presented: left_presented,
597 },
598 InvalidPurposeContext {
599 required: right_required,
600 presented: right_presented,
601 },
602 ) => (left_required, left_presented) == (right_required, right_presented),
603 (InvalidOcspResponse, InvalidOcspResponse) => true,
604 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
605 (UnknownRevocationStatus, UnknownRevocationStatus) => true,
606 (ExpiredRevocationList, ExpiredRevocationList) => true,
607 (
608 ExpiredRevocationListContext {
609 time: left_time,
610 next_update: left_next_update,
611 },
612 ExpiredRevocationListContext {
613 time: right_time,
614 next_update: right_next_update,
615 },
616 ) => (left_time, left_next_update) == (right_time, right_next_update),
617 _ => false,
618 }
619 }
620}
621
622impl From<CertificateError> for AlertDescription {
626 fn from(e: CertificateError) -> Self {
627 use CertificateError::*;
628 match e {
629 BadEncoding
630 | UnhandledCriticalExtension
631 | NotValidForName
632 | NotValidForNameContext { .. } => Self::BadCertificate,
633 Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
637 Self::CertificateExpired
638 }
639 Revoked => Self::CertificateRevoked,
640 UnknownIssuer
643 | UnknownRevocationStatus
644 | ExpiredRevocationList
645 | ExpiredRevocationListContext { .. } => Self::UnknownCA,
646 InvalidOcspResponse => Self::BadCertificateStatusResponse,
647 #[allow(deprecated)]
648 BadSignature
649 | UnsupportedSignatureAlgorithm
650 | UnsupportedSignatureAlgorithmContext { .. }
651 | UnsupportedSignatureAlgorithmForPublicKeyContext { .. } => Self::DecryptError,
652 InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate,
653 ApplicationVerificationFailure => Self::AccessDenied,
654 Other(..) => Self::CertificateUnknown,
659 }
660 }
661}
662
663impl fmt::Display for CertificateError {
664 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
665 match self {
666 #[cfg(feature = "std")]
667 Self::NotValidForNameContext {
668 expected,
669 presented,
670 } => {
671 write!(
672 f,
673 "certificate not valid for name {:?}; certificate ",
674 expected.to_str()
675 )?;
676
677 match presented.as_slice() {
678 &[] => write!(
679 f,
680 "is not valid for any names (according to its subjectAltName extension)"
681 ),
682 [one] => write!(f, "is only valid for {one}"),
683 many => {
684 write!(f, "is only valid for ")?;
685
686 let n = many.len();
687 let all_but_last = &many[..n - 1];
688 let last = &many[n - 1];
689
690 for (i, name) in all_but_last.iter().enumerate() {
691 write!(f, "{name}")?;
692 if i < n - 2 {
693 write!(f, ", ")?;
694 }
695 }
696 write!(f, " or {last}")
697 }
698 }
699 }
700
701 Self::ExpiredContext { time, not_after } => write!(
702 f,
703 "certificate expired: verification time {} (UNIX), \
704 but certificate is not valid after {} \
705 ({} seconds ago)",
706 time.as_secs(),
707 not_after.as_secs(),
708 time.as_secs()
709 .saturating_sub(not_after.as_secs())
710 ),
711
712 Self::NotValidYetContext { time, not_before } => write!(
713 f,
714 "certificate not valid yet: verification time {} (UNIX), \
715 but certificate is not valid before {} \
716 ({} seconds in future)",
717 time.as_secs(),
718 not_before.as_secs(),
719 not_before
720 .as_secs()
721 .saturating_sub(time.as_secs())
722 ),
723
724 Self::ExpiredRevocationListContext { time, next_update } => write!(
725 f,
726 "certificate revocation list expired: \
727 verification time {} (UNIX), \
728 but CRL is not valid after {} \
729 ({} seconds ago)",
730 time.as_secs(),
731 next_update.as_secs(),
732 time.as_secs()
733 .saturating_sub(next_update.as_secs())
734 ),
735
736 Self::InvalidPurposeContext {
737 required,
738 presented,
739 } => {
740 write!(
741 f,
742 "certificate does not allow extended key usage for {required}, allows "
743 )?;
744 for (i, eku) in presented.iter().enumerate() {
745 if i > 0 {
746 write!(f, ", ")?;
747 }
748 write!(f, "{eku}")?;
749 }
750 Ok(())
751 }
752
753 other => write!(f, "{other:?}"),
754 }
755 }
756}
757
758impl From<CertificateError> for Error {
759 #[inline]
760 fn from(e: CertificateError) -> Self {
761 Self::InvalidCertificate(e)
762 }
763}
764
765#[derive(Clone, Debug, Eq, PartialEq)]
770pub enum ExtendedKeyPurpose {
771 ClientAuth,
773 ServerAuth,
775 Other(Vec<usize>),
779}
780
781impl ExtendedKeyPurpose {
782 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
783 let values = values.collect::<Vec<_>>();
784 match &*values {
785 KeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
786 KeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
787 _ => Self::Other(values),
788 }
789 }
790}
791
792impl fmt::Display for ExtendedKeyPurpose {
793 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
794 match self {
795 Self::ClientAuth => write!(f, "client authentication"),
796 Self::ServerAuth => write!(f, "server authentication"),
797 Self::Other(values) => {
798 for (i, value) in values.iter().enumerate() {
799 if i > 0 {
800 write!(f, ", ")?;
801 }
802 write!(f, "{value}")?;
803 }
804 Ok(())
805 }
806 }
807 }
808}
809
810#[non_exhaustive]
811#[derive(Debug, Clone)]
812pub enum CertRevocationListError {
814 BadSignature,
816
817 #[deprecated(
819 since = "0.23.29",
820 note = "use `UnsupportedSignatureAlgorithmContext` instead"
821 )]
822 UnsupportedSignatureAlgorithm,
823
824 UnsupportedSignatureAlgorithmContext {
826 signature_algorithm_id: Vec<u8>,
828 supported_algorithms: Vec<AlgorithmIdentifier>,
830 },
831
832 UnsupportedSignatureAlgorithmForPublicKeyContext {
834 signature_algorithm_id: Vec<u8>,
836 public_key_algorithm_id: Vec<u8>,
838 },
839
840 InvalidCrlNumber,
842
843 InvalidRevokedCertSerialNumber,
845
846 IssuerInvalidForCrl,
848
849 Other(OtherError),
853
854 ParseError,
856
857 UnsupportedCrlVersion,
859
860 UnsupportedCriticalExtension,
862
863 UnsupportedDeltaCrl,
865
866 UnsupportedIndirectCrl,
869
870 UnsupportedRevocationReason,
875}
876
877impl PartialEq<Self> for CertRevocationListError {
878 fn eq(&self, other: &Self) -> bool {
879 use CertRevocationListError::*;
880 #[allow(clippy::match_like_matches_macro)]
881 match (self, other) {
882 (BadSignature, BadSignature) => true,
883 #[allow(deprecated)]
884 (UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm) => true,
885 (
886 UnsupportedSignatureAlgorithmContext {
887 signature_algorithm_id: left_signature_algorithm_id,
888 supported_algorithms: left_supported_algorithms,
889 },
890 UnsupportedSignatureAlgorithmContext {
891 signature_algorithm_id: right_signature_algorithm_id,
892 supported_algorithms: right_supported_algorithms,
893 },
894 ) => {
895 (left_signature_algorithm_id, left_supported_algorithms)
896 == (right_signature_algorithm_id, right_supported_algorithms)
897 }
898 (
899 UnsupportedSignatureAlgorithmForPublicKeyContext {
900 signature_algorithm_id: left_signature_algorithm_id,
901 public_key_algorithm_id: left_public_key_algorithm_id,
902 },
903 UnsupportedSignatureAlgorithmForPublicKeyContext {
904 signature_algorithm_id: right_signature_algorithm_id,
905 public_key_algorithm_id: right_public_key_algorithm_id,
906 },
907 ) => {
908 (left_signature_algorithm_id, left_public_key_algorithm_id)
909 == (right_signature_algorithm_id, right_public_key_algorithm_id)
910 }
911 (InvalidCrlNumber, InvalidCrlNumber) => true,
912 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
913 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
914 (ParseError, ParseError) => true,
915 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
916 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
917 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
918 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
919 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
920 _ => false,
921 }
922 }
923}
924
925impl From<CertRevocationListError> for Error {
926 #[inline]
927 fn from(e: CertRevocationListError) -> Self {
928 Self::InvalidCertRevocationList(e)
929 }
930}
931
932#[non_exhaustive]
933#[derive(Debug, Clone, Eq, PartialEq)]
934pub enum EncryptedClientHelloError {
936 InvalidConfigList,
938 NoCompatibleConfig,
940 SniRequired,
942}
943
944impl From<EncryptedClientHelloError> for Error {
945 #[inline]
946 fn from(e: EncryptedClientHelloError) -> Self {
947 Self::InvalidEncryptedClientHello(e)
948 }
949}
950
951fn join<T: fmt::Debug>(items: &[T]) -> String {
952 items
953 .iter()
954 .map(|x| format!("{x:?}"))
955 .collect::<Vec<String>>()
956 .join(" or ")
957}
958
959impl fmt::Display for Error {
960 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
961 match self {
962 Self::InappropriateMessage {
963 expect_types,
964 got_type,
965 } => write!(
966 f,
967 "received unexpected message: got {:?} when expecting {}",
968 got_type,
969 join::<ContentType>(expect_types)
970 ),
971 Self::InappropriateHandshakeMessage {
972 expect_types,
973 got_type,
974 } => write!(
975 f,
976 "received unexpected handshake message: got {:?} when expecting {}",
977 got_type,
978 join::<HandshakeType>(expect_types)
979 ),
980 Self::InvalidMessage(typ) => {
981 write!(f, "received corrupt message of type {typ:?}")
982 }
983 Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {why:?}"),
984 Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {why:?}"),
985 Self::AlertReceived(alert) => write!(f, "received fatal alert: {alert:?}"),
986 Self::InvalidCertificate(err) => {
987 write!(f, "invalid peer certificate: {err}")
988 }
989 Self::InvalidCertRevocationList(err) => {
990 write!(f, "invalid certificate revocation list: {err:?}")
991 }
992 Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
993 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
994 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
995 Self::InvalidEncryptedClientHello(err) => {
996 write!(f, "encrypted client hello failure: {err:?}")
997 }
998 Self::EncryptError => write!(f, "cannot encrypt message"),
999 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
1000 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
1001 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
1002 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
1003 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
1004 Self::BadMaxFragmentSize => {
1005 write!(f, "the supplied max_fragment_size was too small or large")
1006 }
1007 Self::InconsistentKeys(why) => {
1008 write!(f, "keys may not be consistent: {why:?}")
1009 }
1010 Self::General(err) => write!(f, "unexpected error: {err}"),
1011 Self::Other(err) => write!(f, "other error: {err}"),
1012 }
1013 }
1014}
1015
1016#[cfg(feature = "std")]
1017impl From<SystemTimeError> for Error {
1018 #[inline]
1019 fn from(_: SystemTimeError) -> Self {
1020 Self::FailedToGetCurrentTime
1021 }
1022}
1023
1024#[cfg(feature = "std")]
1025impl std::error::Error for Error {}
1026
1027impl From<rand::GetRandomFailed> for Error {
1028 fn from(_: rand::GetRandomFailed) -> Self {
1029 Self::FailedToGetRandomBytes
1030 }
1031}
1032
1033mod other_error {
1034 use core::fmt;
1035 #[cfg(feature = "std")]
1036 use std::error::Error as StdError;
1037
1038 use super::Error;
1039 #[cfg(feature = "std")]
1040 use crate::sync::Arc;
1041
1042 #[derive(Debug, Clone)]
1049 pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
1050
1051 impl PartialEq<Self> for OtherError {
1052 fn eq(&self, _other: &Self) -> bool {
1053 false
1054 }
1055 }
1056
1057 impl From<OtherError> for Error {
1058 fn from(value: OtherError) -> Self {
1059 Self::Other(value)
1060 }
1061 }
1062
1063 impl fmt::Display for OtherError {
1064 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
1065 #[cfg(feature = "std")]
1066 {
1067 write!(f, "{}", self.0)
1068 }
1069 #[cfg(not(feature = "std"))]
1070 {
1071 f.write_str("no further information available")
1072 }
1073 }
1074 }
1075
1076 #[cfg(feature = "std")]
1077 impl StdError for OtherError {
1078 fn source(&self) -> Option<&(dyn StdError + 'static)> {
1079 Some(self.0.as_ref())
1080 }
1081 }
1082}
1083
1084pub use other_error::OtherError;
1085
1086#[cfg(test)]
1087mod tests {
1088 use core::time::Duration;
1089 use std::prelude::v1::*;
1090 use std::{println, vec};
1091
1092 use pki_types::ServerName;
1093
1094 use super::{
1095 CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError, UnixTime,
1096 };
1097 #[cfg(feature = "std")]
1098 use crate::sync::Arc;
1099
1100 #[test]
1101 fn certificate_error_equality() {
1102 use super::CertificateError::*;
1103 assert_eq!(BadEncoding, BadEncoding);
1104 assert_eq!(Expired, Expired);
1105 let context = ExpiredContext {
1106 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1107 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1108 };
1109 assert_eq!(context, context);
1110 assert_ne!(
1111 context,
1112 ExpiredContext {
1113 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1114 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1115 }
1116 );
1117 assert_ne!(
1118 context,
1119 ExpiredContext {
1120 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1121 not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1122 }
1123 );
1124 assert_eq!(NotValidYet, NotValidYet);
1125 let context = NotValidYetContext {
1126 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1127 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1128 };
1129 assert_eq!(context, context);
1130 assert_ne!(
1131 context,
1132 NotValidYetContext {
1133 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1134 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1135 }
1136 );
1137 assert_ne!(
1138 context,
1139 NotValidYetContext {
1140 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1141 not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1142 }
1143 );
1144 assert_eq!(Revoked, Revoked);
1145 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
1146 assert_eq!(UnknownIssuer, UnknownIssuer);
1147 assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
1148 assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
1149 let context = ExpiredRevocationListContext {
1150 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1151 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1152 };
1153 assert_eq!(context, context);
1154 assert_ne!(
1155 context,
1156 ExpiredRevocationListContext {
1157 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1158 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1159 }
1160 );
1161 assert_ne!(
1162 context,
1163 ExpiredRevocationListContext {
1164 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1165 next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1166 }
1167 );
1168 assert_eq!(BadSignature, BadSignature);
1169 #[allow(deprecated)]
1170 {
1171 assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm);
1172 }
1173 assert_eq!(
1174 UnsupportedSignatureAlgorithmContext {
1175 signature_algorithm_id: vec![1, 2, 3],
1176 supported_algorithms: vec![]
1177 },
1178 UnsupportedSignatureAlgorithmContext {
1179 signature_algorithm_id: vec![1, 2, 3],
1180 supported_algorithms: vec![]
1181 }
1182 );
1183 assert_eq!(
1184 UnsupportedSignatureAlgorithmForPublicKeyContext {
1185 signature_algorithm_id: vec![1, 2, 3],
1186 public_key_algorithm_id: vec![4, 5, 6]
1187 },
1188 UnsupportedSignatureAlgorithmForPublicKeyContext {
1189 signature_algorithm_id: vec![1, 2, 3],
1190 public_key_algorithm_id: vec![4, 5, 6]
1191 }
1192 );
1193 assert_eq!(NotValidForName, NotValidForName);
1194 let context = NotValidForNameContext {
1195 expected: ServerName::try_from("example.com")
1196 .unwrap()
1197 .to_owned(),
1198 presented: vec!["other.com".into()],
1199 };
1200 assert_eq!(context, context);
1201 assert_ne!(
1202 context,
1203 NotValidForNameContext {
1204 expected: ServerName::try_from("example.com")
1205 .unwrap()
1206 .to_owned(),
1207 presented: vec![]
1208 }
1209 );
1210 assert_ne!(
1211 context,
1212 NotValidForNameContext {
1213 expected: ServerName::try_from("huh.com")
1214 .unwrap()
1215 .to_owned(),
1216 presented: vec!["other.com".into()],
1217 }
1218 );
1219 assert_eq!(InvalidPurpose, InvalidPurpose);
1220 assert_eq!(
1221 ApplicationVerificationFailure,
1222 ApplicationVerificationFailure
1223 );
1224 assert_eq!(InvalidOcspResponse, InvalidOcspResponse);
1225 let other = Other(OtherError(
1226 #[cfg(feature = "std")]
1227 Arc::from(Box::from("")),
1228 ));
1229 assert_ne!(other, other);
1230 assert_ne!(BadEncoding, Expired);
1231 }
1232
1233 #[test]
1234 fn crl_error_equality() {
1235 use super::CertRevocationListError::*;
1236 assert_eq!(BadSignature, BadSignature);
1237 #[allow(deprecated)]
1238 {
1239 assert_eq!(UnsupportedSignatureAlgorithm, UnsupportedSignatureAlgorithm);
1240 }
1241 assert_eq!(
1242 UnsupportedSignatureAlgorithmContext {
1243 signature_algorithm_id: vec![1, 2, 3],
1244 supported_algorithms: vec![]
1245 },
1246 UnsupportedSignatureAlgorithmContext {
1247 signature_algorithm_id: vec![1, 2, 3],
1248 supported_algorithms: vec![]
1249 }
1250 );
1251 assert_eq!(
1252 UnsupportedSignatureAlgorithmForPublicKeyContext {
1253 signature_algorithm_id: vec![1, 2, 3],
1254 public_key_algorithm_id: vec![4, 5, 6]
1255 },
1256 UnsupportedSignatureAlgorithmForPublicKeyContext {
1257 signature_algorithm_id: vec![1, 2, 3],
1258 public_key_algorithm_id: vec![4, 5, 6]
1259 }
1260 );
1261 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
1262 assert_eq!(
1263 InvalidRevokedCertSerialNumber,
1264 InvalidRevokedCertSerialNumber
1265 );
1266 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
1267 assert_eq!(ParseError, ParseError);
1268 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
1269 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
1270 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
1271 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
1272 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
1273 let other = Other(OtherError(
1274 #[cfg(feature = "std")]
1275 Arc::from(Box::from("")),
1276 ));
1277 assert_ne!(other, other);
1278 assert_ne!(BadSignature, InvalidCrlNumber);
1279 }
1280
1281 #[test]
1282 #[cfg(feature = "std")]
1283 fn other_error_equality() {
1284 let other_error = OtherError(Arc::from(Box::from("")));
1285 assert_ne!(other_error, other_error);
1286 let other: Error = other_error.into();
1287 assert_ne!(other, other);
1288 }
1289
1290 #[test]
1291 fn smoke() {
1292 use crate::enums::{AlertDescription, ContentType, HandshakeType};
1293
1294 let all = vec![
1295 Error::InappropriateMessage {
1296 expect_types: vec![ContentType::Alert],
1297 got_type: ContentType::Handshake,
1298 },
1299 Error::InappropriateHandshakeMessage {
1300 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
1301 got_type: HandshakeType::ServerHello,
1302 },
1303 Error::InvalidMessage(InvalidMessage::InvalidCcs),
1304 Error::NoCertificatesPresented,
1305 Error::DecryptError,
1306 super::PeerIncompatible::Tls12NotOffered.into(),
1307 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
1308 Error::AlertReceived(AlertDescription::ExportRestriction),
1309 super::CertificateError::Expired.into(),
1310 super::CertificateError::NotValidForNameContext {
1311 expected: ServerName::try_from("example.com")
1312 .unwrap()
1313 .to_owned(),
1314 presented: vec![],
1315 }
1316 .into(),
1317 super::CertificateError::NotValidForNameContext {
1318 expected: ServerName::try_from("example.com")
1319 .unwrap()
1320 .to_owned(),
1321 presented: vec!["DnsName(\"hello.com\")".into()],
1322 }
1323 .into(),
1324 super::CertificateError::NotValidForNameContext {
1325 expected: ServerName::try_from("example.com")
1326 .unwrap()
1327 .to_owned(),
1328 presented: vec![
1329 "DnsName(\"hello.com\")".into(),
1330 "DnsName(\"goodbye.com\")".into(),
1331 ],
1332 }
1333 .into(),
1334 super::CertificateError::NotValidYetContext {
1335 time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1336 not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1337 }
1338 .into(),
1339 super::CertificateError::ExpiredContext {
1340 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1341 not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1342 }
1343 .into(),
1344 super::CertificateError::ExpiredRevocationListContext {
1345 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1346 next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1347 }
1348 .into(),
1349 super::CertificateError::InvalidOcspResponse.into(),
1350 Error::General("undocumented error".to_string()),
1351 Error::FailedToGetCurrentTime,
1352 Error::FailedToGetRandomBytes,
1353 Error::HandshakeNotComplete,
1354 Error::PeerSentOversizedRecord,
1355 Error::NoApplicationProtocol,
1356 Error::BadMaxFragmentSize,
1357 Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
1358 Error::InconsistentKeys(InconsistentKeys::Unknown),
1359 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
1360 Error::Other(OtherError(
1361 #[cfg(feature = "std")]
1362 Arc::from(Box::from("")),
1363 )),
1364 ];
1365
1366 for err in all {
1367 println!("{err:?}:");
1368 println!(" fmt '{err}'");
1369 }
1370 }
1371
1372 #[test]
1373 fn rand_error_mapping() {
1374 use super::rand;
1375 let err: Error = rand::GetRandomFailed.into();
1376 assert_eq!(err, Error::FailedToGetRandomBytes);
1377 }
1378
1379 #[cfg(feature = "std")]
1380 #[test]
1381 fn time_error_mapping() {
1382 use std::time::SystemTime;
1383
1384 let time_error = SystemTime::UNIX_EPOCH
1385 .duration_since(SystemTime::now())
1386 .unwrap_err();
1387 let err: Error = time_error.into();
1388 assert_eq!(err, Error::FailedToGetCurrentTime);
1389 }
1390}