1use alloc::format;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5#[cfg(feature = "std")]
6use std::time::SystemTimeError;
7
8use crate::enums::{AlertDescription, ContentType, HandshakeType};
9use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
10use crate::rand;
11
12#[non_exhaustive]
14#[derive(Debug, PartialEq, Clone)]
15pub enum Error {
16 InappropriateMessage {
22 expect_types: Vec<ContentType>,
24 got_type: ContentType,
26 },
27
28 InappropriateHandshakeMessage {
32 expect_types: Vec<HandshakeType>,
34 got_type: HandshakeType,
36 },
37
38 InvalidEncryptedClientHello(EncryptedClientHelloError),
40
41 InvalidMessage(InvalidMessage),
43
44 NoCertificatesPresented,
46
47 UnsupportedNameType,
49
50 DecryptError,
52
53 EncryptError,
56
57 PeerIncompatible(PeerIncompatible),
60
61 PeerMisbehaved(PeerMisbehaved),
64
65 AlertReceived(AlertDescription),
67
68 InvalidCertificate(CertificateError),
73
74 InvalidCertRevocationList(CertRevocationListError),
76
77 General(String),
79
80 FailedToGetCurrentTime,
82
83 FailedToGetRandomBytes,
85
86 HandshakeNotComplete,
89
90 PeerSentOversizedRecord,
92
93 NoApplicationProtocol,
95
96 BadMaxFragmentSize,
99
100 InconsistentKeys(InconsistentKeys),
104
105 Other(OtherError),
113}
114
115#[non_exhaustive]
119#[derive(Clone, Copy, Debug, Eq, PartialEq)]
120pub enum InconsistentKeys {
121 KeyMismatch,
125
126 Unknown,
130}
131
132impl From<InconsistentKeys> for Error {
133 #[inline]
134 fn from(e: InconsistentKeys) -> Self {
135 Self::InconsistentKeys(e)
136 }
137}
138
139#[non_exhaustive]
141#[derive(Debug, Clone, Copy, PartialEq)]
142
143pub enum InvalidMessage {
144 CertificatePayloadTooLarge,
146 HandshakePayloadTooLarge,
148 InvalidCcs,
150 InvalidContentType,
152 InvalidCertificateStatusType,
154 InvalidCertRequest,
156 InvalidDhParams,
158 InvalidEmptyPayload,
160 InvalidKeyUpdate,
162 InvalidServerName,
164 MessageTooLarge,
166 MessageTooShort,
168 MissingData(&'static str),
170 MissingKeyExchange,
172 NoSignatureSchemes,
174 TrailingData(&'static str),
176 UnexpectedMessage(&'static str),
178 UnknownProtocolVersion,
180 UnsupportedCompression,
182 UnsupportedCurveType,
184 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
186}
187
188impl From<InvalidMessage> for Error {
189 #[inline]
190 fn from(e: InvalidMessage) -> Self {
191 Self::InvalidMessage(e)
192 }
193}
194
195#[non_exhaustive]
196#[allow(missing_docs)]
197#[derive(Debug, PartialEq, Clone)]
198pub enum PeerMisbehaved {
209 AttemptedDowngradeToTls12WhenTls13IsSupported,
210 BadCertChainExtensions,
211 DisallowedEncryptedExtension,
212 DuplicateClientHelloExtensions,
213 DuplicateEncryptedExtensions,
214 DuplicateHelloRetryRequestExtensions,
215 DuplicateNewSessionTicketExtensions,
216 DuplicateServerHelloExtensions,
217 DuplicateServerNameTypes,
218 EarlyDataAttemptedInSecondClientHello,
219 EarlyDataExtensionWithoutResumption,
220 EarlyDataOfferedWithVariedCipherSuite,
221 HandshakeHashVariedAfterRetry,
222 IllegalHelloRetryRequestWithEmptyCookie,
223 IllegalHelloRetryRequestWithNoChanges,
224 IllegalHelloRetryRequestWithOfferedGroup,
225 IllegalHelloRetryRequestWithUnofferedCipherSuite,
226 IllegalHelloRetryRequestWithUnofferedNamedGroup,
227 IllegalHelloRetryRequestWithUnsupportedVersion,
228 IllegalHelloRetryRequestWithWrongSessionId,
229 IllegalHelloRetryRequestWithInvalidEch,
230 IllegalMiddleboxChangeCipherSpec,
231 IllegalTlsInnerPlaintext,
232 IncorrectBinder,
233 InvalidCertCompression,
234 InvalidMaxEarlyDataSize,
235 InvalidKeyShare,
236 KeyEpochWithPendingFragment,
237 KeyUpdateReceivedInQuicConnection,
238 MessageInterleavedWithHandshakeMessage,
239 MissingBinderInPskExtension,
240 MissingKeyShare,
241 MissingPskModesExtension,
242 MissingQuicTransportParameters,
243 OfferedDuplicateCertificateCompressions,
244 OfferedDuplicateKeyShares,
245 OfferedEarlyDataWithOldProtocolVersion,
246 OfferedEmptyApplicationProtocol,
247 OfferedIncorrectCompressions,
248 PskExtensionMustBeLast,
249 PskExtensionWithMismatchedIdsAndBinders,
250 RefusedToFollowHelloRetryRequest,
251 RejectedEarlyDataInterleavedWithHandshakeMessage,
252 ResumptionAttemptedWithVariedEms,
253 ResumptionOfferedWithVariedCipherSuite,
254 ResumptionOfferedWithVariedEms,
255 ResumptionOfferedWithIncompatibleCipherSuite,
256 SelectedDifferentCipherSuiteAfterRetry,
257 SelectedInvalidPsk,
258 SelectedTls12UsingTls13VersionExtension,
259 SelectedUnofferedApplicationProtocol,
260 SelectedUnofferedCertCompression,
261 SelectedUnofferedCipherSuite,
262 SelectedUnofferedCompression,
263 SelectedUnofferedKxGroup,
264 SelectedUnofferedPsk,
265 SelectedUnusableCipherSuiteForVersion,
266 ServerHelloMustOfferUncompressedEcPoints,
267 ServerNameDifferedOnRetry,
268 ServerNameMustContainOneHostName,
269 SignedKxWithWrongAlgorithm,
270 SignedHandshakeWithUnadvertisedSigScheme,
271 TooManyEmptyFragments,
272 TooManyKeyUpdateRequests,
273 TooManyRenegotiationRequests,
274 TooManyWarningAlertsReceived,
275 TooMuchEarlyDataReceived,
276 UnexpectedCleartextExtension,
277 UnsolicitedCertExtension,
278 UnsolicitedEncryptedExtension,
279 UnsolicitedSctList,
280 UnsolicitedServerHelloExtension,
281 WrongGroupForKeyShare,
282 UnsolicitedEchExtension,
283}
284
285impl From<PeerMisbehaved> for Error {
286 #[inline]
287 fn from(e: PeerMisbehaved) -> Self {
288 Self::PeerMisbehaved(e)
289 }
290}
291
292#[non_exhaustive]
293#[allow(missing_docs)]
294#[derive(Debug, PartialEq, Clone)]
295pub enum PeerIncompatible {
301 EcPointsExtensionRequired,
302 ExtendedMasterSecretExtensionRequired,
303 KeyShareExtensionRequired,
304 NamedGroupsExtensionRequired,
305 NoCertificateRequestSignatureSchemesInCommon,
306 NoCipherSuitesInCommon,
307 NoEcPointFormatsInCommon,
308 NoKxGroupsInCommon,
309 NoSignatureSchemesInCommon,
310 NullCompressionRequired,
311 ServerDoesNotSupportTls12Or13,
312 ServerSentHelloRetryRequestWithUnknownExtension,
313 ServerTlsVersionIsDisabledByOurConfig,
314 SignatureAlgorithmsExtensionRequired,
315 SupportedVersionsExtensionRequired,
316 Tls12NotOffered,
317 Tls12NotOfferedOrEnabled,
318 Tls13RequiredForQuic,
319 UncompressedEcPointsRequired,
320 ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
321}
322
323impl From<PeerIncompatible> for Error {
324 #[inline]
325 fn from(e: PeerIncompatible) -> Self {
326 Self::PeerIncompatible(e)
327 }
328}
329
330#[non_exhaustive]
331#[derive(Debug, Clone)]
332pub enum CertificateError {
340 BadEncoding,
342
343 Expired,
345
346 NotValidYet,
348
349 Revoked,
351
352 UnhandledCriticalExtension,
355
356 UnknownIssuer,
358
359 UnknownRevocationStatus,
361
362 ExpiredRevocationList,
364
365 BadSignature,
368
369 NotValidForName,
372
373 InvalidPurpose,
375
376 ApplicationVerificationFailure,
379
380 Other(OtherError),
391}
392
393impl PartialEq<Self> for CertificateError {
394 fn eq(&self, other: &Self) -> bool {
395 use CertificateError::*;
396 #[allow(clippy::match_like_matches_macro)]
397 match (self, other) {
398 (BadEncoding, BadEncoding) => true,
399 (Expired, Expired) => true,
400 (NotValidYet, NotValidYet) => true,
401 (Revoked, Revoked) => true,
402 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
403 (UnknownIssuer, UnknownIssuer) => true,
404 (BadSignature, BadSignature) => true,
405 (NotValidForName, NotValidForName) => true,
406 (InvalidPurpose, InvalidPurpose) => true,
407 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
408 (ExpiredRevocationList, ExpiredRevocationList) => true,
409 _ => false,
410 }
411 }
412}
413
414impl From<CertificateError> for AlertDescription {
418 fn from(e: CertificateError) -> Self {
419 use CertificateError::*;
420 match e {
421 BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate,
422 Expired | NotValidYet => Self::CertificateExpired,
426 Revoked => Self::CertificateRevoked,
427 UnknownIssuer | UnknownRevocationStatus | ExpiredRevocationList => Self::UnknownCA,
430 BadSignature => Self::DecryptError,
431 InvalidPurpose => Self::UnsupportedCertificate,
432 ApplicationVerificationFailure => Self::AccessDenied,
433 Other(..) => Self::CertificateUnknown,
438 }
439 }
440}
441
442impl From<CertificateError> for Error {
443 #[inline]
444 fn from(e: CertificateError) -> Self {
445 Self::InvalidCertificate(e)
446 }
447}
448
449#[non_exhaustive]
450#[derive(Debug, Clone)]
451pub enum CertRevocationListError {
453 BadSignature,
455
456 InvalidCrlNumber,
458
459 InvalidRevokedCertSerialNumber,
461
462 IssuerInvalidForCrl,
464
465 Other(OtherError),
469
470 ParseError,
472
473 UnsupportedCrlVersion,
475
476 UnsupportedCriticalExtension,
478
479 UnsupportedDeltaCrl,
481
482 UnsupportedIndirectCrl,
485
486 UnsupportedRevocationReason,
491}
492
493impl PartialEq<Self> for CertRevocationListError {
494 fn eq(&self, other: &Self) -> bool {
495 use CertRevocationListError::*;
496 #[allow(clippy::match_like_matches_macro)]
497 match (self, other) {
498 (BadSignature, BadSignature) => true,
499 (InvalidCrlNumber, InvalidCrlNumber) => true,
500 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
501 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
502 (ParseError, ParseError) => true,
503 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
504 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
505 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
506 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
507 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
508 _ => false,
509 }
510 }
511}
512
513impl From<CertRevocationListError> for Error {
514 #[inline]
515 fn from(e: CertRevocationListError) -> Self {
516 Self::InvalidCertRevocationList(e)
517 }
518}
519
520#[non_exhaustive]
521#[derive(Debug, Clone, Eq, PartialEq)]
522pub enum EncryptedClientHelloError {
524 InvalidConfigList,
526 NoCompatibleConfig,
528 SniRequired,
530}
531
532impl From<EncryptedClientHelloError> for Error {
533 #[inline]
534 fn from(e: EncryptedClientHelloError) -> Self {
535 Self::InvalidEncryptedClientHello(e)
536 }
537}
538
539fn join<T: fmt::Debug>(items: &[T]) -> String {
540 items
541 .iter()
542 .map(|x| format!("{:?}", x))
543 .collect::<Vec<String>>()
544 .join(" or ")
545}
546
547impl fmt::Display for Error {
548 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
549 match *self {
550 Self::InappropriateMessage {
551 ref expect_types,
552 ref got_type,
553 } => write!(
554 f,
555 "received unexpected message: got {:?} when expecting {}",
556 got_type,
557 join::<ContentType>(expect_types)
558 ),
559 Self::InappropriateHandshakeMessage {
560 ref expect_types,
561 ref got_type,
562 } => write!(
563 f,
564 "received unexpected handshake message: got {:?} when expecting {}",
565 got_type,
566 join::<HandshakeType>(expect_types)
567 ),
568 Self::InvalidMessage(ref typ) => {
569 write!(f, "received corrupt message of type {:?}", typ)
570 }
571 Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why),
572 Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why),
573 Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
574 Self::InvalidCertificate(ref err) => {
575 write!(f, "invalid peer certificate: {:?}", err)
576 }
577 Self::InvalidCertRevocationList(ref err) => {
578 write!(f, "invalid certificate revocation list: {:?}", err)
579 }
580 Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
581 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
582 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
583 Self::InvalidEncryptedClientHello(ref err) => {
584 write!(f, "encrypted client hello failure: {:?}", err)
585 }
586 Self::EncryptError => write!(f, "cannot encrypt message"),
587 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
588 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
589 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
590 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
591 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
592 Self::BadMaxFragmentSize => {
593 write!(f, "the supplied max_fragment_size was too small or large")
594 }
595 Self::InconsistentKeys(ref why) => {
596 write!(f, "keys may not be consistent: {:?}", why)
597 }
598 Self::General(ref err) => write!(f, "unexpected error: {}", err),
599 Self::Other(ref err) => write!(f, "other error: {}", err),
600 }
601 }
602}
603
604#[cfg(feature = "std")]
605impl From<SystemTimeError> for Error {
606 #[inline]
607 fn from(_: SystemTimeError) -> Self {
608 Self::FailedToGetCurrentTime
609 }
610}
611
612#[cfg(feature = "std")]
613impl std::error::Error for Error {}
614
615impl From<rand::GetRandomFailed> for Error {
616 fn from(_: rand::GetRandomFailed) -> Self {
617 Self::FailedToGetRandomBytes
618 }
619}
620
621mod other_error {
622 #[cfg(feature = "std")]
623 use alloc::sync::Arc;
624 use core::fmt;
625 #[cfg(feature = "std")]
626 use std::error::Error as StdError;
627
628 use super::Error;
629
630 #[derive(Debug, Clone)]
637 pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
638
639 impl PartialEq<Self> for OtherError {
640 fn eq(&self, _other: &Self) -> bool {
641 false
642 }
643 }
644
645 impl From<OtherError> for Error {
646 fn from(value: OtherError) -> Self {
647 Self::Other(value)
648 }
649 }
650
651 impl fmt::Display for OtherError {
652 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
653 #[cfg(feature = "std")]
654 {
655 write!(f, "{}", self.0)
656 }
657 #[cfg(not(feature = "std"))]
658 {
659 f.write_str("no further information available")
660 }
661 }
662 }
663
664 #[cfg(feature = "std")]
665 impl StdError for OtherError {
666 fn source(&self) -> Option<&(dyn StdError + 'static)> {
667 Some(self.0.as_ref())
668 }
669 }
670}
671
672pub use other_error::OtherError;
673
674#[cfg(test)]
675mod tests {
676 use std::prelude::v1::*;
677 use std::{println, vec};
678
679 use super::{Error, InconsistentKeys, InvalidMessage};
680 use crate::error::{CertRevocationListError, OtherError};
681
682 #[test]
683 fn certificate_error_equality() {
684 use super::CertificateError::*;
685 assert_eq!(BadEncoding, BadEncoding);
686 assert_eq!(Expired, Expired);
687 assert_eq!(NotValidYet, NotValidYet);
688 assert_eq!(Revoked, Revoked);
689 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
690 assert_eq!(UnknownIssuer, UnknownIssuer);
691 assert_eq!(BadSignature, BadSignature);
692 assert_eq!(NotValidForName, NotValidForName);
693 assert_eq!(InvalidPurpose, InvalidPurpose);
694 assert_eq!(
695 ApplicationVerificationFailure,
696 ApplicationVerificationFailure
697 );
698 let other = Other(OtherError(
699 #[cfg(feature = "std")]
700 alloc::sync::Arc::from(Box::from("")),
701 ));
702 assert_ne!(other, other);
703 assert_ne!(BadEncoding, Expired);
704 }
705
706 #[test]
707 fn crl_error_equality() {
708 use super::CertRevocationListError::*;
709 assert_eq!(BadSignature, BadSignature);
710 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
711 assert_eq!(
712 InvalidRevokedCertSerialNumber,
713 InvalidRevokedCertSerialNumber
714 );
715 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
716 assert_eq!(ParseError, ParseError);
717 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
718 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
719 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
720 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
721 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
722 let other = Other(OtherError(
723 #[cfg(feature = "std")]
724 alloc::sync::Arc::from(Box::from("")),
725 ));
726 assert_ne!(other, other);
727 assert_ne!(BadSignature, InvalidCrlNumber);
728 }
729
730 #[test]
731 #[cfg(feature = "std")]
732 fn other_error_equality() {
733 let other_error = OtherError(alloc::sync::Arc::from(Box::from("")));
734 assert_ne!(other_error, other_error);
735 let other: Error = other_error.into();
736 assert_ne!(other, other);
737 }
738
739 #[test]
740 fn smoke() {
741 use crate::enums::{AlertDescription, ContentType, HandshakeType};
742
743 let all = vec![
744 Error::InappropriateMessage {
745 expect_types: vec![ContentType::Alert],
746 got_type: ContentType::Handshake,
747 },
748 Error::InappropriateHandshakeMessage {
749 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
750 got_type: HandshakeType::ServerHello,
751 },
752 Error::InvalidMessage(InvalidMessage::InvalidCcs),
753 Error::NoCertificatesPresented,
754 Error::DecryptError,
755 super::PeerIncompatible::Tls12NotOffered.into(),
756 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
757 Error::AlertReceived(AlertDescription::ExportRestriction),
758 super::CertificateError::Expired.into(),
759 Error::General("undocumented error".to_string()),
760 Error::FailedToGetCurrentTime,
761 Error::FailedToGetRandomBytes,
762 Error::HandshakeNotComplete,
763 Error::PeerSentOversizedRecord,
764 Error::NoApplicationProtocol,
765 Error::BadMaxFragmentSize,
766 Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
767 Error::InconsistentKeys(InconsistentKeys::Unknown),
768 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
769 Error::Other(OtherError(
770 #[cfg(feature = "std")]
771 alloc::sync::Arc::from(Box::from("")),
772 )),
773 ];
774
775 for err in all {
776 println!("{:?}:", err);
777 println!(" fmt '{}'", err);
778 }
779 }
780
781 #[test]
782 fn rand_error_mapping() {
783 use super::rand;
784 let err: Error = rand::GetRandomFailed.into();
785 assert_eq!(err, Error::FailedToGetRandomBytes);
786 }
787
788 #[cfg(feature = "std")]
789 #[test]
790 fn time_error_mapping() {
791 use std::time::SystemTime;
792
793 let time_error = SystemTime::UNIX_EPOCH
794 .duration_since(SystemTime::now())
795 .unwrap_err();
796 let err: Error = time_error.into();
797 assert_eq!(err, Error::FailedToGetCurrentTime);
798 }
799}