- Introduce locks around all pkcs11 operations, in case the caller

is multithreaded and wants to access us from different threads.


git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@912 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
okir 2003-02-17 14:21:38 +00:00
parent 5265456cab
commit cf6037314f
5 changed files with 421 additions and 175 deletions

View File

@ -32,15 +32,17 @@ extern CK_FUNCTION_LIST pkcs11_function_list;
CK_RV C_Initialize(CK_VOID_PTR pReserved)
{
int i, rc;
int i, rc, rv;
if (context != NULL) {
error(context, "C_Initialize(): Cryptoki already initialized\n");
return CKR_CRYPTOKI_ALREADY_INITIALIZED;
}
rc = sc_establish_context(&context, "opensc-pkcs11");
if (rc != 0)
return CKR_DEVICE_ERROR;
if (rc != 0) {
rv = CKR_DEVICE_ERROR;
goto out;
}
/* Load configuration */
load_pkcs11_parameters(&sc_pkcs11_conf, context);
@ -55,25 +57,34 @@ CK_RV C_Initialize(CK_VOID_PTR pReserved)
/* Detect any card, but do not flag "insert" events */
__card_detect_all(0);
debug(context, "Cryptoki initialized\n");
return CKR_OK;
rv = sc_pkcs11_init_lock((CK_C_INITIALIZE_ARGS_PTR) pReserved);
out: debug(context, "C_Initialize: result = %d\n", rv);
return rv;
}
CK_RV C_Finalize(CK_VOID_PTR pReserved)
{
int i;
sc_pkcs11_lock();
debug(context, "Shutting down Cryptoki\n");
for (i=0; i<context->reader_count; i++)
card_removed(i);
sc_release_context(context);
context = NULL;
sc_pkcs11_unlock();
sc_pkcs11_free_lock();
return CKR_OK;
}
CK_RV C_GetInfo(CK_INFO_PTR pInfo)
{
sc_pkcs11_lock();
debug(context, "Cryptoki info query\n");
memset(pInfo, 0, sizeof(CK_INFO));
@ -88,6 +99,7 @@ CK_RV C_GetInfo(CK_INFO_PTR pInfo)
pInfo->libraryVersion.major = 0;
pInfo->libraryVersion.minor = 2;
sc_pkcs11_unlock();
return CKR_OK;
}
@ -104,6 +116,9 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
CK_SLOT_ID found[SC_PKCS11_MAX_VIRTUAL_SLOTS];
int numMatches, i;
sc_pkcs11_slot_t *slot;
CK_RV rv;
sc_pkcs11_lock();
debug(context, "Getting slot listing\n");
card_detect_all();
@ -119,20 +134,25 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
if (pSlotList == NULL_PTR) {
debug(context, "was only a size inquiry (%d)\n", numMatches);
*pulCount = numMatches;
return CKR_OK;
rv = CKR_OK;
goto out;
}
if (*pulCount < numMatches) {
debug(context, "buffer was too small (needed %d)\n", numMatches);
*pulCount = numMatches;
return CKR_BUFFER_TOO_SMALL;
rv = CKR_BUFFER_TOO_SMALL;
goto out;
}
memcpy(pSlotList, found, numMatches * sizeof(CK_SLOT_ID));
*pulCount = numMatches;
rv = CKR_OK;
debug(context, "returned %d slots\n", numMatches);
return CKR_OK;
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
@ -140,19 +160,19 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
struct sc_pkcs11_slot *slot;
CK_RV rv;
rv = slot_get_slot(slotID, &slot);
if (rv != CKR_OK)
return rv;
if (!slot->card) {
rv = card_detect_all();
if (rv != CKR_OK)
return rv;
}
sc_pkcs11_lock();
debug(context, "Getting info about slot %d\n", slotID);
memcpy(pInfo, &slot->slot_info, sizeof(CK_SLOT_INFO));
return CKR_OK;
rv = slot_get_slot(slotID, &slot);
if (rv == CKR_OK && !slot->card)
rv = card_detect_all();
if (rv == CKR_OK)
memcpy(pInfo, &slot->slot_info, sizeof(CK_SLOT_INFO));
sc_pkcs11_unlock();
return rv;
}
CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
@ -160,13 +180,16 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
struct sc_pkcs11_slot *slot;
CK_RV rv;
rv = slot_get_token(slotID, &slot);
if (rv != CKR_OK)
return rv;
sc_pkcs11_lock();
debug(context, "Getting info about token in slot %d\n", slotID);
memcpy(pInfo, &slot->token_info, sizeof(CK_TOKEN_INFO));
return CKR_OK;
rv = slot_get_token(slotID, &slot);
if (rv == CKR_OK)
memcpy(pInfo, &slot->token_info, sizeof(CK_TOKEN_INFO));
sc_pkcs11_unlock();
return rv;
}
CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
@ -176,11 +199,14 @@ CK_RV C_GetMechanismList(CK_SLOT_ID slotID,
struct sc_pkcs11_slot *slot;
CK_RV rv;
rv = slot_get_token(slotID, &slot);
if (rv != CKR_OK)
return rv;
sc_pkcs11_lock();
return sc_pkcs11_get_mechanism_list(slot->card, pMechanismList, pulCount);
rv = slot_get_token(slotID, &slot);
if (rv == CKR_OK)
rv = sc_pkcs11_get_mechanism_list(slot->card, pMechanismList, pulCount);
sc_pkcs11_unlock();
return rv;
}
CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
@ -190,11 +216,14 @@ CK_RV C_GetMechanismInfo(CK_SLOT_ID slotID,
struct sc_pkcs11_slot *slot;
CK_RV rv;
rv = slot_get_token(slotID, &slot);
if (rv != CKR_OK)
return rv;
sc_pkcs11_lock();
return sc_pkcs11_get_mechanism_info(slot->card, type, pInfo);
rv = slot_get_token(slotID, &slot);
if (rv == CKR_OK)
rv = sc_pkcs11_get_mechanism_info(slot->card, type, pInfo);
sc_pkcs11_unlock();
return rv;
}
CK_RV C_InitToken(CK_SLOT_ID slotID,
@ -207,15 +236,19 @@ CK_RV C_InitToken(CK_SLOT_ID slotID,
struct sc_pkcs11_slot *slot;
CK_RV rv;
sc_pkcs11_lock();
rv = slot_get_token(slotID, &slot);
if (rv != CKR_OK)
return rv;
goto out;
/* Make sure there's no open session for this token */
for (item = session_pool.head; item; item = item->next) {
session = (struct sc_pkcs11_session*) item->item;
if (session->slot == slot)
return CKR_SESSION_EXISTS;
if (session->slot == slot) {
rv = CKR_SESSION_EXISTS;
goto out;
}
}
if (slot->card->framework->init_token == NULL)
@ -223,12 +256,13 @@ CK_RV C_InitToken(CK_SLOT_ID slotID,
rv = slot->card->framework->init_token(slot->card,
slot->fw_data, pPin, ulPinLen, pLabel);
if (rv != CKR_OK)
return rv;
if (rv == CKR_OK) {
/* Now we should re-bind all tokens so they get the
* corresponding function vector and flags */
}
/* Now we should re-bind all tokens so they get the
* corresponding function vector and flags */
return CKR_OK;
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */
@ -241,11 +275,13 @@ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */
unsigned int mask, events;
CK_RV rv;
sc_pkcs11_lock();
mask = SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED;
if ((rv = slot_find_changed(pSlot, mask)) == CKR_OK
|| (flags & CKF_DONT_BLOCK))
return rv;
goto out;
for (i = k = 0; i < context->reader_count; i++) {
reader = context->reader[i];
@ -255,16 +291,103 @@ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */
}
}
sc_pkcs11_unlock();
r = sc_wait_for_event(readers, slots, k, mask, &found, &events, -1);
sc_pkcs11_lock();
if (r != SC_SUCCESS) {
error(context, "sc_wait_for_event() returned %d\n", r);
return sc_to_cryptoki_error(r, -1);
rv = sc_to_cryptoki_error(r, -1);
goto out;
}
if ((rv = slot_find_changed(pSlot, mask)) == CKR_OK)
return rv;
if ((rv = slot_find_changed(pSlot, mask)) != CKR_OK)
rv = CKR_FUNCTION_FAILED;
return CKR_FUNCTION_FAILED;
out: sc_pkcs11_unlock();
return rv;
}
/*
* Locking functions
*/
#include "../libopensc/internal.h"
static CK_C_INITIALIZE_ARGS_PTR _locking;
static void * _lock = NULL;
CK_RV
sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR args)
{
int rv = CKR_OK;
if (_lock)
return CKR_OK;
/* No CK_C_INITIALIZE_ARGS pointer, no locking */
if (!args)
return CKR_OK;
if (args->pReserved)
return CKR_ARGUMENTS_BAD;
/* If the app tells us OS locking is okay,
* use that. Otherwise use the supplied functions.
*/
_locking = NULL;
if (args->flags & CKF_OS_LOCKING_OK) {
if (!(_lock = sc_mutex_new()))
rv = CKR_CANT_LOCK;
} else
if (args->CreateMutex
&& args->DestroyMutex
&& args->LockMutex
&& args->UnlockMutex) {
rv = args->CreateMutex(&_lock);
if (rv == CKR_OK)
_locking = args;
}
return rv;
}
void
sc_pkcs11_free_lock()
{
if (!_lock)
return;
if (_locking)
_locking->DestroyMutex(_lock);
else
sc_mutex_free((sc_mutex_t *) _lock);
_locking = NULL;
_lock = NULL;
}
void
sc_pkcs11_lock()
{
if (!_lock)
return;
if (_locking) {
while (_locking->LockMutex(_lock) != CKR_OK)
;
} else {
sc_mutex_lock((sc_mutex_t *) _lock);
}
}
void
sc_pkcs11_unlock()
{
if (!_lock)
return;
if (_locking) {
while (_locking->UnlockMutex(_lock) != CKR_OK)
;
} else {
sc_mutex_unlock((sc_mutex_t *) _lock);
}
}
CK_FUNCTION_LIST pkcs11_function_list = {

View File

@ -37,18 +37,22 @@ CK_RV C_CreateObject(CK_SESSION_HANDLE hSession, /* the session's handle */
struct sc_pkcs11_card *card;
int rv;
sc_pkcs11_lock();
dump_template("C_CreateObject()", pTemplate, ulCount);
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
card = session->slot->card;
if (card->framework->create_object == NULL)
return CKR_FUNCTION_NOT_SUPPORTED;
return card->framework->create_object(card, session->slot,
rv = CKR_FUNCTION_NOT_SUPPORTED;
else
rv = card->framework->create_object(card, session->slot,
pTemplate, ulCount, phObject);
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_CopyObject(CK_SESSION_HANDLE hSession, /* the session's handle */
@ -90,13 +94,15 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle
struct sc_pkcs11_object *object;
int res, res_type;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
rv = pool_find(&session->slot->object_pool, hObject, (void**) &object);
if (rv != CKR_OK)
return rv;
goto out;
res_type = 0;
for (i = 0; i < ulCount; i++) {
@ -125,6 +131,7 @@ CK_RV C_GetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle
}
}
out: sc_pkcs11_unlock();
return rv;
}
@ -137,24 +144,28 @@ CK_RV C_SetAttributeValue(CK_SESSION_HANDLE hSession, /* the session's handle
struct sc_pkcs11_session *session;
struct sc_pkcs11_object *object;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
rv = pool_find(&session->slot->object_pool, hObject, (void**) &object);
if (rv != CKR_OK)
return rv;
goto out;
if (object->ops->set_attribute == NULL)
return CKR_FUNCTION_NOT_SUPPORTED;
for (i = 0; i < ulCount; i++) {
rv = object->ops->set_attribute(session, object, &pTemplate[i]);
if (rv != CKR_OK)
return rv;
rv = CKR_FUNCTION_NOT_SUPPORTED;
else {
for (i = 0; i < ulCount; i++) {
rv = object->ops->set_attribute(session, object, &pTemplate[i]);
if (rv != CKR_OK)
break;
}
}
return CKR_OK;
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */
@ -170,9 +181,11 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */
struct sc_pkcs11_find_operation *operation;
struct sc_pkcs11_pool_item *item;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
debug(context, "C_FindObjectsInit(slot = %d)\n", session->slot->id);
dump_template("C_FindObjectsInit()", pTemplate, ulCount);
@ -180,9 +193,8 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */
rv = session_start_operation(session, SC_PKCS11_OPERATION_FIND,
&find_mechanism,
(struct sc_pkcs11_operation**) &operation);
if (rv != CKR_OK)
return rv;
goto out;
operation->current_handle = 0;
operation->num_handles = 0;
@ -234,7 +246,9 @@ CK_RV C_FindObjectsInit(CK_SESSION_HANDLE hSession, /* the session's handle */
}
debug(context, "%d matching objects\n", operation->num_handles);
return CKR_OK;
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's handle */
@ -246,14 +260,16 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's han
struct sc_pkcs11_session *session;
struct sc_pkcs11_find_operation *operation;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
rv = session_get_operation(session, SC_PKCS11_OPERATION_FIND,
(sc_pkcs11_operation_t **) &operation);
if (rv != CKR_OK)
return rv;
goto out;
to_return = operation->num_handles - operation->current_handle;
if (to_return > ulMaxObjectCount)
@ -267,7 +283,8 @@ CK_RV C_FindObjects(CK_SESSION_HANDLE hSession, /* the session's han
operation->current_handle += to_return;
return CKR_OK;
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */
@ -275,16 +292,18 @@ CK_RV C_FindObjectsFinal(CK_SESSION_HANDLE hSession) /* the session's handle */
int rv;
struct sc_pkcs11_session *session;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
rv = session_get_operation(session, SC_PKCS11_OPERATION_FIND, NULL);
if (rv != CKR_OK)
return rv;
if (rv == CKR_OK)
session_stop_operation(session, SC_PKCS11_OPERATION_FIND);
session_stop_operation(session, SC_PKCS11_OPERATION_FIND);
return CKR_OK;
out: sc_pkcs11_unlock();
return rv;
}
/*
@ -298,13 +317,14 @@ CK_RV C_DigestInit(CK_SESSION_HANDLE hSession, /* the session's handle */
int rv;
struct sc_pkcs11_session *session;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
rv = sc_pkcs11_md_init(session, pMechanism);
if (rv == CKR_OK)
rv = sc_pkcs11_md_init(session, pMechanism);
debug(context, "C_DigestInit returns %d\n", rv);
sc_pkcs11_unlock();
return rv;
}
@ -317,15 +337,19 @@ CK_RV C_Digest(CK_SESSION_HANDLE hSession, /* the session's handle */
int rv;
struct sc_pkcs11_session *session;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
rv = sc_pkcs11_md_update(session, pData, ulDataLen);
if (rv == CKR_OK)
rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen);
debug(context, "C_Digest returns %d\n", rv);
out: debug(context, "C_Digest returns %d\n", rv);
sc_pkcs11_unlock();
return rv;
}
@ -336,13 +360,14 @@ CK_RV C_DigestUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
int rv;
struct sc_pkcs11_session *session;
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
sc_pkcs11_lock();
rv = sc_pkcs11_md_update(session, pPart, ulPartLen);
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv == CKR_OK)
rv = sc_pkcs11_md_update(session, pPart, ulPartLen);
debug(context, "C_DigestUpdate returns %d\n", rv);
sc_pkcs11_unlock();
return rv;
}
@ -359,13 +384,14 @@ CK_RV C_DigestFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
int rv;
struct sc_pkcs11_session *session;
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
sc_pkcs11_lock();
rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen);
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv == CKR_OK)
rv = sc_pkcs11_md_final(session, pDigest, pulDigestLen);
debug(context, "C_DigestFinal returns %d\n", rv);
sc_pkcs11_unlock();
return rv;
}
@ -377,34 +403,42 @@ CK_RV C_SignInit(CK_SESSION_HANDLE hSession, /* the session's handle */
CK_KEY_TYPE key_type;
CK_ATTRIBUTE sign_attribute = { CKA_SIGN, &can_sign, sizeof(can_sign) };
CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) };
int rv;
struct sc_pkcs11_session *session;
struct sc_pkcs11_object *object;
int rv;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
rv = pool_find(&session->slot->object_pool, hKey, (void**) &object);
if (rv != CKR_OK)
return rv;
goto out;
if (object->ops->sign == NULL_PTR)
return CKR_KEY_TYPE_INCONSISTENT;
if (object->ops->sign == NULL_PTR) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
rv = object->ops->get_attribute(session, object, &sign_attribute);
if (rv != CKR_OK || !can_sign)
return CKR_KEY_TYPE_INCONSISTENT;
if (rv != CKR_OK || !can_sign) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
rv = object->ops->get_attribute(session, object, &key_type_attr);
if (rv != CKR_OK)
return CKR_KEY_TYPE_INCONSISTENT;
if (rv != CKR_OK) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
debug(context, "Sign operation initialized\n");
rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type);
debug(context, "Sign initialization returns %d\n", rv);
out: debug(context, "Sign initialization returns %d\n", rv);
sc_pkcs11_unlock();
return rv;
}
@ -418,9 +452,11 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */
struct sc_pkcs11_session *session;
CK_ULONG length;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
/* According to the pkcs11 specs, we must not do any calls that
* change our crypto state if the caller is just asking for the
@ -428,18 +464,20 @@ CK_RV C_Sign(CK_SESSION_HANDLE hSession, /* the session's handle */
* CKR_BUFFER_TOO_SMALL. Thus we cannot do the sign_update call
* below. */
if ((rv = sc_pkcs11_sign_size(session, &length)) != CKR_OK)
return rv;
goto out;
if (pSignature == NULL || length > *pulSignatureLen) {
*pulSignatureLen = length;
return pSignature? CKR_BUFFER_TOO_SMALL : CKR_OK;
rv = pSignature? CKR_BUFFER_TOO_SMALL : CKR_OK;
goto out;
}
rv = sc_pkcs11_sign_update(session, pData, ulDataLen);
if (rv == CKR_OK)
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
debug(context, "Signing result was %d\n", rv);
out: debug(context, "Signing result was %d\n", rv);
sc_pkcs11_unlock();
return rv;
}
@ -448,15 +486,17 @@ CK_RV C_SignUpdate(CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pPart, /* the data (digest) to be signed */
CK_ULONG ulPartLen) /* count of bytes to be signed */
{
int rv;
struct sc_pkcs11_session *session;
int rv;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
if (rv == CKR_OK)
rv = sc_pkcs11_sign_update(session, pPart, ulPartLen);
rv = sc_pkcs11_sign_update(session, pPart, ulPartLen);
debug(context, "C_SignUpdate returns %d\n", rv);
sc_pkcs11_unlock();
return rv;
}
@ -464,13 +504,15 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
CK_BYTE_PTR pSignature, /* receives the signature */
CK_ULONG_PTR pulSignatureLen) /* receives byte count of signature */
{
int rv;
struct sc_pkcs11_session *session;
CK_ULONG length;
int rv;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
/* According to the pkcs11 specs, we must not do any calls that
* change our crypto state if the caller is just asking for the
@ -478,16 +520,18 @@ CK_RV C_SignFinal(CK_SESSION_HANDLE hSession, /* the session's handle */
* CKR_BUFFER_TOO_SMALL.
*/
if ((rv = sc_pkcs11_sign_size(session, &length)) != CKR_OK)
return rv;
goto out;
if (pSignature == NULL || length > *pulSignatureLen) {
*pulSignatureLen = length;
return pSignature? CKR_BUFFER_TOO_SMALL : CKR_OK;
rv = pSignature? CKR_BUFFER_TOO_SMALL : CKR_OK;
} else {
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
}
out: debug(context, "C_SignFinal returns %d\n", rv);
sc_pkcs11_unlock();
rv = sc_pkcs11_sign_final(session, pSignature, pulSignatureLen);
debug(context, "C_SignFinal returns %d\n", rv);
return rv;
}
@ -499,28 +543,35 @@ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, /* the session's handle */
CK_KEY_TYPE key_type;
CK_ATTRIBUTE sign_attribute = { CKA_SIGN, &can_sign, sizeof(can_sign) };
CK_ATTRIBUTE key_type_attr = { CKA_KEY_TYPE, &key_type, sizeof(key_type) };
int rv;
struct sc_pkcs11_session *session;
struct sc_pkcs11_object *object;
int rv;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
rv = pool_find(&session->slot->object_pool, hKey, (void**) &object);
if (rv != CKR_OK)
return rv;
goto out;
if (object->ops->sign == NULL_PTR)
return CKR_KEY_TYPE_INCONSISTENT;
if (object->ops->sign == NULL_PTR) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
rv = object->ops->get_attribute(session, object, &sign_attribute);
if (rv != CKR_OK || !can_sign)
return CKR_KEY_TYPE_INCONSISTENT;
if (rv != CKR_OK || !can_sign) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
rv = object->ops->get_attribute(session, object, &key_type_attr);
if (rv != CKR_OK)
return CKR_KEY_TYPE_INCONSISTENT;
if (rv != CKR_OK) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
/* XXX: need to tell the signature algorithm that we want
* to recover the signature */
@ -528,7 +579,8 @@ CK_RV C_SignRecoverInit(CK_SESSION_HANDLE hSession, /* the session's handle */
rv = sc_pkcs11_sign_init(session, pMechanism, object, key_type);
debug(context, "Sign initialization returns %d\n", rv);
out: debug(context, "Sign initialization returns %d\n", rv);
sc_pkcs11_unlock();
return rv;
}
@ -681,21 +733,25 @@ CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, /* the session's handl
CK_ULONG ulAttributeCount, /* # of attributes in template */
CK_OBJECT_HANDLE_PTR phKey) /* gets handle of recovered key */
{
int rv;
struct sc_pkcs11_session *session;
struct sc_pkcs11_object *object, *result;
int rv;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
rv = pool_find(&session->slot->object_pool, hUnwrappingKey,
(void**) &object);
if (rv != CKR_OK)
return rv;
goto out;
if (object->ops->sign == NULL_PTR)
return CKR_KEY_TYPE_INCONSISTENT;
if (object->ops->sign == NULL_PTR) {
rv = CKR_KEY_TYPE_INCONSISTENT;
goto out;
}
rv = object->ops->unwrap_key(session, object, pMechanism,
pWrappedKey, ulWrappedKeyLen,
@ -704,10 +760,10 @@ CK_RV C_UnwrapKey(CK_SESSION_HANDLE hSession, /* the session's handl
debug(context, "Unwrapping result was %d\n", rv);
if (rv != CKR_OK)
return rv;
if (rv == CKR_OK)
rv = pool_insert(&session->slot->object_pool, result, phKey);
rv = pool_insert(&session->slot->object_pool, result, phKey);
out: sc_pkcs11_unlock();
return rv;
}
@ -729,11 +785,14 @@ CK_RV C_SeedRandom(CK_SESSION_HANDLE hSession, /* the session's handle */
struct sc_pkcs11_session *session;
int rv;
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
sc_pkcs11_lock();
return sc_pkcs11_openssl_add_seed_rand(session, pSeed, ulSeedLen);
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv == CKR_OK)
rv = sc_pkcs11_openssl_add_seed_rand(session, pSeed, ulSeedLen);
sc_pkcs11_unlock();
return rv;
#else
return CKR_FUNCTION_NOT_SUPPORTED;
#endif
@ -747,11 +806,14 @@ CK_RV C_GenerateRandom(CK_SESSION_HANDLE hSession, /* the session's handle */
struct sc_pkcs11_session *session;
int rv;
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
sc_pkcs11_lock();
return sc_pkcs11_openssl_add_gen_rand(session, RandomData, ulRandomLen);
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv == CKR_OK)
rv = sc_pkcs11_openssl_add_gen_rand(session, RandomData, ulRandomLen);
sc_pkcs11_unlock();
return rv;
#else
return CKR_FUNCTION_NOT_SUPPORTED;
#endif

View File

@ -33,18 +33,24 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */
struct sc_pkcs11_session *session;
int rv;
sc_pkcs11_lock();
debug(context, "Opening new session for slot %d\n", slotID);
if (!(flags & CKF_SERIAL_SESSION))
return CKR_SESSION_PARALLEL_NOT_SUPPORTED;
if (!(flags & CKF_SERIAL_SESSION)) {
rv = CKR_SESSION_PARALLEL_NOT_SUPPORTED;
goto out;
}
rv = slot_get_token(slotID, &slot);
if (rv != CKR_OK)
return rv;
goto out;
/* Check that no conflictions sessions exist */
if (!(flags & CKF_RW_SESSION) && (slot->login_user == CKU_SO))
return CKR_SESSION_READ_WRITE_SO_EXISTS;
if (!(flags & CKF_RW_SESSION) && (slot->login_user == CKU_SO)) {
rv = CKR_SESSION_READ_WRITE_SO_EXISTS;
goto out;
}
session = (struct sc_pkcs11_session*) malloc(sizeof(struct sc_pkcs11_session));
memset(session, 0, sizeof(struct sc_pkcs11_session));
@ -59,18 +65,21 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */
else
slot->nsessions++;
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */
{
struct sc_pkcs11_slot *slot;
int rv;
struct sc_pkcs11_session *session;
int rv;
sc_pkcs11_lock();
rv = pool_find_and_delete(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
debug(context, "C_CloseSession(slot %d)\n", session->slot->id);
@ -84,10 +93,14 @@ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */
}
free(session);
return CKR_OK;
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) /* the token's slot */
/* Internal version of C_CloseAllSessions that gets called with
* the global lock held */
CK_RV sc_pkcs11_close_all_sessions(CK_SLOT_ID slotID)
{
struct sc_pkcs11_pool_item *item, *next;
struct sc_pkcs11_session *session;
@ -105,15 +118,27 @@ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) /* the token's slot */
return CKR_OK;
}
CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) /* the token's slot */
{
int rv;
sc_pkcs11_lock();
rv = sc_pkcs11_close_all_sessions(slotID);
sc_pkcs11_unlock();
return rv;
}
CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */
CK_SESSION_INFO_PTR pInfo) /* receives session information */
{
int rv;
struct sc_pkcs11_session *session;
int rv;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
debug(context, "C_GetSessionInfo(slot %d).\n", session->slot->id);
pInfo->slotID = session->slot->id;
@ -133,7 +158,8 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */
? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION;
}
return CKR_OK;
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, /* the session's handle */
@ -161,22 +187,30 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
struct sc_pkcs11_session *session;
struct sc_pkcs11_slot *slot;
if (userType != CKU_USER && userType != CKU_SO)
return CKR_USER_TYPE_INVALID;
sc_pkcs11_lock();
if (userType != CKU_USER && userType != CKU_SO) {
rv = CKR_USER_TYPE_INVALID;
goto out;
}
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
debug(context, "Login for session %d\n", hSession);
slot = session->slot;
if (!(slot->token_info.flags & CKF_USER_PIN_INITIALIZED))
return CKR_USER_PIN_NOT_INITIALIZED;
if (!(slot->token_info.flags & CKF_USER_PIN_INITIALIZED)) {
rv = CKR_USER_PIN_NOT_INITIALIZED;
goto out;
}
if (slot->login_user >= 0)
return CKR_USER_ALREADY_LOGGED_IN;
if (slot->login_user >= 0) {
rv = CKR_USER_ALREADY_LOGGED_IN;
goto out;
}
rv = slot->card->framework->login(slot->card,
slot->fw_data,
@ -184,6 +218,7 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
if (rv == CKR_OK)
slot->login_user = userType;
out: sc_pkcs11_unlock();
return rv;
}
@ -193,19 +228,23 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) /* the session's handle */
struct sc_pkcs11_session *session;
struct sc_pkcs11_slot *slot;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
debug(context, "Logout for session %d\n", hSession);
slot = session->slot;
if (slot->login_user < 0)
return CKR_OK;
if (slot->login_user >= 0) {
slot->login_user = -1;
rv = slot->card->framework->logout(slot->card, slot->fw_data);
}
slot->login_user = -1;
return slot->card->framework->logout(slot->card, slot->fw_data);
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_InitPIN(CK_SESSION_HANDLE hSession,
@ -216,17 +255,25 @@ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession,
struct sc_pkcs11_slot *slot;
int rv;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
slot = session->slot;
if (slot->login_user != CKU_SO)
return CKR_USER_NOT_LOGGED_IN;
if (slot->card->framework->init_pin == NULL)
return CKR_FUNCTION_NOT_SUPPORTED;
return slot->card->framework->init_pin(slot->card, slot,
if (slot->login_user != CKU_SO) {
rv = CKR_USER_NOT_LOGGED_IN;
} else
if (slot->card->framework->init_pin == NULL) {
rv = CKR_FUNCTION_NOT_SUPPORTED;
} else {
rv = slot->card->framework->init_pin(slot->card, slot,
pPin, ulPinLen);
}
out: sc_pkcs11_unlock();
return rv;
}
CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
@ -239,18 +286,25 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
struct sc_pkcs11_session *session;
struct sc_pkcs11_slot *slot;
sc_pkcs11_lock();
rv = pool_find(&session_pool, hSession, (void**) &session);
if (rv != CKR_OK)
return rv;
goto out;
debug(context, "Changing PIN (session %d)\n", hSession);
#if 0
if (!(ses->flags & CKF_RW_SESSION))
return CKR_SESSION_READ_ONLY;
if (!(ses->flags & CKF_RW_SESSION)) {
rv = CKR_SESSION_READ_ONLY;
goto out;
}
#endif
slot = session->slot;
return slot->card->framework->change_pin(slot->card, slot->fw_data,
rv = slot->card->framework->change_pin(slot->card, slot->fw_data,
pOldPin, ulOldLen,
pNewPin, ulNewLen);
out: sc_pkcs11_unlock();
return rv;
}

View File

@ -314,6 +314,7 @@ CK_RV session_start_operation(struct sc_pkcs11_session *,
CK_RV session_get_operation(struct sc_pkcs11_session *, int,
struct sc_pkcs11_operation **);
CK_RV session_stop_operation(struct sc_pkcs11_session *, int);
CK_RV sc_pkcs11_close_all_sessions(CK_SLOT_ID);
/* Generic secret key stuff */
CK_RV sc_pkcs11_create_secret_key(struct sc_pkcs11_session *,
@ -372,6 +373,12 @@ CK_RV sc_pkcs11_openssl_add_gen_rand(struct sc_pkcs11_session *, CK_BYTE_PTR, CK
/* Load configuration defaults */
void load_pkcs11_parameters(struct sc_pkcs11_config *, struct sc_context *);
/* Locking primitives at the pkcs11 level */
CK_RV sc_pkcs11_init_lock(CK_C_INITIALIZE_ARGS_PTR);
void sc_pkcs11_lock(void);
void sc_pkcs11_unlock(void);
void sc_pkcs11_free_lock(void);
#ifdef __cplusplus
}
#endif

View File

@ -278,7 +278,7 @@ CK_RV slot_token_removed(int id)
token_was_present = (slot->slot_info.flags & CKF_TOKEN_PRESENT);
/* Terminate active sessions */
C_CloseAllSessions(id);
sc_pkcs11_close_all_sessions(id);
/* Object pool */
while (pool_find_and_delete(&slot->object_pool, 0, (void**) &object) == CKR_OK) {