Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Avoid enums with FFI to avoid UB #12

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
target/
**/*.rs.bk
Cargo.lock
.DS_Store
7 changes: 4 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -30,12 +30,13 @@ buildlib = ["libyubihsm-sys/buildlib"]

[dependencies]
lazy_static = "1.4.0"
log = "0.3.8"
regex = "0.2.2"
log = "0.4.14"
regex = "1.5.4"
rustc-serialize = "0.3.24"
num_enum = "0.5.6"

[dev-dependencies]
base64 = "0.7.0"
base64 = "0.13.0"

[dependencies.libyubihsm-sys]
path = "libyubihsm-sys"
Expand Down
7 changes: 5 additions & 2 deletions libyubihsm-sys/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ categories = ["external-ffi-bindings"]
default = ["pkg-config"]
buildlib = ["cmake"]

[dependencies]
num_enum = "0.5.6"

[build-dependencies]
cmake = {version = "0.1", optional = true}
pkg-config = {version = "0.3.11", optional = true}
cmake = {version = "0.1.48", optional = true}
pkg-config = {version = "0.3.24", optional = true}
109 changes: 73 additions & 36 deletions libyubihsm-sys/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,19 @@
* limitations under the License.
*/

extern crate num_enum;

use std::error;
use std::fmt;
use std::os::raw::c_int;

/// FFI return type of the public functions
pub type yh_rc = c_int;

#[repr(i32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, num_enum::FromPrimitive)]
/// Return type of the public functions
pub enum yh_rc {
pub enum yh_rc_enum {
/// Successs
YHR_SUCCESS = 0,
/// Memory error
Expand Down Expand Up @@ -81,11 +87,21 @@ pub enum yh_rc {
YHR_DEVICE_OBJECT_EXISTS = -28,
/// Connector operation failed
YHR_CONNECTOR_ERROR = -29,
/// Return value when encountering SSH CA constraint violation
YHR_DEVICE_SSH_CA_CONSTRAINT_VIOLATION = -30,
/// Return value when an algorithm is disabled
YHR_DEVICE_ALGORITHM_DISABLED = -31,
#[num_enum(default)]
/// Return value for unknown error codes
YHR_UNKNOWN_ERROR = -99
}

#[derive(Clone, Copy, Debug)]
/// Rust enum of possible error types
pub enum Error {
/// Success
Success,

/// Unable to allocate memory
Memory,

Expand Down Expand Up @@ -172,45 +188,58 @@ pub enum Error {

/// Connector operation failed
ConnectorError,

/// Return value when encountering SSH CA constraint violation
SshCaConstraintViolation,

/// Return value when an algorithm is disabled
AlgorithmDisabled,

/// Unknown error
Unknown
}

fn code_to_err(return_code: yh_rc) -> Error {
fn code_to_err(return_code: yh_rc_enum) -> Error {
match return_code {
yh_rc::YHR_MEMORY => Error::Memory,
yh_rc::YHR_INIT_ERROR => Error::InitError,
yh_rc::YHR_NET_ERROR => Error::NetworkError,
yh_rc::YHR_CONNECTOR_NOT_FOUND => Error::ConnectorNotFound,
yh_rc::YHR_INVALID_PARAMS => Error::InvalidParams,
yh_rc::YHR_WRONG_LENGTH => Error::WrongLength,
yh_rc::YHR_BUFFER_TOO_SMALL => Error::BufferTooSmall,
yh_rc::YHR_CRYPTOGRAM_MISMATCH => Error::CryptogramMismatch,
yh_rc::YHR_AUTH_SESSION_ERROR => Error::AuthSessionError,
yh_rc::YHR_MAC_MISMATCH => Error::MacMismatch,
yh_rc::YHR_DEVICE_OK => Error::DeviceOk,
yh_rc::YHR_DEVICE_INV_COMMAND => Error::DeviceInvalidCommand,
yh_rc::YHR_DEVICE_INV_DATA => Error::DeviceInvalidData,
yh_rc::YHR_DEVICE_INV_SESSION => Error::DeviceInvalidSession,
yh_rc::YHR_DEVICE_AUTH_FAIL => Error::DeviceAuthenticationFailed,
yh_rc::YHR_DEVICE_SESSIONS_FULL => Error::DeviceSessionsFull,
yh_rc::YHR_DEVICE_SESSION_FAILED => Error::DeviceSessionFailed,
yh_rc::YHR_DEVICE_STORAGE_FAILED => Error::DeviceStorageFailed,
yh_rc::YHR_DEVICE_WRONG_LENGTH => Error::DeviceWrongLength,
yh_rc::YHR_DEVICE_INV_PERMISSION => Error::DeviceInvalidPermissions,
yh_rc::YHR_DEVICE_LOG_FULL => Error::DeviceLogFull,
yh_rc::YHR_DEVICE_OBJ_NOT_FOUND => Error::DeviceObjectNotFound,
yh_rc::YHR_DEVICE_ID_ILLEGAL => Error::DeviceIdIllegal,
yh_rc::YHR_DEVICE_INVALID_OTP => Error::DeviceInvalidOtp,
yh_rc::YHR_DEVICE_DEMO_MODE => Error::DeviceDemoMode,
yh_rc::YHR_DEVICE_CMD_UNEXECUTED => Error::DeviceCmdUnexecuted,
yh_rc::YHR_GENERIC_ERROR => Error::GenericError,
yh_rc::YHR_DEVICE_OBJECT_EXISTS => Error::ObjectExists,
yh_rc::YHR_CONNECTOR_ERROR => Error::ConnectorError,
yh_rc::YHR_SUCCESS => unreachable!(),
yh_rc_enum::YHR_SUCCESS => Error::Success,
yh_rc_enum::YHR_MEMORY => Error::Memory,
yh_rc_enum::YHR_INIT_ERROR => Error::InitError,
yh_rc_enum::YHR_NET_ERROR => Error::NetworkError,
yh_rc_enum::YHR_CONNECTOR_NOT_FOUND => Error::ConnectorNotFound,
yh_rc_enum::YHR_INVALID_PARAMS => Error::InvalidParams,
yh_rc_enum::YHR_WRONG_LENGTH => Error::WrongLength,
yh_rc_enum::YHR_BUFFER_TOO_SMALL => Error::BufferTooSmall,
yh_rc_enum::YHR_CRYPTOGRAM_MISMATCH => Error::CryptogramMismatch,
yh_rc_enum::YHR_AUTH_SESSION_ERROR => Error::AuthSessionError,
yh_rc_enum::YHR_MAC_MISMATCH => Error::MacMismatch,
yh_rc_enum::YHR_DEVICE_OK => Error::DeviceOk,
yh_rc_enum::YHR_DEVICE_INV_COMMAND => Error::DeviceInvalidCommand,
yh_rc_enum::YHR_DEVICE_INV_DATA => Error::DeviceInvalidData,
yh_rc_enum::YHR_DEVICE_INV_SESSION => Error::DeviceInvalidSession,
yh_rc_enum::YHR_DEVICE_AUTH_FAIL => Error::DeviceAuthenticationFailed,
yh_rc_enum::YHR_DEVICE_SESSIONS_FULL => Error::DeviceSessionsFull,
yh_rc_enum::YHR_DEVICE_SESSION_FAILED => Error::DeviceSessionFailed,
yh_rc_enum::YHR_DEVICE_STORAGE_FAILED => Error::DeviceStorageFailed,
yh_rc_enum::YHR_DEVICE_WRONG_LENGTH => Error::DeviceWrongLength,
yh_rc_enum::YHR_DEVICE_INV_PERMISSION => Error::DeviceInvalidPermissions,
yh_rc_enum::YHR_DEVICE_LOG_FULL => Error::DeviceLogFull,
yh_rc_enum::YHR_DEVICE_OBJ_NOT_FOUND => Error::DeviceObjectNotFound,
yh_rc_enum::YHR_DEVICE_ID_ILLEGAL => Error::DeviceIdIllegal,
yh_rc_enum::YHR_DEVICE_INVALID_OTP => Error::DeviceInvalidOtp,
yh_rc_enum::YHR_DEVICE_DEMO_MODE => Error::DeviceDemoMode,
yh_rc_enum::YHR_DEVICE_CMD_UNEXECUTED => Error::DeviceCmdUnexecuted,
yh_rc_enum::YHR_GENERIC_ERROR => Error::GenericError,
yh_rc_enum::YHR_DEVICE_OBJECT_EXISTS => Error::ObjectExists,
yh_rc_enum::YHR_CONNECTOR_ERROR => Error::ConnectorError,
yh_rc_enum::YHR_DEVICE_SSH_CA_CONSTRAINT_VIOLATION => Error::SshCaConstraintViolation,
yh_rc_enum::YHR_DEVICE_ALGORITHM_DISABLED => Error::AlgorithmDisabled,
yh_rc_enum::YHR_UNKNOWN_ERROR => Error::Unknown
}
}

fn code_to_str(return_code: Error) -> &'static str {
match return_code {
Error::Success => "Success",
Error::Memory => "Unable to allocate memory",
Error::InitError => "Unable to initialize the libyubihsm",
Error::NetworkError => "Libcurl error",
Expand Down Expand Up @@ -240,12 +269,20 @@ fn code_to_str(return_code: Error) -> &'static str {
Error::GenericError => "Generic error",
Error::ObjectExists => "Object with given ID and type already exists",
Error::ConnectorError => "Connector operation failed",
Error::SshCaConstraintViolation => "SSH CA constraint violation",
Error::AlgorithmDisabled => "Algorithm disabled",
Error::Unknown => "Unknown error"
}
}

impl From<yh_rc> for Error {
fn from(return_code: yh_rc) -> Self {
Self::from(yh_rc_enum::from(return_code))
}
}

impl Error {
/// Create an Error type from a `yh_rc` value
pub fn new(return_code: yh_rc) -> Self {
impl From<yh_rc_enum> for Error {
fn from(return_code: yh_rc_enum) -> Self {
code_to_err(return_code)
}
}
Expand Down
76 changes: 30 additions & 46 deletions libyubihsm-sys/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@

//! FFI bindings for libyubihsm

extern crate num_enum;

pub use self::error::*;

use std::os::raw::{c_char, c_int, c_uint};
Expand Down Expand Up @@ -157,10 +159,13 @@ fn bindgen_test_layout_yh_capabilities() {
);
}

/// Raw Command byte definitions
pub type yh_cmd = c_uint;

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, num_enum::TryFromPrimitive)]
/// Command byte definitions
pub enum yh_cmd {
pub enum yh_cmd_enum {
/// Echo, request
YHC_ECHO = 0x01,
/// Echo, response
Expand Down Expand Up @@ -369,10 +374,14 @@ pub enum yh_cmd {
YHC_ERROR = 0x7f,
}

/// Raw Object types
pub type yh_object_type = c_uint;

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, num_enum::FromPrimitive)]
/// Object types
pub enum yh_object_type {
pub enum yh_object_type_enum {
#[num_enum(default)]
/// Any object type (convenience value, not in libyubihsm)
YH_ANY = 0x00,
/// Opaque object
Expand All @@ -393,17 +402,15 @@ pub enum yh_object_type {
YH_PUBLIC_KEY = 0x83,
}

impl Default for yh_object_type {
fn default() -> yh_object_type {
yh_object_type::YH_ANY
}
}
/// Raw Algorithms
pub type yh_algorithm = c_uint;

#[repr(u32)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, num_enum::FromPrimitive)]
/// Algorithms
pub enum yh_algorithm {
pub enum yh_algorithm_enum {
/// Any algorithm (convenience value, not in libyubihsm)
#[num_enum(default)]
YH_ALGO_ANY = 0,
/// RSA PKCS1v1.5 with SHA1
YH_ALGO_RSA_PKCS1_SHA1 = 1,
Expand Down Expand Up @@ -501,28 +508,30 @@ pub enum yh_algorithm {
YH_ALGO_EC_P224 = 47,
/// RSA PKCS1v1.5 decrypt
YH_ALGO_RSA_PKCS1_DECRYPT = 48,
/// ec-p256-yubico-authentication
YH_ALGO_EC_P256_YUBICO_AUTHENTICATION = 49,
}

impl Default for yh_algorithm {
fn default() -> yh_algorithm {
yh_algorithm::YH_ALGO_ANY
}
}
/// Raw Device-global options
pub type yh_option = c_uint;

#[repr(u32)]
/// Device-global options
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum yh_option {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, num_enum::TryFromPrimitive)]
pub enum yh_option_enum {
/// Forced audit mode
YH_OPTION_FORCE_AUDIT = 1,
/// Audit logging per command
YH_OPTION_COMMAND_AUDIT = 3,
}

/// Raw Connector options
pub type yh_connector_option = c_uint;

#[repr(u32)]
/// Connector options
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
pub enum yh_connector_option {
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash, num_enum::TryFromPrimitive)]
pub enum yh_connector_option_enum {
/// File with CA certificate to validate the connector with (const char *) not
/// implemented on Windows
YH_CONNECTOR_HTTPS_CA = 1,
Expand Down Expand Up @@ -680,7 +689,7 @@ impl ToString for yh_label {
String::from(
unsafe { ::std::ffi::CStr::from_ptr(&self.label[0]) }
.to_str()
.unwrap(),
.unwrap_or_default(),
)
}
}
Expand Down Expand Up @@ -902,13 +911,6 @@ fn bindgen_test_layout_yh_cap() {
)
);
}

extern "C" {
#[link_name = "yh_capability"]
/// Object capabilities
pub static mut yh_capability: [yh_cap; 47usize];
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
/// Algorithms
Expand Down Expand Up @@ -955,12 +957,6 @@ fn bindgen_test_layout_yh_algo() {
);
}

extern "C" {
#[link_name = "yh_algorithms"]
/// Object and function algorithm
pub static mut yh_algorithms: [yh_algo; 46usize];
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
/// Object types
Expand Down Expand Up @@ -1007,12 +1003,6 @@ fn bindgen_test_layout_yh_ot() {
);
}

extern "C" {
#[link_name = "yh_types"]
/// Object type
pub static mut yh_types: [yh_ot; 7usize];
}

#[repr(C)]
#[derive(Debug, Clone, Copy)]
/// Options
Expand Down Expand Up @@ -1059,12 +1049,6 @@ fn bindgen_test_layout_yh_opt() {
);
}

extern "C" {
#[link_name = "yh_options"]
/// Device global setting
pub static mut yh_options: [yh_opt; 2usize];
}

extern "C" {
/**
* Return a string describing an error condition
Expand Down
15 changes: 12 additions & 3 deletions src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,12 @@ impl fmt::Display for Error {
}
}

impl From<std::ffi::NulError> for Error {
fn from(_: std::ffi::NulError) -> Self {
Error::InvalidParameter("String contains embedded nul bytes".to_string())
}
}

impl error::Error for Error {
fn description(&self) -> &str {
match *self {
Expand All @@ -62,12 +68,15 @@ impl error::Error for Error {
// Public but not re-exported by lib.rs, so only visible within crate.

pub fn result_from_libyh(code: lyh::yh_rc) -> ::std::result::Result<(), Error> {
result_from_libyh_enum(code.into())
}

pub fn result_from_libyh_enum(code: lyh::yh_rc_enum) -> ::std::result::Result<(), Error> {
match code {
lyh::yh_rc::YHR_SUCCESS => Ok(()),
err => Err(Error::LibYubiHsm(lyh::Error::new(err))),
lyh::yh_rc_enum::YHR_SUCCESS => Ok(()),
_ => Err(Error::LibYubiHsm(code.into())),
}
}

#[cfg(test)]
mod tests {

Expand Down
Loading