summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2007-04-29 00:20:38 +0000
committerStef Walter <stef@memberwebs.com>2007-04-29 00:20:38 +0000
commit856a057fc0a0807e9c0dd2b11c04e1f1312bdb12 (patch)
tree1286bdecc6beb0d43cfc883016e8d8f834e8d119
parent31366290fcfbb7b51332e41755ba3f0c4b01084f (diff)
Fix tons of bugs and performance issues to better list the certificates.
-rw-r--r--ckcapi-cert.c32
-rw-r--r--ckcapi-object.c42
-rw-r--r--ckcapi-session.c167
-rw-r--r--ckcapi-util.c18
-rw-r--r--ckcapi-util.h4
-rw-r--r--ckcapi.c9
-rw-r--r--ckcapi.h81
7 files changed, 268 insertions, 85 deletions
diff --git a/ckcapi-cert.c b/ckcapi-cert.c
index 672e189..0162983 100644
--- a/ckcapi-cert.c
+++ b/ckcapi-cert.c
@@ -440,7 +440,7 @@ static const CkCapiObjectVtable cert_object_vtable = {
static CK_RV
register_cert_object(CkCapiSession* sess, const char* store, PCCERT_CONTEXT cert,
- CK_OBJECT_HANDLE_PTR id)
+ CkCapiObject** obj)
{
CertObject* cobj;
CK_RV ret;
@@ -485,21 +485,36 @@ register_cert_object(CkCapiSession* sess, const char* store, PCCERT_CONTEXT cert
}
ASSERT(cobj->obj.id != 0);
- *id = cobj->obj.id;
+ *obj = &cobj->obj;
return CKR_OK;
}
+static void
+clear_object_data_for_store(CkCapiSession* sess, CkCapiObject* obj,
+ CkCapiObjectData* data, void* arg)
+{
+ const char* store = (const char*) arg;
+ CertObject *cobj = (CertObject*)obj;
+
+ if(strcmp(cobj->store, store) == 0)
+ ckcapi_session_clear_object_data(sess, obj);
+}
+
CK_RV
ckcapi_cert_find_in_store(CkCapiSession* sess, const char* store_name,
CK_ATTRIBUTE_PTR match, CK_ULONG count, CkCapiArray* arr)
{
PCCERT_CONTEXT cert = NULL;
- CK_OBJECT_HANDLE obj;
+ CkCapiObject* obj;
HCERTSTORE store;
CkCapiObjectData objdata;
DWORD err;
CK_RV ret = CKR_OK;
+
+ /* Clear any loaded data for objects in this store */
+ ckcapi_session_enum_object_data(sess, clear_object_data_for_store, (void*)store_name);
+
store = CertOpenSystemStore((HCRYPTPROV)NULL, store_name);
if(store == NULL)
{
@@ -525,7 +540,16 @@ ckcapi_cert_find_in_store(CkCapiSession* sess, const char* store_name,
if(ret != CKR_OK)
break;
- ckcapi_array_append(arr, obj);
+ ASSERT(obj);
+
+ /* Store away the object data for performance reasons */
+ objdata.data = (void*)CertDuplicateCertificateContext(cert);
+ if(objdata.data) {
+ if(ckcapi_session_set_object_data(sess, obj, &objdata) != CKR_OK)
+ CertFreeCertificateContext((PCCERT_CONTEXT)objdata.data);
+ }
+
+ ckcapi_array_append(arr, obj->id);
}
}
diff --git a/ckcapi-object.c b/ckcapi-object.c
index da3a467..49da8eb 100644
--- a/ckcapi-object.c
+++ b/ckcapi-object.c
@@ -26,7 +26,7 @@ ckcapi_object_clear_all(void)
if(object_hash)
{
- ckcapi_hash_free(object_hash);
+ ckcapi_hash_free(object_hash, NULL);
object_hash = NULL;
}
@@ -45,6 +45,14 @@ ckcapi_object_clear_all(void)
ckcapi_unlock_global();
}
+CK_OBJECT_HANDLE
+ckcapi_object_get_max_handle(void)
+{
+ if(!object_array)
+ return 0;
+ return object_array->len;
+}
+
CkCapiObject*
ckcapi_object_lookup(CkCapiSession* sess, CK_OBJECT_HANDLE obj)
{
@@ -165,38 +173,6 @@ ckcapi_object_register(CkCapiSession* sess, CkCapiObject* obj)
}
-CK_RV
-ckcapi_object_load_data(CkCapiObject* obj, CkCapiObjectData* objdata)
-{
- ASSERT(obj);
- ASSERT(obj->id);
- ASSERT(obj->obj_funcs.load_data);
-
- memset(objdata, 0, sizeof(*objdata));
- return (obj->obj_funcs.load_data)(obj, objdata);
-}
-
-void
-ckcapi_object_data_release(CkCapiObjectData* objdata)
-{
- ASSERT(objdata->data_funcs.release);
- (objdata->data_funcs.release)(objdata->data);
- memset(objdata, 0, sizeof(*objdata));
-}
-
-CK_RV
-ckcapi_object_load_data_for(CkCapiSession* sess, CK_OBJECT_HANDLE hand,
- CkCapiObjectData* objdata)
-{
- CkCapiObject* obj;
-
- obj = ckcapi_object_lookup(sess, hand);
- if(!obj)
- return CKR_OBJECT_HANDLE_INVALID;
-
- return ckcapi_object_load_data(obj, objdata);
-}
-
enum
{
DATA_UNKNOWN = 0,
diff --git a/ckcapi-session.c b/ckcapi-session.c
index ce7e9d2..9f9a6e6 100644
--- a/ckcapi-session.c
+++ b/ckcapi-session.c
@@ -11,6 +11,13 @@ typedef struct _SessionList {
/* These are protected by global_mutex */
static SessionList the_sessions = { NULL, 0 };
+static void
+object_data_release(CkCapiObjectData* objdata)
+{
+ ASSERT(objdata->data_funcs.release);
+ (objdata->data_funcs.release)(objdata->data);
+ free(objdata);
+}
CkCapiSession*
ckcapi_session_create(void)
@@ -19,9 +26,15 @@ ckcapi_session_create(void)
if(!sess)
return NULL;
+ sess->object_data = ckcapi_hash_new();
+ if(!sess->object_data) {
+ free(sess);
+ return NULL;
+ }
+
sess->mutex = CreateMutex(NULL, FALSE, NULL);
- if(!sess->mutex)
- {
+ if(!sess->mutex) {
+ ckcapi_hash_free(sess->object_data, NULL);
free(sess);
return NULL;
}
@@ -132,6 +145,10 @@ ckcapi_session_destroy(CkCapiSession* sess)
ASSERT(sess->operation_data == NULL);
ASSERT(sess->operation_cancel == NULL);
+ /* Make all the object adat go away */
+ ASSERT(sess->object_data != NULL);
+ ckcapi_hash_free(sess->object_data, object_data_release);
+
/* And make the mutex go away */
ASSERT(sess->mutex != NULL);
CloseHandle(sess->mutex);
@@ -328,6 +345,150 @@ ckcapi_session_close_all()
}
/* ----------------------------------------------------------------------------
+ * OBJECT DATA
+ */
+
+CK_RV
+ckcapi_object_load_data(CkCapiObject* obj, CkCapiObjectData* objdata)
+{
+ ASSERT(obj);
+ ASSERT(obj->id);
+ ASSERT(obj->obj_funcs.load_data);
+
+ memset(objdata, 0, sizeof(*objdata));
+ return (obj->obj_funcs.load_data)(obj, objdata);
+}
+
+CK_RV
+ckcapi_session_get_object_data(CkCapiSession* sess, CkCapiObject* obj,
+ CkCapiObjectData** objdata)
+{
+ CK_OBJECT_HANDLE id;
+ CkCapiObjectData* newdata;
+ CK_RV ret;
+
+ ASSERT(sess);
+ ASSERT(sess->object_data);
+ ASSERT(obj);
+ ASSERT(obj->obj_funcs.load_data);
+ ASSERT(objdata);
+
+ id = obj->id;
+
+ *objdata = ckcapi_hash_get(sess->object_data, &id, sizeof(id));
+ if(*objdata)
+ return CKR_OK;
+
+ newdata = calloc(sizeof(CkCapiObjectData), 1);
+ if(!newdata)
+ return CKR_HOST_MEMORY;
+
+ newdata->object = id;
+ ret = (obj->obj_funcs.load_data)(obj, newdata);
+ if(ret != CKR_OK) {
+ free(newdata);
+ return ret;
+ }
+
+ if(!ckcapi_hash_set(sess->object_data, &newdata->object,
+ sizeof(newdata->object), newdata)) {
+ object_data_release(newdata);
+ return CKR_HOST_MEMORY;
+ }
+
+ *objdata = newdata;
+ return CKR_OK;
+}
+
+void
+ckcapi_session_clear_object_data(CkCapiSession* sess, CkCapiObject* obj)
+{
+ CkCapiObjectData* objdata;
+
+ ASSERT(sess);
+ ASSERT(sess->object_data);
+ ASSERT(obj);
+
+ objdata = (CkCapiObjectData*)ckcapi_hash_rem(sess->object_data, &obj->id, sizeof(obj->id));
+ if(objdata)
+ object_data_release(objdata);
+}
+
+void
+ckcapi_session_enum_object_data(CkCapiSession* sess,
+ CkCapiEnumObjectData enum_func, void* arg)
+{
+ CK_OBJECT_HANDLE i, max;
+ CkCapiObject* obj;
+ CkCapiObjectData* objdata;
+
+ ASSERT(sess);
+ ASSERT(sess->object_data);
+ ASSERT(enum_func);
+
+ max = ckcapi_object_get_max_handle();
+ for(i = 0; i < max; ++i)
+ {
+ objdata = (CkCapiObjectData*)ckcapi_hash_get(sess->object_data, &i, sizeof(i));
+ if(!objdata)
+ continue;
+
+ obj = ckcapi_object_lookup (sess, i);
+ if(!obj)
+ continue;
+
+ (enum_func)(sess, obj, objdata, arg);
+ }
+}
+
+CK_RV
+ckcapi_session_get_object_data_for(CkCapiSession* sess, CK_OBJECT_HANDLE hand,
+ CkCapiObjectData** objdata)
+{
+ CkCapiObject* obj;
+
+ obj = ckcapi_object_lookup(sess, hand);
+ if(!obj)
+ return CKR_OBJECT_HANDLE_INVALID;
+
+ return ckcapi_session_get_object_data(sess, obj, objdata);
+}
+
+CK_RV
+ckcapi_session_set_object_data(CkCapiSession* sess, CkCapiObject* obj,
+ const CkCapiObjectData* objdata)
+{
+ CkCapiObjectData* newdata;
+ CkCapiObjectData* prev;
+
+ ASSERT(obj);
+ ASSERT(sess);
+ ASSERT(sess->object_data);
+ ASSERT(objdata);
+
+ newdata = calloc(sizeof(CkCapiObjectData), 1);
+ if(!newdata)
+ return CKR_HOST_MEMORY;
+
+ newdata->object = obj->id;
+ newdata->data = objdata->data;
+ newdata->data_funcs = objdata->data_funcs;
+
+ prev = ckcapi_hash_rem(sess->object_data, &obj->id, sizeof(obj->id));
+ if(prev)
+ object_data_release(prev);
+
+ if(!ckcapi_hash_set(sess->object_data, &newdata->object,
+ sizeof(newdata->object), newdata)) {
+ free(newdata);
+ return CKR_HOST_MEMORY;
+ }
+
+ return CKR_OK;
+}
+
+
+/* ----------------------------------------------------------------------------
* FIND OPERATION
*/
@@ -420,7 +581,7 @@ purge_duplicate_ulongs(CkCapiArray* arr)
}
}
- ckcapi_hash_free(checks);
+ ckcapi_hash_free(checks, NULL);
}
CK_RV
diff --git a/ckcapi-util.c b/ckcapi-util.c
index 3c587ac..7fd1d1d 100644
--- a/ckcapi-util.c
+++ b/ckcapi-util.c
@@ -202,7 +202,7 @@ typedef struct _HashEntry
unsigned int hash;
const void* key;
size_t klen;
- const void* val;
+ void* val;
}
HashEntry;
@@ -252,17 +252,19 @@ ckcapi_hash_new()
}
void
-ckcapi_hash_free(CkCapiHash* ht)
+ckcapi_hash_free(CkCapiHash* ht, CkCapiHashDestroy destroy_func)
{
HashEntry* he;
HashEntry* next;
size_t i;
- for(i = 0; i < ht->max; ++i)
+ for(i = 0; i <= ht->max; ++i)
{
for(he = ht->array[i]; he; )
{
next = he->next;
+ if(destroy_func)
+ (destroy_func)((void*)he->val);
free(he);
he = next;
}
@@ -290,13 +292,13 @@ expand_array(CkCapiHash* ht)
if(!new_array)
return 0;
- for(i = 0; i < ht->max; ++i)
+ for(i = 0; i <= ht->max; ++i)
{
for(he = ht->array[i]; he; he = he->next)
{
- unsigned int i = he->hash & new_max;
- he->next = new_array[i];
- new_array[i] = he;
+ unsigned int j = he->hash & new_max;
+ he->next = new_array[j];
+ new_array[j] = he;
}
}
@@ -318,7 +320,7 @@ expand_array(CkCapiHash* ht)
*/
static HashEntry**
-find_entry(CkCapiHash* ht, const void* key, size_t klen, const void* val)
+find_entry(CkCapiHash* ht, const void* key, size_t klen, void* val)
{
HashEntry** hep;
HashEntry* he;
diff --git a/ckcapi-util.h b/ckcapi-util.h
index ea3d5e2..84aa9bd 100644
--- a/ckcapi-util.h
+++ b/ckcapi-util.h
@@ -44,8 +44,10 @@ void ckcapi_array_remove_range (CkCapiArray* array, unsigned int index,
struct _CkCapiHash;
typedef struct _CkCapiHash CkCapiHash;
+typedef void (*CkCapiHashDestroy)(void* val);
+
CkCapiHash* ckcapi_hash_new();
-void ckcapi_hash_free(CkCapiHash* ht);
+void ckcapi_hash_free(CkCapiHash* ht, CkCapiHashDestroy destroy_func);
size_t ckcapi_hash_count(CkCapiHash* ht);
void* ckcapi_hash_get(CkCapiHash* ht, const void* key, size_t klen);
int ckcapi_hash_set(CkCapiHash* ht, const void* key, size_t klen, void* val);
diff --git a/ckcapi.c b/ckcapi.c
index a1243b8..0bed282 100644
--- a/ckcapi.c
+++ b/ckcapi.c
@@ -582,7 +582,7 @@ CC_C_GetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
CK_ATTRIBUTE_PTR templ, CK_ULONG count)
{
CkCapiSession* sess;
- CkCapiObjectData objdata;
+ CkCapiObjectData* objdata;
CK_RV ret;
ENTER(C_GetAttributeValue);
@@ -593,12 +593,9 @@ CC_C_GetAttributeValue(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE object,
ret = ckcapi_session_get_lock_ref(session, 0, &sess);
if(ret == CKR_OK)
{
- ret = ckcapi_object_load_data_for(sess, object, &objdata);
+ ret = ckcapi_session_get_object_data_for(sess, object, &objdata);
if(ret == CKR_OK)
- {
- ret = ckcapi_object_data_get_attrs(&objdata, templ, count);
- ckcapi_object_data_release(&objdata);
- }
+ ret = ckcapi_object_data_get_attrs(objdata, templ, count);
ckcapi_session_unref_unlock(sess);
}
diff --git a/ckcapi.h b/ckcapi.h
index e1a0301..d6ee27b 100644
--- a/ckcapi.h
+++ b/ckcapi.h
@@ -18,6 +18,9 @@
struct _CkCapiObject;
struct _CkCapiSession;
+typedef struct _CkCapiObject CkCapiObject;
+typedef struct _CkCapiSession CkCapiSession;
+
/* ------------------------------------------------------------------
* cryptoki-capi.c
*/
@@ -30,6 +33,32 @@ void ckcapi_lock_global(void);
void ckcapi_unlock_global(void);
CK_RV ckcapi_winerr_to_ckr (DWORD werr);
+/* object data ------------------- */
+
+typedef CK_RV (*CkCapiGetAttribute)(void* obj, CK_ATTRIBUTE_TYPE type,
+ CK_VOID_PTR data, CK_ULONG_PTR len);
+
+typedef void (*CkCapiRelease)(void* value);
+
+typedef struct _CkCapiObjectDataVtable
+{
+ CkCapiGetAttribute get_bool;
+ CkCapiGetAttribute get_ulong;
+ CkCapiGetAttribute get_bytes;
+ CkCapiGetAttribute get_date;
+ CkCapiRelease release;
+}
+CkCapiObjectDataVtable;
+
+typedef struct _CkCapiObjectData
+{
+ CK_OBJECT_HANDLE object;
+ void* data;
+ CkCapiObjectDataVtable data_funcs;
+}
+CkCapiObjectData;
+
+
/* ------------------------------------------------------------------
* cryptoki-capi-session.c
*/
@@ -52,6 +81,8 @@ typedef struct _CkCapiSession
void* operation_data; /* Data for this operation */
CkCapiSessionCancel operation_cancel; /* Callback to cancel operation when necessary */
+ CkCapiHash* object_data;
+
CK_NOTIFY notify_callback; /* Application specified callback */
CK_VOID_PTR user_data; /* Argument for above */
@@ -75,6 +106,22 @@ CK_RV ckcapi_session_find (CkCapiSession* sess, CK_OBJECT_HANDLE_PTR objects
CK_ULONG max_object_count, CK_ULONG_PTR object_count);
CK_RV ckcapi_session_find_final (CkCapiSession* sess);
+CK_RV ckcapi_session_get_object_data (CkCapiSession* sess, CkCapiObject* obj,
+ CkCapiObjectData** objdata);
+
+CK_RV ckcapi_session_get_object_data_for (CkCapiSession* sess, CK_OBJECT_HANDLE hand,
+ CkCapiObjectData** objdata);
+
+CK_RV ckcapi_session_set_object_data (CkCapiSession* sess, CkCapiObject* obj,
+ const CkCapiObjectData* objdata);
+
+void ckcapi_session_clear_object_data (CkCapiSession* sess, CkCapiObject* obj);
+
+typedef void (*CkCapiEnumObjectData)(CkCapiSession* sess, CkCapiObject* obj, CkCapiObjectData* data, void* arg);
+
+void ckcapi_session_enum_object_data (CkCapiSession* sess, CkCapiEnumObjectData enum_func, void* arg);
+
+
/* ------------------------------------------------------------------
* ckcapi-object.c
*/
@@ -86,27 +133,6 @@ enum
OBJECT_BUILTIN = 2
};
-typedef CK_RV (*CkCapiGetAttribute)(void* obj, CK_ATTRIBUTE_TYPE type,
- CK_VOID_PTR data, CK_ULONG_PTR len);
-
-typedef void (*CkCapiRelease)(void* value);
-
-typedef struct _CkCapiObjectDataVtable
-{
- CkCapiGetAttribute get_bool;
- CkCapiGetAttribute get_ulong;
- CkCapiGetAttribute get_bytes;
- CkCapiGetAttribute get_date;
- CkCapiRelease release;
-}
-CkCapiObjectDataVtable;
-
-typedef struct _CkCapiObjectData
-{
- void* data;
- CkCapiObjectDataVtable data_funcs;
-}
-CkCapiObjectData;
typedef CK_RV (*CkCapiPurge)(struct _CkCapiObject* obj);
typedef CK_RV (*CkCapiLoadData)(struct _CkCapiObject* obj, CkCapiObjectData* objdata);
@@ -138,7 +164,7 @@ CkCapiObjectVtable;
#define UNIQUE_KEY_VAR_LEN(obj, first, last, len) \
((((char*)&((obj->last))) - ((char*)&((obj->first)))) + (len))
-typedef struct _CkCapiObject
+struct _CkCapiObject
{
CK_OBJECT_HANDLE id;
@@ -146,22 +172,19 @@ typedef struct _CkCapiObject
CkCapiObjectVtable obj_funcs;
void* unique_key;
size_t unique_len;
-}
-CkCapiObject;
+};
#define DBGO(obj, msg) \
ckcapi_debug("O%d: %s", (obj) ? (obj)->id : 0, (msg))
+CK_OBJECT_HANDLE ckcapi_object_get_max_handle (void);
+
CkCapiObject* ckcapi_object_lookup (CkCapiSession* sess, CK_OBJECT_HANDLE obj);
CK_RV ckcapi_object_register (CkCapiSession* sess, CkCapiObject* obj);
void ckcapi_object_clear_all (void);
-CK_RV ckcapi_object_load_data (CkCapiObject* obj, CkCapiObjectData* objdata);
-
-CK_RV ckcapi_object_load_data_for (CkCapiSession* sess, CK_OBJECT_HANDLE hand,
- CkCapiObjectData* objdata);
CK_BBOOL ckcapi_object_data_match (CkCapiObjectData* objdata,
CK_ATTRIBUTE_PTR matches, CK_ULONG count);
@@ -172,8 +195,6 @@ CK_BBOOL ckcapi_object_data_match_attr (CkCapiObjectData* objdata,
CK_RV ckcapi_object_data_get_attrs (CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attrs,
CK_ULONG count);
-void ckcapi_object_data_release (CkCapiObjectData* objdata);
-
/* -------------------------------------------------------------------
* ckcapi-cert.c
*/