From 795589cfa3cde700d44201c7390a41ee4c5891ed Mon Sep 17 00:00:00 2001 From: Q Date: Sat, 21 Oct 2023 16:49:16 +0100 Subject: [PATCH 1/6] Add draft initial support openssl engine binding --- openssl-sys/src/engine.rs | 90 +++++++++++++++++++++++++++++++++++++++ openssl-sys/src/lib.rs | 2 + 2 files changed, 92 insertions(+) create mode 100644 openssl-sys/src/engine.rs diff --git a/openssl-sys/src/engine.rs b/openssl-sys/src/engine.rs new file mode 100644 index 0000000000..5f46aa523a --- /dev/null +++ b/openssl-sys/src/engine.rs @@ -0,0 +1,90 @@ +use libc::*; +use crate::{ENGINE, EVP_PKEY, SSL, stack_st_X509, stack_st_X509_NAME, X509}; + +extern "C" { + pub fn ENGINE_load_builtin_engines(); + pub fn ENGINE_by_id(id: *const c_char) -> *mut ENGINE; + + pub fn ENGINE_init(e: *mut ENGINE) -> c_int; + pub fn ENGINE_finish(e: *mut ENGINE) -> c_int; + pub fn ENGINE_free(e: *mut ENGINE) -> c_int; + + pub fn ENGINE_ctrl_cmd( + e: *mut ENGINE, + cmd_name: *const c_char, + i: c_long, + p: *mut c_void, + f: extern "C" fn() -> (), + cmd_optional: c_int, + ) -> c_int; + pub fn ENGINE_ctrl_cmd_string( + e: *mut ENGINE, + cmd_name: *const c_char, + arg: *const c_char, + cmd_optional: c_int, + ) -> c_int; + + pub fn ENGINE_load_private_key( + e: *mut ENGINE, + key_id: *const c_char, + ui_method: *mut UI_METHOD, + callback_data: *mut c_void, + ) -> *mut EVP_PKEY; + pub fn ENGINE_load_public_key( + e: *mut ENGINE, + key_id: *const c_char, + ui_method: *mut UI_METHOD, + callback_data: *mut c_void, + ) -> *mut EVP_PKEY; + pub fn ENGINE_load_ssl_client_cert( + e: *mut ENGINE, + ssl: *mut SSL, + ca_dn: *mut stack_st_X509_NAME, + pcert: *mut *mut X509, + ppkey: *mut *mut EVP_PKEY, + pother: *mut *mut stack_st_X509, + ui_method: *mut UI_METHOD, + callback_data: *mut c_void, + ) -> c_int; + + pub fn UI_set_default_method(meth: *const UI_METHOD); + pub fn UI_get_default_method() -> *const UI_METHOD; + pub fn UI_get_method(ui: *mut UI) -> *const UI_METHOD; + pub fn UI_set_method(ui: *mut UI, meth: *const UI_METHOD) -> *const UI_METHOD; + + pub fn UI_OpenSSL() -> *mut UI_METHOD; + pub fn UI_null() -> *const UI_METHOD; +} + +type UI = c_int; +type UI_STRING = c_int; + +pub enum UI_METHOD {} + +// #[repr(C)] +// pub struct UI_METHOD { +// name: *const c_char, +// ui_open_session: extern "C" fn(ui: *mut UI) -> c_int, +// ui_write_string: extern "C" fn(ui: *mut UI, uis: *mut UI_STRING) -> c_int, +// ui_flush: extern "C" fn(ui: *mut UI) -> c_int, +// ui_read_string: extern "C" fn(ui: *mut UI, uis: *mut UI_STRING) -> c_int, +// ui_close_session: extern "C" fn(ui: *mut UI) -> c_int, +// ui_construct_prompt: extern "C" fn( +// ui: *mut UI, +// object_desc: *const c_char, +// object_name: *const c_char, +// ) -> *mut c_char, +// } + +const UI_FLAG_REDOABLE: c_int = 0x0001; +const UI_FLAG_PRINT_ERRORS: c_int = 0x0100; + +#[repr(C)] +pub enum UI_string_types { + UIT_NONE = 0, + UIT_PROMPT, + UIT_VERIFY, + UIT_BOOLEAN, + UIT_INFO, + UIT_ERROR, +} \ No newline at end of file diff --git a/openssl-sys/src/lib.rs b/openssl-sys/src/lib.rs index 0e23386fd3..1673d0fbc7 100644 --- a/openssl-sys/src/lib.rs +++ b/openssl-sys/src/lib.rs @@ -66,6 +66,7 @@ mod openssl { pub use self::x509::*; pub use self::x509_vfy::*; pub use self::x509v3::*; + pub use self::engine::*; #[macro_use] mod macros; @@ -96,6 +97,7 @@ mod openssl { mod x509; mod x509_vfy; mod x509v3; + mod engine; use std::sync::Once; // explicitly initialize to work around https://github.com/openssl/openssl/issues/3505 From afba39f57bb8fd75fbdc1a3ea5a565f4666376b7 Mon Sep 17 00:00:00 2001 From: Walter BONETTI Date: Sat, 3 Aug 2024 16:25:42 -0400 Subject: [PATCH 2/6] Fix missing systest dependency on engine.h --- systest/build.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/systest/build.rs b/systest/build.rs index fc970f410a..8ce783fe42 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -50,6 +50,7 @@ fn main() { cfg.header("openssl/comp.h") .header("openssl/dh.h") + .header("openssl/engine.h") .header("openssl/ossl_typ.h") .header("openssl/stack.h") .header("openssl/x509.h") From 4b08cd63734f37a7708d61843fbe4bf20219007e Mon Sep 17 00:00:00 2001 From: Walter BONETTI Date: Sat, 3 Aug 2024 19:17:18 -0400 Subject: [PATCH 3/6] Move definition of UI_METHOD to handwritten --- openssl-sys/src/engine.rs | 34 +++---------------------- openssl-sys/src/handwritten/mod.rs | 2 ++ openssl-sys/src/handwritten/ui.rs | 40 ++++++++++++++++++++++++++++++ 3 files changed, 45 insertions(+), 31 deletions(-) create mode 100644 openssl-sys/src/handwritten/ui.rs diff --git a/openssl-sys/src/engine.rs b/openssl-sys/src/engine.rs index 5f46aa523a..91b1d9a202 100644 --- a/openssl-sys/src/engine.rs +++ b/openssl-sys/src/engine.rs @@ -1,5 +1,7 @@ +use crate::{ + stack_st_X509, stack_st_X509_NAME, CRYPTO_EX_DATA, ENGINE, EVP_PKEY, SSL, UI, UI_METHOD, X509, +}; use libc::*; -use crate::{ENGINE, EVP_PKEY, SSL, stack_st_X509, stack_st_X509_NAME, X509}; extern "C" { pub fn ENGINE_load_builtin_engines(); @@ -56,35 +58,5 @@ extern "C" { pub fn UI_null() -> *const UI_METHOD; } -type UI = c_int; -type UI_STRING = c_int; - -pub enum UI_METHOD {} - -// #[repr(C)] -// pub struct UI_METHOD { -// name: *const c_char, -// ui_open_session: extern "C" fn(ui: *mut UI) -> c_int, -// ui_write_string: extern "C" fn(ui: *mut UI, uis: *mut UI_STRING) -> c_int, -// ui_flush: extern "C" fn(ui: *mut UI) -> c_int, -// ui_read_string: extern "C" fn(ui: *mut UI, uis: *mut UI_STRING) -> c_int, -// ui_close_session: extern "C" fn(ui: *mut UI) -> c_int, -// ui_construct_prompt: extern "C" fn( -// ui: *mut UI, -// object_desc: *const c_char, -// object_name: *const c_char, -// ) -> *mut c_char, -// } - const UI_FLAG_REDOABLE: c_int = 0x0001; const UI_FLAG_PRINT_ERRORS: c_int = 0x0100; - -#[repr(C)] -pub enum UI_string_types { - UIT_NONE = 0, - UIT_PROMPT, - UIT_VERIFY, - UIT_BOOLEAN, - UIT_INFO, - UIT_ERROR, -} \ No newline at end of file diff --git a/openssl-sys/src/handwritten/mod.rs b/openssl-sys/src/handwritten/mod.rs index 47b3360fd8..8138385c75 100644 --- a/openssl-sys/src/handwritten/mod.rs +++ b/openssl-sys/src/handwritten/mod.rs @@ -33,6 +33,7 @@ pub use self::stack::*; pub use self::thread::*; pub use self::tls1::*; pub use self::types::*; +pub use self::ui::*; pub use self::x509::*; pub use self::x509_vfy::*; pub use self::x509v3::*; @@ -72,6 +73,7 @@ mod stack; mod thread; mod tls1; mod types; +mod ui; mod x509; mod x509_vfy; mod x509v3; diff --git a/openssl-sys/src/handwritten/ui.rs b/openssl-sys/src/handwritten/ui.rs new file mode 100644 index 0000000000..4c328ae2d3 --- /dev/null +++ b/openssl-sys/src/handwritten/ui.rs @@ -0,0 +1,40 @@ +use super::super::*; +use libc::*; + +pub enum UI {} + +pub enum UI_STRING {} + +cfg_if! { + if #[cfg(any(ossl110, libressl280))] { + pub enum UI_METHOD {} + } else { + #[repr(C)] + pub struct UI_METHOD { + pub name: *const c_char, + pub ui_open_session: Option c_int>, + pub ui_write_string: Option c_int>, + pub ui_flush: Option c_int>, + pub ui_read_string: Option c_int>, + pub ui_close_session: Option c_int>, + pub ui_duplicate_data: Option *mut c_void>, + pub ui_destroy_data: Option, + pub ui_construct_prompt: Option *mut c_char>, + pub ex_data: CRYPTO_EX_DATA, + } + } +} + +#[repr(C)] +pub enum UI_string_types { + UIT_NONE = 0, + UIT_PROMPT, + UIT_VERIFY, + UIT_BOOLEAN, + UIT_INFO, + UIT_ERROR, +} From 94ac329ce294423c3d52c428415b104980da02d8 Mon Sep 17 00:00:00 2001 From: Walter BONETTI Date: Sun, 4 Aug 2024 20:46:37 -0400 Subject: [PATCH 4/6] Add Engine and UI bases --- openssl-sys/build/run_bindgen.rs | 2 + openssl-sys/src/engine.rs | 14 +- openssl-sys/src/handwritten/ui.rs | 239 ++++++++++++++++++++++++++---- openssl-sys/src/ui.rs | 2 + openssl/src/engine.rs | 150 +++++++++++++++++++ openssl/src/lib.rs | 4 + openssl/src/ui.rs | 106 +++++++++++++ systest/build.rs | 1 + 8 files changed, 478 insertions(+), 40 deletions(-) create mode 100644 openssl-sys/src/ui.rs create mode 100644 openssl/src/engine.rs create mode 100644 openssl/src/ui.rs diff --git a/openssl-sys/build/run_bindgen.rs b/openssl-sys/build/run_bindgen.rs index 27bd482b38..40dc68e675 100644 --- a/openssl-sys/build/run_bindgen.rs +++ b/openssl-sys/build/run_bindgen.rs @@ -12,6 +12,8 @@ const INCLUDES: &str = " #include #include #include +#include +#include #include #include #include diff --git a/openssl-sys/src/engine.rs b/openssl-sys/src/engine.rs index 91b1d9a202..f8e4457316 100644 --- a/openssl-sys/src/engine.rs +++ b/openssl-sys/src/engine.rs @@ -7,6 +7,7 @@ extern "C" { pub fn ENGINE_load_builtin_engines(); pub fn ENGINE_by_id(id: *const c_char) -> *mut ENGINE; + pub fn ENGINE_new() -> *mut ENGINE; pub fn ENGINE_init(e: *mut ENGINE) -> c_int; pub fn ENGINE_finish(e: *mut ENGINE) -> c_int; pub fn ENGINE_free(e: *mut ENGINE) -> c_int; @@ -16,7 +17,7 @@ extern "C" { cmd_name: *const c_char, i: c_long, p: *mut c_void, - f: extern "C" fn() -> (), + f: Option, cmd_optional: c_int, ) -> c_int; pub fn ENGINE_ctrl_cmd_string( @@ -48,15 +49,4 @@ extern "C" { ui_method: *mut UI_METHOD, callback_data: *mut c_void, ) -> c_int; - - pub fn UI_set_default_method(meth: *const UI_METHOD); - pub fn UI_get_default_method() -> *const UI_METHOD; - pub fn UI_get_method(ui: *mut UI) -> *const UI_METHOD; - pub fn UI_set_method(ui: *mut UI, meth: *const UI_METHOD) -> *const UI_METHOD; - - pub fn UI_OpenSSL() -> *mut UI_METHOD; - pub fn UI_null() -> *const UI_METHOD; } - -const UI_FLAG_REDOABLE: c_int = 0x0001; -const UI_FLAG_PRINT_ERRORS: c_int = 0x0100; diff --git a/openssl-sys/src/handwritten/ui.rs b/openssl-sys/src/handwritten/ui.rs index 4c328ae2d3..887fb64b51 100644 --- a/openssl-sys/src/handwritten/ui.rs +++ b/openssl-sys/src/handwritten/ui.rs @@ -1,35 +1,8 @@ use super::super::*; use libc::*; -pub enum UI {} - -pub enum UI_STRING {} - -cfg_if! { - if #[cfg(any(ossl110, libressl280))] { - pub enum UI_METHOD {} - } else { - #[repr(C)] - pub struct UI_METHOD { - pub name: *const c_char, - pub ui_open_session: Option c_int>, - pub ui_write_string: Option c_int>, - pub ui_flush: Option c_int>, - pub ui_read_string: Option c_int>, - pub ui_close_session: Option c_int>, - pub ui_duplicate_data: Option *mut c_void>, - pub ui_destroy_data: Option, - pub ui_construct_prompt: Option *mut c_char>, - pub ex_data: CRYPTO_EX_DATA, - } - } -} - #[repr(C)] +#[derive(Copy, Clone)] pub enum UI_string_types { UIT_NONE = 0, UIT_PROMPT, @@ -38,3 +11,213 @@ pub enum UI_string_types { UIT_INFO, UIT_ERROR, } + +pub enum UI_STRING {} + +extern "C" { + pub fn UI_get_string_type(uis: *mut UI_STRING) -> c_uint; + pub fn UI_get_input_flags(uis: *mut UI_STRING) -> c_int; + pub fn UI_get0_output_string(uis: *mut UI_STRING) -> *const c_char; + pub fn UI_get0_action_string(uis: *mut UI_STRING) -> *const c_char; + pub fn UI_get0_result_string(uis: *mut UI_STRING) -> *const c_char; + pub fn UI_get_result_string_length(uis: *mut UI_STRING) -> c_int; + pub fn UI_get0_test_string(uis: *mut UI_STRING) -> *const c_char; + pub fn UI_get_result_minsize(uis: *mut UI_STRING) -> c_int; + pub fn UI_get_result_maxsize(uis: *mut UI_STRING) -> c_int; + pub fn UI_set_result(ui: *mut UI, uis: *mut UI_STRING, result: *const c_char) -> c_int; + pub fn UI_set_result_ex( + ui: *mut UI, + uis: *mut UI_STRING, + result: *const c_char, + len: c_int, + ) -> c_int; +} + +pub enum UI_METHOD {} +// #[repr(C)] +// pub struct UI_METHOD { +// pub name: *const c_char, +// pub ui_open_session: Option c_int>, +// pub ui_write_string: Option c_int>, +// pub ui_flush: Option c_int>, +// pub ui_read_string: Option c_int>, +// pub ui_close_session: Option c_int>, +// pub ui_duplicate_data: Option *mut c_void>, +// pub ui_destroy_data: Option, +// pub ui_construct_prompt: Option *mut c_char>, +// pub ex_data: CRYPTO_EX_DATA, +// } + +extern "C" { + pub fn UI_create_method(name: *const c_char) -> *mut UI_METHOD; + pub fn UI_destroy_method(ui_method: *mut UI_METHOD); + pub fn UI_method_set_opener( + method: *mut UI_METHOD, + opener: Option c_int>, + ) -> c_int; + pub fn UI_method_set_writer( + method: *mut UI_METHOD, + writer: Option c_int>, + ) -> c_int; + pub fn UI_method_set_flusher( + method: *mut UI_METHOD, + flusher: Option c_int>, + ) -> c_int; + pub fn UI_method_set_reader( + method: *mut UI_METHOD, + reader: Option c_int>, + ) -> c_int; + pub fn UI_method_set_closer( + method: *mut UI_METHOD, + closer: Option c_int>, + ) -> c_int; + pub fn UI_method_set_data_duplicator( + method: *mut UI_METHOD, + duplicator: Option *mut c_void>, + destructor: Option, + ) -> c_int; + pub fn UI_method_set_prompt_constructor( + method: *mut UI_METHOD, + prompt_constructor: Option< + extern "C" fn(*mut UI, *const c_char, *const c_char) -> *mut c_char, + >, + ) -> c_int; + // Next functions will return: + // int(*)(UI*) (*__test_fn_UI_method_get_opener(void))(const UI_METHOD*) + // But, our needs is int (*__test_UI_method_get_opener(const UI_METHOD *method)) (UI *); + // pub fn UI_method_get_opener( + // method: *const UI_METHOD, + // ) -> Option c_int>; + // pub fn UI_method_get_writer( + // method: *const UI_METHOD, + // ) -> Option c_int>; + // pub fn UI_method_get_flusher( + // method: *const UI_METHOD, + // ) -> Option c_int>; + // pub fn UI_method_get_reader( + // method: *const UI_METHOD, + // ) -> Option c_int>; + // pub fn UI_method_get_closer( + // method: *const UI_METHOD, + // ) -> Option c_int>; + // pub fn UI_method_get_prompt_constructor( + // method: *const UI_METHOD, + // ) -> Option *mut c_char>; + // pub fn UI_method_get_data_duplicator( + // method: *const UI_METHOD, + // ) -> Option *mut c_void>; + // pub fn UI_method_get_data_destructor( + // method: *const UI_METHOD, + // ) -> Option; +} + +extern "C" { + pub fn UI_method_set_ex_data(method: *mut UI_METHOD, idx: c_int, data: *mut c_void) -> c_int; + pub fn UI_method_get_ex_data(method: *const UI_METHOD, idx: c_int) -> *const c_void; +} + +pub enum UI {} + +extern "C" { + pub fn UI_new() -> *mut UI; + pub fn UI_new_method(meth: *const UI_METHOD) -> *mut UI; + pub fn UI_free(e: *mut UI); + pub fn UI_add_input_string( + ui: *mut UI, + prompt: *const c_char, + flags: c_int, + result_buf: *mut c_char, + minsize: c_int, + maxsize: c_int, + ) -> c_int; + pub fn UI_dup_input_string( + ui: *mut UI, + prompt: *const c_char, + flags: c_int, + result_buf: *mut c_char, + minsize: c_int, + maxsize: c_int, + ) -> c_int; + pub fn UI_add_verify_string( + ui: *mut UI, + prompt: *const c_char, + flags: c_int, + result_buf: *mut c_char, + minsize: c_int, + maxsize: c_int, + test_buf: *const c_char, + ) -> c_int; + pub fn UI_dup_verify_string( + ui: *mut UI, + prompt: *const c_char, + flags: c_int, + result_buf: *mut c_char, + minsize: c_int, + maxsize: c_int, + test_buf: *const c_char, + ) -> c_int; + pub fn UI_add_input_boolean( + ui: *mut UI, + prompt: *const c_char, + action_desc: *const c_char, + ok_chars: *const c_char, + cancel_chars: *const c_char, + flags: c_int, + result_buf: *mut c_char, + ) -> c_int; + pub fn UI_dup_input_boolean( + ui: *mut UI, + prompt: *const c_char, + action_desc: *const c_char, + ok_chars: *const c_char, + cancel_chars: *const c_char, + flags: c_int, + result_buf: *mut c_char, + ) -> c_int; + pub fn UI_add_info_string(ui: *mut UI, text: *const c_char) -> c_int; + pub fn UI_dup_info_string(ui: *mut UI, text: *const c_char) -> c_int; + pub fn UI_add_error_string(ui: *mut UI, text: *const c_char) -> c_int; + pub fn UI_dup_error_string(ui: *mut UI, text: *const c_char) -> c_int; + pub fn UI_construct_prompt( + ui: *mut UI, + phrase_desc: *const c_char, + object_name: *const c_char, + ) -> *mut c_char; + pub fn UI_add_user_data(ui: *mut UI, user_data: *mut c_void) -> *mut c_void; + pub fn UI_dup_user_data(ui: *mut UI, user_data: *mut c_void) -> c_int; + pub fn UI_get0_user_data(ui: *mut UI) -> *mut c_void; + pub fn UI_get0_result(ui: *mut UI, i: c_int) -> *const c_char; + pub fn UI_get_result_length(ui: *mut UI, i: c_int) -> c_int; + pub fn UI_process(ui: *mut UI) -> c_int; + pub fn UI_ctrl( + ui: *mut UI, + cmd: c_int, + i: c_long, + p: *mut c_void, + f: unsafe extern "C" fn(), + ) -> c_int; + pub fn UI_set_default_method(meth: *const UI_METHOD); + pub fn UI_get_default_method() -> *const UI_METHOD; + pub fn UI_get_method(ui: *mut UI) -> *const UI_METHOD; + pub fn UI_set_method(ui: *mut UI, meth: *const UI_METHOD) -> *const UI_METHOD; + pub fn UI_OpenSSL() -> *mut UI_METHOD; + pub fn UI_null() -> *const UI_METHOD; +} + +extern "C" { + #[cfg(not(ossl110))] + pub fn UI_get_ex_new_index( + argl: c_long, + argp: *mut c_void, + new_func: Option, + dup_func: Option, + free_func: Option, + ) -> c_int; + + pub fn UI_set_ex_data(ssl: *mut UI, idx: c_int, data: *mut c_void) -> c_int; + pub fn UI_get_ex_data(ssl: *const UI, idx: c_int) -> *mut c_void; +} diff --git a/openssl-sys/src/ui.rs b/openssl-sys/src/ui.rs new file mode 100644 index 0000000000..dfeb4f5d37 --- /dev/null +++ b/openssl-sys/src/ui.rs @@ -0,0 +1,2 @@ +const UI_FLAG_REDOABLE: c_int = 0x0001; +const UI_FLAG_PRINT_ERRORS: c_int = 0x0100; diff --git a/openssl/src/engine.rs b/openssl/src/engine.rs new file mode 100644 index 0000000000..c4ea9817a3 --- /dev/null +++ b/openssl/src/engine.rs @@ -0,0 +1,150 @@ +//! Interface for OpenSSL engine. + +use std::{ffi::CString, ptr::null_mut}; + +use foreign_types::ForeignType; +use libc::c_void; +use openssl_macros::corresponds; + +use crate::{ + cvt, cvt_p, + error::ErrorStack, + pkey::{PKey, Private, Public}, + ui::UiMethod, +}; + +fn engine_free(ptr: *mut ffi::ENGINE) { + unsafe { + // ENGINE_free() always returns 1 + ffi::ENGINE_free(ptr); + } +} + +foreign_type_and_impl_send_sync! { + type CType = ffi::ENGINE; + fn drop = engine_free; + + pub struct Engine; + pub struct EngineRef; +} + +impl Engine { + /// Create a new engine + /// + /// # Examples + /// + /// ``` + /// use openssl::engine::{Engine}; + /// + /// let engine = Engine::new(); + /// ``` + #[corresponds(ENGINE_new)] + pub fn new() -> Result { + unsafe { cvt_p(ffi::ENGINE_new()).map(Engine) } + } + + /// Load all bundled ENGINEs into memory and make them visible + /// + /// # Examples + /// + /// ``` + /// use openssl::engine::{Engine}; + /// + /// let engine = Engine::load_builtin_engines(); + /// ``` + #[corresponds(ENGINE_new)] + pub fn load_builtin_engines() { + unsafe { ffi::ENGINE_load_builtin_engines() } + } + + /// Get an engine from the `engine_id` + /// + /// # Examples + /// + /// ```(ignore) + /// use openssl::engine::{Engine}; + /// + /// let engine = Engine::new("pkcs11"); + /// ``` + #[corresponds(ENGINE_by_id)] + pub fn by_id(id: &str) -> Result { + let id = CString::new(id).unwrap(); + unsafe { cvt_p(ffi::ENGINE_by_id(id.as_ptr())).map(Engine) } + } + + /// Lock the engine + #[corresponds(ENGINE_init)] + pub fn init(&mut self) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::ENGINE_init(self.as_ptr())).map(|_| ()) } + } + + /// Unlock the engine + #[corresponds(ENGINE_finish)] + pub fn finish(&mut self) -> Result<(), ErrorStack> { + unsafe { cvt(ffi::ENGINE_finish(self.as_ptr())).map(|_| ()) } + } + + /// Loads a private key + #[corresponds(ENGINE_load_private_key)] + pub fn load_private_key( + &mut self, + key_id: &str, + ui_method: Option, + callback_data: Option, + ) -> Result, ErrorStack> { + let key_id = CString::new(key_id).unwrap(); + let raw = match callback_data { + Some(callback_data) => Box::into_raw(Box::new(callback_data)) as *mut c_void, + None => null_mut(), + }; + + let res = unsafe { + cvt_p(ffi::ENGINE_load_private_key( + self.as_ptr(), + key_id.as_ptr(), + ui_method.map_or(null_mut(), |value| value.as_ptr()), + raw, + )) + .map(|op| PKey::from_ptr(op)) + }; + + // cleanup + if !raw.is_null() { + let _ = unsafe { Box::::from_raw(raw as *mut T) }; + }; + + res + } + + /// Loads a public key + #[corresponds(ENGINE_load_public_key)] + pub fn load_public_key( + &mut self, + key_id: &str, + ui_method: Option, + callback_data: Option, + ) -> Result, ErrorStack> { + let key_id = CString::new(key_id).unwrap(); + let raw = match callback_data { + Some(callback_data) => Box::into_raw(Box::new(callback_data)) as *mut c_void, + None => null_mut(), + }; + + let res = unsafe { + cvt_p(ffi::ENGINE_load_public_key( + self.as_ptr(), + key_id.as_ptr(), + ui_method.map_or(null_mut(), |value| value.as_ptr()), + raw, + )) + .map(|op| PKey::from_ptr(op)) + }; + + // cleanup + if !raw.is_null() { + let _ = unsafe { Box::::from_raw(raw as *mut T) }; + }; + + res + } +} diff --git a/openssl/src/lib.rs b/openssl/src/lib.rs index c58e5bf598..4b51b5a19f 100644 --- a/openssl/src/lib.rs +++ b/openssl/src/lib.rs @@ -144,6 +144,10 @@ use crate::error::ErrorStack; mod macros; mod bio; + +pub mod engine; +pub mod ui; + #[macro_use] mod util; pub mod aes; diff --git a/openssl/src/ui.rs b/openssl/src/ui.rs new file mode 100644 index 0000000000..04933e52d6 --- /dev/null +++ b/openssl/src/ui.rs @@ -0,0 +1,106 @@ +use foreign_types::ForeignType; +use libc::c_void; +use openssl_macros::corresponds; + +use crate::{cvt_p, error::ErrorStack, ex_data::Index}; + +fn safe_null_destroy_method(ui_method: *mut ffi::UI_METHOD) { + // pre-check UI_null + let ui_null: *const ffi::UI_METHOD = unsafe { ffi::UI_null() }; + + // Ensure the comparison is done correctly + if ui_method != ui_null as *mut ffi::UI_METHOD { + unsafe { ffi::UI_destroy_method(ui_method) } + } +} + +foreign_type_and_impl_send_sync! { + type CType = ffi::UI_METHOD; + fn drop = safe_null_destroy_method; + + /// A User Interface + /// + /// UI stands for User Interface, and is general purpose set of routines to prompt the user for text-based information. + /// Through user-written methods (see UI_create_method(3)), prompting can be done in any way imaginable, + /// be it plain text prompting, through dialog boxes or from a cell phone. + pub struct UiMethod; + + /// Reference to [`UiMethod`] + /// + /// [`UiMethod`]: struct.Ui.html + pub struct UiMethodRef; +} + +foreign_type_and_impl_send_sync! { + type CType = ffi::UI; + fn drop = ffi::UI_free; + + /// A User Interface + /// + /// UI stands for User Interface, and is general purpose set of routines to prompt the user for text-based information. + /// Through user-written methods (see UI_create_method(3)), prompting can be done in any way imaginable, + /// be it plain text prompting, through dialog boxes or from a cell phone. + pub struct Ui; + + /// Reference to [`Ui`] + /// + /// [`Ui`]: struct.Ui.html + pub struct UiRef; +} + +impl Ui { + #[corresponds(UI_new)] + pub fn new() -> Result { + unsafe { + ffi::init(); + + cvt_p(ffi::UI_new()).map(Ui) + } + } + + /// Sets the extra data at the specified index. + /// + /// This can be used to provide data to callbacks registered with the context. Use the + /// `Ssl::new_ex_index` method to create an `Index`. + // FIXME should return a result + #[corresponds(UI_set_ex_data)] + pub fn set_ex_data(&mut self, index: Index, data: T) { + match self.ex_data_mut(index) { + Some(v) => *v = data, + None => unsafe { + let data = Box::new(data); + ffi::UI_set_ex_data( + self.as_ptr(), + index.as_raw(), + Box::into_raw(data) as *mut c_void, + ); + }, + } + } + + /// Returns a reference to the extra data at the specified index. + #[corresponds(UI_get_ex_data)] + pub fn ex_data(&self, index: Index) -> Option<&T> { + unsafe { + let data = ffi::UI_get_ex_data(self.as_ptr(), index.as_raw()); + if data.is_null() { + None + } else { + Some(&*(data as *const T)) + } + } + } + + /// Returns a mutable reference to the extra data at the specified index. + #[corresponds(UI_get_ex_data)] + pub fn ex_data_mut(&mut self, index: Index) -> Option<&mut T> { + unsafe { + let data = ffi::UI_get_ex_data(self.as_ptr(), index.as_raw()); + if data.is_null() { + None + } else { + Some(&mut *(data as *mut T)) + } + } + } +} diff --git a/systest/build.rs b/systest/build.rs index 8ce783fe42..f6b6e7f912 100644 --- a/systest/build.rs +++ b/systest/build.rs @@ -51,6 +51,7 @@ fn main() { cfg.header("openssl/comp.h") .header("openssl/dh.h") .header("openssl/engine.h") + .header("openssl/ui.h") .header("openssl/ossl_typ.h") .header("openssl/stack.h") .header("openssl/x509.h") From aca7be959f1bba5a7c9189232a95a2bca556cb2c Mon Sep 17 00:00:00 2001 From: Walter BONETTI Date: Tue, 17 Sep 2024 14:32:17 -0400 Subject: [PATCH 5/6] Fix: ENGINE_load_builtin_engines corresponds --- openssl/src/engine.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/openssl/src/engine.rs b/openssl/src/engine.rs index c4ea9817a3..268255906a 100644 --- a/openssl/src/engine.rs +++ b/openssl/src/engine.rs @@ -52,7 +52,7 @@ impl Engine { /// /// let engine = Engine::load_builtin_engines(); /// ``` - #[corresponds(ENGINE_new)] + #[corresponds(ENGINE_load_builtin_engines)] pub fn load_builtin_engines() { unsafe { ffi::ENGINE_load_builtin_engines() } } From 334d778bfb6067560d86e37d579650b99f3d3e4e Mon Sep 17 00:00:00 2001 From: Walter BONETTI Date: Tue, 17 Sep 2024 14:36:35 -0400 Subject: [PATCH 6/6] Fix: Engine enforces ffi::init usage --- openssl/src/engine.rs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/openssl/src/engine.rs b/openssl/src/engine.rs index 268255906a..82a103c55f 100644 --- a/openssl/src/engine.rs +++ b/openssl/src/engine.rs @@ -40,6 +40,8 @@ impl Engine { /// ``` #[corresponds(ENGINE_new)] pub fn new() -> Result { + ffi::init(); + unsafe { cvt_p(ffi::ENGINE_new()).map(Engine) } } @@ -54,6 +56,9 @@ impl Engine { /// ``` #[corresponds(ENGINE_load_builtin_engines)] pub fn load_builtin_engines() { + ffi::init(); + + // TODO: not sure about the ffi::init for this one. unsafe { ffi::ENGINE_load_builtin_engines() } } @@ -68,6 +73,8 @@ impl Engine { /// ``` #[corresponds(ENGINE_by_id)] pub fn by_id(id: &str) -> Result { + ffi::init(); + let id = CString::new(id).unwrap(); unsafe { cvt_p(ffi::ENGINE_by_id(id.as_ptr())).map(Engine) } }