/* * Copyright 2011-2016 The Pkcs11Interop Project * Copyright 2019 Igalia S.L. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ /* * Originally written for the Pkcs11Interop project by: Jaroslav IMRICH */ /* * This file implements a PKCS #11 module to be loaded that returns a mock slot and objects. * * It is based on this project originally: https://github.com/Pkcs11Interop/pkcs11-mock * * Quite a few things have been changed since then though: * - The CK defines just below use glib macros just out of convenience. * - Logging was added just for ease of debugging. * - Instead of hardcoded defines for objects this now has an array * of mock_objects that is easier to read and extend. The search behavior * of C_FindObjects was also updated to actually search through this. * - The certificates/keys are real certificates/keys backed by gnutls * loading them in C_Initialize from glib-networkings normal test data. * This changes the behavior of many functions most notably including C_GetAttributeValue * and C_Sign to use them. Any function not used in a TLS handshake was largely * ignored and won't work. */ #undef G_LOG_DOMAIN #define G_LOG_DOMAIN "MockPKCS11" #include #include #include #include /* See http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html */ #define CK_PTR * #define CK_DEFINE_FUNCTION(returnType, name) returnType G_MODULE_EXPORT name #define CK_DECLARE_FUNCTION(returnType, name) returnType G_MODULE_EXPORT name #define CK_DECLARE_FUNCTION_POINTER(returnType, name) returnType (* name) #define CK_CALLBACK_FUNCTION(returnType, name) returnType (* name) #define NULL_PTR NULL #include "pkcs11/pkcs11.h" #define IGNORE(P) (void)(P) #define MOCK_MANUFACTURER_ID "GLib-Networking" #define MOCK_MODEL "mock" #define PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN 256 #define PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN 4 static CK_INFO mock_info = { .cryptokiVersion = { 2, 40 }, .manufacturerID = MOCK_MANUFACTURER_ID, .libraryDescription = "Mock Module", }; typedef struct { CK_OBJECT_CLASS object_class; CK_TOKEN_INFO info; union { gnutls_x509_crt_t cert; gnutls_privkey_t key; }; } MockObject; static MockObject mock_objects[] = { { .object_class = CKO_CERTIFICATE, .info = { .model = MOCK_MODEL, .label = "Mock Certificate", .serialNumber = "1", .manufacturerID = MOCK_MANUFACTURER_ID, .flags = CKF_TOKEN_INITIALIZED | CKF_WRITE_PROTECTED | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED, .ulMaxSessionCount = 1, }, }, { .object_class = CKO_PRIVATE_KEY, .info = { .model = MOCK_MODEL, .label = "Mock Private Key", .serialNumber = "2", .manufacturerID = MOCK_MANUFACTURER_ID, .flags = CKF_TOKEN_INITIALIZED | CKF_WRITE_PROTECTED | CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED, .ulMaxSessionCount = 1, .ulMaxPinLen = PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN, .ulMinPinLen = PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN, }, } }; typedef struct { CK_SLOT_INFO info; //CK_TOKEN_INFO_PTR tokens[2]; } MockSlot; static const MockSlot mock_slots[] = { { .info = { .slotDescription = "Mock Slot", .manufacturerID = MOCK_MANUFACTURER_ID, .flags = CKF_TOKEN_PRESENT, }, } }; // FIXME: These are left overs that are unused #define PKCS11_MOCK_CK_OBJECT_HANDLE_DATA 1 #define PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY 2 #define PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY 3 #define PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY 4 #define PKCS11_MOCK_CK_SLOT_ID 0 #define PKCS11_MOCK_CK_SESSION_ID 1 typedef enum { PKCS11_MOCK_CK_OPERATION_NONE, PKCS11_MOCK_CK_OPERATION_FIND, PKCS11_MOCK_CK_OPERATION_ENCRYPT, PKCS11_MOCK_CK_OPERATION_DECRYPT, PKCS11_MOCK_CK_OPERATION_DIGEST, PKCS11_MOCK_CK_OPERATION_SIGN, PKCS11_MOCK_CK_OPERATION_SIGN_RECOVER, PKCS11_MOCK_CK_OPERATION_VERIFY, PKCS11_MOCK_CK_OPERATION_VERIFY_RECOVER, PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT, PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST, PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT, PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY } PKCS11_MOCK_CK_OPERATION; #define PKCS11_MOCK_CKO_ANYTHING -1 // We'll use -1 as a magic match all static CK_BBOOL pkcs11_mock_initialized = CK_FALSE; static CK_BBOOL pkcs11_mock_session_opened = CK_FALSE; static CK_ULONG pkcs11_mock_session_state = CKS_RO_PUBLIC_SESSION; static PKCS11_MOCK_CK_OPERATION pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; static CK_ULONG pkcs11_mock_sign_key = 0; static CK_LONG mock_search_template_class = PKCS11_MOCK_CKO_ANYTHING; static char *mock_search_template_label; static CK_ULONG mock_search_iterator = 0; static gboolean mock_logged_in_state = FALSE; static size_t mock_login_attempts = 0; static CK_ULONG mock_sign_algo = 0; /* LCOV_EXCL_START */ static CK_FUNCTION_LIST pkcs11_mock_functions = { {2, 20}, &C_Initialize, &C_Finalize, &C_GetInfo, &C_GetFunctionList, &C_GetSlotList, &C_GetSlotInfo, &C_GetTokenInfo, &C_GetMechanismList, &C_GetMechanismInfo, &C_InitToken, &C_InitPIN, &C_SetPIN, &C_OpenSession, &C_CloseSession, &C_CloseAllSessions, &C_GetSessionInfo, &C_GetOperationState, &C_SetOperationState, &C_Login, &C_Logout, &C_CreateObject, &C_CopyObject, &C_DestroyObject, &C_GetObjectSize, &C_GetAttributeValue, &C_SetAttributeValue, &C_FindObjectsInit, &C_FindObjects, &C_FindObjectsFinal, &C_EncryptInit, &C_Encrypt, &C_EncryptUpdate, &C_EncryptFinal, &C_DecryptInit, &C_Decrypt, &C_DecryptUpdate, &C_DecryptFinal, &C_DigestInit, &C_Digest, &C_DigestUpdate, &C_DigestKey, &C_DigestFinal, &C_SignInit, &C_Sign, &C_SignUpdate, &C_SignFinal, &C_SignRecoverInit, &C_SignRecover, &C_VerifyInit, &C_Verify, &C_VerifyUpdate, &C_VerifyFinal, &C_VerifyRecoverInit, &C_VerifyRecover, &C_DigestEncryptUpdate, &C_DecryptDigestUpdate, &C_SignEncryptUpdate, &C_DecryptVerifyUpdate, &C_GenerateKey, &C_GenerateKeyPair, &C_WrapKey, &C_UnwrapKey, &C_DeriveKey, &C_SeedRandom, &C_GenerateRandom, &C_GetFunctionStatus, &C_CancelFunction, &C_WaitForSlotEvent }; /* Copy a string into a buffer without NUL termination and padded with ' ' */ static void copy_padded_string(CK_UTF8CHAR_PTR dest, const CK_UTF8CHAR_PTR src, size_t dest_size) { const size_t len = strlen((char*)src); g_assert (len < dest_size); memset(dest, ' ', dest_size); memcpy(dest, src, len); } CK_DEFINE_FUNCTION(CK_RV, C_Initialize)(CK_VOID_PTR pInitArgs) { int status; gnutls_datum_t data; char *path; if (CK_TRUE == pkcs11_mock_initialized) return CKR_CRYPTOKI_ALREADY_INITIALIZED; IGNORE(pInitArgs); path = g_test_build_filename(G_TEST_DIST, "test-cert.pem", NULL); status = gnutls_load_file(path, &data); g_debug("Loading %s - %s", path, gnutls_strerror(status)); g_assert(status == GNUTLS_E_SUCCESS); status = gnutls_x509_crt_init(&mock_objects[0].cert); g_assert(status == GNUTLS_E_SUCCESS); status = gnutls_x509_crt_import(mock_objects[0].cert, &data, GNUTLS_X509_FMT_PEM); g_assert(status == GNUTLS_E_SUCCESS); gnutls_free(data.data); g_free(path); path = g_test_build_filename(G_TEST_DIST, "test-key.pem", NULL); status = gnutls_load_file(path, &data); g_debug("Loading %s - %s", path, gnutls_strerror(status)); g_assert(status == GNUTLS_E_SUCCESS); status = gnutls_privkey_init(&mock_objects[1].key); g_assert(status == GNUTLS_E_SUCCESS); status = gnutls_privkey_import_x509_raw(mock_objects[1].key, &data, GNUTLS_X509_FMT_PEM, NULL, 0); g_assert(status == GNUTLS_E_SUCCESS); gnutls_free(data.data); g_free(path); pkcs11_mock_initialized = CK_TRUE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_Finalize)(CK_VOID_PTR pReserved) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; IGNORE(pReserved); gnutls_x509_crt_deinit(mock_objects[0].cert); gnutls_privkey_deinit(mock_objects[1].key); pkcs11_mock_initialized = CK_FALSE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetInfo)(CK_INFO_PTR pInfo) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (NULL == pInfo) return CKR_ARGUMENTS_BAD; pInfo->cryptokiVersion = mock_info.cryptokiVersion; copy_padded_string(pInfo->manufacturerID, mock_info.manufacturerID, sizeof(pInfo->manufacturerID)); pInfo->flags = 0; copy_padded_string(pInfo->libraryDescription, mock_info.libraryDescription, sizeof(pInfo->libraryDescription)); pInfo->libraryVersion = mock_info.libraryVersion; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionList)(CK_FUNCTION_LIST_PTR_PTR ppFunctionList) { if (NULL == ppFunctionList) return CKR_ARGUMENTS_BAD; *ppFunctionList = &pkcs11_mock_functions; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetSlotList)(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList, CK_ULONG_PTR pulCount) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; IGNORE(tokenPresent); if (NULL == pulCount) return CKR_ARGUMENTS_BAD; if (NULL == pSlotList) { *pulCount = 1; } else { if (0 == *pulCount) return CKR_BUFFER_TOO_SMALL; pSlotList[0] = PKCS11_MOCK_CK_SLOT_ID; *pulCount = 1; } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetSlotInfo)(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo) { MockSlot mock_slot; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (slotID > G_N_ELEMENTS (mock_slots)) return CKR_SLOT_ID_INVALID; if (NULL == pInfo) return CKR_ARGUMENTS_BAD; mock_slot = mock_slots[slotID]; copy_padded_string(pInfo->slotDescription, mock_slot.info.slotDescription, sizeof(pInfo->slotDescription)); copy_padded_string(pInfo->manufacturerID, mock_slot.info.manufacturerID, sizeof(pInfo->manufacturerID)); pInfo->flags = mock_slot.info.flags; pInfo->hardwareVersion = mock_slot.info.hardwareVersion; pInfo->firmwareVersion = mock_slot.info.firmwareVersion; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetTokenInfo)(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo) { CK_TOKEN_INFO token; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (slotID > G_N_ELEMENTS (mock_slots)) return CKR_SLOT_ID_INVALID; if (NULL == pInfo) return CKR_ARGUMENTS_BAD; token = mock_objects[slotID].info; copy_padded_string(pInfo->label, token.label, sizeof(pInfo->label)); copy_padded_string(pInfo->manufacturerID, token.manufacturerID, sizeof(pInfo->manufacturerID)); copy_padded_string(pInfo->serialNumber, token.serialNumber, sizeof(pInfo->serialNumber)); copy_padded_string(pInfo->model, token.model, sizeof(pInfo->model)); pInfo->flags = token.flags; pInfo->ulMaxSessionCount = token.ulMaxSessionCount; pInfo->ulSessionCount = (CK_TRUE == pkcs11_mock_session_opened) ? 1 : 0; pInfo->ulMaxRwSessionCount = token.ulMaxRwSessionCount; pInfo->ulRwSessionCount = ((CK_TRUE == pkcs11_mock_session_opened) && ((CKS_RO_PUBLIC_SESSION != pkcs11_mock_session_state) || (CKS_RO_USER_FUNCTIONS != pkcs11_mock_session_state))) ? 1 : 0; pInfo->ulMaxPinLen = token.ulMaxPinLen; pInfo->ulMinPinLen = token.ulMinPinLen; pInfo->ulTotalPublicMemory = token.ulTotalPublicMemory; pInfo->ulFreePublicMemory = token.ulFreePublicMemory; pInfo->ulTotalPrivateMemory = token.ulTotalPrivateMemory; pInfo->ulFreePrivateMemory = token.ulFreePrivateMemory; pInfo->hardwareVersion = token.hardwareVersion; pInfo->firmwareVersion = token.firmwareVersion; memset(pInfo->utcTime, ' ', sizeof(pInfo->utcTime)); // FIXME: Not picked up by gnutls if (mock_login_attempts > 2) { pInfo->flags |= CKF_USER_PIN_COUNT_LOW; } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismList)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList, CK_ULONG_PTR pulCount) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (slotID > G_N_ELEMENTS(mock_slots)) return CKR_SLOT_ID_INVALID; if (NULL == pulCount) return CKR_ARGUMENTS_BAD; if (NULL == pMechanismList) { *pulCount = 9; } else { if (9 > *pulCount) return CKR_BUFFER_TOO_SMALL; pMechanismList[0] = CKM_RSA_PKCS_KEY_PAIR_GEN; pMechanismList[1] = CKM_RSA_PKCS; pMechanismList[2] = CKM_SHA1_RSA_PKCS; pMechanismList[3] = CKM_RSA_PKCS_OAEP; pMechanismList[4] = CKM_DES3_CBC; pMechanismList[5] = CKM_DES3_KEY_GEN; pMechanismList[6] = CKM_SHA_1; pMechanismList[7] = CKM_XOR_BASE_AND_DATA; pMechanismList[8] = CKM_AES_CBC; *pulCount = 9; } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetMechanismInfo)(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type, CK_MECHANISM_INFO_PTR pInfo) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_SLOT_ID != slotID) return CKR_SLOT_ID_INVALID; if (NULL == pInfo) return CKR_ARGUMENTS_BAD; switch (type) { case CKM_RSA_PKCS_KEY_PAIR_GEN: pInfo->ulMinKeySize = 1024; pInfo->ulMaxKeySize = 1024; pInfo->flags = CKF_GENERATE_KEY_PAIR; break; case CKM_RSA_PKCS: pInfo->ulMinKeySize = 1024; pInfo->ulMaxKeySize = 1024; pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT | CKF_SIGN | CKF_SIGN_RECOVER | CKF_VERIFY | CKF_VERIFY_RECOVER | CKF_WRAP | CKF_UNWRAP; break; case CKM_SHA1_RSA_PKCS: pInfo->ulMinKeySize = 1024; pInfo->ulMaxKeySize = 1024; pInfo->flags = CKF_SIGN | CKF_VERIFY; break; case CKM_RSA_PKCS_OAEP: pInfo->ulMinKeySize = 1024; pInfo->ulMaxKeySize = 1024; pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT; break; case CKM_DES3_CBC: pInfo->ulMinKeySize = 192; pInfo->ulMaxKeySize = 192; pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT; break; case CKM_DES3_KEY_GEN: pInfo->ulMinKeySize = 192; pInfo->ulMaxKeySize = 192; pInfo->flags = CKF_GENERATE; break; case CKM_SHA_1: pInfo->ulMinKeySize = 0; pInfo->ulMaxKeySize = 0; pInfo->flags = CKF_DIGEST; break; case CKM_XOR_BASE_AND_DATA: pInfo->ulMinKeySize = 128; pInfo->ulMaxKeySize = 256; pInfo->flags = CKF_DERIVE; break; case CKM_AES_CBC: pInfo->ulMinKeySize = 128; pInfo->ulMaxKeySize = 256; pInfo->flags = CKF_ENCRYPT | CKF_DECRYPT; break; case CKM_RSA_PKCS_PSS: // FIXME: Made up key sizes pInfo->ulMinKeySize = 256; pInfo->ulMaxKeySize = 256; // Flags based on table here: http://docs.oasis-open.org/pkcs11/pkcs11-curr/v2.40/csd01/pkcs11-curr-v2.40-csd01.html pInfo->flags = CKF_SIGN | CKF_VERIFY; break; default: return CKR_MECHANISM_INVALID; } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_InitToken)(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen, CK_UTF8CHAR_PTR pLabel) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_SLOT_ID != slotID) return CKR_SLOT_ID_INVALID; if (NULL == pPin) return CKR_ARGUMENTS_BAD; if ((ulPinLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulPinLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN)) return CKR_PIN_LEN_RANGE; if (NULL == pLabel) return CKR_ARGUMENTS_BAD; if (CK_TRUE == pkcs11_mock_session_opened) return CKR_SESSION_EXISTS; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_InitPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (CKS_RW_SO_FUNCTIONS != pkcs11_mock_session_state) return CKR_USER_NOT_LOGGED_IN; if (NULL == pPin) return CKR_ARGUMENTS_BAD; if ((ulPinLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulPinLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN)) return CKR_PIN_LEN_RANGE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SetPIN)(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if ((CKS_RO_PUBLIC_SESSION == pkcs11_mock_session_state) || (CKS_RO_USER_FUNCTIONS == pkcs11_mock_session_state)) return CKR_SESSION_READ_ONLY; if (NULL == pOldPin) return CKR_ARGUMENTS_BAD; if ((ulOldLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulOldLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN)) return CKR_PIN_LEN_RANGE; if (NULL == pNewPin) return CKR_ARGUMENTS_BAD; if ((ulNewLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulNewLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN)) return CKR_PIN_LEN_RANGE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_OpenSession)(CK_SLOT_ID slotID, CK_FLAGS flags, CK_VOID_PTR pApplication, CK_NOTIFY Notify, CK_SESSION_HANDLE_PTR phSession) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (CK_TRUE == pkcs11_mock_session_opened) return CKR_SESSION_COUNT; if (PKCS11_MOCK_CK_SLOT_ID != slotID) return CKR_SLOT_ID_INVALID; if (!(flags & CKF_SERIAL_SESSION)) return CKR_SESSION_PARALLEL_NOT_SUPPORTED; IGNORE(pApplication); IGNORE(Notify); if (NULL == phSession) return CKR_ARGUMENTS_BAD; pkcs11_mock_session_opened = CK_TRUE; pkcs11_mock_session_state = (flags & CKF_RW_SESSION) ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION; *phSession = PKCS11_MOCK_CK_SESSION_ID; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_CloseSession)(CK_SESSION_HANDLE hSession) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; pkcs11_mock_session_opened = CK_FALSE; pkcs11_mock_session_state = CKS_RO_PUBLIC_SESSION; pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_CloseAllSessions)(CK_SLOT_ID slotID) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_SLOT_ID != slotID) return CKR_SLOT_ID_INVALID; pkcs11_mock_session_opened = CK_FALSE; pkcs11_mock_session_state = CKS_RO_PUBLIC_SESSION; pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetSessionInfo)(CK_SESSION_HANDLE hSession, CK_SESSION_INFO_PTR pInfo) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pInfo) return CKR_ARGUMENTS_BAD; pInfo->slotID = PKCS11_MOCK_CK_SLOT_ID; pInfo->state = pkcs11_mock_session_state; pInfo->flags = CKF_SERIAL_SESSION; if ((pkcs11_mock_session_state != CKS_RO_PUBLIC_SESSION) && (pkcs11_mock_session_state != CKS_RO_USER_FUNCTIONS)) pInfo->flags = pInfo->flags | CKF_RW_SESSION; pInfo->ulDeviceError = 0; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetOperationState)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG_PTR pulOperationStateLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pulOperationStateLen) return CKR_ARGUMENTS_BAD; if (NULL == pOperationState) { *pulOperationStateLen = 256; } else { if (256 > *pulOperationStateLen) return CKR_BUFFER_TOO_SMALL; memset(pOperationState, 1, 256); *pulOperationStateLen = 256; } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SetOperationState)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pOperationState, CK_ULONG ulOperationStateLen, CK_OBJECT_HANDLE hEncryptionKey, CK_OBJECT_HANDLE hAuthenticationKey) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pOperationState) return CKR_ARGUMENTS_BAD; if (256 != ulOperationStateLen) return CKR_ARGUMENTS_BAD; IGNORE(hEncryptionKey); IGNORE(hAuthenticationKey); return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_Login)(CK_SESSION_HANDLE hSession, CK_USER_TYPE userType, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen) { // More hardcoding const char *password = "ABC123"; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if ((CKU_SO != userType) && (CKU_USER != userType) && (CKU_CONTEXT_SPECIFIC != userType)) return CKR_USER_TYPE_INVALID; if (NULL == pPin) return CKR_ARGUMENTS_BAD; if ((ulPinLen < PKCS11_MOCK_CK_TOKEN_INFO_MIN_PIN_LEN) || (ulPinLen > PKCS11_MOCK_CK_TOKEN_INFO_MAX_PIN_LEN)) return CKR_PIN_LEN_RANGE; // FIXME: gnutls bug? It calls this before an operation // if (pkcs11_mock_active_operation == PKCS11_MOCK_CK_OPERATION_NONE && CKU_CONTEXT_SPECIFIC != userType) // return CKR_OPERATION_NOT_INITIALIZED; if (mock_logged_in_state == TRUE) return CKR_USER_ALREADY_LOGGED_IN; if (ulPinLen == strlen (password) && strncmp ((char*)pPin, password, ulPinLen) == 0) { mock_logged_in_state = TRUE; mock_login_attempts = 0; return CKR_OK; } else { mock_login_attempts += 1; return CKR_PIN_INCORRECT; } // TODO: We don't test any of these states atm // switch (pkcs11_mock_session_state) // { // case CKS_RO_PUBLIC_SESSION: // if (CKU_SO == userType) // rv = CKR_SESSION_READ_ONLY_EXISTS; // else // pkcs11_mock_session_state = CKS_RO_USER_FUNCTIONS; // break; // case CKS_RO_USER_FUNCTIONS: // case CKS_RW_USER_FUNCTIONS: // rv = (CKU_SO == userType) ? CKR_USER_ANOTHER_ALREADY_LOGGED_IN : CKR_USER_ALREADY_LOGGED_IN; // break; // case CKS_RW_PUBLIC_SESSION: // pkcs11_mock_session_state = (CKU_SO == userType) ? CKS_RW_SO_FUNCTIONS : CKS_RW_USER_FUNCTIONS; // break; // case CKS_RW_SO_FUNCTIONS: // rv = (CKU_SO == userType) ? CKR_USER_ALREADY_LOGGED_IN : CKR_USER_ANOTHER_ALREADY_LOGGED_IN; // break; // } // return rv; } CK_DEFINE_FUNCTION(CK_RV, C_Logout)(CK_SESSION_HANDLE hSession) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (mock_logged_in_state == FALSE) return CKR_USER_NOT_LOGGED_IN; // if ((pkcs11_mock_session_state == CKS_RO_PUBLIC_SESSION) || (pkcs11_mock_session_state == CKS_RW_PUBLIC_SESSION)) // return CKR_USER_NOT_LOGGED_IN; mock_logged_in_state = FALSE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_CreateObject)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pTemplate) return CKR_ARGUMENTS_BAD; if (0 >= ulCount) return CKR_ARGUMENTS_BAD; if (NULL == phObject) return CKR_ARGUMENTS_BAD; for (i = 0; i < ulCount; i++) { if (NULL == pTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; } *phObject = PKCS11_MOCK_CK_OBJECT_HANDLE_DATA; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_CopyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phNewObject) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_DATA != hObject) return CKR_OBJECT_HANDLE_INVALID; if (NULL == phNewObject) return CKR_ARGUMENTS_BAD; if ((NULL != pTemplate) && (0 >= ulCount)) { for (i = 0; i < ulCount; i++) { if (NULL == pTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; } } *phNewObject = PKCS11_MOCK_CK_OBJECT_HANDLE_DATA; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DestroyObject)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if ((PKCS11_MOCK_CK_OBJECT_HANDLE_DATA != hObject) && (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hObject) && (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hObject) && (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hObject)) return CKR_OBJECT_HANDLE_INVALID; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetObjectSize)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ULONG_PTR pulSize) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (hObject > G_N_ELEMENTS (mock_objects)) return CKR_OBJECT_HANDLE_INVALID; if (NULL == pulSize) return CKR_ARGUMENTS_BAD; *pulSize = 0; // FIXME: mock_objects[hObject].size; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_ULONG i = 0; MockObject obj; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (hObject > G_N_ELEMENTS (mock_objects)) return CKR_OBJECT_HANDLE_INVALID; if (NULL == pTemplate) return CKR_ARGUMENTS_BAD; if (0 >= ulCount) return CKR_ARGUMENTS_BAD; obj = mock_objects[hObject]; for (i = 0; i < ulCount; i++) { if (CKA_LABEL == pTemplate[i].type || CKA_ID == pTemplate[i].type) { if (NULL != pTemplate[i].pValue) { if (pTemplate[i].ulValueLen < strlen((char*)obj.info.label)) return CKR_BUFFER_TOO_SMALL; else memcpy(pTemplate[i].pValue, obj.info.label, strlen((char*)obj.info.label)); } pTemplate[i].ulValueLen = strlen((char*)obj.info.label); } else if (CKA_EXTRACTABLE == pTemplate[i].type) { *((CK_BBOOL *) pTemplate[i].pValue) = obj.object_class == CKO_CERTIFICATE ? CK_TRUE : CK_FALSE; pTemplate[i].ulValueLen = sizeof(CK_BBOOL); } else if (CKA_NEVER_EXTRACTABLE == pTemplate[i].type || CKA_SENSITIVE == pTemplate[i].type) { *((CK_BBOOL *) pTemplate[i].pValue) = obj.object_class == CKO_PRIVATE_KEY ? CK_TRUE : CK_FALSE; pTemplate[i].ulValueLen = sizeof(CK_BBOOL); } else if (CKA_CERTIFICATE_CATEGORY == pTemplate[i].type) { CK_ULONG t; if (pTemplate[i].ulValueLen < sizeof(CK_ULONG)) return CKR_BUFFER_TOO_SMALL; if (obj.object_class == CKO_CERTIFICATE) t = CK_CERTIFICATE_CATEGORY_AUTHORITY; else t = CK_CERTIFICATE_CATEGORY_UNSPECIFIED; memcpy(pTemplate[i].pValue, &t, sizeof(CK_ULONG)); } else if (CKA_SUBJECT == pTemplate[i].type) { int status; gnutls_datum_t data; gnutls_x509_dn_t dn; /* Owned by cert */ g_assert (obj.object_class == CKO_CERTIFICATE); status = gnutls_x509_crt_get_subject(obj.cert, &dn); g_assert(status == GNUTLS_E_SUCCESS); status = gnutls_x509_dn_get_str(dn, &data); g_assert(status == GNUTLS_E_SUCCESS); if (data.size > pTemplate[i].ulValueLen) { gnutls_free(data.data); pTemplate[i].ulValueLen = data.size; if (pTemplate[i].pValue != NULL) /* If NULL return OK */ return CKR_BUFFER_TOO_SMALL; } else { memcpy(pTemplate[i].pValue, data.data, data.size); pTemplate[i].ulValueLen = data.size; gnutls_free(data.data); } } else if (CKA_VALUE == pTemplate[i].type) { if (obj.object_class == CKO_CERTIFICATE) { int status; gnutls_datum_t data; status = gnutls_x509_crt_export2(obj.cert, GNUTLS_X509_FMT_DER, &data); g_assert(status == GNUTLS_E_SUCCESS); if (data.size > pTemplate[i].ulValueLen) { gnutls_free(data.data); pTemplate[i].ulValueLen = data.size; if (pTemplate[i].pValue != NULL) /* If NULL return OK */ return CKR_BUFFER_TOO_SMALL; } else { memcpy(pTemplate[i].pValue, data.data, data.size); gnutls_free(data.data); pTemplate[i].ulValueLen = data.size; } } else { pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION; } } else if (CKA_CLASS == pTemplate[i].type) { if (NULL != pTemplate[i].pValue) *((CK_ULONG *) pTemplate[i].pValue) = obj.object_class; pTemplate[i].ulValueLen = sizeof (obj.object_class); } else if (CKA_CERTIFICATE_TYPE == pTemplate[i].type) { CK_CERTIFICATE_TYPE ret = CKC_X_509; if (pTemplate[i].ulValueLen != sizeof(CK_CERTIFICATE_TYPE)) return CKR_ARGUMENTS_BAD; /* TODO: Test both TRUE and FALSE */ memcpy(pTemplate[i].pValue, &ret, sizeof(CK_CERTIFICATE_TYPE)); } else if (CKA_KEY_TYPE == pTemplate[i].type) { CK_KEY_TYPE t; if (pTemplate[i].ulValueLen != sizeof(CK_KEY_TYPE)) return CKR_ARGUMENTS_BAD; if (obj.object_class != CKO_PRIVATE_KEY) return CKR_ARGUMENTS_BAD; switch (gnutls_privkey_get_pk_algorithm (obj.key, NULL)) { case GNUTLS_PK_RSA: t = CKK_RSA; break; case GNUTLS_PK_DSA: t = CKK_DSA; break; case GNUTLS_PK_DH: t = CKK_DH; break; case GNUTLS_PK_EC: t = CKK_EC; break; default: pTemplate[i].ulValueLen = CK_UNAVAILABLE_INFORMATION; return CKR_ATTRIBUTE_TYPE_INVALID; } memcpy(pTemplate[i].pValue, &t, sizeof(CK_KEY_TYPE)); } else if (CKA_ALWAYS_AUTHENTICATE == pTemplate[i].type) { CK_BBOOL ret = CK_TRUE; if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) return CKR_ARGUMENTS_BAD; /* TODO: Test both TRUE and FALSE */ memcpy(pTemplate[i].pValue, &ret, sizeof(CK_BBOOL)); } else if (CKA_MODULUS == pTemplate[i].type && obj.object_class == CKO_PRIVATE_KEY) { /* Hardcode RSA for now */ gnutls_datum_t modulus; int status = gnutls_privkey_export_rsa_raw (obj.key, &modulus, NULL, NULL, NULL, NULL, NULL, NULL, NULL); g_assert (status == GNUTLS_E_SUCCESS); if (modulus.size > pTemplate[i].ulValueLen) { gnutls_free(modulus.data); pTemplate[i].ulValueLen = modulus.size; if (pTemplate[i].pValue != NULL) /* If NULL return OK */ return CKR_BUFFER_TOO_SMALL; } else { memcpy(pTemplate[i].pValue, modulus.data, modulus.size); gnutls_free(modulus.data); pTemplate[i].ulValueLen = modulus.size; } } else if (CKA_SIGN == pTemplate[i].type && obj.object_class == CKO_PRIVATE_KEY) /* Any key type in future */ { CK_BBOOL ret = CK_TRUE; if (pTemplate[i].ulValueLen != sizeof(CK_BBOOL)) return CKR_ARGUMENTS_BAD; memcpy(pTemplate[i].pValue, &ret, sizeof(CK_BBOOL)); } else { return CKR_ATTRIBUTE_TYPE_INVALID; } } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SetAttributeValue)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (hObject > G_N_ELEMENTS (mock_objects)) if ((PKCS11_MOCK_CK_OBJECT_HANDLE_DATA != hObject) && (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hObject) && (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hObject) && (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hObject)) return CKR_OBJECT_HANDLE_INVALID; if (NULL == pTemplate) return CKR_ARGUMENTS_BAD; if (0 >= ulCount) return CKR_ARGUMENTS_BAD; for (i = 0; i < ulCount; i++) { if ((CKA_LABEL == pTemplate[i].type) || (CKA_VALUE == pTemplate[i].type)) { if (NULL == pTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; } else { return CKR_ATTRIBUTE_TYPE_INVALID; } } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsInit)(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount) { CK_ULONG i = 0; CK_ULONG_PTR cka_class_value = NULL; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_NONE != pkcs11_mock_active_operation) return CKR_OPERATION_ACTIVE; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pTemplate && ulCount != 0) return CKR_ARGUMENTS_BAD; mock_search_template_class = PKCS11_MOCK_CKO_ANYTHING; g_clear_pointer (&mock_search_template_label, g_free); for (i = 0; i < ulCount; i++) { if (NULL == pTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; if (CKA_CLASS == pTemplate[i].type) { if (sizeof(CK_ULONG) != pTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; cka_class_value = (CK_ULONG_PTR) pTemplate[i].pValue; mock_search_template_class = *cka_class_value; } else if (CKA_LABEL == pTemplate[i].type) { const char *cka_label_value = (char*)pTemplate[i].pValue; mock_search_template_label = g_strndup (cka_label_value, pTemplate[i].ulValueLen); } else { g_info ("Ignoring search template for %lu", pTemplate[i].type); } } pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_FIND; mock_search_iterator = 0; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_FindObjects)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject, CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_FIND != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if ((NULL == phObject) && (0 < ulMaxObjectCount)) return CKR_ARGUMENTS_BAD; if (NULL == pulObjectCount) return CKR_ARGUMENTS_BAD; *pulObjectCount = 0; for (; mock_search_iterator < G_N_ELEMENTS (mock_objects) && *pulObjectCount < ulMaxObjectCount; mock_search_iterator++) { if ((mock_search_template_class == PKCS11_MOCK_CKO_ANYTHING || mock_objects[mock_search_iterator].object_class == mock_search_template_class) && (mock_search_template_label == NULL || g_strcmp0 ((char*)mock_objects[mock_search_iterator].info.label, mock_search_template_label) == 0)) { phObject[*pulObjectCount] = mock_search_iterator; *pulObjectCount = *pulObjectCount + 1; } } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_FindObjectsFinal)(CK_SESSION_HANDLE hSession) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_FIND != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_EncryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_NONE != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DIGEST != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_SIGN != pkcs11_mock_active_operation)) return CKR_OPERATION_ACTIVE; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; switch (pMechanism->mechanism) { case CKM_RSA_PKCS: if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; break; case CKM_RSA_PKCS_OAEP: if ((NULL == pMechanism->pParameter) || (sizeof(CK_RSA_PKCS_OAEP_PARAMS) != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; break; case CKM_DES3_CBC: if ((NULL == pMechanism->pParameter) || (8 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; break; case CKM_AES_CBC: if ((NULL == pMechanism->pParameter) || (16 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; break; default: return CKR_MECHANISM_INVALID; } switch (pkcs11_mock_active_operation) { case PKCS11_MOCK_CK_OPERATION_NONE: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_ENCRYPT; break; case PKCS11_MOCK_CK_OPERATION_DIGEST: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT; break; case PKCS11_MOCK_CK_OPERATION_SIGN: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT; break; default: return CKR_FUNCTION_FAILED; } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_Encrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData, CK_ULONG_PTR pulEncryptedDataLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_ENCRYPT != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pData) return CKR_ARGUMENTS_BAD; if (0 >= ulDataLen) return CKR_ARGUMENTS_BAD; if (NULL == pulEncryptedDataLen) return CKR_ARGUMENTS_BAD; if (NULL != pEncryptedData) { if (ulDataLen > *pulEncryptedDataLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulDataLen; i++) pEncryptedData[i] = pData[i] ^ 0xAB; pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; } } *pulEncryptedDataLen = ulDataLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_EncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_ENCRYPT != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pPart) return CKR_ARGUMENTS_BAD; if (0 >= ulPartLen) return CKR_ARGUMENTS_BAD; if (NULL == pulEncryptedPartLen) return CKR_ARGUMENTS_BAD; if (NULL != pEncryptedPart) { if (ulPartLen > *pulEncryptedPartLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulPartLen; i++) pEncryptedPart[i] = pPart[i] ^ 0xAB; } } *pulEncryptedPartLen = ulPartLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_EncryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastEncryptedPart, CK_ULONG_PTR pulLastEncryptedPartLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_ENCRYPT != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT != pkcs11_mock_active_operation)) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pulLastEncryptedPartLen) return CKR_ARGUMENTS_BAD; if (NULL != pLastEncryptedPart) { switch (pkcs11_mock_active_operation) { case PKCS11_MOCK_CK_OPERATION_ENCRYPT: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; break; case PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST; break; case PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_SIGN; break; default: return CKR_FUNCTION_FAILED; } } *pulLastEncryptedPartLen = 0; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DecryptInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_NONE != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DIGEST != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_VERIFY != pkcs11_mock_active_operation)) return CKR_OPERATION_ACTIVE; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; switch (pMechanism->mechanism) { case CKM_RSA_PKCS: if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; break; case CKM_RSA_PKCS_OAEP: if ((NULL == pMechanism->pParameter) || (sizeof(CK_RSA_PKCS_OAEP_PARAMS) != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; break; case CKM_DES3_CBC: if ((NULL == pMechanism->pParameter) || (8 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; break; case CKM_AES_CBC: if ((NULL == pMechanism->pParameter) || (16 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; break; default: return CKR_MECHANISM_INVALID; } switch (pkcs11_mock_active_operation) { case PKCS11_MOCK_CK_OPERATION_NONE: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT; break; case PKCS11_MOCK_CK_OPERATION_DIGEST: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST; break; case PKCS11_MOCK_CK_OPERATION_VERIFY: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY; break; default: return CKR_FUNCTION_FAILED; } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_Decrypt)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedData, CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_DECRYPT != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pEncryptedData) return CKR_ARGUMENTS_BAD; if (0 >= ulEncryptedDataLen) return CKR_ARGUMENTS_BAD; if (NULL == pulDataLen) return CKR_ARGUMENTS_BAD; if (NULL != pData) { if (ulEncryptedDataLen > *pulDataLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulEncryptedDataLen; i++) pData[i] = pEncryptedData[i] ^ 0xAB; pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; } } *pulDataLen = ulEncryptedDataLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DecryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_DECRYPT != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pEncryptedPart) return CKR_ARGUMENTS_BAD; if (0 >= ulEncryptedPartLen) return CKR_ARGUMENTS_BAD; if (NULL == pulPartLen) return CKR_ARGUMENTS_BAD; if (NULL != pPart) { if (ulEncryptedPartLen > *pulPartLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulEncryptedPartLen; i++) pPart[i] = pEncryptedPart[i] ^ 0xAB; } } *pulPartLen = ulEncryptedPartLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DecryptFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pLastPart, CK_ULONG_PTR pulLastPartLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_DECRYPT != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != pkcs11_mock_active_operation)) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pulLastPartLen) return CKR_ARGUMENTS_BAD; if (NULL != pLastPart) { switch (pkcs11_mock_active_operation) { case PKCS11_MOCK_CK_OPERATION_DECRYPT: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; break; case PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST; break; case PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_VERIFY; break; default: return CKR_FUNCTION_FAILED; } } *pulLastPartLen = 0; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DigestInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_NONE != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_ENCRYPT != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT != pkcs11_mock_active_operation)) return CKR_OPERATION_ACTIVE; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if (CKM_SHA_1 != pMechanism->mechanism) return CKR_MECHANISM_INVALID; if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; switch (pkcs11_mock_active_operation) { case PKCS11_MOCK_CK_OPERATION_NONE: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST; break; case PKCS11_MOCK_CK_OPERATION_ENCRYPT: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT; break; case PKCS11_MOCK_CK_OPERATION_DECRYPT: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST; break; default: return CKR_FUNCTION_FAILED; } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_Digest)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { CK_BYTE hash[20] = { 0x7B, 0x50, 0x2C, 0x3A, 0x1F, 0x48, 0xC8, 0x60, 0x9A, 0xE2, 0x12, 0xCD, 0xFB, 0x63, 0x9D, 0xEE, 0x39, 0x67, 0x3F, 0x5E }; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_DIGEST != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pData) return CKR_ARGUMENTS_BAD; if (0 >= ulDataLen) return CKR_ARGUMENTS_BAD; if (NULL == pulDigestLen) return CKR_ARGUMENTS_BAD; if (NULL != pDigest) { if (sizeof(hash) > *pulDigestLen) { return CKR_BUFFER_TOO_SMALL; } else { memcpy(pDigest, hash, sizeof(hash)); pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; } } *pulDigestLen = sizeof(hash); return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_DIGEST != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pPart) return CKR_ARGUMENTS_BAD; if (0 >= ulPartLen) return CKR_ARGUMENTS_BAD; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DigestKey)(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_DIGEST != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey) return CKR_OBJECT_HANDLE_INVALID; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DigestFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen) { CK_BYTE hash[20] = { 0x7B, 0x50, 0x2C, 0x3A, 0x1F, 0x48, 0xC8, 0x60, 0x9A, 0xE2, 0x12, 0xCD, 0xFB, 0x63, 0x9D, 0xEE, 0x39, 0x67, 0x3F, 0x5E }; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_DIGEST != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != pkcs11_mock_active_operation)) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pulDigestLen) return CKR_ARGUMENTS_BAD; if (NULL != pDigest) { if (sizeof(hash) > *pulDigestLen) { return CKR_BUFFER_TOO_SMALL; } else { memcpy(pDigest, hash, sizeof(hash)); switch (pkcs11_mock_active_operation) { case PKCS11_MOCK_CK_OPERATION_DIGEST: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; break; case PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_ENCRYPT; break; case PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST: pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT; break; default: return CKR_FUNCTION_FAILED; } } } *pulDigestLen = sizeof(hash); return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SignInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_NONE != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_ENCRYPT != pkcs11_mock_active_operation)) return CKR_OPERATION_ACTIVE; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (hKey > G_N_ELEMENTS(mock_objects) || mock_objects[hKey].object_class != CKO_PRIVATE_KEY) return CKR_KEY_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; mock_sign_algo = pMechanism->mechanism; // TODO: Hardcoded list if (CKM_RSA_PKCS_PSS == pMechanism->mechanism) { CK_RSA_PKCS_PSS_PARAMS *params; if ((NULL == pMechanism->pParameter) || (0 == pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; params = pMechanism->pParameter; g_assert (params->hashAlg == CKM_SHA256); g_assert (params->mgf == CKG_MGF1_SHA256); // if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hKey) // return CKR_KEY_TYPE_INCONSISTENT; } else if (CKM_RSA_PKCS == pMechanism->mechanism) { // FIXME: Also assert SHA256? } else { g_assert_not_reached (); return CKR_MECHANISM_INVALID; } if (PKCS11_MOCK_CK_OPERATION_NONE == pkcs11_mock_active_operation) pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_SIGN; else pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT; pkcs11_mock_sign_key = hKey; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_Sign)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { const gnutls_datum_t data = { .data = pData, .size = ulDataLen, }; gnutls_datum_t signature; int status; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_SIGN != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pData) return CKR_ARGUMENTS_BAD; if (0 >= ulDataLen) return CKR_ARGUMENTS_BAD; if (NULL == pulSignatureLen) return CKR_ARGUMENTS_BAD; // TODO: Handle user not logged in // TODO: Hardcoded algo list if (mock_sign_algo == CKM_RSA_PKCS_PSS) status = gnutls_privkey_sign_hash2 (mock_objects[pkcs11_mock_sign_key].key, GNUTLS_SIGN_RSA_PSS_SHA256, GNUTLS_PRIVKEY_SIGN_FLAG_RSA_PSS, &data, &signature); else if (mock_sign_algo == CKM_RSA_PKCS) status = gnutls_privkey_sign_hash2 (mock_objects[pkcs11_mock_sign_key].key, GNUTLS_SIGN_RSA_SHA256, GNUTLS_PRIVKEY_SIGN_FLAG_TLS1_RSA, &data, &signature); else g_assert_not_reached (); // g_assert (status == GNUTLS_E_SUCCESS); if (status != GNUTLS_E_SUCCESS) return CKR_FUNCTION_FAILED; // TODO: Best return code? if (signature.size > *pulSignatureLen) { gnutls_free (signature.data); *pulSignatureLen = signature.size; if (pSignature != NULL) return CKR_BUFFER_TOO_SMALL; } else { // This is called twice, once with NULL to just query size if (pSignature != NULL) { memcpy (pSignature, signature.data, signature.size); pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; } *pulSignatureLen = signature.size; gnutls_free (signature.data); } return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SignUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_SIGN != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pPart) return CKR_ARGUMENTS_BAD; if (0 >= ulPartLen) return CKR_ARGUMENTS_BAD; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SignFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_BYTE signature[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_SIGN != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT != pkcs11_mock_active_operation)) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pulSignatureLen) return CKR_ARGUMENTS_BAD; if (NULL != pSignature) { if (sizeof(signature) > *pulSignatureLen) { return CKR_BUFFER_TOO_SMALL; } else { memcpy(pSignature, signature, sizeof(signature)); if (PKCS11_MOCK_CK_OPERATION_SIGN == pkcs11_mock_active_operation) pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; else pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_ENCRYPT; } } *pulSignatureLen = sizeof(signature); return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SignRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_NONE != pkcs11_mock_active_operation) return CKR_OPERATION_ACTIVE; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if (CKM_RSA_PKCS == pMechanism->mechanism) { if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; } else { return CKR_MECHANISM_INVALID; } pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_SIGN_RECOVER; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SignRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG_PTR pulSignatureLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_SIGN_RECOVER != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pData) return CKR_ARGUMENTS_BAD; if (0 >= ulDataLen) return CKR_ARGUMENTS_BAD; if (NULL == pulSignatureLen) return CKR_ARGUMENTS_BAD; if (NULL != pSignature) { if (ulDataLen > *pulSignatureLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulDataLen; i++) pSignature[i] = pData[i] ^ 0xAB; pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; } } *pulSignatureLen = ulDataLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_VerifyInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_NONE != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT != pkcs11_mock_active_operation)) return CKR_OPERATION_ACTIVE; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if ((CKM_RSA_PKCS == pMechanism->mechanism) || (CKM_SHA1_RSA_PKCS == pMechanism->mechanism)) { if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; } else { return CKR_MECHANISM_INVALID; } if (PKCS11_MOCK_CK_OPERATION_NONE == pkcs11_mock_active_operation) pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_VERIFY; else pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_Verify)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_BYTE signature[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_VERIFY != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pData) return CKR_ARGUMENTS_BAD; if (0 >= ulDataLen) return CKR_ARGUMENTS_BAD; if (NULL == pSignature) return CKR_ARGUMENTS_BAD; if (0 >= ulSignatureLen) return CKR_ARGUMENTS_BAD; if (sizeof(signature) != ulSignatureLen) return CKR_SIGNATURE_LEN_RANGE; if (0 != memcmp(pSignature, signature, sizeof(signature))) return CKR_SIGNATURE_INVALID; pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_VerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_VERIFY != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pPart) return CKR_ARGUMENTS_BAD; if (0 >= ulPartLen) return CKR_ARGUMENTS_BAD; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_VerifyFinal)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen) { CK_BYTE signature[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((PKCS11_MOCK_CK_OPERATION_VERIFY != pkcs11_mock_active_operation) && (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != pkcs11_mock_active_operation)) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pSignature) return CKR_ARGUMENTS_BAD; if (0 >= ulSignatureLen) return CKR_ARGUMENTS_BAD; if (sizeof(signature) != ulSignatureLen) return CKR_SIGNATURE_LEN_RANGE; if (0 != memcmp(pSignature, signature, sizeof(signature))) return CKR_SIGNATURE_INVALID; if (PKCS11_MOCK_CK_OPERATION_VERIFY == pkcs11_mock_active_operation) pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; else pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_DECRYPT; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecoverInit)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hKey) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_NONE != pkcs11_mock_active_operation) return CKR_OPERATION_ACTIVE; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if (CKM_RSA_PKCS == pMechanism->mechanism) { if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hKey) return CKR_KEY_TYPE_INCONSISTENT; } else { return CKR_MECHANISM_INVALID; } pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_VERIFY_RECOVER; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_VerifyRecover)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_VERIFY_RECOVER != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pSignature) return CKR_ARGUMENTS_BAD; if (0 >= ulSignatureLen) return CKR_ARGUMENTS_BAD; if (NULL == pulDataLen) return CKR_ARGUMENTS_BAD; if (NULL != pData) { if (ulSignatureLen > *pulDataLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulSignatureLen; i++) pData[i] = pSignature[i] ^ 0xAB; pkcs11_mock_active_operation = PKCS11_MOCK_CK_OPERATION_NONE; } } *pulDataLen = ulSignatureLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DigestEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_DIGEST_ENCRYPT != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pPart) return CKR_ARGUMENTS_BAD; if (0 >= ulPartLen) return CKR_ARGUMENTS_BAD; if (NULL == pulEncryptedPartLen) return CKR_ARGUMENTS_BAD; if (NULL != pEncryptedPart) { if (ulPartLen > *pulEncryptedPartLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulPartLen; i++) pEncryptedPart[i] = pPart[i] ^ 0xAB; } } *pulEncryptedPartLen = ulPartLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DecryptDigestUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_DECRYPT_DIGEST != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pEncryptedPart) return CKR_ARGUMENTS_BAD; if (0 >= ulEncryptedPartLen) return CKR_ARGUMENTS_BAD; if (NULL == pulPartLen) return CKR_ARGUMENTS_BAD; if (NULL != pPart) { if (ulEncryptedPartLen > *pulPartLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulEncryptedPartLen; i++) pPart[i] = pEncryptedPart[i] ^ 0xAB; } } *pulPartLen = ulEncryptedPartLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SignEncryptUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart, CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart, CK_ULONG_PTR pulEncryptedPartLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_SIGN_ENCRYPT != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pPart) return CKR_ARGUMENTS_BAD; if (0 >= ulPartLen) return CKR_ARGUMENTS_BAD; if (NULL == pulEncryptedPartLen) return CKR_ARGUMENTS_BAD; if (NULL != pEncryptedPart) { if (ulPartLen > *pulEncryptedPartLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulPartLen; i++) pEncryptedPart[i] = pPart[i] ^ 0xAB; } } *pulEncryptedPartLen = ulPartLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DecryptVerifyUpdate)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pEncryptedPart, CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart, CK_ULONG_PTR pulPartLen) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if (PKCS11_MOCK_CK_OPERATION_DECRYPT_VERIFY != pkcs11_mock_active_operation) return CKR_OPERATION_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pEncryptedPart) return CKR_ARGUMENTS_BAD; if (0 >= ulEncryptedPartLen) return CKR_ARGUMENTS_BAD; if (NULL == pulPartLen) return CKR_ARGUMENTS_BAD; if (NULL != pPart) { if (ulEncryptedPartLen > *pulPartLen) { return CKR_BUFFER_TOO_SMALL; } else { for (i = 0; i < ulEncryptedPartLen; i++) pPart[i] = pEncryptedPart[i] ^ 0xAB; } } *pulPartLen = ulEncryptedPartLen; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GenerateKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phKey) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if (CKM_DES3_KEY_GEN != pMechanism->mechanism) return CKR_MECHANISM_INVALID; if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (NULL == pTemplate) return CKR_ARGUMENTS_BAD; if (0 >= ulCount) return CKR_ARGUMENTS_BAD; if (NULL == phKey) return CKR_ARGUMENTS_BAD; for (i = 0; i < ulCount; i++) { if (NULL == pTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; } *phKey = PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GenerateKeyPair)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_ATTRIBUTE_PTR pPublicKeyTemplate, CK_ULONG ulPublicKeyAttributeCount, CK_ATTRIBUTE_PTR pPrivateKeyTemplate, CK_ULONG ulPrivateKeyAttributeCount, CK_OBJECT_HANDLE_PTR phPublicKey, CK_OBJECT_HANDLE_PTR phPrivateKey) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if (CKM_RSA_PKCS_KEY_PAIR_GEN != pMechanism->mechanism) return CKR_MECHANISM_INVALID; if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (NULL == pPublicKeyTemplate) return CKR_ARGUMENTS_BAD; if (0 >= ulPublicKeyAttributeCount) return CKR_ARGUMENTS_BAD; if (NULL == pPrivateKeyTemplate) return CKR_ARGUMENTS_BAD; if (0 >= ulPrivateKeyAttributeCount) return CKR_ARGUMENTS_BAD; if (NULL == phPublicKey) return CKR_ARGUMENTS_BAD; if (NULL == phPrivateKey) return CKR_ARGUMENTS_BAD; for (i = 0; i < ulPublicKeyAttributeCount; i++) { if (NULL == pPublicKeyTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pPublicKeyTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; } for (i = 0; i < ulPrivateKeyAttributeCount; i++) { if (NULL == pPrivateKeyTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pPrivateKeyTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; } *phPublicKey = PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY; *phPrivateKey = PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_WrapKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hWrappingKey, CK_OBJECT_HANDLE hKey, CK_BYTE_PTR pWrappedKey, CK_ULONG_PTR pulWrappedKeyLen) { CK_BYTE wrappedKey[10] = { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09 }; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if (CKM_RSA_PKCS != pMechanism->mechanism) return CKR_MECHANISM_INVALID; if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PUBLIC_KEY != hWrappingKey) return CKR_KEY_HANDLE_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hKey) return CKR_KEY_HANDLE_INVALID; if (NULL != pWrappedKey) { if (sizeof(wrappedKey) > *pulWrappedKeyLen) return CKR_BUFFER_TOO_SMALL; else memcpy(pWrappedKey, wrappedKey, sizeof(wrappedKey)); } *pulWrappedKeyLen = sizeof(wrappedKey); return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_UnwrapKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hUnwrappingKey, CK_BYTE_PTR pWrappedKey, CK_ULONG ulWrappedKeyLen, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if (CKM_RSA_PKCS != pMechanism->mechanism) return CKR_MECHANISM_INVALID; if ((NULL != pMechanism->pParameter) || (0 != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_PRIVATE_KEY != hUnwrappingKey) return CKR_KEY_HANDLE_INVALID; if (NULL == pWrappedKey) return CKR_ARGUMENTS_BAD; if (0 >= ulWrappedKeyLen) return CKR_ARGUMENTS_BAD; if (NULL == pTemplate) return CKR_ARGUMENTS_BAD; if (0 >= ulAttributeCount) return CKR_ARGUMENTS_BAD; if (NULL == phKey) return CKR_ARGUMENTS_BAD; for (i = 0; i < ulAttributeCount; i++) { if (NULL == pTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; } *phKey = PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_DeriveKey)(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism, CK_OBJECT_HANDLE hBaseKey, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulAttributeCount, CK_OBJECT_HANDLE_PTR phKey) { CK_ULONG i = 0; if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pMechanism) return CKR_ARGUMENTS_BAD; if (CKM_XOR_BASE_AND_DATA != pMechanism->mechanism) return CKR_MECHANISM_INVALID; if ((NULL == pMechanism->pParameter) || (sizeof(CK_KEY_DERIVATION_STRING_DATA) != pMechanism->ulParameterLen)) return CKR_MECHANISM_PARAM_INVALID; if (PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY != hBaseKey) return CKR_OBJECT_HANDLE_INVALID; if (NULL == phKey) return CKR_ARGUMENTS_BAD; if ((NULL != pTemplate) && (0 >= ulAttributeCount)) { for (i = 0; i < ulAttributeCount; i++) { if (NULL == pTemplate[i].pValue) return CKR_ATTRIBUTE_VALUE_INVALID; if (0 >= pTemplate[i].ulValueLen) return CKR_ATTRIBUTE_VALUE_INVALID; } } *phKey = PKCS11_MOCK_CK_OBJECT_HANDLE_SECRET_KEY; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_SeedRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSeed, CK_ULONG ulSeedLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == pSeed) return CKR_ARGUMENTS_BAD; if (0 >= ulSeedLen) return CKR_ARGUMENTS_BAD; return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GenerateRandom)(CK_SESSION_HANDLE hSession, CK_BYTE_PTR RandomData, CK_ULONG ulRandomLen) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; if (NULL == RandomData) return CKR_ARGUMENTS_BAD; if (0 >= ulRandomLen) return CKR_ARGUMENTS_BAD; memset(RandomData, 1, ulRandomLen); return CKR_OK; } CK_DEFINE_FUNCTION(CK_RV, C_GetFunctionStatus)(CK_SESSION_HANDLE hSession) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; return CKR_FUNCTION_NOT_PARALLEL; } CK_DEFINE_FUNCTION(CK_RV, C_CancelFunction)(CK_SESSION_HANDLE hSession) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((CK_FALSE == pkcs11_mock_session_opened) || (PKCS11_MOCK_CK_SESSION_ID != hSession)) return CKR_SESSION_HANDLE_INVALID; return CKR_FUNCTION_NOT_PARALLEL; } CK_DEFINE_FUNCTION(CK_RV, C_WaitForSlotEvent)(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved) { if (CK_FALSE == pkcs11_mock_initialized) return CKR_CRYPTOKI_NOT_INITIALIZED; if ((0 != flags) && (CKF_DONT_BLOCK != flags)) return CKR_ARGUMENTS_BAD; if (NULL == pSlot) return CKR_ARGUMENTS_BAD; if (NULL != pReserved) return CKR_ARGUMENTS_BAD; return CKR_NO_EVENT; } /* LCOV_EXCL_STOP */