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}