use crate::forge::{bindings, osslparams, upcalls};
use crate::Error as OurError;
use crate::ProviderInstance;
use crate::{named, CoreDispatch};
use bindings::OSSL_DISPATCH;
use bindings::OSSL_PARAM;
use bindings::{OSSL_PROV_PARAM_BUILDINFO, OSSL_PROV_PARAM_NAME, OSSL_PROV_PARAM_VERSION};
use libc::{c_int, c_void};
use osslparams::OSSLParam;
use std::sync::Once;
use upcalls::OSSL_CORE_HANDLE;
use crate::{PROV_NAME, PROV_VER};
#[cfg(feature = "env_logger")]
pub use env_logger as logger;
#[cfg(feature = "env_logger")]
fn inner_try_init_logging() -> Result<(), OurError> {
logger::Builder::from_default_env()
.format_timestamp(None) .format_module_path(false) .format_target(true) .format_source_path(true)
.is_test(cfg!(test))
.try_init()
.map_err(OurError::from)
}
pub(crate) fn try_init_logging() -> Result<(), OurError> {
static INIT: Once = Once::new();
INIT.call_once(|| {
#[cfg(feature = "env_logger")]
inner_try_init_logging().expect("Failed to initialize the logging system");
});
Ok(())
}
#[named]
#[allow(non_snake_case)]
#[no_mangle]
pub extern "C" fn OSSL_provider_init(
handle: *const OSSL_CORE_HANDLE,
core_dispatch: *const OSSL_DISPATCH,
provider_dispatch: *mut *const OSSL_DISPATCH,
provctx: *mut *mut c_void,
) -> c_int {
const RET_SUCCESS: c_int = 1;
const RET_FAILURE: c_int = 0;
#[cfg(feature = "env_logger")]
try_init_logging().expect("Failed initializing logger subsystem");
trace!(target: log_target!(), "Just called a 🦀 Rust function from C!");
trace!(target: log_target!(), "This is 🌌 {} v{}", PROV_NAME, PROV_VER);
let core_dispatch = match CoreDispatch::try_from(core_dispatch) {
Ok(cd) => cd,
Err(e) => {
error!(target: log_target!(), "Failed to import core_dspatch: {e:?}");
return RET_FAILURE;
}
};
let mut prov = Box::new(ProviderInstance::new(handle, core_dispatch));
let ourdispatch = prov.get_provider_dispatch();
unsafe {
*provctx = Box::into_raw(prov).cast();
*provider_dispatch = ourdispatch;
}
trace!(target: log_target!(), "{}", "Just written to C pointers from a 🦀 Rust function!");
RET_SUCCESS
}
#[named]
pub unsafe extern "C" fn provider_teardown(vprovctx: *mut c_void) {
trace!(target: log_target!(), "{}", "Called!");
if vprovctx.is_null() {
debug!(target: log_target!(), "Bailing out: called with a NULL pointer.");
return;
}
let prov: Box<ProviderInstance> = unsafe { Box::from_raw(vprovctx.cast()) };
let name = prov.name;
trace!(target: log_target!(), "Teardown of \"{name}\"");
trace!(target: log_target!(), "🦀 Goodbye!");
}
#[named]
pub unsafe extern "C" fn gettable_params(vprovctx: *mut c_void) -> *const OSSL_PARAM {
const FAILURE: *const OSSL_PARAM = std::ptr::null();
trace!(target: log_target!(), "Called!");
let prov: &mut ProviderInstance<'_> = match vprovctx.try_into() {
Ok(p) => p,
Err(e) => {
error!(target: log_target!(), "{}", e);
return FAILURE;
}
};
prov.get_params_array()
}
#[named]
pub unsafe extern "C" fn get_params(vprovctx: *mut c_void, params: *mut OSSL_PARAM) -> c_int {
const FAILURE: c_int = 0;
const SUCCESS: c_int = 1;
trace!(target: log_target!(), "Called!");
let prov: &ProviderInstance<'_> = match vprovctx.try_into() {
Ok(p) => p,
Err(e) => {
error!(target: log_target!(), "{}", e);
return FAILURE;
}
};
let params = match OSSLParam::try_from(params) {
Ok(params) => params,
Err(e) => {
error!(target: log_target!(), "Failed decoding params: {:?}", e);
return FAILURE;
}
};
for mut p in params {
let key = match p.get_key() {
Some(key) => key,
None => {
error!(target: log_target!(), "Param without valid key {:?}", p);
return FAILURE;
}
};
if key == OSSL_PROV_PARAM_NAME {
let str = prov.c_prov_name();
match p.set(str) {
Ok(_) => (),
Err(e) => {
error!(target: log_target!(), "Cannot set OSSL_PROV_PARAM_NAME {p:?}: {e:?}");
return FAILURE;
}
}
} else if key == OSSL_PROV_PARAM_VERSION {
let str = prov.c_prov_version();
match p.set(str) {
Ok(_) => (),
Err(e) => {
error!(target: log_target!(), "Cannot set OSSL_PROV_PARAM_VERSION {p:?}: {e:?}");
return FAILURE;
}
}
} else if key == OSSL_PROV_PARAM_BUILDINFO {
let str = prov.c_prov_buildinfo();
match p.set(str) {
Ok(_) => (),
Err(e) => {
error!(target: log_target!(), "Cannot set OSSL_PROV_PARAM_BUILDINFO {p:?}: {e:?}");
return FAILURE;
}
}
}
}
SUCCESS
}