summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorStef Walter <stef@memberwebs.com>2007-04-28 04:35:20 +0000
committerStef Walter <stef@memberwebs.com>2007-04-28 04:35:20 +0000
commit0ba89ba85a58264e4b1b44a5593e84fb070126e3 (patch)
treefa4179ef40460b8276de649ce297930584ad946b
parent4928a4bff079c140d261cb3fefdc07c60c0bdebf (diff)
Show windows CAPI certificates. Basic implementation and functionality complete.
-rw-r--r--ckcapi-cert.c90
-rw-r--r--ckcapi-object.c73
-rw-r--r--ckcapi-util.c3
-rw-r--r--ckcapi.c3
-rw-r--r--ckcapi.dsp6
-rw-r--r--ckcapi.h2
6 files changed, 127 insertions, 50 deletions
diff --git a/ckcapi-cert.c b/ckcapi-cert.c
index 7436307..0605ef9 100644
--- a/ckcapi-cert.c
+++ b/ckcapi-cert.c
@@ -5,6 +5,14 @@
#include <wincrypt.h>
+#ifndef CERT_FIND_KEY_IDENTIFIER
+#define CERT_FIND_KEY_IDENTIFIER 983040
+#endif
+
+#ifndef CERT_KEY_IDENTIFIER_PROP_ID
+#define CERT_KEY_IDENTIFIER_PROP_ID 20
+#endif
+
typedef struct _CertObject
{
CkCapiObject obj;
@@ -145,7 +153,8 @@ cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
CK_VOID_PTR data, CK_ULONG_PTR len)
{
PCCERT_CONTEXT cert = (PCCERT_CONTEXT)obj;
-
+ DWORD err;
+
ASSERT(sizeof(CK_ULONG) == sizeof(DWORD));
ASSERT(obj);
@@ -161,27 +170,49 @@ cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
*/
case CKA_LABEL:
{
- WCHAR* utf16;
+ WCHAR* utf16 = NULL;
+ DWORD size;
/* Get the UTF16 string, a worst case of twice as long as UTF8 */
- (*len) *= sizeof(WCHAR);
- utf16 = _alloca(*len);
+ if(data)
+ {
+ size = *len * sizeof(WCHAR);
+ utf16 = _alloca(size);
+ }
+
if(!CertGetCertificateContextProperty(cert, CERT_FRIENDLY_NAME_PROP_ID,
- utf16, (DWORD*)len))
+ utf16, &size))
{
- DWORD err = GetLastError();
+ err = GetLastError();
if(err == CRYPT_E_NOT_FOUND)
- utf16 = L"Unnamed Certificate";
+ utf16 = L"";
else
return ckcapi_winerr_to_ckr(err);
}
- /* Convert the data into the buffer */
- if(!WideCharToMultiByte(CP_UTF8, 0, utf16, -1, data, *len, "?", NULL))
- return ckcapi_winerr_to_ckr(GetLastError());
- return CKR_OK;
+ 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)
+ return ckcapi_winerr_to_ckr(GetLastError());
+ }
+ else
+ {
+ /* Just return an appropriate allocation length */
+ *len = (size / sizeof(WCHAR)) + sizeof(WCHAR);
+ }
+
}
- break;
+ return CKR_OK;
/*
* A byte array unique to this certificate. The CKA_ID of
@@ -191,17 +222,16 @@ cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
* We use CAPI's CERT_KEY_IDENTIFIER_PROP_ID property directly.
*/
case CKA_ID:
- {
- if(!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID,
+ if(!CertGetCertificateContextProperty(cert, CERT_KEY_IDENTIFIER_PROP_ID,
data, (DWORD*)len))
- {
- DWORD err = GetLastError();
- if(err == CRYPT_E_NOT_FOUND)
- return CKR_ATTRIBUTE_TYPE_INVALID;
- return ckcapi_winerr_to_ckr(err);
- }
+ {
+ err = GetLastError();
+ if(err == CRYPT_E_NOT_FOUND)
+ return CKR_ATTRIBUTE_TYPE_INVALID;
+ return ckcapi_winerr_to_ckr(err);
}
- break;
+ return CKR_OK;
+
/*
* DER-encoding of the certificate subject name.
@@ -234,17 +264,15 @@ cert_bytes_attribute(void* obj, CK_ATTRIBUTE_TYPE type,
* &size);
*/
case CKA_SERIAL_NUMBER:
+ if(!CryptEncodeObject(X509_ASN_ENCODING, X509_MULTI_BYTE_INTEGER,
+ &cert->pCertInfo->SerialNumber, data, len))
{
- if(!CryptEncodeObject(X509_ASN_ENCODING, X509_MULTI_BYTE_INTEGER,
- &cert->pCertInfo->SerialNumber, data, len))
- {
- DWORD err = GetLastError();
- if(err == ERROR_FILE_NOT_FOUND)
- return CKR_GENERAL_ERROR;
- return ckcapi_winerr_to_ckr(err);
- }
+ err = GetLastError();
+ if(err == ERROR_FILE_NOT_FOUND)
+ return CKR_GENERAL_ERROR;
+ return ckcapi_winerr_to_ckr(err);
}
- break;
+ return CKR_OK;
/*
* BER-encoding of the full certificate.
@@ -469,7 +497,7 @@ ckcapi_cert_find_in_store(CkCapiSession* sess, const char* store_name,
if(ckcapi_object_data_match(&objdata, match, count))
{
- ret = register_cert_object(sess, store, cert, &obj);
+ ret = register_cert_object(sess, store_name, cert, &obj);
if(ret != CKR_OK)
break;
diff --git a/ckcapi-object.c b/ckcapi-object.c
index c02c365..c620cc4 100644
--- a/ckcapi-object.c
+++ b/ckcapi-object.c
@@ -17,6 +17,34 @@ object_free(CkCapiObject* obj)
(obj->obj_funcs.release)(obj);
}
+void
+ckcapi_object_clear_all(void)
+{
+ size_t i;
+
+ ckcapi_lock_global();
+
+ if(object_hash)
+ {
+ ckcapi_hash_free(object_hash);
+ object_hash = NULL;
+ }
+
+ if(object_array)
+ {
+ for(i = 0; i < object_array->len; ++i)
+ {
+ ASSERT(ckcapi_array_index(object_array, CkCapiObject*, i));
+ object_free(ckcapi_array_index(object_array, CkCapiObject*, i));
+ }
+
+ ckcapi_array_free(object_array, TRUE);
+ object_array = NULL;
+ }
+
+ ckcapi_unlock_global();
+}
+
CkCapiObject*
ckcapi_object_lookup(CkCapiSession* sess, CK_OBJECT_HANDLE obj)
{
@@ -48,7 +76,7 @@ ckcapi_object_register(CkCapiSession* sess, CkCapiObject* obj)
ASSERT(obj->unique_key);
ASSERT(obj->unique_len);
- DBGS(sess, "registering new session");
+ DBGS(sess, "registering new object");
ckcapi_lock_global();
@@ -364,7 +392,7 @@ ckcapi_object_data_get_attrs(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attrs,
break;
case DATA_ULONG:
rv = (objdata->data_funcs.get_ulong)(objdata->data, attrs[i].type,
- attrs[i].pValue, &attrs[i].ulValueLen);
+ attrs[i].pValue, &attrs[i].ulValueLen);
break;
case DATA_BYTES:
rv = (objdata->data_funcs.get_bytes)(objdata->data, attrs[i].type,
@@ -383,23 +411,36 @@ ckcapi_object_data_get_attrs(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attrs,
};
/* Not an error if they were just requesting the size */
- if(rv == CKR_BUFFER_TOO_SMALL)
+ if(rv != CKR_OK)
{
- if(!attrs[i].pValue)
- rv = CKR_OK;
- }
+ if(rv == CKR_BUFFER_TOO_SMALL)
+ {
+ if(!attrs[i].pValue)
+ rv = CKR_OK;
+ }
- /* Is it a fatal error? */
- else if(rv != CKR_ATTRIBUTE_TYPE_INVALID)
- {
- ret = rv;
- break;
- }
+ /* Attribute is sensitive */
+ else if(rv == CKR_ATTRIBUTE_SENSITIVE)
+ {
+ attrs[i].ulValueLen = (CK_ULONG)-1;
+ }
- /* Transfer any non-fatal errors outward */
- if(rv != CKR_OK && ret == CKR_OK)
- {
- ret = rv;
+ /* Attribute doesn't exist */
+ else if(rv == CKR_ATTRIBUTE_TYPE_INVALID)
+ {
+ attrs[i].ulValueLen = (CK_ULONG)-1;
+ }
+
+ /* A fatal error? */
+ else
+ {
+ ret = rv;
+ break;
+ }
+
+ /* Transfer any non-fatal errors outward */
+ if(rv != CKR_OK && ret == CKR_OK)
+ ret = rv;
}
}
diff --git a/ckcapi-util.c b/ckcapi-util.c
index 6969c2e..4078ab5 100644
--- a/ckcapi-util.c
+++ b/ckcapi-util.c
@@ -99,7 +99,8 @@ ckcapi_array_free(CkCapiArray* array, int free_segment)
if(free_segment)
{
- free(array->data);
+ if(array->data)
+ free(array->data);
segment = NULL;
}
else
diff --git a/ckcapi.c b/ckcapi.c
index 971b034..84538c8 100644
--- a/ckcapi.c
+++ b/ckcapi.c
@@ -161,6 +161,9 @@ CC_C_Finalize(CK_VOID_PTR pReserved)
cryptoki_initialized = 0;
+ ckcapi_session_close_all();
+ ckcapi_object_clear_all();
+
RETURN(CKR_OK);
}
diff --git a/ckcapi.dsp b/ckcapi.dsp
index a5b73e8..c50d0af 100644
--- a/ckcapi.dsp
+++ b/ckcapi.dsp
@@ -40,6 +40,7 @@ RSC=rc.exe
# PROP Use_Debug_Libraries 0
# PROP Output_Dir "Release"
# PROP Intermediate_Dir "Release"
+# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTOKI_CAPI_EXPORTS" /YX /FD /c
# ADD CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTOKI_CAPI_EXPORTS" /YX /FD /c
@@ -52,7 +53,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib crypt32.lib /nologo /dll /machine:I386
!ELSEIF "$(CFG)" == "cryptoki_capi - Win32 Debug"
@@ -65,6 +66,7 @@ LINK32=link.exe
# PROP Use_Debug_Libraries 1
# PROP Output_Dir "Debug"
# PROP Intermediate_Dir "Debug"
+# PROP Ignore_Export_Lib 0
# PROP Target_Dir ""
# ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTOKI_CAPI_EXPORTS" /YX /FD /GZ /c
# ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "CRYPTOKI_CAPI_EXPORTS" /YX /FD /GZ /c
@@ -77,7 +79,7 @@ BSC32=bscmake.exe
# ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
-# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib crypt32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
!ENDIF
diff --git a/ckcapi.h b/ckcapi.h
index 6442a8d..2f832dd 100644
--- a/ckcapi.h
+++ b/ckcapi.h
@@ -129,6 +129,8 @@ 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,