From c6d18eea781bc98a362595e2334223b48f41b522 Mon Sep 17 00:00:00 2001 From: Stef Walter Date: Fri, 11 May 2007 17:07:19 +0000 Subject: Add different tokens for different certificate stores. --- ckcapi-token.c | 230 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 230 insertions(+) create mode 100644 ckcapi-token.c (limited to 'ckcapi-token.c') diff --git a/ckcapi-token.c b/ckcapi-token.c new file mode 100644 index 0000000..d7ef75a --- /dev/null +++ b/ckcapi-token.c @@ -0,0 +1,230 @@ + +#include "ckcapi.h" + +static CkCapiArray* object_array = NULL; +static CkCapiHash* object_hash = NULL; + +typedef struct _SlotInfo +{ + const char* capi_store; + const char* display_name; + CK_ULONG slot_flags; +} +SlotInfo; + +static const SlotInfo slot_info[] = { + { "My", "Personal Certificates", CKCAPI_SLOT_TRUSTED }, + { "AddressBook", "Address Book Certificates", 0 }, + { "CA", "Certificate Authorities", CKCAPI_SLOT_CA }, + { "Root", "Root Authorities", CKCAPI_SLOT_TRUSTED | CKCAPI_SLOT_CA }, + { "Trust", "Trust", 0 }, + { "TrustedPeople", "Trusted People", CKCAPI_SLOT_TRUSTED }, + { "AuthRoot", "Auth Root", 0 }, +}; + +unsigned int +ckcapi_token_get_count(void) +{ + return sizeof(slot_info) / sizeof(slot_info[0]); +} + +CK_BBOOL +ckcapi_token_is_valid(CK_SLOT_ID slot) +{ + return slot >= 0 && slot < ckcapi_token_get_count(); +} + +const char* +ckcapi_token_get_display_name(CK_SLOT_ID slot) +{ + ASSERT(ckcapi_token_is_valid(slot)); + ASSERT(slot_info[slot].display_name); + return slot_info[slot].display_name; +} + +const char* +ckcapi_token_get_store_name(CK_SLOT_ID slot) +{ + ASSERT(ckcapi_token_is_valid(slot)); + ASSERT(slot_info[slot].capi_store); + return slot_info[slot].capi_store; +} + +CK_ULONG +ckcapi_token_get_flags(CK_SLOT_ID slot) +{ + ASSERT(ckcapi_token_is_valid(slot)); + return slot_info[slot].slot_flags; +} + +static void +object_free(CkCapiObject* obj) +{ + ASSERT(obj); + ASSERT(obj->obj_funcs); + ASSERT(obj->obj_funcs->release); + (obj->obj_funcs->release)(obj); +} + +void +ckcapi_token_cleanup_all(void) +{ + size_t i; + + ckcapi_lock_global(); + + if(object_hash) + { + ckcapi_hash_free(object_hash, NULL); + object_hash = NULL; + } + + if(object_array) + { + for(i = 1; i < object_array->len; ++i) + { + ASSERT(ckcapi_array_index(object_array, CkCapiObject*, i)); + object_free(ckcapi_array_index(object_array, CkCapiObject*, i)); + } + + ckcapi_array_free(object_array, TRUE); + object_array = NULL; + } + + ckcapi_unlock_global(); +} + +CK_OBJECT_HANDLE +ckcapi_token_get_max_handle(void) +{ + if(!object_array) + return 0; + return object_array->len; +} + +CkCapiObject* +ckcapi_token_lookup_object(CK_SLOT_ID slot, CK_OBJECT_HANDLE obj) +{ + /* This must be called without any locks held */ + + CkCapiObject* ret = NULL; + + ASSERT(slot); + ASSERT(obj > 0); + + ckcapi_lock_global(); + + if(object_array && obj < object_array->len) + ret = ckcapi_array_index(object_array, CkCapiObject*, obj); + + ckcapi_unlock_global(); + + /* Must belong to the right slot */ + if(ret && ret->slot != slot) + ret = NULL; + + return ret; +} + +CK_RV +ckcapi_token_register_object(CK_SLOT_ID slot, CkCapiObject* obj) +{ + CkCapiObject* prev; + CK_RV ret = CKR_OK; + void* key; + size_t klen; + + ASSERT(slot); + ASSERT(obj->id == 0); + ASSERT(obj->unique_key); + ASSERT(obj->unique_len > 0); + + DBG(("registering object")); + + ckcapi_lock_global(); + + if(!object_array) + { + object_array = ckcapi_array_sized_new(0, 1, sizeof(CkCapiObject*), 16); + if(object_array) + { + /* A blank entry for '0' */ + CkCapiObject* blank = NULL; + ckcapi_array_append(object_array, blank); + } + + object_hash = ckcapi_hash_new(); + + + if(!object_array || !object_hash) + { + /* Allocation failed above */ + ret = CKR_HOST_MEMORY; + } + } + + if(ret == CKR_OK) + { + ASSERT(object_array); + ASSERT(object_hash); + + /* The type of object is part of the hash */ + key = obj->unique_key; + klen = obj->unique_len; + + /* Sanity check, in case calcs went wrong somewhere */ + ASSERT(klen < 0xFFFFFF); +/* xxxxx hash function xxxxx */ + /* Look in the hash and find a previous object */ + prev = ckcapi_hash_get(object_hash, key, klen); + if(prev) + { + /* Register it in the previous object's place */ + obj->id = prev->id; + ASSERT(prev->id < object_array->len); + if(ckcapi_hash_set(object_hash, key, klen, obj)) + { + ckcapi_array_index(object_array, CkCapiObject*, obj->id) = obj; + object_free(prev); + DBGO(obj, "found old object id"); + } + else + { + ret = CKR_HOST_MEMORY; + } + + } + else + { + /* Register it at the end of the array */ + obj->id = object_array->len; + ASSERT(obj->id > 0); + if(ckcapi_hash_set(object_hash, key, klen, obj)) + { + if(ckcapi_array_append(object_array, obj)) + { + DBGO(obj, "registered new object id"); + } + else + { + ret = CKR_HOST_MEMORY; + + /* Roll back our addition */ + ckcapi_hash_rem(object_hash, key, klen); + } + } + else + { + ret = CKR_HOST_MEMORY; + } + } + } + + if(ret == CKR_OK) + obj->slot = slot; + + ckcapi_unlock_global(); + + return ret; + +} -- cgit v1.2.3