1 /* -*- Mode: rust; rust-indent-offset: 4 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #![allow(non_snake_case)]
8 extern crate byteorder;
9 #[cfg(any(target_os = "macos", target_os = "ios"))]
11 extern crate core_foundation;
12 extern crate env_logger;
13 #[cfg(any(target_os = "macos", target_os = "ios"))]
15 extern crate lazy_static;
16 #[cfg(target_os = "macos")]
17 extern crate libloading;
20 extern crate pkcs11_bindings;
22 extern crate rsclientcerts;
24 #[cfg(target_os = "windows")]
27 use pkcs11_bindings::*;
28 use rsclientcerts::manager::{ManagerProxy, SlotType};
33 #[cfg(any(target_os = "macos", target_os = "ios"))]
35 #[cfg(target_os = "windows")]
38 #[cfg(any(target_os = "macos", target_os = "ios"))]
39 use crate::backend_macos::Backend;
40 #[cfg(target_os = "windows")]
41 use crate::backend_windows::Backend;
44 manager_proxy: ManagerProxy,
45 mechanisms: Vec<CK_MECHANISM_TYPE>,
48 /// The singleton `ModuleState` that handles state with respect to PKCS #11. Only one thread
49 /// may use it at a time, but there is no restriction on which threads may use it. However, as
50 /// OS APIs being used are not necessarily thread-safe (e.g. they may be using
51 /// thread-local-storage), the `ManagerProxy` of the `ModuleState` forwards calls from any
52 /// thread to a single thread where the real `Manager` does the actual work.
53 static MODULE_STATE: Mutex<Option<ModuleState>> = Mutex::new(None);
55 // Obtaining a handle on the manager proxy is a two-step process. First the mutex must be locked,
56 // which (if successful), results in a mutex guard object. We must then get a mutable refence to the
57 // underlying manager proxy (if set - otherwise we return an error). This can't happen all in one
58 // macro without dropping a reference that needs to live long enough for this to be safe. In
59 // practice, this looks like:
60 // let mut module_state_guard = try_to_get_module_state_guard!();
61 // let manager = module_state_guard_to_manager!(module_state_guard);
62 macro_rules! try_to_get_module_state_guard {
64 match MODULE_STATE.lock() {
65 Ok(maybe_module_state) => maybe_module_state,
66 Err(poison_error) => {
69 "previous thread panicked acquiring manager lock: {}",
72 return CKR_DEVICE_ERROR;
78 macro_rules! module_state_guard_to_manager {
79 ($module_state_guard:ident) => {
80 match $module_state_guard.as_mut() {
81 Some(module_state) => &mut module_state.manager_proxy,
83 log_with_thread_id!(error, "module state expected to be set, but it is not");
84 return CKR_DEVICE_ERROR;
90 macro_rules! module_state_guard_to_mechanisms {
91 ($module_state_guard:ident) => {
92 match $module_state_guard.as_ref() {
93 Some(module_state) => &module_state.mechanisms,
95 log_with_thread_id!(error, "module state expected to be set, but it is not");
96 return CKR_DEVICE_ERROR;
102 // Helper macro to prefix log messages with the current thread ID.
103 macro_rules! log_with_thread_id {
104 ($log_level:ident, $($message:expr),*) => {
105 $log_level!("{:?} {}", thread::current().id(), format_args!($($message),*));
109 /// This gets called to initialize the module. For this implementation, this consists of
110 /// instantiating the `ManagerProxy`.
111 extern "C" fn C_Initialize(pInitArgs: CK_VOID_PTR) -> CK_RV {
112 // This will fail if this has already been called, but this isn't a problem because either way,
113 // logging has been initialized.
114 let _ = env_logger::try_init();
116 if pInitArgs.is_null() {
117 return CKR_DEVICE_ERROR;
119 let init_args_ptr = unsafe { (*(pInitArgs as CK_C_INITIALIZE_ARGS_PTR)).pReserved };
120 if init_args_ptr.is_null() {
121 return CKR_DEVICE_ERROR;
123 let init_args_cstr = unsafe { CStr::from_ptr(init_args_ptr as *mut std::os::raw::c_char) };
124 let init_args = match init_args_cstr.to_str() {
125 Ok(init_args) => init_args,
126 Err(_) => return CKR_DEVICE_ERROR,
128 let mechanisms = if init_args == "RSA-PSS" {
129 vec![CKM_ECDSA, CKM_RSA_PKCS, CKM_RSA_PKCS_PSS]
131 vec![CKM_ECDSA, CKM_RSA_PKCS]
133 let mut module_state_guard = try_to_get_module_state_guard!();
134 let manager_proxy = match ManagerProxy::new(Backend {}) {
137 log_with_thread_id!(error, "C_Initialize: ManagerProxy: {}", e);
138 return CKR_DEVICE_ERROR;
141 match module_state_guard.replace(ModuleState {
145 Some(_unexpected_previous_module_state) => {
146 #[cfg(any(target_os = "macos", target_os = "ios"))]
148 log_with_thread_id!(info, "C_Initialize: module state previously set (this is expected on macOS - replacing it)");
150 #[cfg(target_os = "windows")]
154 "C_Initialize: module state unexpectedly previously set (replacing it)"
160 log_with_thread_id!(debug, "C_Initialize: CKR_OK");
164 extern "C" fn C_Finalize(_pReserved: CK_VOID_PTR) -> CK_RV {
165 let mut module_state_guard = try_to_get_module_state_guard!();
166 let manager = module_state_guard_to_manager!(module_state_guard);
167 match manager.stop() {
169 log_with_thread_id!(debug, "C_Finalize: CKR_OK");
173 log_with_thread_id!(error, "C_Finalize: CKR_DEVICE_ERROR: {}", e);
179 // The specification mandates that these strings be padded with spaces to the appropriate length.
180 // Since the length of fixed-size arrays in rust is part of the type, the compiler enforces that
181 // these byte strings are of the correct length.
182 const MANUFACTURER_ID_BYTES: &[u8; 32] = b"Mozilla Corporation ";
183 const LIBRARY_DESCRIPTION_BYTES: &[u8; 32] = b"OS Client Cert Module ";
185 /// This gets called to gather some information about the module. In particular, this implementation
186 /// supports (portions of) cryptoki (PKCS #11) version 2.2.
187 extern "C" fn C_GetInfo(pInfo: CK_INFO_PTR) -> CK_RV {
189 log_with_thread_id!(error, "C_GetInfo: CKR_ARGUMENTS_BAD");
190 return CKR_ARGUMENTS_BAD;
192 log_with_thread_id!(debug, "C_GetInfo: CKR_OK");
193 let mut info = CK_INFO::default();
194 info.cryptokiVersion.major = 2;
195 info.cryptokiVersion.minor = 2;
196 info.manufacturerID = *MANUFACTURER_ID_BYTES;
197 info.libraryDescription = *LIBRARY_DESCRIPTION_BYTES;
204 /// This module has one slot.
205 const SLOT_COUNT: CK_ULONG = 1;
206 const SLOT_ID: CK_SLOT_ID = 1;
208 /// This gets called twice: once with a null `pSlotList` to get the number of slots (returned via
209 /// `pulCount`) and a second time to get the ID for each slot.
210 extern "C" fn C_GetSlotList(
211 _tokenPresent: CK_BBOOL,
212 pSlotList: CK_SLOT_ID_PTR,
213 pulCount: CK_ULONG_PTR,
215 if pulCount.is_null() {
216 log_with_thread_id!(error, "C_GetSlotList: CKR_ARGUMENTS_BAD");
217 return CKR_ARGUMENTS_BAD;
219 if !pSlotList.is_null() {
220 if unsafe { *pulCount } < SLOT_COUNT {
221 log_with_thread_id!(error, "C_GetSlotList: CKR_BUFFER_TOO_SMALL");
222 return CKR_BUFFER_TOO_SMALL;
225 *pSlotList = SLOT_ID;
229 *pulCount = SLOT_COUNT;
231 log_with_thread_id!(debug, "C_GetSlotList: CKR_OK");
235 const SLOT_DESCRIPTION_BYTES: &[u8; 64] =
236 b"OS Client Cert Slot ";
238 /// This gets called to obtain information about slots. In this implementation, the token is
239 /// always present in the singular slot.
240 extern "C" fn C_GetSlotInfo(slotID: CK_SLOT_ID, pInfo: CK_SLOT_INFO_PTR) -> CK_RV {
241 if slotID != SLOT_ID || pInfo.is_null() {
242 log_with_thread_id!(error, "C_GetSlotInfo: CKR_ARGUMENTS_BAD");
243 return CKR_ARGUMENTS_BAD;
245 let slot_info = CK_SLOT_INFO {
246 slotDescription: *SLOT_DESCRIPTION_BYTES,
247 manufacturerID: *MANUFACTURER_ID_BYTES,
248 flags: CKF_TOKEN_PRESENT,
249 hardwareVersion: CK_VERSION::default(),
250 firmwareVersion: CK_VERSION::default(),
255 log_with_thread_id!(debug, "C_GetSlotInfo: CKR_OK");
259 const TOKEN_LABEL_BYTES: &[u8; 32] = b"OS Client Cert Token ";
260 const TOKEN_MODEL_BYTES: &[u8; 16] = b"osclientcerts ";
261 const TOKEN_SERIAL_NUMBER_BYTES: &[u8; 16] = b"0000000000000000";
263 /// This gets called to obtain some information about tokens. This implementation has one slot,
264 /// so it has one token. This information is primarily for display purposes.
265 extern "C" fn C_GetTokenInfo(slotID: CK_SLOT_ID, pInfo: CK_TOKEN_INFO_PTR) -> CK_RV {
266 if slotID != SLOT_ID || pInfo.is_null() {
267 log_with_thread_id!(error, "C_GetTokenInfo: CKR_ARGUMENTS_BAD");
268 return CKR_ARGUMENTS_BAD;
270 let mut token_info = CK_TOKEN_INFO::default();
271 token_info.label = *TOKEN_LABEL_BYTES;
272 token_info.manufacturerID = *MANUFACTURER_ID_BYTES;
273 token_info.model = *TOKEN_MODEL_BYTES;
274 token_info.serialNumber = *TOKEN_SERIAL_NUMBER_BYTES;
278 log_with_thread_id!(debug, "C_GetTokenInfo: CKR_OK");
282 /// This gets called to determine what mechanisms a slot supports. The singular slot supports
283 /// ECDSA and RSA PKCS1. Depending on the configuration the module was loaded with, it may also
285 extern "C" fn C_GetMechanismList(
287 pMechanismList: CK_MECHANISM_TYPE_PTR,
288 pulCount: CK_ULONG_PTR,
290 if slotID != SLOT_ID || pulCount.is_null() {
291 log_with_thread_id!(error, "C_GetMechanismList: CKR_ARGUMENTS_BAD");
292 return CKR_ARGUMENTS_BAD;
294 let module_state_guard = try_to_get_module_state_guard!();
295 let mechanisms = module_state_guard_to_mechanisms!(module_state_guard);
296 if !pMechanismList.is_null() {
297 if unsafe { *pulCount as usize } < mechanisms.len() {
298 log_with_thread_id!(error, "C_GetMechanismList: CKR_ARGUMENTS_BAD");
299 return CKR_ARGUMENTS_BAD;
301 for (i, mechanism) in mechanisms.iter().enumerate() {
303 *pMechanismList.add(i) = *mechanism;
308 *pulCount = mechanisms.len() as CK_ULONG;
310 log_with_thread_id!(debug, "C_GetMechanismList: CKR_OK");
314 extern "C" fn C_GetMechanismInfo(
316 _type: CK_MECHANISM_TYPE,
317 _pInfo: CK_MECHANISM_INFO_PTR,
319 log_with_thread_id!(error, "C_GetMechanismInfo: CKR_FUNCTION_NOT_SUPPORTED");
320 CKR_FUNCTION_NOT_SUPPORTED
323 extern "C" fn C_InitToken(
325 _pPin: CK_UTF8CHAR_PTR,
327 _pLabel: CK_UTF8CHAR_PTR,
329 log_with_thread_id!(error, "C_InitToken: CKR_FUNCTION_NOT_SUPPORTED");
330 CKR_FUNCTION_NOT_SUPPORTED
333 extern "C" fn C_InitPIN(
334 _hSession: CK_SESSION_HANDLE,
335 _pPin: CK_UTF8CHAR_PTR,
338 log_with_thread_id!(error, "C_InitPIN: CKR_FUNCTION_NOT_SUPPORTED");
339 CKR_FUNCTION_NOT_SUPPORTED
342 extern "C" fn C_SetPIN(
343 _hSession: CK_SESSION_HANDLE,
344 _pOldPin: CK_UTF8CHAR_PTR,
346 _pNewPin: CK_UTF8CHAR_PTR,
349 log_with_thread_id!(error, "C_SetPIN: CKR_FUNCTION_NOT_SUPPORTED");
350 CKR_FUNCTION_NOT_SUPPORTED
353 /// This gets called to create a new session. This module defers to the `ManagerProxy` to implement
355 extern "C" fn C_OpenSession(
358 _pApplication: CK_VOID_PTR,
360 phSession: CK_SESSION_HANDLE_PTR,
362 if slotID != SLOT_ID || phSession.is_null() {
363 log_with_thread_id!(error, "C_OpenSession: CKR_ARGUMENTS_BAD");
364 return CKR_ARGUMENTS_BAD;
366 let mut module_state_guard = try_to_get_module_state_guard!();
367 let manager = module_state_guard_to_manager!(module_state_guard);
368 // The "modern"/"legacy" slot distinction still exists in ipcclientcerts,
369 // which shares some library code with this module, to allow for a more
370 // nuanced notion of whether or not e.g. RSA-PSS is supported.
371 let session_handle = match manager.open_session(SlotType::Modern) {
372 Ok(session_handle) => session_handle,
374 log_with_thread_id!(error, "C_OpenSession: open_session failed: {}", e);
375 return CKR_DEVICE_ERROR;
379 *phSession = session_handle;
381 log_with_thread_id!(debug, "C_OpenSession: CKR_OK");
385 /// This gets called to close a session. This is handled by the `ManagerProxy`.
386 extern "C" fn C_CloseSession(hSession: CK_SESSION_HANDLE) -> CK_RV {
387 let mut module_state_guard = try_to_get_module_state_guard!();
388 let manager = module_state_guard_to_manager!(module_state_guard);
389 if manager.close_session(hSession).is_err() {
390 log_with_thread_id!(error, "C_CloseSession: CKR_SESSION_HANDLE_INVALID");
391 return CKR_SESSION_HANDLE_INVALID;
393 log_with_thread_id!(debug, "C_CloseSession: CKR_OK");
397 /// This gets called to close all open sessions at once. This is handled by the `ManagerProxy`.
398 extern "C" fn C_CloseAllSessions(slotID: CK_SLOT_ID) -> CK_RV {
399 if slotID != SLOT_ID {
400 log_with_thread_id!(error, "C_CloseAllSessions: CKR_ARGUMENTS_BAD");
401 return CKR_ARGUMENTS_BAD;
403 let mut module_state_guard = try_to_get_module_state_guard!();
404 let manager = module_state_guard_to_manager!(module_state_guard);
405 match manager.close_all_sessions(SlotType::Modern) {
407 log_with_thread_id!(debug, "C_CloseAllSessions: CKR_OK");
413 "C_CloseAllSessions: close_all_sessions failed: {}",
421 extern "C" fn C_GetSessionInfo(_hSession: CK_SESSION_HANDLE, _pInfo: CK_SESSION_INFO_PTR) -> CK_RV {
422 log_with_thread_id!(error, "C_GetSessionInfo: CKR_FUNCTION_NOT_SUPPORTED");
423 CKR_FUNCTION_NOT_SUPPORTED
426 extern "C" fn C_GetOperationState(
427 _hSession: CK_SESSION_HANDLE,
428 _pOperationState: CK_BYTE_PTR,
429 _pulOperationStateLen: CK_ULONG_PTR,
431 log_with_thread_id!(error, "C_GetOperationState: CKR_FUNCTION_NOT_SUPPORTED");
432 CKR_FUNCTION_NOT_SUPPORTED
435 extern "C" fn C_SetOperationState(
436 _hSession: CK_SESSION_HANDLE,
437 _pOperationState: CK_BYTE_PTR,
438 _ulOperationStateLen: CK_ULONG,
439 _hEncryptionKey: CK_OBJECT_HANDLE,
440 _hAuthenticationKey: CK_OBJECT_HANDLE,
442 log_with_thread_id!(error, "C_SetOperationState: CKR_FUNCTION_NOT_SUPPORTED");
443 CKR_FUNCTION_NOT_SUPPORTED
446 extern "C" fn C_Login(
447 _hSession: CK_SESSION_HANDLE,
448 _userType: CK_USER_TYPE,
449 _pPin: CK_UTF8CHAR_PTR,
452 log_with_thread_id!(error, "C_Login: CKR_FUNCTION_NOT_SUPPORTED");
453 CKR_FUNCTION_NOT_SUPPORTED
456 /// This gets called to log out and drop any authenticated resources. Because this module does not
457 /// hold on to authenticated resources, this module "implements" this by doing nothing and
458 /// returning a success result.
459 extern "C" fn C_Logout(_hSession: CK_SESSION_HANDLE) -> CK_RV {
460 log_with_thread_id!(debug, "C_Logout: CKR_OK");
464 extern "C" fn C_CreateObject(
465 _hSession: CK_SESSION_HANDLE,
466 _pTemplate: CK_ATTRIBUTE_PTR,
468 _phObject: CK_OBJECT_HANDLE_PTR,
470 log_with_thread_id!(error, "C_CreateObject: CKR_FUNCTION_NOT_SUPPORTED");
471 CKR_FUNCTION_NOT_SUPPORTED
474 extern "C" fn C_CopyObject(
475 _hSession: CK_SESSION_HANDLE,
476 _hObject: CK_OBJECT_HANDLE,
477 _pTemplate: CK_ATTRIBUTE_PTR,
479 _phNewObject: CK_OBJECT_HANDLE_PTR,
481 log_with_thread_id!(error, "C_CopyObject: CKR_FUNCTION_NOT_SUPPORTED");
482 CKR_FUNCTION_NOT_SUPPORTED
485 extern "C" fn C_DestroyObject(_hSession: CK_SESSION_HANDLE, _hObject: CK_OBJECT_HANDLE) -> CK_RV {
486 log_with_thread_id!(error, "C_DestroyObject: CKR_FUNCTION_NOT_SUPPORTED");
487 CKR_FUNCTION_NOT_SUPPORTED
490 extern "C" fn C_GetObjectSize(
491 _hSession: CK_SESSION_HANDLE,
492 _hObject: CK_OBJECT_HANDLE,
493 _pulSize: CK_ULONG_PTR,
495 log_with_thread_id!(error, "C_GetObjectSize: CKR_FUNCTION_NOT_SUPPORTED");
496 CKR_FUNCTION_NOT_SUPPORTED
499 /// This gets called to obtain the values of a number of attributes of an object identified by the
500 /// given handle. This module implements this by requesting that the `ManagerProxy` find the object
501 /// and attempt to get the value of each attribute. If a specified attribute is not defined on the
502 /// object, the length of that attribute is set to -1 to indicate that it is not available.
503 /// This gets called twice: once to obtain the lengths of the attributes and again to get the
505 extern "C" fn C_GetAttributeValue(
506 _hSession: CK_SESSION_HANDLE,
507 hObject: CK_OBJECT_HANDLE,
508 pTemplate: CK_ATTRIBUTE_PTR,
511 if pTemplate.is_null() {
512 log_with_thread_id!(error, "C_GetAttributeValue: CKR_ARGUMENTS_BAD");
513 return CKR_ARGUMENTS_BAD;
515 let mut attr_types = Vec::with_capacity(ulCount as usize);
516 for i in 0..ulCount as usize {
517 let attr = unsafe { &*pTemplate.add(i) };
518 attr_types.push(attr.type_);
520 let mut module_state_guard = try_to_get_module_state_guard!();
521 let manager = module_state_guard_to_manager!(module_state_guard);
522 let values = match manager.get_attributes(hObject, attr_types) {
523 Ok(values) => values,
525 log_with_thread_id!(error, "C_GetAttributeValue: CKR_ARGUMENTS_BAD ({})", e);
526 return CKR_ARGUMENTS_BAD;
529 if values.len() != ulCount as usize {
532 "C_GetAttributeValue: manager.get_attributes didn't return the right number of values"
534 return CKR_DEVICE_ERROR;
536 for (i, value) in values.iter().enumerate().take(ulCount as usize) {
537 let attr = unsafe { &mut *pTemplate.add(i) };
538 if let Some(attr_value) = value {
539 if attr.pValue.is_null() {
540 attr.ulValueLen = attr_value.len() as CK_ULONG;
542 let ptr: *mut u8 = attr.pValue as *mut u8;
543 if attr_value.len() != attr.ulValueLen as usize {
544 log_with_thread_id!(error, "C_GetAttributeValue: incorrect attr size");
545 return CKR_ARGUMENTS_BAD;
548 std::ptr::copy_nonoverlapping(attr_value.as_ptr(), ptr, attr_value.len());
552 attr.ulValueLen = (0 - 1) as CK_ULONG;
555 log_with_thread_id!(debug, "C_GetAttributeValue: CKR_OK");
559 extern "C" fn C_SetAttributeValue(
560 _hSession: CK_SESSION_HANDLE,
561 _hObject: CK_OBJECT_HANDLE,
562 _pTemplate: CK_ATTRIBUTE_PTR,
565 log_with_thread_id!(error, "C_SetAttributeValue: CKR_FUNCTION_NOT_SUPPORTED");
566 CKR_FUNCTION_NOT_SUPPORTED
569 fn trace_attr(prefix: &str, attr: &CK_ATTRIBUTE) {
570 let typ = match unsafe_packed_field_access!(attr.type_) {
571 CKA_CLASS => "CKA_CLASS".to_string(),
572 CKA_TOKEN => "CKA_TOKEN".to_string(),
573 CKA_LABEL => "CKA_LABEL".to_string(),
574 CKA_ID => "CKA_ID".to_string(),
575 CKA_VALUE => "CKA_VALUE".to_string(),
576 CKA_ISSUER => "CKA_ISSUER".to_string(),
577 CKA_SERIAL_NUMBER => "CKA_SERIAL_NUMBER".to_string(),
578 CKA_SUBJECT => "CKA_SUBJECT".to_string(),
579 CKA_PRIVATE => "CKA_PRIVATE".to_string(),
580 CKA_KEY_TYPE => "CKA_KEY_TYPE".to_string(),
581 CKA_MODULUS => "CKA_MODULUS".to_string(),
582 CKA_EC_PARAMS => "CKA_EC_PARAMS".to_string(),
583 _ => format!("0x{:x}", unsafe_packed_field_access!(attr.type_)),
586 unsafe { std::slice::from_raw_parts(attr.pValue as *const u8, attr.ulValueLen as usize) };
589 "{}CK_ATTRIBUTE {{ type: {}, pValue: {:?}, ulValueLen: {} }}",
593 unsafe_packed_field_access!(attr.ulValueLen)
597 const RELEVANT_ATTRIBUTES: &[CK_ATTRIBUTE_TYPE] = &[
612 /// This gets called to initialize a search for objects matching a given list of attributes. This
613 /// module implements this by gathering the attributes and passing them to the `ManagerProxy` to
614 /// start the search.
615 extern "C" fn C_FindObjectsInit(
616 hSession: CK_SESSION_HANDLE,
617 pTemplate: CK_ATTRIBUTE_PTR,
620 if pTemplate.is_null() {
621 log_with_thread_id!(error, "C_FindObjectsInit: CKR_ARGUMENTS_BAD");
622 return CKR_ARGUMENTS_BAD;
624 let mut attrs = Vec::new();
625 log_with_thread_id!(trace, "C_FindObjectsInit:");
626 for i in 0..ulCount as usize {
627 let attr = unsafe { &*pTemplate.add(i) };
628 trace_attr(" ", attr);
629 // Copy out the attribute type to avoid making a reference to an unaligned field.
630 let attr_type = attr.type_;
631 if !RELEVANT_ATTRIBUTES.contains(&attr_type) {
634 "C_FindObjectsInit: irrelevant attribute, returning CKR_ATTRIBUTE_TYPE_INVALID"
636 return CKR_ATTRIBUTE_TYPE_INVALID;
639 std::slice::from_raw_parts(attr.pValue as *const u8, attr.ulValueLen as usize)
641 attrs.push((attr_type, slice.to_owned()));
643 let mut module_state_guard = try_to_get_module_state_guard!();
644 let manager = module_state_guard_to_manager!(module_state_guard);
645 match manager.start_search(hSession, attrs) {
648 log_with_thread_id!(error, "C_FindObjectsInit: CKR_ARGUMENTS_BAD: {}", e);
649 return CKR_ARGUMENTS_BAD;
652 log_with_thread_id!(debug, "C_FindObjectsInit: CKR_OK");
656 /// This gets called after `C_FindObjectsInit` to get the results of a search. This module
657 /// implements this by looking up the search in the `ManagerProxy` and copying out the matching
659 extern "C" fn C_FindObjects(
660 hSession: CK_SESSION_HANDLE,
661 phObject: CK_OBJECT_HANDLE_PTR,
662 ulMaxObjectCount: CK_ULONG,
663 pulObjectCount: CK_ULONG_PTR,
665 if phObject.is_null() || pulObjectCount.is_null() || ulMaxObjectCount == 0 {
666 log_with_thread_id!(error, "C_FindObjects: CKR_ARGUMENTS_BAD");
667 return CKR_ARGUMENTS_BAD;
669 let mut module_state_guard = try_to_get_module_state_guard!();
670 let manager = module_state_guard_to_manager!(module_state_guard);
671 let handles = match manager.search(hSession, ulMaxObjectCount as usize) {
672 Ok(handles) => handles,
674 log_with_thread_id!(error, "C_FindObjects: CKR_ARGUMENTS_BAD: {}", e);
675 return CKR_ARGUMENTS_BAD;
678 log_with_thread_id!(debug, "C_FindObjects: found handles {:?}", handles);
679 if handles.len() > ulMaxObjectCount as usize {
680 log_with_thread_id!(error, "C_FindObjects: manager returned too many handles");
681 return CKR_DEVICE_ERROR;
684 *pulObjectCount = handles.len() as CK_ULONG;
686 for (index, handle) in handles.iter().enumerate() {
687 if index < ulMaxObjectCount as usize {
689 *(phObject.add(index)) = *handle;
693 log_with_thread_id!(debug, "C_FindObjects: CKR_OK");
697 /// This gets called after `C_FindObjectsInit` and `C_FindObjects` to finish a search. The module
698 /// tells the `ManagerProxy` to clear the search.
699 extern "C" fn C_FindObjectsFinal(hSession: CK_SESSION_HANDLE) -> CK_RV {
700 let mut module_state_guard = try_to_get_module_state_guard!();
701 let manager = module_state_guard_to_manager!(module_state_guard);
702 // It would be an error if there were no search for this session, but we can be permissive here.
703 match manager.clear_search(hSession) {
705 log_with_thread_id!(debug, "C_FindObjectsFinal: CKR_OK");
709 log_with_thread_id!(error, "C_FindObjectsFinal: clear_search failed: {}", e);
715 extern "C" fn C_EncryptInit(
716 _hSession: CK_SESSION_HANDLE,
717 _pMechanism: CK_MECHANISM_PTR,
718 _hKey: CK_OBJECT_HANDLE,
720 log_with_thread_id!(error, "C_EncryptInit: CKR_FUNCTION_NOT_SUPPORTED");
721 CKR_FUNCTION_NOT_SUPPORTED
724 extern "C" fn C_Encrypt(
725 _hSession: CK_SESSION_HANDLE,
727 _ulDataLen: CK_ULONG,
728 _pEncryptedData: CK_BYTE_PTR,
729 _pulEncryptedDataLen: CK_ULONG_PTR,
731 log_with_thread_id!(error, "C_Encrypt: CKR_FUNCTION_NOT_SUPPORTED");
732 CKR_FUNCTION_NOT_SUPPORTED
735 extern "C" fn C_EncryptUpdate(
736 _hSession: CK_SESSION_HANDLE,
738 _ulPartLen: CK_ULONG,
739 _pEncryptedPart: CK_BYTE_PTR,
740 _pulEncryptedPartLen: CK_ULONG_PTR,
742 log_with_thread_id!(error, "C_EncryptUpdate: CKR_FUNCTION_NOT_SUPPORTED");
743 CKR_FUNCTION_NOT_SUPPORTED
746 extern "C" fn C_EncryptFinal(
747 _hSession: CK_SESSION_HANDLE,
748 _pLastEncryptedPart: CK_BYTE_PTR,
749 _pulLastEncryptedPartLen: CK_ULONG_PTR,
751 log_with_thread_id!(error, "C_EncryptFinal: CKR_FUNCTION_NOT_SUPPORTED");
752 CKR_FUNCTION_NOT_SUPPORTED
755 extern "C" fn C_DecryptInit(
756 _hSession: CK_SESSION_HANDLE,
757 _pMechanism: CK_MECHANISM_PTR,
758 _hKey: CK_OBJECT_HANDLE,
760 log_with_thread_id!(error, "C_DecryptInit: CKR_FUNCTION_NOT_SUPPORTED");
761 CKR_FUNCTION_NOT_SUPPORTED
764 extern "C" fn C_Decrypt(
765 _hSession: CK_SESSION_HANDLE,
766 _pEncryptedData: CK_BYTE_PTR,
767 _ulEncryptedDataLen: CK_ULONG,
769 _pulDataLen: CK_ULONG_PTR,
771 log_with_thread_id!(error, "C_Decrypt: CKR_FUNCTION_NOT_SUPPORTED");
772 CKR_FUNCTION_NOT_SUPPORTED
775 extern "C" fn C_DecryptUpdate(
776 _hSession: CK_SESSION_HANDLE,
777 _pEncryptedPart: CK_BYTE_PTR,
778 _ulEncryptedPartLen: CK_ULONG,
780 _pulPartLen: CK_ULONG_PTR,
782 log_with_thread_id!(error, "C_DecryptUpdate: CKR_FUNCTION_NOT_SUPPORTED");
783 CKR_FUNCTION_NOT_SUPPORTED
786 extern "C" fn C_DecryptFinal(
787 _hSession: CK_SESSION_HANDLE,
788 _pLastPart: CK_BYTE_PTR,
789 _pulLastPartLen: CK_ULONG_PTR,
791 log_with_thread_id!(error, "C_DecryptFinal: CKR_FUNCTION_NOT_SUPPORTED");
792 CKR_FUNCTION_NOT_SUPPORTED
795 extern "C" fn C_DigestInit(_hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR) -> CK_RV {
796 log_with_thread_id!(error, "C_DigestInit: CKR_FUNCTION_NOT_SUPPORTED");
797 CKR_FUNCTION_NOT_SUPPORTED
800 extern "C" fn C_Digest(
801 _hSession: CK_SESSION_HANDLE,
803 _ulDataLen: CK_ULONG,
804 _pDigest: CK_BYTE_PTR,
805 _pulDigestLen: CK_ULONG_PTR,
807 log_with_thread_id!(error, "C_Digest: CKR_FUNCTION_NOT_SUPPORTED");
808 CKR_FUNCTION_NOT_SUPPORTED
811 extern "C" fn C_DigestUpdate(
812 _hSession: CK_SESSION_HANDLE,
814 _ulPartLen: CK_ULONG,
816 log_with_thread_id!(error, "C_DigestUpdate: CKR_FUNCTION_NOT_SUPPORTED");
817 CKR_FUNCTION_NOT_SUPPORTED
820 extern "C" fn C_DigestKey(_hSession: CK_SESSION_HANDLE, _hKey: CK_OBJECT_HANDLE) -> CK_RV {
821 log_with_thread_id!(error, "C_DigestKey: CKR_FUNCTION_NOT_SUPPORTED");
822 CKR_FUNCTION_NOT_SUPPORTED
825 extern "C" fn C_DigestFinal(
826 _hSession: CK_SESSION_HANDLE,
827 _pDigest: CK_BYTE_PTR,
828 _pulDigestLen: CK_ULONG_PTR,
830 log_with_thread_id!(error, "C_DigestFinal: CKR_FUNCTION_NOT_SUPPORTED");
831 CKR_FUNCTION_NOT_SUPPORTED
834 /// This gets called to set up a sign operation. The module essentially defers to the
836 extern "C" fn C_SignInit(
837 hSession: CK_SESSION_HANDLE,
838 pMechanism: CK_MECHANISM_PTR,
839 hKey: CK_OBJECT_HANDLE,
841 if pMechanism.is_null() {
842 log_with_thread_id!(error, "C_SignInit: CKR_ARGUMENTS_BAD");
843 return CKR_ARGUMENTS_BAD;
845 // Presumably we should validate the mechanism against hKey, but the specification doesn't
846 // actually seem to require this.
847 let mechanism = unsafe { *pMechanism };
848 log_with_thread_id!(debug, "C_SignInit: mechanism is {:?}", mechanism);
849 let mechanism_params = if mechanism.mechanism == CKM_RSA_PKCS_PSS {
850 if mechanism.ulParameterLen as usize != std::mem::size_of::<CK_RSA_PKCS_PSS_PARAMS>() {
853 "C_SignInit: bad ulParameterLen for CKM_RSA_PKCS_PSS: {}",
854 unsafe_packed_field_access!(mechanism.ulParameterLen)
856 return CKR_ARGUMENTS_BAD;
858 Some(unsafe { *(mechanism.pParameter as *const CK_RSA_PKCS_PSS_PARAMS) })
862 let mut module_state_guard = try_to_get_module_state_guard!();
863 let manager = module_state_guard_to_manager!(module_state_guard);
864 match manager.start_sign(hSession, hKey, mechanism_params) {
867 log_with_thread_id!(error, "C_SignInit: CKR_GENERAL_ERROR: {}", e);
868 return CKR_GENERAL_ERROR;
871 log_with_thread_id!(debug, "C_SignInit: CKR_OK");
875 /// NSS calls this after `C_SignInit` (there are more ways in the PKCS #11 specification to sign
876 /// data, but this is the only way supported by this module). The module essentially defers to the
877 /// `ManagerProxy` and copies out the resulting signature.
878 extern "C" fn C_Sign(
879 hSession: CK_SESSION_HANDLE,
882 pSignature: CK_BYTE_PTR,
883 pulSignatureLen: CK_ULONG_PTR,
885 if pData.is_null() || pulSignatureLen.is_null() {
886 log_with_thread_id!(error, "C_Sign: CKR_ARGUMENTS_BAD");
887 return CKR_ARGUMENTS_BAD;
889 let data = unsafe { std::slice::from_raw_parts(pData, ulDataLen as usize) };
890 if pSignature.is_null() {
891 let mut module_state_guard = try_to_get_module_state_guard!();
892 let manager = module_state_guard_to_manager!(module_state_guard);
893 match manager.get_signature_length(hSession, data.to_vec()) {
894 Ok(signature_length) => unsafe {
895 *pulSignatureLen = signature_length as CK_ULONG;
898 log_with_thread_id!(error, "C_Sign: get_signature_length failed: {}", e);
899 log_with_thread_id!(error, "C_Sign: try setting security.osclientcerts.assume_rsa_pss_support to false and restarting");
900 return CKR_GENERAL_ERROR;
904 let mut module_state_guard = try_to_get_module_state_guard!();
905 let manager = module_state_guard_to_manager!(module_state_guard);
906 match manager.sign(hSession, data.to_vec()) {
908 let signature_capacity = unsafe { *pulSignatureLen } as usize;
909 if signature_capacity < signature.len() {
910 log_with_thread_id!(error, "C_Sign: CKR_ARGUMENTS_BAD");
911 return CKR_ARGUMENTS_BAD;
913 let ptr: *mut u8 = pSignature as *mut u8;
915 std::ptr::copy_nonoverlapping(signature.as_ptr(), ptr, signature.len());
916 *pulSignatureLen = signature.len() as CK_ULONG;
920 log_with_thread_id!(error, "C_Sign: sign failed: {}", e);
921 log_with_thread_id!(error, "C_Sign: try setting security.osclientcerts.assume_rsa_pss_support to false and restarting");
922 return CKR_GENERAL_ERROR;
926 log_with_thread_id!(debug, "C_Sign: CKR_OK");
930 extern "C" fn C_SignUpdate(
931 _hSession: CK_SESSION_HANDLE,
933 _ulPartLen: CK_ULONG,
935 log_with_thread_id!(error, "C_SignUpdate: CKR_FUNCTION_NOT_SUPPORTED");
936 CKR_FUNCTION_NOT_SUPPORTED
939 extern "C" fn C_SignFinal(
940 _hSession: CK_SESSION_HANDLE,
941 _pSignature: CK_BYTE_PTR,
942 _pulSignatureLen: CK_ULONG_PTR,
944 log_with_thread_id!(error, "C_SignFinal: CKR_FUNCTION_NOT_SUPPORTED");
945 CKR_FUNCTION_NOT_SUPPORTED
948 extern "C" fn C_SignRecoverInit(
949 _hSession: CK_SESSION_HANDLE,
950 _pMechanism: CK_MECHANISM_PTR,
951 _hKey: CK_OBJECT_HANDLE,
953 log_with_thread_id!(error, "C_SignRecoverInit: CKR_FUNCTION_NOT_SUPPORTED");
954 CKR_FUNCTION_NOT_SUPPORTED
957 extern "C" fn C_SignRecover(
958 _hSession: CK_SESSION_HANDLE,
960 _ulDataLen: CK_ULONG,
961 _pSignature: CK_BYTE_PTR,
962 _pulSignatureLen: CK_ULONG_PTR,
964 log_with_thread_id!(error, "C_SignRecover: CKR_FUNCTION_NOT_SUPPORTED");
965 CKR_FUNCTION_NOT_SUPPORTED
968 extern "C" fn C_VerifyInit(
969 _hSession: CK_SESSION_HANDLE,
970 _pMechanism: CK_MECHANISM_PTR,
971 _hKey: CK_OBJECT_HANDLE,
973 log_with_thread_id!(error, "C_VerifyInit: CKR_FUNCTION_NOT_SUPPORTED");
974 CKR_FUNCTION_NOT_SUPPORTED
977 extern "C" fn C_Verify(
978 _hSession: CK_SESSION_HANDLE,
980 _ulDataLen: CK_ULONG,
981 _pSignature: CK_BYTE_PTR,
982 _ulSignatureLen: CK_ULONG,
984 log_with_thread_id!(error, "C_Verify: CKR_FUNCTION_NOT_SUPPORTED");
985 CKR_FUNCTION_NOT_SUPPORTED
988 extern "C" fn C_VerifyUpdate(
989 _hSession: CK_SESSION_HANDLE,
991 _ulPartLen: CK_ULONG,
993 log_with_thread_id!(error, "C_VerifyUpdate: CKR_FUNCTION_NOT_SUPPORTED");
994 CKR_FUNCTION_NOT_SUPPORTED
997 extern "C" fn C_VerifyFinal(
998 _hSession: CK_SESSION_HANDLE,
999 _pSignature: CK_BYTE_PTR,
1000 _ulSignatureLen: CK_ULONG,
1002 log_with_thread_id!(error, "C_VerifyFinal: CKR_FUNCTION_NOT_SUPPORTED");
1003 CKR_FUNCTION_NOT_SUPPORTED
1006 extern "C" fn C_VerifyRecoverInit(
1007 _hSession: CK_SESSION_HANDLE,
1008 _pMechanism: CK_MECHANISM_PTR,
1009 _hKey: CK_OBJECT_HANDLE,
1011 log_with_thread_id!(error, "C_VerifyRecoverInit: CKR_FUNCTION_NOT_SUPPORTED");
1012 CKR_FUNCTION_NOT_SUPPORTED
1015 extern "C" fn C_VerifyRecover(
1016 _hSession: CK_SESSION_HANDLE,
1017 _pSignature: CK_BYTE_PTR,
1018 _ulSignatureLen: CK_ULONG,
1019 _pData: CK_BYTE_PTR,
1020 _pulDataLen: CK_ULONG_PTR,
1022 log_with_thread_id!(error, "C_VerifyRecover: CKR_FUNCTION_NOT_SUPPORTED");
1023 CKR_FUNCTION_NOT_SUPPORTED
1026 extern "C" fn C_DigestEncryptUpdate(
1027 _hSession: CK_SESSION_HANDLE,
1028 _pPart: CK_BYTE_PTR,
1029 _ulPartLen: CK_ULONG,
1030 _pEncryptedPart: CK_BYTE_PTR,
1031 _pulEncryptedPartLen: CK_ULONG_PTR,
1033 log_with_thread_id!(error, "C_DigestEncryptUpdate: CKR_FUNCTION_NOT_SUPPORTED");
1034 CKR_FUNCTION_NOT_SUPPORTED
1037 extern "C" fn C_DecryptDigestUpdate(
1038 _hSession: CK_SESSION_HANDLE,
1039 _pEncryptedPart: CK_BYTE_PTR,
1040 _ulEncryptedPartLen: CK_ULONG,
1041 _pPart: CK_BYTE_PTR,
1042 _pulPartLen: CK_ULONG_PTR,
1044 log_with_thread_id!(error, "C_DecryptDigestUpdate: CKR_FUNCTION_NOT_SUPPORTED");
1045 CKR_FUNCTION_NOT_SUPPORTED
1048 extern "C" fn C_SignEncryptUpdate(
1049 _hSession: CK_SESSION_HANDLE,
1050 _pPart: CK_BYTE_PTR,
1051 _ulPartLen: CK_ULONG,
1052 _pEncryptedPart: CK_BYTE_PTR,
1053 _pulEncryptedPartLen: CK_ULONG_PTR,
1055 log_with_thread_id!(error, "C_SignEncryptUpdate: CKR_FUNCTION_NOT_SUPPORTED");
1056 CKR_FUNCTION_NOT_SUPPORTED
1059 extern "C" fn C_DecryptVerifyUpdate(
1060 _hSession: CK_SESSION_HANDLE,
1061 _pEncryptedPart: CK_BYTE_PTR,
1062 _ulEncryptedPartLen: CK_ULONG,
1063 _pPart: CK_BYTE_PTR,
1064 _pulPartLen: CK_ULONG_PTR,
1066 log_with_thread_id!(error, "C_DecryptVerifyUpdate: CKR_FUNCTION_NOT_SUPPORTED");
1067 CKR_FUNCTION_NOT_SUPPORTED
1070 extern "C" fn C_GenerateKey(
1071 _hSession: CK_SESSION_HANDLE,
1072 _pMechanism: CK_MECHANISM_PTR,
1073 _pTemplate: CK_ATTRIBUTE_PTR,
1075 _phKey: CK_OBJECT_HANDLE_PTR,
1077 log_with_thread_id!(error, "C_GenerateKey: CKR_FUNCTION_NOT_SUPPORTED");
1078 CKR_FUNCTION_NOT_SUPPORTED
1081 extern "C" fn C_GenerateKeyPair(
1082 _hSession: CK_SESSION_HANDLE,
1083 _pMechanism: CK_MECHANISM_PTR,
1084 _pPublicKeyTemplate: CK_ATTRIBUTE_PTR,
1085 _ulPublicKeyAttributeCount: CK_ULONG,
1086 _pPrivateKeyTemplate: CK_ATTRIBUTE_PTR,
1087 _ulPrivateKeyAttributeCount: CK_ULONG,
1088 _phPublicKey: CK_OBJECT_HANDLE_PTR,
1089 _phPrivateKey: CK_OBJECT_HANDLE_PTR,
1091 log_with_thread_id!(error, "C_GenerateKeyPair: CKR_FUNCTION_NOT_SUPPORTED");
1092 CKR_FUNCTION_NOT_SUPPORTED
1095 extern "C" fn C_WrapKey(
1096 _hSession: CK_SESSION_HANDLE,
1097 _pMechanism: CK_MECHANISM_PTR,
1098 _hWrappingKey: CK_OBJECT_HANDLE,
1099 _hKey: CK_OBJECT_HANDLE,
1100 _pWrappedKey: CK_BYTE_PTR,
1101 _pulWrappedKeyLen: CK_ULONG_PTR,
1103 log_with_thread_id!(error, "C_WrapKey: CKR_FUNCTION_NOT_SUPPORTED");
1104 CKR_FUNCTION_NOT_SUPPORTED
1107 extern "C" fn C_UnwrapKey(
1108 _hSession: CK_SESSION_HANDLE,
1109 _pMechanism: CK_MECHANISM_PTR,
1110 _hUnwrappingKey: CK_OBJECT_HANDLE,
1111 _pWrappedKey: CK_BYTE_PTR,
1112 _ulWrappedKeyLen: CK_ULONG,
1113 _pTemplate: CK_ATTRIBUTE_PTR,
1114 _ulAttributeCount: CK_ULONG,
1115 _phKey: CK_OBJECT_HANDLE_PTR,
1117 log_with_thread_id!(error, "C_UnwrapKey: CKR_FUNCTION_NOT_SUPPORTED");
1118 CKR_FUNCTION_NOT_SUPPORTED
1121 extern "C" fn C_DeriveKey(
1122 _hSession: CK_SESSION_HANDLE,
1123 _pMechanism: CK_MECHANISM_PTR,
1124 _hBaseKey: CK_OBJECT_HANDLE,
1125 _pTemplate: CK_ATTRIBUTE_PTR,
1126 _ulAttributeCount: CK_ULONG,
1127 _phKey: CK_OBJECT_HANDLE_PTR,
1129 log_with_thread_id!(error, "C_DeriveKey: CKR_FUNCTION_NOT_SUPPORTED");
1130 CKR_FUNCTION_NOT_SUPPORTED
1133 extern "C" fn C_SeedRandom(
1134 _hSession: CK_SESSION_HANDLE,
1135 _pSeed: CK_BYTE_PTR,
1136 _ulSeedLen: CK_ULONG,
1138 log_with_thread_id!(error, "C_SeedRandom: CKR_FUNCTION_NOT_SUPPORTED");
1139 CKR_FUNCTION_NOT_SUPPORTED
1142 extern "C" fn C_GenerateRandom(
1143 _hSession: CK_SESSION_HANDLE,
1144 _RandomData: CK_BYTE_PTR,
1145 _ulRandomLen: CK_ULONG,
1147 log_with_thread_id!(error, "C_GenerateRandom: CKR_FUNCTION_NOT_SUPPORTED");
1148 CKR_FUNCTION_NOT_SUPPORTED
1151 extern "C" fn C_GetFunctionStatus(_hSession: CK_SESSION_HANDLE) -> CK_RV {
1152 log_with_thread_id!(error, "C_GetFunctionStatus: CKR_FUNCTION_NOT_SUPPORTED");
1153 CKR_FUNCTION_NOT_SUPPORTED
1156 extern "C" fn C_CancelFunction(_hSession: CK_SESSION_HANDLE) -> CK_RV {
1157 log_with_thread_id!(error, "C_CancelFunction: CKR_FUNCTION_NOT_SUPPORTED");
1158 CKR_FUNCTION_NOT_SUPPORTED
1161 extern "C" fn C_WaitForSlotEvent(
1163 _pSlot: CK_SLOT_ID_PTR,
1164 _pRserved: CK_VOID_PTR,
1166 log_with_thread_id!(error, "C_WaitForSlotEvent: CKR_FUNCTION_NOT_SUPPORTED");
1167 CKR_FUNCTION_NOT_SUPPORTED
1170 /// To be a valid PKCS #11 module, this list of functions must be supported. At least cryptoki 2.2
1171 /// must be supported for this module to work in NSS.
1172 static FUNCTION_LIST: CK_FUNCTION_LIST = CK_FUNCTION_LIST {
1173 version: CK_VERSION { major: 2, minor: 2 },
1174 C_Initialize: Some(C_Initialize),
1175 C_Finalize: Some(C_Finalize),
1176 C_GetInfo: Some(C_GetInfo),
1177 C_GetFunctionList: None,
1178 C_GetSlotList: Some(C_GetSlotList),
1179 C_GetSlotInfo: Some(C_GetSlotInfo),
1180 C_GetTokenInfo: Some(C_GetTokenInfo),
1181 C_GetMechanismList: Some(C_GetMechanismList),
1182 C_GetMechanismInfo: Some(C_GetMechanismInfo),
1183 C_InitToken: Some(C_InitToken),
1184 C_InitPIN: Some(C_InitPIN),
1185 C_SetPIN: Some(C_SetPIN),
1186 C_OpenSession: Some(C_OpenSession),
1187 C_CloseSession: Some(C_CloseSession),
1188 C_CloseAllSessions: Some(C_CloseAllSessions),
1189 C_GetSessionInfo: Some(C_GetSessionInfo),
1190 C_GetOperationState: Some(C_GetOperationState),
1191 C_SetOperationState: Some(C_SetOperationState),
1192 C_Login: Some(C_Login),
1193 C_Logout: Some(C_Logout),
1194 C_CreateObject: Some(C_CreateObject),
1195 C_CopyObject: Some(C_CopyObject),
1196 C_DestroyObject: Some(C_DestroyObject),
1197 C_GetObjectSize: Some(C_GetObjectSize),
1198 C_GetAttributeValue: Some(C_GetAttributeValue),
1199 C_SetAttributeValue: Some(C_SetAttributeValue),
1200 C_FindObjectsInit: Some(C_FindObjectsInit),
1201 C_FindObjects: Some(C_FindObjects),
1202 C_FindObjectsFinal: Some(C_FindObjectsFinal),
1203 C_EncryptInit: Some(C_EncryptInit),
1204 C_Encrypt: Some(C_Encrypt),
1205 C_EncryptUpdate: Some(C_EncryptUpdate),
1206 C_EncryptFinal: Some(C_EncryptFinal),
1207 C_DecryptInit: Some(C_DecryptInit),
1208 C_Decrypt: Some(C_Decrypt),
1209 C_DecryptUpdate: Some(C_DecryptUpdate),
1210 C_DecryptFinal: Some(C_DecryptFinal),
1211 C_DigestInit: Some(C_DigestInit),
1212 C_Digest: Some(C_Digest),
1213 C_DigestUpdate: Some(C_DigestUpdate),
1214 C_DigestKey: Some(C_DigestKey),
1215 C_DigestFinal: Some(C_DigestFinal),
1216 C_SignInit: Some(C_SignInit),
1217 C_Sign: Some(C_Sign),
1218 C_SignUpdate: Some(C_SignUpdate),
1219 C_SignFinal: Some(C_SignFinal),
1220 C_SignRecoverInit: Some(C_SignRecoverInit),
1221 C_SignRecover: Some(C_SignRecover),
1222 C_VerifyInit: Some(C_VerifyInit),
1223 C_Verify: Some(C_Verify),
1224 C_VerifyUpdate: Some(C_VerifyUpdate),
1225 C_VerifyFinal: Some(C_VerifyFinal),
1226 C_VerifyRecoverInit: Some(C_VerifyRecoverInit),
1227 C_VerifyRecover: Some(C_VerifyRecover),
1228 C_DigestEncryptUpdate: Some(C_DigestEncryptUpdate),
1229 C_DecryptDigestUpdate: Some(C_DecryptDigestUpdate),
1230 C_SignEncryptUpdate: Some(C_SignEncryptUpdate),
1231 C_DecryptVerifyUpdate: Some(C_DecryptVerifyUpdate),
1232 C_GenerateKey: Some(C_GenerateKey),
1233 C_GenerateKeyPair: Some(C_GenerateKeyPair),
1234 C_WrapKey: Some(C_WrapKey),
1235 C_UnwrapKey: Some(C_UnwrapKey),
1236 C_DeriveKey: Some(C_DeriveKey),
1237 C_SeedRandom: Some(C_SeedRandom),
1238 C_GenerateRandom: Some(C_GenerateRandom),
1239 C_GetFunctionStatus: Some(C_GetFunctionStatus),
1240 C_CancelFunction: Some(C_CancelFunction),
1241 C_WaitForSlotEvent: Some(C_WaitForSlotEvent),
1246 /// This is the only function this module exposes. NSS calls it to obtain the list of functions
1247 /// comprising this module.
1248 /// ppFunctionList must be a valid pointer.
1250 pub unsafe extern "C" fn C_GetFunctionList(ppFunctionList: CK_FUNCTION_LIST_PTR_PTR) -> CK_RV {
1251 if ppFunctionList.is_null() {
1252 return CKR_ARGUMENTS_BAD;
1254 // CK_FUNCTION_LIST_PTR is a *mut CK_FUNCTION_LIST, but as per the
1255 // specification, the caller must treat it as *const CK_FUNCTION_LIST.
1256 *ppFunctionList = std::ptr::addr_of!(FUNCTION_LIST) as CK_FUNCTION_LIST_PTR;
1261 any(target_os = "macos", target_os = "ios"),
1262 link(name = "Security", kind = "framework")