1use crate::enums::{AlertDescription, ContentType, HandshakeType};
2use crate::msgs::handshake::KeyExchangeAlgorithm;
3use crate::rand;
4
5use alloc::format;
6use alloc::string::String;
7use alloc::sync::Arc;
8use alloc::vec::Vec;
9use core::fmt;
10use std::error::Error as StdError;
11use std::time::SystemTimeError;
12
13#[non_exhaustive]
15#[derive(Debug, PartialEq, Clone)]
16pub enum Error {
17 InappropriateMessage {
23 expect_types: Vec<ContentType>,
25 got_type: ContentType,
27 },
28
29 InappropriateHandshakeMessage {
33 expect_types: Vec<HandshakeType>,
35 got_type: HandshakeType,
37 },
38
39 InvalidMessage(InvalidMessage),
41
42 NoCertificatesPresented,
44
45 UnsupportedNameType,
47
48 DecryptError,
50
51 EncryptError,
54
55 PeerIncompatible(PeerIncompatible),
58
59 PeerMisbehaved(PeerMisbehaved),
62
63 AlertReceived(AlertDescription),
65
66 InvalidCertificate(CertificateError),
71
72 InvalidCertRevocationList(CertRevocationListError),
74
75 General(String),
77
78 FailedToGetCurrentTime,
80
81 FailedToGetRandomBytes,
83
84 FailedCertificateDecompression,
86
87 FailedCertificateCompression,
89
90 UnknownCertCompressionAlg,
92
93 HandshakeNotComplete,
96
97 PeerSentOversizedRecord,
99
100 NoApplicationProtocol,
102
103 BadMaxFragmentSize,
106
107 Other(OtherError),
115}
116
117#[non_exhaustive]
119#[derive(Debug, Clone, Copy, PartialEq)]
120
121pub enum InvalidMessage {
122 HandshakePayloadTooLarge,
124 InvalidCcs,
126 InvalidContentType,
128 InvalidCertificateStatusType,
130 InvalidCertRequest,
132 InvalidDhParams,
134 InvalidEmptyPayload,
136 InvalidKeyUpdate,
138 InvalidServerName,
140 MessageTooLarge,
142 MessageTooShort,
144 MissingData(&'static str),
146 MissingKeyExchange,
148 NoSignatureSchemes,
150 TrailingData(&'static str),
152 UnexpectedMessage(&'static str),
154 UnknownProtocolVersion,
156 UnsupportedCompression,
158 UnsupportedCurveType,
160 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
162}
163
164impl From<InvalidMessage> for Error {
165 #[inline]
166 fn from(e: InvalidMessage) -> Self {
167 Self::InvalidMessage(e)
168 }
169}
170
171#[non_exhaustive]
172#[allow(missing_docs)]
173#[derive(Debug, PartialEq, Clone)]
174pub enum PeerMisbehaved {
185 AttemptedDowngradeToTls12WhenTls13IsSupported,
186 BadCertChainExtensions,
187 DisallowedEncryptedExtension,
188 DuplicateClientHelloExtensions,
189 DuplicateEncryptedExtensions,
190 DuplicateHelloRetryRequestExtensions,
191 DuplicateNewSessionTicketExtensions,
192 DuplicateServerHelloExtensions,
193 DuplicateServerNameTypes,
194 DuplicateCertificateCompressionAlgorithms,
195 EarlyDataAttemptedInSecondClientHello,
196 EarlyDataExtensionWithoutResumption,
197 EarlyDataOfferedWithVariedCipherSuite,
198 HandshakeHashVariedAfterRetry,
199 IllegalHelloRetryRequestWithEmptyCookie,
200 IllegalHelloRetryRequestWithNoChanges,
201 IllegalHelloRetryRequestWithOfferedGroup,
202 IllegalHelloRetryRequestWithUnofferedCipherSuite,
203 IllegalHelloRetryRequestWithUnofferedNamedGroup,
204 IllegalHelloRetryRequestWithUnsupportedVersion,
205 IllegalHelloRetryRequestWithWrongSessionId,
206 IllegalMiddleboxChangeCipherSpec,
207 IllegalTlsInnerPlaintext,
208 IncorrectBinder,
209 InvalidMaxEarlyDataSize,
210 InvalidKeyShare,
211 KeyEpochWithPendingFragment,
212 KeyUpdateReceivedInQuicConnection,
213 MessageInterleavedWithHandshakeMessage,
214 MissingBinderInPskExtension,
215 MissingKeyShare,
216 MissingPskModesExtension,
217 MissingQuicTransportParameters,
218 OfferedDuplicateKeyShares,
219 OfferedEarlyDataWithOldProtocolVersion,
220 OfferedEmptyApplicationProtocol,
221 OfferedIncorrectCompressions,
222 PskExtensionMustBeLast,
223 PskExtensionWithMismatchedIdsAndBinders,
224 RefusedToFollowHelloRetryRequest,
225 RejectedEarlyDataInterleavedWithHandshakeMessage,
226 ResumptionAttemptedWithVariedEms,
227 ResumptionOfferedWithVariedCipherSuite,
228 ResumptionOfferedWithVariedEms,
229 ResumptionOfferedWithIncompatibleCipherSuite,
230 SelectedDifferentCipherSuiteAfterRetry,
231 SelectedInvalidPsk,
232 SelectedTls12UsingTls13VersionExtension,
233 SelectedUnofferedApplicationProtocol,
234 SelectedUnofferedCipherSuite,
235 SelectedUnofferedCompression,
236 SelectedUnofferedKxGroup,
237 SelectedUnofferedPsk,
238 SelectedUnusableCipherSuiteForVersion,
239 ServerHelloMustOfferUncompressedEcPoints,
240 ServerNameDifferedOnRetry,
241 ServerNameMustContainOneHostName,
242 SignedKxWithWrongAlgorithm,
243 SignedHandshakeWithUnadvertisedSigScheme,
244 TooMuchEarlyDataReceived,
245 UnexpectedCleartextExtension,
246 UnsolicitedCertExtension,
247 UnsolicitedEncryptedExtension,
248 UnsolicitedSctList,
249 UnsolicitedServerHelloExtension,
250 WrongGroupForKeyShare,
251}
252
253impl From<PeerMisbehaved> for Error {
254 #[inline]
255 fn from(e: PeerMisbehaved) -> Self {
256 Self::PeerMisbehaved(e)
257 }
258}
259
260#[non_exhaustive]
261#[allow(missing_docs)]
262#[derive(Debug, PartialEq, Clone)]
263pub enum PeerIncompatible {
269 EcPointsExtensionRequired,
270 KeyShareExtensionRequired,
271 NamedGroupsExtensionRequired,
272 NoCertificateRequestSignatureSchemesInCommon,
273 NoCipherSuitesInCommon,
274 NoEcPointFormatsInCommon,
275 NoKxGroupsInCommon,
276 NoSignatureSchemesInCommon,
277 NullCompressionRequired,
278 ServerDoesNotSupportTls12Or13,
279 ServerSentHelloRetryRequestWithUnknownExtension,
280 ServerTlsVersionIsDisabledByOurConfig,
281 SignatureAlgorithmsExtensionRequired,
282 SupportedVersionsExtensionRequired,
283 Tls12NotOffered,
284 Tls12NotOfferedOrEnabled,
285 Tls13RequiredForQuic,
286 UncompressedEcPointsRequired,
287}
288
289impl From<PeerIncompatible> for Error {
290 #[inline]
291 fn from(e: PeerIncompatible) -> Self {
292 Self::PeerIncompatible(e)
293 }
294}
295
296#[non_exhaustive]
297#[derive(Debug, Clone)]
298pub enum CertificateError {
306 BadEncoding,
308
309 Expired,
311
312 NotValidYet,
314
315 Revoked,
317
318 UnhandledCriticalExtension,
321
322 UnknownIssuer,
324
325 UnknownRevocationStatus,
327
328 BadSignature,
331
332 NotValidForName,
335
336 InvalidPurpose,
338
339 ApplicationVerificationFailure,
342
343 Other(OtherError),
354}
355
356impl PartialEq<Self> for CertificateError {
357 fn eq(&self, other: &Self) -> bool {
358 use CertificateError::*;
359 #[allow(clippy::match_like_matches_macro)]
360 match (self, other) {
361 (BadEncoding, BadEncoding) => true,
362 (Expired, Expired) => true,
363 (NotValidYet, NotValidYet) => true,
364 (Revoked, Revoked) => true,
365 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
366 (UnknownIssuer, UnknownIssuer) => true,
367 (BadSignature, BadSignature) => true,
368 (NotValidForName, NotValidForName) => true,
369 (InvalidPurpose, InvalidPurpose) => true,
370 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
371 _ => false,
372 }
373 }
374}
375
376impl From<CertificateError> for AlertDescription {
380 fn from(e: CertificateError) -> Self {
381 use CertificateError::*;
382 match e {
383 BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate,
384 Expired | NotValidYet => Self::CertificateExpired,
388 Revoked => Self::CertificateRevoked,
389 UnknownIssuer | UnknownRevocationStatus => Self::UnknownCA,
392 BadSignature => Self::DecryptError,
393 InvalidPurpose => Self::UnsupportedCertificate,
394 ApplicationVerificationFailure => Self::AccessDenied,
395 Other(_) => Self::CertificateUnknown,
400 }
401 }
402}
403
404impl From<CertificateError> for Error {
405 #[inline]
406 fn from(e: CertificateError) -> Self {
407 Self::InvalidCertificate(e)
408 }
409}
410
411#[non_exhaustive]
412#[derive(Debug, Clone)]
413pub enum CertRevocationListError {
415 BadSignature,
417
418 InvalidCrlNumber,
420
421 InvalidRevokedCertSerialNumber,
423
424 IssuerInvalidForCrl,
426
427 Other(OtherError),
431
432 ParseError,
434
435 UnsupportedCrlVersion,
437
438 UnsupportedCriticalExtension,
440
441 UnsupportedDeltaCrl,
443
444 UnsupportedIndirectCrl,
447
448 UnsupportedRevocationReason,
453}
454
455impl PartialEq<Self> for CertRevocationListError {
456 fn eq(&self, other: &Self) -> bool {
457 use CertRevocationListError::*;
458 #[allow(clippy::match_like_matches_macro)]
459 match (self, other) {
460 (BadSignature, BadSignature) => true,
461 (InvalidCrlNumber, InvalidCrlNumber) => true,
462 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
463 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
464 (ParseError, ParseError) => true,
465 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
466 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
467 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
468 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
469 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
470 _ => false,
471 }
472 }
473}
474
475impl From<CertRevocationListError> for Error {
476 #[inline]
477 fn from(e: CertRevocationListError) -> Self {
478 Self::InvalidCertRevocationList(e)
479 }
480}
481
482fn join<T: fmt::Debug>(items: &[T]) -> String {
483 items
484 .iter()
485 .map(|x| format!("{:?}", x))
486 .collect::<Vec<String>>()
487 .join(" or ")
488}
489
490impl fmt::Display for Error {
491 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
492 match *self {
493 Self::InappropriateMessage {
494 ref expect_types,
495 ref got_type,
496 } => write!(
497 f,
498 "received unexpected message: got {:?} when expecting {}",
499 got_type,
500 join::<ContentType>(expect_types)
501 ),
502 Self::InappropriateHandshakeMessage {
503 ref expect_types,
504 ref got_type,
505 } => write!(
506 f,
507 "received unexpected handshake message: got {:?} when expecting {}",
508 got_type,
509 join::<HandshakeType>(expect_types)
510 ),
511 Self::InvalidMessage(ref typ) => {
512 write!(f, "received corrupt message of type {:?}", typ)
513 }
514 Self::PeerIncompatible(ref why) => write!(f, "peer is incompatible: {:?}", why),
515 Self::PeerMisbehaved(ref why) => write!(f, "peer misbehaved: {:?}", why),
516 Self::AlertReceived(ref alert) => write!(f, "received fatal alert: {:?}", alert),
517 Self::InvalidCertificate(ref err) => {
518 write!(f, "invalid peer certificate: {:?}", err)
519 }
520 Self::InvalidCertRevocationList(ref err) => {
521 write!(f, "invalid certificate revocation list: {:?}", err)
522 }
523 Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
524 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
525 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
526 Self::EncryptError => write!(f, "cannot encrypt message"),
527 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
528 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
529 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
530 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
531 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
532 Self::FailedCertificateDecompression => {
533 write!(f, "failed to decompress certificate")
534 }
535 Self::FailedCertificateCompression => {
536 write!(f, "failed to compress certificate")
537 }
538 Self::UnknownCertCompressionAlg => {
539 write!(f, "unknown certificate compression algorithm")
540 }
541 Self::BadMaxFragmentSize => {
542 write!(f, "the supplied max_fragment_size was too small or large")
543 }
544 Self::General(ref err) => write!(f, "unexpected error: {}", err),
545 Self::Other(ref err) => write!(f, "other error: {}", err),
546 }
547 }
548}
549
550impl From<SystemTimeError> for Error {
551 #[inline]
552 fn from(_: SystemTimeError) -> Self {
553 Self::FailedToGetCurrentTime
554 }
555}
556
557impl StdError for Error {}
558
559impl From<rand::GetRandomFailed> for Error {
560 fn from(_: rand::GetRandomFailed) -> Self {
561 Self::FailedToGetRandomBytes
562 }
563}
564
565#[derive(Debug, Clone)]
572pub struct OtherError(pub Arc<dyn StdError + Send + Sync>);
573
574impl PartialEq<Self> for OtherError {
575 fn eq(&self, _other: &Self) -> bool {
576 false
577 }
578}
579
580impl From<OtherError> for Error {
581 fn from(value: OtherError) -> Self {
582 Self::Other(value)
583 }
584}
585
586impl fmt::Display for OtherError {
587 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
588 write!(f, "{}", self.0)
589 }
590}
591
592impl StdError for OtherError {
593 fn source(&self) -> Option<&(dyn StdError + 'static)> {
594 Some(self.0.as_ref())
595 }
596}
597
598#[cfg(test)]
599mod tests {
600 use super::{Error, InvalidMessage};
601 use crate::error::{CertRevocationListError, OtherError};
602
603 #[test]
604 fn certificate_error_equality() {
605 use super::CertificateError::*;
606 assert_eq!(BadEncoding, BadEncoding);
607 assert_eq!(Expired, Expired);
608 assert_eq!(NotValidYet, NotValidYet);
609 assert_eq!(Revoked, Revoked);
610 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
611 assert_eq!(UnknownIssuer, UnknownIssuer);
612 assert_eq!(BadSignature, BadSignature);
613 assert_eq!(NotValidForName, NotValidForName);
614 assert_eq!(InvalidPurpose, InvalidPurpose);
615 assert_eq!(
616 ApplicationVerificationFailure,
617 ApplicationVerificationFailure
618 );
619 let other = Other(OtherError(alloc::sync::Arc::from(Box::from(""))));
620 assert_ne!(other, other);
621 assert_ne!(BadEncoding, Expired);
622 }
623
624 #[test]
625 fn crl_error_equality() {
626 use super::CertRevocationListError::*;
627 assert_eq!(BadSignature, BadSignature);
628 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
629 assert_eq!(
630 InvalidRevokedCertSerialNumber,
631 InvalidRevokedCertSerialNumber
632 );
633 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
634 assert_eq!(ParseError, ParseError);
635 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
636 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
637 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
638 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
639 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
640 let other = Other(OtherError(alloc::sync::Arc::from(Box::from(""))));
641 assert_ne!(other, other);
642 assert_ne!(BadSignature, InvalidCrlNumber);
643 }
644
645 #[test]
646 fn other_error_equality() {
647 let other_error = OtherError(alloc::sync::Arc::from(Box::from("")));
648 assert_ne!(other_error, other_error);
649 let other: Error = other_error.into();
650 assert_ne!(other, other);
651 }
652
653 #[test]
654 fn smoke() {
655 use crate::enums::{AlertDescription, ContentType, HandshakeType};
656
657 let all = vec![
658 Error::InappropriateMessage {
659 expect_types: vec![ContentType::Alert],
660 got_type: ContentType::Handshake,
661 },
662 Error::InappropriateHandshakeMessage {
663 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
664 got_type: HandshakeType::ServerHello,
665 },
666 Error::InvalidMessage(InvalidMessage::InvalidCcs),
667 Error::NoCertificatesPresented,
668 Error::DecryptError,
669 super::PeerIncompatible::Tls12NotOffered.into(),
670 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
671 Error::AlertReceived(AlertDescription::ExportRestriction),
672 super::CertificateError::Expired.into(),
673 Error::General("undocumented error".to_string()),
674 Error::FailedToGetCurrentTime,
675 Error::FailedToGetRandomBytes,
676 Error::HandshakeNotComplete,
677 Error::PeerSentOversizedRecord,
678 Error::NoApplicationProtocol,
679 Error::BadMaxFragmentSize,
680 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
681 Error::Other(OtherError(alloc::sync::Arc::from(Box::from("")))),
682 ];
683
684 for err in all {
685 println!("{:?}:", err);
686 println!(" fmt '{}'", err);
687 }
688 }
689
690 #[test]
691 fn rand_error_mapping() {
692 use super::rand;
693 let err: Error = rand::GetRandomFailed.into();
694 assert_eq!(err, Error::FailedToGetRandomBytes);
695 }
696
697 #[test]
698 fn time_error_mapping() {
699 use std::time::SystemTime;
700
701 let time_error = SystemTime::UNIX_EPOCH
702 .duration_since(SystemTime::now())
703 .unwrap_err();
704 let err: Error = time_error.into();
705 assert_eq!(err, Error::FailedToGetCurrentTime);
706 }
707}