Skip to main content

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