rustls_ffi/
error.rs

1use std::cmp::min;
2use std::fmt::Display;
3use std::sync::Arc;
4
5use libc::{c_char, c_uint, size_t};
6use rustls::server::VerifierBuilderError;
7use rustls::{
8    AlertDescription, CertRevocationListError, CertificateError, EncryptedClientHelloError, Error,
9    InconsistentKeys, InvalidMessage,
10};
11
12use crate::panic::ffi_panic_boundary;
13
14/// A return value for a function that may return either success (0) or a
15/// non-zero value representing an error.
16///
17/// The values should match socket error numbers for your operating system --
18/// for example, the integers for `ETIMEDOUT`, `EAGAIN`, or similar.
19#[repr(transparent)]
20#[derive(Debug, Clone, Copy, PartialEq, Eq)]
21pub struct rustls_io_result(pub libc::c_int);
22
23macro_rules! u32_enum_builder {
24    (
25    $(#[$comment:meta])*
26        EnumName: $enum_name: ident;
27        EnumDefault: $enum_default: ident;
28        EnumVal { $( $enum_var: ident => $enum_val: expr ),* }
29    ) => {
30        $(#[$comment])*
31        #[allow(dead_code)]
32        #[repr(u32)]
33        #[derive(Debug, Clone, Copy, PartialEq, Eq)]
34        pub enum $enum_name {
35            $( $enum_var = $enum_val),*
36        }
37        impl From<u32> for $enum_name {
38            fn from(x: u32) -> Self {
39                match x {
40                    $($enum_val => $enum_name::$enum_var),*
41                    , _ => $enum_name::$enum_default,
42                }
43            }
44        }
45    };
46}
47
48u32_enum_builder! {
49    /// Numeric error codes returned from rustls-ffi API functions.
50    EnumName: rustls_result;
51    EnumDefault: InvalidParameter;
52    EnumVal{
53        Ok => 7000,
54        Io => 7001,
55        NullParameter => 7002,
56        InvalidDnsNameError => 7003,
57        Panic => 7004,
58        CertificateParseError => 7005,
59        PrivateKeyParseError => 7006,
60        InsufficientSize => 7007,
61        NotFound => 7008,
62        InvalidParameter => 7009,
63        UnexpectedEof => 7010,
64        PlaintextEmpty => 7011,
65        AcceptorNotReady => 7012,
66        AlreadyUsed => 7013,
67        CertificateRevocationListParseError => 7014,
68        NoServerCertVerifier => 7015,
69        NoDefaultCryptoProvider => 7016,
70        GetRandomFailed => 7017,
71        NoCertResolver => 7018,
72        HpkeError => 7019,
73        BuilderIncompatibleTlsVersions => 7020,
74
75        // From https://docs.rs/rustls/latest/rustls/enum.Error.html
76        NoCertificatesPresented => 7101,
77        DecryptError => 7102,
78        FailedToGetCurrentTime => 7103,
79        FailedToGetRandomBytes => 7113,
80        HandshakeNotComplete => 7104,
81        PeerSentOversizedRecord => 7105,
82        NoApplicationProtocol => 7106,
83        BadMaxFragmentSize => 7114,
84        UnsupportedNameType => 7115,
85        EncryptError => 7116,
86
87        // Reserved from previous use pre rustls-ffi <0.21.0
88        //  CorruptMessage => 7100,
89        //  CorruptMessagePayload => 7111,
90        //  CertInvalidEncoding => 7117,
91        //  CertInvalidSignatureType => 7118,
92        //  CertInvalidSignature => 7119,
93        //  CertInvalidData => 7120,
94
95        // From InvalidCertificate, with fields that get flattened.
96        // https://docs.rs/rustls/0.21.0/rustls/enum.Error.html#variant.InvalidCertificate
97        CertEncodingBad => 7121,
98        CertExpired => 7122,
99        CertNotYetValid => 7123,
100        CertRevoked => 7124,
101        CertUnhandledCriticalExtension => 7125,
102        CertUnknownIssuer => 7126,
103        CertBadSignature => 7127,
104        CertNotValidForName => 7128,
105        CertInvalidPurpose => 7129,
106        CertApplicationVerificationFailure => 7130,
107        CertOtherError => 7131,
108        CertUnknownRevocationStatus => 7154,
109        CertExpiredRevocationList => 7156, // Last added.
110
111        // From InvalidMessage, with fields that get flattened.
112        // https://docs.rs/rustls/0.21.0/rustls/enum.Error.html#variant.InvalidMessage
113        MessageHandshakePayloadTooLarge => 7133,
114        MessageInvalidCcs => 7134,
115        MessageInvalidContentType => 7135,
116        MessageInvalidCertStatusType => 7136,
117        MessageInvalidCertRequest => 7137,
118        MessageInvalidDhParams => 7138,
119        MessageInvalidEmptyPayload => 7139,
120        MessageInvalidKeyUpdate => 7140,
121        MessageInvalidServerName => 7141,
122        MessageTooLarge => 7142,
123        MessageTooShort => 7143,
124        MessageMissingData => 7144,
125        MessageMissingKeyExchange => 7145,
126        MessageNoSignatureSchemes => 7146,
127        MessageTrailingData => 7147,
128        MessageUnexpectedMessage => 7148,
129        MessageUnknownProtocolVersion => 7149,
130        MessageUnsupportedCompression => 7150,
131        MessageUnsupportedCurveType => 7151,
132        MessageUnsupportedKeyExchangeAlgorithm => 7152,
133        MessageInvalidOther => 7153,
134        MessageCertificatePayloadTooLarge => 7155,
135
136        // From Error, with fields that get dropped.
137        PeerIncompatibleError => 7107,
138        PeerMisbehavedError => 7108,
139        InappropriateMessage => 7109,
140        InappropriateHandshakeMessage => 7110,
141        General => 7112,
142
143        // From Error, with fields that get flattened.
144        // https://docs.rs/rustls/latest/rustls/internal/msgs/enums/enum.AlertDescription.html
145        AlertCloseNotify => 7200,
146        AlertUnexpectedMessage => 7201,
147        AlertBadRecordMac => 7202,
148        AlertDecryptionFailed => 7203,
149        AlertRecordOverflow => 7204,
150        AlertDecompressionFailure => 7205,
151        AlertHandshakeFailure => 7206,
152        AlertNoCertificate => 7207,
153        AlertBadCertificate => 7208,
154        AlertUnsupportedCertificate => 7209,
155        AlertCertificateRevoked => 7210,
156        AlertCertificateExpired => 7211,
157        AlertCertificateUnknown => 7212,
158        AlertIllegalParameter => 7213,
159        AlertUnknownCA => 7214,
160        AlertAccessDenied => 7215,
161        AlertDecodeError => 7216,
162        AlertDecryptError => 7217,
163        AlertExportRestriction => 7218,
164        AlertProtocolVersion => 7219,
165        AlertInsufficientSecurity => 7220,
166        AlertInternalError => 7221,
167        AlertInappropriateFallback => 7222,
168        AlertUserCanceled => 7223,
169        AlertNoRenegotiation => 7224,
170        AlertMissingExtension => 7225,
171        AlertUnsupportedExtension => 7226,
172        AlertCertificateUnobtainable => 7227,
173        AlertUnrecognisedName => 7228,
174        AlertBadCertificateStatusResponse => 7229,
175        AlertBadCertificateHashValue => 7230,
176        AlertUnknownPSKIdentity => 7231,
177        AlertCertificateRequired => 7232,
178        AlertNoApplicationProtocol => 7233,
179        AlertUnknown => 7234,
180
181        // Reserved from previous use pre rustls-ffi <0.22.0
182        // CertSCTMalformed => 7319,
183        // CertSCTInvalidSignature => 7320,
184        // CertSCTTimestampInFuture => 7321,
185        // CertSCTUnsupportedVersion => 7322,
186        // CertSCTUnknownLog => 7323,
187
188        // From InvalidCertRevocationList, with fields that get flattened.
189        // https://docs.rs/rustls/0.21.6/rustls/enum.Error.html#variant.InvalidCertRevocationList
190        CertRevocationListBadSignature => 7400,
191        CertRevocationListInvalidCrlNumber => 7401,
192        CertRevocationListInvalidRevokedCertSerialNumber => 7402,
193        CertRevocationListIssuerInvalidForCrl => 7403,
194        CertRevocationListOtherError => 7404,
195        CertRevocationListParseError => 7405,
196        CertRevocationListUnsupportedCrlVersion => 7406,
197        CertRevocationListUnsupportedCriticalExtension => 7407,
198        CertRevocationListUnsupportedDeltaCrl => 7408,
199        CertRevocationListUnsupportedIndirectCrl => 7409,
200        CertRevocationListUnsupportedRevocationReason => 7410,
201
202        // From ClientCertVerifierBuilderError, with fields that get flattened.
203        ClientCertVerifierBuilderNoRootAnchors => 7500,
204
205        // From InconsistentKeys, with fields that get flattened.
206        InconsistentKeysKeysMismatch => 7600,
207        InconsistentKeysUnknown => 7601,
208
209        // From InvalidEncryptedClientHello, with fields that get flattened.
210        InvalidEncryptedClientHelloInvalidConfigList => 7700,
211        InvalidEncryptedClientHelloNoCompatibleConfig => 7701,
212        InvalidEncryptedClientHelloSniRequired => 7702
213    }
214}
215
216impl rustls_result {
217    /// After a rustls function returns an error, you may call
218    /// this to get a pointer to a buffer containing a detailed error
219    /// message.
220    ///
221    /// The contents of the error buffer will be out_n bytes long,
222    /// UTF-8 encoded, and not NUL-terminated.
223    #[no_mangle]
224    pub extern "C" fn rustls_error(
225        result: c_uint,
226        buf: *mut c_char,
227        len: size_t,
228        out_n: *mut size_t,
229    ) {
230        ffi_panic_boundary! {
231            if buf.is_null() {
232                return;
233            }
234            if out_n.is_null() {
235                return;
236            }
237            let error_str = rustls_result::from(result).to_string();
238            let out_len = min(len, error_str.len());
239            unsafe {
240                std::ptr::copy_nonoverlapping(error_str.as_ptr() as *mut c_char, buf, out_len);
241                *out_n = out_len;
242            }
243        }
244    }
245
246    /// Returns true if the `result` is a certificate related error.
247    #[no_mangle]
248    pub extern "C" fn rustls_result_is_cert_error(result: c_uint) -> bool {
249        use rustls_result::*;
250        matches!(
251            rustls_result::from(result),
252            CertEncodingBad
253                | CertExpired
254                | CertNotYetValid
255                | CertRevoked
256                | CertUnhandledCriticalExtension
257                | CertUnknownIssuer
258                | CertUnknownRevocationStatus
259                | CertBadSignature
260                | CertNotValidForName
261                | CertInvalidPurpose
262                | CertApplicationVerificationFailure
263                | CertOtherError
264        )
265    }
266}
267
268impl Display for rustls_result {
269    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
270        use rustls::AlertDescription as alert;
271        use rustls_result::*;
272
273        match self {
274            // These variants are local to this glue layer.
275            Ok => write!(f, "OK"),
276            Io => write!(f, "I/O error"),
277            NullParameter => write!(f, "a parameter was NULL"),
278            InvalidDnsNameError => write!(
279                f,
280                "server name was malformed (not a valid hostname or IP address)"
281            ),
282            Panic => write!(f, "a Rust component panicked"),
283            CertificateParseError => write!(f, "error parsing certificate"),
284            PrivateKeyParseError => write!(f, "error parsing private key"),
285            InsufficientSize => write!(f, "provided buffer is of insufficient size"),
286            NotFound => write!(f, "the item was not found"),
287            InvalidParameter => write!(f, "a parameter had an invalid value"),
288            UnexpectedEof => write!(
289                f,
290                "peer closed TCP connection without first closing TLS connection"
291            ),
292            PlaintextEmpty => write!(
293                f,
294                "no plaintext available; call rustls_connection_read_tls again"
295            ),
296            AcceptorNotReady => write!(
297                f,
298                "rustls_acceptor not ready yet; read more TLS bytes into it"
299            ),
300            AlreadyUsed => write!(
301                f,
302                "tried to use a rustls struct after it had been converted to another struct"
303            ),
304            CertificateRevocationListParseError => {
305                write!(f, "error parsing certificate revocation list (CRL)",)
306            }
307            NoServerCertVerifier => {
308                write!(
309                    f,
310                    "no server certificate verifier was configured on the client config builder"
311                )
312            }
313            NoDefaultCryptoProvider => {
314                write!(
315                    f,
316                    "no default process-wide crypto provider has been installed"
317                )
318            }
319            GetRandomFailed => {
320                write!(f, "failed to get random bytes from the crypto provider")
321            }
322            NoCertResolver => {
323                write!(f, "no certificate resolver was configured")
324            }
325            HpkeError => {
326                write!(f, "an error occurred with the selected HPKE suite")
327            }
328            BuilderIncompatibleTlsVersions => {
329                write!(
330                    f,
331                    "the client config builder specifies incompatible TLS versions for the requested feature"
332                )
333            }
334
335            CertEncodingBad => Error::InvalidCertificate(CertificateError::BadEncoding).fmt(f),
336            CertExpired => Error::InvalidCertificate(CertificateError::Expired).fmt(f),
337            CertNotYetValid => Error::InvalidCertificate(CertificateError::NotValidYet).fmt(f),
338            CertRevoked => Error::InvalidCertificate(CertificateError::Revoked).fmt(f),
339            CertUnhandledCriticalExtension => {
340                Error::InvalidCertificate(CertificateError::UnhandledCriticalExtension).fmt(f)
341            }
342            CertUnknownIssuer => Error::InvalidCertificate(CertificateError::UnknownIssuer).fmt(f),
343            CertBadSignature => Error::InvalidCertificate(CertificateError::BadSignature).fmt(f),
344            CertNotValidForName => {
345                Error::InvalidCertificate(CertificateError::NotValidForName).fmt(f)
346            }
347            CertInvalidPurpose => {
348                Error::InvalidCertificate(CertificateError::InvalidPurpose).fmt(f)
349            }
350            CertApplicationVerificationFailure => {
351                Error::InvalidCertificate(CertificateError::ApplicationVerificationFailure).fmt(f)
352            }
353            CertUnknownRevocationStatus => {
354                Error::InvalidCertificate(CertificateError::UnknownRevocationStatus).fmt(f)
355            }
356            CertExpiredRevocationList => {
357                Error::InvalidCertificate(CertificateError::ExpiredRevocationList).fmt(f)
358            }
359            CertOtherError => write!(f, "unknown certificate error"),
360
361            // These variants correspond to a rustls::Error variant with a field,
362            // where generating an arbitrary field would produce a confusing error
363            // message. So we reproduce a simplified error string.
364            InappropriateMessage => write!(f, "received unexpected message"),
365            InappropriateHandshakeMessage => write!(f, "received unexpected handshake message"),
366
367            MessageHandshakePayloadTooLarge => {
368                Error::InvalidMessage(InvalidMessage::HandshakePayloadTooLarge).fmt(f)
369            }
370            MessageCertificatePayloadTooLarge => {
371                Error::InvalidMessage(InvalidMessage::CertificatePayloadTooLarge).fmt(f)
372            }
373            MessageInvalidContentType => {
374                Error::InvalidMessage(InvalidMessage::InvalidContentType).fmt(f)
375            }
376            MessageInvalidServerName => {
377                Error::InvalidMessage(InvalidMessage::InvalidServerName).fmt(f)
378            }
379            MessageTooLarge => Error::InvalidMessage(InvalidMessage::MessageTooLarge).fmt(f),
380            MessageTooShort => Error::InvalidMessage(InvalidMessage::MessageTooShort).fmt(f),
381            MessageUnknownProtocolVersion => {
382                Error::InvalidMessage(InvalidMessage::UnknownProtocolVersion).fmt(f)
383            }
384            MessageUnsupportedCompression => {
385                Error::InvalidMessage(InvalidMessage::UnsupportedCompression).fmt(f)
386            }
387            MessageInvalidEmptyPayload => {
388                Error::InvalidMessage(InvalidMessage::InvalidEmptyPayload).fmt(f)
389            }
390            MessageInvalidCertStatusType => {
391                Error::InvalidMessage(InvalidMessage::InvalidCertificateStatusType).fmt(f)
392            }
393            MessageInvalidKeyUpdate => {
394                Error::InvalidMessage(InvalidMessage::InvalidKeyUpdate).fmt(f)
395            }
396            MessageUnsupportedCurveType => {
397                Error::InvalidMessage(InvalidMessage::UnsupportedCurveType).fmt(f)
398            }
399
400            // These variants correspond to a InvalidMessage variant with a field where generating an
401            // arbitrary field would produce a confusing error message. So we reproduce a simplified
402            // error string.
403            MessageMissingData => write!(f, "missing data for the named handshake payload value"),
404            MessageTrailingData => write!(
405                f,
406                "trailing data found for the named handshake payload value"
407            ),
408            MessageUnexpectedMessage => write!(f, "peer sent unexpected message type"),
409            MessageUnsupportedKeyExchangeAlgorithm => {
410                write!(f, "peer sent an unsupported key exchange algorithm")
411            }
412
413            // These variants correspond to an InvalidMessage variant where the Debug fmt may not
414            // express enough information, so we provide a friendlier error string.
415            MessageMissingKeyExchange => {
416                write!(f, "peer did not advertise supported key exchange groups")
417            }
418            MessageNoSignatureSchemes => write!(f, "peer sent an empty list of signature schemes"),
419            MessageInvalidDhParams => write!(
420                f,
421                "peer's Diffie-Hellman (DH) parameters could not be decoded"
422            ),
423            MessageInvalidCertRequest => write!(f, "invalid certificate request context"),
424            MessageInvalidCcs => write!(f, "invalid change cipher spec (CCS) payload"),
425            MessageInvalidOther => write!(f, "invalid message"),
426
427            PeerIncompatibleError => write!(f, "peer is incompatible"),
428            PeerMisbehavedError => write!(f, "peer misbehaved"),
429
430            General => write!(f, "general error"),
431
432            NoCertificatesPresented => Error::NoCertificatesPresented.fmt(f),
433            DecryptError => Error::DecryptError.fmt(f),
434            FailedToGetCurrentTime => Error::FailedToGetCurrentTime.fmt(f),
435            FailedToGetRandomBytes => Error::FailedToGetRandomBytes.fmt(f),
436            HandshakeNotComplete => Error::HandshakeNotComplete.fmt(f),
437            PeerSentOversizedRecord => Error::PeerSentOversizedRecord.fmt(f),
438            NoApplicationProtocol => Error::NoApplicationProtocol.fmt(f),
439            BadMaxFragmentSize => Error::BadMaxFragmentSize.fmt(f),
440            UnsupportedNameType => Error::UnsupportedNameType.fmt(f),
441            EncryptError => Error::EncryptError.fmt(f),
442
443            AlertCloseNotify => Error::AlertReceived(alert::CloseNotify).fmt(f),
444            AlertUnexpectedMessage => Error::AlertReceived(alert::UnexpectedMessage).fmt(f),
445            AlertBadRecordMac => Error::AlertReceived(alert::BadRecordMac).fmt(f),
446            AlertDecryptionFailed => Error::AlertReceived(alert::DecryptionFailed).fmt(f),
447            AlertRecordOverflow => Error::AlertReceived(alert::RecordOverflow).fmt(f),
448            AlertDecompressionFailure => Error::AlertReceived(alert::DecompressionFailure).fmt(f),
449            AlertHandshakeFailure => Error::AlertReceived(alert::HandshakeFailure).fmt(f),
450            AlertNoCertificate => Error::AlertReceived(alert::NoCertificate).fmt(f),
451            AlertBadCertificate => Error::AlertReceived(alert::BadCertificate).fmt(f),
452            AlertUnsupportedCertificate => {
453                Error::AlertReceived(alert::UnsupportedCertificate).fmt(f)
454            }
455            AlertCertificateRevoked => Error::AlertReceived(alert::CertificateRevoked).fmt(f),
456            AlertCertificateExpired => Error::AlertReceived(alert::CertificateExpired).fmt(f),
457            AlertCertificateUnknown => Error::AlertReceived(alert::CertificateUnknown).fmt(f),
458            AlertIllegalParameter => Error::AlertReceived(alert::IllegalParameter).fmt(f),
459            AlertUnknownCA => Error::AlertReceived(alert::UnknownCA).fmt(f),
460            AlertAccessDenied => Error::AlertReceived(alert::AccessDenied).fmt(f),
461            AlertDecodeError => Error::AlertReceived(alert::DecodeError).fmt(f),
462            AlertDecryptError => Error::AlertReceived(alert::DecryptError).fmt(f),
463            AlertExportRestriction => Error::AlertReceived(alert::ExportRestriction).fmt(f),
464            AlertProtocolVersion => Error::AlertReceived(alert::ProtocolVersion).fmt(f),
465            AlertInsufficientSecurity => Error::AlertReceived(alert::InsufficientSecurity).fmt(f),
466            AlertInternalError => Error::AlertReceived(alert::InternalError).fmt(f),
467            AlertInappropriateFallback => Error::AlertReceived(alert::InappropriateFallback).fmt(f),
468            AlertUserCanceled => Error::AlertReceived(alert::UserCanceled).fmt(f),
469            AlertNoRenegotiation => Error::AlertReceived(alert::NoRenegotiation).fmt(f),
470            AlertMissingExtension => Error::AlertReceived(alert::MissingExtension).fmt(f),
471            AlertUnsupportedExtension => Error::AlertReceived(alert::UnsupportedExtension).fmt(f),
472            AlertCertificateUnobtainable => {
473                Error::AlertReceived(alert::CertificateUnobtainable).fmt(f)
474            }
475            AlertUnrecognisedName => Error::AlertReceived(alert::UnrecognisedName).fmt(f),
476            AlertBadCertificateStatusResponse => {
477                Error::AlertReceived(alert::BadCertificateStatusResponse).fmt(f)
478            }
479            AlertBadCertificateHashValue => {
480                Error::AlertReceived(alert::BadCertificateHashValue).fmt(f)
481            }
482            AlertUnknownPSKIdentity => Error::AlertReceived(alert::UnknownPSKIdentity).fmt(f),
483            AlertCertificateRequired => Error::AlertReceived(alert::CertificateRequired).fmt(f),
484            AlertNoApplicationProtocol => Error::AlertReceived(alert::NoApplicationProtocol).fmt(f),
485            AlertUnknown => Error::AlertReceived(alert::Unknown(0)).fmt(f),
486
487            CertRevocationListBadSignature => {
488                Error::InvalidCertRevocationList(CertRevocationListError::BadSignature).fmt(f)
489            }
490            CertRevocationListInvalidCrlNumber => {
491                Error::InvalidCertRevocationList(CertRevocationListError::InvalidCrlNumber).fmt(f)
492            }
493            CertRevocationListInvalidRevokedCertSerialNumber => Error::InvalidCertRevocationList(
494                CertRevocationListError::InvalidRevokedCertSerialNumber,
495            )
496            .fmt(f),
497            CertRevocationListIssuerInvalidForCrl => {
498                Error::InvalidCertRevocationList(CertRevocationListError::IssuerInvalidForCrl)
499                    .fmt(f)
500            }
501            CertRevocationListOtherError => {
502                write!(f, "unknown certificate revocation list (CRL) error")
503            }
504            CertRevocationListParseError => {
505                Error::InvalidCertRevocationList(CertRevocationListError::ParseError).fmt(f)
506            }
507            CertRevocationListUnsupportedCrlVersion => {
508                Error::InvalidCertRevocationList(CertRevocationListError::UnsupportedCrlVersion)
509                    .fmt(f)
510            }
511            CertRevocationListUnsupportedCriticalExtension => Error::InvalidCertRevocationList(
512                CertRevocationListError::UnsupportedCriticalExtension,
513            )
514            .fmt(f),
515            CertRevocationListUnsupportedDeltaCrl => {
516                Error::InvalidCertRevocationList(CertRevocationListError::UnsupportedDeltaCrl)
517                    .fmt(f)
518            }
519            CertRevocationListUnsupportedIndirectCrl => {
520                Error::InvalidCertRevocationList(CertRevocationListError::UnsupportedIndirectCrl)
521                    .fmt(f)
522            }
523            CertRevocationListUnsupportedRevocationReason => Error::InvalidCertRevocationList(
524                CertRevocationListError::UnsupportedRevocationReason,
525            )
526            .fmt(f),
527
528            ClientCertVerifierBuilderNoRootAnchors => write!(f, "no root trust anchors provided"),
529
530            InconsistentKeysKeysMismatch => {
531                Error::InconsistentKeys(InconsistentKeys::KeyMismatch).fmt(f)
532            }
533            InconsistentKeysUnknown => Error::InconsistentKeys(InconsistentKeys::Unknown).fmt(f),
534
535            InvalidEncryptedClientHelloInvalidConfigList => {
536                Error::InvalidEncryptedClientHello(EncryptedClientHelloError::InvalidConfigList)
537                    .fmt(f)
538            }
539            InvalidEncryptedClientHelloNoCompatibleConfig => {
540                Error::InvalidEncryptedClientHello(EncryptedClientHelloError::NoCompatibleConfig)
541                    .fmt(f)
542            }
543            InvalidEncryptedClientHelloSniRequired => {
544                Error::InvalidEncryptedClientHello(EncryptedClientHelloError::SniRequired).fmt(f)
545            }
546        }
547    }
548}
549
550pub(crate) fn map_error(input: Error) -> rustls_result {
551    use rustls_result::*;
552
553    match input {
554        Error::InappropriateMessage { .. } => InappropriateMessage,
555        Error::InappropriateHandshakeMessage { .. } => InappropriateHandshakeMessage,
556
557        Error::NoCertificatesPresented => NoCertificatesPresented,
558        Error::DecryptError => DecryptError,
559        Error::PeerIncompatible(_) => PeerIncompatibleError,
560        Error::PeerMisbehaved(_) => PeerMisbehavedError,
561        Error::UnsupportedNameType => UnsupportedNameType,
562        Error::EncryptError => EncryptError,
563
564        Error::InvalidMessage(e) => map_invalid_message_error(e),
565
566        Error::FailedToGetCurrentTime => FailedToGetCurrentTime,
567        Error::FailedToGetRandomBytes => FailedToGetRandomBytes,
568        Error::HandshakeNotComplete => HandshakeNotComplete,
569        Error::PeerSentOversizedRecord => PeerSentOversizedRecord,
570        Error::NoApplicationProtocol => NoApplicationProtocol,
571        Error::BadMaxFragmentSize => BadMaxFragmentSize,
572
573        Error::InvalidCertificate(e) => map_invalid_certificate_error(e),
574
575        Error::General(_) => General,
576
577        Error::AlertReceived(e) => map_alert_error(e),
578
579        Error::InvalidCertRevocationList(e) => map_crl_error(e),
580
581        Error::InconsistentKeys(InconsistentKeys::KeyMismatch) => InconsistentKeysKeysMismatch,
582        Error::InconsistentKeys(InconsistentKeys::Unknown) => InconsistentKeysUnknown,
583
584        Error::InvalidEncryptedClientHello(err) => map_ech_error(err),
585
586        _ => General,
587    }
588}
589
590/// For cert-related rustls_results, turn them into a rustls::Error.
591///
592/// For other inputs, including Ok, return rustls::Error::General.
593pub(crate) fn cert_result_to_error(result: rustls_result) -> Error {
594    use rustls::Error::*;
595    use rustls::OtherError;
596    use rustls_result::*;
597    match result {
598        CertEncodingBad => InvalidCertificate(CertificateError::BadEncoding),
599        CertExpired => InvalidCertificate(CertificateError::Expired),
600        CertNotYetValid => InvalidCertificate(CertificateError::NotValidYet),
601        CertRevoked => InvalidCertificate(CertificateError::Revoked),
602        CertUnhandledCriticalExtension => {
603            InvalidCertificate(CertificateError::UnhandledCriticalExtension)
604        }
605        CertUnknownIssuer => InvalidCertificate(CertificateError::UnknownIssuer),
606        CertBadSignature => InvalidCertificate(CertificateError::BadSignature),
607        CertNotValidForName => InvalidCertificate(CertificateError::NotValidForName),
608        CertInvalidPurpose => InvalidCertificate(CertificateError::InvalidPurpose),
609        CertApplicationVerificationFailure => {
610            InvalidCertificate(CertificateError::ApplicationVerificationFailure)
611        }
612        CertExpiredRevocationList => InvalidCertificate(CertificateError::ExpiredRevocationList),
613        CertOtherError => InvalidCertificate(CertificateError::Other(OtherError(Arc::from(
614            Box::from(""),
615        )))),
616        _ => Error::General("".into()),
617    }
618}
619
620pub(crate) fn map_verifier_builder_error(err: VerifierBuilderError) -> rustls_result {
621    match err {
622        VerifierBuilderError::NoRootAnchors => {
623            rustls_result::ClientCertVerifierBuilderNoRootAnchors
624        }
625        VerifierBuilderError::InvalidCrl(crl_err) => map_crl_error(crl_err),
626        _ => rustls_result::General,
627    }
628}
629
630fn map_alert_error(alert: AlertDescription) -> rustls_result {
631    use rustls_result::*;
632
633    match alert {
634        AlertDescription::CloseNotify => AlertCloseNotify,
635        AlertDescription::UnexpectedMessage => AlertUnexpectedMessage,
636        AlertDescription::BadRecordMac => AlertBadRecordMac,
637        AlertDescription::DecryptionFailed => AlertDecryptionFailed,
638        AlertDescription::RecordOverflow => AlertRecordOverflow,
639        AlertDescription::DecompressionFailure => AlertDecompressionFailure,
640        AlertDescription::HandshakeFailure => AlertHandshakeFailure,
641        AlertDescription::NoCertificate => AlertNoCertificate,
642        AlertDescription::BadCertificate => AlertBadCertificate,
643        AlertDescription::UnsupportedCertificate => AlertUnsupportedCertificate,
644        AlertDescription::CertificateRevoked => AlertCertificateRevoked,
645        AlertDescription::CertificateExpired => AlertCertificateExpired,
646        AlertDescription::CertificateUnknown => AlertCertificateUnknown,
647        AlertDescription::IllegalParameter => AlertIllegalParameter,
648        AlertDescription::UnknownCA => AlertUnknownCA,
649        AlertDescription::AccessDenied => AlertAccessDenied,
650        AlertDescription::DecodeError => AlertDecodeError,
651        AlertDescription::DecryptError => AlertDecryptError,
652        AlertDescription::ExportRestriction => AlertExportRestriction,
653        AlertDescription::ProtocolVersion => AlertProtocolVersion,
654        AlertDescription::InsufficientSecurity => AlertInsufficientSecurity,
655        AlertDescription::InternalError => AlertInternalError,
656        AlertDescription::InappropriateFallback => AlertInappropriateFallback,
657        AlertDescription::UserCanceled => AlertUserCanceled,
658        AlertDescription::NoRenegotiation => AlertNoRenegotiation,
659        AlertDescription::MissingExtension => AlertMissingExtension,
660        AlertDescription::UnsupportedExtension => AlertUnsupportedExtension,
661        AlertDescription::CertificateUnobtainable => AlertCertificateUnobtainable,
662        AlertDescription::UnrecognisedName => AlertUnrecognisedName,
663        AlertDescription::BadCertificateStatusResponse => AlertBadCertificateStatusResponse,
664        AlertDescription::BadCertificateHashValue => AlertBadCertificateHashValue,
665        AlertDescription::UnknownPSKIdentity => AlertUnknownPSKIdentity,
666        AlertDescription::CertificateRequired => AlertCertificateRequired,
667        AlertDescription::NoApplicationProtocol => AlertNoApplicationProtocol,
668        AlertDescription::Unknown(_) => AlertUnknown,
669        _ => AlertUnknown,
670    }
671}
672
673fn map_crl_error(err: CertRevocationListError) -> rustls_result {
674    use rustls_result::*;
675
676    match err {
677        CertRevocationListError::BadSignature => CertRevocationListBadSignature,
678        CertRevocationListError::InvalidCrlNumber => CertRevocationListInvalidCrlNumber,
679        CertRevocationListError::InvalidRevokedCertSerialNumber => {
680            CertRevocationListInvalidRevokedCertSerialNumber
681        }
682        CertRevocationListError::IssuerInvalidForCrl => CertRevocationListIssuerInvalidForCrl,
683        CertRevocationListError::Other(_) => CertRevocationListOtherError,
684        CertRevocationListError::ParseError => CertRevocationListParseError,
685        CertRevocationListError::UnsupportedCrlVersion => CertRevocationListUnsupportedCrlVersion,
686        CertRevocationListError::UnsupportedCriticalExtension => {
687            CertRevocationListUnsupportedCriticalExtension
688        }
689        CertRevocationListError::UnsupportedDeltaCrl => CertRevocationListUnsupportedDeltaCrl,
690        CertRevocationListError::UnsupportedIndirectCrl => CertRevocationListUnsupportedIndirectCrl,
691        CertRevocationListError::UnsupportedRevocationReason => {
692            CertRevocationListUnsupportedRevocationReason
693        }
694        _ => CertRevocationListOtherError,
695    }
696}
697
698fn map_invalid_message_error(err: InvalidMessage) -> rustls_result {
699    use rustls_result::*;
700
701    match err {
702        InvalidMessage::HandshakePayloadTooLarge => MessageHandshakePayloadTooLarge,
703        InvalidMessage::CertificatePayloadTooLarge => MessageCertificatePayloadTooLarge,
704        InvalidMessage::InvalidCcs => MessageInvalidCcs,
705        InvalidMessage::InvalidContentType => MessageInvalidContentType,
706        InvalidMessage::InvalidCertificateStatusType => MessageInvalidCertStatusType,
707        InvalidMessage::InvalidCertRequest => MessageInvalidCertRequest,
708        InvalidMessage::InvalidDhParams => MessageInvalidDhParams,
709        InvalidMessage::InvalidEmptyPayload => MessageInvalidEmptyPayload,
710        InvalidMessage::InvalidKeyUpdate => MessageInvalidKeyUpdate,
711        InvalidMessage::InvalidServerName => MessageInvalidServerName,
712        InvalidMessage::MessageTooLarge => MessageTooLarge,
713        InvalidMessage::MessageTooShort => MessageTooShort,
714        InvalidMessage::MissingData(_) => MessageMissingData,
715        InvalidMessage::MissingKeyExchange => MessageMissingKeyExchange,
716        InvalidMessage::NoSignatureSchemes => MessageNoSignatureSchemes,
717        InvalidMessage::TrailingData(_) => MessageTrailingData,
718        InvalidMessage::UnexpectedMessage(_) => MessageUnexpectedMessage,
719        InvalidMessage::UnknownProtocolVersion => MessageUnknownProtocolVersion,
720        InvalidMessage::UnsupportedCompression => MessageUnsupportedCompression,
721        InvalidMessage::UnsupportedCurveType => MessageUnsupportedCurveType,
722        InvalidMessage::UnsupportedKeyExchangeAlgorithm(_) => MessageUnsupportedCompression,
723        _ => MessageInvalidOther,
724    }
725}
726
727fn map_invalid_certificate_error(err: CertificateError) -> rustls_result {
728    use rustls_result::*;
729
730    match err {
731        CertificateError::BadEncoding => CertEncodingBad,
732        CertificateError::Expired | CertificateError::ExpiredContext { .. } => CertExpired,
733        CertificateError::NotValidYet | CertificateError::NotValidYetContext { .. } => {
734            CertNotYetValid
735        }
736        CertificateError::Revoked => CertRevoked,
737        CertificateError::UnhandledCriticalExtension => CertUnhandledCriticalExtension,
738        CertificateError::UnknownIssuer => CertUnknownIssuer,
739        CertificateError::UnknownRevocationStatus => CertUnknownRevocationStatus,
740        CertificateError::ExpiredRevocationList
741        | CertificateError::ExpiredRevocationListContext { .. } => CertExpiredRevocationList,
742        CertificateError::BadSignature => CertBadSignature,
743        CertificateError::NotValidForName | CertificateError::NotValidForNameContext { .. } => {
744            CertNotValidForName
745        }
746        CertificateError::InvalidPurpose => CertInvalidPurpose,
747        CertificateError::ApplicationVerificationFailure => CertApplicationVerificationFailure,
748        _ => CertOtherError,
749    }
750}
751
752fn map_ech_error(err: EncryptedClientHelloError) -> rustls_result {
753    use rustls_result::*;
754
755    match err {
756        EncryptedClientHelloError::InvalidConfigList => {
757            InvalidEncryptedClientHelloInvalidConfigList
758        }
759        EncryptedClientHelloError::NoCompatibleConfig => {
760            InvalidEncryptedClientHelloNoCompatibleConfig
761        }
762        EncryptedClientHelloError::SniRequired => InvalidEncryptedClientHelloSniRequired,
763        _ => General,
764    }
765}
766
767#[cfg(test)]
768mod tests {
769    use super::*;
770
771    #[test]
772    fn test_rustls_error() {
773        let mut buf = [0 as c_char; 512];
774        let mut n = 0;
775        rustls_result::rustls_error(0, &mut buf as *mut _, buf.len(), &mut n);
776        let output = String::from_utf8(buf[0..n].iter().map(|b| *b as u8).collect()).unwrap();
777        assert_eq!(&output, "a parameter had an invalid value");
778
779        rustls_result::rustls_error(7000, &mut buf as *mut _, buf.len(), &mut n);
780        let output = String::from_utf8(buf[0..n].iter().map(|b| *b as u8).collect()).unwrap();
781        assert_eq!(&output, "OK");
782
783        rustls_result::rustls_error(7101, &mut buf as *mut _, buf.len(), &mut n);
784        let output = String::from_utf8(buf[0..n].iter().map(|b| *b as u8).collect()).unwrap();
785        assert_eq!(&output, "peer sent no certificates");
786    }
787
788    #[test]
789    fn test_rustls_error_into_empty_buffer() {
790        let mut n = 99;
791        rustls_result::rustls_error(0, &mut [] as *mut _, 0, &mut n);
792        assert_eq!(n, 0);
793    }
794
795    #[test]
796    fn test_rustls_result_is_cert_error() {
797        assert!(!rustls_result::rustls_result_is_cert_error(0));
798        assert!(!rustls_result::rustls_result_is_cert_error(7000));
799
800        // Test CertificateError range.
801        for id in 7121..=7131 {
802            assert!(rustls_result::rustls_result_is_cert_error(id));
803        }
804    }
805}