1use alloc::format;
2use alloc::string::String;
3use alloc::vec::Vec;
4use core::fmt;
5use pki_types::{ServerName, UnixTime};
6#[cfg(feature = "std")]
7use std::time::SystemTimeError;
8
9use crate::enums::{AlertDescription, ContentType, HandshakeType};
10use crate::msgs::handshake::{EchConfigPayload, KeyExchangeAlgorithm};
11use crate::rand;
12
13/// rustls reports protocol errors using this type.
14#[non_exhaustive]
15#[derive(Debug, PartialEq, Clone)]
16pub enum Error {
17 /// We received a TLS message that isn't valid right now.
18 /// `expect_types` lists the message types we can expect right now.
19 /// `got_type` is the type we found. This error is typically
20 /// caused by a buggy TLS stack (the peer or this one), a broken
21 /// network, or an attack.
22 InappropriateMessage {
23 /// Which types we expected
24 expect_types: Vec<ContentType>,
25 /// What type we received
26 got_type: ContentType,
27 },
28
29 /// We received a TLS handshake message that isn't valid right now.
30 /// `expect_types` lists the handshake message types we can expect
31 /// right now. `got_type` is the type we found.
32 InappropriateHandshakeMessage {
33 /// Which handshake type we expected
34 expect_types: Vec<HandshakeType>,
35 /// What handshake type we received
36 got_type: HandshakeType,
37 },
38
39 /// An error occurred while handling Encrypted Client Hello (ECH).
40 InvalidEncryptedClientHello(EncryptedClientHelloError),
41
42 /// The peer sent us a TLS message with invalid contents.
43 InvalidMessage(InvalidMessage),
44
45 /// The peer didn't give us any certificates.
46 NoCertificatesPresented,
47
48 /// The certificate verifier doesn't support the given type of name.
49 UnsupportedNameType,
50
51 /// We couldn't decrypt a message. This is invariably fatal.
52 DecryptError,
53
54 /// We couldn't encrypt a message because it was larger than the allowed message size.
55 /// This should never happen if the application is using valid record sizes.
56 EncryptError,
57
58 /// The peer doesn't support a protocol version/feature we require.
59 /// The parameter gives a hint as to what version/feature it is.
60 PeerIncompatible(PeerIncompatible),
61
62 /// The peer deviated from the standard TLS protocol.
63 /// The parameter gives a hint where.
64 PeerMisbehaved(PeerMisbehaved),
65
66 /// We received a fatal alert. This means the peer is unhappy.
67 AlertReceived(AlertDescription),
68
69 /// We saw an invalid certificate.
70 ///
71 /// The contained error is from the certificate validation trait
72 /// implementation.
73 InvalidCertificate(CertificateError),
74
75 /// A provided certificate revocation list (CRL) was invalid.
76 InvalidCertRevocationList(CertRevocationListError),
77
78 /// A catch-all error for unlikely errors.
79 General(String),
80
81 /// We failed to figure out what time it currently is.
82 FailedToGetCurrentTime,
83
84 /// We failed to acquire random bytes from the system.
85 FailedToGetRandomBytes,
86
87 /// This function doesn't work until the TLS handshake
88 /// is complete.
89 HandshakeNotComplete,
90
91 /// The peer sent an oversized record/fragment.
92 PeerSentOversizedRecord,
93
94 /// An incoming connection did not support any known application protocol.
95 NoApplicationProtocol,
96
97 /// The `max_fragment_size` value supplied in configuration was too small,
98 /// or too large.
99 BadMaxFragmentSize,
100
101 /// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
102 ///
103 /// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
104 InconsistentKeys(InconsistentKeys),
105
106 /// Any other error.
107 ///
108 /// This variant should only be used when the error is not better described by a more
109 /// specific variant. For example, if a custom crypto provider returns a
110 /// provider specific error.
111 ///
112 /// Enums holding this variant will never compare equal to each other.
113 Other(OtherError),
114}
115
116/// Specific failure cases from [`keys_match`] or a [`crate::crypto::signer::SigningKey`] that cannot produce a corresponding public key.
117///
118/// [`keys_match`]: crate::crypto::signer::CertifiedKey::keys_match
119#[non_exhaustive]
120#[derive(Clone, Copy, Debug, Eq, PartialEq)]
121pub enum InconsistentKeys {
122 /// The public key returned by the [`SigningKey`] does not match the public key information in the certificate.
123 ///
124 /// [`SigningKey`]: crate::crypto::signer::SigningKey
125 KeyMismatch,
126
127 /// The [`SigningKey`] cannot produce its corresponding public key.
128 ///
129 /// [`SigningKey`]: crate::crypto::signer::SigningKey
130 Unknown,
131}
132
133impl From<InconsistentKeys> for Error {
134 #[inline]
135 fn from(e: InconsistentKeys) -> Self {
136 Self::InconsistentKeys(e)
137 }
138}
139
140/// A corrupt TLS message payload that resulted in an error.
141#[non_exhaustive]
142#[derive(Debug, Clone, Copy, PartialEq)]
143
144pub enum InvalidMessage {
145 /// A certificate payload exceeded rustls's 64KB limit
146 CertificatePayloadTooLarge,
147 /// An advertised message was larger then expected.
148 HandshakePayloadTooLarge,
149 /// The peer sent us a syntactically incorrect ChangeCipherSpec payload.
150 InvalidCcs,
151 /// An unknown content type was encountered during message decoding.
152 InvalidContentType,
153 /// A peer sent an invalid certificate status type
154 InvalidCertificateStatusType,
155 /// Context was incorrectly attached to a certificate request during a handshake.
156 InvalidCertRequest,
157 /// A peer's DH params could not be decoded
158 InvalidDhParams,
159 /// A message was zero-length when its record kind forbids it.
160 InvalidEmptyPayload,
161 /// A peer sent an unexpected key update request.
162 InvalidKeyUpdate,
163 /// A peer's server name could not be decoded
164 InvalidServerName,
165 /// A TLS message payload was larger then allowed by the specification.
166 MessageTooLarge,
167 /// Message is shorter than the expected length
168 MessageTooShort,
169 /// Missing data for the named handshake payload value
170 MissingData(&'static str),
171 /// A peer did not advertise its supported key exchange groups.
172 MissingKeyExchange,
173 /// A peer sent an empty list of signature schemes
174 NoSignatureSchemes,
175 /// Trailing data found for the named handshake payload value
176 TrailingData(&'static str),
177 /// A peer sent an unexpected message type.
178 UnexpectedMessage(&'static str),
179 /// An unknown TLS protocol was encountered during message decoding.
180 UnknownProtocolVersion,
181 /// A peer sent a non-null compression method.
182 UnsupportedCompression,
183 /// A peer sent an unknown elliptic curve type.
184 UnsupportedCurveType,
185 /// A peer sent an unsupported key exchange algorithm.
186 UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm),
187}
188
189impl From<InvalidMessage> for Error {
190 #[inline]
191 fn from(e: InvalidMessage) -> Self {
192 Self::InvalidMessage(e)
193 }
194}
195
196#[non_exhaustive]
197#[allow(missing_docs)]
198#[derive(Debug, PartialEq, Clone)]
199/// The set of cases where we failed to make a connection because we thought
200/// the peer was misbehaving.
201///
202/// This is `non_exhaustive`: we might add or stop using items here in minor
203/// versions. We also don't document what they mean. Generally a user of
204/// rustls shouldn't vary its behaviour on these error codes, and there is
205/// nothing it can do to improve matters.
206///
207/// Please file a bug against rustls if you see `Error::PeerMisbehaved` in
208/// the wild.
209pub enum PeerMisbehaved {
210 AttemptedDowngradeToTls12WhenTls13IsSupported,
211 BadCertChainExtensions,
212 DisallowedEncryptedExtension,
213 DuplicateClientHelloExtensions,
214 DuplicateEncryptedExtensions,
215 DuplicateHelloRetryRequestExtensions,
216 DuplicateNewSessionTicketExtensions,
217 DuplicateServerHelloExtensions,
218 DuplicateServerNameTypes,
219 EarlyDataAttemptedInSecondClientHello,
220 EarlyDataExtensionWithoutResumption,
221 EarlyDataOfferedWithVariedCipherSuite,
222 HandshakeHashVariedAfterRetry,
223 IllegalHelloRetryRequestWithEmptyCookie,
224 IllegalHelloRetryRequestWithNoChanges,
225 IllegalHelloRetryRequestWithOfferedGroup,
226 IllegalHelloRetryRequestWithUnofferedCipherSuite,
227 IllegalHelloRetryRequestWithUnofferedNamedGroup,
228 IllegalHelloRetryRequestWithUnsupportedVersion,
229 IllegalHelloRetryRequestWithWrongSessionId,
230 IllegalHelloRetryRequestWithInvalidEch,
231 IllegalMiddleboxChangeCipherSpec,
232 IllegalTlsInnerPlaintext,
233 IncorrectBinder,
234 InvalidCertCompression,
235 InvalidMaxEarlyDataSize,
236 InvalidKeyShare,
237 KeyEpochWithPendingFragment,
238 KeyUpdateReceivedInQuicConnection,
239 MessageInterleavedWithHandshakeMessage,
240 MissingBinderInPskExtension,
241 MissingKeyShare,
242 MissingPskModesExtension,
243 MissingQuicTransportParameters,
244 OfferedDuplicateCertificateCompressions,
245 OfferedDuplicateKeyShares,
246 OfferedEarlyDataWithOldProtocolVersion,
247 OfferedEmptyApplicationProtocol,
248 OfferedIncorrectCompressions,
249 PskExtensionMustBeLast,
250 PskExtensionWithMismatchedIdsAndBinders,
251 RefusedToFollowHelloRetryRequest,
252 RejectedEarlyDataInterleavedWithHandshakeMessage,
253 ResumptionAttemptedWithVariedEms,
254 ResumptionOfferedWithVariedCipherSuite,
255 ResumptionOfferedWithVariedEms,
256 ResumptionOfferedWithIncompatibleCipherSuite,
257 SelectedDifferentCipherSuiteAfterRetry,
258 SelectedInvalidPsk,
259 SelectedTls12UsingTls13VersionExtension,
260 SelectedUnofferedApplicationProtocol,
261 SelectedUnofferedCertCompression,
262 SelectedUnofferedCipherSuite,
263 SelectedUnofferedCompression,
264 SelectedUnofferedKxGroup,
265 SelectedUnofferedPsk,
266 SelectedUnusableCipherSuiteForVersion,
267 ServerEchoedCompatibilitySessionId,
268 ServerHelloMustOfferUncompressedEcPoints,
269 ServerNameDifferedOnRetry,
270 ServerNameMustContainOneHostName,
271 SignedKxWithWrongAlgorithm,
272 SignedHandshakeWithUnadvertisedSigScheme,
273 TooManyEmptyFragments,
274 TooManyKeyUpdateRequests,
275 TooManyRenegotiationRequests,
276 TooManyWarningAlertsReceived,
277 TooMuchEarlyDataReceived,
278 UnexpectedCleartextExtension,
279 UnsolicitedCertExtension,
280 UnsolicitedEncryptedExtension,
281 UnsolicitedSctList,
282 UnsolicitedServerHelloExtension,
283 WrongGroupForKeyShare,
284 UnsolicitedEchExtension,
285}
286
287impl From<PeerMisbehaved> for Error {
288 #[inline]
289 fn from(e: PeerMisbehaved) -> Self {
290 Self::PeerMisbehaved(e)
291 }
292}
293
294#[non_exhaustive]
295#[allow(missing_docs)]
296#[derive(Debug, PartialEq, Clone)]
297/// The set of cases where we failed to make a connection because a peer
298/// doesn't support a TLS version/feature we require.
299///
300/// This is `non_exhaustive`: we might add or stop using items here in minor
301/// versions.
302pub enum PeerIncompatible {
303 EcPointsExtensionRequired,
304 ExtendedMasterSecretExtensionRequired,
305 IncorrectCertificateTypeExtension,
306 KeyShareExtensionRequired,
307 NamedGroupsExtensionRequired,
308 NoCertificateRequestSignatureSchemesInCommon,
309 NoCipherSuitesInCommon,
310 NoEcPointFormatsInCommon,
311 NoKxGroupsInCommon,
312 NoSignatureSchemesInCommon,
313 NullCompressionRequired,
314 ServerDoesNotSupportTls12Or13,
315 ServerSentHelloRetryRequestWithUnknownExtension,
316 ServerTlsVersionIsDisabledByOurConfig,
317 SignatureAlgorithmsExtensionRequired,
318 SupportedVersionsExtensionRequired,
319 Tls12NotOffered,
320 Tls12NotOfferedOrEnabled,
321 Tls13RequiredForQuic,
322 UncompressedEcPointsRequired,
323 UnsolicitedCertificateTypeExtension,
324 ServerRejectedEncryptedClientHello(Option<Vec<EchConfigPayload>>),
325}
326
327impl From<PeerIncompatible> for Error {
328 #[inline]
329 fn from(e: PeerIncompatible) -> Self {
330 Self::PeerIncompatible(e)
331 }
332}
333
334#[non_exhaustive]
335#[derive(Debug, Clone)]
336/// The ways in which certificate validators can express errors.
337///
338/// Note that the rustls TLS protocol code interprets specifically these
339/// error codes to send specific TLS alerts. Therefore, if a
340/// custom certificate validator uses incorrect errors the library as
341/// a whole will send alerts that do not match the standard (this is usually
342/// a minor issue, but could be misleading).
343pub enum CertificateError {
344 /// The certificate is not correctly encoded.
345 BadEncoding,
346
347 /// The current time is after the `notAfter` time in the certificate.
348 Expired,
349
350 /// The current time is after the `notAfter` time in the certificate.
351 ///
352 /// This variant is semantically the same as `Expired`, but includes
353 /// extra data to improve error reports.
354 ExpiredContext {
355 /// The validation time.
356 time: UnixTime,
357 /// The `notAfter` time of the certificate.
358 not_after: UnixTime,
359 },
360
361 /// The current time is before the `notBefore` time in the certificate.
362 NotValidYet,
363
364 /// The current time is before the `notBefore` time in the certificate.
365 ///
366 /// This variant is semantically the same as `NotValidYet`, but includes
367 /// extra data to improve error reports.
368 NotValidYetContext {
369 /// The validation time.
370 time: UnixTime,
371 /// The `notBefore` time of the certificate.
372 not_before: UnixTime,
373 },
374
375 /// The certificate has been revoked.
376 Revoked,
377
378 /// The certificate contains an extension marked critical, but it was
379 /// not processed by the certificate validator.
380 UnhandledCriticalExtension,
381
382 /// The certificate chain is not issued by a known root certificate.
383 UnknownIssuer,
384
385 /// The certificate's revocation status could not be determined.
386 UnknownRevocationStatus,
387
388 /// The certificate's revocation status could not be determined, because the CRL is expired.
389 ExpiredRevocationList,
390
391 /// The certificate's revocation status could not be determined, because the CRL is expired.
392 ///
393 /// This variant is semantically the same as `ExpiredRevocationList`, but includes
394 /// extra data to improve error reports.
395 ExpiredRevocationListContext {
396 /// The validation time.
397 time: UnixTime,
398 /// The nextUpdate time of the CRL.
399 next_update: UnixTime,
400 },
401
402 /// A certificate is not correctly signed by the key of its alleged
403 /// issuer.
404 BadSignature,
405
406 /// The subject names in an end-entity certificate do not include
407 /// the expected name.
408 NotValidForName,
409
410 /// The subject names in an end-entity certificate do not include
411 /// the expected name.
412 ///
413 /// This variant is semantically the same as `NotValidForName`, but includes
414 /// extra data to improve error reports.
415 NotValidForNameContext {
416 /// Expected server name.
417 expected: ServerName<'static>,
418
419 /// The names presented in the end entity certificate.
420 ///
421 /// These are the subject names as present in the leaf certificate and may contain DNS names
422 /// with or without a wildcard label as well as IP address names.
423 presented: Vec<String>,
424 },
425
426 /// The certificate is being used for a different purpose than allowed.
427 InvalidPurpose,
428
429 /// The certificate is valid, but the handshake is rejected for other
430 /// reasons.
431 ApplicationVerificationFailure,
432
433 /// Any other error.
434 ///
435 /// This can be used by custom verifiers to expose the underlying error
436 /// (where they are not better described by the more specific errors
437 /// above).
438 ///
439 /// It is also used by the default verifier in case its error is
440 /// not covered by the above common cases.
441 ///
442 /// Enums holding this variant will never compare equal to each other.
443 Other(OtherError),
444}
445
446impl PartialEq<Self> for CertificateError {
447 fn eq(&self, other: &Self) -> bool {
448 use CertificateError::*;
449 #[allow(clippy::match_like_matches_macro)]
450 match (self, other) {
451 (BadEncoding, BadEncoding) => true,
452 (Expired, Expired) => true,
453 (
454 ExpiredContext {
455 time: left_time,
456 not_after: left_not_after,
457 },
458 ExpiredContext {
459 time: right_time,
460 not_after: right_not_after,
461 },
462 ) => (left_time, left_not_after) == (right_time, right_not_after),
463 (NotValidYet, NotValidYet) => true,
464 (
465 NotValidYetContext {
466 time: left_time,
467 not_before: left_not_before,
468 },
469 NotValidYetContext {
470 time: right_time,
471 not_before: right_not_before,
472 },
473 ) => (left_time, left_not_before) == (right_time, right_not_before),
474 (Revoked, Revoked) => true,
475 (UnhandledCriticalExtension, UnhandledCriticalExtension) => true,
476 (UnknownIssuer, UnknownIssuer) => true,
477 (BadSignature, BadSignature) => true,
478 (NotValidForName, NotValidForName) => true,
479 (
480 NotValidForNameContext {
481 expected: left_expected,
482 presented: left_presented,
483 },
484 NotValidForNameContext {
485 expected: right_expected,
486 presented: right_presented,
487 },
488 ) => (left_expected, left_presented) == (right_expected, right_presented),
489 (InvalidPurpose, InvalidPurpose) => true,
490 (ApplicationVerificationFailure, ApplicationVerificationFailure) => true,
491 (UnknownRevocationStatus, UnknownRevocationStatus) => true,
492 (ExpiredRevocationList, ExpiredRevocationList) => true,
493 (
494 ExpiredRevocationListContext {
495 time: left_time,
496 next_update: left_next_update,
497 },
498 ExpiredRevocationListContext {
499 time: right_time,
500 next_update: right_next_update,
501 },
502 ) => (left_time, left_next_update) == (right_time, right_next_update),
503 _ => false,
504 }
505 }
506}
507
508// The following mapping are heavily referenced in:
509// * [OpenSSL Implementation](https://github.com/openssl/openssl/blob/45bb98bfa223efd3258f445ad443f878011450f0/ssl/statem/statem_lib.c#L1434)
510// * [BoringSSL Implementation](https://github.com/google/boringssl/blob/583c60bd4bf76d61b2634a58bcda99a92de106cb/ssl/ssl_x509.cc#L1323)
511impl From<CertificateError> for AlertDescription {
512 fn from(e: CertificateError) -> Self {
513 use CertificateError::*;
514 match e {
515 BadEncoding
516 | UnhandledCriticalExtension
517 | NotValidForName
518 | NotValidForNameContext { .. } => Self::BadCertificate,
519 // RFC 5246/RFC 8446
520 // certificate_expired
521 // A certificate has expired or **is not currently valid**.
522 Expired | ExpiredContext { .. } | NotValidYet | NotValidYetContext { .. } => {
523 Self::CertificateExpired
524 }
525 Revoked => Self::CertificateRevoked,
526 // OpenSSL, BoringSSL and AWS-LC all generate an Unknown CA alert for
527 // the case where revocation status can not be determined, so we do the same here.
528 UnknownIssuer
529 | UnknownRevocationStatus
530 | ExpiredRevocationList
531 | ExpiredRevocationListContext { .. } => Self::UnknownCA,
532 BadSignature => Self::DecryptError,
533 InvalidPurpose => Self::UnsupportedCertificate,
534 ApplicationVerificationFailure => Self::AccessDenied,
535 // RFC 5246/RFC 8446
536 // certificate_unknown
537 // Some other (unspecified) issue arose in processing the
538 // certificate, rendering it unacceptable.
539 Other(..) => Self::CertificateUnknown,
540 }
541 }
542}
543
544impl fmt::Display for CertificateError {
545 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
546 match self {
547 #[cfg(feature = "std")]
548 Self::NotValidForNameContext {
549 expected,
550 presented,
551 } => {
552 write!(
553 f,
554 "certificate not valid for name {:?}; certificate ",
555 expected.to_str()
556 )?;
557
558 match presented.as_slice() {
559 &[] => write!(
560 f,
561 "is not valid for any names (according to its subjectAltName extension)"
562 ),
563 [one] => write!(f, "is only valid for {}", one),
564 many => {
565 write!(f, "is only valid for ")?;
566
567 let n = many.len();
568 let all_but_last = &many[..n - 1];
569 let last = &many[n - 1];
570
571 for (i, name) in all_but_last.iter().enumerate() {
572 write!(f, "{}", name)?;
573 if i < n - 2 {
574 write!(f, ", ")?;
575 }
576 }
577 write!(f, " or {}", last)
578 }
579 }
580 }
581
582 Self::ExpiredContext { time, not_after } => write!(
583 f,
584 "certificate expired: verification time {} (UNIX), \
585 but certificate is not valid after {} \
586 ({} seconds ago)",
587 time.as_secs(),
588 not_after.as_secs(),
589 time.as_secs()
590 .saturating_sub(not_after.as_secs())
591 ),
592
593 Self::NotValidYetContext { time, not_before } => write!(
594 f,
595 "certificate not valid yet: verification time {} (UNIX), \
596 but certificate is not valid before {} \
597 ({} seconds in future)",
598 time.as_secs(),
599 not_before.as_secs(),
600 not_before
601 .as_secs()
602 .saturating_sub(time.as_secs())
603 ),
604
605 Self::ExpiredRevocationListContext { time, next_update } => write!(
606 f,
607 "certificate revocation list expired: \
608 verification time {} (UNIX), \
609 but CRL is not valid after {} \
610 ({} seconds ago)",
611 time.as_secs(),
612 next_update.as_secs(),
613 time.as_secs()
614 .saturating_sub(next_update.as_secs())
615 ),
616
617 other => write!(f, "{:?}", other),
618 }
619 }
620}
621
622impl From<CertificateError> for Error {
623 #[inline]
624 fn from(e: CertificateError) -> Self {
625 Self::InvalidCertificate(e)
626 }
627}
628
629#[non_exhaustive]
630#[derive(Debug, Clone)]
631/// The ways in which a certificate revocation list (CRL) can be invalid.
632pub enum CertRevocationListError {
633 /// The CRL had a bad, or unsupported signature from its issuer.
634 BadSignature,
635
636 /// The CRL contained an invalid CRL number.
637 InvalidCrlNumber,
638
639 /// The CRL contained a revoked certificate with an invalid serial number.
640 InvalidRevokedCertSerialNumber,
641
642 /// The CRL issuer does not specify the cRLSign key usage.
643 IssuerInvalidForCrl,
644
645 /// The CRL is invalid for some other reason.
646 ///
647 /// Enums holding this variant will never compare equal to each other.
648 Other(OtherError),
649
650 /// The CRL is not correctly encoded.
651 ParseError,
652
653 /// The CRL is not a v2 X.509 CRL.
654 UnsupportedCrlVersion,
655
656 /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension.
657 UnsupportedCriticalExtension,
658
659 /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL.
660 UnsupportedDeltaCrl,
661
662 /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA
663 /// other than the issuer of the CRL.
664 UnsupportedIndirectCrl,
665
666 /// The CRL contained a revoked certificate with an unsupported revocation reason.
667 /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons.
668 ///
669 /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1>
670 UnsupportedRevocationReason,
671}
672
673impl PartialEq<Self> for CertRevocationListError {
674 fn eq(&self, other: &Self) -> bool {
675 use CertRevocationListError::*;
676 #[allow(clippy::match_like_matches_macro)]
677 match (self, other) {
678 (BadSignature, BadSignature) => true,
679 (InvalidCrlNumber, InvalidCrlNumber) => true,
680 (InvalidRevokedCertSerialNumber, InvalidRevokedCertSerialNumber) => true,
681 (IssuerInvalidForCrl, IssuerInvalidForCrl) => true,
682 (ParseError, ParseError) => true,
683 (UnsupportedCrlVersion, UnsupportedCrlVersion) => true,
684 (UnsupportedCriticalExtension, UnsupportedCriticalExtension) => true,
685 (UnsupportedDeltaCrl, UnsupportedDeltaCrl) => true,
686 (UnsupportedIndirectCrl, UnsupportedIndirectCrl) => true,
687 (UnsupportedRevocationReason, UnsupportedRevocationReason) => true,
688 _ => false,
689 }
690 }
691}
692
693impl From<CertRevocationListError> for Error {
694 #[inline]
695 fn from(e: CertRevocationListError) -> Self {
696 Self::InvalidCertRevocationList(e)
697 }
698}
699
700#[non_exhaustive]
701#[derive(Debug, Clone, Eq, PartialEq)]
702/// An error that occurred while handling Encrypted Client Hello (ECH).
703pub enum EncryptedClientHelloError {
704 /// The provided ECH configuration list was invalid.
705 InvalidConfigList,
706 /// No compatible ECH configuration.
707 NoCompatibleConfig,
708 /// The client configuration has server name indication (SNI) disabled.
709 SniRequired,
710}
711
712impl From<EncryptedClientHelloError> for Error {
713 #[inline]
714 fn from(e: EncryptedClientHelloError) -> Self {
715 Self::InvalidEncryptedClientHello(e)
716 }
717}
718
719fn join<T: fmt::Debug>(items: &[T]) -> String {
720 items
721 .iter()
722 .map(|x| format!("{:?}", x))
723 .collect::<Vec<String>>()
724 .join(sep:" or ")
725}
726
727impl fmt::Display for Error {
728 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
729 match self {
730 Self::InappropriateMessage {
731 expect_types,
732 got_type,
733 } => write!(
734 f,
735 "received unexpected message: got {:?} when expecting {}",
736 got_type,
737 join::<ContentType>(expect_types)
738 ),
739 Self::InappropriateHandshakeMessage {
740 expect_types,
741 got_type,
742 } => write!(
743 f,
744 "received unexpected handshake message: got {:?} when expecting {}",
745 got_type,
746 join::<HandshakeType>(expect_types)
747 ),
748 Self::InvalidMessage(typ) => {
749 write!(f, "received corrupt message of type {:?}", typ)
750 }
751 Self::PeerIncompatible(why) => write!(f, "peer is incompatible: {:?}", why),
752 Self::PeerMisbehaved(why) => write!(f, "peer misbehaved: {:?}", why),
753 Self::AlertReceived(alert) => write!(f, "received fatal alert: {:?}", alert),
754 Self::InvalidCertificate(err) => {
755 write!(f, "invalid peer certificate: {}", err)
756 }
757 Self::InvalidCertRevocationList(err) => {
758 write!(f, "invalid certificate revocation list: {:?}", err)
759 }
760 Self::NoCertificatesPresented => write!(f, "peer sent no certificates"),
761 Self::UnsupportedNameType => write!(f, "presented server name type wasn't supported"),
762 Self::DecryptError => write!(f, "cannot decrypt peer's message"),
763 Self::InvalidEncryptedClientHello(err) => {
764 write!(f, "encrypted client hello failure: {:?}", err)
765 }
766 Self::EncryptError => write!(f, "cannot encrypt message"),
767 Self::PeerSentOversizedRecord => write!(f, "peer sent excess record size"),
768 Self::HandshakeNotComplete => write!(f, "handshake not complete"),
769 Self::NoApplicationProtocol => write!(f, "peer doesn't support any known protocol"),
770 Self::FailedToGetCurrentTime => write!(f, "failed to get current time"),
771 Self::FailedToGetRandomBytes => write!(f, "failed to get random bytes"),
772 Self::BadMaxFragmentSize => {
773 write!(f, "the supplied max_fragment_size was too small or large")
774 }
775 Self::InconsistentKeys(why) => {
776 write!(f, "keys may not be consistent: {:?}", why)
777 }
778 Self::General(err) => write!(f, "unexpected error: {}", err),
779 Self::Other(err) => write!(f, "other error: {}", err),
780 }
781 }
782}
783
784#[cfg(feature = "std")]
785impl From<SystemTimeError> for Error {
786 #[inline]
787 fn from(_: SystemTimeError) -> Self {
788 Self::FailedToGetCurrentTime
789 }
790}
791
792#[cfg(feature = "std")]
793impl std::error::Error for Error {}
794
795impl From<rand::GetRandomFailed> for Error {
796 fn from(_: rand::GetRandomFailed) -> Self {
797 Self::FailedToGetRandomBytes
798 }
799}
800
801mod other_error {
802 use core::fmt;
803 #[cfg(feature = "std")]
804 use std::error::Error as StdError;
805
806 use super::Error;
807 #[cfg(feature = "std")]
808 use crate::sync::Arc;
809
810 /// Any other error that cannot be expressed by a more specific [`Error`] variant.
811 ///
812 /// For example, an `OtherError` could be produced by a custom crypto provider
813 /// exposing a provider specific error.
814 ///
815 /// Enums holding this type will never compare equal to each other.
816 #[derive(Debug, Clone)]
817 pub struct OtherError(#[cfg(feature = "std")] pub Arc<dyn StdError + Send + Sync>);
818
819 impl PartialEq<Self> for OtherError {
820 fn eq(&self, _other: &Self) -> bool {
821 false
822 }
823 }
824
825 impl From<OtherError> for Error {
826 fn from(value: OtherError) -> Self {
827 Self::Other(value)
828 }
829 }
830
831 impl fmt::Display for OtherError {
832 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
833 #[cfg(feature = "std")]
834 {
835 write!(f, "{}", self.0)
836 }
837 #[cfg(not(feature = "std"))]
838 {
839 f.write_str("no further information available")
840 }
841 }
842 }
843
844 #[cfg(feature = "std")]
845 impl StdError for OtherError {
846 fn source(&self) -> Option<&(dyn StdError + 'static)> {
847 Some(self.0.as_ref())
848 }
849 }
850}
851
852pub use other_error::OtherError;
853
854#[cfg(test)]
855mod tests {
856 use core::time::Duration;
857 use std::prelude::v1::*;
858 use std::{println, vec};
859
860 use super::{
861 CertRevocationListError, Error, InconsistentKeys, InvalidMessage, OtherError, UnixTime,
862 };
863 #[cfg(feature = "std")]
864 use crate::sync::Arc;
865 use pki_types::ServerName;
866
867 #[test]
868 fn certificate_error_equality() {
869 use super::CertificateError::*;
870 assert_eq!(BadEncoding, BadEncoding);
871 assert_eq!(Expired, Expired);
872 let context = ExpiredContext {
873 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
874 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
875 };
876 assert_eq!(context, context);
877 assert_ne!(
878 context,
879 ExpiredContext {
880 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
881 not_after: UnixTime::since_unix_epoch(Duration::from_secs(123)),
882 }
883 );
884 assert_ne!(
885 context,
886 ExpiredContext {
887 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
888 not_after: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
889 }
890 );
891 assert_eq!(NotValidYet, NotValidYet);
892 let context = NotValidYetContext {
893 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
894 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
895 };
896 assert_eq!(context, context);
897 assert_ne!(
898 context,
899 NotValidYetContext {
900 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
901 not_before: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
902 }
903 );
904 assert_ne!(
905 context,
906 NotValidYetContext {
907 time: UnixTime::since_unix_epoch(Duration::from_secs(123)),
908 not_before: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
909 }
910 );
911 assert_eq!(Revoked, Revoked);
912 assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension);
913 assert_eq!(UnknownIssuer, UnknownIssuer);
914 assert_eq!(ExpiredRevocationList, ExpiredRevocationList);
915 assert_eq!(UnknownRevocationStatus, UnknownRevocationStatus);
916 let context = ExpiredRevocationListContext {
917 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
918 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
919 };
920 assert_eq!(context, context);
921 assert_ne!(
922 context,
923 ExpiredRevocationListContext {
924 time: UnixTime::since_unix_epoch(Duration::from_secs(12345)),
925 next_update: UnixTime::since_unix_epoch(Duration::from_secs(123)),
926 }
927 );
928 assert_ne!(
929 context,
930 ExpiredRevocationListContext {
931 time: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
932 next_update: UnixTime::since_unix_epoch(Duration::from_secs(1234)),
933 }
934 );
935 assert_eq!(BadSignature, BadSignature);
936 assert_eq!(NotValidForName, NotValidForName);
937 let context = NotValidForNameContext {
938 expected: ServerName::try_from("example.com")
939 .unwrap()
940 .to_owned(),
941 presented: vec!["other.com".into()],
942 };
943 assert_eq!(context, context);
944 assert_ne!(
945 context,
946 NotValidForNameContext {
947 expected: ServerName::try_from("example.com")
948 .unwrap()
949 .to_owned(),
950 presented: vec![]
951 }
952 );
953 assert_ne!(
954 context,
955 NotValidForNameContext {
956 expected: ServerName::try_from("huh.com")
957 .unwrap()
958 .to_owned(),
959 presented: vec!["other.com".into()],
960 }
961 );
962 assert_eq!(InvalidPurpose, InvalidPurpose);
963 assert_eq!(
964 ApplicationVerificationFailure,
965 ApplicationVerificationFailure
966 );
967 let other = Other(OtherError(
968 #[cfg(feature = "std")]
969 Arc::from(Box::from("")),
970 ));
971 assert_ne!(other, other);
972 assert_ne!(BadEncoding, Expired);
973 }
974
975 #[test]
976 fn crl_error_equality() {
977 use super::CertRevocationListError::*;
978 assert_eq!(BadSignature, BadSignature);
979 assert_eq!(InvalidCrlNumber, InvalidCrlNumber);
980 assert_eq!(
981 InvalidRevokedCertSerialNumber,
982 InvalidRevokedCertSerialNumber
983 );
984 assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl);
985 assert_eq!(ParseError, ParseError);
986 assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension);
987 assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion);
988 assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl);
989 assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl);
990 assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason);
991 let other = Other(OtherError(
992 #[cfg(feature = "std")]
993 Arc::from(Box::from("")),
994 ));
995 assert_ne!(other, other);
996 assert_ne!(BadSignature, InvalidCrlNumber);
997 }
998
999 #[test]
1000 #[cfg(feature = "std")]
1001 fn other_error_equality() {
1002 let other_error = OtherError(Arc::from(Box::from("")));
1003 assert_ne!(other_error, other_error);
1004 let other: Error = other_error.into();
1005 assert_ne!(other, other);
1006 }
1007
1008 #[test]
1009 fn smoke() {
1010 use crate::enums::{AlertDescription, ContentType, HandshakeType};
1011
1012 let all = vec![
1013 Error::InappropriateMessage {
1014 expect_types: vec![ContentType::Alert],
1015 got_type: ContentType::Handshake,
1016 },
1017 Error::InappropriateHandshakeMessage {
1018 expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished],
1019 got_type: HandshakeType::ServerHello,
1020 },
1021 Error::InvalidMessage(InvalidMessage::InvalidCcs),
1022 Error::NoCertificatesPresented,
1023 Error::DecryptError,
1024 super::PeerIncompatible::Tls12NotOffered.into(),
1025 super::PeerMisbehaved::UnsolicitedCertExtension.into(),
1026 Error::AlertReceived(AlertDescription::ExportRestriction),
1027 super::CertificateError::Expired.into(),
1028 super::CertificateError::NotValidForNameContext {
1029 expected: ServerName::try_from("example.com")
1030 .unwrap()
1031 .to_owned(),
1032 presented: vec![],
1033 }
1034 .into(),
1035 super::CertificateError::NotValidForNameContext {
1036 expected: ServerName::try_from("example.com")
1037 .unwrap()
1038 .to_owned(),
1039 presented: vec!["DnsName(\"hello.com\")".into()],
1040 }
1041 .into(),
1042 super::CertificateError::NotValidForNameContext {
1043 expected: ServerName::try_from("example.com")
1044 .unwrap()
1045 .to_owned(),
1046 presented: vec![
1047 "DnsName(\"hello.com\")".into(),
1048 "DnsName(\"goodbye.com\")".into(),
1049 ],
1050 }
1051 .into(),
1052 super::CertificateError::NotValidYetContext {
1053 time: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1054 not_before: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1055 }
1056 .into(),
1057 super::CertificateError::ExpiredContext {
1058 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1059 not_after: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1060 }
1061 .into(),
1062 super::CertificateError::ExpiredRevocationListContext {
1063 time: UnixTime::since_unix_epoch(Duration::from_secs(320)),
1064 next_update: UnixTime::since_unix_epoch(Duration::from_secs(300)),
1065 }
1066 .into(),
1067 Error::General("undocumented error".to_string()),
1068 Error::FailedToGetCurrentTime,
1069 Error::FailedToGetRandomBytes,
1070 Error::HandshakeNotComplete,
1071 Error::PeerSentOversizedRecord,
1072 Error::NoApplicationProtocol,
1073 Error::BadMaxFragmentSize,
1074 Error::InconsistentKeys(InconsistentKeys::KeyMismatch),
1075 Error::InconsistentKeys(InconsistentKeys::Unknown),
1076 Error::InvalidCertRevocationList(CertRevocationListError::BadSignature),
1077 Error::Other(OtherError(
1078 #[cfg(feature = "std")]
1079 Arc::from(Box::from("")),
1080 )),
1081 ];
1082
1083 for err in all {
1084 println!("{:?}:", err);
1085 println!(" fmt '{}'", err);
1086 }
1087 }
1088
1089 #[test]
1090 fn rand_error_mapping() {
1091 use super::rand;
1092 let err: Error = rand::GetRandomFailed.into();
1093 assert_eq!(err, Error::FailedToGetRandomBytes);
1094 }
1095
1096 #[cfg(feature = "std")]
1097 #[test]
1098 fn time_error_mapping() {
1099 use std::time::SystemTime;
1100
1101 let time_error = SystemTime::UNIX_EPOCH
1102 .duration_since(SystemTime::now())
1103 .unwrap_err();
1104 let err: Error = time_error.into();
1105 assert_eq!(err, Error::FailedToGetCurrentTime);
1106 }
1107}
1108