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