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 extern crate pkcs11_bindings;
11 extern crate rsclientcerts;
14 use pkcs11_bindings::*;
15 use rsclientcerts::manager::{Manager, SlotType};
16 use std::ffi::{c_void, CStr};
23 type FindObjectsCallback = Option<
35 type FindObjectsFunction = extern "C" fn(callback: FindObjectsCallback, ctx: *mut c_void);
38 Option<unsafe extern "C" fn(data_len: usize, data: *const u8, ctx: *mut c_void)>;
40 type SignFunction = extern "C" fn(
47 callback: SignCallback,
51 /// The singleton `Manager` that handles state with respect to PKCS #11. Only one thread
52 /// may use it at a time, but there is no restriction on which threads may use it.
53 static MANAGER: Mutex<Option<Manager<Backend>>> = Mutex::new(None);
55 // Obtaining a handle on the manager is a two-step process. First the mutex must be locked, which
56 // (if successful), results in a mutex guard object. We must then get a mutable refence to the
57 // underlying manager (if set - otherwise we return an error). This can't happen all in one macro
58 // without dropping a reference that needs to live long enough for this to be safe. In
59 // practice, this looks like:
60 // let mut manager_guard = try_to_get_manager_guard!();
61 // let manager = manager_guard_to_manager!(manager_guard);
62 macro_rules! try_to_get_manager_guard {
64 match MANAGER.lock() {
65 Ok(maybe_manager) => maybe_manager,
66 Err(_) => return CKR_DEVICE_ERROR,
71 macro_rules! manager_guard_to_manager {
72 ($manager_guard:ident) => {
73 match $manager_guard.as_mut() {
74 Some(manager) => manager,
75 None => return CKR_DEVICE_ERROR,
80 /// This gets called to initialize the module. For this implementation, this consists of
81 /// instantiating the `Manager`.
82 extern "C" fn C_Initialize(pInitArgs: CK_VOID_PTR) -> CK_RV {
83 // pInitArgs.pReserved will be a c-string containing the base-16
84 // stringification of the addresses of the functions to call to communicate
85 // with the main process.
86 if pInitArgs.is_null() {
87 return CKR_DEVICE_ERROR;
89 let serialized_addresses_ptr = unsafe { (*(pInitArgs as CK_C_INITIALIZE_ARGS_PTR)).pReserved };
90 if serialized_addresses_ptr.is_null() {
91 return CKR_DEVICE_ERROR;
93 let serialized_addresses_cstr =
94 unsafe { CStr::from_ptr(serialized_addresses_ptr as *mut std::os::raw::c_char) };
95 let serialized_addresses = match serialized_addresses_cstr.to_str() {
96 Ok(serialized_addresses) => serialized_addresses,
97 Err(_) => return CKR_DEVICE_ERROR,
99 let function_addresses: Vec<usize> = serialized_addresses
101 .filter_map(|serialized_address| usize::from_str_radix(serialized_address, 16).ok())
103 if function_addresses.len() != 2 {
104 return CKR_DEVICE_ERROR;
106 let find_objects: FindObjectsFunction = unsafe { std::mem::transmute(function_addresses[0]) };
107 let sign: SignFunction = unsafe { std::mem::transmute(function_addresses[1]) };
108 let mut manager_guard = try_to_get_manager_guard!();
109 let _unexpected_previous_manager =
110 manager_guard.replace(Manager::new(Backend::new(find_objects, sign)));
114 extern "C" fn C_Finalize(_pReserved: CK_VOID_PTR) -> CK_RV {
115 // Drop the manager. When C_Finalize is called, there should be only one
116 // reference to this module (which is going away), so there shouldn't be
117 // any concurrency issues.
118 let mut manager_guard = try_to_get_manager_guard!();
119 match manager_guard.take() {
121 None => CKR_CRYPTOKI_NOT_INITIALIZED,
125 // The specification mandates that these strings be padded with spaces to the appropriate length.
126 // Since the length of fixed-size arrays in rust is part of the type, the compiler enforces that
127 // these byte strings are of the correct length.
128 const MANUFACTURER_ID_BYTES: &[u8; 32] = b"Mozilla Corporation ";
129 const LIBRARY_DESCRIPTION_BYTES: &[u8; 32] = b"IPC Client Cert Module ";
131 /// This gets called to gather some information about the module. In particular, this implementation
132 /// supports (portions of) cryptoki (PKCS #11) version 2.2.
133 extern "C" fn C_GetInfo(pInfo: CK_INFO_PTR) -> CK_RV {
135 return CKR_ARGUMENTS_BAD;
137 let mut info = CK_INFO::default();
138 info.cryptokiVersion.major = 2;
139 info.cryptokiVersion.minor = 2;
140 info.manufacturerID = *MANUFACTURER_ID_BYTES;
141 info.libraryDescription = *LIBRARY_DESCRIPTION_BYTES;
148 /// This module has two slots.
149 const SLOT_COUNT: CK_ULONG = 2;
150 /// The slot with ID 1 supports modern mechanisms like RSA-PSS.
151 const SLOT_ID_MODERN: CK_SLOT_ID = 1;
152 /// The slot with ID 2 only supports legacy mechanisms.
153 const SLOT_ID_LEGACY: CK_SLOT_ID = 2;
155 /// This gets called twice: once with a null `pSlotList` to get the number of slots (returned via
156 /// `pulCount`) and a second time to get the ID for each slot.
157 extern "C" fn C_GetSlotList(
158 _tokenPresent: CK_BBOOL,
159 pSlotList: CK_SLOT_ID_PTR,
160 pulCount: CK_ULONG_PTR,
162 if pulCount.is_null() {
163 return CKR_ARGUMENTS_BAD;
165 if !pSlotList.is_null() {
166 if unsafe { *pulCount } < SLOT_COUNT {
167 return CKR_BUFFER_TOO_SMALL;
170 *pSlotList = SLOT_ID_MODERN;
171 *pSlotList.offset(1) = SLOT_ID_LEGACY;
175 *pulCount = SLOT_COUNT;
180 const SLOT_DESCRIPTION_MODERN_BYTES: &[u8; 64] =
181 b"IPC Client Cert Slot (Modern) ";
182 const SLOT_DESCRIPTION_LEGACY_BYTES: &[u8; 64] =
183 b"IPC Client Cert Slot (Legacy) ";
185 /// This gets called to obtain information about slots. In this implementation, the tokens are
186 /// always present in the slots.
187 extern "C" fn C_GetSlotInfo(slotID: CK_SLOT_ID, pInfo: CK_SLOT_INFO_PTR) -> CK_RV {
188 if (slotID != SLOT_ID_MODERN && slotID != SLOT_ID_LEGACY) || pInfo.is_null() {
189 return CKR_ARGUMENTS_BAD;
191 let description = if slotID == SLOT_ID_MODERN {
192 SLOT_DESCRIPTION_MODERN_BYTES
194 SLOT_DESCRIPTION_LEGACY_BYTES
196 let slot_info = CK_SLOT_INFO {
197 slotDescription: *description,
198 manufacturerID: *MANUFACTURER_ID_BYTES,
199 flags: CKF_TOKEN_PRESENT,
200 hardwareVersion: CK_VERSION::default(),
201 firmwareVersion: CK_VERSION::default(),
209 const TOKEN_LABEL_MODERN_BYTES: &[u8; 32] = b"IPC Client Cert Token (Modern) ";
210 const TOKEN_LABEL_LEGACY_BYTES: &[u8; 32] = b"IPC Client Cert Token (Legacy) ";
211 const TOKEN_MODEL_BYTES: &[u8; 16] = b"ipcclientcerts ";
212 const TOKEN_SERIAL_NUMBER_BYTES: &[u8; 16] = b"0000000000000000";
214 /// This gets called to obtain some information about tokens. This implementation has two slots,
215 /// so it has two tokens. This information is primarily for display purposes.
216 extern "C" fn C_GetTokenInfo(slotID: CK_SLOT_ID, pInfo: CK_TOKEN_INFO_PTR) -> CK_RV {
217 if (slotID != SLOT_ID_MODERN && slotID != SLOT_ID_LEGACY) || pInfo.is_null() {
218 return CKR_ARGUMENTS_BAD;
220 let mut token_info = CK_TOKEN_INFO::default();
221 let label = if slotID == SLOT_ID_MODERN {
222 TOKEN_LABEL_MODERN_BYTES
224 TOKEN_LABEL_LEGACY_BYTES
226 token_info.label = *label;
227 token_info.manufacturerID = *MANUFACTURER_ID_BYTES;
228 token_info.model = *TOKEN_MODEL_BYTES;
229 token_info.serialNumber = *TOKEN_SERIAL_NUMBER_BYTES;
236 /// This gets called to determine what mechanisms a slot supports. The modern slot supports ECDSA,
237 /// RSA PKCS, and RSA PSS. The legacy slot only supports RSA PKCS.
238 extern "C" fn C_GetMechanismList(
240 pMechanismList: CK_MECHANISM_TYPE_PTR,
241 pulCount: CK_ULONG_PTR,
243 if (slotID != SLOT_ID_MODERN && slotID != SLOT_ID_LEGACY) || pulCount.is_null() {
244 return CKR_ARGUMENTS_BAD;
246 let mechanisms = if slotID == SLOT_ID_MODERN {
247 vec![CKM_ECDSA, CKM_RSA_PKCS, CKM_RSA_PKCS_PSS]
251 if !pMechanismList.is_null() {
252 if unsafe { *pulCount as usize } < mechanisms.len() {
253 return CKR_ARGUMENTS_BAD;
255 for i in 0..mechanisms.len() {
257 *pMechanismList.offset(i as isize) = mechanisms[i];
262 *pulCount = mechanisms.len() as CK_ULONG;
267 extern "C" fn C_GetMechanismInfo(
269 _type: CK_MECHANISM_TYPE,
270 _pInfo: CK_MECHANISM_INFO_PTR,
272 CKR_FUNCTION_NOT_SUPPORTED
275 extern "C" fn C_InitToken(
277 _pPin: CK_UTF8CHAR_PTR,
279 _pLabel: CK_UTF8CHAR_PTR,
281 CKR_FUNCTION_NOT_SUPPORTED
284 extern "C" fn C_InitPIN(
285 _hSession: CK_SESSION_HANDLE,
286 _pPin: CK_UTF8CHAR_PTR,
289 CKR_FUNCTION_NOT_SUPPORTED
292 extern "C" fn C_SetPIN(
293 _hSession: CK_SESSION_HANDLE,
294 _pOldPin: CK_UTF8CHAR_PTR,
296 _pNewPin: CK_UTF8CHAR_PTR,
299 CKR_FUNCTION_NOT_SUPPORTED
302 /// This gets called to create a new session. This module defers to the `ManagerProxy` to implement
304 extern "C" fn C_OpenSession(
307 _pApplication: CK_VOID_PTR,
309 phSession: CK_SESSION_HANDLE_PTR,
311 if (slotID != SLOT_ID_MODERN && slotID != SLOT_ID_LEGACY) || phSession.is_null() {
312 return CKR_ARGUMENTS_BAD;
314 let mut manager_guard = try_to_get_manager_guard!();
315 let manager = manager_guard_to_manager!(manager_guard);
316 let slot_type = if slotID == SLOT_ID_MODERN {
321 let session_handle = match manager.open_session(slot_type) {
322 Ok(session_handle) => session_handle,
323 Err(_) => return CKR_DEVICE_ERROR,
326 *phSession = session_handle;
331 /// This gets called to close a session. This is handled by the `ManagerProxy`.
332 extern "C" fn C_CloseSession(hSession: CK_SESSION_HANDLE) -> CK_RV {
333 let mut manager_guard = try_to_get_manager_guard!();
334 let manager = manager_guard_to_manager!(manager_guard);
335 if manager.close_session(hSession).is_err() {
336 return CKR_SESSION_HANDLE_INVALID;
341 /// This gets called to close all open sessions at once. This is handled by the `ManagerProxy`.
342 extern "C" fn C_CloseAllSessions(slotID: CK_SLOT_ID) -> CK_RV {
343 if slotID != SLOT_ID_MODERN && slotID != SLOT_ID_LEGACY {
344 return CKR_ARGUMENTS_BAD;
346 let mut manager_guard = try_to_get_manager_guard!();
347 let manager = manager_guard_to_manager!(manager_guard);
348 let slot_type = if slotID == SLOT_ID_MODERN {
353 match manager.close_all_sessions(slot_type) {
355 Err(_) => CKR_DEVICE_ERROR,
359 extern "C" fn C_GetSessionInfo(_hSession: CK_SESSION_HANDLE, _pInfo: CK_SESSION_INFO_PTR) -> CK_RV {
360 CKR_FUNCTION_NOT_SUPPORTED
363 extern "C" fn C_GetOperationState(
364 _hSession: CK_SESSION_HANDLE,
365 _pOperationState: CK_BYTE_PTR,
366 _pulOperationStateLen: CK_ULONG_PTR,
368 CKR_FUNCTION_NOT_SUPPORTED
371 extern "C" fn C_SetOperationState(
372 _hSession: CK_SESSION_HANDLE,
373 _pOperationState: CK_BYTE_PTR,
374 _ulOperationStateLen: CK_ULONG,
375 _hEncryptionKey: CK_OBJECT_HANDLE,
376 _hAuthenticationKey: CK_OBJECT_HANDLE,
378 CKR_FUNCTION_NOT_SUPPORTED
381 extern "C" fn C_Login(
382 _hSession: CK_SESSION_HANDLE,
383 _userType: CK_USER_TYPE,
384 _pPin: CK_UTF8CHAR_PTR,
387 CKR_FUNCTION_NOT_SUPPORTED
390 /// This gets called to log out and drop any authenticated resources. Because this module does not
391 /// hold on to authenticated resources, this module "implements" this by doing nothing and
392 /// returning a success result.
393 extern "C" fn C_Logout(_hSession: CK_SESSION_HANDLE) -> CK_RV {
397 extern "C" fn C_CreateObject(
398 _hSession: CK_SESSION_HANDLE,
399 _pTemplate: CK_ATTRIBUTE_PTR,
401 _phObject: CK_OBJECT_HANDLE_PTR,
403 CKR_FUNCTION_NOT_SUPPORTED
406 extern "C" fn C_CopyObject(
407 _hSession: CK_SESSION_HANDLE,
408 _hObject: CK_OBJECT_HANDLE,
409 _pTemplate: CK_ATTRIBUTE_PTR,
411 _phNewObject: CK_OBJECT_HANDLE_PTR,
413 CKR_FUNCTION_NOT_SUPPORTED
416 extern "C" fn C_DestroyObject(_hSession: CK_SESSION_HANDLE, _hObject: CK_OBJECT_HANDLE) -> CK_RV {
417 CKR_FUNCTION_NOT_SUPPORTED
420 extern "C" fn C_GetObjectSize(
421 _hSession: CK_SESSION_HANDLE,
422 _hObject: CK_OBJECT_HANDLE,
423 _pulSize: CK_ULONG_PTR,
425 CKR_FUNCTION_NOT_SUPPORTED
428 /// This gets called to obtain the values of a number of attributes of an object identified by the
429 /// given handle. This module implements this by requesting that the `ManagerProxy` find the object
430 /// and attempt to get the value of each attribute. If a specified attribute is not defined on the
431 /// object, the length of that attribute is set to -1 to indicate that it is not available.
432 /// This gets called twice: once to obtain the lengths of the attributes and again to get the
434 extern "C" fn C_GetAttributeValue(
435 _hSession: CK_SESSION_HANDLE,
436 hObject: CK_OBJECT_HANDLE,
437 pTemplate: CK_ATTRIBUTE_PTR,
440 if pTemplate.is_null() {
441 return CKR_ARGUMENTS_BAD;
443 let mut attr_types = Vec::with_capacity(ulCount as usize);
444 for i in 0..ulCount {
445 let attr = unsafe { &*pTemplate.offset(i as isize) };
446 attr_types.push(attr.type_);
448 let mut manager_guard = try_to_get_manager_guard!();
449 let manager = manager_guard_to_manager!(manager_guard);
450 let values = match manager.get_attributes(hObject, attr_types) {
451 Ok(values) => values,
452 Err(_) => return CKR_ARGUMENTS_BAD,
454 if values.len() != ulCount as usize {
455 return CKR_DEVICE_ERROR;
457 for i in 0..ulCount as usize {
458 let attr = unsafe { &mut *pTemplate.offset(i as isize) };
459 // NB: the safety of this array access depends on the length check above
460 if let Some(attr_value) = &values[i] {
461 if attr.pValue.is_null() {
462 attr.ulValueLen = attr_value.len() as CK_ULONG;
464 let ptr: *mut u8 = attr.pValue as *mut u8;
465 if attr_value.len() != attr.ulValueLen as usize {
466 return CKR_ARGUMENTS_BAD;
469 std::ptr::copy_nonoverlapping(attr_value.as_ptr(), ptr, attr_value.len());
473 attr.ulValueLen = (0 - 1) as CK_ULONG;
479 extern "C" fn C_SetAttributeValue(
480 _hSession: CK_SESSION_HANDLE,
481 _hObject: CK_OBJECT_HANDLE,
482 _pTemplate: CK_ATTRIBUTE_PTR,
485 CKR_FUNCTION_NOT_SUPPORTED
488 const RELEVANT_ATTRIBUTES: &[CK_ATTRIBUTE_TYPE] = &[
503 /// This gets called to initialize a search for objects matching a given list of attributes. This
504 /// module implements this by gathering the attributes and passing them to the `ManagerProxy` to
505 /// start the search.
506 extern "C" fn C_FindObjectsInit(
507 hSession: CK_SESSION_HANDLE,
508 pTemplate: CK_ATTRIBUTE_PTR,
511 if pTemplate.is_null() {
512 return CKR_ARGUMENTS_BAD;
514 let mut attrs = Vec::new();
515 for i in 0..ulCount {
516 let attr = unsafe { &*pTemplate.offset(i as isize) };
517 // Copy out the attribute type to avoid making a reference to an unaligned field.
518 let attr_type = attr.type_;
519 if !RELEVANT_ATTRIBUTES.contains(&attr_type) {
520 return CKR_ATTRIBUTE_TYPE_INVALID;
523 std::slice::from_raw_parts(attr.pValue as *const u8, attr.ulValueLen as usize)
525 attrs.push((attr_type, slice.to_owned()));
527 let mut manager_guard = try_to_get_manager_guard!();
528 let manager = manager_guard_to_manager!(manager_guard);
529 match manager.start_search(hSession, attrs) {
531 Err(_) => return CKR_ARGUMENTS_BAD,
536 /// This gets called after `C_FindObjectsInit` to get the results of a search. This module
537 /// implements this by looking up the search in the `ManagerProxy` and copying out the matching
539 extern "C" fn C_FindObjects(
540 hSession: CK_SESSION_HANDLE,
541 phObject: CK_OBJECT_HANDLE_PTR,
542 ulMaxObjectCount: CK_ULONG,
543 pulObjectCount: CK_ULONG_PTR,
545 if phObject.is_null() || pulObjectCount.is_null() || ulMaxObjectCount == 0 {
546 return CKR_ARGUMENTS_BAD;
548 let mut manager_guard = try_to_get_manager_guard!();
549 let manager = manager_guard_to_manager!(manager_guard);
550 let handles = match manager.search(hSession, ulMaxObjectCount as usize) {
551 Ok(handles) => handles,
552 Err(_) => return CKR_ARGUMENTS_BAD,
554 if handles.len() > ulMaxObjectCount as usize {
555 return CKR_DEVICE_ERROR;
558 *pulObjectCount = handles.len() as CK_ULONG;
560 for (index, handle) in handles.iter().enumerate() {
561 if index < ulMaxObjectCount as usize {
563 *(phObject.add(index)) = *handle;
570 /// This gets called after `C_FindObjectsInit` and `C_FindObjects` to finish a search. The module
571 /// tells the `ManagerProxy` to clear the search.
572 extern "C" fn C_FindObjectsFinal(hSession: CK_SESSION_HANDLE) -> CK_RV {
573 let mut manager_guard = try_to_get_manager_guard!();
574 let manager = manager_guard_to_manager!(manager_guard);
575 // It would be an error if there were no search for this session, but we can be permissive here.
576 match manager.clear_search(hSession) {
578 Err(_) => CKR_DEVICE_ERROR,
582 extern "C" fn C_EncryptInit(
583 _hSession: CK_SESSION_HANDLE,
584 _pMechanism: CK_MECHANISM_PTR,
585 _hKey: CK_OBJECT_HANDLE,
587 CKR_FUNCTION_NOT_SUPPORTED
590 extern "C" fn C_Encrypt(
591 _hSession: CK_SESSION_HANDLE,
593 _ulDataLen: CK_ULONG,
594 _pEncryptedData: CK_BYTE_PTR,
595 _pulEncryptedDataLen: CK_ULONG_PTR,
597 CKR_FUNCTION_NOT_SUPPORTED
600 extern "C" fn C_EncryptUpdate(
601 _hSession: CK_SESSION_HANDLE,
603 _ulPartLen: CK_ULONG,
604 _pEncryptedPart: CK_BYTE_PTR,
605 _pulEncryptedPartLen: CK_ULONG_PTR,
607 CKR_FUNCTION_NOT_SUPPORTED
610 extern "C" fn C_EncryptFinal(
611 _hSession: CK_SESSION_HANDLE,
612 _pLastEncryptedPart: CK_BYTE_PTR,
613 _pulLastEncryptedPartLen: CK_ULONG_PTR,
615 CKR_FUNCTION_NOT_SUPPORTED
618 extern "C" fn C_DecryptInit(
619 _hSession: CK_SESSION_HANDLE,
620 _pMechanism: CK_MECHANISM_PTR,
621 _hKey: CK_OBJECT_HANDLE,
623 CKR_FUNCTION_NOT_SUPPORTED
626 extern "C" fn C_Decrypt(
627 _hSession: CK_SESSION_HANDLE,
628 _pEncryptedData: CK_BYTE_PTR,
629 _ulEncryptedDataLen: CK_ULONG,
631 _pulDataLen: CK_ULONG_PTR,
633 CKR_FUNCTION_NOT_SUPPORTED
636 extern "C" fn C_DecryptUpdate(
637 _hSession: CK_SESSION_HANDLE,
638 _pEncryptedPart: CK_BYTE_PTR,
639 _ulEncryptedPartLen: CK_ULONG,
641 _pulPartLen: CK_ULONG_PTR,
643 CKR_FUNCTION_NOT_SUPPORTED
646 extern "C" fn C_DecryptFinal(
647 _hSession: CK_SESSION_HANDLE,
648 _pLastPart: CK_BYTE_PTR,
649 _pulLastPartLen: CK_ULONG_PTR,
651 CKR_FUNCTION_NOT_SUPPORTED
654 extern "C" fn C_DigestInit(_hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR) -> CK_RV {
655 CKR_FUNCTION_NOT_SUPPORTED
658 extern "C" fn C_Digest(
659 _hSession: CK_SESSION_HANDLE,
661 _ulDataLen: CK_ULONG,
662 _pDigest: CK_BYTE_PTR,
663 _pulDigestLen: CK_ULONG_PTR,
665 CKR_FUNCTION_NOT_SUPPORTED
668 extern "C" fn C_DigestUpdate(
669 _hSession: CK_SESSION_HANDLE,
671 _ulPartLen: CK_ULONG,
673 CKR_FUNCTION_NOT_SUPPORTED
676 extern "C" fn C_DigestKey(_hSession: CK_SESSION_HANDLE, _hKey: CK_OBJECT_HANDLE) -> CK_RV {
677 CKR_FUNCTION_NOT_SUPPORTED
680 extern "C" fn C_DigestFinal(
681 _hSession: CK_SESSION_HANDLE,
682 _pDigest: CK_BYTE_PTR,
683 _pulDigestLen: CK_ULONG_PTR,
685 CKR_FUNCTION_NOT_SUPPORTED
688 /// This gets called to set up a sign operation. The module essentially defers to the
690 extern "C" fn C_SignInit(
691 hSession: CK_SESSION_HANDLE,
692 pMechanism: CK_MECHANISM_PTR,
693 hKey: CK_OBJECT_HANDLE,
695 if pMechanism.is_null() {
696 return CKR_ARGUMENTS_BAD;
698 // Presumably we should validate the mechanism against hKey, but the specification doesn't
699 // actually seem to require this.
700 let mechanism = unsafe { *pMechanism };
701 let mechanism_params = if mechanism.mechanism == CKM_RSA_PKCS_PSS {
702 if mechanism.ulParameterLen as usize != std::mem::size_of::<CK_RSA_PKCS_PSS_PARAMS>() {
703 return CKR_ARGUMENTS_BAD;
705 Some(unsafe { *(mechanism.pParameter as *const CK_RSA_PKCS_PSS_PARAMS) })
709 let mut manager_guard = try_to_get_manager_guard!();
710 let manager = manager_guard_to_manager!(manager_guard);
711 match manager.start_sign(hSession, hKey, mechanism_params) {
713 Err(_) => return CKR_GENERAL_ERROR,
718 /// NSS calls this after `C_SignInit` (there are more ways in the PKCS #11 specification to sign
719 /// data, but this is the only way supported by this module). The module essentially defers to the
720 /// `ManagerProxy` and copies out the resulting signature.
721 extern "C" fn C_Sign(
722 hSession: CK_SESSION_HANDLE,
725 pSignature: CK_BYTE_PTR,
726 pulSignatureLen: CK_ULONG_PTR,
728 if pData.is_null() || pulSignatureLen.is_null() {
729 return CKR_ARGUMENTS_BAD;
731 let data = unsafe { std::slice::from_raw_parts(pData, ulDataLen as usize) };
732 if pSignature.is_null() {
733 let mut manager_guard = try_to_get_manager_guard!();
734 let manager = manager_guard_to_manager!(manager_guard);
735 match manager.get_signature_length(hSession, data.to_vec()) {
736 Ok(signature_length) => unsafe {
737 *pulSignatureLen = signature_length as CK_ULONG;
739 Err(_) => return CKR_GENERAL_ERROR,
742 let mut manager_guard = try_to_get_manager_guard!();
743 let manager = manager_guard_to_manager!(manager_guard);
744 match manager.sign(hSession, data.to_vec()) {
746 let signature_capacity = unsafe { *pulSignatureLen } as usize;
747 if signature_capacity < signature.len() {
748 return CKR_ARGUMENTS_BAD;
750 let ptr: *mut u8 = pSignature as *mut u8;
752 std::ptr::copy_nonoverlapping(signature.as_ptr(), ptr, signature.len());
753 *pulSignatureLen = signature.len() as CK_ULONG;
756 Err(_) => return CKR_GENERAL_ERROR,
762 extern "C" fn C_SignUpdate(
763 _hSession: CK_SESSION_HANDLE,
765 _ulPartLen: CK_ULONG,
767 CKR_FUNCTION_NOT_SUPPORTED
770 extern "C" fn C_SignFinal(
771 _hSession: CK_SESSION_HANDLE,
772 _pSignature: CK_BYTE_PTR,
773 _pulSignatureLen: CK_ULONG_PTR,
775 CKR_FUNCTION_NOT_SUPPORTED
778 extern "C" fn C_SignRecoverInit(
779 _hSession: CK_SESSION_HANDLE,
780 _pMechanism: CK_MECHANISM_PTR,
781 _hKey: CK_OBJECT_HANDLE,
783 CKR_FUNCTION_NOT_SUPPORTED
786 extern "C" fn C_SignRecover(
787 _hSession: CK_SESSION_HANDLE,
789 _ulDataLen: CK_ULONG,
790 _pSignature: CK_BYTE_PTR,
791 _pulSignatureLen: CK_ULONG_PTR,
793 CKR_FUNCTION_NOT_SUPPORTED
796 extern "C" fn C_VerifyInit(
797 _hSession: CK_SESSION_HANDLE,
798 _pMechanism: CK_MECHANISM_PTR,
799 _hKey: CK_OBJECT_HANDLE,
801 CKR_FUNCTION_NOT_SUPPORTED
804 extern "C" fn C_Verify(
805 _hSession: CK_SESSION_HANDLE,
807 _ulDataLen: CK_ULONG,
808 _pSignature: CK_BYTE_PTR,
809 _ulSignatureLen: CK_ULONG,
811 CKR_FUNCTION_NOT_SUPPORTED
814 extern "C" fn C_VerifyUpdate(
815 _hSession: CK_SESSION_HANDLE,
817 _ulPartLen: CK_ULONG,
819 CKR_FUNCTION_NOT_SUPPORTED
822 extern "C" fn C_VerifyFinal(
823 _hSession: CK_SESSION_HANDLE,
824 _pSignature: CK_BYTE_PTR,
825 _ulSignatureLen: CK_ULONG,
827 CKR_FUNCTION_NOT_SUPPORTED
830 extern "C" fn C_VerifyRecoverInit(
831 _hSession: CK_SESSION_HANDLE,
832 _pMechanism: CK_MECHANISM_PTR,
833 _hKey: CK_OBJECT_HANDLE,
835 CKR_FUNCTION_NOT_SUPPORTED
838 extern "C" fn C_VerifyRecover(
839 _hSession: CK_SESSION_HANDLE,
840 _pSignature: CK_BYTE_PTR,
841 _ulSignatureLen: CK_ULONG,
843 _pulDataLen: CK_ULONG_PTR,
845 CKR_FUNCTION_NOT_SUPPORTED
848 extern "C" fn C_DigestEncryptUpdate(
849 _hSession: CK_SESSION_HANDLE,
851 _ulPartLen: CK_ULONG,
852 _pEncryptedPart: CK_BYTE_PTR,
853 _pulEncryptedPartLen: CK_ULONG_PTR,
855 CKR_FUNCTION_NOT_SUPPORTED
858 extern "C" fn C_DecryptDigestUpdate(
859 _hSession: CK_SESSION_HANDLE,
860 _pEncryptedPart: CK_BYTE_PTR,
861 _ulEncryptedPartLen: CK_ULONG,
863 _pulPartLen: CK_ULONG_PTR,
865 CKR_FUNCTION_NOT_SUPPORTED
868 extern "C" fn C_SignEncryptUpdate(
869 _hSession: CK_SESSION_HANDLE,
871 _ulPartLen: CK_ULONG,
872 _pEncryptedPart: CK_BYTE_PTR,
873 _pulEncryptedPartLen: CK_ULONG_PTR,
875 CKR_FUNCTION_NOT_SUPPORTED
878 extern "C" fn C_DecryptVerifyUpdate(
879 _hSession: CK_SESSION_HANDLE,
880 _pEncryptedPart: CK_BYTE_PTR,
881 _ulEncryptedPartLen: CK_ULONG,
883 _pulPartLen: CK_ULONG_PTR,
885 CKR_FUNCTION_NOT_SUPPORTED
888 extern "C" fn C_GenerateKey(
889 _hSession: CK_SESSION_HANDLE,
890 _pMechanism: CK_MECHANISM_PTR,
891 _pTemplate: CK_ATTRIBUTE_PTR,
893 _phKey: CK_OBJECT_HANDLE_PTR,
895 CKR_FUNCTION_NOT_SUPPORTED
898 extern "C" fn C_GenerateKeyPair(
899 _hSession: CK_SESSION_HANDLE,
900 _pMechanism: CK_MECHANISM_PTR,
901 _pPublicKeyTemplate: CK_ATTRIBUTE_PTR,
902 _ulPublicKeyAttributeCount: CK_ULONG,
903 _pPrivateKeyTemplate: CK_ATTRIBUTE_PTR,
904 _ulPrivateKeyAttributeCount: CK_ULONG,
905 _phPublicKey: CK_OBJECT_HANDLE_PTR,
906 _phPrivateKey: CK_OBJECT_HANDLE_PTR,
908 CKR_FUNCTION_NOT_SUPPORTED
911 extern "C" fn C_WrapKey(
912 _hSession: CK_SESSION_HANDLE,
913 _pMechanism: CK_MECHANISM_PTR,
914 _hWrappingKey: CK_OBJECT_HANDLE,
915 _hKey: CK_OBJECT_HANDLE,
916 _pWrappedKey: CK_BYTE_PTR,
917 _pulWrappedKeyLen: CK_ULONG_PTR,
919 CKR_FUNCTION_NOT_SUPPORTED
922 extern "C" fn C_UnwrapKey(
923 _hSession: CK_SESSION_HANDLE,
924 _pMechanism: CK_MECHANISM_PTR,
925 _hUnwrappingKey: CK_OBJECT_HANDLE,
926 _pWrappedKey: CK_BYTE_PTR,
927 _ulWrappedKeyLen: CK_ULONG,
928 _pTemplate: CK_ATTRIBUTE_PTR,
929 _ulAttributeCount: CK_ULONG,
930 _phKey: CK_OBJECT_HANDLE_PTR,
932 CKR_FUNCTION_NOT_SUPPORTED
935 extern "C" fn C_DeriveKey(
936 _hSession: CK_SESSION_HANDLE,
937 _pMechanism: CK_MECHANISM_PTR,
938 _hBaseKey: CK_OBJECT_HANDLE,
939 _pTemplate: CK_ATTRIBUTE_PTR,
940 _ulAttributeCount: CK_ULONG,
941 _phKey: CK_OBJECT_HANDLE_PTR,
943 CKR_FUNCTION_NOT_SUPPORTED
946 extern "C" fn C_SeedRandom(
947 _hSession: CK_SESSION_HANDLE,
949 _ulSeedLen: CK_ULONG,
951 CKR_FUNCTION_NOT_SUPPORTED
954 extern "C" fn C_GenerateRandom(
955 _hSession: CK_SESSION_HANDLE,
956 _RandomData: CK_BYTE_PTR,
957 _ulRandomLen: CK_ULONG,
959 CKR_FUNCTION_NOT_SUPPORTED
962 extern "C" fn C_GetFunctionStatus(_hSession: CK_SESSION_HANDLE) -> CK_RV {
963 CKR_FUNCTION_NOT_SUPPORTED
966 extern "C" fn C_CancelFunction(_hSession: CK_SESSION_HANDLE) -> CK_RV {
967 CKR_FUNCTION_NOT_SUPPORTED
970 extern "C" fn C_WaitForSlotEvent(
972 _pSlot: CK_SLOT_ID_PTR,
973 _pRserved: CK_VOID_PTR,
975 CKR_FUNCTION_NOT_SUPPORTED
978 /// To be a valid PKCS #11 module, this list of functions must be supported. At least cryptoki 2.2
979 /// must be supported for this module to work in NSS.
980 static FUNCTION_LIST: CK_FUNCTION_LIST = CK_FUNCTION_LIST {
981 version: CK_VERSION { major: 2, minor: 2 },
982 C_Initialize: Some(C_Initialize),
983 C_Finalize: Some(C_Finalize),
984 C_GetInfo: Some(C_GetInfo),
985 C_GetFunctionList: None,
986 C_GetSlotList: Some(C_GetSlotList),
987 C_GetSlotInfo: Some(C_GetSlotInfo),
988 C_GetTokenInfo: Some(C_GetTokenInfo),
989 C_GetMechanismList: Some(C_GetMechanismList),
990 C_GetMechanismInfo: Some(C_GetMechanismInfo),
991 C_InitToken: Some(C_InitToken),
992 C_InitPIN: Some(C_InitPIN),
993 C_SetPIN: Some(C_SetPIN),
994 C_OpenSession: Some(C_OpenSession),
995 C_CloseSession: Some(C_CloseSession),
996 C_CloseAllSessions: Some(C_CloseAllSessions),
997 C_GetSessionInfo: Some(C_GetSessionInfo),
998 C_GetOperationState: Some(C_GetOperationState),
999 C_SetOperationState: Some(C_SetOperationState),
1000 C_Login: Some(C_Login),
1001 C_Logout: Some(C_Logout),
1002 C_CreateObject: Some(C_CreateObject),
1003 C_CopyObject: Some(C_CopyObject),
1004 C_DestroyObject: Some(C_DestroyObject),
1005 C_GetObjectSize: Some(C_GetObjectSize),
1006 C_GetAttributeValue: Some(C_GetAttributeValue),
1007 C_SetAttributeValue: Some(C_SetAttributeValue),
1008 C_FindObjectsInit: Some(C_FindObjectsInit),
1009 C_FindObjects: Some(C_FindObjects),
1010 C_FindObjectsFinal: Some(C_FindObjectsFinal),
1011 C_EncryptInit: Some(C_EncryptInit),
1012 C_Encrypt: Some(C_Encrypt),
1013 C_EncryptUpdate: Some(C_EncryptUpdate),
1014 C_EncryptFinal: Some(C_EncryptFinal),
1015 C_DecryptInit: Some(C_DecryptInit),
1016 C_Decrypt: Some(C_Decrypt),
1017 C_DecryptUpdate: Some(C_DecryptUpdate),
1018 C_DecryptFinal: Some(C_DecryptFinal),
1019 C_DigestInit: Some(C_DigestInit),
1020 C_Digest: Some(C_Digest),
1021 C_DigestUpdate: Some(C_DigestUpdate),
1022 C_DigestKey: Some(C_DigestKey),
1023 C_DigestFinal: Some(C_DigestFinal),
1024 C_SignInit: Some(C_SignInit),
1025 C_Sign: Some(C_Sign),
1026 C_SignUpdate: Some(C_SignUpdate),
1027 C_SignFinal: Some(C_SignFinal),
1028 C_SignRecoverInit: Some(C_SignRecoverInit),
1029 C_SignRecover: Some(C_SignRecover),
1030 C_VerifyInit: Some(C_VerifyInit),
1031 C_Verify: Some(C_Verify),
1032 C_VerifyUpdate: Some(C_VerifyUpdate),
1033 C_VerifyFinal: Some(C_VerifyFinal),
1034 C_VerifyRecoverInit: Some(C_VerifyRecoverInit),
1035 C_VerifyRecover: Some(C_VerifyRecover),
1036 C_DigestEncryptUpdate: Some(C_DigestEncryptUpdate),
1037 C_DecryptDigestUpdate: Some(C_DecryptDigestUpdate),
1038 C_SignEncryptUpdate: Some(C_SignEncryptUpdate),
1039 C_DecryptVerifyUpdate: Some(C_DecryptVerifyUpdate),
1040 C_GenerateKey: Some(C_GenerateKey),
1041 C_GenerateKeyPair: Some(C_GenerateKeyPair),
1042 C_WrapKey: Some(C_WrapKey),
1043 C_UnwrapKey: Some(C_UnwrapKey),
1044 C_DeriveKey: Some(C_DeriveKey),
1045 C_SeedRandom: Some(C_SeedRandom),
1046 C_GenerateRandom: Some(C_GenerateRandom),
1047 C_GetFunctionStatus: Some(C_GetFunctionStatus),
1048 C_CancelFunction: Some(C_CancelFunction),
1049 C_WaitForSlotEvent: Some(C_WaitForSlotEvent),
1052 /// This is the only function this module exposes. The C stub calls it when NSS
1053 /// calls its exposed C_GetFunctionList function to obtain the list of functions
1054 /// comprising this module.
1056 pub extern "C" fn IPCCC_GetFunctionList(ppFunctionList: CK_FUNCTION_LIST_PTR_PTR) -> CK_RV {
1057 if ppFunctionList.is_null() {
1058 return CKR_ARGUMENTS_BAD;
1061 // CK_FUNCTION_LIST_PTR is a *mut CK_FUNCTION_LIST, but as per the
1062 // specification, the caller must treat it as *const CK_FUNCTION_LIST.
1063 *ppFunctionList = std::ptr::addr_of!(FUNCTION_LIST) as CK_FUNCTION_LIST_PTR;
1069 any(target_os = "macos", target_os = "ios"),
1070 link(name = "Security", kind = "framework")