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 HandshakeNotComplete,
87
88 PeerSentOversizedRecord,
90
91 NoApplicationProtocol,
93
94 BadMaxFragmentSize,
97
98 Other(OtherError),
106}
107
108#[non_exhaustive]
110#[derive(Debug, Clone, Copy, PartialEq)]
111
112pub enum InvalidMessage {
113 HandshakePayloadTooLarge,
115 InvalidCcs,
117 InvalidContentType,
119 InvalidCertificateStatusType,
121 InvalidCertRequest,
123 InvalidDhParams,
125 InvalidEmptyPayload,
127 InvalidKeyUpdate,
129 InvalidServerName,
131 MessageTooLarge,
133 MessageTooShort,
135 MissingData(&'static str),
137 MissingKeyExchange,
139 NoSignatureSchemes,
141 TrailingData(&'static str),
143 UnexpectedMessage(&'static str),
145 UnknownProtocolVersion,
147 UnsupportedCompression,
149 UnsupportedCurveType,
151 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
153}
154
155impl From<InvalidMessage> for Error {
156 #[inline]
157 fn from(e: InvalidMessage) -> Self {
158 Self::InvalidMessage(e)
159 }
160}
161
162#[non_exhaustive]
163#[allow(missing_docs)]
164#[derive(Debug, PartialEq, Clone)]
165pub enum PeerMisbehaved {
176 AttemptedDowngradeToTls12WhenTls13IsSupported,
177 BadCertChainExtensions,
178 DisallowedEncryptedExtension,
179 DuplicateClientHelloExtensions,
180 DuplicateEncryptedExtensions,
181 DuplicateHelloRetryRequestExtensions,
182 DuplicateNewSessionTicketExtensions,
183 DuplicateServerHelloExtensions,
184 DuplicateServerNameTypes,
185 EarlyDataAttemptedInSecondClientHello,
186 EarlyDataExtensionWithoutResumption,
187 EarlyDataOfferedWithVariedCipherSuite,
188 HandshakeHashVariedAfterRetry,
189 IllegalHelloRetryRequestWithEmptyCookie,
190 IllegalHelloRetryRequestWithNoChanges,
191 IllegalHelloRetryRequestWithOfferedGroup,
192 IllegalHelloRetryRequestWithUnofferedCipherSuite,
193 IllegalHelloRetryRequestWithUnofferedNamedGroup,
194 IllegalHelloRetryRequestWithUnsupportedVersion,
195 IllegalHelloRetryRequestWithWrongSessionId,
196 IllegalMiddleboxChangeCipherSpec,
197 IllegalTlsInnerPlaintext,
198 IncorrectBinder,
199 InvalidMaxEarlyDataSize,
200 InvalidKeyShare,
201 KeyEpochWithPendingFragment,
202 KeyUpdateReceivedInQuicConnection,
203 MessageInterleavedWithHandshakeMessage,
204 MissingBinderInPskExtension,
205 MissingKeyShare,
206 MissingPskModesExtension,
207 MissingQuicTransportParameters,
208 OfferedDuplicateKeyShares,
209 OfferedEarlyDataWithOldProtocolVersion,
210 OfferedEmptyApplicationProtocol,
211 OfferedIncorrectCompressions,
212 PskExtensionMustBeLast,
213 PskExtensionWithMismatchedIdsAndBinders,
214 RefusedToFollowHelloRetryRequest,
215 RejectedEarlyDataInterleavedWithHandshakeMessage,
216 ResumptionAttemptedWithVariedEms,
217 ResumptionOfferedWithVariedCipherSuite,
218 ResumptionOfferedWithVariedEms,
219 ResumptionOfferedWithIncompatibleCipherSuite,
220 SelectedDifferentCipherSuiteAfterRetry,
221 SelectedInvalidPsk,
222 SelectedTls12UsingTls13VersionExtension,
223 SelectedUnofferedApplicationProtocol,
224 SelectedUnofferedCipherSuite,
225 SelectedUnofferedCompression,
226 SelectedUnofferedKxGroup,
227 SelectedUnofferedPsk,
228 SelectedUnusableCipherSuiteForVersion,
229 ServerHelloMustOfferUncompressedEcPoints,
230 ServerNameDifferedOnRetry,
231 ServerNameMustContainOneHostName,
232 SignedKxWithWrongAlgorithm,
233 SignedHandshakeWithUnadvertisedSigScheme,
234 TooMuchEarlyDataReceived,
235 UnexpectedCleartextExtension,
236 UnsolicitedCertExtension,
237 UnsolicitedEncryptedExtension,
238 UnsolicitedSctList,
239 UnsolicitedServerHelloExtension,
240 WrongGroupForKeyShare,
241}
242
243impl From<PeerMisbehaved> for Error {
244 #[inline]
245 fn from(e: PeerMisbehaved) -> Self {
246 Self::PeerMisbehaved(e)
247 }
248}
249
250#[non_exhaustive]
251#[allow(missing_docs)]
252#[derive(Debug, PartialEq, Clone)]
253pub enum PeerIncompatible {
259 EcPointsExtensionRequired,
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
531impl From<SystemTimeError> for Error {
532 #[inline]
533 fn from(_: SystemTimeError) -> Self {
534 Self::FailedToGetCurrentTime
535 }
536}
537
538impl StdError for Error {}
539
540impl From<rand::GetRandomFailed> for Error {
541 fn from(_: rand::GetRandomFailed) -> Self {
542 Self::FailedToGetRandomBytes
543 }
544}
545
546#[derive(Debug, Clone)]
553pub struct OtherError(pub Arc<dyn StdError + Send + Sync>);
554
555impl PartialEq<Self> for OtherError {
556 fn eq(&self, _other: &Self) -> bool {
557 false
558 }
559}
560
561impl From<OtherError> for Error {
562 fn from(value: OtherError) -> Self {
563 Self::Other(value)
564 }
565}
566
567impl fmt::Display for OtherError {
568 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
569 write!(f, "{}", self.0)
570 }
571}
572
573impl StdError for OtherError {
574 fn source(&self) -> Option<&(dyn StdError + 'static)> {
575 Some(self.0.as_ref())
576 }
577}
578
579#[cfg(test)]
580mod tests {
581 use super::{Error, InvalidMessage};
582 use crate::error::{CertRevocationListError, OtherError};
583 use std::prelude::v1::*;
584 use std::{println, vec};
585
586 #[test]
587 fn certificate_error_equality() {
588 use super::CertificateError::*;
589 assert_eq!(BadEncoding, BadEncoding);
590 assert_eq!(Expired, Expired);
591 assert_eq!(NotValidYet, NotValidYet);
592 assert_eq!(Revoked, Revoked);
593 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
594 assert_eq!(UnknownIssuer, UnknownIssuer);
595 assert_eq!(BadSignature, BadSignature);
596 assert_eq!(NotValidForName, NotValidForName);
597 assert_eq!(InvalidPurpose, InvalidPurpose);
598 assert_eq!(
599 ApplicationVerificationFailure,
600 ApplicationVerificationFailure
601 );
602 let other = Other(OtherError(alloc::sync::Arc::from(Box::from(""))));
603 assert_ne!(other, other);
604 assert_ne!(BadEncoding, Expired);
605 }
606
607 #[test]
608 fn crl_error_equality() {
609 use super::CertRevocationListError::*;
610 assert_eq!(BadSignature, BadSignature);
611 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
612 assert_eq!(
613 InvalidRevokedCertSerialNumber,
614 InvalidRevokedCertSerialNumber
615 );
616 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
617 assert_eq!(ParseError, ParseError);
618 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
619 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
620 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
621 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
622 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
623 let other = Other(OtherError(alloc::sync::Arc::from(Box::from(""))));
624 assert_ne!(other, other);
625 assert_ne!(BadSignature, InvalidCrlNumber);
626 }
627
628 #[test]
629 fn other_error_equality() {
630 let other_error = OtherError(alloc::sync::Arc::from(Box::from("")));
631 assert_ne!(other_error, other_error);
632 let other: Error = other_error.into();
633 assert_ne!(other, other);
634 }
635
636 #[test]
637 fn smoke() {
638 use crate::enums::{AlertDescription, ContentType, HandshakeType};
639
640 let all = vec![
641 Error::InappropriateMessage {
642 expect_types: vec![ContentType::Alert],
643 got_type: ContentType::Handshake,
644 },
645 Error::InappropriateHandshakeMessage {
646 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
647 got_type: HandshakeType::ServerHello,
648 },
649 Error::InvalidMessage(InvalidMessage::InvalidCcs),
650 Error::NoCertificatesPresented,
651 Error::DecryptError,
652 super::PeerIncompatible::Tls12NotOffered.into(),
653 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
654 Error::AlertReceived(AlertDescription::ExportRestriction),
655 super::CertificateError::Expired.into(),
656 Error::General("undocumented error".to_string()),
657 Error::FailedToGetCurrentTime,
658 Error::FailedToGetRandomBytes,
659 Error::HandshakeNotComplete,
660 Error::PeerSentOversizedRecord,
661 Error::NoApplicationProtocol,
662 Error::BadMaxFragmentSize,
663 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
664 Error::Other(OtherError(alloc::sync::Arc::from(Box::from("")))),
665 ];
666
667 for err in all {
668 println!("{:?}:", err);
669 println!(" fmt '{}'", err);
670 }
671 }
672
673 #[test]
674 fn rand_error_mapping() {
675 use super::rand;
676 let err: Error = rand::GetRandomFailed.into();
677 assert_eq!(err, Error::FailedToGetRandomBytes);
678 }
679
680 #[test]
681 fn time_error_mapping() {
682 use std::time::SystemTime;
683
684 let time_error = SystemTime::UNIX_EPOCH
685 .duration_since(SystemTime::now())
686 .unwrap_err();
687 let err: Error = time_error.into();
688 assert_eq!(err, Error::FailedToGetCurrentTime);
689 }
690}