diff options
Diffstat (limited to 'ckcapi.c')
-rw-r--r-- | ckcapi.c | 1167 |
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; +} |