macro_rules! get_pkcs11 {
($pkcs11:expr, $func_name:ident) => {
($pkcs11
.impl_
.function_list
.$func_name
.ok_or(crate::error::Error::NullFunctionPointer)?)
};
}
mod general_purpose;
mod info;
mod locking;
mod session_management;
mod slot_token_management;
pub use general_purpose::*;
pub use info::*;
pub use locking::*;
use crate::error::{Error, Result, Rv};
use log::error;
use std::fmt;
use std::mem;
use std::path::Path;
use std::ptr;
use std::sync::Arc;
use std::sync::RwLock;
pub(crate) struct Pkcs11Impl {
_pkcs11_lib: cryptoki_sys::Pkcs11,
pub(crate) function_list: cryptoki_sys::_CK_FUNCTION_LIST,
}
impl fmt::Debug for Pkcs11Impl {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
f.debug_struct("Pkcs11Impl")
.field("function_list", &self.function_list)
.finish()
}
}
impl Pkcs11Impl {
#[inline(always)]
fn finalize(&self) -> Result<()> {
unsafe {
Rv::from(self
.function_list
.C_Finalize
.ok_or(Error::NullFunctionPointer)?(
ptr::null_mut()
))
.into_result(Function::Finalize)
}
}
}
impl Drop for Pkcs11Impl {
fn drop(&mut self) {
if let Err(e) = self.finalize() {
error!("Failed to finalize: {}", e);
}
}
}
#[derive(Clone, Debug)]
pub struct Pkcs11 {
pub(crate) impl_: Arc<Pkcs11Impl>,
initialized: Arc<RwLock<bool>>,
}
impl Pkcs11 {
pub fn new<P>(filename: P) -> Result<Self>
where
P: AsRef<Path>,
{
unsafe {
let pkcs11_lib =
cryptoki_sys::Pkcs11::new(filename.as_ref()).map_err(Error::LibraryLoading)?;
let mut list = mem::MaybeUninit::uninit();
Rv::from(pkcs11_lib.C_GetFunctionList(list.as_mut_ptr()))
.into_result(Function::GetFunctionList)?;
let list_ptr = *list.as_ptr();
Ok(Pkcs11 {
impl_: Arc::new(Pkcs11Impl {
_pkcs11_lib: pkcs11_lib,
function_list: *list_ptr,
}),
initialized: Arc::new(RwLock::new(false)),
})
}
}
pub fn initialize(&self, init_args: CInitializeArgs) -> Result<()> {
let mut init_lock = self
.initialized
.as_ref()
.write()
.expect("lock not to be poisoned");
if *init_lock {
Err(Error::AlreadyInitialized)?
}
initialize(self, init_args).map(|_| *init_lock = true)
}
pub fn is_initialized(&self) -> bool {
*self
.initialized
.as_ref()
.read()
.expect("lock not to be poisoned")
}
pub fn finalize(self) {}
pub fn get_library_info(&self) -> Result<Info> {
get_library_info(self)
}
pub fn is_fn_supported(&self, function: Function) -> bool {
is_fn_supported(self, function)
}
}