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}