summaryrefslogtreecommitdiff
path: root/ckcapi-cert.c
diff options
context:
space:
mode:
Diffstat (limited to 'ckcapi-cert.c')
-rw-r--r--ckcapi-cert.c331
1 files changed, 189 insertions, 142 deletions
diff --git a/ckcapi-cert.c b/ckcapi-cert.c
index 064c5f5..ee140ab 100644
--- a/ckcapi-cert.c
+++ b/ckcapi-cert.c
@@ -3,8 +3,6 @@
#include <memory.h>
-#include <wincrypt.h>
-
#ifndef CERT_FIND_KEY_IDENTIFIER
#define CERT_FIND_KEY_IDENTIFIER 983040
#endif
@@ -45,16 +43,22 @@ typedef struct _CertObject
}
CertObject;
+typedef struct _CertObjectData
+{
+ CkCapiObjectData base;
+ PCCERT_CONTEXT cert;
+}
+CertObjectData;
+
static CK_RV
-cert_bool_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
- CK_VOID_PTR data, CK_ULONG_PTR len)
+cert_bool_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
{
- PCCERT_CONTEXT cert = (PCCERT_CONTEXT)obj;
+ CertObjectData* cdata = (CertObjectData*)objdata;
CK_BBOOL val;
- ASSERT(obj);
+ ASSERT(cdata);
- switch(type)
+ switch(attr->type)
{
/*
* Resides on the token
@@ -95,19 +99,18 @@ cert_bool_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
return CKR_ATTRIBUTE_TYPE_INVALID;
};
- return ckcapi_return_data(data, len, &val, sizeof(CK_BBOOL));
+ return ckcapi_return_data(attr->pValue, &attr->ulValueLen, &val, sizeof(CK_BBOOL));
}
static CK_RV
-cert_ulong_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
- CK_VOID_PTR data, CK_ULONG_PTR len)
+cert_ulong_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
{
- PCCERT_CONTEXT cert = (PCCERT_CONTEXT)obj;
+ CertObjectData* cdata = (CertObjectData*)objdata;
CK_ULONG val;
- ASSERT(obj);
+ ASSERT(objdata);
- switch(type)
+ switch(attr->type)
{
/*
@@ -138,26 +141,158 @@ cert_ulong_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
return CKR_ATTRIBUTE_TYPE_INVALID;
};
- if(*len < sizeof(CK_ULONG))
+ return ckcapi_return_data(attr->pValue, &attr->ulValueLen, &val, sizeof(CK_ULONG));
+}
+
+static CK_RV
+cert_bytes_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
+{
+ CertObjectData* cdata = (CertObjectData*)objdata;
+ PCCERT_CONTEXT cert = cdata->cert;
+
+ ASSERT(sizeof(CK_ULONG) == sizeof(DWORD));
+ ASSERT(cdata);
+
+ return ckcapi_cert_certificate_get_bytes(cdata->cert, attr);
+}
+
+static CK_RV
+cert_date_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
+{
+ switch(attr->type)
{
- *len = sizeof(CK_ULONG);
- return CKR_BUFFER_TOO_SMALL;
+
+ /*
+ * Start date for the certificate.
+ * - TODO: Work out where to get this.
+ * pCertInfo->NotBefore;
+ */
+ case CKA_START_DATE:
+ break;
+
+ /*
+ * End date for the certificate.
+ * - TODO: Work out where to get this.
+ * pCertInfo->NotBefore;
+ */
+ case CKA_END_DATE:
+ break;
+ };
+
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+}
+
+static void
+cert_data_release(void* data)
+{
+ CertObjectData* cdata = (CertObjectData*)data;
+ ASSERT(cdata && cdata->cert);
+ CertFreeCertificateContext(cdata->cert);
+ free(cdata);
+}
+
+static const CkCapiObjectDataVtable cert_objdata_vtable = {
+ cert_bool_attribute,
+ cert_ulong_attribute,
+ cert_bytes_attribute,
+ cert_date_attribute,
+ cert_data_release,
+};
+
+static CkCapiObjectData*
+cert_alloc_data(CkCapiSession* sess, CkCapiObject* obj, PCCERT_CONTEXT cert)
+{
+ CertObjectData* cdata;
+
+ cdata = (CertObjectData*)calloc(sizeof(CertObjectData), 1);
+ if(!cdata)
+ return NULL;
+
+ cdata->cert = cert;
+
+ cdata->base.object = obj->id;
+ cdata->base.data_funcs = &cert_objdata_vtable;
+
+ return &(cdata->base);
+}
+
+static CK_RV
+cert_load_data(CkCapiSession* sess, CkCapiObject* obj, CkCapiObjectData** objdata)
+{
+ CertObject* cobj = (CertObject*)obj;
+ HCERTSTORE store;
+ CERT_INFO info;
+ PCCERT_CONTEXT cert;
+
+ ASSERT(cobj);
+ ASSERT(objdata);
+
+ ASSERT(cobj->store);
+ store = CertOpenSystemStore((HCRYPTPROV)NULL, cobj->store);
+ if(!store)
+ return ckcapi_winerr_to_ckr(GetLastError());
+
+ ASSERT(cobj->issuer.pbData);
+ ASSERT(cobj->issuer.cbData);
+ ASSERT(cobj->serial.pbData);
+ ASSERT(cobj->serial.cbData);
+
+ /* Setup our search */
+ memset(&info, 0, sizeof(info));
+ memcpy(&info.SerialNumber, &cobj->serial, sizeof(info.SerialNumber));
+ memcpy(&info.Issuer, &cobj->issuer, sizeof(info.Issuer));
+
+ cert = CertGetSubjectCertificateFromStore(store, USE_ENCODINGS, &info);
+
+ 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());
}
- return ckcapi_return_data(data, len, &val, sizeof(CK_ULONG));
+ *objdata = cert_alloc_data(sess, obj, cert);
+ if(!(*objdata))
+ {
+ CertFreeCertificateContext(cert);
+ return CKR_HOST_MEMORY;
+ }
+
+ return CKR_OK;
}
-CK_RV
-ckcapi_cert_get_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
- CK_VOID_PTR data, CK_ULONG_PTR len)
+static void
+cert_object_release(void* data)
+{
+ CertObject* cobj = (CertObject*)data;
+ ASSERT(cobj);
+ free(cobj);
+}
+
+static const CkCapiObjectVtable cert_object_vtable = {
+ cert_load_data,
+ cert_object_release,
+};
+
+CK_RV
+ckcapi_cert_certificate_get_bytes(PCCERT_CONTEXT cert, CK_ATTRIBUTE_PTR attr)
{
- PCCERT_CONTEXT cert = (PCCERT_CONTEXT)obj;
+ CK_VOID_PTR data = attr->pValue;
+ CK_ULONG_PTR len = &attr->ulValueLen;
DWORD err;
-
- ASSERT(sizeof(CK_ULONG) == sizeof(DWORD));
- ASSERT(obj);
- switch(type)
+ ASSERT(cert);
+ ASSERT(len);
+ ASSERT(attr);
+
+ switch(attr->type)
{
/*
@@ -315,114 +450,18 @@ ckcapi_cert_get_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
return CKR_ATTRIBUTE_TYPE_INVALID;
}
-static CK_RV
-cert_date_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
- CK_VOID_PTR data, CK_ULONG_PTR len)
+PCCERT_CONTEXT
+ckcapi_cert_object_data_get_certificate(CkCapiObjectData* objdata)
{
- switch(type)
- {
-
- /*
- * Start date for the certificate.
- * - TODO: Work out where to get this.
- * pCertInfo->NotBefore;
- */
- case CKA_START_DATE:
- break;
-
- /*
- * End date for the certificate.
- * - TODO: Work out where to get this.
- * pCertInfo->NotBefore;
- */
- case CKA_END_DATE:
- 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,
- ckcapi_cert_get_bytes_attribute,
- cert_date_attribute,
- cert_release,
-};
-
-static CK_RV
-cert_load_data(CkCapiSession* sess, CkCapiObject* obj, CkCapiObjectData* objdata)
-{
- CertObject* cobj = (CertObject*)obj;
- HCERTSTORE store;
- CERT_INFO info;
- PCCERT_CONTEXT cert;
+ CertObjectData* cdata;
- ASSERT(cobj);
ASSERT(objdata);
+ ASSERT(objdata->data_funcs == &cert_objdata_vtable);
- ASSERT(cobj->store);
- store = CertOpenSystemStore((HCRYPTPROV)NULL, cobj->store);
- if(!store)
- return ckcapi_winerr_to_ckr(GetLastError());
-
- ASSERT(cobj->issuer.pbData);
- ASSERT(cobj->issuer.cbData);
- ASSERT(cobj->serial.pbData);
- ASSERT(cobj->serial.cbData);
-
- /* Setup our search */
- memset(&info, 0, sizeof(info));
- memcpy(&info.SerialNumber, &cobj->serial, sizeof(info.SerialNumber));
- memcpy(&info.Issuer, &cobj->issuer, sizeof(info.Issuer));
-
- cert = CertGetSubjectCertificateFromStore(store, USE_ENCODINGS, &info);
-
- 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());
- }
-
- /*
- * Important: The trust stuff depends on the objdata value of a
- * certificate object is a CERT_CONTEXT pointer.
- */
- 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);
+ cdata = (CertObjectData*)objdata;
+ return cdata->cert;
}
-static const CkCapiObjectVtable cert_object_vtable = {
- cert_load_data,
- cert_object_release,
-};
-
static CK_RV
register_cert_object(CkCapiSession* sess, const char* store, PCCERT_CONTEXT cert,
CkCapiObject** obj)
@@ -496,7 +535,8 @@ find_in_store(CkCapiSession* sess, const char* store_name,
PCCERT_CONTEXT cert = NULL;
CkCapiObject* obj;
HCERTSTORE store;
- CkCapiObjectData objdata;
+ CertObjectData cdata;
+ CkCapiObjectData* objdata;
DWORD err;
CK_RV ret = CKR_OK;
@@ -520,10 +560,11 @@ find_in_store(CkCapiSession* sess, const char* store_name,
/* Match each certificate */
while((cert = CertEnumCertificatesInStore(store, cert)) != NULL)
{
- objdata.data = (void*)cert;
- objdata.data_funcs = &cert_objdata_vtable;
+ cdata.cert = cert;
+ cdata.base.object = 0;
+ cdata.base.data_funcs = &cert_objdata_vtable;
- if(ckcapi_object_data_match(&objdata, match, count))
+ if(ckcapi_object_data_match(&cdata.base, match, count))
{
ret = register_cert_object(sess, store_name, cert, &obj);
if(ret != CKR_OK)
@@ -532,10 +573,13 @@ find_in_store(CkCapiSession* sess, const char* store_name,
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);
+ objdata = cert_alloc_data(sess, obj, cert);
+ if(objdata)
+ {
+ ckcapi_session_take_object_data(sess, obj, objdata);
+
+ /* For continuing the enumeration */
+ cert = CertDuplicateCertificateContext(cert);
}
ckcapi_array_append(arr, obj->id);
@@ -554,8 +598,9 @@ match_in_store(CkCapiSession* sess, const char* store_name, PCERT_INFO info,
{
PCCERT_CONTEXT cert = NULL;
CkCapiObject* obj;
+ CkCapiObjectData* objdata;
HCERTSTORE store;
- CkCapiObjectData objdata;
+ CertObjectData cdata;
DWORD err;
CK_RV ret = CKR_OK;
@@ -584,10 +629,11 @@ match_in_store(CkCapiSession* sess, const char* store_name, PCERT_INFO info,
}
/* Match the certificate */
- objdata.data = (void*)cert;
- objdata.data_funcs = &cert_objdata_vtable;
+ cdata.cert = cert;
+ cdata.base.object = 0;
+ cdata.base.data_funcs = &cert_objdata_vtable;
- if(ckcapi_object_data_match(&objdata, match, count))
+ if(ckcapi_object_data_match(&cdata.base, match, count))
{
ret = register_cert_object(sess, store_name, cert, &obj);
if(ret == CKR_OK)
@@ -595,9 +641,10 @@ match_in_store(CkCapiSession* sess, const char* store_name, PCERT_INFO info,
ASSERT(obj);
/* Store away the object data for performance reasons */
- ret = ckcapi_session_set_object_data(sess, obj, &objdata);
- if(ret == CKR_OK)
- ckcapi_array_append(arr, obj->id);
+ objdata = cert_alloc_data(sess, obj, cert);
+ if(objdata)
+ ckcapi_session_take_object_data(sess, obj, objdata);
+ ckcapi_array_append(arr, obj->id);
}
}