summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ckcapi-key.c51
-rw-r--r--ckcapi-rsa.c4
-rw-r--r--ckcapi-session.c24
-rw-r--r--ckcapi-session.h4
-rw-r--r--ckcapi-token.c85
-rw-r--r--ckcapi-token.h6
-rw-r--r--ckcapi.c53
7 files changed, 201 insertions, 26 deletions
diff --git a/ckcapi-key.c b/ckcapi-key.c
index 89ef726..7618e1e 100644
--- a/ckcapi-key.c
+++ b/ckcapi-key.c
@@ -98,7 +98,8 @@ typedef struct _KeyObjectData
KeyObjectData;
static CK_RV
-load_key_handle (CkCapiObjectData* objdata, HCRYPTKEY* ret_key)
+load_key_handle (CkCapiObjectData* objdata, HCRYPTPROV* ret_prov,
+ HCRYPTKEY* ret_key)
{
KeyObjectData* kdata = (KeyObjectData*)objdata;
HCRYPTPROV prov;
@@ -106,6 +107,8 @@ load_key_handle (CkCapiObjectData* objdata, HCRYPTKEY* ret_key)
DWORD error;
ASSERT(kdata);
+ ASSERT(ret_key);
+ ASSERT(ret_prov);
if(!CryptAcquireContextW(&prov, kdata->prov_info->pwszContainerName,
kdata->prov_info->pwszProvName,
@@ -121,12 +124,9 @@ load_key_handle (CkCapiObjectData* objdata, HCRYPTKEY* ret_key)
return ckcapi_winerr_to_ckr(error);
}
- if(ret_key)
- *ret_key = key;
- else
- CryptDestroyKey(key);
+ *ret_key = key;
+ *ret_prov = prov;
- CryptReleaseContext(prov, 0);
return CKR_OK;
}
@@ -135,6 +135,7 @@ static CK_RV
load_raw_public_key(KeyObjectData* kdata)
{
BOOL success = FALSE;
+ HCRYPTPROV prov;
HCRYPTKEY key;
CK_RV ret;
DWORD error;
@@ -142,7 +143,7 @@ load_raw_public_key(KeyObjectData* kdata)
ASSERT(kdata);
ASSERT(!kdata->raw_public_key.pbData);
- ret = load_key_handle(&kdata->base, &key);
+ ret = load_key_handle(&kdata->base, &prov, &key);
if(ret != CKR_OK)
return ret;
@@ -161,6 +162,7 @@ load_raw_public_key(KeyObjectData* kdata)
}
}
+ CryptReleaseContext(prov, 0);
CryptDestroyKey(key);
if(success)
@@ -237,12 +239,13 @@ key_bool_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
{
KeyObjectData* kdata = (KeyObjectData*)objdata;
CK_BBOOL val;
- CK_BBOOL is_private;
+ CK_BBOOL is_private, is_rsa;
ASSERT(objdata);
ASSERT(attr);
is_private = (kdata->object_class == CKO_PRIVATE_KEY);
+ is_rsa = kdata->prov_info->dwProvType == PROV_RSA_FULL;
switch(attr->type)
{
@@ -268,7 +271,7 @@ key_bool_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
* - CKK_RSA but not CKK_DSA.
*/
case CKA_DECRYPT:
- val = CK_TRUE;
+ val = is_private && is_rsa;
break;
/*
@@ -281,6 +284,14 @@ key_bool_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
break;
/*
+ * Whether or not this key can be used to encrypt?.
+ * TODO: Support for RSA public keys.
+ */
+ case CKA_ENCRYPT:
+ val = CK_FALSE;
+ break;
+
+ /*
* Whether this key can be exported or not.
* TODO: We may want to support this for public keys.
*/
@@ -340,11 +351,10 @@ key_bool_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
/*
* Can this key sign recoverable.
- * - Private RSA keys can sign recoverable.
- * TODO: When implementing DSA more logic needed.
+ * TODO: Private RSA keys can sign recoverable.
*/
case CKA_SIGN_RECOVER:
- val = is_private;
+ val = CK_FALSE;
break;
/*
@@ -371,6 +381,21 @@ key_bool_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
case CKA_WRAP_WITH_TRUSTED:
return CKR_ATTRIBUTE_TYPE_INVALID;
+ /*
+ * Whether this key can be used to verify?
+ * TODO: Support for public keys.
+ */
+ case CKA_VERIFY:
+ val = CK_FALSE;
+ break;
+
+ /*
+ * Whether this key can be used to verify?
+ * TODO: Support for public keys.
+ */
+ case CKA_VERIFY_RECOVER:
+ val = CK_FALSE;
+ break;
default:
return CKR_ATTRIBUTE_TYPE_INVALID;
@@ -490,7 +515,7 @@ key_bytes_attribute(CkCapiObjectData* objdata, CK_ATTRIBUTE_PTR attr)
case CKA_EXPONENT_1:
case CKA_EXPONENT_2:
case CKA_COEFFICIENT:
- if(kdata->prov_info->dwProvType = PROV_RSA_FULL)
+ if(kdata->prov_info->dwProvType == PROV_RSA_FULL)
return lookup_rsa_attribute(kdata, attr);
else
return CKR_ATTRIBUTE_TYPE_INVALID;
diff --git a/ckcapi-rsa.c b/ckcapi-rsa.c
index 122ac53..032bf82 100644
--- a/ckcapi-rsa.c
+++ b/ckcapi-rsa.c
@@ -170,7 +170,7 @@ ckcapi_rsa_pkcs_sign_init(CkCapiObjectData *keydata, void** operation)
ASSERT(!*operation);
prov_info = ckcapi_key_object_data_get_prov_info(keydata);
- if(prov_info->dwProvType == PROV_RSA_FULL)
+ if(prov_info->dwProvType != PROV_RSA_FULL)
return CKR_KEY_TYPE_INCONSISTENT;
*operation = keydata;
@@ -302,7 +302,7 @@ ckcapi_rsa_pkcs_decrypt_init(CkCapiObjectData* keydata, void** operation)
ASSERT(!*operation);
prov_info = ckcapi_key_object_data_get_prov_info(keydata);
- if(prov_info->dwProvType == PROV_RSA_FULL)
+ if(prov_info->dwProvType != PROV_RSA_FULL)
return CKR_KEY_TYPE_INCONSISTENT;
*operation = keydata;
diff --git a/ckcapi-session.c b/ckcapi-session.c
index f4f00aa..064e477 100644
--- a/ckcapi-session.c
+++ b/ckcapi-session.c
@@ -212,6 +212,26 @@ ckcapi_session_destroy(CkCapiSession* sess)
free(sess);
}
+void
+ckcapi_session_get_info(CkCapiSession* sess, CK_SESSION_INFO_PTR info)
+{
+ ASSERT(sess);
+ ASSERT(info);
+
+ info->slotID = sess->slot;
+ info->flags = CKF_SERIAL_SESSION;
+ if(sess->read_write)
+ info->flags |= CKF_RW_SESSION;
+
+ if(ckcapi_token_is_logged_in(sess->slot))
+ info->state = sess->read_write ? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS;
+ else
+ info->state = sess->read_write ? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION;
+
+ /* TODO: We could implement some use of GetLastError() here */
+ info->ulDeviceError = 0;
+}
+
static CK_RV
lock_ref_internal(CkCapiArray* sessions, CK_SESSION_HANDLE id,
BOOL remove, BOOL writable, CkCapiSession** sess_ret)
@@ -824,8 +844,10 @@ ckcapi_session_sign_init(CkCapiSession* sess, CK_MECHANISM_PTR mech,
case CKM_RSA_PKCS:
ret = ckcapi_rsa_pkcs_sign_init(objdata, &ctx->mech_data);
ctx->mech_cleanup = ckcapi_rsa_pkcs_sign_cleanup;
+ break;
default:
ret = CKR_MECHANISM_INVALID;
+ break;
};
if(ret != CKR_OK)
@@ -904,8 +926,10 @@ ckcapi_session_decrypt_init(CkCapiSession* sess, CK_MECHANISM_PTR mech,
case CKM_RSA_PKCS:
ret = ckcapi_rsa_pkcs_decrypt_init(objdata, &ctx->mech_data);
ctx->mech_cleanup = ckcapi_rsa_pkcs_decrypt_cleanup;
+ break;
default:
ret = CKR_MECHANISM_INVALID;
+ break;
};
if(ret != CKR_OK)
diff --git a/ckcapi-session.h b/ckcapi-session.h
index 7b71c07..f486277 100644
--- a/ckcapi-session.h
+++ b/ckcapi-session.h
@@ -63,6 +63,10 @@ void ckcapi_session_destroy (CkCapiSession* sess);
/* Register a new session */
CK_RV ckcapi_session_register (CkCapiSession* sess);
+/* Get information about a session */
+void ckcapi_session_get_info (CkCapiSession* sess,
+ CK_SESSION_INFO_PTR info);
+
/* Get a session from a handle, and lock it */
CK_RV ckcapi_session_get_lock_ref (CK_ULONG id, BOOL writable,
CkCapiSession **sess);
diff --git a/ckcapi-token.c b/ckcapi-token.c
index a2beb74..4f0a7a3 100644
--- a/ckcapi-token.c
+++ b/ckcapi-token.c
@@ -23,6 +23,7 @@
static CkCapiArray* object_array = NULL;
static CkCapiHash* object_hash = NULL;
+static CkCapiArray* logged_in_slots = NULL;
typedef struct _SlotInfo
{
@@ -34,11 +35,11 @@ SlotInfo;
#define SLOT_OFFSET 0x00001000
-static const SlotInfo slot_info[] = {
+static SlotInfo slot_info[] = {
{ "My", "Personal Certificates", CKCAPI_SLOT_TRUSTED | CKCAPI_SLOT_CERTS },
{ "AddressBook", "Address Book Certificates", CKCAPI_SLOT_CERTS },
- { "CA", "Certificate Authorities", CKCAPI_SLOT_CA | CKCAPI_SLOT_CERTS},
- { "Root", "Root Authorities", CKCAPI_SLOT_TRUSTED | CKCAPI_SLOT_CA | CKCAPI_SLOT_CERTS},
+ { "CA", "Certificate Authorities", CKCAPI_SLOT_CA | CKCAPI_SLOT_CERTS },
+ { "Root", "Root Authorities", CKCAPI_SLOT_TRUSTED | CKCAPI_SLOT_CA | CKCAPI_SLOT_CERTS },
{ "Trust", "Trust", CKCAPI_SLOT_CERTS },
{ "TrustedPeople", "Trusted People", CKCAPI_SLOT_TRUSTED | CKCAPI_SLOT_CERTS },
{ "AuthRoot", "Auth Root", CKCAPI_SLOT_CERTS },
@@ -130,6 +131,12 @@ ckcapi_token_cleanup_all(void)
object_array = NULL;
}
+ if(logged_in_slots)
+ {
+ ckcapi_array_free(logged_in_slots, TRUE);
+ logged_in_slots = NULL;
+ }
+
ckcapi_unlock_global();
}
@@ -213,7 +220,7 @@ ckcapi_token_register_object(CK_SLOT_ID slot, CkCapiObject* obj)
/* Sanity check, in case calcs went wrong somewhere */
ASSERT(klen < 0xFFFFFF);
-/* xxxxx hash function xxxxx */
+
/* Look in the hash and find a previous object */
prev = ckcapi_hash_get(object_hash, key, klen);
if(prev)
@@ -267,3 +274,73 @@ ckcapi_token_register_object(CK_SLOT_ID slot, CkCapiObject* obj)
return ret;
}
+
+CK_BBOOL
+ckcapi_token_is_logged_in(CK_SLOT_ID slot)
+{
+ unsigned int count, offset;
+
+ ASSERT(ckcapi_token_is_valid(slot));
+
+ if(!logged_in_slots)
+ return CK_FALSE;
+
+ offset = SLOT_TO_OFFSET(slot);
+ count = ckcapi_token_get_count();
+
+ ASSERT(logged_in_slots->len == count && offset < count);
+ return ckcapi_array_index(logged_in_slots, CK_BBOOL, offset);
+}
+
+CK_RV
+ckcapi_token_login(CK_SLOT_ID slot)
+{
+ unsigned int i, count;
+ unsigned int offset;
+ CK_BBOOL value;
+
+ ASSERT(ckcapi_token_is_valid(slot));
+
+ offset = SLOT_TO_OFFSET(slot);
+ count = ckcapi_token_get_count();
+
+ if(!logged_in_slots)
+ {
+ logged_in_slots = ckcapi_array_sized_new(0, 1, sizeof(CK_BBOOL), count);
+ if(!logged_in_slots)
+ return CKR_HOST_MEMORY;
+
+ value = CK_FALSE;
+ for(i = 0; i < count; ++i)
+ ckcapi_array_append(logged_in_slots, value);
+
+ }
+
+ ASSERT(logged_in_slots->len == count && offset < count);
+ if(ckcapi_array_index(logged_in_slots, CK_BBOOL, offset))
+ return CKR_USER_ALREADY_LOGGED_IN;
+
+ ckcapi_array_index(logged_in_slots, CK_BBOOL, offset) = CK_TRUE;
+ return CKR_OK;
+}
+
+CK_RV
+ckcapi_token_logout(CK_SLOT_ID slot)
+{
+ unsigned int count, offset;
+
+ ASSERT(ckcapi_token_is_valid(slot));
+
+ if(!logged_in_slots)
+ return CKR_USER_NOT_LOGGED_IN;
+
+ offset = SLOT_TO_OFFSET(slot);
+ count = ckcapi_token_get_count();
+
+ ASSERT(logged_in_slots->len == count && offset < count);
+ if(!ckcapi_array_index(logged_in_slots, CK_BBOOL, offset))
+ return CKR_USER_NOT_LOGGED_IN;
+
+ ckcapi_array_index(logged_in_slots, CK_BBOOL, offset) = CK_FALSE;
+ return CKR_OK;
+}
diff --git a/ckcapi-token.h b/ckcapi-token.h
index 2024fa6..1176701 100644
--- a/ckcapi-token.h
+++ b/ckcapi-token.h
@@ -51,4 +51,10 @@ const char* ckcapi_token_get_store_name (CK_SLOT_ID slot);
CK_ULONG ckcapi_token_get_flags (CK_SLOT_ID slot);
+CK_RV ckcapi_token_login (CK_SLOT_ID slot);
+
+CK_RV ckcapi_token_logout (CK_SLOT_ID slot);
+
+CK_BBOOL ckcapi_token_is_logged_in (CK_SLOT_ID slot);
+
#endif /* CKCAPI_TOKEN_H */
diff --git a/ckcapi.c b/ckcapi.c
index 378746e..50df4d7 100644
--- a/ckcapi.c
+++ b/ckcapi.c
@@ -76,7 +76,7 @@ ckcapi_debug(const char* msg, ...)
strncpy(buf + len, "\n", 1024 - len);
buf[LINE - 1] = 0;
- OutputDebugStringA(buf);
+ // OutputDebugStringA(buf);
}
/* Bah humbug, MSVC doesn't have __func__ */
@@ -664,12 +664,21 @@ CC_C_CancelFunction(CK_SESSION_HANDLE session)
static CK_RV
CC_C_GetSessionInfo(CK_SESSION_HANDLE session, CK_SESSION_INFO_PTR info)
{
+ CkCapiSession* sess;
+ CK_RV ret;
+
ENTER(C_GetSessionInfo);
PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
PREREQ(info, CKR_ARGUMENTS_BAD);
- // TODO: Implement
- RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+ ret = ckcapi_session_get_lock_ref(session, FALSE, &sess);
+ if(ret == CKR_OK)
+ {
+ ckcapi_session_get_info(sess, info);
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
}
static CK_RV
@@ -721,21 +730,51 @@ static CK_RV
CC_C_Login(CK_SESSION_HANDLE session, CK_USER_TYPE user_type,
CK_UTF8CHAR_PTR pin, CK_ULONG pin_len)
{
+ CkCapiSession* sess;
+ CK_RV ret;
+
ENTER(C_Login);
PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
+
+ ret = ckcapi_session_get_lock_ref(session, FALSE, &sess);
+ if(ret == CKR_OK)
+ {
+ switch(user_type)
+ {
+ case CKU_USER:
+ ret = ckcapi_token_login(sess->slot);
+ break;
+ case CKU_SO:
+ ret = CKR_USER_TYPE_INVALID;
+ break;
+ default:
+ ret = CKR_USER_TYPE_INVALID;
+ break;
+ }
- /* TODO: Implement our local concept of logged in */
- RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
}
static CK_RV
CC_C_Logout(CK_SESSION_HANDLE session)
{
+ CkCapiSession* sess;
+ CK_RV ret;
+
ENTER(C_Logout);
PREREQ(cryptoki_initialized, CKR_CRYPTOKI_NOT_INITIALIZED);
- /* TODO: Implement our local concept of logged in */
- RETURN(CKR_FUNCTION_NOT_SUPPORTED);
+ ret = ckcapi_session_get_lock_ref(session, FALSE, &sess);
+ if(ret == CKR_OK)
+ {
+ ret = ckcapi_token_logout(sess->slot);
+ ckcapi_session_unref_unlock(sess);
+ }
+
+ RETURN(ret);
}
static CK_RV