Skip to content

Commit

Permalink
error: replace num_enum with minimal macro rule.
Browse files Browse the repository at this point in the history
The `num_enum` dependency brings with it a large number of transitive
dependencies. Some of those transitive deps now have an aggressive MSRV
of 1.64+.

The existing usage of `num_enum` is very minimal: just one derived trait
for the `rustls_result` enum to provide it with a `From` impl for u32
primitive values.

This commit replaces the `num_enum` crate with a small
`u32_enum_builder!` macro rule loosely based on the Rustls
`enum_builder` macro. Since our use case is narrower, I've simplified
the macro and tailored it to the rustls-ffi use-case.

This approach adds one complication related to `cbindgen`: it now has to
be instructed to expand the `rustls-ffi` crate before generating
bindings in order to find the `rustls_result` enum. Doing this requires
tweaking the `cbindgen.toml` to add a `parse.expand` configuration
setting. Notably this also means `cbindgen` now has to be run with a
nightly `rustc`. Since this is a developer only workflow it shouldn't be
too onerous a requirement.

We're now happily building with Rust 1.60 again and can also breathe
easy knowing we have a slimmer dependency profile!
  • Loading branch information
cpu committed Jun 29, 2023
1 parent 7aa7453 commit c6bed25
Show file tree
Hide file tree
Showing 5 changed files with 167 additions and 133 deletions.
6 changes: 6 additions & 0 deletions .github/workflows/test.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,12 @@ jobs:
- uses: actions/checkout@v2
with:
persist-credentials: false
- name: Install nightly rust toolchain
uses: actions-rs/toolchain@v1
with:
toolchain: nightly
override: true
default: true
- run: touch src/lib.rs
- run: cbindgen --version
- run: make src/rustls.h
Expand Down
1 change: 0 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,6 @@ libc = "0.2"
sct = "0.7"
rustls-pemfile = "0.2.1"
log = "0.4.17"
num_enum = "0.5.10"

[lib]
name = "rustls_ffi"
Expand Down
4 changes: 4 additions & 0 deletions cbindgen.toml
Original file line number Diff line number Diff line change
Expand Up @@ -11,3 +11,7 @@ include = ["rustls_tls_version"]

[defines]
"feature = read_buf" = "DEFINE_READ_BUF"

[parse.expand]
crates = ["rustls-ffi"]
features = ["read_buf"]
287 changes: 156 additions & 131 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ use std::sync::Arc;

use crate::ffi_panic_boundary;
use libc::{c_char, c_uint, size_t};
use num_enum::TryFromPrimitive;
use rustls::{CertificateError, Error, InvalidMessage};

/// A return value for a function that may return either success (0) or a
Expand All @@ -16,6 +15,162 @@ use rustls::{CertificateError, Error, InvalidMessage};
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct rustls_io_result(pub libc::c_int);

macro_rules! u32_enum_builder {
(
$(#[$comment:meta])*
EnumName: $enum_name: ident;
EnumDefault: $enum_default: ident;
EnumVal { $( $enum_var: ident => $enum_val: expr ),* }
) => {
$(#[$comment])*
#[allow(dead_code)]
#[repr(u32)]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum $enum_name {
$( $enum_var = $enum_val),*
}
impl From<u32> for $enum_name {
fn from(x: u32) -> Self {
match x {
$($enum_val => $enum_name::$enum_var),*
, _ => $enum_name::$enum_default,
}
}
}
};
}

u32_enum_builder! {
EnumName: rustls_result;
EnumDefault: InvalidParameter;
EnumVal{
Ok => 7000,
Io => 7001,
NullParameter => 7002,
InvalidDnsNameError => 7003,
Panic => 7004,
CertificateParseError => 7005,
PrivateKeyParseError => 7006,
InsufficientSize => 7007,
NotFound => 7008,
InvalidParameter => 7009,
UnexpectedEof => 7010,
PlaintextEmpty => 7011,
AcceptorNotReady => 7012,
AlreadyUsed => 7013,

// From https://docs.rs/rustls/latest/rustls/enum.Error.html
NoCertificatesPresented => 7101,
DecryptError => 7102,
FailedToGetCurrentTime => 7103,
FailedToGetRandomBytes => 7113,
HandshakeNotComplete => 7104,
PeerSentOversizedRecord => 7105,
NoApplicationProtocol => 7106,
BadMaxFragmentSize => 7114,
UnsupportedNameType => 7115,
EncryptError => 7116,

// Reserved from previous use pre rustls-ffi <0.21.0
// CorruptMessage => 7100,
// CorruptMessagePayload => 7111,
// CertInvalidEncoding => 7117,
// CertInvalidSignatureType => 7118,
// CertInvalidSignature => 7119,
// CertInvalidData => 7120,

// From InvalidCertificate, with fields that get flattened.
// https://docs.rs/rustls/0.21.0/rustls/enum.Error.html#variant.InvalidCertificate
CertEncodingBad => 7121,
CertExpired => 7122,
CertNotYetValid => 7123,
CertRevoked => 7124,
CertUnhandledCriticalExtension => 7125,
CertUnknownIssuer => 7126,
CertBadSignature => 7127,
CertNotValidForName => 7128,
CertInvalidPurpose => 7129,
CertApplicationVerificationFailure => 7130,
CertOtherError => 7131,

// From InvalidMessage, with fields that get flattened.
// https://docs.rs/rustls/0.21.0/rustls/enum.Error.html#variant.InvalidMessage
MessageHandshakePayloadTooLarge => 7133,
MessageInvalidCcs => 7134,
MessageInvalidContentType => 7135,
MessageInvalidCertStatusType => 7136,
MessageInvalidCertRequest => 7137,
MessageInvalidDhParams => 7138,
MessageInvalidEmptyPayload => 7139,
MessageInvalidKeyUpdate => 7140,
MessageInvalidServerName => 7141,
MessageTooLarge => 7142,
MessageTooShort => 7143,
MessageMissingData => 7144,
MessageMissingKeyExchange => 7145,
MessageNoSignatureSchemes => 7146,
MessageTrailingData => 7147,
MessageUnexpectedMessage => 7148,
MessageUnknownProtocolVersion => 7149,
MessageUnsupportedCompression => 7150,
MessageUnsupportedCurveType => 7151,
MessageUnsupportedKeyExchangeAlgorithm => 7152,
MessageInvalidOther => 7153, // Last added.

// From Error, with fields that get dropped.
PeerIncompatibleError => 7107,
PeerMisbehavedError => 7108,
InappropriateMessage => 7109,
InappropriateHandshakeMessage => 7110,
General => 7112,

// From Error, with fields that get flattened.
// https://docs.rs/rustls/latest/rustls/internal/msgs/enums/enum.AlertDescription.html
AlertCloseNotify => 7200,
AlertUnexpectedMessage => 7201,
AlertBadRecordMac => 7202,
AlertDecryptionFailed => 7203,
AlertRecordOverflow => 7204,
AlertDecompressionFailure => 7205,
AlertHandshakeFailure => 7206,
AlertNoCertificate => 7207,
AlertBadCertificate => 7208,
AlertUnsupportedCertificate => 7209,
AlertCertificateRevoked => 7210,
AlertCertificateExpired => 7211,
AlertCertificateUnknown => 7212,
AlertIllegalParameter => 7213,
AlertUnknownCA => 7214,
AlertAccessDenied => 7215,
AlertDecodeError => 7216,
AlertDecryptError => 7217,
AlertExportRestriction => 7218,
AlertProtocolVersion => 7219,
AlertInsufficientSecurity => 7220,
AlertInternalError => 7221,
AlertInappropriateFallback => 7222,
AlertUserCanceled => 7223,
AlertNoRenegotiation => 7224,
AlertMissingExtension => 7225,
AlertUnsupportedExtension => 7226,
AlertCertificateUnobtainable => 7227,
AlertUnrecognisedName => 7228,
AlertBadCertificateStatusResponse => 7229,
AlertBadCertificateHashValue => 7230,
AlertUnknownPSKIdentity => 7231,
AlertCertificateRequired => 7232,
AlertNoApplicationProtocol => 7233,
AlertUnknown => 7234,

// https://docs.rs/sct/latest/sct/enum.Error.html
CertSCTMalformed => 7319,
CertSCTInvalidSignature => 7320,
CertSCTTimestampInFuture => 7321,
CertSCTUnsupportedVersion => 7322,
CertSCTUnknownLog => 7323
}
}

impl rustls_result {
/// After a rustls function returns an error, you may call
/// this to get a pointer to a buffer containing a detailed error
Expand Down Expand Up @@ -135,136 +290,6 @@ fn test_rustls_result_is_cert_error() {
}
}

#[allow(dead_code)]
#[repr(u32)]
#[derive(Debug, TryFromPrimitive, Clone, Copy, PartialEq, Eq)]
pub enum rustls_result {
Ok = 7000,
Io = 7001,
NullParameter = 7002,
InvalidDnsNameError = 7003,
Panic = 7004,
CertificateParseError = 7005,
PrivateKeyParseError = 7006,
InsufficientSize = 7007,
NotFound = 7008,
InvalidParameter = 7009,
UnexpectedEof = 7010,
PlaintextEmpty = 7011,
AcceptorNotReady = 7012,
AlreadyUsed = 7013,

// From https://docs.rs/rustls/latest/rustls/enum.Error.html
NoCertificatesPresented = 7101,
DecryptError = 7102,
FailedToGetCurrentTime = 7103,
FailedToGetRandomBytes = 7113,
HandshakeNotComplete = 7104,
PeerSentOversizedRecord = 7105,
NoApplicationProtocol = 7106,
BadMaxFragmentSize = 7114,
UnsupportedNameType = 7115,
EncryptError = 7116,

// Reserved from previous use pre rustls-ffi <0.21.0
// CorruptMessage = 7100,
// CorruptMessagePayload = 7111,
// CertInvalidEncoding = 7117,
// CertInvalidSignatureType = 7118,
// CertInvalidSignature = 7119,
// CertInvalidData = 7120,

// From InvalidCertificate, with fields that get flattened.
// https://docs.rs/rustls/0.21.0/rustls/enum.Error.html#variant.InvalidCertificate
CertEncodingBad = 7121,
CertExpired = 7122,
CertNotYetValid = 7123,
CertRevoked = 7124,
CertUnhandledCriticalExtension = 7125,
CertUnknownIssuer = 7126,
CertBadSignature = 7127,
CertNotValidForName = 7128,
CertInvalidPurpose = 7129,
CertApplicationVerificationFailure = 7130,
CertOtherError = 7131,

// From InvalidMessage, with fields that get flattened.
// https://docs.rs/rustls/0.21.0/rustls/enum.Error.html#variant.InvalidMessage
MessageHandshakePayloadTooLarge = 7133,
MessageInvalidCcs = 7134,
MessageInvalidContentType = 7135,
MessageInvalidCertStatusType = 7136,
MessageInvalidCertRequest = 7137,
MessageInvalidDhParams = 7138,
MessageInvalidEmptyPayload = 7139,
MessageInvalidKeyUpdate = 7140,
MessageInvalidServerName = 7141,
MessageTooLarge = 7142,
MessageTooShort = 7143,
MessageMissingData = 7144,
MessageMissingKeyExchange = 7145,
MessageNoSignatureSchemes = 7146,
MessageTrailingData = 7147,
MessageUnexpectedMessage = 7148,
MessageUnknownProtocolVersion = 7149,
MessageUnsupportedCompression = 7150,
MessageUnsupportedCurveType = 7151,
MessageUnsupportedKeyExchangeAlgorithm = 7152,
MessageInvalidOther = 7153, // Last added.

// From Error, with fields that get dropped.
PeerIncompatibleError = 7107,
PeerMisbehavedError = 7108,
InappropriateMessage = 7109,
InappropriateHandshakeMessage = 7110,
General = 7112,

// From Error, with fields that get flattened.
// https://docs.rs/rustls/latest/rustls/internal/msgs/enums/enum.AlertDescription.html
AlertCloseNotify = 7200,
AlertUnexpectedMessage = 7201,
AlertBadRecordMac = 7202,
AlertDecryptionFailed = 7203,
AlertRecordOverflow = 7204,
AlertDecompressionFailure = 7205,
AlertHandshakeFailure = 7206,
AlertNoCertificate = 7207,
AlertBadCertificate = 7208,
AlertUnsupportedCertificate = 7209,
AlertCertificateRevoked = 7210,
AlertCertificateExpired = 7211,
AlertCertificateUnknown = 7212,
AlertIllegalParameter = 7213,
AlertUnknownCA = 7214,
AlertAccessDenied = 7215,
AlertDecodeError = 7216,
AlertDecryptError = 7217,
AlertExportRestriction = 7218,
AlertProtocolVersion = 7219,
AlertInsufficientSecurity = 7220,
AlertInternalError = 7221,
AlertInappropriateFallback = 7222,
AlertUserCanceled = 7223,
AlertNoRenegotiation = 7224,
AlertMissingExtension = 7225,
AlertUnsupportedExtension = 7226,
AlertCertificateUnobtainable = 7227,
AlertUnrecognisedName = 7228,
AlertBadCertificateStatusResponse = 7229,
AlertBadCertificateHashValue = 7230,
AlertUnknownPSKIdentity = 7231,
AlertCertificateRequired = 7232,
AlertNoApplicationProtocol = 7233,
AlertUnknown = 7234,

// https://docs.rs/sct/latest/sct/enum.Error.html
CertSCTMalformed = 7319,
CertSCTInvalidSignature = 7320,
CertSCTTimestampInFuture = 7321,
CertSCTUnsupportedVersion = 7322,
CertSCTUnknownLog = 7323,
}

pub(crate) fn map_error(input: rustls::Error) -> rustls_result {
use rustls::AlertDescription as alert;
use rustls_result::*;
Expand Down
2 changes: 1 addition & 1 deletion src/session.rs
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ impl SessionStoreBroker {
Err(_) => return false,
};
let result = unsafe { cb(userdata, &key, &value) };
result == rustls_result::Ok as u32
rustls_result::from(result) == rustls_result::Ok
}
}

Expand Down

0 comments on commit c6bed25

Please sign in to comment.