summaryrefslogtreecommitdiff
path: root/ckcapi-token.c
diff options
context:
space:
mode:
Diffstat (limited to 'ckcapi-token.c')
-rw-r--r--ckcapi-token.c230
1 files changed, 230 insertions, 0 deletions
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;
+
+}