diff options
Diffstat (limited to 'ckcapi-cert.c')
-rw-r--r-- | ckcapi-cert.c | 331 |
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); } } |