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::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    InvalidMessage(InvalidMessage),
40
41    NoCertificatesPresented,
43
44    UnsupportedNameType,
46
47    DecryptError,
49
50    EncryptError,
53
54    PeerIncompatible(PeerIncompatible),
57
58    PeerMisbehaved(PeerMisbehaved),
61
62    AlertReceived(AlertDescription),
64
65    InvalidCertificate(CertificateError),
70
71    InvalidCertRevocationList(CertRevocationListError),
73
74    General(String),
76
77    FailedToGetCurrentTime,
79
80    FailedToGetRandomBytes,
82
83    HandshakeNotComplete,
86
87    PeerSentOversizedRecord,
89
90    NoApplicationProtocol,
92
93    BadMaxFragmentSize,
96
97    Other(OtherError),
105}
106
107#[non_exhaustive]
109#[derive(Debug, Clone, Copy, PartialEq)]
110
111pub enum InvalidMessage {
112    HandshakePayloadTooLarge,
114    InvalidCcs,
116    InvalidContentType,
118    InvalidCertificateStatusType,
120    InvalidCertRequest,
122    InvalidDhParams,
124    InvalidEmptyPayload,
126    InvalidKeyUpdate,
128    InvalidServerName,
130    MessageTooLarge,
132    MessageTooShort,
134    MissingData(&'static str),
136    MissingKeyExchange,
138    NoSignatureSchemes,
140    TrailingData(&'static str),
142    UnexpectedMessage(&'static str),
144    UnknownProtocolVersion,
146    UnsupportedCompression,
148    UnsupportedCurveType,
150    UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
152}
153
154impl From<InvalidMessage> for Error {
155    #[inline]
156    fn from(e: InvalidMessage) -> Self {
157        Self::InvalidMessage(e)
158    }
159}
160
161#[non_exhaustive]
162#[allow(missing_docs)]
163#[derive(Debug, PartialEq, Clone)]
164pub enum PeerMisbehaved {
175    AttemptedDowngradeToTls12WhenTls13IsSupported,
176    BadCertChainExtensions,
177    DisallowedEncryptedExtension,
178    DuplicateClientHelloExtensions,
179    DuplicateEncryptedExtensions,
180    DuplicateHelloRetryRequestExtensions,
181    DuplicateNewSessionTicketExtensions,
182    DuplicateServerHelloExtensions,
183    DuplicateServerNameTypes,
184    EarlyDataAttemptedInSecondClientHello,
185    EarlyDataExtensionWithoutResumption,
186    EarlyDataOfferedWithVariedCipherSuite,
187    HandshakeHashVariedAfterRetry,
188    IllegalHelloRetryRequestWithEmptyCookie,
189    IllegalHelloRetryRequestWithNoChanges,
190    IllegalHelloRetryRequestWithOfferedGroup,
191    IllegalHelloRetryRequestWithUnofferedCipherSuite,
192    IllegalHelloRetryRequestWithUnofferedNamedGroup,
193    IllegalHelloRetryRequestWithUnsupportedVersion,
194    IllegalHelloRetryRequestWithWrongSessionId,
195    IllegalMiddleboxChangeCipherSpec,
196    IllegalTlsInnerPlaintext,
197    IncorrectBinder,
198    InvalidMaxEarlyDataSize,
199    InvalidKeyShare,
200    KeyEpochWithPendingFragment,
201    KeyUpdateReceivedInQuicConnection,
202    MessageInterleavedWithHandshakeMessage,
203    MissingBinderInPskExtension,
204    MissingKeyShare,
205    MissingPskModesExtension,
206    MissingQuicTransportParameters,
207    OfferedDuplicateKeyShares,
208    OfferedEarlyDataWithOldProtocolVersion,
209    OfferedEmptyApplicationProtocol,
210    OfferedIncorrectCompressions,
211    PskExtensionMustBeLast,
212    PskExtensionWithMismatchedIdsAndBinders,
213    RefusedToFollowHelloRetryRequest,
214    RejectedEarlyDataInterleavedWithHandshakeMessage,
215    ResumptionAttemptedWithVariedEms,
216    ResumptionOfferedWithVariedCipherSuite,
217    ResumptionOfferedWithVariedEms,
218    ResumptionOfferedWithIncompatibleCipherSuite,
219    SelectedDifferentCipherSuiteAfterRetry,
220    SelectedInvalidPsk,
221    SelectedTls12UsingTls13VersionExtension,
222    SelectedUnofferedApplicationProtocol,
223    SelectedUnofferedCipherSuite,
224    SelectedUnofferedCompression,
225    SelectedUnofferedKxGroup,
226    SelectedUnofferedPsk,
227    SelectedUnusableCipherSuiteForVersion,
228    ServerHelloMustOfferUncompressedEcPoints,
229    ServerNameDifferedOnRetry,
230    ServerNameMustContainOneHostName,
231    SignedKxWithWrongAlgorithm,
232    SignedHandshakeWithUnadvertisedSigScheme,
233    TooMuchEarlyDataReceived,
234    UnexpectedCleartextExtension,
235    UnsolicitedCertExtension,
236    UnsolicitedEncryptedExtension,
237    UnsolicitedSctList,
238    UnsolicitedServerHelloExtension,
239    WrongGroupForKeyShare,
240}
241
242impl From<PeerMisbehaved> for Error {
243    #[inline]
244    fn from(e: PeerMisbehaved) -> Self {
245        Self::PeerMisbehaved(e)
246    }
247}
248
249#[non_exhaustive]
250#[allow(missing_docs)]
251#[derive(Debug, PartialEq, Clone)]
252pub enum PeerIncompatible {
258    EcPointsExtensionRequired,
259    ExtendedMasterSecretExtensionRequired,
260    KeyShareExtensionRequired,
261    NamedGroupsExtensionRequired,
262    NoCertificateRequestSignatureSchemesInCommon,
263    NoCipherSuitesInCommon,
264    NoEcPointFormatsInCommon,
265    NoKxGroupsInCommon,
266    NoSignatureSchemesInCommon,
267    NullCompressionRequired,
268    ServerDoesNotSupportTls12Or13,
269    ServerSentHelloRetryRequestWithUnknownExtension,
270    ServerTlsVersionIsDisabledByOurConfig,
271    SignatureAlgorithmsExtensionRequired,
272    SupportedVersionsExtensionRequired,
273    Tls12NotOffered,
274    Tls12NotOfferedOrEnabled,
275    Tls13RequiredForQuic,
276    UncompressedEcPointsRequired,
277}
278
279impl From<PeerIncompatible> for Error {
280    #[inline]
281    fn from(e: PeerIncompatible) -> Self {
282        Self::PeerIncompatible(e)
283    }
284}
285
286#[non_exhaustive]
287#[derive(Debug, Clone)]
288pub enum CertificateError {
296    BadEncoding,
298
299    Expired,
301
302    NotValidYet,
304
305    Revoked,
307
308    UnhandledCriticalExtension,
311
312    UnknownIssuer,
314
315    UnknownRevocationStatus,
317
318    BadSignature,
321
322    NotValidForName,
325
326    InvalidPurpose,
328
329    ApplicationVerificationFailure,
332
333    Other(OtherError),
344}
345
346impl PartialEq<Self> for CertificateError {
347    fn eq(&self, other: &Self) -> bool {
348        use CertificateError::*;
349        #[allow(clippy::match_like_matches_macro)]
350        match (self, other) {
351            (BadEncoding, BadEncoding) => true,
352            (Expired, Expired) => true,
353            (NotValidYet, NotValidYet) => true,
354            (Revoked, Revoked) => true,
355            (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
356            (UnknownIssuer, UnknownIssuer) => true,
357            (BadSignature, BadSignature) => true,
358            (NotValidForName, NotValidForName) => true,
359            (InvalidPurpose, InvalidPurpose) => true,
360            (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
361            _ => false,
362        }
363    }
364}
365
366impl From<CertificateError> for AlertDescription {
370    fn from(e: CertificateError) -> Self {
371        use CertificateError::*;
372        match e {
373            BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate,
374            Expired | NotValidYet => Self::CertificateExpired,
378            Revoked => Self::CertificateRevoked,
379            UnknownIssuer | UnknownRevocationStatus => Self::UnknownCA,
382            BadSignature => Self::DecryptError,
383            InvalidPurpose => Self::UnsupportedCertificate,
384            ApplicationVerificationFailure => Self::AccessDenied,
385            Other(..) => Self::CertificateUnknown,
390        }
391    }
392}
393
394impl From<CertificateError> for Error {
395    #[inline]
396    fn from(e: CertificateError) -> Self {
397        Self::InvalidCertificate(e)
398    }
399}
400
401#[non_exhaustive]
402#[derive(Debug, Clone)]
403pub enum CertRevocationListError {
405    BadSignature,
407
408    InvalidCrlNumber,
410
411    InvalidRevokedCertSerialNumber,
413
414    IssuerInvalidForCrl,
416
417    Other(OtherError),
421
422    ParseError,
424
425    UnsupportedCrlVersion,
427
428    UnsupportedCriticalExtension,
430
431    UnsupportedDeltaCrl,
433
434    UnsupportedIndirectCrl,
437
438    UnsupportedRevocationReason,
443}
444
445impl PartialEq<Self> for CertRevocationListError {
446    fn eq(&self, other: &Self) -> bool {
447        use CertRevocationListError::*;
448        #[allow(clippy::match_like_matches_macro)]
449        match (self, other) {
450            (BadSignature, BadSignature) => true,
451            (InvalidCrlNumber, InvalidCrlNumber) => true,
452            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
453            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
454            (ParseError, ParseError) => true,
455            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
456            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
457            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
458            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
459            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
460            _ => false,
461        }
462    }
463}
464
465impl From<CertRevocationListError> for Error {
466    #[inline]
467    fn from(e: CertRevocationListError) -> Self {
468        Self::InvalidCertRevocationList(e)
469    }
470}
471
472fn join<T: fmt::Debug>(items: &[T]) -> String {
473    items
474        .iter()
475        .map(|x| format!("{:?}", x))
476        .collect::<Vec<String>>()
477        .join(" or ")
478}
479
480impl fmt::Display for Error {
481    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
482        match *self {
483            Self::InappropriateMessage {
484                ref expect_types,
485                ref got_type,
486            } => write!(
487                f,
488                "received unexpected message: got {:?} when expecting {}",
489                got_type,
490                join::<ContentType>(expect_types)
491            ),
492            Self::InappropriateHandshakeMessage {
493                ref expect_types,
494                ref got_type,
495            } => write!(
496                f,
497                "received unexpected handshake message: got {:?} when expecting {}",
498                got_type,
499                join::<HandshakeType>(expect_types)
500            ),
501            Self::InvalidMessage(ref typ) => {
502                write!(f, "received corrupt message of type {:?}", typ)
503            }
504            Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why),
505            Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why),
506            Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
507            Self::InvalidCertificate(ref err) => {
508                write!(f, "invalid peer certificate: {:?}", err)
509            }
510            Self::InvalidCertRevocationList(ref err) => {
511                write!(f, "invalid certificate revocation list: {:?}", err)
512            }
513            Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
514            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
515            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
516            Self::EncryptError => write!(f, "cannot encrypt message"),
517            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
518            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
519            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
520            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
521            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
522            Self::BadMaxFragmentSize => {
523                write!(f, "the supplied max_fragment_size was too small or large")
524            }
525            Self::General(ref err) => write!(f, "unexpected error: {}", err),
526            Self::Other(ref err) => write!(f, "other error: {}", err),
527        }
528    }
529}
530
531#[cfg(feature = "std")]
532impl From<SystemTimeError> for Error {
533    #[inline]
534    fn from(_: SystemTimeError) -> Self {
535        Self::FailedToGetCurrentTime
536    }
537}
538
539#[cfg(feature = "std")]
540impl std::error::Error for Error {}
541
542impl From<rand::GetRandomFailed> for Error {
543    fn from(_: rand::GetRandomFailed) -> Self {
544        Self::FailedToGetRandomBytes
545    }
546}
547
548mod other_error {
549    #[cfg(feature = "std")]
550    use alloc::sync::Arc;
551    use core::fmt;
552    #[cfg(feature = "std")]
553    use std::error::Error as StdError;
554
555    use super::Error;
556
557    #[derive(Debug, Clone)]
564    pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
565
566    impl PartialEq<Self> for OtherError {
567        fn eq(&self, _other: &Self) -> bool {
568            false
569        }
570    }
571
572    impl From<OtherError> for Error {
573        fn from(value: OtherError) -> Self {
574            Self::Other(value)
575        }
576    }
577
578    impl fmt::Display for OtherError {
579        fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
580            #[cfg(feature = "std")]
581            {
582                write!(f, "{}", self.0)
583            }
584            #[cfg(not(feature = "std"))]
585            {
586                f.write_str("no further information available")
587            }
588        }
589    }
590
591    #[cfg(feature = "std")]
592    impl StdError for OtherError {
593        fn source(&self) -> Option<&(dyn StdError + 'static)> {
594            Some(self.0.as_ref())
595        }
596    }
597}
598
599pub use other_error::OtherError;
600
601#[cfg(test)]
602mod tests {
603    use std::prelude::v1::*;
604    use std::{println, vec};
605
606    use super::{Error, InvalidMessage};
607    use crate::error::{CertRevocationListError, OtherError};
608
609    #[test]
610    fn certificate_error_equality() {
611        use super::CertificateError::*;
612        assert_eq!(BadEncoding, BadEncoding);
613        assert_eq!(Expired, Expired);
614        assert_eq!(NotValidYet, NotValidYet);
615        assert_eq!(Revoked, Revoked);
616        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
617        assert_eq!(UnknownIssuer, UnknownIssuer);
618        assert_eq!(BadSignature, BadSignature);
619        assert_eq!(NotValidForName, NotValidForName);
620        assert_eq!(InvalidPurpose, InvalidPurpose);
621        assert_eq!(
622            ApplicationVerificationFailure,
623            ApplicationVerificationFailure
624        );
625        let other = Other(OtherError(
626            #[cfg(feature = "std")]
627            alloc::sync::Arc::from(Box::from("")),
628        ));
629        assert_ne!(other, other);
630        assert_ne!(BadEncoding, Expired);
631    }
632
633    #[test]
634    fn crl_error_equality() {
635        use super::CertRevocationListError::*;
636        assert_eq!(BadSignature, BadSignature);
637        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
638        assert_eq!(
639            InvalidRevokedCertSerialNumber,
640            InvalidRevokedCertSerialNumber
641        );
642        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
643        assert_eq!(ParseError, ParseError);
644        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
645        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
646        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
647        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
648        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
649        let other = Other(OtherError(
650            #[cfg(feature = "std")]
651            alloc::sync::Arc::from(Box::from("")),
652        ));
653        assert_ne!(other, other);
654        assert_ne!(BadSignature, InvalidCrlNumber);
655    }
656
657    #[test]
658    #[cfg(feature = "std")]
659    fn other_error_equality() {
660        let other_error = OtherError(alloc::sync::Arc::from(Box::from("")));
661        assert_ne!(other_error, other_error);
662        let other: Error = other_error.into();
663        assert_ne!(other, other);
664    }
665
666    #[test]
667    fn smoke() {
668        use crate::enums::{AlertDescription, ContentType, HandshakeType};
669
670        let all = vec![
671            Error::InappropriateMessage {
672                expect_types: vec![ContentType::Alert],
673                got_type: ContentType::Handshake,
674            },
675            Error::InappropriateHandshakeMessage {
676                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
677                got_type: HandshakeType::ServerHello,
678            },
679            Error::InvalidMessage(InvalidMessage::InvalidCcs),
680            Error::NoCertificatesPresented,
681            Error::DecryptError,
682            super::PeerIncompatible::Tls12NotOffered.into(),
683            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
684            Error::AlertReceived(AlertDescription::ExportRestriction),
685            super::CertificateError::Expired.into(),
686            Error::General("undocumented error".to_string()),
687            Error::FailedToGetCurrentTime,
688            Error::FailedToGetRandomBytes,
689            Error::HandshakeNotComplete,
690            Error::PeerSentOversizedRecord,
691            Error::NoApplicationProtocol,
692            Error::BadMaxFragmentSize,
693            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
694            Error::Other(OtherError(
695                #[cfg(feature = "std")]
696                alloc::sync::Arc::from(Box::from("")),
697            )),
698        ];
699
700        for err in all {
701            println!("{:?}:", err);
702            println!("  fmt '{}'", err);
703        }
704    }
705
706    #[test]
707    fn rand_error_mapping() {
708        use super::rand;
709        let err: Error = rand::GetRandomFailed.into();
710        assert_eq!(err, Error::FailedToGetRandomBytes);
711    }
712
713    #[cfg(feature = "std")]
714    #[test]
715    fn time_error_mapping() {
716        use std::time::SystemTime;
717
718        let time_error = SystemTime::UNIX_EPOCH
719            .duration_since(SystemTime::now())
720            .unwrap_err();
721        let err: Error = time_error.into();
722        assert_eq!(err, Error::FailedToGetCurrentTime);
723    }
724}