1 | use crate::enums::{AlertDescription, ContentType, HandshakeType}; |
2 | use crate::msgs::handshake::KeyExchangeAlgorithm; |
3 | use crate::rand; |
4 | |
5 | use alloc::format; |
6 | use alloc::string::String; |
7 | use alloc::sync::Arc; |
8 | use alloc::vec::Vec; |
9 | use core::fmt; |
10 | use std::error::Error as StdError; |
11 | use std::time::SystemTimeError; |
12 | |
13 | /// rustls reports protocol errors using this type. |
14 | #[non_exhaustive ] |
15 | #[derive (Debug, PartialEq, Clone)] |
16 | pub 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 | /// The peer sent us a TLS message with invalid contents. |
40 | InvalidMessage(InvalidMessage), |
41 | |
42 | /// The peer didn't give us any certificates. |
43 | NoCertificatesPresented, |
44 | |
45 | /// The certificate verifier doesn't support the given type of name. |
46 | UnsupportedNameType, |
47 | |
48 | /// We couldn't decrypt a message. This is invariably fatal. |
49 | DecryptError, |
50 | |
51 | /// We couldn't encrypt a message because it was larger than the allowed message size. |
52 | /// This should never happen if the application is using valid record sizes. |
53 | EncryptError, |
54 | |
55 | /// The peer doesn't support a protocol version/feature we require. |
56 | /// The parameter gives a hint as to what version/feature it is. |
57 | PeerIncompatible(PeerIncompatible), |
58 | |
59 | /// The peer deviated from the standard TLS protocol. |
60 | /// The parameter gives a hint where. |
61 | PeerMisbehaved(PeerMisbehaved), |
62 | |
63 | /// We received a fatal alert. This means the peer is unhappy. |
64 | AlertReceived(AlertDescription), |
65 | |
66 | /// We saw an invalid certificate. |
67 | /// |
68 | /// The contained error is from the certificate validation trait |
69 | /// implementation. |
70 | InvalidCertificate(CertificateError), |
71 | |
72 | /// A provided certificate revocation list (CRL) was invalid. |
73 | InvalidCertRevocationList(CertRevocationListError), |
74 | |
75 | /// A catch-all error for unlikely errors. |
76 | General(String), |
77 | |
78 | /// We failed to figure out what time it currently is. |
79 | FailedToGetCurrentTime, |
80 | |
81 | /// We failed to acquire random bytes from the system. |
82 | FailedToGetRandomBytes, |
83 | |
84 | /// This function doesn't work until the TLS handshake |
85 | /// is complete. |
86 | HandshakeNotComplete, |
87 | |
88 | /// The peer sent an oversized record/fragment. |
89 | PeerSentOversizedRecord, |
90 | |
91 | /// An incoming connection did not support any known application protocol. |
92 | NoApplicationProtocol, |
93 | |
94 | /// The `max_fragment_size` value supplied in configuration was too small, |
95 | /// or too large. |
96 | BadMaxFragmentSize, |
97 | |
98 | /// Any other error. |
99 | /// |
100 | /// This variant should only be used when the error is not better described by a more |
101 | /// specific variant. For example, if a custom crypto provider returns a |
102 | /// provider specific error. |
103 | /// |
104 | /// Enums holding this variant will never compare equal to each other. |
105 | Other(OtherError), |
106 | } |
107 | |
108 | /// A corrupt TLS message payload that resulted in an error. |
109 | #[non_exhaustive ] |
110 | #[derive (Debug, Clone, Copy, PartialEq)] |
111 | |
112 | pub enum InvalidMessage { |
113 | /// An advertised message was larger then expected. |
114 | HandshakePayloadTooLarge, |
115 | /// The peer sent us a syntactically incorrect ChangeCipherSpec payload. |
116 | InvalidCcs, |
117 | /// An unknown content type was encountered during message decoding. |
118 | InvalidContentType, |
119 | /// A peer sent an invalid certificate status type |
120 | InvalidCertificateStatusType, |
121 | /// Context was incorrectly attached to a certificate request during a handshake. |
122 | InvalidCertRequest, |
123 | /// A peer's DH params could not be decoded |
124 | InvalidDhParams, |
125 | /// A message was zero-length when its record kind forbids it. |
126 | InvalidEmptyPayload, |
127 | /// A peer sent an unexpected key update request. |
128 | InvalidKeyUpdate, |
129 | /// A peer's server name could not be decoded |
130 | InvalidServerName, |
131 | /// A TLS message payload was larger then allowed by the specification. |
132 | MessageTooLarge, |
133 | /// Message is shorter than the expected length |
134 | MessageTooShort, |
135 | /// Missing data for the named handshake payload value |
136 | MissingData(&'static str), |
137 | /// A peer did not advertise its supported key exchange groups. |
138 | MissingKeyExchange, |
139 | /// A peer sent an empty list of signature schemes |
140 | NoSignatureSchemes, |
141 | /// Trailing data found for the named handshake payload value |
142 | TrailingData(&'static str), |
143 | /// A peer sent an unexpected message type. |
144 | UnexpectedMessage(&'static str), |
145 | /// An unknown TLS protocol was encountered during message decoding. |
146 | UnknownProtocolVersion, |
147 | /// A peer sent a non-null compression method. |
148 | UnsupportedCompression, |
149 | /// A peer sent an unknown elliptic curve type. |
150 | UnsupportedCurveType, |
151 | /// A peer sent an unsupported key exchange algorithm. |
152 | UnsupportedKeyExchangeAlgorithm(KeyExchangeAlgorithm), |
153 | } |
154 | |
155 | impl 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)] |
165 | /// The set of cases where we failed to make a connection because we thought |
166 | /// the peer was misbehaving. |
167 | /// |
168 | /// This is `non_exhaustive`: we might add or stop using items here in minor |
169 | /// versions. We also don't document what they mean. Generally a user of |
170 | /// rustls shouldn't vary its behaviour on these error codes, and there is |
171 | /// nothing it can do to improve matters. |
172 | /// |
173 | /// Please file a bug against rustls if you see `Error::PeerMisbehaved` in |
174 | /// the wild. |
175 | pub 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 | |
243 | impl 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)] |
253 | /// The set of cases where we failed to make a connection because a peer |
254 | /// doesn't support a TLS version/feature we require. |
255 | /// |
256 | /// This is `non_exhaustive`: we might add or stop using items here in minor |
257 | /// versions. |
258 | pub 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 | |
279 | impl 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)] |
288 | /// The ways in which certificate validators can express errors. |
289 | /// |
290 | /// Note that the rustls TLS protocol code interprets specifically these |
291 | /// error codes to send specific TLS alerts. Therefore, if a |
292 | /// custom certificate validator uses incorrect errors the library as |
293 | /// a whole will send alerts that do not match the standard (this is usually |
294 | /// a minor issue, but could be misleading). |
295 | pub enum CertificateError { |
296 | /// The certificate is not correctly encoded. |
297 | BadEncoding, |
298 | |
299 | /// The current time is after the `notAfter` time in the certificate. |
300 | Expired, |
301 | |
302 | /// The current time is before the `notBefore` time in the certificate. |
303 | NotValidYet, |
304 | |
305 | /// The certificate has been revoked. |
306 | Revoked, |
307 | |
308 | /// The certificate contains an extension marked critical, but it was |
309 | /// not processed by the certificate validator. |
310 | UnhandledCriticalExtension, |
311 | |
312 | /// The certificate chain is not issued by a known root certificate. |
313 | UnknownIssuer, |
314 | |
315 | /// The certificate's revocation status could not be determined. |
316 | UnknownRevocationStatus, |
317 | |
318 | /// A certificate is not correctly signed by the key of its alleged |
319 | /// issuer. |
320 | BadSignature, |
321 | |
322 | /// The subject names in an end-entity certificate do not include |
323 | /// the expected name. |
324 | NotValidForName, |
325 | |
326 | /// The certificate is being used for a different purpose than allowed. |
327 | InvalidPurpose, |
328 | |
329 | /// The certificate is valid, but the handshake is rejected for other |
330 | /// reasons. |
331 | ApplicationVerificationFailure, |
332 | |
333 | /// Any other error. |
334 | /// |
335 | /// This can be used by custom verifiers to expose the underlying error |
336 | /// (where they are not better described by the more specific errors |
337 | /// above). |
338 | /// |
339 | /// It is also used by the default verifier in case its error is |
340 | /// not covered by the above common cases. |
341 | /// |
342 | /// Enums holding this variant will never compare equal to each other. |
343 | Other(OtherError), |
344 | } |
345 | |
346 | impl 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 | |
366 | // The following mapping are heavily referenced in: |
367 | // * [OpenSSL Implementation](https://github.com/openssl/openssl/blob/45bb98bfa223efd3258f445ad443f878011450f0/ssl/statem/statem_lib.c#L1434) |
368 | // * [BoringSSL Implementation](https://github.com/google/boringssl/blob/583c60bd4bf76d61b2634a58bcda99a92de106cb/ssl/ssl_x509.cc#L1323) |
369 | impl From<CertificateError> for AlertDescription { |
370 | fn from(e: CertificateError) -> Self { |
371 | use CertificateError::*; |
372 | match e { |
373 | BadEncoding | UnhandledCriticalExtension | NotValidForName => Self::BadCertificate, |
374 | // RFC 5246/RFC 8446 |
375 | // certificate_expired |
376 | // A certificate has expired or **is not currently valid**. |
377 | Expired | NotValidYet => Self::CertificateExpired, |
378 | Revoked => Self::CertificateRevoked, |
379 | // OpenSSL, BoringSSL and AWS-LC all generate an Unknown CA alert for |
380 | // the case where revocation status can not be determined, so we do the same here. |
381 | UnknownIssuer | UnknownRevocationStatus => Self::UnknownCA, |
382 | BadSignature => Self::DecryptError, |
383 | InvalidPurpose => Self::UnsupportedCertificate, |
384 | ApplicationVerificationFailure => Self::AccessDenied, |
385 | // RFC 5246/RFC 8446 |
386 | // certificate_unknown |
387 | // Some other (unspecified) issue arose in processing the |
388 | // certificate, rendering it unacceptable. |
389 | Other(_) => Self::CertificateUnknown, |
390 | } |
391 | } |
392 | } |
393 | |
394 | impl 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)] |
403 | /// The ways in which a certificate revocation list (CRL) can be invalid. |
404 | pub enum CertRevocationListError { |
405 | /// The CRL had a bad, or unsupported signature from its issuer. |
406 | BadSignature, |
407 | |
408 | /// The CRL contained an invalid CRL number. |
409 | InvalidCrlNumber, |
410 | |
411 | /// The CRL contained a revoked certificate with an invalid serial number. |
412 | InvalidRevokedCertSerialNumber, |
413 | |
414 | /// The CRL issuer does not specify the cRLSign key usage. |
415 | IssuerInvalidForCrl, |
416 | |
417 | /// The CRL is invalid for some other reason. |
418 | /// |
419 | /// Enums holding this variant will never compare equal to each other. |
420 | Other(OtherError), |
421 | |
422 | /// The CRL is not correctly encoded. |
423 | ParseError, |
424 | |
425 | /// The CRL is not a v2 X.509 CRL. |
426 | UnsupportedCrlVersion, |
427 | |
428 | /// The CRL, or a revoked certificate in the CRL, contained an unsupported critical extension. |
429 | UnsupportedCriticalExtension, |
430 | |
431 | /// The CRL is an unsupported delta CRL, containing only changes relative to another CRL. |
432 | UnsupportedDeltaCrl, |
433 | |
434 | /// The CRL is an unsupported indirect CRL, containing revoked certificates issued by a CA |
435 | /// other than the issuer of the CRL. |
436 | UnsupportedIndirectCrl, |
437 | |
438 | /// The CRL contained a revoked certificate with an unsupported revocation reason. |
439 | /// See RFC 5280 Section 5.3.1[^1] for a list of supported revocation reasons. |
440 | /// |
441 | /// [^1]: <https://www.rfc-editor.org/rfc/rfc5280#section-5.3.1> |
442 | UnsupportedRevocationReason, |
443 | } |
444 | |
445 | impl 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 | |
465 | impl From<CertRevocationListError> for Error { |
466 | #[inline ] |
467 | fn from(e: CertRevocationListError) -> Self { |
468 | Self::InvalidCertRevocationList(e) |
469 | } |
470 | } |
471 | |
472 | fn join<T: fmt::Debug>(items: &[T]) -> String { |
473 | items |
474 | .iter() |
475 | .map(|x| format!(" {:?}" , x)) |
476 | .collect::<Vec<String>>() |
477 | .join(sep:" or " ) |
478 | } |
479 | |
480 | impl 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 | impl From<SystemTimeError> for Error { |
532 | #[inline ] |
533 | fn from(_: SystemTimeError) -> Self { |
534 | Self::FailedToGetCurrentTime |
535 | } |
536 | } |
537 | |
538 | impl StdError for Error {} |
539 | |
540 | impl From<rand::GetRandomFailed> for Error { |
541 | fn from(_: rand::GetRandomFailed) -> Self { |
542 | Self::FailedToGetRandomBytes |
543 | } |
544 | } |
545 | |
546 | /// Any other error that cannot be expressed by a more specific [`Error`] variant. |
547 | /// |
548 | /// For example, an `OtherError` could be produced by a custom crypto provider |
549 | /// exposing a provider specific error. |
550 | /// |
551 | /// Enums holding this type will never compare equal to each other. |
552 | #[derive (Debug, Clone)] |
553 | pub struct OtherError(pub Arc<dyn StdError + Send + Sync>); |
554 | |
555 | impl PartialEq<Self> for OtherError { |
556 | fn eq(&self, _other: &Self) -> bool { |
557 | false |
558 | } |
559 | } |
560 | |
561 | impl From<OtherError> for Error { |
562 | fn from(value: OtherError) -> Self { |
563 | Self::Other(value) |
564 | } |
565 | } |
566 | |
567 | impl fmt::Display for OtherError { |
568 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |
569 | write!(f, " {}" , self.0) |
570 | } |
571 | } |
572 | |
573 | impl StdError for OtherError { |
574 | fn source(&self) -> Option<&(dyn StdError + 'static)> { |
575 | Some(self.0.as_ref()) |
576 | } |
577 | } |
578 | |
579 | #[cfg (test)] |
580 | mod tests { |
581 | use super::{Error, InvalidMessage}; |
582 | use crate::error::{CertRevocationListError, OtherError}; |
583 | |
584 | #[test ] |
585 | fn certificate_error_equality() { |
586 | use super::CertificateError::*; |
587 | assert_eq!(BadEncoding, BadEncoding); |
588 | assert_eq!(Expired, Expired); |
589 | assert_eq!(NotValidYet, NotValidYet); |
590 | assert_eq!(Revoked, Revoked); |
591 | assert_eq!(UnhandledCriticalExtension, UnhandledCriticalExtension); |
592 | assert_eq!(UnknownIssuer, UnknownIssuer); |
593 | assert_eq!(BadSignature, BadSignature); |
594 | assert_eq!(NotValidForName, NotValidForName); |
595 | assert_eq!(InvalidPurpose, InvalidPurpose); |
596 | assert_eq!( |
597 | ApplicationVerificationFailure, |
598 | ApplicationVerificationFailure |
599 | ); |
600 | let other = Other(OtherError(alloc::sync::Arc::from(Box::from("" )))); |
601 | assert_ne!(other, other); |
602 | assert_ne!(BadEncoding, Expired); |
603 | } |
604 | |
605 | #[test ] |
606 | fn crl_error_equality() { |
607 | use super::CertRevocationListError::*; |
608 | assert_eq!(BadSignature, BadSignature); |
609 | assert_eq!(InvalidCrlNumber, InvalidCrlNumber); |
610 | assert_eq!( |
611 | InvalidRevokedCertSerialNumber, |
612 | InvalidRevokedCertSerialNumber |
613 | ); |
614 | assert_eq!(IssuerInvalidForCrl, IssuerInvalidForCrl); |
615 | assert_eq!(ParseError, ParseError); |
616 | assert_eq!(UnsupportedCriticalExtension, UnsupportedCriticalExtension); |
617 | assert_eq!(UnsupportedCrlVersion, UnsupportedCrlVersion); |
618 | assert_eq!(UnsupportedDeltaCrl, UnsupportedDeltaCrl); |
619 | assert_eq!(UnsupportedIndirectCrl, UnsupportedIndirectCrl); |
620 | assert_eq!(UnsupportedRevocationReason, UnsupportedRevocationReason); |
621 | let other = Other(OtherError(alloc::sync::Arc::from(Box::from("" )))); |
622 | assert_ne!(other, other); |
623 | assert_ne!(BadSignature, InvalidCrlNumber); |
624 | } |
625 | |
626 | #[test ] |
627 | fn other_error_equality() { |
628 | let other_error = OtherError(alloc::sync::Arc::from(Box::from("" ))); |
629 | assert_ne!(other_error, other_error); |
630 | let other: Error = other_error.into(); |
631 | assert_ne!(other, other); |
632 | } |
633 | |
634 | #[test ] |
635 | fn smoke() { |
636 | use crate::enums::{AlertDescription, ContentType, HandshakeType}; |
637 | |
638 | let all = vec![ |
639 | Error::InappropriateMessage { |
640 | expect_types: vec![ContentType::Alert], |
641 | got_type: ContentType::Handshake, |
642 | }, |
643 | Error::InappropriateHandshakeMessage { |
644 | expect_types: vec![HandshakeType::ClientHello, HandshakeType::Finished], |
645 | got_type: HandshakeType::ServerHello, |
646 | }, |
647 | Error::InvalidMessage(InvalidMessage::InvalidCcs), |
648 | Error::NoCertificatesPresented, |
649 | Error::DecryptError, |
650 | super::PeerIncompatible::Tls12NotOffered.into(), |
651 | super::PeerMisbehaved::UnsolicitedCertExtension.into(), |
652 | Error::AlertReceived(AlertDescription::ExportRestriction), |
653 | super::CertificateError::Expired.into(), |
654 | Error::General("undocumented error" .to_string()), |
655 | Error::FailedToGetCurrentTime, |
656 | Error::FailedToGetRandomBytes, |
657 | Error::HandshakeNotComplete, |
658 | Error::PeerSentOversizedRecord, |
659 | Error::NoApplicationProtocol, |
660 | Error::BadMaxFragmentSize, |
661 | Error::InvalidCertRevocationList(CertRevocationListError::BadSignature), |
662 | Error::Other(OtherError(alloc::sync::Arc::from(Box::from("" )))), |
663 | ]; |
664 | |
665 | for err in all { |
666 | println!("{:?}:" , err); |
667 | println!(" fmt '{}'" , err); |
668 | } |
669 | } |
670 | |
671 | #[test ] |
672 | fn rand_error_mapping() { |
673 | use super::rand; |
674 | let err: Error = rand::GetRandomFailed.into(); |
675 | assert_eq!(err, Error::FailedToGetRandomBytes); |
676 | } |
677 | |
678 | #[test ] |
679 | fn time_error_mapping() { |
680 | use std::time::SystemTime; |
681 | |
682 | let time_error = SystemTime::UNIX_EPOCH |
683 | .duration_since(SystemTime::now()) |
684 | .unwrap_err(); |
685 | let err: Error = time_error.into(); |
686 | assert_eq!(err, Error::FailedToGetCurrentTime); |
687 | } |
688 | } |
689 | |