Skip to main content

aurora/
lib.rs

1#![deny(unexpected_cfgs)]
2
3pub type Error = anyhow::Error;
4
5#[macro_use]
6extern crate log;
7
8#[macro_use]
9mod helpers;
10pub(crate) use helpers::{concat_cstr, handleResult, log_target, named, str_to_cstr};
11
12pub(crate) mod adapters;
13pub(crate) mod forge;
14pub(crate) mod traits;
15
16mod init;
17mod query;
18pub(crate) mod random;
19
20pub(crate) mod asn_definitions;
21
22#[cfg(feature = "built_info")]
23pub mod built_info;
24
25#[cfg(test)]
26pub(crate) mod tests;
27
28use std::ffi::{CStr, CString};
29
30use bindings::dispatch_table_entry;
31use bindings::OSSL_PARAM;
32use bindings::{
33    OSSL_FUNC_provider_get_capabilities_fn, OSSL_FUNC_provider_get_params_fn,
34    OSSL_FUNC_provider_gettable_params_fn, OSSL_FUNC_provider_query_operation_fn,
35    OSSL_FUNC_provider_teardown_fn, OSSL_DISPATCH, OSSL_FUNC_PROVIDER_GETTABLE_PARAMS,
36    OSSL_FUNC_PROVIDER_GET_CAPABILITIES, OSSL_FUNC_PROVIDER_GET_PARAMS,
37    OSSL_FUNC_PROVIDER_QUERY_OPERATION, OSSL_FUNC_PROVIDER_TEARDOWN, OSSL_PROV_PARAM_BUILDINFO,
38    OSSL_PROV_PARAM_NAME, OSSL_PROV_PARAM_VERSION,
39};
40use forge::{bindings, osslparams, upcalls};
41use osslparams::{OSSLParam, OSSLParamData, Utf8PtrData, OSSL_PARAM_END};
42use upcalls::traits::{CoreUpcaller, CoreUpcallerWithCoreHandle};
43use upcalls::OSSL_CORE_HANDLE;
44pub use upcalls::{CoreDispatch, CoreDispatchWithCoreHandle};
45
46/// This is an abstract representation of one Provider instance.
47/// Remember that a single provider module could be loaded multiple
48/// times within the same process, either in the same OpenSSL libctx or
49/// within different libctx's.
50///
51/// At the moment a single instance holds nothing of relevance, but in
52/// the future all the context which is specific to an instance should
53/// be encapsulated within it, so that different instances could have
54/// different configurations, and their own separate state.
55#[derive(Debug)]
56pub struct ProviderInstance<'a> {
57    core_handle: *const OSSL_CORE_HANDLE,
58    core_dispatch: CoreDispatch<'a>,
59    pub name: &'a str,
60    pub version: &'a str,
61    params: Vec<OSSLParam<'a>>,
62    param_array_ptr: Option<*mut [OSSL_PARAM]>,
63    pub(crate) adapters_ctx: adapters::FinalizedAdaptersHandle,
64}
65
66/// We implement the Drop trait to make it explicit when a provider
67/// instance is dropped: this should only happen after `teardown()` has
68/// been called.
69impl<'a> Drop for ProviderInstance<'a> {
70    #[named]
71    fn drop(&mut self) {
72        let tname = std::any::type_name_of_val(self);
73        let name = self.name;
74        trace!(
75            target: log_target!(),
76            "🗑️\tDropping {tname} named {name}",
77        )
78    }
79}
80
81//pub static PROV_NAME: &str = env!("CARGO_PKG_NAME");
82pub static PROV_NAME: &str = "aurora";
83pub static PROV_VER: &str = env!("CARGO_PKG_VERSION");
84pub static PROV_BUILDINFO: &str = env!("CARGO_GIT_DESCRIBE");
85
86const PROPERTY_DEFINITION: &CStr =
87    concat_cstr!(c"provider=", str_to_cstr!(PROV_NAME), c",x.author=QUBIP");
88
89impl<'a> ProviderInstance<'a> {
90    #[named]
91    pub fn new(handle: *const OSSL_CORE_HANDLE, core_dispatch: CoreDispatch<'a>) -> Self {
92        trace!(target: log_target!(), "Called");
93
94        let upcaller: CoreDispatchWithCoreHandle<'a> = (core_dispatch, handle).into();
95
96        #[cfg(not(test))]
97        helpers::examine_core_parameters(&upcaller).expect("Error while examining core parameters");
98
99        let adapters_ctx = { adapters::FinalizedAdaptersHandle::new(&upcaller) };
100
101        let core_dispatch: CoreDispatch = upcaller.into();
102
103        Self {
104            core_handle: handle,
105            core_dispatch,
106            name: PROV_NAME,
107            version: PROV_VER,
108            param_array_ptr: None,
109            params: vec![
110                OSSLParam::Utf8Ptr(Utf8PtrData::new_null(OSSL_PROV_PARAM_NAME)),
111                OSSLParam::Utf8Ptr(Utf8PtrData::new_null(OSSL_PROV_PARAM_VERSION)),
112                OSSLParam::Utf8Ptr(Utf8PtrData::new_null(OSSL_PROV_PARAM_BUILDINFO)),
113            ],
114            adapters_ctx,
115        }
116    }
117
118    /// Retrieve a heap allocated `OSSL_DISPATCH` table associated with this provider instance.
119    pub fn get_provider_dispatch(&mut self) -> *const OSSL_DISPATCH {
120        let ret = Box::new([
121            dispatch_table_entry!(
122                OSSL_FUNC_PROVIDER_TEARDOWN,
123                OSSL_FUNC_provider_teardown_fn,
124                crate::init::provider_teardown
125            ),
126            dispatch_table_entry!(
127                OSSL_FUNC_PROVIDER_GETTABLE_PARAMS,
128                OSSL_FUNC_provider_gettable_params_fn,
129                crate::init::gettable_params
130            ),
131            dispatch_table_entry!(
132                OSSL_FUNC_PROVIDER_GET_PARAMS,
133                OSSL_FUNC_provider_get_params_fn,
134                crate::init::get_params
135            ),
136            dispatch_table_entry!(
137                OSSL_FUNC_PROVIDER_QUERY_OPERATION,
138                OSSL_FUNC_provider_query_operation_fn,
139                crate::query::query_operation
140            ),
141            dispatch_table_entry!(
142                OSSL_FUNC_PROVIDER_GET_CAPABILITIES,
143                OSSL_FUNC_provider_get_capabilities_fn,
144                crate::query::get_capabilities
145            ),
146            OSSL_DISPATCH::END,
147        ]);
148        Box::into_raw(ret).cast()
149    }
150
151    fn get_params_array(&mut self) -> *const OSSL_PARAM {
152        // This is kind of like a poor man's std::sync::Once
153        let raw_ptr = match self.param_array_ptr {
154            Some(raw_ptr) => raw_ptr,
155            None => {
156                let slice = self
157                    .params
158                    .iter_mut()
159                    .map(|p| unsafe { *p.get_c_struct() })
160                    .chain(std::iter::once(OSSL_PARAM_END))
161                    .collect::<Vec<_>>()
162                    .into_boxed_slice();
163                let raw_ptr = Box::into_raw(slice);
164                self.param_array_ptr = Some(raw_ptr);
165                raw_ptr
166            }
167        };
168        raw_ptr.cast()
169    }
170
171    pub fn c_prov_name(&self) -> &CStr {
172        use std::sync::OnceLock;
173
174        static CELL: OnceLock<CString> = OnceLock::new();
175
176        let l = CELL.get_or_init(|| CString::new(self.name).expect("Error parsing self.name"));
177        l.as_ref()
178    }
179
180    pub fn c_prov_version(&self) -> &CStr {
181        use std::sync::OnceLock;
182
183        static CELL: OnceLock<CString> = OnceLock::new();
184
185        let l =
186            CELL.get_or_init(|| CString::new(self.version).expect("Error parsing self.version"));
187        l.as_ref()
188    }
189
190    pub fn c_prov_buildinfo(&self) -> &CStr {
191        use std::sync::OnceLock;
192
193        static CELL: OnceLock<CString> = OnceLock::new();
194
195        let l = CELL.get_or_init(|| {
196            CString::new(crate::PROV_BUILDINFO).expect("Error parsing cPROV_BUILDINFO")
197        });
198        l.as_ref()
199    }
200}
201
202impl<'a> TryFrom<*mut core::ffi::c_void> for &mut ProviderInstance<'a> {
203    type Error = Error;
204
205    #[named]
206    fn try_from(vctx: *mut core::ffi::c_void) -> Result<Self, Self::Error> {
207        trace!(target: log_target!(), "Called for {}",
208        "impl<'a> TryFrom<*mut core::ffi::c_void> for &mut ProviderInstance<'a>"
209        );
210        let provp = vctx as *mut ProviderInstance;
211        if provp.is_null() {
212            return Err(anyhow::anyhow!("vctx was null"));
213        }
214        Ok(unsafe { &mut *provp })
215    }
216}
217
218impl<'a> TryFrom<*mut core::ffi::c_void> for &ProviderInstance<'a> {
219    type Error = Error;
220
221    #[named]
222    fn try_from(vctx: *mut core::ffi::c_void) -> Result<Self, Self::Error> {
223        trace!(target: log_target!(), "Called for {}", "impl<'a> TryFrom<*mut core::ffi::c_void> for &ProviderInstance<'a>");
224        let r: &mut ProviderInstance<'a> = vctx.try_into()?;
225        Ok(r)
226    }
227}
228
229impl CoreUpcaller for ProviderInstance<'_> {
230    fn fn_from_core_dispatch(&self, id: u32) -> Option<unsafe extern "C" fn()> {
231        self.core_dispatch.fn_from_core_dispatch(id)
232    }
233}
234
235impl CoreUpcallerWithCoreHandle for ProviderInstance<'_> {
236    fn get_core_handle(&self) -> *const OSSL_CORE_HANDLE {
237        self.core_handle
238    }
239}