1use crate::enums::{AlertDescription, ContentType, HandshakeType};
2use crate::msgs::handshake::KeyExchangeAlgorithm;
3use crate::rand;
4
5use std::error::Error as StdError;
6use std::fmt;
7use std::sync::Arc;
8use std::time::SystemTimeError;
9
10#[non_exhaustive]
12#[derive(Debug, PartialEq, Clone)]
13pub enum Error {
14    InappropriateMessage {
20        expect_types: Vec<ContentType>,
22        got_type: ContentType,
24    },
25
26    InappropriateHandshakeMessage {
30        expect_types: Vec<HandshakeType>,
32        got_type: HandshakeType,
34    },
35
36    InvalidMessage(InvalidMessage),
38
39    NoCertificatesPresented,
41
42    UnsupportedNameType,
44
45    DecryptError,
47
48    EncryptError,
51
52    PeerIncompatible(PeerIncompatible),
55
56    PeerMisbehaved(PeerMisbehaved),
59
60    AlertReceived(AlertDescription),
62
63    InvalidCertificate(CertificateError),
68
69    InvalidSct(sct::Error),
71
72    InvalidCertRevocationList(CertRevocationListError),
74
75    General(String),
77
78    FailedToGetCurrentTime,
80
81    FailedToGetRandomBytes,
83
84    HandshakeNotComplete,
87
88    PeerSentOversizedRecord,
90
91    NoApplicationProtocol,
93
94    BadMaxFragmentSize,
97}
98
99#[non_exhaustive]
101#[derive(Debug, Clone, Copy, PartialEq)]
102
103pub enum InvalidMessage {
104    HandshakePayloadTooLarge,
106    InvalidCcs,
108    InvalidContentType,
110    InvalidCertificateStatusType,
112    InvalidCertRequest,
114    InvalidDhParams,
116    InvalidEmptyPayload,
118    InvalidKeyUpdate,
120    InvalidServerName,
122    MessageTooLarge,
124    MessageTooShort,
126    MissingData(&'static str),
128    MissingKeyExchange,
130    NoSignatureSchemes,
132    TrailingData(&'static str),
134    UnexpectedMessage(&'static str),
136    UnknownProtocolVersion,
138    UnsupportedCompression,
140    UnsupportedCurveType,
142    UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
144}
145
146impl From<InvalidMessage> for Error {
147    #[inline]
148    fn from(e: InvalidMessage) -> Self {
149        Self::InvalidMessage(e)
150    }
151}
152
153#[non_exhaustive]
154#[allow(missing_docs)]
155#[derive(Debug, PartialEq, Clone)]
156pub enum PeerMisbehaved {
167    AttemptedDowngradeToTls12WhenTls13IsSupported,
168    BadCertChainExtensions,
169    DisallowedEncryptedExtension,
170    DuplicateClientHelloExtensions,
171    DuplicateEncryptedExtensions,
172    DuplicateHelloRetryRequestExtensions,
173    DuplicateNewSessionTicketExtensions,
174    DuplicateServerHelloExtensions,
175    DuplicateServerNameTypes,
176    EarlyDataAttemptedInSecondClientHello,
177    EarlyDataExtensionWithoutResumption,
178    EarlyDataOfferedWithVariedCipherSuite,
179    HandshakeHashVariedAfterRetry,
180    IllegalHelloRetryRequestWithEmptyCookie,
181    IllegalHelloRetryRequestWithNoChanges,
182    IllegalHelloRetryRequestWithOfferedGroup,
183    IllegalHelloRetryRequestWithUnofferedCipherSuite,
184    IllegalHelloRetryRequestWithUnofferedNamedGroup,
185    IllegalHelloRetryRequestWithUnsupportedVersion,
186    IllegalHelloRetryRequestWithWrongSessionId,
187    IllegalMiddleboxChangeCipherSpec,
188    IllegalTlsInnerPlaintext,
189    IncorrectBinder,
190    InvalidMaxEarlyDataSize,
191    InvalidKeyShare,
192    InvalidSctList,
193    KeyEpochWithPendingFragment,
194    KeyUpdateReceivedInQuicConnection,
195    MessageInterleavedWithHandshakeMessage,
196    MissingBinderInPskExtension,
197    MissingKeyShare,
198    MissingPskModesExtension,
199    MissingQuicTransportParameters,
200    OfferedDuplicateKeyShares,
201    OfferedEarlyDataWithOldProtocolVersion,
202    OfferedEmptyApplicationProtocol,
203    OfferedIncorrectCompressions,
204    PskExtensionMustBeLast,
205    PskExtensionWithMismatchedIdsAndBinders,
206    RefusedToFollowHelloRetryRequest,
207    RejectedEarlyDataInterleavedWithHandshakeMessage,
208    ResumptionAttemptedWithVariedEms,
209    ResumptionOfferedWithVariedCipherSuite,
210    ResumptionOfferedWithVariedEms,
211    ResumptionOfferedWithIncompatibleCipherSuite,
212    SelectedDifferentCipherSuiteAfterRetry,
213    SelectedInvalidPsk,
214    SelectedTls12UsingTls13VersionExtension,
215    SelectedUnofferedApplicationProtocol,
216    SelectedUnofferedCipherSuite,
217    SelectedUnofferedCompression,
218    SelectedUnofferedKxGroup,
219    SelectedUnofferedPsk,
220    SelectedUnusableCipherSuiteForVersion,
221    ServerHelloMustOfferUncompressedEcPoints,
222    ServerNameDifferedOnRetry,
223    ServerNameMustContainOneHostName,
224    SignedKxWithWrongAlgorithm,
225    SignedHandshakeWithUnadvertisedSigScheme,
226    TooMuchEarlyDataReceived,
227    UnexpectedCleartextExtension,
228    UnsolicitedCertExtension,
229    UnsolicitedEncryptedExtension,
230    UnsolicitedSctList,
231    UnsolicitedServerHelloExtension,
232    WrongGroupForKeyShare,
233}
234
235impl From<PeerMisbehaved> for Error {
236    #[inline]
237    fn from(e: PeerMisbehaved) -> Self {
238        Self::PeerMisbehaved(e)
239    }
240}
241
242#[non_exhaustive]
243#[allow(missing_docs)]
244#[derive(Debug, PartialEq, Clone)]
245pub enum PeerIncompatible {
251    EcPointsExtensionRequired,
252    KeyShareExtensionRequired,
253    NamedGroupsExtensionRequired,
254    NoCertificateRequestSignatureSchemesInCommon,
255    NoCipherSuitesInCommon,
256    NoEcPointFormatsInCommon,
257    NoKxGroupsInCommon,
258    NoSignatureSchemesInCommon,
259    NullCompressionRequired,
260    ServerDoesNotSupportTls12Or13,
261    ServerSentHelloRetryRequestWithUnknownExtension,
262    ServerTlsVersionIsDisabledByOurConfig,
263    SignatureAlgorithmsExtensionRequired,
264    SupportedVersionsExtensionRequired,
265    Tls12NotOffered,
266    Tls12NotOfferedOrEnabled,
267    Tls13RequiredForQuic,
268    UncompressedEcPointsRequired,
269}
270
271impl From<PeerIncompatible> for Error {
272    #[inline]
273    fn from(e: PeerIncompatible) -> Self {
274        Self::PeerIncompatible(e)
275    }
276}
277
278#[non_exhaustive]
279#[derive(Debug, Clone)]
280pub enum CertificateError {
288    BadEncoding,
290
291    Expired,
293
294    NotValidYet,
296
297    Revoked,
299
300    UnhandledCriticalExtension,
303
304    UnknownIssuer,
306
307    BadSignature,
310
311    NotValidForName,
314
315    InvalidPurpose,
317
318    ApplicationVerificationFailure,
321
322    Other(Arc<dyn StdError + Send + Sync>),
333}
334
335impl PartialEq<Self> for CertificateError {
336    fn eq(&self, other: &Self) -> bool {
337        use CertificateError::*;
338        #[allow(clippy::match_like_matches_macro)]
339        match (self, other) {
340            (BadEncoding, BadEncoding) => true,
341            (Expired, Expired) => true,
342            (NotValidYet, NotValidYet) => true,
343            (Revoked, Revoked) => true,
344            (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
345            (UnknownIssuer, UnknownIssuer) => true,
346            (BadSignature, BadSignature) => true,
347            (NotValidForName, NotValidForName) => true,
348            (InvalidPurpose, InvalidPurpose) => true,
349            (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
350            _ => false,
351        }
352    }
353}
354
355impl From<CertificateError> for AlertDescription {
359    fn from(e: CertificateError) -> Self {
360        use CertificateError::*;
361        match e {
362            BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate,
363            Expired | NotValidYet => Self::CertificateExpired,
367            Revoked => Self::CertificateRevoked,
368            UnknownIssuer => Self::UnknownCA,
369            BadSignature => Self::DecryptError,
370            InvalidPurpose => Self::UnsupportedCertificate,
371            ApplicationVerificationFailure => Self::AccessDenied,
372            Other(_) => Self::CertificateUnknown,
377        }
378    }
379}
380
381impl From<CertificateError> for Error {
382    #[inline]
383    fn from(e: CertificateError) -> Self {
384        Self::InvalidCertificate(e)
385    }
386}
387
388#[non_exhaustive]
389#[derive(Debug, Clone)]
390pub enum CertRevocationListError {
392    BadSignature,
394
395    InvalidCrlNumber,
397
398    InvalidRevokedCertSerialNumber,
400
401    IssuerInvalidForCrl,
403
404    Other(Arc<dyn StdError + Send + Sync>),
408
409    ParseError,
411
412    UnsupportedCrlVersion,
414
415    UnsupportedCriticalExtension,
417
418    UnsupportedDeltaCrl,
420
421    UnsupportedIndirectCrl,
424
425    UnsupportedRevocationReason,
430}
431
432impl PartialEq<Self> for CertRevocationListError {
433    fn eq(&self, other: &Self) -> bool {
434        use CertRevocationListError::*;
435        #[allow(clippy::match_like_matches_macro)]
436        match (self, other) {
437            (BadSignature, BadSignature) => true,
438            (InvalidCrlNumber, InvalidCrlNumber) => true,
439            (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
440            (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
441            (ParseError, ParseError) => true,
442            (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
443            (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
444            (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
445            (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
446            (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
447            _ => false,
448        }
449    }
450}
451
452impl From<webpki::Error> for CertRevocationListError {
453    fn from(e: webpki::Error) -> Self {
454        use webpki::Error::*;
455        match e {
456            InvalidCrlSignatureForPublicKey
457            | UnsupportedCrlSignatureAlgorithm
458            | UnsupportedCrlSignatureAlgorithmForPublicKey => Self::BadSignature,
459            InvalidCrlNumber => Self::InvalidCrlNumber,
460            InvalidSerialNumber => Self::InvalidRevokedCertSerialNumber,
461            IssuerNotCrlSigner => Self::IssuerInvalidForCrl,
462            MalformedExtensions | BadDer | BadDerTime => Self::ParseError,
463            UnsupportedCriticalExtension => Self::UnsupportedCriticalExtension,
464            UnsupportedCrlVersion => Self::UnsupportedCrlVersion,
465            UnsupportedDeltaCrl => Self::UnsupportedDeltaCrl,
466            UnsupportedIndirectCrl => Self::UnsupportedIndirectCrl,
467            UnsupportedRevocationReason => Self::UnsupportedRevocationReason,
468
469            _ => Self::Other(Arc::new(e)),
470        }
471    }
472}
473
474impl From<CertRevocationListError> for Error {
475    #[inline]
476    fn from(e: CertRevocationListError) -> Self {
477        Self::InvalidCertRevocationList(e)
478    }
479}
480
481fn join<T: fmt::Debug>(items: &[T]) -> String {
482    items
483        .iter()
484        .map(|x| format!("{:?}", x))
485        .collect::<Vec<String>>()
486        .join(" or ")
487}
488
489impl fmt::Display for Error {
490    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
491        match *self {
492            Self::InappropriateMessage {
493                ref expect_types,
494                ref got_type,
495            } => write!(
496                f,
497                "received unexpected message: got {:?} when expecting {}",
498                got_type,
499                join::<ContentType>(expect_types)
500            ),
501            Self::InappropriateHandshakeMessage {
502                ref expect_types,
503                ref got_type,
504            } => write!(
505                f,
506                "received unexpected handshake message: got {:?} when expecting {}",
507                got_type,
508                join::<HandshakeType>(expect_types)
509            ),
510            Self::InvalidMessage(ref typ) => {
511                write!(f, "received corrupt message of type {:?}", typ)
512            }
513            Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why),
514            Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why),
515            Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
516            Self::InvalidCertificate(ref err) => {
517                write!(f, "invalid peer certificate: {:?}", err)
518            }
519            Self::InvalidCertRevocationList(ref err) => {
520                write!(f, "invalid certificate revocation list: {:?}", err)
521            }
522            Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
523            Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
524            Self::DecryptError => write!(f, "cannot decrypt peer's message"),
525            Self::EncryptError => write!(f, "cannot encrypt message"),
526            Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
527            Self::HandshakeNotComplete => write!(f, "handshake not complete"),
528            Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
529            Self::InvalidSct(ref err) => write!(f, "invalid certificate timestamp: {:?}", err),
530            Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
531            Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
532            Self::BadMaxFragmentSize => {
533                write!(f, "the supplied max_fragment_size was too small or large")
534            }
535            Self::General(ref err) => write!(f, "unexpected error: {}", err),
536        }
537    }
538}
539
540impl From<SystemTimeError> for Error {
541    #[inline]
542    fn from(_: SystemTimeError) -> Self {
543        Self::FailedToGetCurrentTime
544    }
545}
546
547impl StdError for Error {}
548
549impl From<rand::GetRandomFailed> for Error {
550    fn from(_: rand::GetRandomFailed) -> Self {
551        Self::FailedToGetRandomBytes
552    }
553}
554
555#[cfg(test)]
556mod tests {
557    use super::{Error, InvalidMessage};
558    use crate::error::CertRevocationListError;
559
560    #[test]
561    fn certificate_error_equality() {
562        use super::CertificateError::*;
563        assert_eq!(BadEncoding, BadEncoding);
564        assert_eq!(Expired, Expired);
565        assert_eq!(NotValidYet, NotValidYet);
566        assert_eq!(Revoked, Revoked);
567        assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
568        assert_eq!(UnknownIssuer, UnknownIssuer);
569        assert_eq!(BadSignature, BadSignature);
570        assert_eq!(NotValidForName, NotValidForName);
571        assert_eq!(InvalidPurpose, InvalidPurpose);
572        assert_eq!(
573            ApplicationVerificationFailure,
574            ApplicationVerificationFailure
575        );
576        let other = Other(std::sync::Arc::from(Box::from("")));
577        assert_ne!(other, other);
578        assert_ne!(BadEncoding, Expired);
579    }
580
581    #[test]
582    fn crl_error_equality() {
583        use super::CertRevocationListError::*;
584        assert_eq!(BadSignature, BadSignature);
585        assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
586        assert_eq!(
587            InvalidRevokedCertSerialNumber,
588            InvalidRevokedCertSerialNumber
589        );
590        assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
591        assert_eq!(ParseError, ParseError);
592        assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
593        assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
594        assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
595        assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
596        assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
597        let other = Other(std::sync::Arc::from(Box::from("")));
598        assert_ne!(other, other);
599        assert_ne!(BadSignature, InvalidCrlNumber);
600    }
601
602    #[test]
603    fn crl_error_from_webpki() {
604        use super::CertRevocationListError::*;
605        let testcases = &[
606            (webpki::Error::InvalidCrlSignatureForPublicKey, BadSignature),
607            (
608                webpki::Error::UnsupportedCrlSignatureAlgorithm,
609                BadSignature,
610            ),
611            (
612                webpki::Error::UnsupportedCrlSignatureAlgorithmForPublicKey,
613                BadSignature,
614            ),
615            (webpki::Error::InvalidCrlNumber, InvalidCrlNumber),
616            (
617                webpki::Error::InvalidSerialNumber,
618                InvalidRevokedCertSerialNumber,
619            ),
620            (webpki::Error::IssuerNotCrlSigner, IssuerInvalidForCrl),
621            (webpki::Error::MalformedExtensions, ParseError),
622            (webpki::Error::BadDer, ParseError),
623            (webpki::Error::BadDerTime, ParseError),
624            (
625                webpki::Error::UnsupportedCriticalExtension,
626                UnsupportedCriticalExtension,
627            ),
628            (webpki::Error::UnsupportedCrlVersion, UnsupportedCrlVersion),
629            (webpki::Error::UnsupportedDeltaCrl, UnsupportedDeltaCrl),
630            (
631                webpki::Error::UnsupportedIndirectCrl,
632                UnsupportedIndirectCrl,
633            ),
634            (
635                webpki::Error::UnsupportedRevocationReason,
636                UnsupportedRevocationReason,
637            ),
638        ];
639        for t in testcases {
640            assert_eq!(
641                <webpki::Error as Into<CertRevocationListError>>::into(t.0),
642                t.1
643            );
644        }
645
646        assert!(matches!(
647            <webpki::Error as Into<CertRevocationListError>>::into(
648                webpki::Error::NameConstraintViolation
649            ),
650            Other(_)
651        ));
652    }
653
654    #[test]
655    fn smoke() {
656        use crate::enums::{AlertDescription, ContentType, HandshakeType};
657        use sct;
658
659        let all = vec![
660            Error::InappropriateMessage {
661                expect_types: vec![ContentType::Alert],
662                got_type: ContentType::Handshake,
663            },
664            Error::InappropriateHandshakeMessage {
665                expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
666                got_type: HandshakeType::ServerHello,
667            },
668            Error::InvalidMessage(InvalidMessage::InvalidCcs),
669            Error::NoCertificatesPresented,
670            Error::DecryptError,
671            super::PeerIncompatible::Tls12NotOffered.into(),
672            super::PeerMisbehaved::UnsolicitedCertExtension.into(),
673            Error::AlertReceived(AlertDescription::ExportRestriction),
674            super::CertificateError::Expired.into(),
675            Error::InvalidSct(sct::Error::MalformedSct),
676            Error::General("undocumented error".to_string()),
677            Error::FailedToGetCurrentTime,
678            Error::FailedToGetRandomBytes,
679            Error::HandshakeNotComplete,
680            Error::PeerSentOversizedRecord,
681            Error::NoApplicationProtocol,
682            Error::BadMaxFragmentSize,
683            Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
684        ];
685
686        for err in all {
687            println!("{:?}:", err);
688            println!("  fmt '{}'", err);
689        }
690    }
691
692    #[test]
693    fn rand_error_mapping() {
694        use super::rand;
695        let err: Error = rand::GetRandomFailed.into();
696        assert_eq!(err, Error::FailedToGetRandomBytes);
697    }
698
699    #[test]
700    fn time_error_mapping() {
701        use std::time::SystemTime;
702
703        let time_error = SystemTime::UNIX_EPOCH
704            .duration_since(SystemTime::now())
705            .unwrap_err();
706        let err: Error = time_error.into();
707        assert_eq!(err, Error::FailedToGetCurrentTime);
708    }
709}