summaryrefslogtreecommitdiff
path: root/ckcapi-cert.c
diff options
context:
space:
mode:
Diffstat (limited to 'ckcapi-cert.c')
-rw-r--r--ckcapi-cert.c201
1 files changed, 95 insertions, 106 deletions
diff --git a/ckcapi-cert.c b/ckcapi-cert.c
index ebb34ff..6e51f3e 100644
--- a/ckcapi-cert.c
+++ b/ckcapi-cert.c
@@ -309,46 +309,25 @@ ckcapi_cert_certificate_get_bytes(PCCERT_CONTEXT cert, CK_ATTRIBUTE_PTR attr)
WCHAR* utf16 = NULL;
DWORD size;
- /* Get the UTF16 string, a worst case of twice as long as UTF8 */
- if(data)
- {
- size = *len * sizeof(WCHAR);
- utf16 = _alloca(size);
- }
-
- if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
- utf16, &size))
+ if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, NULL, &size))
{
err = GetLastError();
if(err == CRYPT_E_NOT_FOUND)
- utf16 = L"";
+ utf16 = L"Unnamed Certificate";
else
return ckcapi_winerr_to_ckr(err);
}
- if(utf16)
+ if(!utf16)
{
- /* Always have a default name */
- if(!utf16[0])
- {
- utf16 = L"Unnamed Certificate";
- size = wcslen(utf16) * 2;
- }
-
- /* Convert the data into the buffer */
- *len = WideCharToMultiByte(CP_UTF8, 0, utf16, size / sizeof(WCHAR),
- data, *len, NULL, NULL);
- if(!*len)
+ utf16 = _alloca(size);
+ if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID, utf16, &size))
return ckcapi_winerr_to_ckr(GetLastError());
}
- else
- {
- /* Just return an appropriate allocation length */
- *len = (size / sizeof(WCHAR)) + sizeof(WCHAR);
- }
+ return ckcapi_return_string(data, len, utf16);
}
- return CKR_OK;
+ break;
/*
* A byte array unique to this certificate. The CKA_ID of
@@ -417,7 +396,7 @@ ckcapi_cert_certificate_get_bytes(PCCERT_CONTEXT cert, CK_ATTRIBUTE_PTR attr)
*/
case CKA_VALUE:
return ckcapi_return_data(data, len, cert->pbCertEncoded,
- cert->cbCertEncoded);
+ cert->cbCertEncoded);
/*
* If CKA_VALUE not specified, this is where the full
@@ -514,22 +493,36 @@ register_cert_object(CkCapiSession* sess, PCCERT_CONTEXT cert, CkCapiObject** ob
}
static CK_RV
-find_in_store(CkCapiSession* sess, CK_ATTRIBUTE_PTR match,
- CK_ULONG count, CkCapiArray* arr)
+find_in_store(CkCapiSession* sess, DWORD find_type, const void *find_criteria,
+ CK_ATTRIBUTE_PTR match, CK_ULONG count, CkCapiArray* arr)
{
PCCERT_CONTEXT cert = NULL;
CkCapiObject* obj;
- CertObjectData cdata;
CkCapiObjectData* objdata;
+ CertObjectData cdata;
+ DWORD err;
CK_RV ret = CKR_OK;
/* No store, no objects */
if(!sess->store)
return CKR_OK;
- /* Match each certificate */
- while((cert = CertEnumCertificatesInStore(sess->store, cert)) != NULL)
+ for(;;)
{
+ cert = CertFindCertificateInStore(sess->store, CKCAPI_ENCODINGS, 0,
+ find_type, find_criteria, cert);
+ if(cert == NULL)
+ {
+ err = GetLastError();
+
+ /* Certificate not found, we don't care */
+ if(err == CRYPT_E_NOT_FOUND)
+ return CKR_OK;
+ else
+ return ckcapi_winerr_to_ckr(err);
+ }
+
+ /* Match the certificate */
cdata.cert = cert;
cdata.base.object = 0;
cdata.base.data_funcs = &cert_objdata_vtable;
@@ -537,72 +530,22 @@ find_in_store(CkCapiSession* sess, CK_ATTRIBUTE_PTR match,
if(ckcapi_object_data_match(&cdata.base, match, count))
{
ret = register_cert_object(sess, cert, &obj);
- if(ret != CKR_OK)
- break;
-
- ASSERT(obj);
-
- /* Store away the object data for performance reasons */
- objdata = cert_alloc_data(sess, obj, cert);
- if(objdata)
+ if(ret == CKR_OK)
{
- ckcapi_session_take_object_data(sess, obj, objdata);
-
- /* For continuing the enumeration */
- cert = CertDuplicateCertificateContext(cert);
- }
-
- ckcapi_array_append(arr, obj->id);
- }
- }
-
- return ret;
-}
-
-static CK_RV
-match_in_store(CkCapiSession* sess, PCERT_INFO info, CK_ATTRIBUTE_PTR match,
- CK_ULONG count, CkCapiArray* arr)
-{
- PCCERT_CONTEXT cert = NULL;
- CkCapiObject* obj;
- CkCapiObjectData* objdata;
- CertObjectData cdata;
- DWORD err;
- CK_RV ret = CKR_OK;
-
- /* No store, no objects */
- if(!sess->store)
- return CKR_OK;
-
- cert = CertGetSubjectCertificateFromStore(sess->store, CKCAPI_ENCODINGS, info);
- if(cert == NULL)
- {
- err = GetLastError();
+ ASSERT(obj);
- /* Certificate not found, we don't care */
- if(err == CRYPT_E_NOT_FOUND)
- return CKR_OK;
- else
- return ckcapi_winerr_to_ckr(err);
- }
-
- /* Match the certificate */
- cdata.cert = cert;
- cdata.base.object = 0;
- cdata.base.data_funcs = &cert_objdata_vtable;
+ /* Store away the object data for performance reasons */
+ objdata = cert_alloc_data(sess, obj, cert);
+ if(objdata)
+ {
+ ckcapi_session_take_object_data(sess, obj, objdata);
- if(ckcapi_object_data_match(&cdata.base, match, count))
- {
- ret = register_cert_object(sess, cert, &obj);
- if(ret == CKR_OK)
- {
- ASSERT(obj);
+ /* For continuing the enumeration */
+ cert = CertDuplicateCertificateContext(cert);
+ }
- /* Store away the object data for performance reasons */
- objdata = cert_alloc_data(sess, obj, cert);
- if(objdata)
- ckcapi_session_take_object_data(sess, obj, objdata);
- ckcapi_array_append(arr, obj->id);
+ ckcapi_array_append(arr, obj->id);
+ }
}
}
@@ -617,20 +560,46 @@ ckcapi_cert_find(CkCapiSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR matc
CK_ULONG count, CkCapiArray* arr)
{
CRYPT_INTEGER_BLOB* serial = NULL;
- CERT_INFO info;
CK_RV ret;
CK_ULONG i;
DWORD size;
+ CERT_INFO find_info; /* For searching by issuer and serial */
+ CRYPT_HASH_BLOB find_key; /* For searching by ID */
+
/* We only have certificates here */
if(cls != CKO_CERTIFICATE && cls != CKO_ANY)
return CKR_OK;
+ /* Only work with slots that have certificates */
+ if(!(ckcapi_token_get_flags (sess->slot) & CKCAPI_SLOT_CERTS))
+ return CKR_OK;
+
/*
+ * There are some better searches we can do rather than
+ * listing everything.
+ *
+ * CKA_ISSUER + CKA_SERIAL_NUMBER
* See if we have a issuer and serial number for a
* specific certificate to find.
+ *
+ * CKA_ID
+ * Search by key identifier
+ *
+ * TODO: could search by hash (use CertFindCertificateInStore
+ * with CERT_FIND_HASH or CERT_FIND_SHA1_HASH or CERT_FIND_MD5_HASH)
+ *
+ * TODO: could search by issuer (use CertFindCertificateInStore
+ * with CERT_FIND_ISSUER_NAME)
+ *
+ * TODO: could search by subject (use CertFindCertificateInStore
+ * with CERT_FIND_SUBJECT_NAME)
+ *
+ * TODO: could search by CKA_VALUE (use CertFindCertificateInStore
+ * with CERT_FIND_EXISTING)
*/
- memset(&info, 0, sizeof(info));
+ memset(&find_info, 0, sizeof(find_info));
+ memset(&find_key, 0, sizeof(find_key));
for(i = 0; i < count; ++i)
{
@@ -639,10 +608,11 @@ ckcapi_cert_find(CkCapiSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR matc
if(match[i].type == CKA_ISSUER)
{
- info.Issuer.cbData = match[i].ulValueLen;
- info.Issuer.pbData = match[i].pValue;
+ find_info.Issuer.cbData = match[i].ulValueLen;
+ find_info.Issuer.pbData = match[i].pValue;
}
- else if(!serial && match[i].type == CKA_SERIAL_NUMBER)
+
+ else if(match[i].type == CKA_SERIAL_NUMBER && !serial)
{
if(!CryptDecodeObject(CKCAPI_ENCODINGS, X509_MULTI_BYTE_INTEGER,
match[i].pValue, match[i].ulValueLen, 0, NULL, &size))
@@ -658,18 +628,37 @@ ckcapi_cert_find(CkCapiSession* sess, CK_OBJECT_CLASS cls, CK_ATTRIBUTE_PTR matc
ASSERT(serial->cbData);
ASSERT(serial->pbData);
- info.SerialNumber.cbData = serial->cbData;
- info.SerialNumber.pbData = serial->pbData;
+ find_info.SerialNumber.cbData = serial->cbData;
+ find_info.SerialNumber.pbData = serial->pbData;
+ }
+
+ else if(match[i].type == CKA_ID)
+ {
+ find_key.cbData = match[i].ulValueLen;
+ find_key.pbData = match[i].pValue;
}
}
/* Match a specific certificate */
- if(info.SerialNumber.cbData && info.Issuer.cbData)
- ret = match_in_store(sess, &info, match, count, arr);
+ if(find_info.SerialNumber.cbData && find_info.Issuer.cbData)
+ {
+ ret = find_in_store(sess, CERT_FIND_SUBJECT_CERT, &find_info,
+ match, count, arr);
+ }
+
+ /* Find all certificates with key identifier */
+ else if(find_key.cbData)
+ {
+ ret = find_in_store(sess, CERT_FIND_KEY_IDENTIFIER, &find_key,
+ match, count, arr);
+ }
/* Match any ol certificate */
else
- ret = find_in_store(sess, match, count, arr);
+ {
+ ret = find_in_store(sess, CERT_FIND_ANY, NULL,
+ match, count, arr);
+ }
if(serial)
free(serial);