summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2007-04-27 20:37:40 +0000
committerStef Walter <stef@memberwebs.com>2007-04-27 20:37:40 +0000
commit4928a4bff079c140d261cb3fefdc07c60c0bdebf (patch)
treec5258568f5e417f0a2c9d19099c6ed057cfd73bd
parent3d8ed01d2653c45e52821ba00ac72099a12600e1 (diff)
A bunch more changes, that implement almost complete find and get support.
-rw-r--r--ckcapi-cert.c456
-rw-r--r--ckcapi-object.c744
-rw-r--r--ckcapi-session.c168
-rw-r--r--ckcapi-util.c336
-rw-r--r--ckcapi-util.h42
-rw-r--r--ckcapi.c (renamed from cryptoki-capi.c)48
-rw-r--r--ckcapi.dsp (renamed from cryptoki-capi.dsp)18
-rw-r--r--ckcapi.dsw (renamed from cryptoki-capi.dsw)0
-rw-r--r--ckcapi.h160
-rw-r--r--cryptoki-capi.h99
10 files changed, 1161 insertions, 910 deletions
diff --git a/ckcapi-cert.c b/ckcapi-cert.c
index d1b9b32..7436307 100644
--- a/ckcapi-cert.c
+++ b/ckcapi-cert.c
@@ -1,18 +1,25 @@
+#include "ckcapi.h"
-typedef struct _CertRef
-{
-
+#include <memory.h>
+#include <wincrypt.h>
+
+typedef struct _CertObject
+{
+ CkCapiObject obj;
+ const char* store;
+ BYTE* key_id;
+ DWORD key_id_len;
}
-CertRef;
+CertObject;
static CK_RV
copy_static_data(CK_VOID_PTR val, CK_ULONG_PTR len,
CK_VOID_PTR data, DWORD cb)
{
if(cb == 0)
- return CKR_CANCEL;
+ return CKR_ATTRIBUTE_TYPE_INVALID;
if(!val)
{
@@ -39,7 +46,6 @@ cert_bool_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
CK_BBOOL val;
ASSERT(obj);
- ASSERT(ret);
switch(type)
{
@@ -79,7 +85,7 @@ cert_bool_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
/* TODO: Implement */
default:
- return CK_CANCEL;
+ return CKR_ATTRIBUTE_TYPE_INVALID;
};
return copy_static_data(data, len, &val, sizeof(CK_BBOOL));
@@ -93,7 +99,6 @@ cert_ulong_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
CK_ULONG val;
ASSERT(obj);
- ASSERT(ret);
switch(type)
{
@@ -102,7 +107,7 @@ cert_ulong_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
* Object class.
* - Always CKO_CERTIFICATE for certificates.
*/
- case CKA_OBJECT_CLASS:
+ case CKA_CLASS:
val = CKO_CERTIFICATE;
break;
@@ -123,7 +128,7 @@ cert_ulong_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
/* TODO: Implement */
default:
- return CK_CANCEL;
+ return CKR_ATTRIBUTE_TYPE_INVALID;
};
if(*len < sizeof(CK_ULONG))
@@ -137,218 +142,6 @@ cert_ulong_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
static CK_RV
cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
- CkCapiAttrAction action, CK_ATTRIBUTE_PTR attr)
-{
- PCCERT_CONTEXT cert = (PCCERT_CONTEXT)obj;
- CK_VOID_PTR val;
- CK_ULONG len;
- size_t maxa;
- BOOL r;
-
-
- DWORD size = *len;
-
- int allocated = 0;
-
- ASSERT(obj);
- ASSERT(ret);
-
- /*
- * We don't need to retrieve the full value of any of
- * these fields if we don't have to. Just calculate
- * the max amount to retrieve, so we can compare, or
- * notify caller of real length.
- */
- maxa = attr->ulValueLen;
- if(maxa == 0)
- maxa = 4;
- /* Keep dynamic allocations under a 64k. */
- if(maxa > 0xFFFF)
- maxa = 0xFFFF;
-
- switch(type)
- {
-
- /*
- * Description of the object.
- * - We use CAPI's CERT_FRIENDLY_NAME_PROP_ID property,
- * converted into UTF8.
- * - Yes this is slow, but this is not really a property
- * that's searched on or retrieved intensively.
- */
- case CKA_LABEL:
- {
- DWORD size = maxa * sizeof(WCHAR);
- WCHAR* utf16;
-xxxxxx, this is wrong, second call may be needed
- /* Get the UTF16 string, a worst case of twice as long as UTF8 */
- WCHAR* utf16 = alloca(size);
- r = CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
- utf16, &size);
- if(!r)
- {
- DWORD err = GetLastError();
- if(err == ERROR_MORE_DATA)
- {
- /* Truncate long names */
- utf16[maxa - 1] = 0;
- r = TRUE;
- }
- else if (err != CRYPT_E_NOT_FOUND)
- {
- return ckcapi_winerr_to_ckr(err);
- }
- }
-
- if(r)
- {
- /* Convert it */
- if(!ckcapi_util_utf16_to_utf8(utf16, &val, &len))
- SetLastError(ERROR_NOT_ENOUGH_MEMORY);
- allocated = 1;
- }
- else
- {
- /* We always like to have a decent label */
- val = "Unnamed Certificate";
- len = strlen(val);
- allocated = 0;
- }
- }
- break;
-
- /*
- * A byte array unique to this certificate. The CKA_ID of
- * matching certificates and private keys should match.
- * Should match the key identifier in an X.509v3 certificate.
- *
- * We use CAPI's CERT_KEY_IDENTIFIER_PROP_ID property directly.
- */
- case CKA_ID:
- {
- BOOL r;
-
- val = alloca(size);
- r = CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
- val, &size);
- if(!r)
- {
- DWORD err = GetLastError();
- if(err == CRYPT_E_NOT_FOUND)
- return CKR_CANCEL;
- if(err != ERROR_MORE_DATA)
- return ckcapi_winerr_to_ckr(err);
- }
-
- *len = size;
- }
- break;
-
- /*
- * DER-encoding of the certificate subject name.
- *
- * We use CAPI's CERT_CONTEXT pCertInfo->Subject field
- * directly.
- */
- case CKA_SUBJECT:
- if(cert->pCertInfo->Subject.pbData == NULL ||
- cert->pCertInfo->Subject.cbData == 0)
- return CKR_CANCEL;
- val = cert->pCertInfo->Subject.pbData;
- len = cert->pCertInfo->Subject.cbData;
- break;
-
- /*
- * DER-encoding of the certificate issuer name.
- *
- * We use CAPI's CERT_CONTEXT pCertInfo->Issuer field
- * directly.
- */
- case CKA_ISSUER:
- if(cert->pCertInfo->Issuer.pbData == NULL ||
- cert->pCertInfo->Issuer.cbData == 0)
- return CKR_CANCEL;
- val = cert->pCertInfo->Issuer.pbData;
- len = cert->pCertInfo->Issuer.cbData;
- break;
-
- /*
- * DER-encoding of the certificate serial number.
- *
- * TODO:
- * BOOL rc = CryptEncodeObject(X509_ASN_ENCODING,
- * X509_MULTI_BYTE_INTEGER,
- * &certContext->pCertInfo->SerialNumber,
- * co->derSerial,
- * &size);
- */
- case CKA_SERIAL_NUMBER:
- {
- BOOL r;
- DWORD size = *len;
-
- r = CryptEncodeObject(X509_ASN_ENCODING, X509_MULTI_BYTE_INTEGER,
- &cert->pCertInfo->SerialNumber, val, *len);
- if(!r)
- {
- DWORD err = GetLastError();
- if(err == ERROR_FILE_NOT_FOUND)
- return CKR_GENERAL_ERROR;
- if(err != ERROR_MORE_DATA)
- return ckcapi_winerr_to_ckr(err);
- }
-
- len = size;
- }
- break;
-
- /*
- * BER-encoding of the full certificate.
- *
- * We use CAPI's CERT_CONTEXT pbCertEncoded field directly.
- */
- case CKA_VALUE:
- if(cert->pbCertEncoded == NULL ||
- cert->cbCertEncoded == 0)
- return CKR_CANCEL;
- val = cert->pbCertEncoded;
- len = cert->cbCertEncoded;
- break;
- break;
-
- /*
- * If CKA_VALUE not specified, this is where the full
- * certificate can be found.
- *
- * We don't support this. All our certificates are present
- * in full.
- */
- case CKA_URL:
- return CKR_CANCEL;
-
- /*
- * Checksum
- * - TODO: Work out what to do here
- */
- case CKA_CHECKSUM:
- break;
-
- /*
- * TODO: Should we support these?
- */
- CKA_HASH_OF_SUBJECT_PUBLIC_KEY
- CKA_HASH_OF_ISSUER_PUBLIC_KEY
- break;
-
- /* Not supported */
-
- default:
- break
- };
-};
-
-static CK_RV
-cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
CK_VOID_PTR data, CK_ULONG_PTR len)
{
PCCERT_CONTEXT cert = (PCCERT_CONTEXT)obj;
@@ -372,8 +165,8 @@ cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
/* Get the UTF16 string, a worst case of twice as long as UTF8 */
(*len) *= sizeof(WCHAR);
- utf16 = alloca(*len);
- r = CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
+ utf16 = _alloca(*len);
+ if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
utf16, (DWORD*)len))
{
DWORD err = GetLastError();
@@ -384,7 +177,9 @@ cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
}
/* Convert the data into the buffer */
- return ckcapi_util_utf16_to_utf8(utf16, data, len));
+ if(!WideCharToMultiByte(CP_UTF8, 0, utf16, -1, data, *len, "?", NULL))
+ return ckcapi_winerr_to_ckr(GetLastError());
+ return CKR_OK;
}
break;
@@ -402,7 +197,7 @@ cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
{
DWORD err = GetLastError();
if(err == CRYPT_E_NOT_FOUND)
- return CKR_CANCEL;
+ return CKR_ATTRIBUTE_TYPE_INVALID;
return ckcapi_winerr_to_ckr(err);
}
}
@@ -474,27 +269,28 @@ cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
* Checksum
* - TODO: Work out what to do here
*/
- case CKA_CHECKSUM:
+ case CKA_CHECK_VALUE:
break;
/*
* TODO: Should we support these?
*/
- CKA_HASH_OF_SUBJECT_PUBLIC_KEY
- CKA_HASH_OF_ISSUER_PUBLIC_KEY
+ case CKA_HASH_OF_SUBJECT_PUBLIC_KEY:
+ case CKA_HASH_OF_ISSUER_PUBLIC_KEY:
break;
/* Not supported */
default:
- break
+ break;
};
- return CKR_CANCEL;
+ return CKR_ATTRIBUTE_TYPE_INVALID;
}
-static xxx
-cert_date_attribute()
+static CK_RV
+cert_date_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
+ CK_VOID_PTR data, CK_ULONG_PTR len)
{
switch(type)
{
@@ -505,7 +301,6 @@ cert_date_attribute()
* pCertInfo->NotBefore;
*/
case CKA_START_DATE:
- xxxx;
break;
/*
@@ -514,7 +309,198 @@ cert_date_attribute()
* pCertInfo->NotBefore;
*/
case CKA_END_DATE:
- xxxx;
break;
};
+
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+}
+
+static void
+cert_release(void* data)
+{
+ PCCERT_CONTEXT cert = (PCCERT_CONTEXT)data;
+ ASSERT(cert);
+ CertFreeCertificateContext(cert);
+}
+
+static const CkCapiObjectDataVtable cert_objdata_vtable = {
+ cert_bool_attribute,
+ cert_ulong_attribute,
+ cert_bytes_attribute,
+ cert_date_attribute,
+ cert_release,
+};
+
+static CK_RV
+cert_load(CkCapiObject* obj, CkCapiObjectData* objdata)
+{
+ CertObject* cobj = (CertObject*)obj;
+ HCERTSTORE store;
+ PCCERT_CONTEXT cert;
+ CRYPT_HASH_BLOB blob;
+
+ ASSERT(cobj);
+ ASSERT(objdata);
+
+ ASSERT(cobj->store);
+ store = CertOpenSystemStore((HCRYPTPROV)NULL, cobj->store);
+ if(!store)
+ return ckcapi_winerr_to_ckr(GetLastError());
+
+ ASSERT(cobj->key_id);
+ ASSERT(cobj->key_id_len);
+ blob.pbData = cobj->key_id;
+ blob.cbData = cobj->key_id_len;
+
+ cert = CertFindCertificateInStore(store, X509_ASN_ENCODING | PKCS_7_ASN_ENCODING,
+ 0, CERT_FIND_KEY_IDENTIFIER, &blob, NULL);
+
+ CertCloseStore(store, 0);
+
+ if(!cert)
+ {
+ DWORD err = GetLastError();
+
+ /* TODO: Is this right for a deleted certificate? */
+ ASSERT(err != E_INVALIDARG);
+ if(err == CRYPT_E_NOT_FOUND)
+ return CKR_OBJECT_HANDLE_INVALID;
+ else
+ return ckcapi_winerr_to_ckr(GetLastError());
+ }
+
+ objdata->data = (void*)cert;
+ objdata->data_funcs = cert_objdata_vtable;
+ return CKR_OK;
+}
+
+
+static void
+cert_object_release(void* data)
+{
+ CertObject* cobj = (CertObject*)data;
+ ASSERT(cobj);
+ free(cobj);
+}
+
+static const CkCapiObjectVtable cert_object_vtable = {
+ cert_load,
+ cert_object_release,
+};
+
+static CK_RV
+register_cert_object(CkCapiSession* sess, const char* store, PCCERT_CONTEXT cert,
+ CK_OBJECT_HANDLE_PTR id)
+{
+ CertObject* cobj;
+ CK_RV ret;
+ DWORD len;
+
+ if(!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID, NULL, &len))
+ {
+ DBG(("cannot get certificate key identifier: %d", GetLastError()));
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+
+ cobj = calloc(sizeof(CertObject) + len, 1);
+ if(!cobj)
+ return CKR_HOST_MEMORY;
+
+ /* Store keyid in allocated area after CertObject */
+ cobj->key_id = (BYTE*)(cobj + 1);
+ cobj->key_id_len = len;
+
+ if(!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID,
+ cobj->key_id, &(cobj->key_id_len)))
+ {
+ DBG(("cannot read certificate key identifier: %d", GetLastError()));
+ free(cobj);
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ }
+
+ cobj->store = store;
+ cobj->obj.id = 0;
+ cobj->obj.unique_key = cobj->key_id;
+ cobj->obj.unique_len = cobj->key_id_len;
+ cobj->obj.obj_funcs = cert_object_vtable;
+ cobj->obj.data_funcs = cert_objdata_vtable;
+
+ ret = ckcapi_object_register(sess, &(cobj->obj));
+ if(ret != CKR_OK)
+ {
+ free(cobj);
+ return ret;
+ }
+
+ ASSERT(cobj->obj.id != 0);
+ *id = cobj->obj.id;
+ return CKR_OK;
+}
+
+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;
+ HCERTSTORE store;
+ CkCapiObjectData objdata;
+ DWORD err;
+ CK_RV ret = CKR_OK;
+
+ store = CertOpenSystemStore((HCRYPTPROV)NULL, store_name);
+ if(store == NULL)
+ {
+ err = GetLastError();
+
+ /* Store not found, we don't care */
+ if(err == ERROR_FILE_NOT_FOUND)
+ return CKR_OK;
+
+ else
+ return ckcapi_winerr_to_ckr(err);
+ }
+
+ /* Match each certificate */
+ while((cert = CertEnumCertificatesInStore(store, cert)) != NULL)
+ {
+ objdata.data = (void*)cert;
+ objdata.data_funcs = cert_objdata_vtable;
+
+ if(ckcapi_object_data_match(&objdata, match, count))
+ {
+ ret = register_cert_object(sess, store, cert, &obj);
+ if(ret != CKR_OK)
+ break;
+
+ ckcapi_array_append(arr, obj);
+ }
+ }
+
+ ASSERT(store);
+ CertCloseStore(store, 0);
+
+ return ret;
+}
+
+CK_RV
+ckcapi_cert_find_all(CkCapiSession* sess, CK_ATTRIBUTE_PTR match,
+ CK_ULONG count, CkCapiArray* arr)
+{
+ CK_RV ret;
+
+ ret = ckcapi_cert_find_in_store(sess, "My", match, count, arr);
+ if(ret == CKR_OK)
+ ret = ckcapi_cert_find_in_store(sess, "AddressBook", match, count, arr);
+ if(ret == CKR_OK)
+ ret = ckcapi_cert_find_in_store(sess, "CA", match, count, arr);
+ if(ret == CKR_OK)
+ ret = ckcapi_cert_find_in_store(sess, "Root", match, count, arr);
+ if(ret == CKR_OK)
+ ret = ckcapi_cert_find_in_store(sess, "Trust", match, count, arr);
+ if(ret == CKR_OK)
+ ret = ckcapi_cert_find_in_store(sess, "TrustedPeople", match, count, arr);
+ if(ret == CKR_OK)
+ ret = ckcapi_cert_find_in_store(sess, "AuthRoot", match, count, arr);
+ return ret;
}
diff --git a/ckcapi-object.c b/ckcapi-object.c
index 531ad2f..c02c365 100644
--- a/ckcapi-object.c
+++ b/ckcapi-object.c
@@ -1,9 +1,165 @@
-#include "cryptoki-capi.h"
+#include "ckcapi.h"
+
+#include <memory.h>
#include <wtypes.h>
#include <wincrypt.h>
+static CkCapiArray* object_array = NULL;
+static CkCapiHash* object_hash = NULL;
+
+static void
+object_free(CkCapiObject* obj)
+{
+ ASSERT(obj);
+ ASSERT(obj->obj_funcs.release);
+ (obj->obj_funcs.release)(obj);
+}
+
+CkCapiObject*
+ckcapi_object_lookup(CkCapiSession* sess, CK_OBJECT_HANDLE obj)
+{
+ /* This must be called without any locks held */
+
+ CkCapiObject* ret = NULL;
+
+ ASSERT(sess);
+ ASSERT(obj > 0);
+
+ ckcapi_lock_global();
+
+ if(object_array && obj < object_array->len)
+ ret = ckcapi_array_index(object_array, CkCapiObject*, obj);
+
+ ckcapi_unlock_global();
+
+ return ret;
+}
+
+CK_RV
+ckcapi_object_register(CkCapiSession* sess, CkCapiObject* obj)
+{
+ CkCapiObject* prev;
+ CK_RV ret = CKR_OK;
+
+ ASSERT(sess);
+ ASSERT(obj->id == 0);
+ ASSERT(obj->unique_key);
+ ASSERT(obj->unique_len);
+
+ DBGS(sess, "registering new session");
+
+ 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);
+
+ /* Look in the hash and find a previous object */
+ prev = ckcapi_hash_get(object_hash, obj->unique_key, obj->unique_len);
+ 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, obj->unique_key, obj->unique_len, 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, obj->unique_key, obj->unique_len, 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, obj->unique_key, obj->unique_len);
+ }
+ }
+ else
+ {
+ ret = CKR_HOST_MEMORY;
+ }
+ }
+ }
+
+ ckcapi_unlock_global();
+
+ return ret;
+
+}
+
+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,
@@ -13,7 +169,6 @@ enum
DATA_BYTES
};
-
int
attribute_data_type(CK_ATTRIBUTE_TYPE type)
{
@@ -27,7 +182,7 @@ attribute_data_type(CK_ATTRIBUTE_TYPE type)
case CKA_MODULUS_BITS:
case CKA_PRIME_BITS:
case CKA_SUBPRIME_BITS:
- case CKA_SUB_PRIME_BITS:
+ /* case CKA_SUB_PRIME_BITS: */
case CKA_VALUE_BITS:
case CKA_VALUE_LEN:
case CKA_KEY_GEN_MECHANISM:
@@ -40,7 +195,7 @@ attribute_data_type(CK_ATTRIBUTE_TYPE type)
case CKA_BITS_PER_PIXEL:
case CKA_MECHANISM_TYPE:
case CKA_JAVA_MIDP_SECURITY_DOMAIN:
- return DATA_ULONG:
+ return DATA_ULONG;
// CK_BBOOL attribute types
case CKA_TOKEN:
@@ -56,7 +211,7 @@ attribute_data_type(CK_ATTRIBUTE_TYPE type)
case CKA_NEVER_EXTRACTABLE:
case CKA_ALWAYS_SENSITIVE:
case CKA_WRAP_WITH_TRUSTED:
- case CKA_ALWAYS_AUTHENTICATE
+ case CKA_ALWAYS_AUTHENTICATE:
case CKA_ENCRYPT:
case CKA_WRAP:
case CKA_VERIFY:
@@ -96,7 +251,7 @@ attribute_data_type(CK_ATTRIBUTE_TYPE type)
case CKA_SUBPRIME:
case CKA_BASE:
case CKA_ECDSA_PARAMS:
- case CKA_EC_PARAMS:
+ /* case CKA_EC_PARAMS: */
case CKA_EC_POINT:
case CKA_CHAR_SETS:
case CKA_ENCODING_METHODS:
@@ -120,536 +275,133 @@ attribute_data_type(CK_ATTRIBUTE_TYPE type)
};
}
-CK_RV
-attribute_fill(CK_ATTRIBUTE_PTR attr, CK_ATTRIBUTE_TYPE type,
- CK_VOID_PTR* val, CK_ULONG len)
+CK_BBOOL
+ckcapi_object_data_match_attr(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR match)
{
- ASSERT(attr);
- ASSERT(val);
- ASSERT(len);
-
- attr->type = type;
+ CK_VOID_PTR value;
+ CK_ULONG len;
+ CK_RV rv;
+ int dtype;
- if(attr->pValue && attr->ulValueLen < len)
- {
- attr->ulValueLen = len;
- return CKR_BUFFER_TOO_SMALL;
- }
-
- else if(!attr->pValue)
- {
- attr->ulValueLen = len;
- return CKR_OK;
- }
+ ASSERT(match);
+ ASSERT(objdata && objdata->data);
- else
- {
- memcpy(attr->pValue, &val, len);
- attr->ulValueLen = len;
- return CKR_OK;
- }
-}
+ /* Get the data type of the attribute */
+ dtype = attribute_data_type(match->type);
+ if(dtype == DATA_UNKNOWN)
+ return CK_FALSE;
-CK_RV
-attribute_match(CK_ATTRIBUTE_PTR attr, CK_ATTRIBUTE_TYPE type,
- CK_VOID_PTR* val, CK_ULONG len)
-{
- ASSERT(attr);
- ASSERT(val);
- ASSERT(len);
-
- if(attr->pValue && attr->ulValueLen == len &&
- memcmp(attr->pValue, &val, len);
- return CKR_OK;
- return CKR_CANCEL;
-}
+ /* We only do byte matching */
+ if(match->pValue == NULL)
+ return CK_FALSE;
-/* --------------------------------------------------------------------------
- * CERTIFICATES
- */
+ /* Only load as much data as is needed */
+ value = _alloca(match->ulValueLen > 4 ? match->ulValueLen : 4);
+ len = match->ulValueLen;
-static CK_RV
-cert_bool_attribute(CK_ATTRIBUTE_TYPE type, PCCERT_CONTEXT cert,
- CK_ATTRIBUTE_PTR attr, CK_BBOOL fill)
-{
- CK_BBOOL val;
- switch(type)
+ switch(dtype)
{
- /*
- * Resides on the token
- * - Always true for CAPI objects.
- */
- case CKA_TOKEN:
- val = CK_TRUE;
+ case DATA_BOOL:
+ rv = (objdata->data_funcs.get_bool)(objdata->data, match->type, value, &len);
break;
-
- /*
- * Private vs. Public object.
- * - Always false for certificates.
- */
- case CKA_PRIVATE:
- val = CK_FALSE;
+ case DATA_ULONG:
+ rv = (objdata->data_funcs.get_ulong)(objdata->data, match->type, value, &len);
break;
-
- /*
- * If object can be modified.
- * - Currently always false. In the future with additional
- * functionality this may change.
- */
- case CKA_MODIFIABLE:
- val = CK_FALSE;
+ case DATA_BYTES:
+ rv = (objdata->data_funcs.get_bytes)(objdata->data, match->type, value, &len);
break;
-
- /*
- * Whether the certificate can be trusted for the application
- * in which it was created.
- * - Use CertGetCertificateChain to build up a chain
- * for this certificate, and then look in the CERT_CHAIN_CONTEXT
- * TrustStatus field.
- */
- case CKA_TRUSTED:
- /* TODO: Implement */
-
- default:
- return CK_CANCEL;
- };
-
- if(fill)
- return attribute_fill(attr, type, &val, sizeof(CK_BBOOL));
- else
- return attribute_match(attr, type, &val, sizeof(CK_BBOOL));
-}
-
-static CK_RV
-cert_ulong_attribute(CK_ATTRIBUTE_TYPE type, PCCERT_CONTEXT cert,
- CK_ATTRIBUTE_PTR attr, CK_BBOOL fill)
-{
- CK_ULONG val;
- switch(type)
- {
-
- /*
- * Object class.
- * - Always CKO_CERTIFICATE for certificates.
- */
- case CKA_OBJECT_CLASS:
- val = CKO_CERTIFICATE;
+ case DATA_DATE:
+ rv = (objdata->data_funcs.get_date)(objdata->data, match->type, value, &len);
break;
-
- /*
- * Type of certificate.
- * - Always X509.
- */
- case CKA_CERTIFICATE_TYPE:
- val = CKC_X_509;
- break;
-
- /*
- * Whether a CA, user certificate, other.
- * - Get certificate szOID_ENHANCED_KEY_USAGE
- * extension or CERT_CTL_PROP_ID and look into CTL_USAGE structure.
- */
- case CKA_CERTIFICATE_CATEGORY:
- /* TODO: Implement */
-
default:
- return CK_CANCEL;
- };
-
- if(fill)
- return attribute_fill(attr, type, &val, sizeof(CK_ULONG));
- else
- return attribute_match(attr, type, &val, sizeof(CK_ULONG));
-}
-
-static CK_RV
-cert_bytes_attribute(CK_ATTRIBUTE_TYPE type, PCCERT_CONTEXT cert,
- CK_ATTRIBUTE_PTR attr, CK_BBOOL fill)
-{
- switch(type)
- {
-
- /*
- * Description of the object.
- * - We use CAPI's CERT_FRIENDLY_NAME_PROP_ID property,
- * converted into UTF8.
- */
- case CKA_LABEL:
- xxxxx
- break;
-
- /*
- * A byte array unique to this certificate. The CKA_ID of
- * matching certificates and private keys should match.
- * Should match the key identifier in an X.509v3 certificate.
- *
- * We use CAPI's CERT_KEY_IDENTIFIER_PROP_ID property directly.
- */
- case CKA_ID:
- xxxxx
+ ASSERT(0 && "unrecognized type");
break;
-
- /*
- * DER-encoding of the certificate subject name.
- *
- * We use CAPI's CERT_CONTEXT pCertInfo->Subject field
- * directly.
- */
- case CKA_SUBJECT:
- xxxxx
- break;
-
- /*
- * DER-encoding of the certificate issuer name.
- *
- * We use CAPI's CERT_CONTEXT pCertInfo->Issuer field
- * directly.
- */
- case CKA_ISSUER:
- xxxxx
- break;
-
- /*
- * DER-encoding of the certificate serial number.
- *
- * TODO:
- * BOOL rc = CryptEncodeObject(X509_ASN_ENCODING,
- * X509_MULTI_BYTE_INTEGER,
- * &certContext->pCertInfo->SerialNumber,
- * co->derSerial,
- * &size);
- */
- case CKA_SERIAL_NUMBER:
- xxxxx
- break;
-
- /*
- * BER-encoding of the full certificate.
- *
- * We use CAPI's CERT_CONTEXT pbCertEncoded field directly.
- */
- case CKA_VALUE:
- xxxxx
- break;
-
- /*
- * If CKA_VALUE not specified, this is where the full
- * certificate can be found.
- *
- * We don't support this. All our certificates are present
- * in full.
- */
- case CKA_URL:
- break;
-
- /*
- * Checksum
- * - TODO: Work out what to do here
- */
- case CKA_CHECKSUM:
- break;
-
- /*
- * TODO: Should we support these?
- */
- CKA_HASH_OF_SUBJECT_PUBLIC_KEY
- CKA_HASH_OF_ISSUER_PUBLIC_KEY
- break;
-
- /* Not supported */
-
- default:
- break
};
-};
-static xxx
-cert_date_attribute()
-{
- switch(type)
- {
-
- /*
- * Start date for the certificate.
- * - TODO: Work out where to get this.
- */
- pCertInfo->NotBefore;
- case CKA_START_DATE:
- xxxx;
- break;
-
- /*
- * End date for the certificate.
- * - TODO: Work out where to get this.
- */
- pCertInfo->NotAfter;
- case CKA_END_DATE:
- xxxx;
- break;
- };
-}
-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
-
-static CK_RV
-cert_ulong_attribute(CK_ATTRIBUTE_TYPE type, PCCERT_CONTEXT cert,
- CK_ATTRIBUTE_PTR attr)
-{
- CK_ATTRIBUTE_PTR ret;
- CK_BBOOL val;
-
- switch(type)
- {
- case CKA_TOKEN:
- val = CK_TRUE;
- break;
- case CKA_PRIVATE:
- case CKA_MODIFIABLE:
- val = CK_FALSE;
- break;
- };
-
- /* If attr is initialized, just do a match */
- if(attr.type == type)
- {
- if(attr->pValue && attr->ulValueLen == sizeof(CK_BBOOL) &&
- memcmp(attr->pValue, &val, sizeof(CK_BBOOL));
- return CKR_OK;
- return CKR_CANCEL;
- }
-
- /* Otherwise fill in the value */
- else
- {
- return prep_attribute(attr, type, &val, sizeof(CK_BBOOL);
- }
-}
-
-static CK_ATTRIBUTE_PTR
-cert_load_attribute(CK_ATTRIBUTE_TYPE type, PCCERT_CONTEXT cert)
-{
- CK_BBOOL vval = CK_FALSE;
- CK_ULONG uval = 0;
- CK_VOID_PTR val;
- CK_ULONG n_val;
-
- switch(type)
- {
- case CKA_CLASS:
- uval = CKO_CERTIFICATE;
- break;
- case CKA_TOKEN;
-
- }
-}
-
-static CK_BBOOL
-cert_match_attr(CK_ATTRIBUTE_PTR match, PCCERT_CONTEXT cert)
-{
- CK_ATTRIBUTE_PTR attr;
- CK_BBOOL ret;
-
- attr = cert_load_attribute(match->type, cert);
- if(!attr)
+ /* Value is longer than this one */
+ if(rv == CKR_BUFFER_TOO_SMALL)
+ return CK_FALSE;
+ if(rv != CKR_OK)
return CK_FALSE;
- ret = (attr->ulValueLen == match->ulValueLen &&
- memcmp(attr->pValue, match->pValue, attr->ulValueLen) == 0);
-
- free_attribute(attr);
- return ret;
+ return (match->ulValueLen == len &&
+ memcmp(match->pValue, value, len) == 0);
}
-static CK_BBOOL
-cert_match(CK_ATTRIBUTE_PTR matches, CK_ULONG count,
- PCCERT_CONTEXT cert)
+CK_BBOOL
+ckcapi_object_data_match(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR matches,
+ CK_ULONG count)
{
CK_ULONG i;
for(i = 0; i < count; ++i)
{
- if(!cert_match_attr(&match[i], cert))
+ if(!ckcapi_object_data_match_attr(objdata, &matches[i]))
return CK_FALSE;
}
return CK_TRUE;
}
-static CK_RV
-gather_store_certs(const char* store_name, Array* arr,
- CK_ATTRIBUTE_PTR match, CK_ULONG count)
+CK_RV
+ckcapi_object_data_get_attrs(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attrs,
+ CK_ULONG count)
{
- PCCERT_CONTEXT cert = NULL;
- CK_OBJECT_HANDLE obj;
- HCERTSTORE store;
- DWORD err;
- CK_RV ret = CKR_OK;
-
- store = CertOpenSystemStore((HCRYPTPROV)NULL, store_name);
- if(store == NULL)
- {
- err = GetLastError();
-
- /* Store not found, we don't care */
- if(err == ERROR_FILE_NOT_FOUND)
- return CKR_OK;
+ CK_ULONG i;
+ CK_RV rv, ret = CKR_OK;
- else
- return ckcapi_winerr_to_ckr(err);
- }
+ ASSERT(objdata && objdata->data);
+ ASSERT(!count || attrs);
- /* Match each certificate */
- while((cert = CertEnumCertificatesInStore(store, cert)) != NULL)
+ for(i = 0; i < count; ++i)
{
- if(match_cert(match, count, cert))
+ /* Get the data type of the attribute */
+ switch(attribute_data_type(attrs[i].type))
{
- obj = register_cert(store, cert);
- if(!obj)
- {
- ret = CKR_HOST_MEMORY;
- break;
- }
-
- ckcapi_util_array_append(arr, obj);
+ case DATA_BOOL:
+ rv = (objdata->data_funcs.get_bool)(objdata->data, attrs[i].type,
+ attrs[i].pValue, &attrs[i].ulValueLen);
+ break;
+ case DATA_ULONG:
+ rv = (objdata->data_funcs.get_ulong)(objdata->data, attrs[i].type,
+ attrs[i].pValue, &attrs[i].ulValueLen);
+ break;
+ case DATA_BYTES:
+ rv = (objdata->data_funcs.get_bytes)(objdata->data, attrs[i].type,
+ attrs[i].pValue, &attrs[i].ulValueLen);
+ break;
+ case DATA_DATE:
+ rv = (objdata->data_funcs.get_date)(objdata->data, attrs[i].type,
+ attrs[i].pValue, &attrs[i].ulValueLen);
+ break;
+ case DATA_UNKNOWN:
+ rv = CKR_ATTRIBUTE_TYPE_INVALID;
+ break;
+ default:
+ ASSERT(0 && "unrecognized type");
+ break;
+ };
+
+ /* Not an error if they were just requesting the size */
+ if(rv == CKR_BUFFER_TOO_SMALL)
+ {
+ if(!attrs[i].pValue)
+ rv = CKR_OK;
}
- }
- ASSERT(store);
- CertCloseStore(store, 0);
-
- return ret;
-}
-
-/* ----------------------------------------------------------------------------
- * FIND
- */
-
-BOOL
-get_ulong_attribute(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR templ,
- CK_ULONG count, CK_ULONG* val)
-{
- CK_ULONG i;
-
- ASSERT(val);
- ASSERT(!count || templ);
+ /* Is it a fatal error? */
+ else if(rv != CKR_ATTRIBUTE_TYPE_INVALID)
+ {
+ ret = rv;
+ break;
+ }
- for(i = 0; i < count; ++i)
- {
- if(templ[i].type == type)
+ /* Transfer any non-fatal errors outward */
+ if(rv != CKR_OK && ret == CKR_OK)
{
- *val = *((CK_ULONG*)templ[i].pValue);
- return TRUE;
+ ret = rv;
}
}
- return FALSE;
-}
-
-
-
-
-CK_RV
-gather_objects(Array* arr, CK_ATTRIBUTE_PTR match, CK_ULONG count)
-{
- CK_OBJECT_CLASS ocls = CK_INVALID_HANDLE;
- CK_RV ret = CKR_OK;
-
- get_ulong_attribute(CKA_CLASS, match, count, &ocls);
- switch(ocls)
- {
- /* all different classes */
- case CK_INVALID_HANDLE:
- case CKO_CERTIFICATE:
- ret = gather_certificates(arr, match, count);
- break;
- case CKO_PUBLIC_KEY:
- case CKO_PRIVATE_KEY:
- default:
- break;
- };
-
return ret;
-}
-
-void
-cleanup_find_operation(Session* sess)
-{
- ASSERT(sess->operation_type == OPERATION_FIND);
- if(sess->operation_data)
- ckcapi_util_array_free((Array*)sess->operation_data, TRUE);
- sess->operation_type = OPERATION_NONE;
- sess->operation_data = NULL;
- sess->operation_cancel = NULL;
-}
-
-CK_RV
-ckcapi_object_find_init(Session* sess, CK_ATTRIBUTE_PTR match,
- CK_ULONG count)
-{
- Array* arr;
- CK_RV ret;
-
- ASSERT(sess);
- ASSERT(!count || match);
-
- if(sess->operation_type != OPERATION_NONE)
- return CKR_OPERATION_ACTIVE;
-
- arr = ckcapi_util_array_new(0, 1, sizeof(CK_OBJECT_HANDLE));
- if(!arr)
- return CKR_HOST_MEMORY;
-
- ret = gather_objects(arr, match, count);
- if(ret != CKR_OK)
- {
- ckcapi_util_array_free(arr, TRUE);
- return ret;
- }
-
- sess->operation_type = OPERATION_FIND;
- sess->operation_data = arr;
- sess->operation_cancel = cleanup_find_operation;
-
- return CKR_OK;
-}
-
-CK_RV
-ckcapi_object_find(Session* sess, CK_OBJECT_HANDLE_PTR objects,
- CK_ULONG max_object_count, CK_ULONG_PTR object_count)
-{
- Array* arr;
- size_t i;
-
- ASSERT(sess);
- ASSERT(object_count);
- ASSERT(!max_object_count || objects);
-
- if(sess->operation_type != OPERATION_FIND)
- return CKR_OPERATION_NOT_INITIALIZED;
-
- if(!max_object_count)
- {
- *object_count = 0;
- return CKR_OK;
- }
-
- arr = (Array*)sess->operation_data;
- *object_count = (max_object_count > arr->len ? arr->len : max_object_count);
- for(i = 0; i < *object_count; ++i)
- objects[i] = ckcapi_util_array_index(arr, CK_OBJECT_HANDLE, i);
- ckcapi_util_array_remove_range(arr, 0, *object_count);
-
- return CKR_OK;
-}
-
-CK_RV
-ckcapi_objects_find_final(Session* sess)
-{
- ASSERT(sess);
-
- if(sess->operation_type != OPERATION_FIND)
- return CKR_OPERATION_NOT_INITIALIZED;
-
- cleanup_find_operation(sess);
- return CKR_OK;
-}
-
+} \ No newline at end of file
diff --git a/ckcapi-session.c b/ckcapi-session.c
index dc700c1..1076fbd 100644
--- a/ckcapi-session.c
+++ b/ckcapi-session.c
@@ -1,10 +1,10 @@
#include <stdlib.h>
-#include "cryptoki-capi.h"
+#include "ckcapi.h"
typedef struct _SessionList {
- Session **list;
+ CkCapiSession **list;
size_t lmax;
} SessionList;
@@ -12,10 +12,10 @@ typedef struct _SessionList {
static SessionList the_sessions = { NULL, 0 };
-Session*
+CkCapiSession*
ckcapi_session_create(void)
{
- Session* sess = calloc(1, sizeof(Session));
+ CkCapiSession* sess = calloc(1, sizeof(CkCapiSession));
if(!sess)
return NULL;
@@ -31,7 +31,7 @@ ckcapi_session_create(void)
}
CK_RV
-ckcapi_session_register(Session* sess)
+ckcapi_session_register(CkCapiSession* sess)
{
CK_ULONG id = 0;
CK_RV ret = CKR_OK;
@@ -67,13 +67,13 @@ ckcapi_session_register(Session* sess)
/* Couldn't find a handle, reallocate */
if(id == 0)
{
- Session** buf;
+ CkCapiSession** buf;
size_t oldmax, newmax;
oldmax = the_sessions.lmax;
newmax = oldmax + 16;
- buf = realloc(the_sessions.list, newmax * sizeof(Session*));
+ buf = realloc(the_sessions.list, newmax * sizeof(CkCapiSession*));
if(!buf)
{
DBGS(sess, ("couldn't allocate session list, out of memory"));
@@ -116,7 +116,7 @@ ckcapi_session_register(Session* sess)
}
void
-ckcapi_session_destroy(Session* sess)
+ckcapi_session_destroy(CkCapiSession* sess)
{
ASSERT(sess);
ASSERT(sess->refs == 0);
@@ -141,10 +141,10 @@ ckcapi_session_destroy(Session* sess)
}
static CK_RV
-find_lock_ref_internal(SessionList* sessions, CK_SESSION_HANDLE id,
- int remove, Session** sess_ret)
+lock_ref_internal(SessionList* sessions, CK_SESSION_HANDLE id,
+ int remove, CkCapiSession** sess_ret)
{
- Session *sess;
+ CkCapiSession *sess;
DWORD r;
ASSERT(sessions);
@@ -185,7 +185,7 @@ find_lock_ref_internal(SessionList* sessions, CK_SESSION_HANDLE id,
}
}
- /* Lock the CallSession */
+ /* Lock the CallCkCapiSession */
r = WaitForSingleObject(sess->mutex, INFINITE);
ASSERT(r == WAIT_OBJECT_0);
@@ -225,7 +225,7 @@ find_lock_ref_internal(SessionList* sessions, CK_SESSION_HANDLE id,
}
CK_RV
-ckcapi_session_find_lock_ref(CK_ULONG id, int remove, Session **sess)
+ckcapi_session_get_lock_ref(CK_ULONG id, int remove, CkCapiSession **sess)
{
/* This must be called without any locks held */
@@ -241,7 +241,7 @@ ckcapi_session_find_lock_ref(CK_ULONG id, int remove, Session **sess)
ckcapi_lock_global();
- ret = find_lock_ref_internal (&the_sessions, id, remove, sess);
+ ret = lock_ref_internal (&the_sessions, id, remove, sess);
ckcapi_unlock_global();
@@ -249,9 +249,9 @@ ckcapi_session_find_lock_ref(CK_ULONG id, int remove, Session **sess)
}
void
-ckcapi_session_unref_unlock(Session* sess)
+ckcapi_session_unref_unlock(CkCapiSession* sess)
{
- /* The CallSession must be locked at this point */
+ /* The CallCkCapiSession must be locked at this point */
int refs;
BOOL r;
@@ -284,7 +284,7 @@ ckcapi_session_close_all()
/* This must be called without any locks held */
SessionList sessions;
- Session *sess;
+ CkCapiSession *sess;
size_t i;
CK_RV ret;
@@ -313,7 +313,7 @@ ckcapi_session_close_all()
if(!sessions.list[i])
continue;
- ret = find_lock_ref_internal (&sessions, i, 1, &sess);
+ ret = lock_ref_internal (&sessions, i, 1, &sess);
ASSERT(ret == CKR_OK);
ckcapi_session_unref_unlock(sess);
@@ -327,3 +327,135 @@ ckcapi_session_close_all()
}
}
+/* ----------------------------------------------------------------------------
+ * FIND OPERATION
+ */
+
+static BOOL
+get_ulong_attribute(CK_ATTRIBUTE_TYPE type, CK_ATTRIBUTE_PTR templ,
+ CK_ULONG count, CK_ULONG* val)
+{
+ CK_ULONG i;
+
+ ASSERT(val);
+ ASSERT(!count || templ);
+
+ for(i = 0; i < count; ++i)
+ {
+ if(templ[i].type == type)
+ {
+ *val = *((CK_ULONG*)templ[i].pValue);
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+static CK_RV
+gather_objects(CkCapiSession* sess, CK_ATTRIBUTE_PTR match,
+ CK_ULONG count, CkCapiArray* arr)
+{
+ CK_OBJECT_CLASS ocls = CK_INVALID_HANDLE;
+ CK_RV ret = CKR_OK;
+
+ get_ulong_attribute(CKA_CLASS, match, count, &ocls);
+ switch(ocls)
+ {
+ /* all different classes */
+ case CK_INVALID_HANDLE:
+ case CKO_CERTIFICATE:
+ ret = ckcapi_cert_find_all(sess, match, count, arr);
+ break;
+ case CKO_PUBLIC_KEY:
+ case CKO_PRIVATE_KEY:
+ default:
+ break;
+ };
+
+ return ret;
+}
+
+void
+cleanup_find_operation(CkCapiSession* sess)
+{
+ ASSERT(sess->operation_type == OPERATION_FIND);
+ if(sess->operation_data)
+ ckcapi_array_free((CkCapiArray*)sess->operation_data, TRUE);
+ sess->operation_type = OPERATION_NONE;
+ sess->operation_data = NULL;
+ sess->operation_cancel = NULL;
+}
+
+CK_RV
+ckcapi_session_find_init(CkCapiSession* sess, CK_ATTRIBUTE_PTR match,
+ CK_ULONG count)
+{
+ CkCapiArray* arr;
+ CK_RV ret;
+
+ ASSERT(sess);
+ ASSERT(!count || match);
+
+ if(sess->operation_type != OPERATION_NONE)
+ return CKR_OPERATION_ACTIVE;
+
+ arr = ckcapi_array_new(0, 1, sizeof(CK_OBJECT_HANDLE));
+ if(!arr)
+ return CKR_HOST_MEMORY;
+
+ ret = gather_objects(sess, match, count, arr);
+ if(ret != CKR_OK)
+ {
+ ckcapi_array_free(arr, TRUE);
+ return ret;
+ }
+
+ sess->operation_type = OPERATION_FIND;
+ sess->operation_data = arr;
+ sess->operation_cancel = cleanup_find_operation;
+
+ return CKR_OK;
+}
+
+CK_RV
+ckcapi_session_find(CkCapiSession* sess, CK_OBJECT_HANDLE_PTR objects,
+ CK_ULONG max_object_count, CK_ULONG_PTR object_count)
+{
+ CkCapiArray* arr;
+ size_t i;
+
+ ASSERT(sess);
+ ASSERT(object_count);
+ ASSERT(!max_object_count || objects);
+
+ if(sess->operation_type != OPERATION_FIND)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ if(!max_object_count)
+ {
+ *object_count = 0;
+ return CKR_OK;
+ }
+
+ arr = (CkCapiArray*)sess->operation_data;
+ *object_count = (max_object_count > arr->len ? arr->len : max_object_count);
+ for(i = 0; i < *object_count; ++i)
+ objects[i] = ckcapi_array_index(arr, CK_OBJECT_HANDLE, i);
+ ckcapi_array_remove_range(arr, 0, *object_count);
+
+ return CKR_OK;
+}
+
+CK_RV
+ckcapi_session_find_final(CkCapiSession* sess)
+{
+ ASSERT(sess);
+
+ if(sess->operation_type != OPERATION_FIND)
+ return CKR_OPERATION_NOT_INITIALIZED;
+
+ cleanup_find_operation(sess);
+ return CKR_OK;
+}
+
diff --git a/ckcapi-util.c b/ckcapi-util.c
index d8d182b..6969c2e 100644
--- a/ckcapi-util.c
+++ b/ckcapi-util.c
@@ -1,17 +1,16 @@
-#include "cryptoki-capi-util.h"
+#include "ckcapi-util.h"
+#include <sys/types.h>
+#include <stdlib.h>
#include <string.h>
-
-
-
#define MIN_ARRAY_SIZE 16
typedef struct _RealArray
{
- Array pub;
+ CkCapiArray pub;
size_t alloc;
size_t elt_size;
int zero_terminated : 1;
@@ -44,7 +43,7 @@ maybe_expand(RealArray *array, size_t len)
array->zero_terminated);
if(want_alloc > array->alloc)
- {
+ {
want_alloc = nearest_pow(want_alloc);
want_alloc = want_alloc > MIN_ARRAY_SIZE ? want_alloc : MIN_ARRAY_SIZE;
@@ -53,21 +52,21 @@ maybe_expand(RealArray *array, size_t len)
return 0;
array->pub.data = mem;
- memset((char*)array->pub.data + array->alloc, 0, want_alloc - array->alloc);
+ memset((char*)array->pub.data + array->alloc, 0, want_alloc - array->alloc);
array->alloc = want_alloc;
}
return 1;
}
-Array*
-ckcapi_util_array_new(int zero_terminated, int clear, size_t elt_size)
+CkCapiArray*
+ckcapi_array_new(int zero_terminated, int clear, size_t elt_size)
{
- return ckcapi_util_array_sized_new(zero_terminated, clear, elt_size, 0);
+ return ckcapi_array_sized_new(zero_terminated, clear, elt_size, 0);
}
-Array*
-ckcapi_util_array_sized_new(int zero_terminated, int clear, size_t elt_size,
+CkCapiArray*
+ckcapi_array_sized_new(int zero_terminated, int clear, size_t elt_size,
size_t reserved_size)
{
RealArray *array = malloc(sizeof(RealArray));
@@ -87,11 +86,11 @@ ckcapi_util_array_sized_new(int zero_terminated, int clear, size_t elt_size,
array_zero_terminate(array);
}
- return (Array*)array;
+ return (CkCapiArray*)array;
}
void*
-ckcapi_util_array_free(Array* array, int free_segment)
+ckcapi_array_free(CkCapiArray* array, int free_segment)
{
void* segment;
@@ -99,10 +98,10 @@ ckcapi_util_array_free(Array* array, int free_segment)
return NULL;
if(free_segment)
- {
+ {
free(array->data);
segment = NULL;
- }
+ }
else
segment = array->data;
@@ -111,7 +110,7 @@ ckcapi_util_array_free(Array* array, int free_segment)
}
int
-ckcapi_util_array_append_vals(Array* parray, const void* data, size_t len)
+ckcapi_array_append_vals(CkCapiArray* parray, const void* data, size_t len)
{
RealArray* array = (RealArray*)parray;
if(!maybe_expand(array, len))
@@ -127,7 +126,7 @@ ckcapi_util_array_append_vals(Array* parray, const void* data, size_t len)
}
void
-ckcapi_util_array_remove_index(Array* parray, unsigned int index)
+ckcapi_array_remove_index(CkCapiArray* parray, unsigned int index)
{
RealArray* array = (RealArray*)parray;
@@ -136,16 +135,16 @@ ckcapi_util_array_remove_index(Array* parray, unsigned int index)
if(index != array->pub.len - 1)
memmove(array_elt_pos (array, index),
- array_elt_pos (array, index + 1),
- array_elt_len (array, array->pub.len - index - 1));
+ array_elt_pos (array, index + 1),
+ array_elt_len (array, array->pub.len - index - 1));
array->pub.len -= 1;
- array_elt_zero (array, array->pub.len, 1);
+ array_elt_zero (array, array->pub.len, 1);
}
void
-ckcapi_util_array_remove_range(Array* parray, unsigned int index, size_t length)
+ckcapi_array_remove_range(CkCapiArray* parray, unsigned int index, size_t length)
{
RealArray *array = (RealArray*)parray;
@@ -162,6 +161,297 @@ ckcapi_util_array_remove_range(Array* parray, unsigned int index, size_t length)
(array->pub.len - (index + length)) * array->elt_size);
array->pub.len -= length;
- array_elt_zero(array, array->pub.len, length);
+ array_elt_zero(array, array->pub.len, length);
+}
+
+
+/*
+ * Originally from apache 2.0
+ * Modifications for general use by <nielsen@memberwebs.com>
+ */
+
+/* Copyright 2000-2004 The Apache Software Foundation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+#define KEY_DATA(he) ((he)->key)
+
+/*
+ * The internal form of a hash table.
+ *
+ * The table is an array indexed by the hash of the key; collisions
+ * are resolved by hanging a linked list of hash entries off each
+ * element of the array. Although this is a really simple design it
+ * isn't too bad given that pools have a low allocation overhead.
+ */
+
+typedef struct _HashEntry
+{
+ struct _HashEntry* next;
+ unsigned int hash;
+ const void* key;
+ size_t klen;
+ const void* val;
}
+HashEntry;
+
+/*
+ * The size of the array is always a power of two. We use the maximum
+ * index rather than the size so that we can use bitwise-AND for
+ * modular arithmetic.
+ * The count of hash entries may be greater depending on the chosen
+ * collision rate.
+ */
+struct _CkCapiHash
+{
+ HashEntry** array;
+ size_t count;
+ size_t max;
+};
+
+#define INITIAL_MAX 15 /* tunable == 2^n - 1 */
+
+/*
+ * Hash creation functions.
+ */
+
+static HashEntry**
+alloc_array(CkCapiHash* ht, size_t max)
+{
+ return calloc(sizeof(*(ht->array)) * (max + 1), 1);
+}
+
+CkCapiHash*
+ckcapi_hash_new()
+{
+ CkCapiHash* ht = malloc(sizeof(CkCapiHash));
+ if(ht)
+ {
+ ht->count = 0;
+ ht->max = INITIAL_MAX;
+ ht->array = alloc_array(ht, ht->max);
+ if(!ht->array)
+ {
+ free(ht);
+ ht = NULL;
+ }
+ }
+ return ht;
+}
+
+void
+ckcapi_hash_free(CkCapiHash* ht)
+{
+ HashEntry* he;
+ HashEntry* next;
+ size_t i;
+
+ for(i = 0; i < ht->max; ++i)
+ {
+ for(he = ht->array[i]; he; )
+ {
+ next = he->next;
+ free(he);
+ he = next;
+ }
+ }
+
+ if(ht->array)
+ free(ht->array);
+ free(ht);
+}
+
+/*
+ * Expanding a hash table
+ */
+static int
+expand_array(CkCapiHash* ht)
+{
+ HashEntry** new_array;
+ size_t new_max;
+ HashEntry* he;
+ size_t i;
+
+ new_max = ht->max * 2 + 1;
+ new_array = alloc_array(ht, new_max);
+
+ if(!new_array)
+ return 0;
+
+ 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;
+ }
+ }
+
+ if(ht->array)
+ free(ht->array);
+
+ ht->array = new_array;
+ ht->max = new_max;
+ return 1;
+}
+
+/*
+ * This is where we keep the details of the hash function and control
+ * the maximum collision rate.
+ *
+ * If val is non-NULL it creates and initializes a new hash entry if
+ * there isn't already one there; it returns an updatable pointer so
+ * that hash entries can be removed.
+ */
+
+static HashEntry**
+find_entry(CkCapiHash* ht, const void* key, size_t klen, const void* val)
+{
+ HashEntry** hep;
+ HashEntry* he;
+ const unsigned char* p;
+ unsigned int hash;
+ size_t i;
+
+ /*
+ * This is the popular `times 33' hash algorithm which is used by
+ * perl and also appears in Berkeley DB. This is one of the best
+ * known hash functions for strings because it is both computed
+ * very fast and distributes very well.
+ *
+ * The originator may be Dan Bernstein but the code in Berkeley DB
+ * cites Chris Torek as the source. The best citation I have found
+ * is "Chris Torek, Hash function for text in C, Usenet message
+ * <27038@mimsy.umd.edu> in comp.lang.c , October, 1990." in Rich
+ * Salz's USENIX 1992 paper about INN which can be found at
+ * <http://citeseer.nj.nec.com/salz92internetnews.html>.
+ *
+ * The magic of number 33, i.e. why it works better than many other
+ * constants, prime or not, has never been adequately explained by
+ * anyone. So I try an explanation: if one experimentally tests all
+ * multipliers between 1 and 256 (as I did while writing a low-level
+ * data structure library some time ago) one detects that even
+ * numbers are not useable at all. The remaining 128 odd numbers
+ * (except for the number 1) work more or less all equally well.
+ * They all distribute in an acceptable way and this way fill a hash
+ * table with an average percent of approx. 86%.
+ *
+ * If one compares the chi^2 values of the variants (see
+ * Bob Jenkins ``Hashing Frequently Asked Questions'' at
+ * http://burtleburtle.net/bob/hash/hashfaq.html for a description
+ * of chi^2), the number 33 not even has the best value. But the
+ * number 33 and a few other equally good numbers like 17, 31, 63,
+ * 127 and 129 have nevertheless a great advantage to the remaining
+ * numbers in the large set of possible multipliers: their multiply
+ * operation can be replaced by a faster operation based on just one
+ * shift plus either a single addition or subtraction operation. And
+ * because a hash function has to both distribute good _and_ has to
+ * be very fast to compute, those few numbers should be preferred.
+ *
+ * -- Ralf S. Engelschall <rse@engelschall.com>
+ */
+
+ hash = 0;
+ for(p = key, i = klen; i; i--, p++)
+ hash = hash * 33 + *p;
+
+ /* scan linked list */
+ for(hep = &ht->array[hash & ht->max], he = *hep;
+ he; hep = &he->next, he = *hep)
+ {
+ if(he->hash == hash && he->klen == klen &&
+ memcmp(KEY_DATA(he), key, klen) == 0)
+ break;
+ }
+
+ if(he || !val)
+ return hep;
+
+ /* add a new entry for non-NULL val */
+ he = malloc(sizeof(*he));
+ if(he)
+ {
+ /* Key points to external data */
+ he->key = key;
+ he->klen = klen;
+
+ he->next = NULL;
+ he->hash = hash;
+ he->val = val;
+
+ *hep = he;
+ ht->count++;
+ }
+
+ return hep;
+}
+
+void*
+ckcapi_hash_get(CkCapiHash* ht, const void *key, size_t klen)
+{
+ HashEntry** he = find_entry(ht, key, klen, NULL);
+ if(he && *he)
+ return (void*)((*he)->val);
+ else
+ return NULL;
+}
+
+int
+ckcapi_hash_set(CkCapiHash* ht, const void* key, size_t klen, void* val)
+{
+ HashEntry** hep = find_entry(ht, key, klen, val);
+ if(hep && *hep)
+ {
+ /* replace entry */
+ (*hep)->val = val;
+
+ /* check that the collision rate isn't too high */
+ if(ht->count > ht->max)
+ {
+ if(!expand_array(ht))
+ return 0;
+ }
+
+ return 1;
+ }
+
+ return 0;
+}
+
+void*
+ckcapi_hash_rem(CkCapiHash* ht, const void* key, size_t klen)
+{
+ HashEntry** hep = find_entry(ht, key, klen, NULL);
+ void* val = NULL;
+
+ if(hep && *hep)
+ {
+ HashEntry* old = *hep;
+ *hep = (*hep)->next;
+ --ht->count;
+ val = (void*)old->val;
+ free(old);
+ }
+
+ return val;
+}
+
+size_t
+ckcapi_hash_count(CkCapiHash* ht)
+{
+ return ht->count;
+}
diff --git a/ckcapi-util.h b/ckcapi-util.h
index b37ea39..ea3d5e2 100644
--- a/ckcapi-util.h
+++ b/ckcapi-util.h
@@ -5,13 +5,6 @@
#include <stdlib.h>
/* --------------------------------------------------------------------------------
- * WINDOWS
- */
-
-CK_RV ckcapi_util_win_to_cryptoki_err (DWORD werr);
-
-
-/* --------------------------------------------------------------------------------
* ARRAYS
*/
@@ -20,27 +13,42 @@ typedef struct _Array
void* data;
size_t len;
}
-Array;
+CkCapiArray;
-#define ckcapi_util_array_append(a,v) \
- ckcapi_util_array_append_vals(a, &(v), 1)
-#define ckcapi_util_array_index(a,t,i) \
+#define ckcapi_array_append(a,v) \
+ ckcapi_array_append_vals(a, &(v), 1)
+#define ckcapi_array_index(a,t,i) \
(((t*) (a)->data) [(i)])
-Array* ckcapi_util_array_new (int zero_terminated, int zero,
+CkCapiArray* ckcapi_array_new (int zero_terminated, int zero,
size_t element_size);
-Array* ckcapi_util_array_sized_new (int zero_terminated, int zero,
+CkCapiArray* ckcapi_array_sized_new (int zero_terminated, int zero,
size_t element_size, size_t reserved_size);
-void* ckcapi_util_array_free (Array* array, int free_segment);
+void* ckcapi_array_free (CkCapiArray* array, int free_segment);
-int ckcapi_util_array_append_vals (Array* array, const void* data,
+int ckcapi_array_append_vals (CkCapiArray* array, const void* data,
size_t num);
-void ckcapi_util_array_remove_index (Array* array, unsigned int index);
+void ckcapi_array_remove_index (CkCapiArray* array, unsigned int index);
-void ckcapi_util_array_remove_range (Array* array, unsigned int index,
+void ckcapi_array_remove_range (CkCapiArray* array, unsigned int index,
size_t count);
+
+/* --------------------------------------------------------------------------------
+ * HASHTABLE
+ */
+
+struct _CkCapiHash;
+typedef struct _CkCapiHash CkCapiHash;
+
+CkCapiHash* ckcapi_hash_new();
+void ckcapi_hash_free(CkCapiHash* ht);
+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);
+void* ckcapi_hash_rem(CkCapiHash* ht, const void* key, size_t klen);
+
#endif /* __CKCAPI_UTIL_H__ */ \ No newline at end of file
diff --git a/cryptoki-capi.c b/ckcapi.c
index b100e25..971b034 100644
--- a/cryptoki-capi.c
+++ b/ckcapi.c
@@ -3,7 +3,7 @@
#include <stdarg.h>
#include <stdio.h>
-#include "cryptoki-capi.h"
+#include "ckcapi.h"
/* -------------------------------------------------------------------
* GLOBALS / DEFINES
@@ -371,7 +371,7 @@ 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;
+ CkCapiSession* sess;
CK_RV ret;
ENTER(C_OpenSession);
@@ -405,14 +405,14 @@ CC_C_OpenSession(CK_SLOT_ID id, CK_FLAGS flags, CK_VOID_PTR application,
static CK_RV
CC_C_CloseSession(CK_SESSION_HANDLE session)
{
- Session* sess;
+ 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_find_lock_ref(session, 1, &sess);
+ ret = ckcapi_session_get_lock_ref(session, 1, &sess);
if(ret == CKR_OK)
{
/* This will unref and possibly destroy the session */
@@ -576,11 +576,29 @@ 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);
+ }
- /* TODO: Implement this */
- RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
}
static CK_RV
@@ -598,17 +616,17 @@ static CK_RV
CC_C_FindObjectsInit(CK_SESSION_HANDLE session, CK_ATTRIBUTE_PTR templ,
CK_ULONG count)
{
- Session* sess;
+ CkCapiSession* 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);
+ ret = ckcapi_session_get_lock_ref(session, 0, &sess);
if(ret == CKR_OK)
{
- ret = ckcapi_object_find_init(sess, templ, count);
+ ret = ckcapi_session_find_init(sess, templ, count);
ckcapi_session_unref_unlock(sess);
}
@@ -619,7 +637,7 @@ 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;
+ CkCapiSession* sess;
CK_RV ret;
ENTER(C_FindObjects);
@@ -627,10 +645,10 @@ CC_C_FindObjects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects,
PREREQ(object_count, CKR_ARGUMENTS_BAD);
PREREQ(!max_object_count || objects, CKR_ARGUMENTS_BAD);
- ret = ckcapi_session_find_lock_ref(session, 0, &sess);
+ ret = ckcapi_session_get_lock_ref(session, 0, &sess);
if(ret == CKR_OK)
{
- ret = ckcapi_object_find(sess, objects, max_object_count, object_count);
+ ret = ckcapi_session_find(sess, objects, max_object_count, object_count);
ckcapi_session_unref_unlock(sess);
}
@@ -640,16 +658,16 @@ CC_C_FindObjects(CK_SESSION_HANDLE session, CK_OBJECT_HANDLE_PTR objects,
static CK_RV
CC_C_FindObjectsFinal(CK_SESSION_HANDLE session)
{
- Session* sess;
+ CkCapiSession* sess;
CK_RV ret;
ENTER(C_FindObjectsFinal);
PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- ret = ckcapi_session_find_lock_ref(session, 0, &sess);
+ ret = ckcapi_session_get_lock_ref(session, 0, &sess);
if(ret == CKR_OK)
{
- ret = ckcapi_objects_find_final(sess);
+ ret = ckcapi_session_find_final(sess);
ckcapi_session_unref_unlock(sess);
}
diff --git a/cryptoki-capi.dsp b/ckcapi.dsp
index 6f93ed3..a5b73e8 100644
--- a/cryptoki-capi.dsp
+++ b/ckcapi.dsp
@@ -8,12 +8,12 @@ CFG=cryptoki_capi - Win32 Debug
!MESSAGE This is not a valid makefile. To build this project using NMAKE,
!MESSAGE use the Export Makefile command and run
!MESSAGE
-!MESSAGE NMAKE /f "cryptoki-capi.mak".
+!MESSAGE NMAKE /f "ckcapi.mak".
!MESSAGE
!MESSAGE You can specify a configuration when running NMAKE
!MESSAGE by defining the macro CFG on the command line. For example:
!MESSAGE
-!MESSAGE NMAKE /f "cryptoki-capi.mak" CFG="cryptoki_capi - Win32 Debug"
+!MESSAGE NMAKE /f "ckcapi.mak" CFG="cryptoki_capi - Win32 Debug"
!MESSAGE
!MESSAGE Possible choices for configuration are:
!MESSAGE
@@ -90,19 +90,23 @@ LINK32=link.exe
# PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
# Begin Source File
+SOURCE=".\ckcapi-cert.c"
+# End Source File
+# Begin Source File
+
SOURCE=".\ckcapi-object.c"
# End Source File
# Begin Source File
-SOURCE=".\ckcapi-util.c"
+SOURCE=".\ckcapi-session.c"
# End Source File
# Begin Source File
-SOURCE=".\cryptoki-capi-session.c"
+SOURCE=".\ckcapi-util.c"
# End Source File
# Begin Source File
-SOURCE=".\cryptoki-capi.c"
+SOURCE=.\ckcapi.c
# End Source File
# End Group
# Begin Group "Header Files"
@@ -110,11 +114,11 @@ SOURCE=".\cryptoki-capi.c"
# PROP Default_Filter "h;hpp;hxx;hm;inl"
# Begin Source File
-SOURCE=".\cryptoki-capi-util.h"
+SOURCE=".\ckcapi-util.h"
# End Source File
# Begin Source File
-SOURCE=".\cryptoki-capi.h"
+SOURCE=.\ckcapi.h
# End Source File
# Begin Source File
diff --git a/cryptoki-capi.dsw b/ckcapi.dsw
index 7f71040..7f71040 100644
--- a/cryptoki-capi.dsw
+++ b/ckcapi.dsw
diff --git a/ckcapi.h b/ckcapi.h
new file mode 100644
index 0000000..6442a8d
--- /dev/null
+++ b/ckcapi.h
@@ -0,0 +1,160 @@
+#ifndef CKCAPI_H
+#define CKCAPI_H
+
+#ifndef ASSERT
+#include "assert.h"
+#define ASSERT assert
+#endif
+
+#define WIN32_LEAN_AND_MEAN
+#define _WIN32_WINNT 0x400
+#include <windows.h>
+
+#define CRYPTOKI_EXPORTS
+#include "pkcs11/cryptoki.h"
+
+#include "ckcapi-util.h"
+
+struct _CkCapiObject;
+struct _CkCapiSession;
+
+/* ------------------------------------------------------------------
+ * cryptoki-capi.c
+ */
+
+#define DBG(args) \
+ ckcapi_debug args
+
+void ckcapi_debug(const char* msg, ...);
+void ckcapi_lock_global(void);
+void ckcapi_unlock_global(void);
+CK_RV ckcapi_winerr_to_ckr (DWORD werr);
+
+/* ------------------------------------------------------------------
+ * cryptoki-capi-session.c
+ */
+
+/* For operation_type in CkCapiSession */
+enum
+{
+ OPERATION_NONE = 0,
+ OPERATION_FIND = 1,
+};
+
+typedef void (*CkCapiSessionCancel) (struct _CkCapiSession* sess);
+
+typedef struct _CkCapiSession
+{
+ CK_ULONG id; /* Unique ID for this session */
+ int in_call; /* Whether this session is use in PKCS#11 function */
+
+ int operation_type; /* Whether an operation is happening or not */
+ void* operation_data; /* Data for this operation */
+ CkCapiSessionCancel operation_cancel; /* Callback to cancel operation when necessary */
+
+ CK_NOTIFY notify_callback; /* Application specified callback */
+ CK_VOID_PTR user_data; /* Argument for above */
+
+ int refs; /* Reference count */
+ HANDLE mutex; /* Mutex for protecting this structure */
+}
+CkCapiSession;
+
+#define DBGS(sess, msg) \
+ ckcapi_debug("S%d: %s", (sess) ? (sess)->id : 0, (msg))
+
+CkCapiSession* ckcapi_session_create(void);
+void ckcapi_session_destroy(CkCapiSession* sess);
+CK_RV ckcapi_session_register(CkCapiSession* sess);
+CK_RV ckcapi_session_get_lock_ref(CK_ULONG id, int remove, CkCapiSession **sess);
+void ckcapi_session_unref_unlock(CkCapiSession* sess);
+void ckcapi_session_close_all();
+
+CK_RV ckcapi_session_find_init (CkCapiSession* sess, CK_ATTRIBUTE_PTR templ, CK_ULONG count);
+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);
+
+
+
+/* ------------------------------------------------------------------
+ * ckcapi-object.c
+ */
+
+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 (*CkCapiLoadData)(struct _CkCapiObject* obj, CkCapiObjectData* objdata);
+
+typedef struct _CkCapiObjectVtable
+{
+ CkCapiLoadData load_data;
+ CkCapiRelease release;
+}
+CkCapiObjectVtable;
+
+typedef struct _CkCapiObject
+{
+ CK_OBJECT_HANDLE id;
+ void* unique_key;
+ size_t unique_len;
+ CkCapiObjectVtable obj_funcs;
+ CkCapiObjectDataVtable data_funcs;
+}
+CkCapiObject;
+
+#define DBGO(obj, msg) \
+ ckcapi_debug("O%d: %s", (obj) ? (obj)->id : 0, (msg))
+
+CkCapiObject* ckcapi_object_lookup (CkCapiSession* sess, CK_OBJECT_HANDLE obj);
+
+CK_RV ckcapi_object_register (CkCapiSession* sess, CkCapiObject* obj);
+
+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);
+
+CK_BBOOL ckcapi_object_data_match_attr (CkCapiObjectData* objdata,
+ CK_ATTRIBUTE_PTR match);
+
+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
+ */
+
+CK_RV ckcapi_cert_find_all (CkCapiSession* sess, CK_ATTRIBUTE_PTR match,
+ CK_ULONG count, CkCapiArray* arr);
+
+CK_RV ckcapi_cert_find_in_store (CkCapiSession* sess, const char* store_name,
+ CK_ATTRIBUTE_PTR match, CK_ULONG count, CkCapiArray* arr);
+
+
+#endif /* CRYPTOKI_CAPI_H */
+
diff --git a/cryptoki-capi.h b/cryptoki-capi.h
deleted file mode 100644
index a5dc9d5..0000000
--- a/cryptoki-capi.h
+++ /dev/null
@@ -1,99 +0,0 @@
-#ifndef CRYPTOKI_CAPI_H
-#define CRYPTOKI_CAPI_H
-
-#ifndef ASSERT
-#include "assert.h"
-#define ASSERT assert
-#endif
-
-#define WIN32_LEAN_AND_MEAN
-#define _WIN32_WINNT 0x400
-#include <windows.h>
-
-#define CRYPTOKI_EXPORTS
-#include "pkcs11/cryptoki.h"
-
-#include "cryptoki-capi-util.h"
-
-struct _Object;
-struct _Session;
-
-/* ------------------------------------------------------------------
- * cryptoki-capi.c
- */
-
-#define DBG(args) \
- ckcapi_debug args
-
-void ckcapi_debug(const char* msg, ...);
-void ckcapi_lock_global(void);
-void ckcapi_unlock_global(void);
-CK_RV ckcapi_winerr_to_ckr (DWORD werr);
-
-/* ------------------------------------------------------------------
- * cryptoki-capi-session.c
- */
-
-/* For operation_type in Session */
-enum
-{
- OPERATION_NONE = 0,
- OPERATION_FIND = 1,
-};
-
-typedef void (*SessionCancel) (struct _Session* sess);
-
-typedef struct _Session
-{
- CK_ULONG id; /* Unique ID for this session */
- int in_call; /* Whether this session is use in PKCS#11 function */
-
- int operation_type; /* Whether an operation is happening or not */
- void* operation_data; /* Data for this operation */
- SessionCancel operation_cancel; /* Callback to cancel operation when necessary */
-
- CK_NOTIFY notify_callback; /* Application specified callback */
- CK_VOID_PTR user_data; /* Argument for above */
-
- int refs; /* Reference count */
- HANDLE mutex; /* Mutex for protecting this structure */
-}
-Session;
-
-#define DBGS(sess, msg) \
- ckcapi_debug("S%d: %s", (sess) ? (sess)->id : 0, (msg))
-
-Session* ckcapi_session_create(void);
-void ckcapi_session_destroy(Session* sess);
-CK_RV ckcapi_session_register(Session* sess);
-CK_RV ckcapi_session_find_lock_ref(CK_ULONG id, int remove, Session **sess);
-void ckcapi_session_unref_unlock(Session* sess);
-void ckcapi_session_close_all();
-
-
-/* ------------------------------------------------------------------
- * cryptoki-capi-object.c
- */
-
-typedef struct _Object
-{
- CK_ULONG id; /* Unique ID for this object */
-
- CK_ATTRIBUTE_PTR attrs; /* All the attributes of this object */
- CK_ULONG n_attrs; /* Number of attributes */
-}
-Object;
-
-/*
-Object* ckcapi_object_create(Session* sess, CK_ATTRIBUTE_PTR attrs, CK_ULONG n_attrs);
-void ckcapi_object_destroy(Session* sess, Object* obj);
-*/
-
-CK_RV ckcapi_object_find_init (Session* sess, CK_ATTRIBUTE_PTR templ, CK_ULONG count);
-CK_RV ckcapi_object_find (Session* sess, CK_OBJECT_HANDLE_PTR objects,
- CK_ULONG max_object_count, CK_ULONG_PTR object_count);
-CK_RV ckcapi_objects_find_final (Session* sess);
-
-
-#endif /* CRYPTOKI_CAPI_H */
-