summaryrefslogtreecommitdiff
path: root/ckcapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'ckcapi.c')
-rw-r--r--ckcapi.c1167
1 files changed, 1167 insertions, 0 deletions
diff --git a/ckcapi.c b/ckcapi.c
new file mode 100644
index 0000000..971b034
--- /dev/null
+++ b/ckcapi.c
@@ -0,0 +1,1167 @@
+
+#include <string.h>
+#include <stdarg.h>
+#include <stdio.h>
+
+#include "ckcapi.h"
+
+/* -------------------------------------------------------------------
+ * GLOBALS / DEFINES
+ */
+
+/* TODO: Use a random number */
+static CK_ULONG slot_id = 33;
+static int cryptoki_initialized = 0;
+static HANDLE global_mutex = NULL;
+
+#define CRYPTOKI_VERSION_MAJOR 2
+#define CRYPTOKI_VERSION_MINOR 11
+#define MANUFACTURER_ID "Cryptoki CAPI "
+#define LIBRARY_DESCRIPTION "Cryptoki CAPI Provider "
+#define LIBRARY_VERSION_MAJOR 1
+#define LIBRARY_VERSION_MINOR 1
+#define SLOT_DESCRIPTION "Windows CAPI Certificates and Keys "
+#define HARDWARE_VERSION_MAJOR 0
+#define HARDWARE_VERSION_MINOR 0
+#define FIRMWARE_VERSION_MAJOR 0
+#define FIRMWARE_VERSION_MINOR 0
+#define SLOT_TOKEN_SERIAL "1.0 "
+#define SLOT_TOKEN_MODEL "1.0 "
+#define MAX_PIN_LEN 256
+#define MIN_PIN_LEN 1
+
+/* -------------------------------------------------------------------
+ * MODULE GLOBAL FUNCTIONS
+ */
+
+void
+ckcapi_debug(const char* msg, ...)
+{
+ char buf[1024];
+ va_list va;
+
+ va_start(va, msg);
+ _vsnprintf(buf, 1024, msg, va);
+ va_end(va);
+
+ OutputDebugStringA(buf);
+}
+
+/* Bah humbug, MSVC doesn't have __func__ */
+#define ENTER(func) \
+ char* _func = #func; \
+ ckcapi_debug("%s: enter", _func)
+
+#define RETURN(ret) \
+ return (ckcapi_debug("%s: %d", _func, ret), ret)
+
+#define PREREQ(cond, ret) \
+ if (!(cond)) { ckcapi_debug("%s: %s failed: %d", _func, #cond, ret); return ret; }
+
+void
+ckcapi_lock_global(void)
+{
+ DWORD r;
+
+ ASSERT(global_mutex);
+
+ r = WaitForSingleObject(global_mutex, INFINITE);
+ ASSERT(r == WAIT_OBJECT_0);
+}
+
+void
+ckcapi_unlock_global(void)
+{
+ BOOL r;
+
+ ASSERT(global_mutex);
+
+ r = ReleaseMutex(global_mutex);
+ ASSERT(r);
+}
+
+CK_RV
+ckcapi_winerr_to_ckr(DWORD werr)
+{
+ switch(werr)
+ {
+ case ERROR_NOT_ENOUGH_MEMORY:
+ return CKR_HOST_MEMORY;
+ break;
+ case NTE_NO_MEMORY:
+ return CKR_DEVICE_MEMORY;
+ break;
+ case ERROR_MORE_DATA:
+ return CKR_BUFFER_TOO_SMALL;
+ case ERROR_INVALID_PARAMETER: /* these params were derived from the */
+ case ERROR_INVALID_HANDLE: /* inputs, so if they are bad, the input */
+ case NTE_BAD_ALGID: /* data is bad */
+ case NTE_BAD_HASH:
+ return CKR_DATA_INVALID;
+ break;
+ case ERROR_BUSY:
+ case NTE_FAIL:
+ case NTE_BAD_UID:
+ return CKR_DEVICE_ERROR;
+ break;
+ default:
+ return CKR_GENERAL_ERROR;
+ };
+}
+
+
+/* ---------------------------------------------------------------- */
+
+static CK_RV
+CC_C_Initialize(CK_VOID_PTR init_args)
+{
+ ENTER(C_Initialize);
+ PREREQ(!cryptoki_initialized, CKR_CRYPTOKI_ALREADY_INITIALIZED);
+
+ if (init_args != NULL) {
+ CK_C_INITIALIZE_ARGS_PTR args;
+ int supplied_ok;
+
+ /* pReserved must be NULL */
+ args = init_args;
+ PREREQ(!args->pReserved, CKR_ARGUMENTS_BAD);
+
+ /* 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);
+ PREREQ(supplied_ok, CKR_ARGUMENTS_BAD);
+
+ /*
+ * When the CKF_OS_LOCKING_OK flag isn't set and mutex function pointers are supplied
+ * by an application, return an error. DBus must be able to use its own locks.
+ */
+ if(!(args->flags & CKF_OS_LOCKING_OK) && (args->CreateMutex != NULL))
+ RETURN(CKR_CANT_LOCK);
+ }
+
+ if(!global_mutex)
+ {
+ global_mutex = CreateMutex(NULL, FALSE, NULL);
+ if(!global_mutex)
+ RETURN(CKR_CANT_LOCK);
+ }
+
+ cryptoki_initialized = 1;
+
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_Finalize(CK_VOID_PTR pReserved)
+{
+ ENTER(C_Finalize);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ cryptoki_initialized = 0;
+
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_GetInfo(CK_INFO_PTR info)
+{
+ ENTER(C_GetInfo);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(info, CKR_ARGUMENTS_BAD);
+
+ ASSERT(strlen(MANUFACTURER_ID) == 32);
+ ASSERT(strlen(LIBRARY_DESCRIPTION) == 32);
+
+ info->cryptokiVersion.major = CRYPTOKI_VERSION_MAJOR;
+ info->cryptokiVersion.minor = CRYPTOKI_VERSION_MINOR;
+ info->libraryVersion.major = LIBRARY_VERSION_MAJOR;
+ info->libraryVersion.minor = LIBRARY_VERSION_MINOR;
+ info->flags = 0;
+ strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32);
+ strncpy((char*)info->libraryDescription, LIBRARY_DESCRIPTION, 32);
+
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR list)
+{
+ /* This would be a strange call to receive */
+ return C_GetFunctionList(list);
+}
+
+static CK_RV
+CC_C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR slot_list, CK_ULONG_PTR count)
+{
+ ENTER(C_GetSlotList);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(count, CKR_ARGUMENTS_BAD);
+
+ /* Token is always present */
+
+ /* Application only wants to know the number of slots. */
+ if(slot_list == NULL)
+ {
+ *count = 1;
+ RETURN(CKR_OK);
+ }
+
+ if((*count < 1) && (slot_list != NULL))
+ {
+ *count = 1;
+ RETURN(CKR_BUFFER_TOO_SMALL);
+ }
+
+ *count = 1;
+ slot_list[0] = slot_id;
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_GetSlotInfo(CK_SLOT_ID id, CK_SLOT_INFO_PTR info)
+{
+ ENTER(C_GetSlotInfo);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(info, CKR_ARGUMENTS_BAD);
+
+ /* Make sure the slot ID is valid */
+ if(id != slot_id)
+ RETURN(CKR_SLOT_ID_INVALID);
+
+ ASSERT(strlen(SLOT_DESCRIPTION) == 64);
+ ASSERT(strlen(MANUFACTURER_ID) == 32);
+
+ /* Provide information about the slot in the provided buffer */
+ strncpy((char*)info->slotDescription, SLOT_DESCRIPTION, 64);
+ strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32);
+ info->hardwareVersion.major = HARDWARE_VERSION_MAJOR;
+ info->hardwareVersion.minor = HARDWARE_VERSION_MINOR;
+ info->firmwareVersion.major = FIRMWARE_VERSION_MAJOR;
+ info->firmwareVersion.minor = FIRMWARE_VERSION_MINOR;
+
+ /* Token is always present */
+ info->flags = CKF_TOKEN_PRESENT;
+
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_GetTokenInfo(CK_SLOT_ID id, CK_TOKEN_INFO_PTR info)
+{
+ ENTER(C_GetTokenInfo);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(info, CKR_ARGUMENTS_BAD);
+
+ /* Make sure the slot ID is valid */
+ if(id != slot_id)
+ RETURN(CKR_SLOT_ID_INVALID);
+
+ ASSERT(strlen(SLOT_DESCRIPTION) == 64);
+ ASSERT(strlen(MANUFACTURER_ID) == 32);
+ ASSERT(strlen(SLOT_TOKEN_MODEL) == 16);
+ ASSERT(strlen(SLOT_TOKEN_SERIAL) == 16);
+
+ /* Provide information about a token in the provided buffer */
+ strncpy((char*)info->label, SLOT_DESCRIPTION, 32);
+ strncpy((char*)info->manufacturerID, MANUFACTURER_ID, 32);
+ strncpy((char*)info->model, SLOT_TOKEN_MODEL, 16);
+ strncpy((char*)info->serialNumber, SLOT_TOKEN_SERIAL, 16);
+
+ /* Protected authentication path: Windows prompts for it's own PINs */
+ info->flags = CKF_TOKEN_INITIALIZED | CKF_PROTECTED_AUTHENTICATION_PATH;
+ info->ulMaxSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulMaxRwSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulRwSessionCount = CK_EFFECTIVELY_INFINITE;
+ info->ulMaxPinLen = MAX_PIN_LEN;
+ info->ulMinPinLen = MIN_PIN_LEN;
+ info->ulTotalPublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePublicMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulTotalPrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->ulFreePrivateMemory = CK_UNAVAILABLE_INFORMATION;
+ info->hardwareVersion.major = HARDWARE_VERSION_MAJOR;
+ info->hardwareVersion.minor = HARDWARE_VERSION_MINOR;
+ info->firmwareVersion.major = FIRMWARE_VERSION_MAJOR;
+ info->firmwareVersion.minor = FIRMWARE_VERSION_MINOR;
+ memset(info->utcTime, ' ', 16);
+
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_GetMechanismList(CK_SLOT_ID id, CK_MECHANISM_TYPE_PTR mechanism_list,
+ CK_ULONG_PTR count)
+{
+ ENTER(C_GetMechanismList);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(count, CKR_ARGUMENTS_BAD);
+
+ if(id != slot_id)
+ RETURN(CKR_SLOT_ID_INVALID);
+
+ if(mechanism_list == NULL)
+ {
+ *count = 1;
+ RETURN(CKR_OK);
+ }
+
+ if(*count < 1)
+ {
+ *count = 1;
+ RETURN(CKR_BUFFER_TOO_SMALL);
+ }
+
+ mechanism_list[0] = CKM_RSA_PKCS;
+ *count = 1;
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_GetMechanismInfo(CK_SLOT_ID id, CK_MECHANISM_TYPE type,
+ CK_MECHANISM_INFO_PTR info)
+{
+ ENTER(C_GetMechanismInfo);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(info, CKR_ARGUMENTS_BAD);
+
+ if(id != slot_id)
+ RETURN(CKR_SLOT_ID_INVALID);
+
+ /* unsupported mechanism */
+ if(type != CKM_RSA_PKCS)
+ RETURN(CKR_MECHANISM_INVALID);
+
+ info->ulMinKeySize = 384;
+ info->ulMaxKeySize = 16384;
+ info->flags = 0; /* TODO: Choose which we'll implement */
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_InitToken(CK_SLOT_ID slot_id, CK_UTF8CHAR_PTR pin, CK_ULONG pin_len,
+ CK_UTF8CHAR_PTR label)
+{
+ ENTER(C_InitToken);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
+{
+ ENTER(C_WaitForSlotEvent);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /*
+ * PKCS#11 GRAY AREA: What happens when we know we'll *never*
+ * have any slot events, and someone calls us without CKR_DONT_BLOCK?
+ * In case there's a thread dedicated to calling this function in a
+ * loop, we wait 1 seconds when called without CKR_DONT_BLOCK.
+ */
+
+ if(!(flags & CKF_DONT_BLOCK))
+ Sleep(1000);
+
+ RETURN(CKR_NO_EVENT);
+}
+
+static CK_RV
+CC_C_OpenSession(CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR application,
+ CK_NOTIFY notify, CK_SESSION_HANDLE_PTR session)
+{
+ CkCapiSession* sess;
+ CK_RV ret;
+
+ ENTER(C_OpenSession);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ if(id != slot_id)
+ RETURN(CKR_SLOT_ID_INVALID);
+
+ sess = ckcapi_session_create();
+ if(sess == NULL)
+ RETURN(CKR_HOST_MEMORY);
+
+ sess->notify_callback = notify;
+ sess->user_data = application;
+
+ ret = ckcapi_session_register(sess);
+ if(ret == CKR_OK)
+ {
+ /* ID should have been assigned when registering */
+ ASSERT(sess->id > 0);
+ *session = sess->id;
+ }
+ else
+ {
+ ckcapi_session_destroy(sess);
+ }
+
+ RETURN(ret);
+}
+
+static CK_RV
+CC_C_CloseSession(CK_SESSION_HANDLE session)
+{
+ CkCapiSession* sess;
+ CK_RV ret;
+
+ ENTER(C_CloseSession);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* The 'remove' flag removes it from the main session list */
+ ret = ckcapi_session_get_lock_ref(session, 1, &sess);
+ if(ret == CKR_OK)
+ {
+ /* This will unref and possibly destroy the session */
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
+}
+
+static CK_RV
+CC_C_CloseAllSessions(CK_SLOT_ID id)
+{
+ ENTER(C_CloseAllSession);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ if(id != slot_id)
+ RETURN(CKR_SLOT_ID_INVALID);
+
+ ckcapi_session_close_all();
+ RETURN(CKR_OK);
+}
+
+static CK_RV
+CC_C_GetFunctionStatus(CK_SESSION_HANDLE session)
+{
+ ENTER(C_GetFunctionStatus);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ RETURN(CKR_FUNCTION_NOT_PARALLEL);
+}
+
+static CK_RV
+CC_C_CancelFunction(CK_SESSION_HANDLE session)
+{
+ ENTER(C_CancelFunction);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ RETURN(CKR_FUNCTION_NOT_PARALLEL);
+}
+
+static CK_RV
+CC_C_GetSessionInfo(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info)
+{
+ ENTER(C_GetSessionInfo);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ // TODO: Implement
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_InitPIN(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR pin,
+ CK_ULONG pin_len)
+{
+ ENTER(C_InitPIN);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* We don't support this stuff. We don't support 'SO' logins. */
+ RETURN(CKR_USER_NOT_LOGGED_IN);
+}
+
+static CK_RV
+CC_C_SetPIN(CK_SESSION_HANDLE session, CK_UTF8CHAR_PTR old_pin,
+ CK_ULONG old_len, CK_UTF8CHAR_PTR new_pin, CK_ULONG new_len)
+{
+ ENTER(C_SetPIN);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* Not supported, Windows takes care of this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_GetOperationState(CK_SESSION_HANDLE session, CK_BYTE_PTR operation_state,
+ CK_ULONG_PTR operation_state_len)
+{
+ ENTER(C_GetOperationState);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* Nasty, no sirrr */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_SetOperationState);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* Nasty, no sirrr */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_Login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type,
+ CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
+{
+ ENTER(C_Login);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement our local concept of logged in */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_Logout(CK_SESSION_HANDLE session)
+{
+ ENTER(C_Logout);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement our local concept of logged in */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_CreateObject(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR templ,
+ CK_ULONG count, CK_OBJECT_HANDLE_PTR object)
+{
+ ENTER(C_CreateObject);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to support this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_CopyObject(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+ CK_ATTRIBUTE_PTR templ, CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR new_object)
+{
+ ENTER(C_CopyObject);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to support this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+
+static CK_RV
+CC_C_DestroyObject(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object)
+{
+ ENTER(C_DestroyObject);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to support this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_GetObjectSize(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+ CK_ULONG_PTR size)
+{
+ ENTER(C_GetObjectSize);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_GetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+ CK_ATTRIBUTE_PTR templ, CK_ULONG count)
+{
+ CkCapiSession* sess;
+ CkCapiObjectData objdata;
+ CK_RV ret;
+
+ ENTER(C_GetAttributeValue);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(object, CKR_OBJECT_HANDLE_INVALID);
+ PREREQ(!count || templ, CKR_ARGUMENTS_BAD);
+
+ ret = ckcapi_session_get_lock_ref(session, 0, &sess);
+ if(ret == CKR_OK)
+ {
+ ret = ckcapi_object_load_data_for(sess, object, &objdata);
+ if(ret == CKR_OK)
+ {
+ ret = ckcapi_object_data_get_attrs(&objdata, templ, count);
+ ckcapi_object_data_release(&objdata);
+ }
+
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
+}
+
+static CK_RV
+CC_C_SetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
+ CK_ATTRIBUTE_PTR templ, CK_ULONG count)
+{
+ ENTER(C_SetAttributeValue);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_FindObjectsInit(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR templ,
+ CK_ULONG count)
+{
+ CkCapiSession* sess;
+ CK_RV ret;
+
+ ENTER(C_FindObjectsInit);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(!count || templ, CKR_ARGUMENTS_BAD);
+
+ ret = ckcapi_session_get_lock_ref(session, 0, &sess);
+ if(ret == CKR_OK)
+ {
+ ret = ckcapi_session_find_init(sess, templ, count);
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
+}
+
+static CK_RV
+CC_C_FindObjects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects,
+ CK_ULONG max_object_count, CK_ULONG_PTR object_count)
+{
+ CkCapiSession* sess;
+ CK_RV ret;
+
+ ENTER(C_FindObjects);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+ PREREQ(object_count, CKR_ARGUMENTS_BAD);
+ PREREQ(!max_object_count || objects, CKR_ARGUMENTS_BAD);
+
+ ret = ckcapi_session_get_lock_ref(session, 0, &sess);
+ if(ret == CKR_OK)
+ {
+ ret = ckcapi_session_find(sess, objects, max_object_count, object_count);
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
+}
+
+static CK_RV
+CC_C_FindObjectsFinal(CK_SESSION_HANDLE session)
+{
+ CkCapiSession* sess;
+ CK_RV ret;
+
+ ENTER(C_FindObjectsFinal);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ ret = ckcapi_session_get_lock_ref(session, 0, &sess);
+ if(ret == CKR_OK)
+ {
+ ret = ckcapi_session_find_final(sess);
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
+}
+
+static CK_RV
+CC_C_EncryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ ENTER(C_EncryptInit);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_Encrypt);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_EncryptUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_EncryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR last_encrypted_part,
+ CK_ULONG_PTR last_encrypted_part_len)
+{
+ ENTER(C_EncryptFinal);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_DecryptInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ ENTER(C_DecryptInit);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_Decrypt);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_DecryptUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_DecryptFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR pLastPart,
+ CK_ULONG_PTR last_part_len)
+{
+ ENTER(C_DecryptFinal);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_DigestInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism)
+{
+ ENTER(C_DigestInit);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_Digest(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
+ CK_BYTE_PTR digest, CK_ULONG_PTR digest_len)
+{
+ ENTER(C_Digest);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_DigestUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+ ENTER(C_DigestUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_DigestKey(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE key)
+{
+ ENTER(C_DigestKey);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_DigestFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR digest,
+ CK_ULONG_PTR digest_len)
+{
+ ENTER(C_DigestFinal);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_SignInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ ENTER(C_SignInit);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_Sign(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
+ CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
+{
+ ENTER(C_Sign);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_SignUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+ ENTER(C_SignUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_SignFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature,
+ CK_ULONG_PTR signature_len)
+{
+ ENTER(C_SignFinal);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_SignRecoverInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ ENTER(C_SignRecoverInit);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_SignRecover(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
+ CK_BYTE_PTR signature, CK_ULONG_PTR signature_len)
+{
+ ENTER(C_SignRecover);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: Implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_VerifyInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ ENTER(C_VerifyInit);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_Verify(CK_SESSION_HANDLE session, CK_BYTE_PTR data, CK_ULONG data_len,
+ CK_BYTE_PTR signature, CK_ULONG signature_len)
+{
+ ENTER(C_Verify);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_VerifyUpdate(CK_SESSION_HANDLE session, CK_BYTE_PTR part, CK_ULONG part_len)
+{
+ ENTER(C_VerifyUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_VerifyFinal(CK_SESSION_HANDLE session, CK_BYTE_PTR signature,
+ CK_ULONG signature_len)
+{
+ ENTER(C_VerifyFinal);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_VerifyRecoverInit(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE key)
+{
+ ENTER(C_VerifyRecoverInit);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_VerifyRecover(CK_SESSION_HANDLE session, CK_BYTE_PTR signature,
+ CK_ULONG signature_len, CK_BYTE_PTR data, CK_ULONG_PTR data_len)
+{
+ ENTER(C_VerifyRecover);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_DigestEncryptUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_DecryptDigestUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_SignEncryptUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_DecryptVerifyUpdate);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_GenerateKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR templ, CK_ULONG count,
+ CK_OBJECT_HANDLE_PTR key)
+{
+ ENTER(C_GenerateKey);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* Let key generation happen via Windows interfaces */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_GenerateKeyPair(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_ATTRIBUTE_PTR public_key_template, CK_ULONG public_key_attribute_count,
+ CK_ATTRIBUTE_PTR private_key_template, CK_ULONG private_key_attribute_count,
+ CK_OBJECT_HANDLE_PTR public_key, CK_OBJECT_HANDLE_PTR private_key)
+{
+ ENTER(C_GenerateKeyPair);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* Let key generation happen via Windows interfaces */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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)
+{
+ ENTER(C_WrapKey);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_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 templ,
+ CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
+{
+ ENTER(C_UnwrapKey);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* TODO: See if we need to implement this */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_DeriveKey(CK_SESSION_HANDLE session, CK_MECHANISM_PTR mechanism,
+ CK_OBJECT_HANDLE base_key, CK_ATTRIBUTE_PTR templ,
+ CK_ULONG count, CK_OBJECT_HANDLE_PTR key)
+{
+ ENTER(C_DeriveKey);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /* Can't do this with RSA */
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_SeedRandom(CK_SESSION_HANDLE session, CK_BYTE_PTR seed, CK_ULONG seed_len)
+{
+ ENTER(C_SeedRandom);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /*
+ * TODO: Perhaps at some point in the future we may want
+ * to see if we can hook into the Windows RNG
+ */
+
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static CK_RV
+CC_C_GenerateRandom(CK_SESSION_HANDLE session, CK_BYTE_PTR random_data,
+ CK_ULONG random_len)
+{
+ ENTER(C_GenerateRandom);
+ PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ /*
+ * TODO: Perhaps at some point in the future we may want
+ * to see if we can hook into the Windows RNG
+ */
+
+ RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+}
+
+static struct CK_FUNCTION_LIST functionList = {
+ { 2, 11 }, /* version */
+ CC_C_Initialize,
+ CC_C_Finalize,
+ CC_C_GetInfo,
+ CC_C_GetFunctionList,
+ CC_C_GetSlotList,
+ CC_C_GetSlotInfo,
+ CC_C_GetTokenInfo,
+ CC_C_GetMechanismList,
+ CC_C_GetMechanismInfo,
+ CC_C_InitToken,
+ CC_C_InitPIN,
+ CC_C_SetPIN,
+ CC_C_OpenSession,
+ CC_C_CloseSession,
+ CC_C_CloseAllSessions,
+ CC_C_GetSessionInfo,
+ CC_C_GetOperationState,
+ CC_C_SetOperationState,
+ CC_C_Login,
+ CC_C_Logout,
+ CC_C_CreateObject,
+ CC_C_CopyObject,
+ CC_C_DestroyObject,
+ CC_C_GetObjectSize,
+ CC_C_GetAttributeValue,
+ CC_C_SetAttributeValue,
+ CC_C_FindObjectsInit,
+ CC_C_FindObjects,
+ CC_C_FindObjectsFinal,
+ CC_C_EncryptInit,
+ CC_C_Encrypt,
+ CC_C_EncryptUpdate,
+ CC_C_EncryptFinal,
+ CC_C_DecryptInit,
+ CC_C_Decrypt,
+ CC_C_DecryptUpdate,
+ CC_C_DecryptFinal,
+ CC_C_DigestInit,
+ CC_C_Digest,
+ CC_C_DigestUpdate,
+ CC_C_DigestKey,
+ CC_C_DigestFinal,
+ CC_C_SignInit,
+ CC_C_Sign,
+ CC_C_SignUpdate,
+ CC_C_SignFinal,
+ CC_C_SignRecoverInit,
+ CC_C_SignRecover,
+ CC_C_VerifyInit,
+ CC_C_Verify,
+ CC_C_VerifyUpdate,
+ CC_C_VerifyFinal,
+ CC_C_VerifyRecoverInit,
+ CC_C_VerifyRecover,
+ CC_C_DigestEncryptUpdate,
+ CC_C_DecryptDigestUpdate,
+ CC_C_SignEncryptUpdate,
+ CC_C_DecryptVerifyUpdate,
+ CC_C_GenerateKey,
+ CC_C_GenerateKeyPair,
+ CC_C_WrapKey,
+ CC_C_UnwrapKey,
+ CC_C_DeriveKey,
+ CC_C_SeedRandom,
+ CC_C_GenerateRandom,
+ CC_C_GetFunctionStatus,
+ CC_C_CancelFunction,
+ CC_C_WaitForSlotEvent
+};
+
+__declspec(dllexport) CK_RV
+C_GetFunctionList(CK_FUNCTION_LIST_PTR_PTR list)
+{
+ if(!list)
+ return CKR_ARGUMENTS_BAD;
+
+ *list = &functionList;
+ return CKR_OK;
+}