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