diff options
Diffstat (limited to 'common/mock.c')
-rw-r--r-- | common/mock.c | 3117 |
1 files changed, 3117 insertions, 0 deletions
diff --git a/common/mock.c b/common/mock.c new file mode 100644 index 0000000..14fd3ec --- /dev/null +++ b/common/mock.c @@ -0,0 +1,3117 @@ +/* + * Copyright (c) 2011, Collabora Ltd. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * * Redistributions of source code must retain the above + * copyright notice, this list of conditions and the + * following disclaimer. + * * Redistributions in binary form must reproduce the + * above copyright notice, this list of conditions and + * the following disclaimer in the documentation and/or + * other materials provided with the distribution. + * * The names of contributors to this software may not be + * used to endorse or promote products derived from this + * software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, + * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS + * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED + * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH + * DAMAGE. + * + * Author: Stef Walter <stefw@collabora.co.uk> + */ + +#include "config.h" + +#include "library.h" +#define CRYPTOKI_EXPORTS +#include "pkcs11.h" + +#include "mock.h" + +#include "attrs.h" +#define P11_DEBUG_FLAG P11_DEBUG_LIB +#include "debug.h" +#include "dict.h" +#include "array.h" + +#include <assert.h> +#include <ctype.h> +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +/* ------------------------------------------------------------------- + * GLOBALS and SUPPORT STUFF + */ + +/* Various mutexes */ +static p11_mutex_t init_mutex; + +/* Whether we've been initialized, and on what process id it happened */ +static bool pkcs11_initialized = false; +static pid_t pkcs11_initialized_pid = 0; + +static CK_UTF8CHAR *the_pin = NULL; +static CK_ULONG n_the_pin = 0; + +static bool logged_in = false; +static CK_USER_TYPE the_user_type = 0; + +typedef struct _Session { + CK_SESSION_HANDLE handle; + p11_dict *objects; + CK_SESSION_INFO info; + + /* For find operations */ + bool finding; + p11_array *matches; + + bool want_context_login; + + /* For encrypt, decrypt operations */ + CK_OBJECT_HANDLE crypto_key; + CK_ATTRIBUTE_TYPE crypto_method; + CK_MECHANISM_TYPE crypto_mechanism; + + /* For sign, verify, digest, CKM_MOCK_COUNT */ + CK_MECHANISM_TYPE hash_mechanism; + CK_ATTRIBUTE_TYPE hash_method; + CK_OBJECT_HANDLE hash_key; + CK_ULONG hash_count; + + /* For 'signing' with CKM_MOCK_PREFIX */ + CK_BYTE sign_prefix[128]; + CK_ULONG n_sign_prefix; + + /* The random seed */ + CK_BYTE random_seed[128]; + CK_ULONG random_seed_len; +} Session; + +static unsigned int unique_identifier = 100; +static p11_dict *the_sessions = NULL; +static p11_dict *the_objects = NULL; + +#define SIGNED_PREFIX "signed-prefix:" + +#define handle_to_pointer(handle) \ + ((void *)(size_t)(handle)) + +#define pointer_to_handle(pointer) \ + ((CK_ULONG)(size_t)(pointer)) + +static void +free_session (void *data) +{ + Session *sess = (Session *)data; + if (sess) + p11_dict_free (sess->objects); + free (sess); +} + +static bool +find_boolean_attribute (CK_ATTRIBUTE *attrs, + CK_ATTRIBUTE_TYPE type, + CK_BBOOL *value) +{ + CK_ATTRIBUTE *attr; + + attr = p11_attrs_find (attrs, type); + if (attr != NULL && + attr->pValue != NULL && + attr->ulValueLen == sizeof (CK_BBOOL)) { + *value = *((CK_BBOOL *)attr->pValue); + return true; + } + + return false; +} + +static CK_RV +lookup_object (Session *sess, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE **attrs, + p11_dict **table) +{ + CK_BBOOL priv; + + *attrs = p11_dict_get (the_objects, handle_to_pointer (object)); + if (*attrs) { + if (table) + *table = the_objects; + } else { + *attrs = p11_dict_get (sess->objects, handle_to_pointer (object)); + if (*attrs) { + if (table) + *table = sess->objects; + } + } + + if (!*attrs) + return CKR_OBJECT_HANDLE_INVALID; + else if (!logged_in && find_boolean_attribute (*attrs, CKA_PRIVATE, &priv) && priv) + return CKR_USER_NOT_LOGGED_IN; + + return CKR_OK; +} + +void +mock_module_add_object (CK_SLOT_ID slot_id, + const CK_ATTRIBUTE *attrs) +{ + CK_ATTRIBUTE *copy; + + return_if_fail (slot_id == MOCK_SLOT_ONE_ID); + return_if_fail (attrs != NULL); + + copy = p11_attrs_dup (attrs); + return_if_fail (copy != NULL); + + mock_module_take_object (slot_id, copy); +} + +void +mock_module_take_object (CK_SLOT_ID slot_id, + CK_ATTRIBUTE *attrs) +{ + CK_OBJECT_HANDLE object; + + return_if_fail (slot_id == MOCK_SLOT_ONE_ID); + return_if_fail (attrs != NULL); + + object = ++unique_identifier; + if (!p11_dict_set (the_objects, handle_to_pointer (object), attrs)) + return_if_reached (); +} + +void +mock_module_reset_objects (CK_SLOT_ID slot_id) +{ + return_if_fail (slot_id == MOCK_SLOT_ONE_ID); + + if (!the_objects) { + the_objects = p11_dict_new (p11_dict_direct_hash, + p11_dict_direct_equal, + NULL, p11_attrs_free); + } + + p11_dict_clear (the_objects); + + /* Our token object */ + { + CK_OBJECT_CLASS klass = CKO_DATA; + char *label = "TEST LABEL"; + CK_ATTRIBUTE attrs[] = { + { CKA_CLASS, &klass, sizeof (klass) }, + { CKA_LABEL, label, strlen (label) }, + { CKA_INVALID, NULL, 0 }, + }; + p11_dict_set (the_objects, handle_to_pointer (2), p11_attrs_dup (attrs)); + } + + /* Private capitalize key */ + { + CK_OBJECT_CLASS klass = CKO_PRIVATE_KEY; + char *label = "Private Capitalize Key"; + char *value = "value"; + CK_MECHANISM_TYPE type = CKM_MOCK_CAPITALIZE; + CK_BBOOL btrue = CK_TRUE; + CK_ATTRIBUTE attrs[] = { + { CKA_CLASS, &klass, sizeof (klass) }, + { CKA_LABEL, label, strlen (label) }, + { CKA_ALLOWED_MECHANISMS, &type, sizeof (type) }, + { CKA_DECRYPT, &btrue, sizeof (btrue) }, + { CKA_PRIVATE, &btrue, sizeof (btrue) }, + { CKA_WRAP, &btrue, sizeof (btrue) }, + { CKA_UNWRAP, &btrue, sizeof (btrue) }, + { CKA_DERIVE, &btrue, sizeof (btrue) }, + { CKA_VALUE, value, strlen (value) }, + { CKA_INVALID, NULL, 0 }, + }; + p11_dict_set (the_objects, handle_to_pointer (MOCK_PRIVATE_KEY_CAPITALIZE), p11_attrs_dup (attrs)); + + } + + { + CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY; + char *label = "Public Capitalize Key"; + char *value = "value"; + CK_MECHANISM_TYPE type = CKM_MOCK_CAPITALIZE; + CK_BBOOL btrue = CK_TRUE; + CK_BBOOL bfalse = CK_FALSE; + CK_ATTRIBUTE attrs[] = { + { CKA_CLASS, &klass, sizeof (klass) }, + { CKA_LABEL, label, strlen (label) }, + { CKA_ALLOWED_MECHANISMS, &type, sizeof (type) }, + { CKA_ENCRYPT, &btrue, sizeof (btrue) }, + { CKA_PRIVATE, &bfalse, sizeof (bfalse) }, + { CKA_VALUE, value, strlen (value) }, + { CKA_INVALID, NULL, 0 }, + }; + p11_dict_set (the_objects, handle_to_pointer (MOCK_PUBLIC_KEY_CAPITALIZE), p11_attrs_dup (attrs)); + + } + + { + CK_OBJECT_CLASS klass = CKO_PRIVATE_KEY; + char *label = "Private prefix key"; + char *value = "value"; + CK_MECHANISM_TYPE type = CKM_MOCK_PREFIX; + CK_BBOOL btrue = CK_TRUE; + CK_ATTRIBUTE attrs[] = { + { CKA_CLASS, &klass, sizeof (klass) }, + { CKA_LABEL, label, strlen (label) }, + { CKA_ALLOWED_MECHANISMS, &type, sizeof (type) }, + { CKA_SIGN, &btrue, sizeof (btrue) }, + { CKA_PRIVATE, &btrue, sizeof (btrue) }, + { CKA_ALWAYS_AUTHENTICATE, &btrue, sizeof (btrue) }, + { CKA_VALUE, value, strlen (value) }, + { CKA_INVALID, NULL, 0 }, + }; + p11_dict_set (the_objects, handle_to_pointer (MOCK_PRIVATE_KEY_PREFIX), p11_attrs_dup (attrs)); + + } + + { + CK_OBJECT_CLASS klass = CKO_PUBLIC_KEY; + char *label = "Public prefix key"; + char *value = "value"; + CK_MECHANISM_TYPE type = CKM_MOCK_PREFIX; + CK_BBOOL btrue = CK_TRUE; + CK_BBOOL bfalse = CK_FALSE; + CK_ATTRIBUTE attrs[] = { + { CKA_CLASS, &klass, sizeof (klass) }, + { CKA_LABEL, label, strlen (label) }, + { CKA_ALLOWED_MECHANISMS, &type, sizeof (type) }, + { CKA_VERIFY, &btrue, sizeof (btrue) }, + { CKA_PRIVATE, &bfalse, sizeof (bfalse) }, + { CKA_ALWAYS_AUTHENTICATE, &btrue, sizeof (btrue) }, + { CKA_VALUE, value, strlen (value) }, + { CKA_INVALID, NULL, 0 }, + }; + p11_dict_set (the_objects, handle_to_pointer (MOCK_PUBLIC_KEY_PREFIX), p11_attrs_dup (attrs)); + + } + +} + +void +mock_module_enumerate_objects (CK_SESSION_HANDLE handle, + mock_enumerator func, + void *user_data) +{ + p11_dictiter iter; + void *key; + void *value; + Session *sess; + + assert (the_objects != NULL); + assert (func != NULL); + + /* Token objects */ + p11_dict_iterate (the_objects, &iter); + while (p11_dict_next (&iter, &key, &value)) { + if (!(func) (pointer_to_handle (key), value, user_data)) + return; + } + + /* session objects */ + if (handle) { + sess = p11_dict_get (the_sessions, handle_to_pointer (handle)); + if (sess) { + p11_dict_iterate (sess->objects, &iter); + while (p11_dict_next (&iter, &key, &value)) { + if (!(func) (pointer_to_handle (key), value, user_data)) + return; + } + } + } +} + +/* ------------------------------------------------------------------- + * INITIALIZATION and 'GLOBAL' CALLS + */ + +CK_RV +mock_C_Initialize (CK_VOID_PTR init_args) +{ + CK_C_INITIALIZE_ARGS_PTR args = NULL; + CK_RV ret = CKR_OK; + pid_t pid; + + p11_debug ("C_Initialize: enter"); + + p11_mutex_lock (&init_mutex); + + if (init_args != NULL) { + int supplied_ok; + + /* pReserved must be NULL */ + args = init_args; + + /* ALL supplied function pointers need to have the value either NULL or non-NULL. */ + supplied_ok = (args->CreateMutex == NULL && args->DestroyMutex == NULL && + args->LockMutex == NULL && args->UnlockMutex == NULL) || + (args->CreateMutex != NULL && args->DestroyMutex != NULL && + args->LockMutex != NULL && args->UnlockMutex != NULL); + if (!supplied_ok) { + p11_debug_precond ("p11-kit: invalid set of mutex calls supplied"); + ret = CKR_ARGUMENTS_BAD; + goto done; + } + + /* + * When the CKF_OS_LOCKING_OK flag isn't set return an error. + * We must be able to use our pthread functionality. + */ + if (!(args->flags & CKF_OS_LOCKING_OK)) { + p11_debug_precond ("p11-kit: can't do without os locking"); + ret = CKR_CANT_LOCK; + goto done; + } + } + + pid = getpid (); + if (pkcs11_initialized) { + + /* This process has called C_Initialize already */ + if (pid == pkcs11_initialized_pid) { + p11_debug_precond ("p11-kit: C_Initialize called twice for same process"); + ret = CKR_CRYPTOKI_ALREADY_INITIALIZED; + goto done; + } + } + + /* We store CK_ULONG as pointers here, so verify that they fit */ + assert (sizeof (CK_ULONG) <= sizeof (void *)); + + the_pin = (CK_UTF8CHAR_PTR)strdup ("booo"); + n_the_pin = 4; + + the_sessions = p11_dict_new (p11_dict_direct_hash, + p11_dict_direct_equal, + NULL, free_session); + + mock_module_reset_objects (MOCK_SLOT_ONE_ID); + +done: + /* Mark us as officially initialized */ + if (ret == CKR_OK) { + pkcs11_initialized = true; + pkcs11_initialized_pid = pid; + } else if (ret != CKR_CRYPTOKI_ALREADY_INITIALIZED) { + pkcs11_initialized = false; + pkcs11_initialized_pid = 0; + } + + p11_mutex_unlock (&init_mutex); + + return ret; +} + +CK_RV +mock_C_Initialize__fails (CK_VOID_PTR init_args) +{ + return CKR_FUNCTION_FAILED; +} + +CK_RV +mock_C_Finalize (CK_VOID_PTR reserved) +{ + return_val_if_fail (pkcs11_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); + return_val_if_fail (reserved == NULL, CKR_ARGUMENTS_BAD); + + p11_mutex_lock (&init_mutex); + + /* This should stop all other calls in */ + pkcs11_initialized = false; + pkcs11_initialized_pid = 0; + + p11_dict_free (the_objects); + the_objects = NULL; + + p11_dict_free (the_sessions); + the_sessions = NULL; + logged_in = false; + the_user_type = 0; + + free (the_pin); + + p11_mutex_unlock (&init_mutex); + + return CKR_OK; +} + +static const CK_INFO MOCK_INFO = { + { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, + "MOCK MANUFACTURER ", + 0, + "MOCK LIBRARY ", + { 45, 145 } +}; + + +CK_RV +mock_C_GetInfo (CK_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + memcpy (info, &MOCK_INFO, sizeof (*info)); + return CKR_OK; +} + +CK_RV +mock_C_GetFunctionList_not_supported (CK_FUNCTION_LIST_PTR_PTR list) +{ + /* This would be a strange call to receive, should be overridden */ + return_val_if_reached (CKR_FUNCTION_NOT_SUPPORTED); +} + +CK_RV +mock_C_GetSlotList (CK_BBOOL token_present, + CK_SLOT_ID_PTR slot_list, + CK_ULONG_PTR count) +{ + CK_ULONG num; + + return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + num = token_present ? 1 : 2; + + /* Application only wants to know the number of slots. */ + if (slot_list == NULL) { + *count = num; + return CKR_OK; + } + + if (*count < num) + return_val_if_reached (CKR_BUFFER_TOO_SMALL); + + *count = num; + slot_list[0] = MOCK_SLOT_ONE_ID; + if (!token_present) + slot_list[1] = MOCK_SLOT_TWO_ID; + + return CKR_OK; + +} + +CK_RV +mock_C_GetSlotList__no_tokens (CK_BBOOL token_present, + CK_SLOT_ID_PTR slot_list, + CK_ULONG_PTR count) +{ + return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + /* No tokens */ + *count = 0; + return CKR_OK; +} + +/* Update mock-module.h URIs when updating this */ + +static const CK_SLOT_INFO MOCK_INFO_ONE = { + "TEST SLOT ", + "TEST MANUFACTURER ", + CKF_TOKEN_PRESENT | CKF_REMOVABLE_DEVICE, + { 55, 155 }, + { 65, 165 }, +}; + +/* Update mock-module.h URIs when updating this */ + +static const CK_SLOT_INFO MOCK_INFO_TWO = { + "TEST SLOT ", + "TEST MANUFACTURER ", + CKF_REMOVABLE_DEVICE, + { 55, 155 }, + { 65, 165 }, +}; + +CK_RV +mock_C_GetSlotInfo (CK_SLOT_ID slot_id, + CK_SLOT_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + if (slot_id == MOCK_SLOT_ONE_ID) { + memcpy (info, &MOCK_INFO_ONE, sizeof (*info)); + return CKR_OK; + } else if (slot_id == MOCK_SLOT_TWO_ID) { + memcpy (info, &MOCK_INFO_TWO, sizeof (*info)); + return CKR_OK; + } else { + return CKR_SLOT_ID_INVALID; + } +} + +CK_RV +mock_C_GetSlotInfo__invalid_slotid (CK_SLOT_ID slot_id, + CK_SLOT_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + return CKR_SLOT_ID_INVALID; +} + +/* Update gck-mock.h URIs when updating this */ + +static const CK_TOKEN_INFO MOCK_TOKEN_ONE = { + "TEST LABEL ", + "TEST MANUFACTURER ", + "TEST MODEL ", + "TEST SERIAL ", + CKF_LOGIN_REQUIRED | CKF_USER_PIN_INITIALIZED | CKF_CLOCK_ON_TOKEN | CKF_TOKEN_INITIALIZED, + 1, + 2, + 3, + 4, + 5, + 6, + 7, + 8, + 9, + 10, + { 75, 175 }, + { 85, 185 }, + { '1', '9', '9', '9', '0', '5', '2', '5', '0', '9', '1', '9', '5', '9', '0', '0' } +}; + +CK_RV +mock_C_GetTokenInfo (CK_SLOT_ID slot_id, + CK_TOKEN_INFO_PTR info) +{ + return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD); + + if (slot_id == MOCK_SLOT_ONE_ID) { + memcpy (info, &MOCK_TOKEN_ONE, sizeof (*info)); + return CKR_OK; + } else if (slot_id == MOCK_SLOT_TWO_ID) { + return CKR_TOKEN_NOT_PRESENT; + } else { + return CKR_SLOT_ID_INVALID; + } +} + +CK_RV +mock_C_GetTokenInfo__invalid_slotid (CK_SLOT_ID slot_id, + CK_TOKEN_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + return CKR_SLOT_ID_INVALID; +} + +/* + * TWO mechanisms: + * CKM_MOCK_CAPITALIZE + * CKM_MOCK_PREFIX + */ + +CK_RV +mock_C_GetMechanismList (CK_SLOT_ID slot_id, + CK_MECHANISM_TYPE_PTR mechanism_list, + CK_ULONG_PTR count) +{ + return_val_if_fail (count != NULL, CKR_ARGUMENTS_BAD); + + if (slot_id == MOCK_SLOT_TWO_ID) + return CKR_TOKEN_NOT_PRESENT; + else if (slot_id != MOCK_SLOT_ONE_ID) + return CKR_SLOT_ID_INVALID; + + /* Application only wants to know the number of slots. */ + if (mechanism_list == NULL) { + *count = 2; + return CKR_OK; + } + + if (*count < 2) + return_val_if_reached (CKR_BUFFER_TOO_SMALL); + + mechanism_list[0] = CKM_MOCK_CAPITALIZE; + mechanism_list[1] = CKM_MOCK_PREFIX; + *count = 2; + return CKR_OK; +} + +CK_RV +mock_C_GetMechanismList__invalid_slotid (CK_SLOT_ID slot_id, + CK_MECHANISM_TYPE_PTR mechanism_list, + CK_ULONG_PTR count) +{ + return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + return CKR_SLOT_ID_INVALID; +} + +static const CK_MECHANISM_INFO MOCK_MECH_CAPITALIZE = { + 512, 4096, CKF_ENCRYPT | CKF_DECRYPT +}; + +static const CK_MECHANISM_INFO MOCK_MECH_PREFIX = { + 2048, 2048, CKF_SIGN | CKF_VERIFY +}; + +CK_RV +mock_C_GetMechanismInfo (CK_SLOT_ID slot_id, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + if (slot_id == MOCK_SLOT_TWO_ID) + return CKR_TOKEN_NOT_PRESENT; + else if (slot_id != MOCK_SLOT_ONE_ID) + return CKR_SLOT_ID_INVALID; + + if (type == CKM_MOCK_CAPITALIZE) { + memcpy (info, &MOCK_MECH_CAPITALIZE, sizeof (*info)); + return CKR_OK; + } else if (type == CKM_MOCK_PREFIX) { + memcpy (info, &MOCK_MECH_PREFIX, sizeof (*info)); + return CKR_OK; + } else { + return CKR_MECHANISM_INVALID; + } +} + +CK_RV +mock_C_GetMechanismInfo__invalid_slotid (CK_SLOT_ID slot_id, + CK_MECHANISM_TYPE type, + CK_MECHANISM_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + return CKR_SLOT_ID_INVALID; +} + +CK_RV +mock_C_InitToken__specific_args (CK_SLOT_ID slot_id, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len, + CK_UTF8CHAR_PTR label) +{ + return_val_if_fail (pin != NULL, CKR_ARGUMENTS_BAD); + return_val_if_fail (label != NULL, CKR_ARGUMENTS_BAD); + + if (slot_id == MOCK_SLOT_TWO_ID) + return CKR_TOKEN_NOT_PRESENT; + else if (slot_id != MOCK_SLOT_ONE_ID) + return CKR_SLOT_ID_INVALID; + + if (strlen ("TEST PIN") != pin_len || + strncmp ((char *)pin, "TEST PIN", pin_len) != 0) + return CKR_PIN_INVALID; + if (strcmp ((char *)label, "TEST LABEL") != 0) + return CKR_ARGUMENTS_BAD; + + free (the_pin); + the_pin = memdup (pin, pin_len); + return_val_if_fail (the_pin != NULL, CKR_HOST_MEMORY); + n_the_pin = pin_len; + return CKR_OK; +} + +CK_RV +mock_C_InitToken__invalid_slotid (CK_SLOT_ID slot_id, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len, + CK_UTF8CHAR_PTR label) +{ + return CKR_SLOT_ID_INVALID; +} + +CK_RV +mock_C_WaitForSlotEvent (CK_FLAGS flags, + CK_SLOT_ID_PTR slot, + CK_VOID_PTR reserved) +{ + return_val_if_fail (slot, CKR_ARGUMENTS_BAD); + + if (flags & CKF_DONT_BLOCK) + return CKR_NO_EVENT; + + *slot = MOCK_SLOT_TWO_ID; + return CKR_OK; +} + +CK_RV +mock_C_WaitForSlotEvent__no_event (CK_FLAGS flags, + CK_SLOT_ID_PTR slot, + CK_VOID_PTR reserved) +{ + return_val_if_fail (slot, CKR_ARGUMENTS_BAD); + + return CKR_NO_EVENT; +} + +CK_RV +mock_C_OpenSession (CK_SLOT_ID slot_id, + CK_FLAGS flags, + CK_VOID_PTR user_data, + CK_NOTIFY callback, + CK_SESSION_HANDLE_PTR session) +{ + Session *sess; + + return_val_if_fail (session, CKR_ARGUMENTS_BAD); + + if (slot_id == MOCK_SLOT_TWO_ID) + return CKR_TOKEN_NOT_PRESENT; + else if (slot_id != MOCK_SLOT_ONE_ID) + return CKR_SLOT_ID_INVALID; + if ((flags & CKF_SERIAL_SESSION) != CKF_SERIAL_SESSION) + return CKR_SESSION_PARALLEL_NOT_SUPPORTED; + + sess = calloc (1, sizeof (Session)); + sess->handle = ++unique_identifier; + sess->info.flags = flags; + sess->info.slotID = slot_id; + sess->info.state = 0; + sess->info.ulDeviceError = 1414; + sess->objects = p11_dict_new (p11_dict_direct_hash, p11_dict_direct_equal, + NULL, p11_attrs_free); + *session = sess->handle; + + memcpy (sess->random_seed, "random", 6); + sess->random_seed_len = 6; + + p11_dict_set (the_sessions, handle_to_pointer (sess->handle), sess); + return CKR_OK; +} + +CK_RV +mock_C_OpenSession__invalid_slotid (CK_SLOT_ID slot_id, + CK_FLAGS flags, + CK_VOID_PTR user_data, + CK_NOTIFY callback, + CK_SESSION_HANDLE_PTR session) +{ + return_val_if_fail (session, CKR_ARGUMENTS_BAD); + + return CKR_SLOT_ID_INVALID; +} + +CK_RV +mock_C_CloseSession (CK_SESSION_HANDLE session) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + p11_dict_remove (the_sessions, handle_to_pointer (session)); + return CKR_OK; +} + +CK_RV +mock_C_CloseSession__invalid_handle (CK_SESSION_HANDLE session) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_CloseAllSessions (CK_SLOT_ID slot_id) +{ + if (slot_id == MOCK_SLOT_TWO_ID) + return CKR_TOKEN_NOT_PRESENT; + else if (slot_id != MOCK_SLOT_ONE_ID) + return CKR_SLOT_ID_INVALID; + + p11_dict_clear (the_sessions); + return CKR_OK; +} + +CK_RV +mock_C_CloseAllSessions__invalid_slotid (CK_SLOT_ID slot_id) +{ + return CKR_SLOT_ID_INVALID; +} + +CK_RV +mock_C_GetFunctionStatus (CK_SESSION_HANDLE session) +{ + if (!p11_dict_get (the_sessions, handle_to_pointer (session))) + return CKR_SESSION_HANDLE_INVALID; + return CKR_FUNCTION_NOT_PARALLEL; +} + +CK_RV +mock_C_GetFunctionStatus__not_parallel (CK_SESSION_HANDLE session) +{ + return CKR_FUNCTION_NOT_PARALLEL; +} + +CK_RV +mock_C_CancelFunction (CK_SESSION_HANDLE session) +{ + if (!p11_dict_get (the_sessions, handle_to_pointer (session))) + return CKR_SESSION_HANDLE_INVALID; + return CKR_FUNCTION_NOT_PARALLEL; +} + +CK_RV +mock_C_CancelFunction__not_parallel (CK_SESSION_HANDLE session) +{ + return CKR_FUNCTION_NOT_PARALLEL; +} + +CK_RV +mock_C_GetSessionInfo (CK_SESSION_HANDLE session, + CK_SESSION_INFO_PTR info) +{ + Session *sess; + + return_val_if_fail (info != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!session) + return CKR_SESSION_HANDLE_INVALID; + + if (logged_in) { + if (sess->info.flags & CKF_RW_SESSION) + sess->info.state = CKS_RW_USER_FUNCTIONS; + else + sess->info.state = CKS_RO_USER_FUNCTIONS; + } else { + if (sess->info.flags & CKF_RW_SESSION) + sess->info.state = CKS_RW_PUBLIC_SESSION; + else + sess->info.state = CKS_RO_PUBLIC_SESSION; + } + + memcpy (info, &sess->info, sizeof (*info)); + return CKR_OK; +} + +CK_RV +mock_C_GetSessionInfo__invalid_handle (CK_SESSION_HANDLE session, + CK_SESSION_INFO_PTR info) +{ + return_val_if_fail (info, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_InitPIN__specific_args (CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (sess == NULL) + return CKR_SESSION_HANDLE_INVALID; + + if (strlen ("TEST PIN") != pin_len || + strncmp ((char *)pin, "TEST PIN", pin_len) != 0) + return CKR_PIN_INVALID; + + free (the_pin); + the_pin = memdup (pin, pin_len); + return_val_if_fail (the_pin != NULL, CKR_HOST_MEMORY); + n_the_pin = pin_len; + return CKR_OK; +} + +CK_RV +mock_C_InitPIN__invalid_handle (CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_SetPIN__specific_args (CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR old_pin, + CK_ULONG old_pin_len, + CK_UTF8CHAR_PTR new_pin, + CK_ULONG new_pin_len) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (sess == NULL) + return CKR_SESSION_HANDLE_INVALID; + + if (old_pin_len != n_the_pin) + return CKR_PIN_INCORRECT; + if (memcmp (old_pin, the_pin, n_the_pin) != 0) + return CKR_PIN_INCORRECT; + + if (strlen ("TEST PIN") != new_pin_len || + strncmp ((char *)new_pin, "TEST PIN", new_pin_len) != 0) + return CKR_PIN_INVALID; + + free (the_pin); + the_pin = memdup (new_pin, new_pin_len); + return_val_if_fail (the_pin != NULL, CKR_HOST_MEMORY); + n_the_pin = new_pin_len; + return CKR_OK; +} + +CK_RV +mock_C_SetPIN__invalid_handle (CK_SESSION_HANDLE session, + CK_UTF8CHAR_PTR old_pin, + CK_ULONG old_pin_len, + CK_UTF8CHAR_PTR new_pin, + CK_ULONG new_pin_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_GetOperationState (CK_SESSION_HANDLE session, + CK_BYTE_PTR operation_state, + CK_ULONG_PTR operation_state_len) +{ + Session *sess; + + return_val_if_fail (operation_state_len, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (sess == NULL) + return CKR_SESSION_HANDLE_INVALID; + + if (!operation_state) { + *operation_state_len = sizeof (sess); + return CKR_OK; + } + + if (*operation_state_len < sizeof (sess)) + return CKR_BUFFER_TOO_SMALL; + + memcpy (operation_state, &sess, sizeof (sess)); + *operation_state_len = sizeof (sess); + return CKR_OK; +} + +CK_RV +mock_C_GetOperationState__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR operation_state, + CK_ULONG_PTR operation_state_len) +{ + return CKR_FUNCTION_NOT_SUPPORTED; +} + +CK_RV +mock_C_SetOperationState (CK_SESSION_HANDLE session, + CK_BYTE_PTR operation_state, + CK_ULONG operation_state_len, + CK_OBJECT_HANDLE encryption_key, + CK_OBJECT_HANDLE authentication_key) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (sess == NULL) + return CKR_SESSION_HANDLE_INVALID; + + if (!operation_state || operation_state_len != sizeof (sess)) + return CKR_ARGUMENTS_BAD; + + /* Yes, just arbitrary numbers, to make sure they got through */ + if (encryption_key != 355 || authentication_key != 455) + return CKR_KEY_HANDLE_INVALID; + if (memcmp (operation_state, &sess, sizeof (sess)) != 0) + return CKR_SAVED_STATE_INVALID; + return CKR_OK; +} + +CK_RV +mock_C_SetOperationState__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR operation_state, + CK_ULONG operation_state_len, + CK_OBJECT_HANDLE encryption_key, + CK_OBJECT_HANDLE authentication_key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_Login (CK_SESSION_HANDLE session, + CK_USER_TYPE user_type, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + Session *sess; + + return_val_if_fail (user_type == CKU_SO || + user_type == CKU_USER || + user_type == CKU_CONTEXT_SPECIFIC, + CKR_USER_TYPE_INVALID); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (sess == NULL) + return CKR_SESSION_HANDLE_INVALID; + + if (logged_in && user_type != CKU_CONTEXT_SPECIFIC) + return CKR_USER_ALREADY_LOGGED_IN; + + if (!pin) + return CKR_PIN_INCORRECT; + + if (pin_len != n_the_pin) + return CKR_PIN_INCORRECT; + if (strncmp ((char *)pin, (char *)the_pin, pin_len) != 0) + return CKR_PIN_INCORRECT; + + if (user_type == CKU_CONTEXT_SPECIFIC) { + return_val_if_fail (sess->want_context_login, CKR_OPERATION_NOT_INITIALIZED); + sess->want_context_login = false; + } else { + logged_in = true; + the_user_type = user_type; + } + + return CKR_OK; +} + +CK_RV +mock_C_Login__invalid_handle (CK_SESSION_HANDLE session, + CK_USER_TYPE user_type, + CK_UTF8CHAR_PTR pin, + CK_ULONG pin_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_Logout (CK_SESSION_HANDLE session) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (!logged_in) + return CKR_USER_NOT_LOGGED_IN; + + logged_in = false; + the_user_type = 0; + return CKR_OK; +} + +CK_RV +mock_C_Logout__invalid_handle (CK_SESSION_HANDLE session) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_CreateObject (CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR object) +{ + CK_ATTRIBUTE *attrs; + Session *sess; + CK_BBOOL token, priv; + + return_val_if_fail (object, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + attrs = p11_attrs_buildn (NULL, template, count); + + if (find_boolean_attribute (attrs, CKA_PRIVATE, &priv) && priv) { + if (!logged_in) { + p11_attrs_free (attrs); + return CKR_USER_NOT_LOGGED_IN; + } + } + + *object = ++unique_identifier; + if (find_boolean_attribute (attrs, CKA_TOKEN, &token) && token) + p11_dict_set (the_objects, handle_to_pointer (*object), attrs); + else + p11_dict_set (sess->objects, handle_to_pointer (*object), attrs); + + return CKR_OK; +} + +CK_RV +mock_C_CreateObject__invalid_handle (CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR new_object) +{ + return_val_if_fail (new_object, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_CopyObject (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR new_object) +{ + CK_ATTRIBUTE *attrs; + Session *sess; + CK_BBOOL token, priv; + CK_RV rv; + + return_val_if_fail (object, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + rv = lookup_object (sess, object, &attrs, NULL); + if (rv != CKR_OK) + return rv; + + if (find_boolean_attribute (attrs, CKA_PRIVATE, &priv) && priv) { + if (!logged_in) + return CKR_USER_NOT_LOGGED_IN; + } + + attrs = p11_attrs_buildn (p11_attrs_dup (attrs), template, count); + + *new_object = ++unique_identifier; + if (find_boolean_attribute (attrs, CKA_TOKEN, &token) && token) + p11_dict_set (the_objects, handle_to_pointer (*new_object), attrs); + else + p11_dict_set (sess->objects, handle_to_pointer (*new_object), attrs); + + return CKR_OK; +} + +CK_RV +mock_C_CopyObject__invalid_handle (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR new_object) +{ + return_val_if_fail (new_object, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + + +CK_RV +mock_C_DestroyObject (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object) +{ + CK_ATTRIBUTE *attrs; + Session *sess; + p11_dict *table; + CK_RV rv; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + rv = lookup_object (sess, object, &attrs, &table); + if (rv != CKR_OK) + return rv; + + p11_dict_remove (table, handle_to_pointer (object)); + return CKR_OK; +} + +CK_RV +mock_C_DestroyObject__invalid_handle (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_GetObjectSize (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ULONG_PTR size) +{ + CK_ATTRIBUTE *attrs; + Session *sess; + CK_RV rv; + CK_ULONG i; + + return_val_if_fail (size != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + rv = lookup_object (sess, object, &attrs, NULL); + if (rv != CKR_OK) + return rv; + + *size = 0; + for (i = 0; !p11_attrs_is_empty (attrs + i); i++) { + if (attrs[i].ulValueLen != (CK_ULONG)-1) + *size += attrs[i].ulValueLen; + } + + return CKR_OK; +} + +CK_RV +mock_C_GetObjectSize__invalid_handle (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ULONG_PTR size) +{ + return_val_if_fail (size, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_GetAttributeValue (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + CK_ATTRIBUTE *result; + CK_RV ret = CKR_OK; + CK_ATTRIBUTE *attrs; + CK_ATTRIBUTE *attr; + Session *sess; + CK_ULONG i; + CK_RV rv; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (sess == NULL) + return CKR_SESSION_HANDLE_INVALID; + + rv = lookup_object (sess, object, &attrs, NULL); + if (rv != CKR_OK) + return rv; + + for (i = 0; i < count; ++i) { + result = template + i; + attr = p11_attrs_find (attrs, result->type); + if (!attr) { + result->ulValueLen = (CK_ULONG)-1; + ret = CKR_ATTRIBUTE_TYPE_INVALID; + continue; + } + + if (!result->pValue) { + result->ulValueLen = attr->ulValueLen; + continue; + } + + if (result->ulValueLen >= attr->ulValueLen) { + memcpy (result->pValue, attr->pValue, attr->ulValueLen); + result->ulValueLen = attr->ulValueLen; + continue; + } + + result->ulValueLen = (CK_ULONG)-1; + ret = CKR_BUFFER_TOO_SMALL; + } + + return ret; +} + +CK_RV +mock_C_GetAttributeValue__invalid_handle (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_SetAttributeValue (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + Session *sess; + CK_ATTRIBUTE *attrs; + p11_dict *table; + CK_RV rv; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + rv = lookup_object (sess, object, &attrs, &table); + if (rv != CKR_OK) + return rv; + + p11_dict_steal (table, handle_to_pointer (object), NULL, (void **)&attrs); + attrs = p11_attrs_buildn (attrs, template, count); + p11_dict_set (table, handle_to_pointer (object), attrs); + return CKR_OK; +} + +CK_RV +mock_C_SetAttributeValue__invalid_handle (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE object, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +typedef struct _FindObjects { + CK_ATTRIBUTE *template; + CK_ULONG count; + Session *sess; +} FindObjects; + +static bool +enumerate_and_find_objects (CK_OBJECT_HANDLE object, + CK_ATTRIBUTE *attrs, + void *user_data) +{ + FindObjects *ctx = user_data; + CK_ATTRIBUTE *match; + CK_ATTRIBUTE *attr; + CK_ULONG i; + + for (i = 0; i < ctx->count; ++i) { + match = ctx->template + i; + attr = p11_attrs_find (attrs, match->type); + if (!attr) + return true; /* Continue */ + + if (attr->ulValueLen != match->ulValueLen || + memcmp (attr->pValue, match->pValue, attr->ulValueLen) != 0) + return true; /* Continue */ + } + + p11_array_push (ctx->sess->matches, handle_to_pointer (object)); + return true; /* Continue */ +} + +static int +compar_handles (const void *one, + const void *two) +{ + void **p1 = (void **)one; + void **p2 = (void **)two; + return pointer_to_handle (*p2) - pointer_to_handle (*p1); +} + +CK_RV +mock_C_FindObjectsInit (CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + Session *sess; + FindObjects ctx; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + /* Starting an operation, cancels any previous one */ + sess->crypto_mechanism = 0; + sess->hash_mechanism = 0; + + sess->finding = true; + p11_array_free (sess->matches); + sess->matches = p11_array_new (NULL); + + ctx.template = template; + ctx.count = count; + ctx.sess = sess; + + mock_module_enumerate_objects (session, enumerate_and_find_objects, &ctx); + qsort (sess->matches->elem, sess->matches->num, sizeof (void *), compar_handles); + return CKR_OK; +} + +CK_RV +mock_C_FindObjectsInit__invalid_handle (CK_SESSION_HANDLE session, + CK_ATTRIBUTE_PTR template, + CK_ULONG count) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_FindObjects (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE_PTR objects, + CK_ULONG max_object_count, + CK_ULONG_PTR object_count) +{ + Session *sess; + + return_val_if_fail (objects, CKR_ARGUMENTS_BAD); + return_val_if_fail (object_count, CKR_ARGUMENTS_BAD); + return_val_if_fail (max_object_count != 0, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (sess == NULL) + return CKR_SESSION_HANDLE_INVALID; + if (!sess->finding) + return CKR_OPERATION_NOT_INITIALIZED; + + *object_count = 0; + while (max_object_count > 0) { + if (sess->matches->num == 0) + break; + *objects = pointer_to_handle (sess->matches->elem[sess->matches->num - 1]); + ++objects; + --max_object_count; + ++(*object_count); + p11_array_remove (sess->matches, sess->matches->num - 1); + } + + return CKR_OK; +} + +CK_RV +mock_C_FindObjects__invalid_handle (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE_PTR objects, + CK_ULONG max_count, + CK_ULONG_PTR count) +{ + return_val_if_fail (count, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_FindObjectsFinal (CK_SESSION_HANDLE session) +{ + + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (sess == NULL) + return CKR_SESSION_HANDLE_INVALID; + if (!sess->finding) + return CKR_OPERATION_NOT_INITIALIZED; + + sess->finding = false; + p11_array_free (sess->matches); + sess->matches = NULL; + + return CKR_OK; +} + +CK_RV +mock_C_FindObjectsFinal__invalid_handle (CK_SESSION_HANDLE session) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_EncryptInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + Session *sess; + + return_val_if_fail (mechanism != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + /* Starting an operation, cancels any previous one */ + sess->finding = CK_FALSE; + + if (mechanism->mechanism != CKM_MOCK_CAPITALIZE) + return CKR_MECHANISM_INVALID; + if (key != MOCK_PUBLIC_KEY_CAPITALIZE) + return CKR_KEY_HANDLE_INVALID; + + sess->crypto_method = CKA_ENCRYPT; + sess->crypto_mechanism = CKM_MOCK_CAPITALIZE; + sess->crypto_key = key; + return CKR_OK; +} + +CK_RV +mock_C_EncryptInit__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_Encrypt (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR encrypted_data, + CK_ULONG_PTR encrypted_data_len) +{ + CK_ULONG last = 0; + CK_RV rv; + rv = mock_C_EncryptUpdate (session, data, data_len, encrypted_data, encrypted_data_len); + if (rv == CKR_OK) + rv = mock_C_EncryptFinal (session, encrypted_data, &last); + return rv; +} + +CK_RV +mock_C_Encrypt__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR encrypted_data, + CK_ULONG_PTR encrypted_data_len) +{ + return_val_if_fail (encrypted_data_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_EncryptUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + Session *sess; + CK_ULONG i; + + return_val_if_fail (part != NULL, CKR_DATA_INVALID); + return_val_if_fail (encrypted_part_len != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (!sess->crypto_mechanism) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->crypto_method != CKA_ENCRYPT) + return CKR_OPERATION_NOT_INITIALIZED; + assert (sess->crypto_mechanism == CKM_MOCK_CAPITALIZE); + assert (sess->crypto_key == MOCK_PUBLIC_KEY_CAPITALIZE); + + if (!encrypted_part) { + *encrypted_part_len = part_len; + return CKR_OK; + } + + if (*encrypted_part_len < part_len) { + *encrypted_part_len = part_len; + return CKR_BUFFER_TOO_SMALL; + } + + for (i = 0; i < part_len; ++i) + encrypted_part[i] = toupper (part[i]); + *encrypted_part_len = part_len; + return CKR_OK; +} + +CK_RV +mock_C_EncryptUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + return_val_if_fail (encrypted_part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_EncryptFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR last_encrypted_part, + CK_ULONG_PTR last_encrypted_part_len) +{ + Session *sess; + + return_val_if_fail (last_encrypted_part_len != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (!sess->crypto_mechanism) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->crypto_method != CKA_ENCRYPT) + return CKR_OPERATION_NOT_INITIALIZED; + + *last_encrypted_part_len = 0; + + sess->crypto_method = 0; + sess->crypto_mechanism = 0; + sess->crypto_key = 0; + return CKR_OK; +} + +CK_RV +mock_C_EncryptFinal__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR last_part, + CK_ULONG_PTR last_part_len) +{ + return_val_if_fail (last_part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DecryptInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + Session *sess; + + return_val_if_fail (mechanism != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + /* Starting an operation, cancels any previous one */ + sess->finding = false; + + if (mechanism->mechanism != CKM_MOCK_CAPITALIZE) + return CKR_MECHANISM_INVALID; + if (key != MOCK_PRIVATE_KEY_CAPITALIZE) + return CKR_KEY_HANDLE_INVALID; + + sess->crypto_method = CKA_DECRYPT; + sess->crypto_mechanism = CKM_MOCK_CAPITALIZE; + sess->crypto_key = key; + return CKR_OK; +} + +CK_RV +mock_C_DecryptInit__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_Decrypt (CK_SESSION_HANDLE session, + CK_BYTE_PTR encrypted_data, + CK_ULONG encrypted_data_len, + CK_BYTE_PTR data, + CK_ULONG_PTR data_len) +{ + CK_ULONG last = 0; + CK_RV rv; + rv = mock_C_DecryptUpdate (session, encrypted_data, encrypted_data_len, data, data_len); + if (rv == CKR_OK) + rv = mock_C_DecryptFinal (session, data, &last); + return rv; +} + +CK_RV +mock_C_Decrypt__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR enc_data, + CK_ULONG enc_data_len, + CK_BYTE_PTR data, + CK_ULONG_PTR data_len) +{ + return_val_if_fail (data_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DecryptUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + Session *sess; + CK_ULONG i; + + return_val_if_fail (encrypted_part, CKR_ENCRYPTED_DATA_INVALID); + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (!sess->crypto_mechanism) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->crypto_method != CKA_DECRYPT) + return CKR_OPERATION_NOT_INITIALIZED; + assert (sess->crypto_mechanism == CKM_MOCK_CAPITALIZE); + assert (sess->crypto_key == MOCK_PRIVATE_KEY_CAPITALIZE); + + if (!part) { + *part_len = encrypted_part_len; + return CKR_OK; + } + + if (*part_len < encrypted_part_len) { + *part_len = encrypted_part_len; + return CKR_BUFFER_TOO_SMALL; + } + + for (i = 0; i < encrypted_part_len; ++i) + part[i] = tolower (encrypted_part[i]); + *part_len = encrypted_part_len; + return CKR_OK; +} + +CK_RV +mock_C_DecryptUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR enc_part, + CK_ULONG enc_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DecryptFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR last_part, + CK_ULONG_PTR last_part_len) +{ + Session *sess; + + return_val_if_fail (last_part_len != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (!sess->crypto_mechanism) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->crypto_method != CKA_DECRYPT) + return CKR_OPERATION_NOT_INITIALIZED; + + *last_part_len = 0; + + sess->crypto_method = 0; + sess->crypto_mechanism = 0; + sess->crypto_key = 0; + + return CKR_OK; +} + +CK_RV +mock_C_DecryptFinal__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR last_part, + CK_ULONG_PTR last_part_len) +{ + return_val_if_fail (last_part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DigestInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism) +{ + Session *sess; + + return_val_if_fail (mechanism != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + /* Starting an operation, cancels any previous one */ + sess->finding = false; + + if (mechanism->mechanism != CKM_MOCK_COUNT) + return CKR_MECHANISM_INVALID; + + sess->hash_mechanism = CKM_MOCK_COUNT; + sess->hash_method = (CK_ULONG)-1; + sess->hash_count = 0; + sess->hash_key = 0; + return CKR_OK; +} + +CK_RV +mock_C_DigestInit__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_Digest (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + CK_RV rv; + + return_val_if_fail (digest_len, CKR_ARGUMENTS_BAD); + + rv = mock_C_DigestUpdate (session, data, data_len); + if (rv == CKR_OK) + rv = mock_C_DigestFinal (session, digest, digest_len); + return rv; +} + +CK_RV +mock_C_Digest__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + return_val_if_fail (digest_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DigestUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (!sess->hash_mechanism) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->hash_method != (CK_ULONG)-1) + return CKR_OPERATION_NOT_INITIALIZED; + assert (sess->hash_mechanism == CKM_MOCK_COUNT); + + sess->hash_count += part_len; + return CKR_OK; +} + +CK_RV +mock_C_DigestUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DigestKey (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE key) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (!sess->hash_mechanism) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->hash_method != (CK_ULONG)-1) + return CKR_OPERATION_NOT_INITIALIZED; + assert (sess->hash_mechanism == CKM_MOCK_COUNT); + + sess->hash_count += key; + return CKR_OK; +} + +CK_RV +mock_C_DigestKey__invalid_handle (CK_SESSION_HANDLE session, + CK_OBJECT_HANDLE key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DigestFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + char buffer[32]; + Session *sess; + int len; + + return_val_if_fail (digest_len != NULL, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (!sess->hash_mechanism) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->hash_method != (CK_ULONG)-1) + return CKR_OPERATION_NOT_INITIALIZED; + assert (sess->hash_mechanism == CKM_MOCK_COUNT); + + len = snprintf (buffer, sizeof (buffer), "%lu", sess->hash_count); + + if (!digest) { + *digest_len = len; + return CKR_OK; + } else if (*digest_len < len) { + *digest_len = len; + return CKR_BUFFER_TOO_SMALL; + } + + memcpy (digest, &buffer, len); + *digest_len = len; + + sess->hash_count = 0; + sess->hash_mechanism = 0; + sess->hash_key = 0; + sess->hash_method = 0; + + return CKR_OK; +} + +CK_RV +mock_C_DigestFinal__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR digest, + CK_ULONG_PTR digest_len) +{ + return_val_if_fail (digest_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +static CK_RV +prefix_mechanism_init (CK_SESSION_HANDLE session, + CK_ATTRIBUTE_TYPE method, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + Session *sess; + CK_ATTRIBUTE *attrs; + CK_ATTRIBUTE *value; + CK_BYTE_PTR param; + CK_ULONG n_param; + CK_ULONG length; + CK_RV rv; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (mechanism->mechanism != CKM_MOCK_PREFIX) + return CKR_MECHANISM_INVALID; + if (method == CKA_SIGN || method == CKA_SIGN_RECOVER) { + if (key != MOCK_PRIVATE_KEY_PREFIX) + return CKR_KEY_HANDLE_INVALID; + } else if (method == CKA_VERIFY || CKA_VERIFY_RECOVER) { + if (key != MOCK_PUBLIC_KEY_PREFIX) + return CKR_KEY_HANDLE_INVALID; + } else { + assert_not_reached (); + } + + rv = lookup_object (sess, key, &attrs, NULL); + if (rv != CKR_OK) + return rv; + + value = p11_attrs_find (attrs, CKA_VALUE); + if (value == NULL) + return CKR_KEY_TYPE_INCONSISTENT; + + if (mechanism->pParameter) { + param = mechanism->pParameter; + n_param = mechanism->ulParameterLen; + } else { + param = (CK_BYTE_PTR)SIGNED_PREFIX; + n_param = strlen (SIGNED_PREFIX) + 1; + } + + length = value->ulValueLen + n_param; + if (length > sizeof (sess->sign_prefix)) + return CKR_KEY_SIZE_RANGE; + + /* Starting an operation, cancels any finding */ + sess->finding = false; + + sess->hash_mechanism = CKM_MOCK_PREFIX; + sess->hash_method = method; + sess->hash_key = key; + sess->hash_count = 0; + + memcpy (sess->sign_prefix, param, n_param); + memcpy (sess->sign_prefix + n_param, value->pValue, value->ulValueLen); + sess->n_sign_prefix = length; + + /* The private key has CKA_ALWAYS_AUTHENTICATE above */ + if (method == CKA_SIGN || method == CKA_SIGN_RECOVER) + sess->want_context_login = true; + + return CKR_OK; + +} + +CK_RV +mock_C_SignInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return_val_if_fail (mechanism != NULL, CKR_ARGUMENTS_BAD); + return prefix_mechanism_init (session, CKA_SIGN, mechanism, key); +} + +CK_RV +mock_C_SignInit__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_Sign (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + CK_RV rv; + + rv = mock_C_SignUpdate (session, data, data_len); + if (rv == CKR_OK) + rv = mock_C_SignFinal (session, signature, signature_len); + + return rv; +} + +CK_RV +mock_C_Sign__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_SignUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + if (sess->hash_mechanism != CKM_MOCK_PREFIX || + sess->hash_method != CKA_SIGN) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->want_context_login) + return CKR_USER_NOT_LOGGED_IN; + + sess->hash_count += part_len; + return CKR_OK; +} + +CK_RV +mock_C_SignUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_SignFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + char buffer[32]; + Session *sess; + CK_ULONG length; + int len; + + return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + if (sess->hash_mechanism != CKM_MOCK_PREFIX || + sess->hash_method != CKA_SIGN) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->want_context_login) + return CKR_USER_NOT_LOGGED_IN; + + len = snprintf (buffer, sizeof (buffer), "%lu", sess->hash_count); + length = sess->n_sign_prefix + len; + + if (!signature) { + *signature_len = length; + return CKR_OK; + } + + if (*signature_len < length) { + *signature_len = length; + return CKR_BUFFER_TOO_SMALL; + } + + memcpy (signature, sess->sign_prefix, sess->n_sign_prefix); + memcpy (signature + sess->n_sign_prefix, buffer, len); + *signature_len = length; + + sess->hash_mechanism = 0; + sess->hash_method = 0; + sess->hash_count = 0; + sess->hash_key = 0; + + return CKR_OK; +} + +CK_RV +mock_C_SignFinal__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_SignRecoverInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return_val_if_fail (mechanism != NULL, CKR_ARGUMENTS_BAD); + return prefix_mechanism_init (session, CKA_SIGN_RECOVER, mechanism, key); +} + +CK_RV +mock_C_SignRecoverInit__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_SignRecover (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + Session *sess; + CK_ULONG length; + + return_val_if_fail (data, CKR_DATA_INVALID); + return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + if (sess->hash_method != CKA_SIGN_RECOVER || + sess->hash_mechanism != CKM_MOCK_PREFIX) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->want_context_login) + return CKR_USER_NOT_LOGGED_IN; + + length = sess->n_sign_prefix + data_len; + + if (!signature) { + *signature_len = length; + return CKR_OK; + } + + if (*signature_len < length) { + *signature_len = length; + return CKR_BUFFER_TOO_SMALL; + } + + memcpy (signature, sess->sign_prefix, sess->n_sign_prefix); + memcpy (signature + sess->n_sign_prefix, data, data_len); + *signature_len = length; + + sess->hash_method = 0; + sess->hash_mechanism = 0; + sess->hash_key = 0; + sess->hash_count = 0; + + return CKR_OK; +} + +CK_RV +mock_C_SignRecover__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG_PTR signature_len) +{ + return_val_if_fail (signature_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_VerifyInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return_val_if_fail (mechanism != NULL, CKR_ARGUMENTS_BAD); + return prefix_mechanism_init (session, CKA_VERIFY, mechanism, key); +} + +CK_RV +mock_C_VerifyInit__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_Verify (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + CK_RV rv; + + rv = mock_C_VerifyUpdate (session, data, data_len); + if (rv == CKR_OK) + rv = mock_C_VerifyFinal (session, signature, signature_len); + + return rv; +} + +CK_RV +mock_C_Verify__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR data, + CK_ULONG data_len, + CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_VerifyUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + if (sess->hash_mechanism != CKM_MOCK_PREFIX || + sess->hash_method != CKA_VERIFY) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->want_context_login) + return CKR_USER_NOT_LOGGED_IN; + + sess->hash_count += part_len; + return CKR_OK; +} + +CK_RV +mock_C_VerifyUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_VerifyFinal (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + char buffer[32]; + Session *sess; + CK_ULONG length; + int len; + + return_val_if_fail (signature, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + if (sess->hash_mechanism != CKM_MOCK_PREFIX || + sess->hash_method != CKA_VERIFY) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->want_context_login) + return CKR_USER_NOT_LOGGED_IN; + + len = snprintf (buffer, sizeof (buffer), "%lu", sess->hash_count); + length = sess->n_sign_prefix + len; + + if (!signature || signature_len != length) + return CKR_SIGNATURE_LEN_RANGE; + + if (memcmp (signature, sess->sign_prefix, sess->n_sign_prefix) != 0 || + memcmp (signature + sess->n_sign_prefix, buffer, len) != 0) + return CKR_SIGNATURE_INVALID; + + sess->hash_mechanism = 0; + sess->hash_method = 0; + sess->hash_count = 0; + sess->hash_key = 0; + + return CKR_OK; +} + +CK_RV +mock_C_VerifyFinal__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG signature_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_VerifyRecoverInit (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return_val_if_fail (mechanism != NULL, CKR_ARGUMENTS_BAD); + return prefix_mechanism_init (session, CKA_VERIFY_RECOVER, mechanism, key); +} + +CK_RV +mock_C_VerifyRecoverInit__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_VerifyRecover (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG signature_len, + CK_BYTE_PTR data, + CK_ULONG_PTR data_len) +{ + Session *sess; + CK_ULONG length; + + return_val_if_fail (signature, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + if (sess->hash_mechanism != CKM_MOCK_PREFIX || + sess->hash_method != CKA_VERIFY_RECOVER) + return CKR_OPERATION_NOT_INITIALIZED; + if (sess->want_context_login) + return CKR_USER_NOT_LOGGED_IN; + + if (signature_len < sess->n_sign_prefix) + return CKR_SIGNATURE_LEN_RANGE; + if (memcmp (signature, sess->sign_prefix, sess->n_sign_prefix) != 0) + return CKR_SIGNATURE_INVALID; + + length = signature_len - sess->n_sign_prefix; + if (!data) { + *data_len = length; + return CKR_OK; + } + + if (*data_len < length) { + *data_len = length; + return CKR_BUFFER_TOO_SMALL; + } + + *data_len = length; + memcpy (data, signature + sess->n_sign_prefix, length); + return CKR_OK; +} + +CK_RV +mock_C_VerifyRecover__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR signature, + CK_ULONG signature_len, + CK_BYTE_PTR data, + CK_ULONG_PTR data_len) +{ + return_val_if_fail (data_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DigestEncryptUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + CK_RV rv; + + rv = mock_C_EncryptUpdate (session, part, part_len, encrypted_part, encrypted_part_len); + if (rv == CKR_OK) + rv = mock_C_DigestUpdate (session, part, part_len); + + return rv; +} + +CK_RV +mock_C_DigestEncryptUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR enc_part, + CK_ULONG_PTR enc_part_len) +{ + return_val_if_fail (enc_part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DecryptDigestUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + CK_RV rv; + + rv = mock_C_DecryptUpdate (session, encrypted_part, encrypted_part_len, part, part_len); + if (rv == CKR_OK) + rv = mock_C_DigestUpdate (session, part, *part_len); + + return rv; +} + +CK_RV +mock_C_DecryptDigestUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR enc_part, + CK_ULONG enc_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_SignEncryptUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR encrypted_part, + CK_ULONG_PTR encrypted_part_len) +{ + CK_RV rv; + + rv = mock_C_EncryptUpdate (session, part, part_len, encrypted_part, encrypted_part_len); + if (rv == CKR_OK) + rv = mock_C_SignUpdate (session, part, part_len); + + return rv; +} + +CK_RV +mock_C_SignEncryptUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR part, + CK_ULONG part_len, + CK_BYTE_PTR enc_part, + CK_ULONG_PTR enc_part_len) +{ + return_val_if_fail (enc_part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DecryptVerifyUpdate (CK_SESSION_HANDLE session, + CK_BYTE_PTR encrypted_part, + CK_ULONG encrypted_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + CK_RV rv; + + rv = mock_C_DecryptUpdate (session, encrypted_part, encrypted_part_len, part, part_len); + if (rv == CKR_OK) + rv = mock_C_VerifyUpdate (session, part, *part_len); + + return rv; +} + +CK_RV +mock_C_DecryptVerifyUpdate__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR enc_part, + CK_ULONG enc_part_len, + CK_BYTE_PTR part, + CK_ULONG_PTR part_len) +{ + return_val_if_fail (part_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_GenerateKey (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + CK_ATTRIBUTE *attrs; + CK_ATTRIBUTE value; + Session *sess; + CK_BBOOL token; + + return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + return_val_if_fail (template, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (count, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (key, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (mechanism->mechanism != CKM_MOCK_GENERATE) + return CKR_MECHANISM_INVALID; + + if (!mechanism->pParameter || mechanism->ulParameterLen != 9 || + memcmp (mechanism->pParameter, "generate", 9) != 0) + return CKR_MECHANISM_PARAM_INVALID; + + value.type = CKA_VALUE; + value.pValue = "generated"; + value.ulValueLen = strlen (value.pValue); + + attrs = p11_attrs_buildn (NULL, template, count); + attrs = p11_attrs_buildn (attrs, &value, 1); + + *key = ++unique_identifier; + if (find_boolean_attribute (attrs, CKA_TOKEN, &token) && token) + p11_dict_set (the_objects, handle_to_pointer (*key), attrs); + else + p11_dict_set (sess->objects, handle_to_pointer (*key), attrs); + + return CKR_OK; +} + +CK_RV +mock_C_GenerateKey__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_GenerateKeyPair (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR public_key_template, + CK_ULONG public_key_count, + CK_ATTRIBUTE_PTR private_key_template, + CK_ULONG private_key_count, + CK_OBJECT_HANDLE_PTR public_key, + CK_OBJECT_HANDLE_PTR private_key) +{ + CK_ATTRIBUTE *attrs; + CK_ATTRIBUTE value; + Session *sess; + CK_BBOOL token; + + return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + return_val_if_fail (public_key_template, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (public_key_count, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (private_key_template, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (private_key_count, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (public_key, CKR_ARGUMENTS_BAD); + return_val_if_fail (private_key, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (mechanism->mechanism != CKM_MOCK_GENERATE) + return CKR_MECHANISM_INVALID; + + if (!mechanism->pParameter || mechanism->ulParameterLen != 9 || + memcmp (mechanism->pParameter, "generate", 9) != 0) + return CKR_MECHANISM_PARAM_INVALID; + + value.type = CKA_VALUE; + value.pValue = "generated"; + value.ulValueLen = strlen (value.pValue); + + attrs = p11_attrs_buildn (NULL, public_key_template, public_key_count); + attrs = p11_attrs_buildn (attrs, &value, 1); + + *public_key = ++unique_identifier; + if (find_boolean_attribute (attrs, CKA_TOKEN, &token) && token) + p11_dict_set (the_objects, handle_to_pointer (*public_key), attrs); + else + p11_dict_set (sess->objects, handle_to_pointer (*public_key), attrs); + + attrs = p11_attrs_buildn (NULL, private_key_template, private_key_count); + attrs = p11_attrs_buildn (attrs, &value, 1); + + *private_key = ++unique_identifier; + if (find_boolean_attribute (attrs, CKA_TOKEN, &token) && token) + p11_dict_set (the_objects, handle_to_pointer (*private_key), attrs); + else + p11_dict_set (sess->objects, handle_to_pointer (*private_key), attrs); + + return CKR_OK; +} + +CK_RV +mock_C_GenerateKeyPair__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_ATTRIBUTE_PTR pub_template, + CK_ULONG pub_count, + CK_ATTRIBUTE_PTR priv_template, + CK_ULONG priv_count, + CK_OBJECT_HANDLE_PTR pub_key, + CK_OBJECT_HANDLE_PTR priv_key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_WrapKey (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE wrapping_key, + CK_OBJECT_HANDLE key, + CK_BYTE_PTR wrapped_key, + CK_ULONG_PTR wrapped_key_len) +{ + CK_ATTRIBUTE *attrs; + CK_ATTRIBUTE *attr; + Session *sess; + CK_RV rv; + + return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + return_val_if_fail (wrapping_key, CKR_OBJECT_HANDLE_INVALID); + return_val_if_fail (key, CKR_OBJECT_HANDLE_INVALID); + return_val_if_fail (wrapped_key_len, CKR_WRAPPED_KEY_LEN_RANGE); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + rv = lookup_object (sess, wrapping_key, &attrs, NULL); + if (rv == CKR_OBJECT_HANDLE_INVALID) + return CKR_WRAPPING_KEY_HANDLE_INVALID; + else if (rv != CKR_OK) + return rv; + + rv = lookup_object (sess, key, &attrs, NULL); + if (rv == CKR_OBJECT_HANDLE_INVALID) + return CKR_WRAPPING_KEY_HANDLE_INVALID; + else if (rv != CKR_OK) + return rv; + + if (mechanism->mechanism != CKM_MOCK_WRAP) + return CKR_MECHANISM_INVALID; + + if (mechanism->pParameter == NULL || + mechanism->ulParameterLen != 4 || + memcmp (mechanism->pParameter, "wrap", 4) != 0) { + return CKR_MECHANISM_PARAM_INVALID; + } + + attr = p11_attrs_find (attrs, CKA_VALUE); + if (attr == NULL) + return CKR_WRAPPED_KEY_INVALID; + + if (!wrapped_key) { + *wrapped_key_len = attr->ulValueLen; + return CKR_OK; + } + + if (*wrapped_key_len < attr->ulValueLen) { + *wrapped_key_len = attr->ulValueLen; + return CKR_BUFFER_TOO_SMALL; + } + + memcpy (wrapped_key, attr->pValue, attr->ulValueLen); + *wrapped_key_len = attr->ulValueLen; + + return CKR_OK; +} + +CK_RV +mock_C_WrapKey__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE wrapping_key, + CK_OBJECT_HANDLE key, + CK_BYTE_PTR wrapped_key, + CK_ULONG_PTR wrapped_key_len) +{ + return_val_if_fail (wrapped_key_len, CKR_ARGUMENTS_BAD); + + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_UnwrapKey (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE unwrapping_key, + CK_BYTE_PTR wrapped_key, + CK_ULONG wrapped_key_len, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + CK_ATTRIBUTE *attrs; + CK_ATTRIBUTE value; + Session *sess; + CK_BBOOL token; + CK_RV rv; + + return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + return_val_if_fail (unwrapping_key, CKR_WRAPPING_KEY_HANDLE_INVALID); + return_val_if_fail (wrapped_key, CKR_WRAPPED_KEY_INVALID); + return_val_if_fail (wrapped_key_len, CKR_WRAPPED_KEY_LEN_RANGE); + return_val_if_fail (key, CKR_ARGUMENTS_BAD); + return_val_if_fail (template, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (count, CKR_TEMPLATE_INCONSISTENT); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + rv = lookup_object (sess, unwrapping_key, &attrs, NULL); + if (rv == CKR_OBJECT_HANDLE_INVALID) + return CKR_WRAPPING_KEY_HANDLE_INVALID; + else if (rv != CKR_OK) + return rv; + + if (mechanism->mechanism != CKM_MOCK_WRAP) + return CKR_MECHANISM_INVALID; + + if (mechanism->pParameter == NULL || + mechanism->ulParameterLen != 4 || + memcmp (mechanism->pParameter, "wrap", 4) != 0) { + return CKR_MECHANISM_PARAM_INVALID; + } + + value.type = CKA_VALUE; + value.pValue = wrapped_key; + value.ulValueLen = wrapped_key_len; + + attrs = p11_attrs_buildn (NULL, template, count); + attrs = p11_attrs_buildn (attrs, &value, 1); + + *key = ++unique_identifier; + if (find_boolean_attribute (attrs, CKA_TOKEN, &token) && token) + p11_dict_set (the_objects, handle_to_pointer (*key), attrs); + else + p11_dict_set (sess->objects, handle_to_pointer (*key), attrs); + + return CKR_OK; +} + +CK_RV +mock_C_UnwrapKey__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE unwrapping_key, + CK_BYTE_PTR wrapped_key, + CK_ULONG wrapped_key_len, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_DeriveKey (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + CK_ATTRIBUTE *attrs, *copy; + CK_ATTRIBUTE value; + Session *sess; + CK_BBOOL token; + CK_RV rv; + + return_val_if_fail (mechanism, CKR_MECHANISM_INVALID); + return_val_if_fail (count, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (template, CKR_TEMPLATE_INCOMPLETE); + return_val_if_fail (key, CKR_ARGUMENTS_BAD); + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + rv = lookup_object (sess, base_key, &attrs, NULL); + if (rv == CKR_OBJECT_HANDLE_INVALID) + return CKR_KEY_HANDLE_INVALID; + else if (rv != CKR_OK) + return rv; + + if (mechanism->mechanism != CKM_MOCK_DERIVE) + return CKR_MECHANISM_INVALID; + + if (mechanism->pParameter == NULL || + mechanism->ulParameterLen != 6 || + memcmp (mechanism->pParameter, "derive", 6) != 0) { + return CKR_MECHANISM_PARAM_INVALID; + } + + value.type = CKA_VALUE; + value.pValue = "derived"; + value.ulValueLen = strlen (value.pValue); + + copy = p11_attrs_buildn (NULL, template, count); + copy = p11_attrs_buildn (copy, &value, 1); + + *key = ++unique_identifier; + if (find_boolean_attribute (copy, CKA_TOKEN, &token) && token) + p11_dict_set (the_objects, handle_to_pointer (*key), copy); + else + p11_dict_set (sess->objects, handle_to_pointer (*key), copy); + + return CKR_OK; +} + +CK_RV +mock_C_DeriveKey__invalid_handle (CK_SESSION_HANDLE session, + CK_MECHANISM_PTR mechanism, + CK_OBJECT_HANDLE base_key, + CK_ATTRIBUTE_PTR template, + CK_ULONG count, + CK_OBJECT_HANDLE_PTR key) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_SeedRandom (CK_SESSION_HANDLE session, + CK_BYTE_PTR seed, + CK_ULONG seed_len) +{ + Session *sess; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + if (seed_len > sizeof (sess->random_seed)) + return CKR_RANDOM_SEED_NOT_SUPPORTED; + + memcpy (sess->random_seed, seed, seed_len); + sess->random_seed_len = seed_len; + return CKR_OK; +} + +CK_RV +mock_C_SeedRandom__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR seed, + CK_ULONG seed_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_RV +mock_C_GenerateRandom (CK_SESSION_HANDLE session, + CK_BYTE_PTR random_data, + CK_ULONG random_len) +{ + Session *sess; + CK_ULONG block; + + sess = p11_dict_get (the_sessions, handle_to_pointer (session)); + if (!sess) + return CKR_SESSION_HANDLE_INVALID; + + while (random_len > 0) { + block = sess->random_seed_len; + if (block > random_len) + block = random_len; + memcpy (random_data, sess->random_seed, block); + random_data += block; + random_len -= block; + } + + return CKR_OK; +} + +CK_RV +mock_C_GenerateRandom__invalid_handle (CK_SESSION_HANDLE session, + CK_BYTE_PTR random_data, + CK_ULONG random_len) +{ + return CKR_SESSION_HANDLE_INVALID; +} + +CK_FUNCTION_LIST mock_module_no_slots = { + { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, /* version */ + mock_C_Initialize, + mock_C_Finalize, + mock_C_GetInfo, + mock_C_GetFunctionList_not_supported, + mock_C_GetSlotList__no_tokens, + mock_C_GetSlotInfo__invalid_slotid, + mock_C_GetTokenInfo__invalid_slotid, + mock_C_GetMechanismList__invalid_slotid, + mock_C_GetMechanismInfo__invalid_slotid, + mock_C_InitToken__invalid_slotid, + mock_C_InitPIN__invalid_handle, + mock_C_SetPIN__invalid_handle, + mock_C_OpenSession__invalid_slotid, + mock_C_CloseSession__invalid_handle, + mock_C_CloseAllSessions__invalid_slotid, + mock_C_GetSessionInfo__invalid_handle, + mock_C_GetOperationState__invalid_handle, + mock_C_SetOperationState__invalid_handle, + mock_C_Login__invalid_handle, + mock_C_Logout__invalid_handle, + mock_C_CreateObject__invalid_handle, + mock_C_CopyObject__invalid_handle, + mock_C_DestroyObject__invalid_handle, + mock_C_GetObjectSize__invalid_handle, + mock_C_GetAttributeValue__invalid_handle, + mock_C_SetAttributeValue__invalid_handle, + mock_C_FindObjectsInit__invalid_handle, + mock_C_FindObjects__invalid_handle, + mock_C_FindObjectsFinal__invalid_handle, + mock_C_EncryptInit__invalid_handle, + mock_C_Encrypt__invalid_handle, + mock_C_EncryptUpdate__invalid_handle, + mock_C_EncryptFinal__invalid_handle, + mock_C_DecryptInit__invalid_handle, + mock_C_Decrypt__invalid_handle, + mock_C_DecryptUpdate__invalid_handle, + mock_C_DecryptFinal__invalid_handle, + mock_C_DigestInit__invalid_handle, + mock_C_Digest__invalid_handle, + mock_C_DigestUpdate__invalid_handle, + mock_C_DigestKey__invalid_handle, + mock_C_DigestFinal__invalid_handle, + mock_C_SignInit__invalid_handle, + mock_C_Sign__invalid_handle, + mock_C_SignUpdate__invalid_handle, + mock_C_SignFinal__invalid_handle, + mock_C_SignRecoverInit__invalid_handle, + mock_C_SignRecover__invalid_handle, + mock_C_VerifyInit__invalid_handle, + mock_C_Verify__invalid_handle, + mock_C_VerifyUpdate__invalid_handle, + mock_C_VerifyFinal__invalid_handle, + mock_C_VerifyRecoverInit__invalid_handle, + mock_C_VerifyRecover__invalid_handle, + mock_C_DigestEncryptUpdate__invalid_handle, + mock_C_DecryptDigestUpdate__invalid_handle, + mock_C_SignEncryptUpdate__invalid_handle, + mock_C_DecryptVerifyUpdate__invalid_handle, + mock_C_GenerateKey__invalid_handle, + mock_C_GenerateKeyPair__invalid_handle, + mock_C_WrapKey__invalid_handle, + mock_C_UnwrapKey__invalid_handle, + mock_C_DeriveKey__invalid_handle, + mock_C_SeedRandom__invalid_handle, + mock_C_GenerateRandom__invalid_handle, + mock_C_GetFunctionStatus__not_parallel, + mock_C_CancelFunction__not_parallel, + mock_C_WaitForSlotEvent__no_event, +}; + +CK_FUNCTION_LIST mock_module = { + { CRYPTOKI_VERSION_MAJOR, CRYPTOKI_VERSION_MINOR }, /* version */ + mock_C_Initialize, + mock_C_Finalize, + mock_C_GetInfo, + mock_C_GetFunctionList_not_supported, + mock_C_GetSlotList, + mock_C_GetSlotInfo, + mock_C_GetTokenInfo, + mock_C_GetMechanismList, + mock_C_GetMechanismInfo, + mock_C_InitToken__specific_args, + mock_C_InitPIN__specific_args, + mock_C_SetPIN__specific_args, + mock_C_OpenSession, + mock_C_CloseSession, + mock_C_CloseAllSessions, + mock_C_GetSessionInfo, + mock_C_GetOperationState, + mock_C_SetOperationState, + mock_C_Login, + mock_C_Logout, + mock_C_CreateObject, + mock_C_CopyObject, + mock_C_DestroyObject, + mock_C_GetObjectSize, + mock_C_GetAttributeValue, + mock_C_SetAttributeValue, + mock_C_FindObjectsInit, + mock_C_FindObjects, + mock_C_FindObjectsFinal, + mock_C_EncryptInit, + mock_C_Encrypt, + mock_C_EncryptUpdate, + mock_C_EncryptFinal, + mock_C_DecryptInit, + mock_C_Decrypt, + mock_C_DecryptUpdate, + mock_C_DecryptFinal, + mock_C_DigestInit, + mock_C_Digest, + mock_C_DigestUpdate, + mock_C_DigestKey, + mock_C_DigestFinal, + mock_C_SignInit, + mock_C_Sign, + mock_C_SignUpdate, + mock_C_SignFinal, + mock_C_SignRecoverInit, + mock_C_SignRecover, + mock_C_VerifyInit, + mock_C_Verify, + mock_C_VerifyUpdate, + mock_C_VerifyFinal, + mock_C_VerifyRecoverInit, + mock_C_VerifyRecover, + mock_C_DigestEncryptUpdate, + mock_C_DecryptDigestUpdate, + mock_C_SignEncryptUpdate, + mock_C_DecryptVerifyUpdate, + mock_C_GenerateKey, + mock_C_GenerateKeyPair, + mock_C_WrapKey, + mock_C_UnwrapKey, + mock_C_DeriveKey, + mock_C_SeedRandom, + mock_C_GenerateRandom, + mock_C_GetFunctionStatus, + mock_C_CancelFunction, + mock_C_WaitForSlotEvent, +}; + +void +mock_module_init (void) +{ + static bool initialized = false; + if (!initialized) { + p11_mutex_init (&init_mutex); + initialized = true; + } +} |