Skip to content
Draft
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
7 changes: 5 additions & 2 deletions cryptoki/src/context/general_purpose.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
// SPDX-License-Identifier: Apache-2.0
//! General-purpose functions

use crate::context::{CInitializeArgs, Info, Pkcs11};
use crate::context::{Info, Pkcs11};
use crate::error::{Result, Rv};
use cryptoki_sys::{CK_C_INITIALIZE_ARGS, CK_INFO};
use paste::paste;
Expand All @@ -12,7 +12,10 @@ use std::ptr;

// See public docs on stub in parent mod.rs
#[inline(always)]
pub(super) fn initialize(ctx: &Pkcs11, init_args: CInitializeArgs) -> Result<()> {
pub(super) fn initialize<T>(ctx: &Pkcs11, init_args: T) -> Result<()>
where
CK_C_INITIALIZE_ARGS: From<T>,
{
// if no args are specified, library expects NULL
let mut init_args = CK_C_INITIALIZE_ARGS::from(init_args);
let init_args_ptr = &mut init_args;
Expand Down
214 changes: 213 additions & 1 deletion cryptoki/src/context/locking.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,14 @@
//! Locking related type

use bitflags::bitflags;
use cryptoki_sys::{self, CK_C_INITIALIZE_ARGS, CK_FLAGS};
use cryptoki_sys::{
self, CKR_GENERAL_ERROR, CKR_HOST_MEMORY, CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED, CKR_OK,
CK_C_INITIALIZE_ARGS, CK_FLAGS, CK_RV,
};

use std::{
marker::PhantomData,
mem::ManuallyDrop,
os::raw::c_void,
ptr::{self, NonNull},
};
Expand All @@ -21,6 +26,163 @@ bitflags! {
}
}

/// Error that occurs during mutex creation
#[derive(Copy, Clone, Debug)]
pub enum CreateError {
/// CKR_GENERAL_ERROR
GeneralError,
///CKR_HOST_MEMORY
HostMemory,
}

impl From<CreateError> for CK_RV {
fn from(value: CreateError) -> Self {
match value {
CreateError::GeneralError => CKR_GENERAL_ERROR,
CreateError::HostMemory => CKR_HOST_MEMORY,
}
}
}

/// Error that occurs during mutex destruction
#[derive(Copy, Clone, Debug)]
pub enum DestroyError {
/// CKR_GENERAL_ERROR
GeneralError,
/// CKR_HOST_MEMORY
HostMemory,
/// CKR_MUTEX_BAD
MutexBad,
}

impl From<DestroyError> for CK_RV {
fn from(value: DestroyError) -> Self {
match value {
DestroyError::GeneralError => CKR_GENERAL_ERROR,
DestroyError::HostMemory => CKR_HOST_MEMORY,
DestroyError::MutexBad => CKR_MUTEX_BAD,
}
}
}

/// Error that occurs during mutex lock
#[derive(Copy, Clone, Debug)]
pub enum LockError {
/// CKR_GENERAL_ERROR
GeneralError,
/// CKR_HOST_MEMORY
HostMemory,
/// CKR_MUTEX_BAD
MutexBad,
}

impl From<LockError> for CK_RV {
fn from(value: LockError) -> Self {
match value {
LockError::GeneralError => CKR_GENERAL_ERROR,
LockError::HostMemory => CKR_HOST_MEMORY,
LockError::MutexBad => CKR_MUTEX_BAD,
}
}
}

/// Error that occurs during mutex unlock
#[derive(Copy, Clone, Debug)]
pub enum UnlockError {
/// CKR_GENERAL_ERROR
GeneralError,
/// CKR_HOST_MEMORY
HostMemory,
/// CKR_MUTEX_BAD
MutexBad,
/// CKR_MUTEX_NOT_LOCKED
MutexNotLocked,
}

impl From<UnlockError> for CK_RV {
fn from(value: UnlockError) -> Self {
match value {
UnlockError::GeneralError => CKR_GENERAL_ERROR,
UnlockError::HostMemory => CKR_HOST_MEMORY,
UnlockError::MutexBad => CKR_MUTEX_BAD,
UnlockError::MutexNotLocked => CKR_MUTEX_NOT_LOCKED,
}
}
}

/// Trait to manage lifecycle of mutex objects
pub trait MutexLifeCycle: Send + Sync {
/// Creates a mutex
fn create() -> Result<Box<Self>, CreateError>;

/// Destroys a mutex
fn destroy(&mut self) -> Result<(), DestroyError>;

/// Locks a mutex
fn lock(&self) -> Result<(), DestroyError>;

/// Unlocks a mutex
fn unlock(&self) -> Result<(), UnlockError>;
}

unsafe extern "C" fn create_mutex<M: MutexLifeCycle>(
ptr_ptr: *mut *mut ::std::os::raw::c_void,
) -> CK_RV {
match M::create() {
Ok(mutex) => {
// SAFETY: This is called by the PKCS#11 library when it needs to
// create a mutex so ptr_ptr contains the address of a valid pointer
unsafe {
*ptr_ptr = Box::into_raw(mutex) as *mut c_void;
}

CKR_OK
}
Err(err) => err.into(),
}
}

unsafe extern "C" fn destroy_mutex<M: MutexLifeCycle>(
mutex_ptr: *mut ::std::os::raw::c_void,
) -> CK_RV {
// SAFETY: This is invoked after create_mutex
// Here we want to drop so ManuallyDrop is not necessary
let mut mutex = unsafe { Box::<M>::from_raw(mutex_ptr as *mut M) };

match mutex.destroy() {
Ok(_) => CKR_OK,
Err(err) => err.into(),
}
}

unsafe extern "C" fn lock_mutex<M: MutexLifeCycle>(
mutex_ptr: *mut ::std::os::raw::c_void,
) -> CK_RV {
// SAFETY: This is invoked after create_mutex
let boxed_mutex = unsafe { Box::<M>::from_raw(mutex_ptr as *mut M) };
// Avoid the call of Box::drop at the end of the function
let mutex = ManuallyDrop::new(boxed_mutex);

match mutex.lock() {
Ok(_) => CKR_OK,
Err(err) => err.into(),
}
}

unsafe extern "C" fn unlock_mutex<M: MutexLifeCycle>(
mutex_ptr: *mut ::std::os::raw::c_void,
) -> CK_RV {
// SAFETY: This is invoked after create_mutex
let boxed_mutex = unsafe { Box::<M>::from_raw(mutex_ptr as *mut M) };
// Avoid the call of Box::drop at the end of the function
let mutex = ManuallyDrop::new(boxed_mutex);

match mutex.unlock() {
Ok(_) => CKR_OK,
Err(err) => err.into(),
}
}

/// Argument for the initialize function
#[derive(Debug, Clone, Copy)]
pub struct CInitializeArgs {
Expand Down Expand Up @@ -106,3 +268,53 @@ impl From<CInitializeArgs> for CK_C_INITIALIZE_ARGS {
}
}
}

/// Argument for the initialize function
#[derive(Debug, Clone, Copy)]
pub struct CInitializeArgsWithMutex<M> {
flags: CInitializeFlags,
p_reserved: Option<NonNull<c_void>>,
_phantom: PhantomData<M>,
}

impl<M> CInitializeArgsWithMutex<M> {
/// Create a new `CInitializeArgsWithMutex` with the given mutex manager and flags
pub fn new(flags: CInitializeFlags) -> Self {
Self {
flags,
p_reserved: None,
_phantom: PhantomData,
}
}

/// Create a new `CInitializeArgsWithMutex` with the given mutex manager, flags and reserved pointer.
pub const unsafe fn new_with_reserved(
flags: CInitializeFlags,
p_reserved: NonNull<c_void>,
) -> Self {
Self {
flags,
p_reserved: Some(p_reserved),
_phantom: PhantomData,
}
}
}

impl<M: MutexLifeCycle> From<CInitializeArgsWithMutex<M>> for CK_C_INITIALIZE_ARGS {
fn from(c_initialize_args: CInitializeArgsWithMutex<M>) -> Self {
let flags = c_initialize_args.flags.bits();
let p_reserved = c_initialize_args
.p_reserved
.map(|non_null| non_null.as_ptr())
.unwrap_or_else(ptr::null_mut);

Self {
CreateMutex: Some(create_mutex::<M> as _),
DestroyMutex: Some(destroy_mutex::<M> as _),
LockMutex: Some(lock_mutex::<M> as _),
UnlockMutex: Some(unlock_mutex::<M> as _),
flags,
pReserved: p_reserved,
}
}
}
6 changes: 5 additions & 1 deletion cryptoki/src/context/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ mod locking;
mod session_management;
mod slot_token_management;

use cryptoki_sys::CK_C_INITIALIZE_ARGS;
pub use general_purpose::*;
pub use info::*;
pub use locking::*;
Expand Down Expand Up @@ -161,7 +162,10 @@ impl Pkcs11 {
}

/// Initialize the PKCS11 library
pub fn initialize(&self, init_args: CInitializeArgs) -> Result<()> {
pub fn initialize<T>(&self, init_args: T) -> Result<()>
where
CK_C_INITIALIZE_ARGS: From<T>,
{
initialize(self, init_args)
}

Expand Down
Loading