1macro_rules! get_pkcs11 {
8 ($pkcs11:expr, $func_name:ident) => {
9 (get_pkcs11_func!($pkcs11, $func_name).ok_or(crate::error::Error::NullFunctionPointer)?)
10 };
11}
12
13macro_rules! get_pkcs11_func {
16 ($pkcs11:expr, $func_name:ident) => {
17 ($pkcs11.impl_.get_function_list().$func_name)
18 };
19}
20
21mod general_purpose;
22mod info;
23mod locking;
24mod session_management;
25mod slot_token_management;
26
27pub use general_purpose::*;
28pub use info::*;
29pub use locking::*;
30
31use crate::error::{Error, Result, Rv};
32
33use log::error;
34use std::fmt;
35use std::mem;
36use std::path::Path;
37use std::ptr;
38use std::sync::Arc;
39use std::sync::RwLock;
40
41#[derive(Debug)]
45enum FunctionList {
46 V2(cryptoki_sys::CK_FUNCTION_LIST_3_0),
48 V3_0(cryptoki_sys::CK_FUNCTION_LIST_3_0),
50 }
54
55pub(crate) struct Pkcs11Impl {
57 _pkcs11_lib: cryptoki_sys::Pkcs11,
60 function_list: FunctionList,
61}
62
63impl fmt::Debug for Pkcs11Impl {
64 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
65 f.debug_struct("Pkcs11Impl")
66 .field("function_list", &self.function_list)
67 .finish()
68 }
69}
70
71impl Pkcs11Impl {
72 #[inline(always)]
73 pub(crate) fn get_function_list(&self) -> cryptoki_sys::CK_FUNCTION_LIST_3_0 {
74 match self.function_list {
75 FunctionList::V2(l) => l,
76 FunctionList::V3_0(l) => l,
77 }
78 }
79
80 #[inline(always)]
82 fn finalize(&self) -> Result<()> {
83 unsafe {
84 Rv::from(self
85 .get_function_list()
86 .C_Finalize
87 .ok_or(Error::NullFunctionPointer)?(
88 ptr::null_mut()
89 ))
90 .into_result(Function::Finalize)
91 }
92 }
93}
94
95impl Drop for Pkcs11Impl {
96 fn drop(&mut self) {
97 if let Err(e) = self.finalize() {
98 error!("Failed to finalize: {}", e);
99 }
100 }
101}
102
103#[derive(Clone, Debug)]
105pub struct Pkcs11 {
106 pub(crate) impl_: Arc<Pkcs11Impl>,
107 initialized: Arc<RwLock<bool>>,
108}
109
110impl Pkcs11 {
111 pub fn new<P>(filename: P) -> Result<Self>
113 where
114 P: AsRef<Path>,
115 {
116 unsafe {
117 let pkcs11_lib =
118 cryptoki_sys::Pkcs11::new(filename.as_ref()).map_err(Error::LibraryLoading)?;
119 Self::_new(pkcs11_lib)
120 }
121 }
122
123 pub fn new_from_self() -> Result<Self> {
125 unsafe {
126 #[cfg(not(windows))]
127 let this_lib = libloading::os::unix::Library::this();
128 #[cfg(windows)]
129 let this_lib = libloading::os::windows::Library::this()?;
130 let pkcs11_lib = cryptoki_sys::Pkcs11::from_library(this_lib)?;
131 Self::_new(pkcs11_lib)
132 }
133 }
134
135 unsafe fn _new(pkcs11_lib: cryptoki_sys::Pkcs11) -> Result<Self> {
136 let mut interface = mem::MaybeUninit::uninit();
139 if pkcs11_lib.C_GetInterface.is_ok() {
140 Rv::from(pkcs11_lib.C_GetInterface(
141 ptr::null_mut(),
142 ptr::null_mut(),
143 interface.as_mut_ptr(),
144 0,
145 ))
146 .into_result(Function::GetInterface)?;
147 if !interface.as_ptr().is_null() {
148 let ifce_ptr: *mut cryptoki_sys::CK_INTERFACE = *interface.as_ptr();
149 let ifce: cryptoki_sys::CK_INTERFACE = *ifce_ptr;
150
151 let list_ptr: *mut cryptoki_sys::CK_FUNCTION_LIST =
152 ifce.pFunctionList as *mut cryptoki_sys::CK_FUNCTION_LIST;
153 let list: cryptoki_sys::CK_FUNCTION_LIST = *list_ptr;
154 if list.version.major >= 3 {
155 let list30_ptr: *mut cryptoki_sys::CK_FUNCTION_LIST_3_0 =
156 ifce.pFunctionList as *mut cryptoki_sys::CK_FUNCTION_LIST_3_0;
157 return Ok(Pkcs11 {
158 impl_: Arc::new(Pkcs11Impl {
159 _pkcs11_lib: pkcs11_lib,
160 function_list: FunctionList::V3_0(*list30_ptr),
161 }),
162 initialized: Arc::new(RwLock::new(false)),
163 });
164 }
165 }
167 }
168
169 let mut list = mem::MaybeUninit::uninit();
170
171 Rv::from(pkcs11_lib.C_GetFunctionList(list.as_mut_ptr()))
172 .into_result(Function::GetFunctionList)?;
173
174 let list_ptr = *list.as_ptr();
175
176 Ok(Pkcs11 {
177 impl_: Arc::new(Pkcs11Impl {
178 _pkcs11_lib: pkcs11_lib,
179 function_list: FunctionList::V2(v2tov3(*list_ptr)),
180 }),
181 initialized: Arc::new(RwLock::new(false)),
182 })
183 }
184
185 pub fn initialize(&self, init_args: CInitializeArgs) -> Result<()> {
187 let mut init_lock = self
188 .initialized
189 .as_ref()
190 .write()
191 .expect("lock not to be poisoned");
192 if *init_lock {
193 Err(Error::AlreadyInitialized)?
194 }
195 initialize(self, init_args).map(|_| *init_lock = true)
196 }
197
198 pub fn is_initialized(&self) -> bool {
200 *self
201 .initialized
202 .as_ref()
203 .read()
204 .expect("lock not to be poisoned")
205 }
206
207 pub fn finalize(self) {}
210
211 pub fn get_library_info(&self) -> Result<Info> {
213 get_library_info(self)
214 }
215
216 pub fn is_fn_supported(&self, function: Function) -> bool {
218 is_fn_supported(self, function)
219 }
220}
221
222fn v2tov3(f: cryptoki_sys::CK_FUNCTION_LIST) -> cryptoki_sys::CK_FUNCTION_LIST_3_0 {
224 cryptoki_sys::CK_FUNCTION_LIST_3_0 {
225 version: f.version,
226 C_Initialize: f.C_Initialize,
227 C_Finalize: f.C_Finalize,
228 C_GetInfo: f.C_GetInfo,
229 C_GetFunctionList: f.C_GetFunctionList,
230 C_GetSlotList: f.C_GetSlotList,
231 C_GetSlotInfo: f.C_GetSlotInfo,
232 C_GetTokenInfo: f.C_GetTokenInfo,
233 C_GetMechanismList: f.C_GetMechanismList,
234 C_GetMechanismInfo: f.C_GetMechanismInfo,
235 C_InitToken: f.C_InitToken,
236 C_InitPIN: f.C_InitPIN,
237 C_SetPIN: f.C_SetPIN,
238 C_OpenSession: f.C_OpenSession,
239 C_CloseSession: f.C_CloseSession,
240 C_CloseAllSessions: f.C_CloseAllSessions,
241 C_GetSessionInfo: f.C_GetSessionInfo,
242 C_GetOperationState: f.C_GetOperationState,
243 C_SetOperationState: f.C_SetOperationState,
244 C_Login: f.C_Login,
245 C_Logout: f.C_Logout,
246 C_CreateObject: f.C_CreateObject,
247 C_CopyObject: f.C_CopyObject,
248 C_DestroyObject: f.C_DestroyObject,
249 C_GetObjectSize: f.C_GetObjectSize,
250 C_GetAttributeValue: f.C_GetAttributeValue,
251 C_SetAttributeValue: f.C_SetAttributeValue,
252 C_FindObjectsInit: f.C_FindObjectsInit,
253 C_FindObjects: f.C_FindObjects,
254 C_FindObjectsFinal: f.C_FindObjectsFinal,
255 C_EncryptInit: f.C_EncryptInit,
256 C_Encrypt: f.C_Encrypt,
257 C_EncryptUpdate: f.C_EncryptUpdate,
258 C_EncryptFinal: f.C_EncryptFinal,
259 C_DecryptInit: f.C_DecryptInit,
260 C_Decrypt: f.C_Decrypt,
261 C_DecryptUpdate: f.C_DecryptUpdate,
262 C_DecryptFinal: f.C_DecryptFinal,
263 C_DigestInit: f.C_DigestInit,
264 C_Digest: f.C_Digest,
265 C_DigestUpdate: f.C_DigestUpdate,
266 C_DigestKey: f.C_DigestKey,
267 C_DigestFinal: f.C_DigestFinal,
268 C_SignInit: f.C_SignInit,
269 C_Sign: f.C_Sign,
270 C_SignUpdate: f.C_SignUpdate,
271 C_SignFinal: f.C_SignFinal,
272 C_SignRecoverInit: f.C_SignRecoverInit,
273 C_SignRecover: f.C_SignRecover,
274 C_VerifyInit: f.C_VerifyInit,
275 C_Verify: f.C_Verify,
276 C_VerifyUpdate: f.C_VerifyUpdate,
277 C_VerifyFinal: f.C_VerifyFinal,
278 C_VerifyRecoverInit: f.C_VerifyRecoverInit,
279 C_VerifyRecover: f.C_VerifyRecover,
280 C_DigestEncryptUpdate: f.C_DigestEncryptUpdate,
281 C_DecryptDigestUpdate: f.C_DecryptDigestUpdate,
282 C_SignEncryptUpdate: f.C_SignEncryptUpdate,
283 C_DecryptVerifyUpdate: f.C_DecryptVerifyUpdate,
284 C_GenerateKey: f.C_GenerateKey,
285 C_GenerateKeyPair: f.C_GenerateKeyPair,
286 C_WrapKey: f.C_WrapKey,
287 C_UnwrapKey: f.C_UnwrapKey,
288 C_DeriveKey: f.C_DeriveKey,
289 C_SeedRandom: f.C_SeedRandom,
290 C_GenerateRandom: f.C_GenerateRandom,
291 C_GetFunctionStatus: f.C_GetFunctionStatus,
292 C_CancelFunction: f.C_CancelFunction,
293 C_WaitForSlotEvent: f.C_WaitForSlotEvent,
294 C_GetInterfaceList: None,
295 C_GetInterface: None,
296 C_LoginUser: None,
297 C_SessionCancel: None,
298 C_MessageEncryptInit: None,
299 C_EncryptMessage: None,
300 C_EncryptMessageBegin: None,
301 C_EncryptMessageNext: None,
302 C_MessageEncryptFinal: None,
303 C_MessageDecryptInit: None,
304 C_DecryptMessage: None,
305 C_DecryptMessageBegin: None,
306 C_DecryptMessageNext: None,
307 C_MessageDecryptFinal: None,
308 C_MessageSignInit: None,
309 C_SignMessage: None,
310 C_SignMessageBegin: None,
311 C_SignMessageNext: None,
312 C_MessageSignFinal: None,
313 C_MessageVerifyInit: None,
314 C_VerifyMessage: None,
315 C_VerifyMessageBegin: None,
316 C_VerifyMessageNext: None,
317 C_MessageVerifyFinal: None,
318 }
319}