#include #include #include #include "cryptoki-capi.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) { Session* 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) { Session* 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_find_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) { ENTER(C_GetAttributeValue); PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); /* TODO: Implement this */ RETURN(CKR_FUNCTION_NOT_SUPPORTED); } 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) { Session* sess; CK_RV ret; ENTER(C_FindObjectsInit); PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); PREREQ(!count || templ, CKR_ARGUMENTS_BAD); ret = ckcapi_session_find_lock_ref(session, 0, &sess); if(ret == CKR_OK) { ret = ckcapi_object_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) { Session* 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_find_lock_ref(session, 0, &sess); if(ret == CKR_OK) { ret = ckcapi_object_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) { Session* sess; CK_RV ret; ENTER(C_FindObjectsFinal); PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED); ret = ckcapi_session_find_lock_ref(session, 0, &sess); if(ret == CKR_OK) { ret = ckcapi_objects_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; }