Skip to content

Commit 0e0a4c9

Browse files
Trait for custom mutex lifecycle
Signed-off-by: Alexandru Placinta <placintaalexandru1@gmail.com>
1 parent 816da50 commit 0e0a4c9

File tree

3 files changed

+223
-107
lines changed

3 files changed

+223
-107
lines changed

cryptoki/src/context/general_purpose.rs

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// SPDX-License-Identifier: Apache-2.0
33
//! General-purpose functions
44
5-
use crate::context::{CInitializeArgs, Info, Pkcs11};
5+
use crate::context::{Info, Pkcs11};
66
use crate::error::{Result, Rv};
77
use cryptoki_sys::{CK_C_INITIALIZE_ARGS, CK_INFO};
88
use paste::paste;
@@ -11,7 +11,10 @@ use std::fmt::Display;
1111

1212
// See public docs on stub in parent mod.rs
1313
#[inline(always)]
14-
pub(super) fn initialize(ctx: &Pkcs11, init_args: CInitializeArgs) -> Result<()> {
14+
pub(super) fn initialize<T>(ctx: &Pkcs11, init_args: T) -> Result<()>
15+
where
16+
CK_C_INITIALIZE_ARGS: From<T>,
17+
{
1518
// if no args are specified, library expects NULL
1619
let mut init_args = CK_C_INITIALIZE_ARGS::from(init_args);
1720
let init_args_ptr = &mut init_args;

cryptoki/src/context/locking.rs

Lines changed: 213 additions & 104 deletions
Original file line numberDiff line numberDiff line change
@@ -2,92 +2,223 @@
22
// SPDX-License-Identifier: Apache-2.0
33
//! Locking related type
44
5-
use cryptoki_sys::{CKF_LIBRARY_CANT_CREATE_OS_THREADS, CKF_OS_LOCKING_OK, CK_FLAGS, CK_RV};
5+
use bitflags::bitflags;
6+
use cryptoki_sys::{
7+
CKF_LIBRARY_CANT_CREATE_OS_THREADS, CKF_OS_LOCKING_OK, CKR_GENERAL_ERROR, CKR_HOST_MEMORY,
8+
CKR_MUTEX_BAD, CKR_MUTEX_NOT_LOCKED, CKR_OK, CK_FLAGS, CK_RV,
9+
};
610

711
use std::{
812
os::raw::c_void,
913
ptr::{self, NonNull},
1014
};
1115

12-
/// Function pointer that creates a mutex
13-
pub type CreateMutexFn = unsafe extern "C" fn(*mut *mut ::std::os::raw::c_void) -> CK_RV;
16+
/// Error that occurs during mutex creation
17+
#[derive(Copy, Clone, Debug)]
18+
pub enum CreateError {
19+
/// CKR_GENERAL_ERROR
20+
GeneralError,
21+
///CKR_HOST_MEMORY
22+
HostMemory,
23+
}
1424

15-
/// Function pointer that destroys a mutex
16-
pub type DestroyMutexFn = unsafe extern "C" fn(*mut ::std::os::raw::c_void) -> CK_RV;
25+
impl From<CreateError> for CK_RV {
26+
fn from(value: CreateError) -> Self {
27+
match value {
28+
CreateError::GeneralError => CKR_GENERAL_ERROR,
29+
CreateError::HostMemory => CKR_HOST_MEMORY,
30+
}
31+
}
32+
}
1733

18-
/// Function pointer that locks a mutex
19-
pub type LockMutexFn = unsafe extern "C" fn(*mut ::std::os::raw::c_void) -> CK_RV;
34+
/// Error that occurs during mutex destruction
35+
#[derive(Copy, Clone, Debug)]
36+
pub enum DestroyError {
37+
/// CKR_GENERAL_ERROR
38+
GeneralError,
39+
/// CKR_HOST_MEMORY
40+
HostMemory,
41+
/// CKR_MUTEX_BAD
42+
MutexBad,
43+
}
2044

21-
/// Function pointer that unlocks a mutex
22-
pub type UnlockMutexFn = unsafe extern "C" fn(*mut ::std::os::raw::c_void) -> CK_RV;
45+
impl From<DestroyError> for CK_RV {
46+
fn from(value: DestroyError) -> Self {
47+
match value {
48+
DestroyError::GeneralError => CKR_GENERAL_ERROR,
49+
DestroyError::HostMemory => CKR_HOST_MEMORY,
50+
DestroyError::MutexBad => CKR_MUTEX_BAD,
51+
}
52+
}
53+
}
2354

24-
/// Provides function pointers for mutex-handling to ensure safe multi-threaded access.
55+
/// Error that occurs during mutex lock
2556
#[derive(Copy, Clone, Debug)]
26-
pub struct CustomMutexHandling {
27-
create_mutex: CreateMutexFn,
28-
destroy_mutex: DestroyMutexFn,
29-
lock_mutex: LockMutexFn,
30-
unlock_mutex: UnlockMutexFn,
57+
pub enum LockError {
58+
/// CKR_GENERAL_ERROR
59+
GeneralError,
60+
/// CKR_HOST_MEMORY
61+
HostMemory,
62+
/// CKR_MUTEX_BAD
63+
MutexBad,
3164
}
3265

33-
impl CustomMutexHandling {
34-
/// Create a new `CustomMutexHandling` with the given function pointers
35-
/// to handle library's thread safety.
36-
///
37-
/// # Safety
38-
/// Considered unsafe due to user's ability to pass any function pointer.
39-
pub const unsafe fn new(
40-
create_mutex: CreateMutexFn,
41-
destroy_mutex: DestroyMutexFn,
42-
lock_mutex: LockMutexFn,
43-
unlock_mutex: UnlockMutexFn,
44-
) -> Self {
45-
Self {
46-
create_mutex: create_mutex,
47-
destroy_mutex: destroy_mutex,
48-
lock_mutex: lock_mutex,
49-
unlock_mutex: unlock_mutex,
66+
impl From<LockError> for CK_RV {
67+
fn from(value: LockError) -> Self {
68+
match value {
69+
LockError::GeneralError => CKR_GENERAL_ERROR,
70+
LockError::HostMemory => CKR_HOST_MEMORY,
71+
LockError::MutexBad => CKR_MUTEX_BAD,
5072
}
5173
}
5274
}
5375

54-
/// Flags to set for the initialize function
76+
/// Error that occurs during mutex unlock
5577
#[derive(Copy, Clone, Debug)]
56-
pub enum CInitializeFlags {
57-
/// The library won’t be accessed from multiple threads simultaneously
58-
None,
59-
/// The library may not create its own threads
60-
NoOsThreads,
61-
/// The library can use the native OS library for locking or the custom
62-
OsThreads,
63-
/// The library needs to use the supplied function pointers
64-
/// for mutex-handling to ensure safe multi-threaded access.
65-
CustomMutexHandling(CustomMutexHandling),
66-
/// The library needs to use either the native operating system primitives
67-
/// or the supplied function pointers for mutex-handling to ensure safe
68-
/// multi-threaded access
69-
OsThreadsOrCustomMutexHandling(CustomMutexHandling),
78+
pub enum UnlockError {
79+
/// CKR_GENERAL_ERROR
80+
GeneralError,
81+
/// CKR_HOST_MEMORY
82+
HostMemory,
83+
/// CKR_MUTEX_BAD
84+
MutexBad,
85+
/// CKR_MUTEX_NOT_LOCKED
86+
MutexNotLocked,
87+
}
88+
89+
impl From<UnlockError> for CK_RV {
90+
fn from(value: UnlockError) -> Self {
91+
match value {
92+
UnlockError::GeneralError => CKR_GENERAL_ERROR,
93+
UnlockError::HostMemory => CKR_HOST_MEMORY,
94+
UnlockError::MutexBad => CKR_MUTEX_BAD,
95+
UnlockError::MutexNotLocked => CKR_MUTEX_NOT_LOCKED,
96+
}
97+
}
98+
}
99+
100+
/// Trait to manage lifecycle of mutex objects
101+
pub trait MutexLifeCycle {
102+
/// Creates a mutex
103+
fn create() -> Result<Box<Self>, CreateError>;
104+
105+
/// Destroys a mutex
106+
fn destroy(&mut self) -> Result<(), DestroyError>;
107+
108+
/// Locks a mutex
109+
fn lock(&self) -> Result<(), DestroyError>;
110+
111+
/// Unlocks a mutex
112+
fn unlock(&self) -> Result<(), UnlockError>;
113+
}
114+
115+
unsafe extern "C" fn create_mutex<M: MutexLifeCycle>(
116+
ptr_ptr: *mut *mut ::std::os::raw::c_void,
117+
) -> CK_RV {
118+
match M::create() {
119+
Ok(mutex) => {
120+
*ptr_ptr = Box::into_raw(mutex) as *mut c_void;
121+
CKR_OK
122+
}
123+
Err(err) => err.into(),
124+
}
125+
}
126+
127+
unsafe extern "C" fn destroy_mutex<M: MutexLifeCycle>(
128+
mutex_ptr: *mut ::std::os::raw::c_void,
129+
) -> CK_RV {
130+
// SAFETY: This is invoked after create_mutex
131+
let mut mutex = unsafe { Box::<M>::from_raw(mutex_ptr as *mut M) };
132+
133+
match mutex.destroy() {
134+
Ok(_) => CKR_OK,
135+
Err(err) => err.into(),
136+
}
137+
}
138+
139+
unsafe extern "C" fn lock_mutex<M: MutexLifeCycle>(
140+
mutex_ptr: *mut ::std::os::raw::c_void,
141+
) -> CK_RV {
142+
// SAFETY: This is invoked after create_mutex
143+
let mutex = unsafe { Box::<M>::from_raw(mutex_ptr as *mut M) };
144+
145+
match mutex.lock() {
146+
Ok(_) => CKR_OK,
147+
Err(err) => err.into(),
148+
}
149+
}
150+
151+
unsafe extern "C" fn unlock_mutex<M: MutexLifeCycle>(
152+
mutex_ptr: *mut ::std::os::raw::c_void,
153+
) -> CK_RV {
154+
// SAFETY: This is invoked after create_mutex
155+
let mutex = unsafe { Box::<M>::from_raw(mutex_ptr as *mut M) };
156+
match mutex.unlock() {
157+
Ok(_) => CKR_OK,
158+
Err(err) => err.into(),
159+
}
160+
}
161+
162+
bitflags! {
163+
/// Flags to set for the initialize function
164+
#[derive(Debug, Clone, Copy)]
165+
pub struct CInitializeFlags: CK_FLAGS {
166+
/// The library can use the native OS library for locking or the custom
167+
const OS_LOCKING_OK = CKF_OS_LOCKING_OK;
168+
/// The library may not create its own threads
169+
const LIBRARY_CANT_CREATE_OS_THREADS = CKF_LIBRARY_CANT_CREATE_OS_THREADS;
170+
}
70171
}
71172

72-
#[derive(Copy, Clone, Debug)]
73173
/// Argument for the initialize function
74-
pub struct CInitializeArgs {
174+
#[derive(Debug, Clone, Copy)]
175+
pub struct CInitializeArgs<M> {
75176
flags: CInitializeFlags,
177+
mutex_lifecycle: Option<M>,
76178
p_reserved: Option<NonNull<c_void>>,
77179
}
78180

79-
impl CInitializeArgs {
181+
impl CInitializeArgs<()> {
80182
/// Create a new `CInitializeArgs` with the given flags
81183
///
82184
/// # Examples
83185
/// ```
84186
/// use cryptoki::context::{CInitializeArgs, CInitializeFlags};
85187
///
86-
/// let args = CInitializeArgs::new(CInitializeFlags::OsThreads);
188+
/// let args = CInitializeArgs::<()>::new(CInitializeFlags::OS_LOCKING_OK | CInitializeFlags::LIBRARY_CANT_CREATE_OS_THREADS);
87189
/// ```
190+
pub fn new(flags: CInitializeFlags) -> Self {
191+
Self {
192+
flags,
193+
mutex_lifecycle: None,
194+
p_reserved: None,
195+
}
196+
}
197+
198+
/// Create a new `CInitializeArgs` with the given flags and reserved pointer.
199+
///
200+
/// # Safety
201+
/// Considered unsafe due to the user's ability to pass any pointer.
202+
///
203+
/// The user is responsible for managing the memory behind the pointer.
204+
pub const unsafe fn new_with_reserved(
205+
flags: CInitializeFlags,
206+
p_reserved: NonNull<c_void>,
207+
) -> Self {
208+
Self {
209+
flags,
210+
mutex_lifecycle: None,
211+
p_reserved: Some(p_reserved),
212+
}
213+
}
214+
}
215+
216+
impl<M: MutexLifeCycle> CInitializeArgs<M> {
217+
/// Create a new `CInitializeArgs` with the given flags
88218
pub const fn new(flags: CInitializeFlags) -> Self {
89219
Self {
90220
flags,
221+
mutex_lifecycle: None,
91222
p_reserved: None,
92223
}
93224
}
@@ -104,69 +235,47 @@ impl CInitializeArgs {
104235
) -> Self {
105236
Self {
106237
flags,
238+
mutex_lifecycle: None,
107239
p_reserved: Some(p_reserved),
108240
}
109241
}
110242
}
111243

112-
impl From<CInitializeArgs> for cryptoki_sys::CK_C_INITIALIZE_ARGS {
113-
fn from(c_initialize_args: CInitializeArgs) -> Self {
114-
let mut flags = CK_FLAGS::default();
244+
impl From<CInitializeArgs<()>> for cryptoki_sys::CK_C_INITIALIZE_ARGS {
245+
fn from(c_initialize_args: CInitializeArgs<()>) -> Self {
246+
let flags = c_initialize_args.flags.bits();
247+
let p_reserved = c_initialize_args
248+
.p_reserved
249+
.map(|non_null| non_null.as_ptr())
250+
.unwrap_or_else(ptr::null_mut);
251+
252+
Self {
253+
CreateMutex: None,
254+
DestroyMutex: None,
255+
LockMutex: None,
256+
UnlockMutex: None,
257+
flags,
258+
pReserved: p_reserved,
259+
}
260+
}
261+
}
262+
263+
impl<M: MutexLifeCycle> From<CInitializeArgs<M>> for cryptoki_sys::CK_C_INITIALIZE_ARGS {
264+
fn from(c_initialize_args: CInitializeArgs<M>) -> Self {
265+
let flags = c_initialize_args.flags.bits();
115266
let p_reserved = c_initialize_args
116267
.p_reserved
117268
.map(|non_null| non_null.as_ptr())
118269
.unwrap_or_else(ptr::null_mut);
270+
let mutex_lifecycle = c_initialize_args.mutex_lifecycle;
119271

120-
match c_initialize_args.flags {
121-
CInitializeFlags::None => Self {
122-
CreateMutex: None,
123-
DestroyMutex: None,
124-
LockMutex: None,
125-
UnlockMutex: None,
126-
flags,
127-
pReserved: p_reserved,
128-
},
129-
CInitializeFlags::NoOsThreads => {
130-
flags |= CKF_LIBRARY_CANT_CREATE_OS_THREADS;
131-
Self {
132-
flags,
133-
CreateMutex: None,
134-
DestroyMutex: None,
135-
LockMutex: None,
136-
UnlockMutex: None,
137-
pReserved: p_reserved,
138-
}
139-
}
140-
CInitializeFlags::OsThreads => {
141-
flags |= CKF_OS_LOCKING_OK;
142-
Self {
143-
flags,
144-
CreateMutex: None,
145-
DestroyMutex: None,
146-
LockMutex: None,
147-
UnlockMutex: None,
148-
pReserved: p_reserved,
149-
}
150-
}
151-
CInitializeFlags::CustomMutexHandling(custom_mutex_handling) => Self {
152-
flags,
153-
CreateMutex: Some(custom_mutex_handling.create_mutex),
154-
DestroyMutex: Some(custom_mutex_handling.destroy_mutex),
155-
LockMutex: Some(custom_mutex_handling.lock_mutex),
156-
UnlockMutex: Some(custom_mutex_handling.unlock_mutex),
157-
pReserved: p_reserved,
158-
},
159-
CInitializeFlags::OsThreadsOrCustomMutexHandling(custom_mutex_handling) => {
160-
flags |= CKF_OS_LOCKING_OK;
161-
Self {
162-
flags,
163-
CreateMutex: Some(custom_mutex_handling.create_mutex),
164-
DestroyMutex: Some(custom_mutex_handling.destroy_mutex),
165-
LockMutex: Some(custom_mutex_handling.lock_mutex),
166-
UnlockMutex: Some(custom_mutex_handling.unlock_mutex),
167-
pReserved: p_reserved,
168-
}
169-
}
272+
Self {
273+
CreateMutex: mutex_lifecycle.as_ref().map(|_| create_mutex::<M> as _),
274+
DestroyMutex: mutex_lifecycle.as_ref().map(|_| destroy_mutex::<M> as _),
275+
LockMutex: mutex_lifecycle.as_ref().map(|_| lock_mutex::<M> as _),
276+
UnlockMutex: mutex_lifecycle.as_ref().map(|_| unlock_mutex::<M> as _),
277+
flags,
278+
pReserved: p_reserved,
170279
}
171280
}
172281
}

0 commit comments

Comments
 (0)