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::{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)]
145
146pub enum InvalidMessage {
147 CertificatePayloadTooLarge,
149 HandshakePayloadTooLarge,
151 InvalidCcs,
153 InvalidContentType,
155 InvalidCertificateStatusType,
157 InvalidCertRequest,
159 InvalidDhParams,
161 InvalidEmptyPayload,
163 InvalidKeyUpdate,
165 InvalidServerName,
167 MessageTooLarge,
169 MessageTooShort,
171 MissingData(&'static str),
173 MissingKeyExchange,
175 NoSignatureSchemes,
177 TrailingData(&'static str),
179 UnexpectedMessage(&'static str),
181 UnknownProtocolVersion,
183 UnsupportedCompression,
185 UnsupportedCurveType,
187 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
189 EmptyTicketValue,
191 IllegalEmptyList(&'static str),
195 IllegalEmptyValue,
197}
198
199impl From<InvalidMessage> for Error {
200 #[inline]
201 fn from(e: InvalidMessage) -> Self {
202 Self::InvalidMessage(e)
203 }
204}
205
206#[non_exhaustive]
207#[allow(missing_docs)]
208#[derive(Debug, PartialEq, Clone)]
209pub enum PeerMisbehaved {
220 AttemptedDowngradeToTls12WhenTls13IsSupported,
221 BadCertChainExtensions,
222 DisallowedEncryptedExtension,
223 DuplicateClientHelloExtensions,
224 DuplicateEncryptedExtensions,
225 DuplicateHelloRetryRequestExtensions,
226 DuplicateNewSessionTicketExtensions,
227 DuplicateServerHelloExtensions,
228 DuplicateServerNameTypes,
229 EarlyDataAttemptedInSecondClientHello,
230 EarlyDataExtensionWithoutResumption,
231 EarlyDataOfferedWithVariedCipherSuite,
232 HandshakeHashVariedAfterRetry,
233 IllegalHelloRetryRequestWithEmptyCookie,
234 IllegalHelloRetryRequestWithNoChanges,
235 IllegalHelloRetryRequestWithOfferedGroup,
236 IllegalHelloRetryRequestWithUnofferedCipherSuite,
237 IllegalHelloRetryRequestWithUnofferedNamedGroup,
238 IllegalHelloRetryRequestWithUnsupportedVersion,
239 IllegalHelloRetryRequestWithWrongSessionId,
240 IllegalHelloRetryRequestWithInvalidEch,
241 IllegalMiddleboxChangeCipherSpec,
242 IllegalTlsInnerPlaintext,
243 IncorrectBinder,
244 InvalidCertCompression,
245 InvalidMaxEarlyDataSize,
246 InvalidKeyShare,
247 KeyEpochWithPendingFragment,
248 KeyUpdateReceivedInQuicConnection,
249 MessageInterleavedWithHandshakeMessage,
250 MissingBinderInPskExtension,
251 MissingKeyShare,
252 MissingPskModesExtension,
253 MissingQuicTransportParameters,
254 OfferedDuplicateCertificateCompressions,
255 OfferedDuplicateKeyShares,
256 OfferedEarlyDataWithOldProtocolVersion,
257 OfferedEmptyApplicationProtocol,
258 OfferedIncorrectCompressions,
259 PskExtensionMustBeLast,
260 PskExtensionWithMismatchedIdsAndBinders,
261 RefusedToFollowHelloRetryRequest,
262 RejectedEarlyDataInterleavedWithHandshakeMessage,
263 ResumptionAttemptedWithVariedEms,
264 ResumptionOfferedWithVariedCipherSuite,
265 ResumptionOfferedWithVariedEms,
266 ResumptionOfferedWithIncompatibleCipherSuite,
267 SelectedDifferentCipherSuiteAfterRetry,
268 SelectedInvalidPsk,
269 SelectedTls12UsingTls13VersionExtension,
270 SelectedUnofferedApplicationProtocol,
271 SelectedUnofferedCertCompression,
272 SelectedUnofferedCipherSuite,
273 SelectedUnofferedCompression,
274 SelectedUnofferedKxGroup,
275 SelectedUnofferedPsk,
276 SelectedUnusableCipherSuiteForVersion,
277 ServerEchoedCompatibilitySessionId,
278 ServerHelloMustOfferUncompressedEcPoints,
279 ServerNameDifferedOnRetry,
280 ServerNameMustContainOneHostName,
281 SignedKxWithWrongAlgorithm,
282 SignedHandshakeWithUnadvertisedSigScheme,
283 TooManyEmptyFragments,
284 TooManyKeyUpdateRequests,
285 TooManyRenegotiationRequests,
286 TooManyWarningAlertsReceived,
287 TooMuchEarlyDataReceived,
288 UnexpectedCleartextExtension,
289 UnsolicitedCertExtension,
290 UnsolicitedEncryptedExtension,
291 UnsolicitedSctList,
292 UnsolicitedServerHelloExtension,
293 WrongGroupForKeyShare,
294 UnsolicitedEchExtension,
295}
296
297impl From<PeerMisbehaved> for Error {
298 #[inline]
299 fn from(e: PeerMisbehaved) -> Self {
300 Self::PeerMisbehaved(e)
301 }
302}
303
304#[non_exhaustive]
305#[allow(missing_docs)]
306#[derive(Debug, PartialEq, Clone)]
307pub enum PeerIncompatible {
313 EcPointsExtensionRequired,
314 ExtendedMasterSecretExtensionRequired,
315 IncorrectCertificateTypeExtension,
316 KeyShareExtensionRequired,
317 NamedGroupsExtensionRequired,
318 NoCertificateRequestSignatureSchemesInCommon,
319 NoCipherSuitesInCommon,
320 NoEcPointFormatsInCommon,
321 NoKxGroupsInCommon,
322 NoSignatureSchemesInCommon,
323 NullCompressionRequired,
324 ServerDoesNotSupportTls12Or13,
325 ServerSentHelloRetryRequestWithUnknownExtension,
326 ServerTlsVersionIsDisabledByOurConfig,
327 SignatureAlgorithmsExtensionRequired,
328 SupportedVersionsExtensionRequired,
329 Tls12NotOffered,
330 Tls12NotOfferedOrEnabled,
331 Tls13RequiredForQuic,
332 UncompressedEcPointsRequired,
333 UnsolicitedCertificateTypeExtension,
334 ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
335}
336
337impl From<PeerIncompatible> for Error {
338 #[inline]
339 fn from(e: PeerIncompatible) -> Self {
340 Self::PeerIncompatible(e)
341 }
342}
343
344#[non_exhaustive]
345#[derive(Debug, Clone)]
346pub enum CertificateError {
354 BadEncoding,
356
357 Expired,
359
360 ExpiredContext {
365 time: UnixTime,
367 not_after: UnixTime,
369 },
370
371 NotValidYet,
373
374 NotValidYetContext {
379 time: UnixTime,
381 not_before: UnixTime,
383 },
384
385 Revoked,
387
388 UnhandledCriticalExtension,
391
392 UnknownIssuer,
394
395 UnknownRevocationStatus,
397
398 ExpiredRevocationList,
400
401 ExpiredRevocationListContext {
406 time: UnixTime,
408 next_update: UnixTime,
410 },
411
412 BadSignature,
415
416 NotValidForName,
419
420 NotValidForNameContext {
426 expected: ServerName<'static>,
428
429 presented: Vec<String>,
434 },
435
436 InvalidPurpose,
438
439 InvalidPurposeContext {
444 required: ExtendedKeyPurpose,
446 presented: Vec<ExtendedKeyPurpose>,
448 },
449
450 ApplicationVerificationFailure,
453
454 Other(OtherError),
465}
466
467impl PartialEq<Self> for CertificateError {
468 fn eq(&self, other: &Self) -> bool {
469 use CertificateError::*;
470 #[allow(clippy::match_like_matches_macro)]
471 match (self, other) {
472 (BadEncoding, BadEncoding) => true,
473 (Expired, Expired) => true,
474 (
475 ExpiredContext {
476 time: left_time,
477 not_after: left_not_after,
478 },
479 ExpiredContext {
480 time: right_time,
481 not_after: right_not_after,
482 },
483 ) => (left_time, left_not_after) == (right_time, right_not_after),
484 (NotValidYet, NotValidYet) => true,
485 (
486 NotValidYetContext {
487 time: left_time,
488 not_before: left_not_before,
489 },
490 NotValidYetContext {
491 time: right_time,
492 not_before: right_not_before,
493 },
494 ) => (left_time, left_not_before) == (right_time, right_not_before),
495 (Revoked, Revoked) => true,
496 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
497 (UnknownIssuer, UnknownIssuer) => true,
498 (BadSignature, BadSignature) => true,
499 (NotValidForName, NotValidForName) => true,
500 (
501 NotValidForNameContext {
502 expected: left_expected,
503 presented: left_presented,
504 },
505 NotValidForNameContext {
506 expected: right_expected,
507 presented: right_presented,
508 },
509 ) => (left_expected, left_presented) == (right_expected, right_presented),
510 (InvalidPurpose, InvalidPurpose) => true,
511 (
512 InvalidPurposeContext {
513 required: left_required,
514 presented: left_presented,
515 },
516 InvalidPurposeContext {
517 required: right_required,
518 presented: right_presented,
519 },
520 ) => (left_required, left_presented) == (right_required, right_presented),
521 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
522 (UnknownRevocationStatus, UnknownRevocationStatus) => true,
523 (ExpiredRevocationList, ExpiredRevocationList) => true,
524 (
525 ExpiredRevocationListContext {
526 time: left_time,
527 next_update: left_next_update,
528 },
529 ExpiredRevocationListContext {
530 time: right_time,
531 next_update: right_next_update,
532 },
533 ) => (left_time, left_next_update) == (right_time, right_next_update),
534 _ => false,
535 }
536 }
537}
538
539impl From<CertificateError> for AlertDescription {
543 fn from(e: CertificateError) -> Self {
544 use CertificateError::*;
545 match e {
546 BadEncoding
547 | UnhandledCriticalExtension
548 | NotValidForName
549 | NotValidForNameContext { .. } => Self::BadCertificate,
550 Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
554 Self::CertificateExpired
555 }
556 Revoked => Self::CertificateRevoked,
557 UnknownIssuer
560 | UnknownRevocationStatus
561 | ExpiredRevocationList
562 | ExpiredRevocationListContext { .. } => Self::UnknownCA,
563 BadSignature => Self::DecryptError,
564 InvalidPurpose | InvalidPurposeContext { .. } => Self::UnsupportedCertificate,
565 ApplicationVerificationFailure => Self::AccessDenied,
566 Other(..) => Self::CertificateUnknown,
571 }
572 }
573}
574
575impl fmt::Display for CertificateError {
576 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
577 match self {
578 #[cfg(feature = "std")]
579 Self::NotValidForNameContext {
580 expected,
581 presented,
582 } => {
583 write!(
584 f,
585 "certificate not valid for name {:?}; certificate ",
586 expected.to_str()
587 )?;
588
589 match presented.as_slice() {
590 &[] => write!(
591 f,
592 "is not valid for any names (according to its subjectAltName extension)"
593 ),
594 [one] => write!(f, "is only valid for {}", one),
595 many => {
596 write!(f, "is only valid for ")?;
597
598 let n = many.len();
599 let all_but_last = &many[..n - 1];
600 let last = &many[n - 1];
601
602 for (i, name) in all_but_last.iter().enumerate() {
603 write!(f, "{}", name)?;
604 if i < n - 2 {
605 write!(f, ", ")?;
606 }
607 }
608 write!(f, " or {}", last)
609 }
610 }
611 }
612
613 Self::ExpiredContext { time, not_after } => write!(
614 f,
615 "certificate expired: verification time {} (UNIX), \
616 but certificate is not valid after {} \
617 ({} seconds ago)",
618 time.as_secs(),
619 not_after.as_secs(),
620 time.as_secs()
621 .saturating_sub(not_after.as_secs())
622 ),
623
624 Self::NotValidYetContext { time, not_before } => write!(
625 f,
626 "certificate not valid yet: verification time {} (UNIX), \
627 but certificate is not valid before {} \
628 ({} seconds in future)",
629 time.as_secs(),
630 not_before.as_secs(),
631 not_before
632 .as_secs()
633 .saturating_sub(time.as_secs())
634 ),
635
636 Self::ExpiredRevocationListContext { time, next_update } => write!(
637 f,
638 "certificate revocation list expired: \
639 verification time {} (UNIX), \
640 but CRL is not valid after {} \
641 ({} seconds ago)",
642 time.as_secs(),
643 next_update.as_secs(),
644 time.as_secs()
645 .saturating_sub(next_update.as_secs())
646 ),
647
648 Self::InvalidPurposeContext {
649 required,
650 presented,
651 } => {
652 write!(
653 f,
654 "certificate does not allow extended key usage for {required}, allows "
655 )?;
656 for (i, eku) in presented.iter().enumerate() {
657 if i > 0 {
658 write!(f, ", ")?;
659 }
660 write!(f, "{eku}")?;
661 }
662 Ok(())
663 }
664
665 other => write!(f, "{:?}", other),
666 }
667 }
668}
669
670impl From<CertificateError> for Error {
671 #[inline]
672 fn from(e: CertificateError) -> Self {
673 Self::InvalidCertificate(e)
674 }
675}
676
677#[derive(Clone, Debug, Eq, PartialEq)]
682pub enum ExtendedKeyPurpose {
683 ClientAuth,
685 ServerAuth,
687 Other(Vec<usize>),
691}
692
693impl ExtendedKeyPurpose {
694 pub(crate) fn for_values(values: impl Iterator<Item = usize>) -> Self {
695 let values = values.collect::<Vec<_>>();
696 match &*values {
697 KeyUsage::CLIENT_AUTH_REPR => Self::ClientAuth,
698 KeyUsage::SERVER_AUTH_REPR => Self::ServerAuth,
699 _ => Self::Other(values),
700 }
701 }
702}
703
704impl fmt::Display for ExtendedKeyPurpose {
705 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
706 match self {
707 Self::ClientAuth => write!(f, "client authentication"),
708 Self::ServerAuth => write!(f, "server authentication"),
709 Self::Other(values) => {
710 for (i, value) in values.iter().enumerate() {
711 if i > 0 {
712 write!(f, ", ")?;
713 }
714 write!(f, "{value}")?;
715 }
716 Ok(())
717 }
718 }
719 }
720}
721
722#[non_exhaustive]
723#[derive(Debug, Clone)]
724pub enum CertRevocationListError {
726 BadSignature,
728
729 InvalidCrlNumber,
731
732 InvalidRevokedCertSerialNumber,
734
735 IssuerInvalidForCrl,
737
738 Other(OtherError),
742
743 ParseError,
745
746 UnsupportedCrlVersion,
748
749 UnsupportedCriticalExtension,
751
752 UnsupportedDeltaCrl,
754
755 UnsupportedIndirectCrl,
758
759 UnsupportedRevocationReason,
764}
765
766impl PartialEq<Self> for CertRevocationListError {
767 fn eq(&self, other: &Self) -> bool {
768 use CertRevocationListError::*;
769 #[allow(clippy::match_like_matches_macro)]
770 match (self, other) {
771 (BadSignature, BadSignature) => true,
772 (InvalidCrlNumber, InvalidCrlNumber) => true,
773 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
774 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
775 (ParseError, ParseError) => true,
776 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
777 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
778 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
779 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
780 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
781 _ => false,
782 }
783 }
784}
785
786impl From<CertRevocationListError> for Error {
787 #[inline]
788 fn from(e: CertRevocationListError) -> Self {
789 Self::InvalidCertRevocationList(e)
790 }
791}
792
793#[non_exhaustive]
794#[derive(Debug, Clone, Eq, PartialEq)]
795pub enum EncryptedClientHelloError {
797 InvalidConfigList,
799 NoCompatibleConfig,
801 SniRequired,
803}
804
805impl From<EncryptedClientHelloError> for Error {
806 #[inline]
807 fn from(e: EncryptedClientHelloError) -> Self {
808 Self::InvalidEncryptedClientHello(e)
809 }
810}
811
812fn join<T: fmt::Debug>(items: &[T]) -> String {
813 items
814 .iter()
815 .map(|x| format!("{:?}", x))
816 .collect::<Vec<String>>()
817 .join(" or ")
818}
819
820impl fmt::Display for Error {
821 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
822 match self {
823 Self::InappropriateMessage {
824 expect_types,
825 got_type,
826 } => write!(
827 f,
828 "received unexpected message: got {:?} when expecting {}",
829 got_type,
830 join::<ContentType>(expect_types)
831 ),
832 Self::InappropriateHandshakeMessage {
833 expect_types,
834 got_type,
835 } => write!(
836 f,
837 "received unexpected handshake message: got {:?} when expecting {}",
838 got_type,
839 join::<HandshakeType>(expect_types)
840 ),
841 Self::InvalidMessage(typ) => {
842 write!(f, "received corrupt message of type {:?}", typ)
843 }
844 Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {:?}", why),
845 Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {:?}", why),
846 Self::AlertReceived(alert) => write!(f, "received fatal alert: {:?}", alert),
847 Self::InvalidCertificate(err) => {
848 write!(f, "invalid peer certificate: {}", err)
849 }
850 Self::InvalidCertRevocationList(err) => {
851 write!(f, "invalid certificate revocation list: {:?}", err)
852 }
853 Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
854 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
855 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
856 Self::InvalidEncryptedClientHello(err) => {
857 write!(f, "encrypted client hello failure: {:?}", err)
858 }
859 Self::EncryptError => write!(f, "cannot encrypt message"),
860 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
861 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
862 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
863 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
864 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
865 Self::BadMaxFragmentSize => {
866 write!(f, "the supplied max_fragment_size was too small or large")
867 }
868 Self::InconsistentKeys(why) => {
869 write!(f, "keys may not be consistent: {:?}", why)
870 }
871 Self::General(err) => write!(f, "unexpected error: {}", err),
872 Self::Other(err) => write!(f, "other error: {}", err),
873 }
874 }
875}
876
877#[cfg(feature = "std")]
878impl From<SystemTimeError> for Error {
879 #[inline]
880 fn from(_: SystemTimeError) -> Self {
881 Self::FailedToGetCurrentTime
882 }
883}
884
885#[cfg(feature = "std")]
886impl std::error::Error for Error {}
887
888impl From<rand::GetRandomFailed> for Error {
889 fn from(_: rand::GetRandomFailed) -> Self {
890 Self::FailedToGetRandomBytes
891 }
892}
893
894mod other_error {
895 use core::fmt;
896 #[cfg(feature = "std")]
897 use std::error::Error as StdError;
898
899 use super::Error;
900 #[cfg(feature = "std")]
901 use crate::sync::Arc;
902
903 #[derive(Debug, Clone)]
910 pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
911
912 impl PartialEq<Self> for OtherError {
913 fn eq(&self, _other: &Self) -> bool {
914 false
915 }
916 }
917
918 impl From<OtherError> for Error {
919 fn from(value: OtherError) -> Self {
920 Self::Other(value)
921 }
922 }
923
924 impl fmt::Display for OtherError {
925 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
926 #[cfg(feature = "std")]
927 {
928 write!(f, "{}", self.0)
929 }
930 #[cfg(not(feature = "std"))]
931 {
932 f.write_str("no further information available")
933 }
934 }
935 }
936
937 #[cfg(feature = "std")]
938 impl StdError for OtherError {
939 fn source(&self) -> Option<&(dyn StdError + 'static)> {
940 Some(self.0.as_ref())
941 }
942 }
943}
944
945pub use other_error::OtherError;
946
947#[cfg(test)]
948mod tests {
949 use core::time::Duration;
950 use std::prelude::v1::*;
951 use std::{println, vec};
952
953 use super::{
954 CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError, UnixTime,
955 };
956 #[cfg(feature = "std")]
957 use crate::sync::Arc;
958 use pki_types::ServerName;
959
960 #[test]
961 fn certificate_error_equality() {
962 use super::CertificateError::*;
963 assert_eq!(BadEncoding, BadEncoding);
964 assert_eq!(Expired, Expired);
965 let context = ExpiredContext {
966 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
967 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
968 };
969 assert_eq!(context, context);
970 assert_ne!(
971 context,
972 ExpiredContext {
973 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
974 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
975 }
976 );
977 assert_ne!(
978 context,
979 ExpiredContext {
980 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
981 not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
982 }
983 );
984 assert_eq!(NotValidYet, NotValidYet);
985 let context = NotValidYetContext {
986 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
987 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
988 };
989 assert_eq!(context, context);
990 assert_ne!(
991 context,
992 NotValidYetContext {
993 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
994 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
995 }
996 );
997 assert_ne!(
998 context,
999 NotValidYetContext {
1000 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1001 not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1002 }
1003 );
1004 assert_eq!(Revoked, Revoked);
1005 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
1006 assert_eq!(UnknownIssuer, UnknownIssuer);
1007 assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
1008 assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
1009 let context = ExpiredRevocationListContext {
1010 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1011 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1012 };
1013 assert_eq!(context, context);
1014 assert_ne!(
1015 context,
1016 ExpiredRevocationListContext {
1017 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
1018 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
1019 }
1020 );
1021 assert_ne!(
1022 context,
1023 ExpiredRevocationListContext {
1024 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1025 next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
1026 }
1027 );
1028 assert_eq!(BadSignature, BadSignature);
1029 assert_eq!(NotValidForName, NotValidForName);
1030 let context = NotValidForNameContext {
1031 expected: ServerName::try_from("example.com")
1032 .unwrap()
1033 .to_owned(),
1034 presented: vec!["other.com".into()],
1035 };
1036 assert_eq!(context, context);
1037 assert_ne!(
1038 context,
1039 NotValidForNameContext {
1040 expected: ServerName::try_from("example.com")
1041 .unwrap()
1042 .to_owned(),
1043 presented: vec![]
1044 }
1045 );
1046 assert_ne!(
1047 context,
1048 NotValidForNameContext {
1049 expected: ServerName::try_from("huh.com")
1050 .unwrap()
1051 .to_owned(),
1052 presented: vec!["other.com".into()],
1053 }
1054 );
1055 assert_eq!(InvalidPurpose, InvalidPurpose);
1056 assert_eq!(
1057 ApplicationVerificationFailure,
1058 ApplicationVerificationFailure
1059 );
1060 let other = Other(OtherError(
1061 #[cfg(feature = "std")]
1062 Arc::from(Box::from("")),
1063 ));
1064 assert_ne!(other, other);
1065 assert_ne!(BadEncoding, Expired);
1066 }
1067
1068 #[test]
1069 fn crl_error_equality() {
1070 use super::CertRevocationListError::*;
1071 assert_eq!(BadSignature, BadSignature);
1072 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
1073 assert_eq!(
1074 InvalidRevokedCertSerialNumber,
1075 InvalidRevokedCertSerialNumber
1076 );
1077 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
1078 assert_eq!(ParseError, ParseError);
1079 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
1080 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
1081 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
1082 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
1083 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
1084 let other = Other(OtherError(
1085 #[cfg(feature = "std")]
1086 Arc::from(Box::from("")),
1087 ));
1088 assert_ne!(other, other);
1089 assert_ne!(BadSignature, InvalidCrlNumber);
1090 }
1091
1092 #[test]
1093 #[cfg(feature = "std")]
1094 fn other_error_equality() {
1095 let other_error = OtherError(Arc::from(Box::from("")));
1096 assert_ne!(other_error, other_error);
1097 let other: Error = other_error.into();
1098 assert_ne!(other, other);
1099 }
1100
1101 #[test]
1102 fn smoke() {
1103 use crate::enums::{AlertDescription, ContentType, HandshakeType};
1104
1105 let all = vec![
1106 Error::InappropriateMessage {
1107 expect_types: vec![ContentType::Alert],
1108 got_type: ContentType::Handshake,
1109 },
1110 Error::InappropriateHandshakeMessage {
1111 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
1112 got_type: HandshakeType::ServerHello,
1113 },
1114 Error::InvalidMessage(InvalidMessage::InvalidCcs),
1115 Error::NoCertificatesPresented,
1116 Error::DecryptError,
1117 super::PeerIncompatible::Tls12NotOffered.into(),
1118 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
1119 Error::AlertReceived(AlertDescription::ExportRestriction),
1120 super::CertificateError::Expired.into(),
1121 super::CertificateError::NotValidForNameContext {
1122 expected: ServerName::try_from("example.com")
1123 .unwrap()
1124 .to_owned(),
1125 presented: vec![],
1126 }
1127 .into(),
1128 super::CertificateError::NotValidForNameContext {
1129 expected: ServerName::try_from("example.com")
1130 .unwrap()
1131 .to_owned(),
1132 presented: vec!["DnsName(\"hello.com\")".into()],
1133 }
1134 .into(),
1135 super::CertificateError::NotValidForNameContext {
1136 expected: ServerName::try_from("example.com")
1137 .unwrap()
1138 .to_owned(),
1139 presented: vec![
1140 "DnsName(\"hello.com\")".into(),
1141 "DnsName(\"goodbye.com\")".into(),
1142 ],
1143 }
1144 .into(),
1145 super::CertificateError::NotValidYetContext {
1146 time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1147 not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1148 }
1149 .into(),
1150 super::CertificateError::ExpiredContext {
1151 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1152 not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1153 }
1154 .into(),
1155 super::CertificateError::ExpiredRevocationListContext {
1156 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1157 next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1158 }
1159 .into(),
1160 Error::General("undocumented error".to_string()),
1161 Error::FailedToGetCurrentTime,
1162 Error::FailedToGetRandomBytes,
1163 Error::HandshakeNotComplete,
1164 Error::PeerSentOversizedRecord,
1165 Error::NoApplicationProtocol,
1166 Error::BadMaxFragmentSize,
1167 Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
1168 Error::InconsistentKeys(InconsistentKeys::Unknown),
1169 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
1170 Error::Other(OtherError(
1171 #[cfg(feature = "std")]
1172 Arc::from(Box::from("")),
1173 )),
1174 ];
1175
1176 for err in all {
1177 println!("{:?}:", err);
1178 println!(" fmt '{}'", err);
1179 }
1180 }
1181
1182 #[test]
1183 fn rand_error_mapping() {
1184 use super::rand;
1185 let err: Error = rand::GetRandomFailed.into();
1186 assert_eq!(err, Error::FailedToGetRandomBytes);
1187 }
1188
1189 #[cfg(feature = "std")]
1190 #[test]
1191 fn time_error_mapping() {
1192 use std::time::SystemTime;
1193
1194 let time_error = SystemTime::UNIX_EPOCH
1195 .duration_since(SystemTime::now())
1196 .unwrap_err();
1197 let err: Error = time_error.into();
1198 assert_eq!(err, Error::FailedToGetCurrentTime);
1199 }
1200}