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    use core::fmt;
625    #[cfg(feature = "std")]
626    use std::error::Error as StdError;
627
628    use super::Error;
629    #[cfg(feature = "std")]
630    use crate::sync::Arc;
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    #[cfg(feature = "std")]
683    use crate::sync::Arc;
684
685    #[test]
686    fn certificate_error_equality() {
687        use super::CertificateError::*;
688        assert_eq!(BadEncoding, BadEncoding);
689        assert_eq!(Expired, Expired);
690        assert_eq!(NotValidYet, NotValidYet);
691        assert_eq!(Revoked, Revoked);
692        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
693        assert_eq!(UnknownIssuer, UnknownIssuer);
694        assert_eq!(BadSignature, BadSignature);
695        assert_eq!(NotValidForName, NotValidForName);
696        assert_eq!(InvalidPurpose, InvalidPurpose);
697        assert_eq!(
698            ApplicationVerificationFailure,
699            ApplicationVerificationFailure
700        );
701        let other = Other(OtherError(
702            #[cfg(feature = "std")]
703            Arc::from(Box::from("")),
704        ));
705        assert_ne!(other, other);
706        assert_ne!(BadEncoding, Expired);
707    }
708
709    #[test]
710    fn crl_error_equality() {
711        use super::CertRevocationListError::*;
712        assert_eq!(BadSignature, BadSignature);
713        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
714        assert_eq!(
715            InvalidRevokedCertSerialNumber,
716            InvalidRevokedCertSerialNumber
717        );
718        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
719        assert_eq!(ParseError, ParseError);
720        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
721        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
722        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
723        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
724        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
725        let other = Other(OtherError(
726            #[cfg(feature = "std")]
727            Arc::from(Box::from("")),
728        ));
729        assert_ne!(other, other);
730        assert_ne!(BadSignature, InvalidCrlNumber);
731    }
732
733    #[test]
734    #[cfg(feature = "std")]
735    fn other_error_equality() {
736        let other_error = OtherError(Arc::from(Box::from("")));
737        assert_ne!(other_error, other_error);
738        let other: Error = other_error.into();
739        assert_ne!(other, other);
740    }
741
742    #[test]
743    fn smoke() {
744        use crate::enums::{AlertDescription, ContentType, HandshakeType};
745
746        let all = vec![
747            Error::InappropriateMessage {
748                expect_types: vec![ContentType::Alert],
749                got_type: ContentType::Handshake,
750            },
751            Error::InappropriateHandshakeMessage {
752                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
753                got_type: HandshakeType::ServerHello,
754            },
755            Error::InvalidMessage(InvalidMessage::InvalidCcs),
756            Error::NoCertificatesPresented,
757            Error::DecryptError,
758            super::PeerIncompatible::Tls12NotOffered.into(),
759            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
760            Error::AlertReceived(AlertDescription::ExportRestriction),
761            super::CertificateError::Expired.into(),
762            Error::General("undocumented error".to_string()),
763            Error::FailedToGetCurrentTime,
764            Error::FailedToGetRandomBytes,
765            Error::HandshakeNotComplete,
766            Error::PeerSentOversizedRecord,
767            Error::NoApplicationProtocol,
768            Error::BadMaxFragmentSize,
769            Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
770            Error::InconsistentKeys(InconsistentKeys::Unknown),
771            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
772            Error::Other(OtherError(
773                #[cfg(feature = "std")]
774                Arc::from(Box::from("")),
775            )),
776        ];
777
778        for err in all {
779            println!("{:?}:", err);
780            println!("  fmt '{}'", err);
781        }
782    }
783
784    #[test]
785    fn rand_error_mapping() {
786        use super::rand;
787        let err: Error = rand::GetRandomFailed.into();
788        assert_eq!(err, Error::FailedToGetRandomBytes);
789    }
790
791    #[cfg(feature = "std")]
792    #[test]
793    fn time_error_mapping() {
794        use std::time::SystemTime;
795
796        let time_error = SystemTime::UNIX_EPOCH
797            .duration_since(SystemTime::now())
798            .unwrap_err();
799        let err: Error = time_error.into();
800        assert_eq!(err, Error::FailedToGetCurrentTime);
801    }
802}