/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ extern crate byteorder; extern crate pkcs11_bindings; pub mod cryptoki; pub mod manager; // Helper macro to prefix log messages with the current thread ID. #[macro_export] macro_rules! log_with_thread_id { ($log_level:ident, $($message:expr),*) => { $log_level!("{:?} {}", std::thread::current().id(), format_args!($($message),*)); }; } // This module defines a few helper macros that can be used to declare the repetitive, boilerplate // code required to implement a PKCS#11 module. They require the macros `try_to_get_manager_guard` // and `manager_guard_to_manager` to be defined. Generally speaking, these manager macros are used // to get a mutable handle on a `Mutex>>` that represents the state of the // module. /// NB: Requires MANUFACTURER_ID_BYTES and LIBRARY_DESCRIPTION_BYTES to be defined. #[macro_export] macro_rules! declare_pkcs11_informational_functions { () => { /// This gets called to gather some information about the module. In particular, this /// implementation supports (portions of) cryptoki (PKCS #11) version 2.2. extern "C" fn C_GetInfo(pInfo: CK_INFO_PTR) -> CK_RV { if pInfo.is_null() { log_with_thread_id!(error, "C_GetInfo: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let info = CK_INFO { cryptokiVersion: CK_VERSION { major: 2, minor: 2 }, manufacturerID: *MANUFACTURER_ID_BYTES, flags: 0, libraryDescription: *LIBRARY_DESCRIPTION_BYTES, libraryVersion: CK_VERSION { major: 0, minor: 0 }, }; unsafe { *pInfo = info; } log_with_thread_id!(debug, "C_GetInfo: CKR_OK"); CKR_OK } /// This gets called twice: once with a null `pSlotList` to get the number of slots /// (returned via `pulCount`) and a second time to get the ID for each slot. extern "C" fn C_GetSlotList( tokenPresent: CK_BBOOL, pSlotList: CK_SLOT_ID_PTR, pulCount: CK_ULONG_PTR, ) -> CK_RV { if pulCount.is_null() { log_with_thread_id!(error, "C_GetSlotList: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); let slot_ids = manager.get_slot_ids(if tokenPresent == CK_TRUE { true } else { false }); let slot_count: CK_ULONG = slot_ids.len().try_into().unwrap(); if !pSlotList.is_null() { if unsafe { *pulCount } < slot_count { log_with_thread_id!(error, "C_GetSlotList: CKR_BUFFER_TOO_SMALL"); return CKR_BUFFER_TOO_SMALL; } unsafe { std::ptr::copy_nonoverlapping(slot_ids.as_ptr(), pSlotList, slot_ids.len()); } }; unsafe { *pulCount = slot_count; } log_with_thread_id!(debug, "C_GetSlotList: CKR_OK"); CKR_OK } extern "C" fn C_GetSlotInfo(slotID: CK_SLOT_ID, pInfo: CK_SLOT_INFO_PTR) -> CK_RV { if pInfo.is_null() { log_with_thread_id!(error, "C_GetSlotInfo: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); let Ok(slot_info) = manager.get_slot_info(slotID) else { log_with_thread_id!(error, "C_GetSlotInfo: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; }; unsafe { *pInfo = slot_info; } log_with_thread_id!(debug, "C_GetSlotInfo: CKR_OK"); CKR_OK } extern "C" fn C_GetTokenInfo(slotID: CK_SLOT_ID, pInfo: CK_TOKEN_INFO_PTR) -> CK_RV { if pInfo.is_null() { log_with_thread_id!(error, "C_GetTokenInfo: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); let Ok(token_info) = manager.get_token_info(slotID) else { log_with_thread_id!(error, "C_GetTokenInfo: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; }; unsafe { *pInfo = token_info; } log_with_thread_id!(debug, "C_GetTokenInfo: CKR_OK"); CKR_OK } extern "C" fn C_GetMechanismList( slotID: CK_SLOT_ID, pMechanismList: CK_MECHANISM_TYPE_PTR, pulCount: CK_ULONG_PTR, ) -> CK_RV { if pulCount.is_null() { log_with_thread_id!(error, "C_GetMechanismList: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); let Ok(mechanisms) = manager.get_mechanism_list(slotID) else { log_with_thread_id!(error, "C_GetMechanismList: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; }; let mechanisms_len: CK_ULONG = mechanisms.len().try_into().unwrap(); if !pMechanismList.is_null() { if unsafe { *pulCount } < mechanisms_len { log_with_thread_id!(error, "C_GetMechanismList: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } unsafe { std::ptr::copy_nonoverlapping( mechanisms.as_ptr(), pMechanismList, mechanisms.len(), ); } } unsafe { *pulCount = mechanisms_len; } log_with_thread_id!(debug, "C_GetMechanismList: CKR_OK"); CKR_OK } }; } #[macro_export] macro_rules! declare_pkcs11_session_functions { () => { extern "C" fn C_OpenSession( slotID: CK_SLOT_ID, _flags: CK_FLAGS, _pApplication: CK_VOID_PTR, _Notify: CK_NOTIFY, phSession: CK_SESSION_HANDLE_PTR, ) -> CK_RV { if phSession.is_null() { log_with_thread_id!(error, "C_OpenSession: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); let session_handle = match manager.open_session(slotID) { Ok(session_handle) => session_handle, Err(e) => { log_with_thread_id!(error, "C_OpenSession: open_session failed: {}", e); return CKR_DEVICE_ERROR; } }; unsafe { *phSession = session_handle; } log_with_thread_id!(debug, "C_OpenSession: CKR_OK"); CKR_OK } extern "C" fn C_CloseSession(hSession: CK_SESSION_HANDLE) -> CK_RV { let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); if manager.close_session(hSession).is_err() { log_with_thread_id!(error, "C_CloseSession: CKR_SESSION_HANDLE_INVALID"); return CKR_SESSION_HANDLE_INVALID; } log_with_thread_id!(debug, "C_CloseSession: CKR_OK"); CKR_OK } extern "C" fn C_CloseAllSessions(slotID: CK_SLOT_ID) -> CK_RV { let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); match manager.close_all_sessions(slotID) { Ok(()) => { log_with_thread_id!(debug, "C_CloseAllSessions: CKR_OK"); CKR_OK } Err(e) => { log_with_thread_id!( error, "C_CloseAllSessions: close_all_sessions failed: {}", e ); CKR_DEVICE_ERROR } } } extern "C" fn C_GetSessionInfo( hSession: CK_SESSION_HANDLE, pInfo: CK_SESSION_INFO_PTR, ) -> CK_RV { if pInfo.is_null() { log_with_thread_id!(error, "C_GetSessionInfo: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); let Ok(session_info) = manager.get_session_info(hSession) else { log_with_thread_id!(error, "C_GetSessionInfo: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; }; unsafe { *pInfo = session_info; } log_with_thread_id!(debug, "C_GetSessionInfo: CKR_OK"); CKR_OK } extern "C" fn C_Login( hSession: CK_SESSION_HANDLE, _userType: CK_USER_TYPE, _pPin: CK_UTF8CHAR_PTR, _ulPinLen: CK_ULONG, ) -> CK_RV { let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); match manager.login(hSession) { Ok(()) => { log_with_thread_id!(debug, "C_Login: CKR_OK"); CKR_OK } Err(e) => { log_with_thread_id!(error, "C_Login failed: {}", e); CKR_GENERAL_ERROR } } } extern "C" fn C_Logout(hSession: CK_SESSION_HANDLE) -> CK_RV { let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); match manager.logout(hSession) { Ok(()) => { log_with_thread_id!(debug, "C_Logout: CKR_OK"); CKR_OK } Err(e) => { log_with_thread_id!(error, "C_Logout failed: {}", e); CKR_GENERAL_ERROR } } } }; } #[macro_export] macro_rules! declare_pkcs11_find_functions { () => { fn trace_attr(prefix: &str, attr: &CK_ATTRIBUTE) { // Copying out the fields of `attr` avoids making a reference to an unaligned field. let typ = attr.type_; let typ = match typ { CKA_CLASS => "CKA_CLASS".to_string(), CKA_TOKEN => "CKA_TOKEN".to_string(), CKA_LABEL => "CKA_LABEL".to_string(), CKA_ID => "CKA_ID".to_string(), CKA_VALUE => "CKA_VALUE".to_string(), CKA_ISSUER => "CKA_ISSUER".to_string(), CKA_SERIAL_NUMBER => "CKA_SERIAL_NUMBER".to_string(), CKA_SUBJECT => "CKA_SUBJECT".to_string(), CKA_PRIVATE => "CKA_PRIVATE".to_string(), CKA_KEY_TYPE => "CKA_KEY_TYPE".to_string(), CKA_MODULUS => "CKA_MODULUS".to_string(), CKA_EC_PARAMS => "CKA_EC_PARAMS".to_string(), _ => format!("0x{:x}", typ), }; let value = unsafe { std::slice::from_raw_parts(attr.pValue as *const u8, attr.ulValueLen as usize) }; let len = attr.ulValueLen; log_with_thread_id!( trace, "{}CK_ATTRIBUTE {{ type: {}, pValue: {:?}, ulValueLen: {} }}", prefix, typ, value, len ); } const RELEVANT_ATTRIBUTES: &[CK_ATTRIBUTE_TYPE] = &[ CKA_CLASS, CKA_EC_PARAMS, CKA_ID, CKA_ISSUER, CKA_KEY_TYPE, CKA_LABEL, CKA_MODULUS, CKA_PRIVATE, CKA_SERIAL_NUMBER, CKA_SUBJECT, CKA_TOKEN, CKA_VALUE, ]; /// This gets called to initialize a search for objects matching a given list of attributes. extern "C" fn C_FindObjectsInit( hSession: CK_SESSION_HANDLE, pTemplate: CK_ATTRIBUTE_PTR, ulCount: CK_ULONG, ) -> CK_RV { if pTemplate.is_null() { log_with_thread_id!(error, "C_FindObjectsInit: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut attrs = Vec::new(); log_with_thread_id!(trace, "C_FindObjectsInit:"); for i in 0..ulCount as usize { let attr = unsafe { &*pTemplate.add(i) }; trace_attr(" ", attr); // Copy out the attribute type to avoid making a reference to an unaligned field. let attr_type = attr.type_; if !RELEVANT_ATTRIBUTES.contains(&attr_type) { log_with_thread_id!( debug, "C_FindObjectsInit: irrelevant attribute, returning CKR_ATTRIBUTE_TYPE_INVALID" ); return CKR_ATTRIBUTE_TYPE_INVALID; } let slice = unsafe { std::slice::from_raw_parts(attr.pValue as *const u8, attr.ulValueLen as usize) }; attrs.push((attr_type, slice.to_owned())); } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); match manager.start_search(hSession, attrs) { Ok(()) => {} Err(e) => { log_with_thread_id!(error, "C_FindObjectsInit: CKR_ARGUMENTS_BAD: {}", e); return CKR_ARGUMENTS_BAD; } } log_with_thread_id!(debug, "C_FindObjectsInit: CKR_OK"); CKR_OK } /// This gets called after `C_FindObjectsInit` to get the results of a search. extern "C" fn C_FindObjects( hSession: CK_SESSION_HANDLE, phObject: CK_OBJECT_HANDLE_PTR, ulMaxObjectCount: CK_ULONG, pulObjectCount: CK_ULONG_PTR, ) -> CK_RV { if phObject.is_null() || pulObjectCount.is_null() || ulMaxObjectCount == 0 { log_with_thread_id!(error, "C_FindObjects: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); let handles = match manager.search(hSession, ulMaxObjectCount as usize) { Ok(handles) => handles, Err(e) => { log_with_thread_id!(error, "C_FindObjects: CKR_ARGUMENTS_BAD: {}", e); return CKR_ARGUMENTS_BAD; } }; log_with_thread_id!(debug, "C_FindObjects: found handles {:?}", handles); if handles.len() > ulMaxObjectCount as usize { log_with_thread_id!(error, "C_FindObjects: manager returned too many handles"); return CKR_DEVICE_ERROR; } unsafe { *pulObjectCount = handles.len() as CK_ULONG; } for (index, handle) in handles.iter().enumerate() { if index < ulMaxObjectCount as usize { unsafe { *(phObject.add(index)) = *handle; } } } log_with_thread_id!(debug, "C_FindObjects: CKR_OK"); CKR_OK } /// This gets called after `C_FindObjectsInit` and `C_FindObjects` to finish a search. extern "C" fn C_FindObjectsFinal(hSession: CK_SESSION_HANDLE) -> CK_RV { let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); // It would be an error if there were no search for this session, but we can be permissive here. match manager.clear_search(hSession) { Ok(()) => { log_with_thread_id!(debug, "C_FindObjectsFinal: CKR_OK"); CKR_OK } Err(e) => { log_with_thread_id!(error, "C_FindObjectsFinal: clear_search failed: {}", e); CKR_DEVICE_ERROR } } } /// This gets called to obtain the values of a number of attributes of an object identified /// by the given handle. If a specified attribute is not defined on the object, the length /// of that attribute is set to CK_UNAVAILABLE_INFORMATION to indicate that it is not /// available. This gets called twice: once to obtain the lengths of the attributes and /// again to get the values. extern "C" fn C_GetAttributeValue( hSession: CK_SESSION_HANDLE, hObject: CK_OBJECT_HANDLE, pTemplate: CK_ATTRIBUTE_PTR, ulCount: CK_ULONG, ) -> CK_RV { if pTemplate.is_null() { log_with_thread_id!(error, "C_GetAttributeValue: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let mut attr_types = Vec::with_capacity(ulCount as usize); for i in 0..ulCount as usize { let attr = unsafe { &*pTemplate.add(i) }; attr_types.push(attr.type_); } let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); let values = match manager.get_attributes(hSession, hObject, attr_types) { Ok(values) => values, Err(e) => { log_with_thread_id!(error, "C_GetAttributeValue: CKR_ARGUMENTS_BAD ({})", e); return CKR_ARGUMENTS_BAD; } }; if values.len() != ulCount as usize { log_with_thread_id!( error, "C_GetAttributeValue: manager.get_attributes didn't return the right number of values" ); return CKR_DEVICE_ERROR; } for (i, value) in values.iter().enumerate().take(ulCount as usize) { let attr = unsafe { &mut *pTemplate.add(i) }; if let Some(attr_value) = value { if attr.pValue.is_null() { attr.ulValueLen = attr_value.len() as CK_ULONG; } else { let ptr: *mut u8 = attr.pValue as *mut u8; if attr_value.len() != attr.ulValueLen as usize { log_with_thread_id!(error, "C_GetAttributeValue: incorrect attr size"); return CKR_ARGUMENTS_BAD; } unsafe { std::ptr::copy_nonoverlapping(attr_value.as_ptr(), ptr, attr_value.len()); } } } else { attr.ulValueLen = CK_UNAVAILABLE_INFORMATION; } } log_with_thread_id!(debug, "C_GetAttributeValue: CKR_OK"); CKR_OK } }; } #[macro_export] macro_rules! declare_pkcs11_sign_functions { () => { /// This gets called to set up a sign operation. extern "C" fn C_SignInit( hSession: CK_SESSION_HANDLE, pMechanism: CK_MECHANISM_PTR, hKey: CK_OBJECT_HANDLE, ) -> CK_RV { if pMechanism.is_null() { log_with_thread_id!(error, "C_SignInit: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } // Presumably we should validate the mechanism against hKey, but the specification // doesn't actually seem to require this. let mechanism = unsafe { *pMechanism }; log_with_thread_id!(debug, "C_SignInit: mechanism is {:?}", mechanism); let mechanism_params = if mechanism.mechanism == CKM_RSA_PKCS_PSS { if mechanism.ulParameterLen as usize != std::mem::size_of::() { let len = mechanism.ulParameterLen; log_with_thread_id!( error, "C_SignInit: bad ulParameterLen for CKM_RSA_PKCS_PSS: {}", len ); return CKR_ARGUMENTS_BAD; } Some(unsafe { *(mechanism.pParameter as *const CK_RSA_PKCS_PSS_PARAMS) }) } else { None }; let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); match manager.start_sign(hSession, hKey, mechanism_params) { Ok(()) => {} Err(e) => { log_with_thread_id!(error, "C_SignInit: CKR_GENERAL_ERROR: {}", e); return CKR_GENERAL_ERROR; } }; log_with_thread_id!(debug, "C_SignInit: CKR_OK"); CKR_OK } /// NSS calls this after `C_SignInit` (there are more ways in the PKCS #11 specification to /// sign data, but this is the only way supported by these modules). extern "C" fn C_Sign( hSession: CK_SESSION_HANDLE, pData: CK_BYTE_PTR, ulDataLen: CK_ULONG, pSignature: CK_BYTE_PTR, pulSignatureLen: CK_ULONG_PTR, ) -> CK_RV { if pData.is_null() || pulSignatureLen.is_null() { log_with_thread_id!(error, "C_Sign: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let data = unsafe { std::slice::from_raw_parts(pData, ulDataLen as usize) }; if pSignature.is_null() { let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); match manager.get_signature_length(hSession, data.to_vec()) { Ok(signature_length) => unsafe { *pulSignatureLen = signature_length as CK_ULONG; }, Err(e) => { log_with_thread_id!(error, "C_Sign: get_signature_length failed: {}", e); return CKR_GENERAL_ERROR; } } } else { let mut manager_guard = try_to_get_manager_guard!(); let manager = manager_guard_to_manager!(manager_guard); match manager.sign(hSession, data.to_vec()) { Ok(signature) => { let signature_capacity = unsafe { *pulSignatureLen } as usize; if signature_capacity < signature.len() { log_with_thread_id!(error, "C_Sign: CKR_ARGUMENTS_BAD"); return CKR_ARGUMENTS_BAD; } let ptr: *mut u8 = pSignature as *mut u8; unsafe { std::ptr::copy_nonoverlapping(signature.as_ptr(), ptr, signature.len()); *pulSignatureLen = signature.len() as CK_ULONG; } } Err(e) => { log_with_thread_id!(error, "C_Sign: sign failed: {}", e); return CKR_GENERAL_ERROR; } } } log_with_thread_id!(debug, "C_Sign: CKR_OK"); CKR_OK } }; } #[macro_export] macro_rules! declare_unsupported_pkcs11_functions { () => { extern "C" fn C_GetMechanismInfo( _slotID: CK_SLOT_ID, _type: CK_MECHANISM_TYPE, _pInfo: CK_MECHANISM_INFO_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_GetMechanismInfo: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_InitToken( _slotID: CK_SLOT_ID, _pPin: CK_UTF8CHAR_PTR, _ulPinLen: CK_ULONG, _pLabel: CK_UTF8CHAR_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_InitToken: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_InitPIN( _hSession: CK_SESSION_HANDLE, _pPin: CK_UTF8CHAR_PTR, _ulPinLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_InitPIN: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SetPIN( _hSession: CK_SESSION_HANDLE, _pOldPin: CK_UTF8CHAR_PTR, _ulOldLen: CK_ULONG, _pNewPin: CK_UTF8CHAR_PTR, _ulNewLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_SetPIN: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_GetOperationState( _hSession: CK_SESSION_HANDLE, _pOperationState: CK_BYTE_PTR, _pulOperationStateLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_GetOperationState: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SetOperationState( _hSession: CK_SESSION_HANDLE, _pOperationState: CK_BYTE_PTR, _ulOperationStateLen: CK_ULONG, _hEncryptionKey: CK_OBJECT_HANDLE, _hAuthenticationKey: CK_OBJECT_HANDLE, ) -> CK_RV { log_with_thread_id!(error, "C_SetOperationState: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_CreateObject( _hSession: CK_SESSION_HANDLE, _pTemplate: CK_ATTRIBUTE_PTR, _ulCount: CK_ULONG, _phObject: CK_OBJECT_HANDLE_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_InitPIN: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_CopyObject( _hSession: CK_SESSION_HANDLE, _hObject: CK_OBJECT_HANDLE, _pTemplate: CK_ATTRIBUTE_PTR, _ulCount: CK_ULONG, _phNewObject: CK_OBJECT_HANDLE_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_CopyObject: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DestroyObject( _hSession: CK_SESSION_HANDLE, _hObject: CK_OBJECT_HANDLE, ) -> CK_RV { log_with_thread_id!(error, "C_DestroyObject: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_GetObjectSize( _hSession: CK_SESSION_HANDLE, _hObject: CK_OBJECT_HANDLE, _pulSize: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_GetObjectSize: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SetAttributeValue( _hSession: CK_SESSION_HANDLE, _hObject: CK_OBJECT_HANDLE, _pTemplate: CK_ATTRIBUTE_PTR, _ulCount: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_SetAttributeValue: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_EncryptInit( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _hKey: CK_OBJECT_HANDLE, ) -> CK_RV { log_with_thread_id!(error, "C_EncryptInit: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_Encrypt( _hSession: CK_SESSION_HANDLE, _pData: CK_BYTE_PTR, _ulDataLen: CK_ULONG, _pEncryptedData: CK_BYTE_PTR, _pulEncryptedDataLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_Encrypt: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_EncryptUpdate( _hSession: CK_SESSION_HANDLE, _pPart: CK_BYTE_PTR, _ulPartLen: CK_ULONG, _pEncryptedPart: CK_BYTE_PTR, _pulEncryptedPartLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_EncryptUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_EncryptFinal( _hSession: CK_SESSION_HANDLE, _pLastEncryptedPart: CK_BYTE_PTR, _pulLastEncryptedPartLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_EncryptFinal: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DecryptInit( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _hKey: CK_OBJECT_HANDLE, ) -> CK_RV { log_with_thread_id!(error, "C_DecryptInit: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_Decrypt( _hSession: CK_SESSION_HANDLE, _pEncryptedData: CK_BYTE_PTR, _ulEncryptedDataLen: CK_ULONG, _pData: CK_BYTE_PTR, _pulDataLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_Decrypt: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DecryptUpdate( _hSession: CK_SESSION_HANDLE, _pEncryptedPart: CK_BYTE_PTR, _ulEncryptedPartLen: CK_ULONG, _pPart: CK_BYTE_PTR, _pulPartLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_DecryptUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DecryptFinal( _hSession: CK_SESSION_HANDLE, _pLastPart: CK_BYTE_PTR, _pulLastPartLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_DecryptFinal: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DigestInit( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_DigestInit: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_Digest( _hSession: CK_SESSION_HANDLE, _pData: CK_BYTE_PTR, _ulDataLen: CK_ULONG, _pDigest: CK_BYTE_PTR, _pulDigestLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_Digest: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DigestUpdate( _hSession: CK_SESSION_HANDLE, _pPart: CK_BYTE_PTR, _ulPartLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_DigestUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DigestKey(_hSession: CK_SESSION_HANDLE, _hKey: CK_OBJECT_HANDLE) -> CK_RV { log_with_thread_id!(error, "C_DigestKey: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DigestFinal( _hSession: CK_SESSION_HANDLE, _pDigest: CK_BYTE_PTR, _pulDigestLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_DigestFinal: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SignUpdate( _hSession: CK_SESSION_HANDLE, _pPart: CK_BYTE_PTR, _ulPartLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_SignUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SignFinal( _hSession: CK_SESSION_HANDLE, _pSignature: CK_BYTE_PTR, _pulSignatureLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_SignFinal: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SignRecoverInit( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _hKey: CK_OBJECT_HANDLE, ) -> CK_RV { log_with_thread_id!(error, "C_SignRecoverInit: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SignRecover( _hSession: CK_SESSION_HANDLE, _pData: CK_BYTE_PTR, _ulDataLen: CK_ULONG, _pSignature: CK_BYTE_PTR, _pulSignatureLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_SignRecover: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_VerifyInit( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _hKey: CK_OBJECT_HANDLE, ) -> CK_RV { log_with_thread_id!(error, "C_VerifyInit: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_Verify( _hSession: CK_SESSION_HANDLE, _pData: CK_BYTE_PTR, _ulDataLen: CK_ULONG, _pSignature: CK_BYTE_PTR, _ulSignatureLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_Verify: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_VerifyUpdate( _hSession: CK_SESSION_HANDLE, _pPart: CK_BYTE_PTR, _ulPartLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_VerifyUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_VerifyFinal( _hSession: CK_SESSION_HANDLE, _pSignature: CK_BYTE_PTR, _ulSignatureLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_VerifyFinal: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_VerifyRecoverInit( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _hKey: CK_OBJECT_HANDLE, ) -> CK_RV { log_with_thread_id!(error, "C_VerifyRecoverInit: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_VerifyRecover( _hSession: CK_SESSION_HANDLE, _pSignature: CK_BYTE_PTR, _ulSignatureLen: CK_ULONG, _pData: CK_BYTE_PTR, _pulDataLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_VerifyRecover: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DigestEncryptUpdate( _hSession: CK_SESSION_HANDLE, _pPart: CK_BYTE_PTR, _ulPartLen: CK_ULONG, _pEncryptedPart: CK_BYTE_PTR, _pulEncryptedPartLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_DigestEncryptUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DecryptDigestUpdate( _hSession: CK_SESSION_HANDLE, _pEncryptedPart: CK_BYTE_PTR, _ulEncryptedPartLen: CK_ULONG, _pPart: CK_BYTE_PTR, _pulPartLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_DecryptDigestUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SignEncryptUpdate( _hSession: CK_SESSION_HANDLE, _pPart: CK_BYTE_PTR, _ulPartLen: CK_ULONG, _pEncryptedPart: CK_BYTE_PTR, _pulEncryptedPartLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_SignEncryptUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DecryptVerifyUpdate( _hSession: CK_SESSION_HANDLE, _pEncryptedPart: CK_BYTE_PTR, _ulEncryptedPartLen: CK_ULONG, _pPart: CK_BYTE_PTR, _pulPartLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_DecryptVerifyUpdate: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_GenerateKey( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _pTemplate: CK_ATTRIBUTE_PTR, _ulCount: CK_ULONG, _phKey: CK_OBJECT_HANDLE_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_GenerateKey: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_GenerateKeyPair( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _pPublicKeyTemplate: CK_ATTRIBUTE_PTR, _ulPublicKeyAttributeCount: CK_ULONG, _pPrivateKeyTemplate: CK_ATTRIBUTE_PTR, _ulPrivateKeyAttributeCount: CK_ULONG, _phPublicKey: CK_OBJECT_HANDLE_PTR, _phPrivateKey: CK_OBJECT_HANDLE_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_GenerateKeyPair: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_WrapKey( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _hWrappingKey: CK_OBJECT_HANDLE, _hKey: CK_OBJECT_HANDLE, _pWrappedKey: CK_BYTE_PTR, _pulWrappedKeyLen: CK_ULONG_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_WrapKey: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_UnwrapKey( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _hUnwrappingKey: CK_OBJECT_HANDLE, _pWrappedKey: CK_BYTE_PTR, _ulWrappedKeyLen: CK_ULONG, _pTemplate: CK_ATTRIBUTE_PTR, _ulAttributeCount: CK_ULONG, _phKey: CK_OBJECT_HANDLE_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_UnwrapKey: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_DeriveKey( _hSession: CK_SESSION_HANDLE, _pMechanism: CK_MECHANISM_PTR, _hBaseKey: CK_OBJECT_HANDLE, _pTemplate: CK_ATTRIBUTE_PTR, _ulAttributeCount: CK_ULONG, _phKey: CK_OBJECT_HANDLE_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_DeriveKey: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_SeedRandom( _hSession: CK_SESSION_HANDLE, _pSeed: CK_BYTE_PTR, _ulSeedLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_SeedRandom: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_GenerateRandom( _hSession: CK_SESSION_HANDLE, _RandomData: CK_BYTE_PTR, _ulRandomLen: CK_ULONG, ) -> CK_RV { log_with_thread_id!(error, "C_GenerateRandom: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_GetFunctionStatus(_hSession: CK_SESSION_HANDLE) -> CK_RV { log_with_thread_id!(error, "C_GetFunctionStatus: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_CancelFunction(_hSession: CK_SESSION_HANDLE) -> CK_RV { log_with_thread_id!(error, "C_CancelFunction: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } extern "C" fn C_WaitForSlotEvent( _flags: CK_FLAGS, _pSlot: CK_SLOT_ID_PTR, _pRserved: CK_VOID_PTR, ) -> CK_RV { log_with_thread_id!(error, "C_WaitForSlotEvent: CKR_FUNCTION_NOT_SUPPORTED"); CKR_FUNCTION_NOT_SUPPORTED } }; }