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 IncorrectCertificateTypeExtension,
304 KeyShareExtensionRequired,
305 NamedGroupsExtensionRequired,
306 NoCertificateRequestSignatureSchemesInCommon,
307 NoCipherSuitesInCommon,
308 NoEcPointFormatsInCommon,
309 NoKxGroupsInCommon,
310 NoSignatureSchemesInCommon,
311 NullCompressionRequired,
312 ServerDoesNotSupportTls12Or13,
313 ServerSentHelloRetryRequestWithUnknownExtension,
314 ServerTlsVersionIsDisabledByOurConfig,
315 SignatureAlgorithmsExtensionRequired,
316 SupportedVersionsExtensionRequired,
317 Tls12NotOffered,
318 Tls12NotOfferedOrEnabled,
319 Tls13RequiredForQuic,
320 UncompressedEcPointsRequired,
321 UnsolicitedCertificateTypeExtension,
322 ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
323}
324
325impl From<PeerIncompatible> for Error {
326 #[inline]
327 fn from(e: PeerIncompatible) -> Self {
328 Self::PeerIncompatible(e)
329 }
330}
331
332#[non_exhaustive]
333#[derive(Debug, Clone)]
334pub enum CertificateError {
342 BadEncoding,
344
345 Expired,
347
348 NotValidYet,
350
351 Revoked,
353
354 UnhandledCriticalExtension,
357
358 UnknownIssuer,
360
361 UnknownRevocationStatus,
363
364 ExpiredRevocationList,
366
367 BadSignature,
370
371 NotValidForName,
374
375 InvalidPurpose,
377
378 ApplicationVerificationFailure,
381
382 Other(OtherError),
393}
394
395impl PartialEq<Self> for CertificateError {
396 fn eq(&self, other: &Self) -> bool {
397 use CertificateError::*;
398 #[allow(clippy::match_like_matches_macro)]
399 match (self, other) {
400 (BadEncoding, BadEncoding) => true,
401 (Expired, Expired) => true,
402 (NotValidYet, NotValidYet) => true,
403 (Revoked, Revoked) => true,
404 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
405 (UnknownIssuer, UnknownIssuer) => true,
406 (BadSignature, BadSignature) => true,
407 (NotValidForName, NotValidForName) => true,
408 (InvalidPurpose, InvalidPurpose) => true,
409 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
410 (ExpiredRevocationList, ExpiredRevocationList) => true,
411 _ => false,
412 }
413 }
414}
415
416impl From<CertificateError> for AlertDescription {
420 fn from(e: CertificateError) -> Self {
421 use CertificateError::*;
422 match e {
423 BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate,
424 Expired | NotValidYet => Self::CertificateExpired,
428 Revoked => Self::CertificateRevoked,
429 UnknownIssuer | UnknownRevocationStatus | ExpiredRevocationList => Self::UnknownCA,
432 BadSignature => Self::DecryptError,
433 InvalidPurpose => Self::UnsupportedCertificate,
434 ApplicationVerificationFailure => Self::AccessDenied,
435 Other(..) => Self::CertificateUnknown,
440 }
441 }
442}
443
444impl From<CertificateError> for Error {
445 #[inline]
446 fn from(e: CertificateError) -> Self {
447 Self::InvalidCertificate(e)
448 }
449}
450
451#[non_exhaustive]
452#[derive(Debug, Clone)]
453pub enum CertRevocationListError {
455 BadSignature,
457
458 InvalidCrlNumber,
460
461 InvalidRevokedCertSerialNumber,
463
464 IssuerInvalidForCrl,
466
467 Other(OtherError),
471
472 ParseError,
474
475 UnsupportedCrlVersion,
477
478 UnsupportedCriticalExtension,
480
481 UnsupportedDeltaCrl,
483
484 UnsupportedIndirectCrl,
487
488 UnsupportedRevocationReason,
493}
494
495impl PartialEq<Self> for CertRevocationListError {
496 fn eq(&self, other: &Self) -> bool {
497 use CertRevocationListError::*;
498 #[allow(clippy::match_like_matches_macro)]
499 match (self, other) {
500 (BadSignature, BadSignature) => true,
501 (InvalidCrlNumber, InvalidCrlNumber) => true,
502 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
503 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
504 (ParseError, ParseError) => true,
505 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
506 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
507 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
508 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
509 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
510 _ => false,
511 }
512 }
513}
514
515impl From<CertRevocationListError> for Error {
516 #[inline]
517 fn from(e: CertRevocationListError) -> Self {
518 Self::InvalidCertRevocationList(e)
519 }
520}
521
522#[non_exhaustive]
523#[derive(Debug, Clone, Eq, PartialEq)]
524pub enum EncryptedClientHelloError {
526 InvalidConfigList,
528 NoCompatibleConfig,
530 SniRequired,
532}
533
534impl From<EncryptedClientHelloError> for Error {
535 #[inline]
536 fn from(e: EncryptedClientHelloError) -> Self {
537 Self::InvalidEncryptedClientHello(e)
538 }
539}
540
541fn join<T: fmt::Debug>(items: &[T]) -> String {
542 items
543 .iter()
544 .map(|x| format!("{:?}", x))
545 .collect::<Vec<String>>()
546 .join(" or ")
547}
548
549impl fmt::Display for Error {
550 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
551 match *self {
552 Self::InappropriateMessage {
553 ref expect_types,
554 ref got_type,
555 } => write!(
556 f,
557 "received unexpected message: got {:?} when expecting {}",
558 got_type,
559 join::<ContentType>(expect_types)
560 ),
561 Self::InappropriateHandshakeMessage {
562 ref expect_types,
563 ref got_type,
564 } => write!(
565 f,
566 "received unexpected handshake message: got {:?} when expecting {}",
567 got_type,
568 join::<HandshakeType>(expect_types)
569 ),
570 Self::InvalidMessage(ref typ) => {
571 write!(f, "received corrupt message of type {:?}", typ)
572 }
573 Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why),
574 Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why),
575 Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
576 Self::InvalidCertificate(ref err) => {
577 write!(f, "invalid peer certificate: {:?}", err)
578 }
579 Self::InvalidCertRevocationList(ref err) => {
580 write!(f, "invalid certificate revocation list: {:?}", err)
581 }
582 Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
583 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
584 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
585 Self::InvalidEncryptedClientHello(ref err) => {
586 write!(f, "encrypted client hello failure: {:?}", err)
587 }
588 Self::EncryptError => write!(f, "cannot encrypt message"),
589 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
590 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
591 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
592 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
593 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
594 Self::BadMaxFragmentSize => {
595 write!(f, "the supplied max_fragment_size was too small or large")
596 }
597 Self::InconsistentKeys(ref why) => {
598 write!(f, "keys may not be consistent: {:?}", why)
599 }
600 Self::General(ref err) => write!(f, "unexpected error: {}", err),
601 Self::Other(ref err) => write!(f, "other error: {}", err),
602 }
603 }
604}
605
606#[cfg(feature = "std")]
607impl From<SystemTimeError> for Error {
608 #[inline]
609 fn from(_: SystemTimeError) -> Self {
610 Self::FailedToGetCurrentTime
611 }
612}
613
614#[cfg(feature = "std")]
615impl std::error::Error for Error {}
616
617impl From<rand::GetRandomFailed> for Error {
618 fn from(_: rand::GetRandomFailed) -> Self {
619 Self::FailedToGetRandomBytes
620 }
621}
622
623mod other_error {
624 #[cfg(feature = "std")]
625 use alloc::sync::Arc;
626 use core::fmt;
627 #[cfg(feature = "std")]
628 use std::error::Error as StdError;
629
630 use super::Error;
631
632 #[derive(Debug, Clone)]
639 pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
640
641 impl PartialEq<Self> for OtherError {
642 fn eq(&self, _other: &Self) -> bool {
643 false
644 }
645 }
646
647 impl From<OtherError> for Error {
648 fn from(value: OtherError) -> Self {
649 Self::Other(value)
650 }
651 }
652
653 impl fmt::Display for OtherError {
654 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
655 #[cfg(feature = "std")]
656 {
657 write!(f, "{}", self.0)
658 }
659 #[cfg(not(feature = "std"))]
660 {
661 f.write_str("no further information available")
662 }
663 }
664 }
665
666 #[cfg(feature = "std")]
667 impl StdError for OtherError {
668 fn source(&self) -> Option<&(dyn StdError + 'static)> {
669 Some(self.0.as_ref())
670 }
671 }
672}
673
674pub use other_error::OtherError;
675
676#[cfg(test)]
677mod tests {
678 use std::prelude::v1::*;
679 use std::{println, vec};
680
681 use super::{CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError};
682
683 #[test]
684 fn certificate_error_equality() {
685 use super::CertificateError::*;
686 assert_eq!(BadEncoding, BadEncoding);
687 assert_eq!(Expired, Expired);
688 assert_eq!(NotValidYet, NotValidYet);
689 assert_eq!(Revoked, Revoked);
690 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
691 assert_eq!(UnknownIssuer, UnknownIssuer);
692 assert_eq!(BadSignature, BadSignature);
693 assert_eq!(NotValidForName, NotValidForName);
694 assert_eq!(InvalidPurpose, InvalidPurpose);
695 assert_eq!(
696 ApplicationVerificationFailure,
697 ApplicationVerificationFailure
698 );
699 let other = Other(OtherError(
700 #[cfg(feature = "std")]
701 alloc::sync::Arc::from(Box::from("")),
702 ));
703 assert_ne!(other, other);
704 assert_ne!(BadEncoding, Expired);
705 }
706
707 #[test]
708 fn crl_error_equality() {
709 use super::CertRevocationListError::*;
710 assert_eq!(BadSignature, BadSignature);
711 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
712 assert_eq!(
713 InvalidRevokedCertSerialNumber,
714 InvalidRevokedCertSerialNumber
715 );
716 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
717 assert_eq!(ParseError, ParseError);
718 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
719 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
720 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
721 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
722 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
723 let other = Other(OtherError(
724 #[cfg(feature = "std")]
725 alloc::sync::Arc::from(Box::from("")),
726 ));
727 assert_ne!(other, other);
728 assert_ne!(BadSignature, InvalidCrlNumber);
729 }
730
731 #[test]
732 #[cfg(feature = "std")]
733 fn other_error_equality() {
734 let other_error = OtherError(alloc::sync::Arc::from(Box::from("")));
735 assert_ne!(other_error, other_error);
736 let other: Error = other_error.into();
737 assert_ne!(other, other);
738 }
739
740 #[test]
741 fn smoke() {
742 use crate::enums::{AlertDescription, ContentType, HandshakeType};
743
744 let all = vec![
745 Error::InappropriateMessage {
746 expect_types: vec![ContentType::Alert],
747 got_type: ContentType::Handshake,
748 },
749 Error::InappropriateHandshakeMessage {
750 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
751 got_type: HandshakeType::ServerHello,
752 },
753 Error::InvalidMessage(InvalidMessage::InvalidCcs),
754 Error::NoCertificatesPresented,
755 Error::DecryptError,
756 super::PeerIncompatible::Tls12NotOffered.into(),
757 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
758 Error::AlertReceived(AlertDescription::ExportRestriction),
759 super::CertificateError::Expired.into(),
760 Error::General("undocumented error".to_string()),
761 Error::FailedToGetCurrentTime,
762 Error::FailedToGetRandomBytes,
763 Error::HandshakeNotComplete,
764 Error::PeerSentOversizedRecord,
765 Error::NoApplicationProtocol,
766 Error::BadMaxFragmentSize,
767 Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
768 Error::InconsistentKeys(InconsistentKeys::Unknown),
769 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
770 Error::Other(OtherError(
771 #[cfg(feature = "std")]
772 alloc::sync::Arc::from(Box::from("")),
773 )),
774 ];
775
776 for err in all {
777 println!("{:?}:", err);
778 println!(" fmt '{}'", err);
779 }
780 }
781
782 #[test]
783 fn rand_error_mapping() {
784 use super::rand;
785 let err: Error = rand::GetRandomFailed.into();
786 assert_eq!(err, Error::FailedToGetRandomBytes);
787 }
788
789 #[cfg(feature = "std")]
790 #[test]
791 fn time_error_mapping() {
792 use std::time::SystemTime;
793
794 let time_error = SystemTime::UNIX_EPOCH
795 .duration_since(SystemTime::now())
796 .unwrap_err();
797 let err: Error = time_error.into();
798 assert_eq!(err, Error::FailedToGetCurrentTime);
799 }
800}