From c775f93c923c615a50987d8eebd0dc325b57c1e4 Mon Sep 17 00:00:00 2001 From: Patrick Griffis Date: Tue, 27 Apr 2021 13:29:19 -0500 Subject: ssl-test: Add tests for PKCS#11 pin protected cert --- tests/mock-pkcs11.c | 2866 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 2866 insertions(+) create mode 100644 tests/mock-pkcs11.c (limited to 'tests/mock-pkcs11.c') diff --git a/tests/mock-pkcs11.c b/tests/mock-pkcs11.c new file mode 100644 index 00000000..fc549d94 --- /dev/null +++ b/tests/mock-pkcs11.c @@ -0,0 +1,2866 @@ +/* + * 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; + +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; +} -- cgit v1.2.1