pkcs11:
- slots, sessions and objects are kept as lists. - change the way slots, cards and readers are managed. - re-implement C_WaitForSlotEvent(/C_Finalize) as written in PCKS#11 v2.20, canceling pending blocking calls. - implement a "virtual hotplug slot" with a floating slot id to keep NSS working with C_WaitForSlotEvent with a new reader. NSS does not call C_GetSlotList(NULL) to re-fetch the list of available slots if C_WaitForSlotEvent returns an event in an already known slot ID. By changing the ID of a slot whenever a reader attached NSS/Firefox can be tricked into recognizing new readers when waiting for events with C_WaitForSlotEvent. - change (possibly break something) sc_to_cryptoki_error() to not have side-effects - Implement CKU_CONTEXT_SPECIFIC in C_Login to implement CKA_ALWAYS_AUTHENTICATE (keys with user consent) git-svn-id: https://www.opensc-project.org/svnp/opensc/trunk@3935 c6295689-39f2-0310-b995-f0e70906c6a9
This commit is contained in:
parent
0595eb7d1e
commit
0244baa494
|
@ -11,16 +11,18 @@ lib_LTLIBRARIES = opensc-pkcs11.la pkcs11-spy.la onepin-opensc-pkcs11.la
|
|||
noinst_LTLIBRARIES = libpkcs11.la
|
||||
|
||||
AM_CFLAGS = $(OPTIONAL_OPENSSL_CFLAGS) $(LTLIB_CFLAGS) $(PTHREAD_CFLAGS)
|
||||
INCLUDES = -I$(top_srcdir)/src/pkcs15init -I$(top_builddir)/src/include
|
||||
INCLUDES = -I$(top_srcdir)/src/pkcs15init -I$(top_builddir)/src/include -I$(top_builddir)/src/common
|
||||
|
||||
OPENSC_PKCS11_INC = sc-pkcs11.h
|
||||
OPENSC_PKCS11_SRC = pkcs11-global.c pkcs11-session.c pkcs11-object.c misc.c slot.c \
|
||||
mechanism.c openssl.c secretkey.c framework-pkcs15.c \
|
||||
framework-pkcs15init.c debug.c opensc-pkcs11.exports
|
||||
framework-pkcs15init.c debug.c opensc-pkcs11.exports \
|
||||
pkcs11-display.c pkcs11-display.h
|
||||
OPENSC_PKCS11_LIBS = $(OPTIONAL_OPENSSL_LIBS) $(PTHREAD_LIBS) \
|
||||
$(top_builddir)/src/pkcs15init/libpkcs15init.la \
|
||||
$(top_builddir)/src/libopensc/libopensc.la \
|
||||
$(top_builddir)/src/scconf/libscconf.la
|
||||
$(top_builddir)/src/scconf/libscconf.la \
|
||||
$(top_builddir)/src/common/libcompat.la
|
||||
|
||||
libpkcs11_la_SOURCES = libpkcs11.c
|
||||
|
||||
|
|
|
@ -163,7 +163,7 @@ static CK_RV pkcs15_bind(struct sc_pkcs11_card *p11card)
|
|||
rc = sc_pkcs15_bind(p11card->card, &fw_data->p15_card);
|
||||
sc_debug(context, "Binding to PKCS#15, rc=%d\n", rc);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
return register_mechanisms(p11card);
|
||||
}
|
||||
|
||||
|
@ -187,7 +187,7 @@ static CK_RV pkcs15_unbind(struct sc_pkcs11_card *p11card)
|
|||
|
||||
rc = sc_pkcs15_unbind(fw_data->p15_card);
|
||||
free(fw_data);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
static void pkcs15_init_token_info(struct sc_pkcs15_card *card, CK_TOKEN_INFO_PTR pToken)
|
||||
|
@ -634,19 +634,6 @@ check_cert_data_read(struct pkcs15_fw_data *fw_data,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int
|
||||
pool_is_present(struct sc_pkcs11_pool *pool, struct pkcs15_any_object *obj)
|
||||
{
|
||||
struct sc_pkcs11_pool_item *item;
|
||||
|
||||
for (item = pool->head; item != NULL; item = item->next) {
|
||||
if (obj == (struct pkcs15_any_object *) item->item)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void
|
||||
pkcs15_add_object(struct sc_pkcs11_slot *slot,
|
||||
struct pkcs15_any_object *obj,
|
||||
|
@ -659,10 +646,13 @@ pkcs15_add_object(struct sc_pkcs11_slot *slot,
|
|||
|| (obj->base.flags & (SC_PKCS11_OBJECT_HIDDEN | SC_PKCS11_OBJECT_RECURS)))
|
||||
return;
|
||||
|
||||
if (pool_is_present(&slot->object_pool, obj))
|
||||
|
||||
if (list_contains(&slot->objects, obj))
|
||||
return;
|
||||
|
||||
pool_insert(&slot->object_pool, obj, pHandle);
|
||||
list_append(&slot->objects, obj); // FIXME: pHandle too!
|
||||
sc_debug(context, "Setting object handle of 0x%lx to 0x%lx", obj->base.handle, (CK_OBJECT_HANDLE)obj);
|
||||
obj->base.handle = (CK_OBJECT_HANDLE)obj; // cast pointer to long
|
||||
obj->base.flags |= SC_PKCS11_OBJECT_SEEN;
|
||||
obj->refcount++;
|
||||
|
||||
|
@ -713,7 +703,7 @@ static void pkcs15_init_slot(struct sc_pkcs15_card *card,
|
|||
slot->token_info.flags |= CKF_TOKEN_INITIALIZED;
|
||||
if (auth != NULL)
|
||||
slot->token_info.flags |= CKF_USER_PIN_INITIALIZED;
|
||||
if (card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
|
||||
if (card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
|
||||
slot->token_info.flags |= CKF_PROTECTED_AUTHENTICATION_PATH;
|
||||
}
|
||||
if (card->card->caps & SC_CARD_CAP_RNG)
|
||||
|
@ -731,6 +721,7 @@ static void pkcs15_init_slot(struct sc_pkcs15_card *card,
|
|||
snprintf(tmp, sizeof(tmp), "%s", card->label);
|
||||
}
|
||||
slot->token_info.flags |= CKF_LOGIN_REQUIRED;
|
||||
/* FIXME: update this information during runtime */
|
||||
if (pin_info->tries_left >= 0) {
|
||||
if (pin_info->tries_left == 1)
|
||||
slot->token_info.flags |= CKF_USER_PIN_FINAL_TRY;
|
||||
|
@ -754,7 +745,7 @@ static void pkcs15_init_slot(struct sc_pkcs15_card *card,
|
|||
if (card->flags & SC_PKCS15_CARD_FLAG_EMULATED)
|
||||
slot->token_info.flags |= CKF_WRITE_PROTECTED;
|
||||
|
||||
sc_debug(context, "Initialized token '%s'\n", tmp);
|
||||
sc_debug(context, "Initialized token '%s' in slot 0x%lx", tmp, slot->id);
|
||||
}
|
||||
|
||||
static CK_RV pkcs15_create_slot(struct sc_pkcs11_card *p11card,
|
||||
|
@ -784,7 +775,7 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
|
|||
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) p11card->fw_data;
|
||||
struct sc_pkcs15_object *auths[MAX_OBJECTS];
|
||||
struct sc_pkcs11_slot *slot = NULL;
|
||||
int i, rv, reader = p11card->reader;
|
||||
int i, rv;
|
||||
int auth_count;
|
||||
int found_auth_count = 0;
|
||||
unsigned int j;
|
||||
|
@ -794,7 +785,7 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
|
|||
auths,
|
||||
SC_PKCS15_MAX_PINS);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
sc_debug(context, "Found %d authentication objects\n", rv);
|
||||
auth_count = rv;
|
||||
|
||||
|
@ -803,42 +794,42 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
|
|||
"private key",
|
||||
__pkcs15_create_prkey_object);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
rv = pkcs15_create_pkcs11_objects(fw_data,
|
||||
SC_PKCS15_TYPE_PUBKEY_RSA,
|
||||
"public key",
|
||||
__pkcs15_create_pubkey_object);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
rv = pkcs15_create_pkcs11_objects(fw_data,
|
||||
SC_PKCS15_TYPE_PRKEY_GOSTR3410,
|
||||
"private key",
|
||||
__pkcs15_create_prkey_object);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
rv = pkcs15_create_pkcs11_objects(fw_data,
|
||||
SC_PKCS15_TYPE_PUBKEY_GOSTR3410,
|
||||
"public key",
|
||||
__pkcs15_create_pubkey_object);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
rv = pkcs15_create_pkcs11_objects(fw_data,
|
||||
SC_PKCS15_TYPE_CERT_X509,
|
||||
"certificate",
|
||||
__pkcs15_create_cert_object);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
rv = pkcs15_create_pkcs11_objects(fw_data,
|
||||
SC_PKCS15_TYPE_DATA_OBJECT,
|
||||
"data object",
|
||||
__pkcs15_create_data_object);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
/* Match up related keys and certificates */
|
||||
pkcs15_bind_related_objects(fw_data);
|
||||
|
@ -921,7 +912,7 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
|
|||
}
|
||||
}
|
||||
|
||||
/* Create read/write slots */
|
||||
/* FIXME Create read/write slots
|
||||
while (slot_allocate(&slot, p11card) == CKR_OK) {
|
||||
if (!sc_pkcs11_conf.hide_empty_tokens && !(fw_data->p15_card->flags & SC_PKCS15_CARD_FLAG_EMULATED)) {
|
||||
slot->slot_info.flags |= CKF_TOKEN_PRESENT;
|
||||
|
@ -930,7 +921,7 @@ static CK_RV pkcs15_create_tokens(struct sc_pkcs11_card *p11card)
|
|||
slot->token_info.flags |= CKF_TOKEN_INITIALIZED;
|
||||
}
|
||||
}
|
||||
|
||||
*/
|
||||
sc_debug(context, "All tokens created\n");
|
||||
return CKR_OK;
|
||||
}
|
||||
|
@ -980,10 +971,10 @@ static CK_RV pkcs15_login(struct sc_pkcs11_card *p11card,
|
|||
}
|
||||
|
||||
sc_debug(context, "No SOPIN found; returns %d\n", rc);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
else if (rc < 0) {
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
break;
|
||||
|
@ -1003,13 +994,13 @@ static CK_RV pkcs15_login(struct sc_pkcs11_card *p11card,
|
|||
}
|
||||
#endif
|
||||
sc_debug(context, "context specific login returns %d\n", rc);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
default:
|
||||
return CKR_USER_TYPE_INVALID;
|
||||
}
|
||||
pin = (struct sc_pkcs15_pin_info *) auth_object->data;
|
||||
|
||||
if (p11card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
|
||||
if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
|
||||
/* pPin should be NULL in case of a pin pad reader, but
|
||||
* some apps (e.g. older Netscapes) don't know about it.
|
||||
* So we don't require that pPin == NULL, but set it to
|
||||
|
@ -1038,11 +1029,11 @@ static CK_RV pkcs15_login(struct sc_pkcs11_card *p11card,
|
|||
* Otherwise an attacker could perform some crypto operation
|
||||
* after we've authenticated with the card */
|
||||
if (sc_pkcs11_conf.lock_login && (rc = lock_card(fw_data)) < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
|
||||
rc = sc_pkcs15_verify_pin(card, pin, pPin, ulPinLen);
|
||||
sc_debug(context, "PKCS15 verify PIN returned %d\n", rc);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
static CK_RV pkcs15_logout(struct sc_pkcs11_card *p11card, void *fw_token)
|
||||
|
@ -1058,7 +1049,7 @@ static CK_RV pkcs15_logout(struct sc_pkcs11_card *p11card, void *fw_token)
|
|||
|
||||
if (sc_pkcs11_conf.lock_login)
|
||||
rc = unlock_card(fw_data);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card,
|
||||
|
@ -1073,7 +1064,7 @@ static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card,
|
|||
if (!(pin = slot_data_pin_info(fw_token)))
|
||||
return CKR_USER_PIN_NOT_INITIALIZED;
|
||||
|
||||
if (p11card->card->slot->capabilities & SC_SLOT_CAP_PIN_PAD) {
|
||||
if (p11card->card->reader->capabilities & SC_READER_CAP_PIN_PAD) {
|
||||
/* pPin should be NULL in case of a pin pad reader, but
|
||||
* some apps (e.g. older Netscapes) don't know about it.
|
||||
* So we don't require that pPin == NULL, but set it to
|
||||
|
@ -1110,7 +1101,7 @@ static CK_RV pkcs15_change_pin(struct sc_pkcs11_card *p11card,
|
|||
}
|
||||
|
||||
sc_debug(context, "PIN change returns %d\n", rc);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
#ifdef USE_PKCS15_INIT
|
||||
|
@ -1139,21 +1130,21 @@ static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card,
|
|||
* of ISO 'RESET RETRY COUNTER' command. */
|
||||
rc = sc_pkcs15_unblock_pin(fw_data->p15_card, pin_info, NULL, 0, pPin, ulPinLen);
|
||||
#else
|
||||
return sc_to_cryptoki_error(SC_ERROR_NOT_SUPPORTED, p11card->reader);
|
||||
return sc_to_cryptoki_error(SC_ERROR_NOT_SUPPORTED);
|
||||
#endif
|
||||
}
|
||||
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
rc = sc_lock(p11card->card);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
|
||||
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
|
||||
if (rc < 0) {
|
||||
sc_unlock(p11card->card);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
memset(&args, 0, sizeof(args));
|
||||
|
@ -1165,11 +1156,11 @@ static CK_RV pkcs15_init_pin(struct sc_pkcs11_card *p11card,
|
|||
sc_pkcs15init_unbind(profile);
|
||||
sc_unlock(p11card->card);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
|
||||
rc = sc_pkcs15_find_pin_by_auth_id(fw_data->p15_card, &args.auth_id, &auth_obj);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
|
||||
/* Re-initialize the slot */
|
||||
free(slot->fw_data);
|
||||
|
@ -1262,7 +1253,7 @@ static CK_RV pkcs15_create_private_key(struct sc_pkcs11_card *p11card,
|
|||
|
||||
rc = sc_pkcs15init_store_private_key(fw_data->p15_card, profile, &args, &key_obj);
|
||||
if (rc < 0) {
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1351,7 +1342,7 @@ static CK_RV pkcs15_create_public_key(struct sc_pkcs11_card *p11card,
|
|||
|
||||
rc = sc_pkcs15init_store_public_key(fw_data->p15_card, profile, &args, &key_obj);
|
||||
if (rc < 0) {
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -1429,7 +1420,7 @@ static CK_RV pkcs15_create_certificate(struct sc_pkcs11_card *p11card,
|
|||
|
||||
rc = sc_pkcs15init_store_certificate(fw_data->p15_card, profile, &args, &cert_obj);
|
||||
if (rc < 0) {
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
goto out;
|
||||
}
|
||||
/* Create a new pkcs11 object for it */
|
||||
|
@ -1511,7 +1502,7 @@ static CK_RV pkcs15_create_data(struct sc_pkcs11_card *p11card,
|
|||
|
||||
rc = sc_pkcs15init_store_data_object(fw_data->p15_card, profile, &args, &data_obj);
|
||||
if (rc < 0) {
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
goto out;
|
||||
}
|
||||
/* Create a new pkcs11 object for it */
|
||||
|
@ -1538,13 +1529,13 @@ static CK_RV pkcs15_create_object(struct sc_pkcs11_card *p11card,
|
|||
|
||||
rc = sc_lock(p11card->card);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
|
||||
/* Bind the profile */
|
||||
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
|
||||
if (rc < 0) {
|
||||
sc_unlock(p11card->card);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
/* Add the PINs the user presented so far to the keycache. */
|
||||
|
@ -1694,12 +1685,12 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
|
|||
|
||||
rc = sc_lock(p11card->card);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
|
||||
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
|
||||
if (rc < 0) {
|
||||
sc_unlock(p11card->card);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
memset(&keygen_args, 0, sizeof(keygen_args));
|
||||
|
@ -1791,13 +1782,13 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
|
|||
rc = sc_pkcs15_find_pubkey_by_id(fw_data->p15_card, &id, &pub_key_obj);
|
||||
if (rc != 0) {
|
||||
sc_debug(context, "sc_pkcs15_find_pubkey_by_id returned %d\n", rc);
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
goto kpgen_done;
|
||||
}
|
||||
}
|
||||
else if (rc != SC_ERROR_NOT_SUPPORTED) {
|
||||
sc_debug(context, "sc_pkcs15init_generate_key returned %d\n", rc);
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
goto kpgen_done;
|
||||
}
|
||||
else {
|
||||
|
@ -1836,7 +1827,7 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
|
|||
}
|
||||
if (rc < 0) {
|
||||
sc_debug(context, "private/public keys not stored: %d\n", rc);
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
goto kpgen_done;
|
||||
}
|
||||
}
|
||||
|
@ -1848,7 +1839,7 @@ static CK_RV pkcs15_gen_keypair(struct sc_pkcs11_card *p11card,
|
|||
rc = __pkcs15_create_pubkey_object(fw_data, pub_key_obj, &pub_any_obj);
|
||||
if (rc != 0) {
|
||||
sc_debug(context, "__pkcs15_create_pr/pubkey_object returned %d\n", rc);
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
goto kpgen_done;
|
||||
}
|
||||
pkcs15_add_object(slot, priv_any_obj, phPrivKey);
|
||||
|
@ -1872,7 +1863,7 @@ static CK_RV pkcs15_get_random(struct sc_pkcs11_card *p11card,
|
|||
struct sc_card *card = fw_data->p15_card->card;
|
||||
|
||||
rc = sc_get_challenge(card, p, (size_t)len);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
struct sc_pkcs11_framework_ops framework_pkcs15 = {
|
||||
|
@ -1913,12 +1904,12 @@ static CK_RV pkcs15_set_attrib(struct sc_pkcs11_session *session,
|
|||
|
||||
rc = sc_lock(p11card->card);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
|
||||
rc = sc_pkcs15init_bind(p11card->card, "pkcs15", NULL, &profile);
|
||||
if (rc < 0) {
|
||||
sc_unlock(p11card->card);
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
/* Add the PINs the user presented so far to the keycache. */
|
||||
|
@ -1947,7 +1938,7 @@ static CK_RV pkcs15_set_attrib(struct sc_pkcs11_session *session,
|
|||
goto set_attr_done;
|
||||
}
|
||||
|
||||
rv = sc_to_cryptoki_error(rc, p11card->reader);
|
||||
rv = sc_to_cryptoki_error(rc);
|
||||
|
||||
set_attr_done:
|
||||
sc_pkcs15init_unbind(profile);
|
||||
|
@ -2340,13 +2331,13 @@ static CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
|
|||
|
||||
rv = sc_lock(ses->slot->card->card);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, ses->slot->card->reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
if (!sc_pkcs11_conf.lock_login) {
|
||||
rv = reselect_app_df(fw_data->p15_card);
|
||||
if (rv < 0) {
|
||||
sc_unlock(ses->slot->card->card);
|
||||
return sc_to_cryptoki_error(rv, ses->slot->card->reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2368,7 +2359,7 @@ static CK_RV pkcs15_prkey_sign(struct sc_pkcs11_session *ses, void *obj,
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
return sc_to_cryptoki_error(rv, ses->slot->card->reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
}
|
||||
|
||||
static CK_RV
|
||||
|
@ -2408,13 +2399,13 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *ses, void *obj,
|
|||
|
||||
rv = sc_lock(ses->slot->card->card);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, ses->slot->card->reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
if (!sc_pkcs11_conf.lock_login) {
|
||||
rv = reselect_app_df(fw_data->p15_card);
|
||||
if (rv < 0) {
|
||||
sc_unlock(ses->slot->card->card);
|
||||
return sc_to_cryptoki_error(rv, ses->slot->card->reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2427,7 +2418,7 @@ pkcs15_prkey_decrypt(struct sc_pkcs11_session *ses, void *obj,
|
|||
sc_debug(context, "Key unwrap/decryption complete. Result %d.\n", rv);
|
||||
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, ses->slot->card->reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
buff_too_small = (*pulDataLen < (CK_ULONG)rv);
|
||||
*pulDataLen = rv;
|
||||
|
@ -2455,7 +2446,7 @@ pkcs15_prkey_unwrap(struct sc_pkcs11_session *ses, void *obj,
|
|||
unwrapped_key, &key_len);
|
||||
|
||||
if (r < 0)
|
||||
return sc_to_cryptoki_error(r, ses->slot->card->reader);
|
||||
return sc_to_cryptoki_error(r);
|
||||
return sc_pkcs11_create_secret_key(ses,
|
||||
unwrapped_key, key_len,
|
||||
pTemplate, ulAttributeCount,
|
||||
|
@ -2665,20 +2656,19 @@ static int pkcs15_dobj_get_value(struct sc_pkcs11_session *session,
|
|||
struct pkcs15_fw_data *fw_data =
|
||||
(struct pkcs15_fw_data *) session->slot->card->fw_data;
|
||||
sc_card_t *card = session->slot->card->card;
|
||||
int reader = session->slot->card->reader;
|
||||
|
||||
if (!out_data)
|
||||
return SC_ERROR_INVALID_ARGUMENTS;
|
||||
|
||||
rv = sc_lock(card);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
rv = sc_pkcs15_read_data_object(fw_data->p15_card, dobj->info, out_data);
|
||||
|
||||
sc_unlock(card);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
@ -2775,18 +2765,17 @@ static CK_RV pkcs15_dobj_destroy(struct sc_pkcs11_session *session, void *object
|
|||
struct sc_pkcs11_card *card = session->slot->card;
|
||||
struct pkcs15_fw_data *fw_data = (struct pkcs15_fw_data *) card->fw_data;
|
||||
struct sc_profile *profile = NULL;
|
||||
int reader = session->slot->card->reader;
|
||||
int rv;
|
||||
|
||||
rv = sc_lock(card->card);
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, card->reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
/* Bind the profile */
|
||||
rv = sc_pkcs15init_bind(card->card, "pkcs15", NULL, &profile);
|
||||
if (rv < 0) {
|
||||
sc_unlock(card->card);
|
||||
return sc_to_cryptoki_error(rv, card->reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
}
|
||||
|
||||
/* Add the PINs the user presented so far to the keycache */
|
||||
|
@ -2794,7 +2783,6 @@ static CK_RV pkcs15_dobj_destroy(struct sc_pkcs11_session *session, void *object
|
|||
|
||||
/* Delete object in smartcard */
|
||||
rv = sc_pkcs15init_delete_object(fw_data->p15_card, profile, obj->base.p15_object);
|
||||
/* FIXME: PIN revalidation missing, following belongs libopensc */
|
||||
if (rv >= 0) {
|
||||
/* pool_find_and_delete is called, therefore correct refcont
|
||||
* Oppose to pkcs15_add_object */
|
||||
|
@ -2807,7 +2795,7 @@ static CK_RV pkcs15_dobj_destroy(struct sc_pkcs11_session *session, void *object
|
|||
sc_unlock(card->card);
|
||||
|
||||
if (rv < 0)
|
||||
return sc_to_cryptoki_error(rv, reader);
|
||||
return sc_to_cryptoki_error(rv);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ static CK_RV pkcs15init_bind(struct sc_pkcs11_card *p11card)
|
|||
rc = sc_pkcs15init_bind(card, "pkcs15", NULL, &profile);
|
||||
if (rc == 0)
|
||||
p11card->fw_data = profile;
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
static CK_RV pkcs15init_unbind(struct sc_pkcs11_card *p11card)
|
||||
|
@ -134,7 +134,7 @@ pkcs15init_initialize(struct sc_pkcs11_card *p11card, void *ptr,
|
|||
args.label = (const char *) pLabel;
|
||||
rc = sc_pkcs15init_add_app(p11card->card, profile, &args);
|
||||
if (rc < 0)
|
||||
return sc_to_cryptoki_error(rc, p11card->reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
|
||||
/* Change the binding from the pkcs15init framework
|
||||
* to the pkcs15 framework on the fly.
|
||||
|
|
|
@ -52,7 +52,7 @@ sc_pkcs11_register_mechanism(struct sc_pkcs11_card *p11card,
|
|||
* Look up a mechanism
|
||||
*/
|
||||
sc_pkcs11_mechanism_type_t *
|
||||
sc_pkcs11_find_mechanism(struct sc_pkcs11_card *p11card, CK_MECHANISM_TYPE mech, int flags)
|
||||
sc_pkcs11_find_mechanism(struct sc_pkcs11_card *p11card, CK_MECHANISM_TYPE mech, unsigned int flags)
|
||||
{
|
||||
sc_pkcs11_mechanism_type_t *mt;
|
||||
unsigned int n;
|
||||
|
@ -199,7 +199,7 @@ sc_pkcs11_md_final(struct sc_pkcs11_session *session,
|
|||
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
|
||||
{
|
||||
sc_pkcs11_operation_t *op;
|
||||
int rv;
|
||||
CK_RV rv;
|
||||
|
||||
rv = session_get_operation(session, SC_PKCS11_OPERATION_DIGEST, &op);
|
||||
if (rv != CKR_OK)
|
||||
|
@ -793,7 +793,7 @@ sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE mech,
|
|||
#endif
|
||||
}
|
||||
if (pInfo->flags & CKF_UNWRAP) {
|
||||
/* ... */
|
||||
/* TODO */
|
||||
}
|
||||
if (pInfo->flags & CKF_DECRYPT) {
|
||||
mt->decrypt_init = sc_pkcs11_decrypt_init;
|
||||
|
|
|
@ -24,22 +24,23 @@
|
|||
|
||||
#define DUMP_TEMPLATE_MAX 32
|
||||
|
||||
void strcpy_bp(u8 *dst, const char *src, size_t dstsize)
|
||||
void strcpy_bp(u8 * dst, const char *src, size_t dstsize)
|
||||
{
|
||||
size_t c;
|
||||
|
||||
if (!dst || !src || !dstsize)
|
||||
return;
|
||||
|
||||
memset((char *) dst, ' ', dstsize);
|
||||
|
||||
memset((char *)dst, ' ', dstsize);
|
||||
|
||||
c = strlen(src) > dstsize ? dstsize : strlen(src);
|
||||
|
||||
memcpy((char *) dst, src, c);
|
||||
|
||||
memcpy((char *)dst, src, c);
|
||||
}
|
||||
|
||||
CK_RV sc_to_cryptoki_error(int rc, int reader)
|
||||
CK_RV sc_to_cryptoki_error(int rc)
|
||||
{
|
||||
sc_debug(context, "opensc error: %s (%d)\n", sc_strerror(rc), rc);
|
||||
switch (rc) {
|
||||
case SC_SUCCESS:
|
||||
return CKR_OK;
|
||||
|
@ -54,7 +55,6 @@ CK_RV sc_to_cryptoki_error(int rc, int reader)
|
|||
case SC_ERROR_BUFFER_TOO_SMALL:
|
||||
return CKR_BUFFER_TOO_SMALL;
|
||||
case SC_ERROR_CARD_NOT_PRESENT:
|
||||
card_removed(reader);
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
case SC_ERROR_INVALID_CARD:
|
||||
return CKR_TOKEN_NOT_RECOGNIZED;
|
||||
|
@ -77,105 +77,29 @@ CK_RV sc_to_cryptoki_error(int rc, int reader)
|
|||
case SC_ERROR_INCORRECT_PARAMETERS:
|
||||
return CKR_DATA_INVALID;
|
||||
case SC_ERROR_CARD_UNRESPONSIVE:
|
||||
case SC_ERROR_READER_LOCKED:
|
||||
return CKR_DEVICE_ERROR;
|
||||
case SC_ERROR_READER_DETACHED:
|
||||
return CKR_TOKEN_NOT_PRESENT; /* Maybe CKR_DEVICE_REMOVED ? */
|
||||
case SC_ERROR_NOT_ENOUGH_MEMORY:
|
||||
return CKR_DEVICE_MEMORY;
|
||||
case SC_ERROR_MEMORY_FAILURE: /* EEPROM has failed */
|
||||
case SC_ERROR_MEMORY_FAILURE: /* EEPROM has failed */
|
||||
return CKR_DEVICE_ERROR;
|
||||
}
|
||||
sc_debug(context, "opensc error: %s (%d)\n", sc_strerror(rc), rc);
|
||||
return CKR_GENERAL_ERROR;
|
||||
}
|
||||
|
||||
/* Pool */
|
||||
CK_RV pool_initialize(struct sc_pkcs11_pool *pool, int type)
|
||||
{
|
||||
pool->type = type;
|
||||
pool->next_free_handle = 1;
|
||||
pool->num_items = 0;
|
||||
pool->head = pool->tail = NULL;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV pool_insert(struct sc_pkcs11_pool *pool, void *item_ptr, CK_ULONG_PTR pHandle)
|
||||
{
|
||||
struct sc_pkcs11_pool_item *item;
|
||||
int handle = pool->next_free_handle++;
|
||||
|
||||
item = (struct sc_pkcs11_pool_item*) malloc(sizeof(struct sc_pkcs11_pool_item));
|
||||
|
||||
if (pHandle != NULL)
|
||||
*pHandle = handle;
|
||||
|
||||
item->handle = handle;
|
||||
item->item = item_ptr;
|
||||
item->next = NULL;
|
||||
item->prev = pool->tail;
|
||||
|
||||
if (pool->head != NULL && pool->tail != NULL) {
|
||||
pool->tail->next = item;
|
||||
pool->tail = item;
|
||||
} else
|
||||
pool->head = pool->tail = item;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV pool_find(struct sc_pkcs11_pool *pool, CK_ULONG handle, void **item_ptr)
|
||||
{
|
||||
struct sc_pkcs11_pool_item *item;
|
||||
|
||||
if (context == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
for (item = pool->head; item != NULL; item = item->next) {
|
||||
if (item->handle == handle) {
|
||||
*item_ptr = item->item;
|
||||
return CKR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return (pool->type == POOL_TYPE_OBJECT)? CKR_OBJECT_HANDLE_INVALID
|
||||
: CKR_SESSION_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
CK_RV pool_find_and_delete(struct sc_pkcs11_pool *pool, CK_ULONG handle, void **item_ptr)
|
||||
{
|
||||
struct sc_pkcs11_pool_item *item;
|
||||
|
||||
if (context == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
for (item = pool->head; item != NULL; item = item->next) {
|
||||
if (handle == 0 || item->handle == handle) {
|
||||
if (item->prev) item->prev->next = item->next;
|
||||
if (item->next) item->next->prev = item->prev;
|
||||
if (pool->head == item) pool->head = item->next;
|
||||
if (pool->tail == item) pool->tail = item->prev;
|
||||
|
||||
*item_ptr = item->item;
|
||||
free(item);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
}
|
||||
|
||||
return (pool->type == POOL_TYPE_OBJECT)? CKR_OBJECT_HANDLE_INVALID
|
||||
: CKR_SESSION_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
/* Session manipulation */
|
||||
CK_RV session_start_operation(struct sc_pkcs11_session *session,
|
||||
int type,
|
||||
sc_pkcs11_mechanism_type_t *mech,
|
||||
struct sc_pkcs11_operation **operation)
|
||||
CK_RV session_start_operation(struct sc_pkcs11_session * session,
|
||||
int type, sc_pkcs11_mechanism_type_t * mech, struct sc_pkcs11_operation ** operation)
|
||||
{
|
||||
sc_pkcs11_operation_t *op;
|
||||
|
||||
if (context == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
SC_FUNC_CALLED(context, 3);
|
||||
sc_debug(context, "Session 0x%lx, type %d", session->handle, type);
|
||||
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
|
@ -192,11 +116,12 @@ CK_RV session_start_operation(struct sc_pkcs11_session *session,
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV session_get_operation(struct sc_pkcs11_session *session, int type,
|
||||
sc_pkcs11_operation_t **operation)
|
||||
CK_RV session_get_operation(struct sc_pkcs11_session * session, int type, sc_pkcs11_operation_t ** operation)
|
||||
{
|
||||
sc_pkcs11_operation_t *op;
|
||||
|
||||
SC_FUNC_CALLED(context, 3);
|
||||
|
||||
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
||||
|
@ -209,7 +134,7 @@ CK_RV session_get_operation(struct sc_pkcs11_session *session, int type,
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV session_stop_operation(struct sc_pkcs11_session *session, int type)
|
||||
CK_RV session_stop_operation(struct sc_pkcs11_session * session, int type)
|
||||
{
|
||||
if (type < 0 || type >= SC_PKCS11_OPERATION_MAX)
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
|
@ -221,9 +146,9 @@ CK_RV session_stop_operation(struct sc_pkcs11_session *session, int type)
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV attr_extract(CK_ATTRIBUTE_PTR pAttr, void *ptr, size_t *sizep)
|
||||
CK_RV attr_extract(CK_ATTRIBUTE_PTR pAttr, void *ptr, size_t * sizep)
|
||||
{
|
||||
unsigned int size;
|
||||
unsigned int size;
|
||||
|
||||
if (sizep) {
|
||||
size = *sizep;
|
||||
|
@ -233,17 +158,23 @@ CK_RV attr_extract(CK_ATTRIBUTE_PTR pAttr, void *ptr, size_t *sizep)
|
|||
} else {
|
||||
switch (pAttr->type) {
|
||||
case CKA_CLASS:
|
||||
size = sizeof(CK_OBJECT_CLASS); break;
|
||||
size = sizeof(CK_OBJECT_CLASS);
|
||||
break;
|
||||
case CKA_KEY_TYPE:
|
||||
size = sizeof(CK_KEY_TYPE); break;
|
||||
size = sizeof(CK_KEY_TYPE);
|
||||
break;
|
||||
case CKA_PRIVATE:
|
||||
size = sizeof(CK_BBOOL); break;
|
||||
size = sizeof(CK_BBOOL);
|
||||
break;
|
||||
case CKA_CERTIFICATE_TYPE:
|
||||
size = sizeof(CK_CERTIFICATE_TYPE); break;
|
||||
size = sizeof(CK_CERTIFICATE_TYPE);
|
||||
break;
|
||||
case CKA_MODULUS_BITS:
|
||||
size = sizeof(CK_ULONG); break;
|
||||
size = sizeof(CK_ULONG);
|
||||
break;
|
||||
case CKA_OBJECT_ID:
|
||||
size = sizeof(struct sc_object_id); break;
|
||||
size = sizeof(struct sc_object_id);
|
||||
break;
|
||||
default:
|
||||
return CKR_FUNCTION_FAILED;
|
||||
}
|
||||
|
@ -254,10 +185,9 @@ CK_RV attr_extract(CK_ATTRIBUTE_PTR pAttr, void *ptr, size_t *sizep)
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV attr_find(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
||||
CK_ULONG type, void *ptr, size_t *sizep)
|
||||
CK_RV attr_find(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void *ptr, size_t * sizep)
|
||||
{
|
||||
unsigned int n;
|
||||
unsigned int n;
|
||||
|
||||
for (n = 0; n < ulCount; n++, pTemplate++) {
|
||||
if (pTemplate->type == type)
|
||||
|
@ -270,11 +200,10 @@ CK_RV attr_find(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|||
}
|
||||
|
||||
CK_RV attr_find2(CK_ATTRIBUTE_PTR pTemp1, CK_ULONG ulCount1,
|
||||
CK_ATTRIBUTE_PTR pTemp2, CK_ULONG ulCount2,
|
||||
CK_ULONG type, void *ptr, size_t *sizep)
|
||||
CK_ATTRIBUTE_PTR pTemp2, CK_ULONG ulCount2, CK_ULONG type, void *ptr, size_t * sizep)
|
||||
{
|
||||
CK_RV rv;
|
||||
|
||||
|
||||
rv = attr_find(pTemp1, ulCount1, type, ptr, sizep);
|
||||
if (rv != CKR_OK)
|
||||
rv = attr_find(pTemp2, ulCount2, type, ptr, sizep);
|
||||
|
@ -282,10 +211,9 @@ CK_RV attr_find2(CK_ATTRIBUTE_PTR pTemp1, CK_ULONG ulCount1,
|
|||
return rv;
|
||||
}
|
||||
|
||||
CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
||||
CK_ULONG type, void **ptr, size_t *sizep)
|
||||
CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void **ptr, size_t * sizep)
|
||||
{
|
||||
unsigned int n;
|
||||
unsigned int n;
|
||||
|
||||
for (n = 0; n < ulCount; n++, pTemplate++) {
|
||||
if (pTemplate->type == type)
|
||||
|
@ -301,10 +229,9 @@ CK_RV attr_find_ptr(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV attr_find_var(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
||||
CK_ULONG type, void *ptr, size_t *sizep)
|
||||
CK_RV attr_find_var(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount, CK_ULONG type, void *ptr, size_t * sizep)
|
||||
{
|
||||
unsigned int n;
|
||||
unsigned int n;
|
||||
|
||||
for (n = 0; n < ulCount; n++, pTemplate++) {
|
||||
if (pTemplate->type == type)
|
||||
|
@ -317,7 +244,7 @@ CK_RV attr_find_var(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
|
|||
return attr_extract(pTemplate, ptr, sizep);
|
||||
}
|
||||
|
||||
void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
|
||||
void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t * ctx)
|
||||
{
|
||||
scconf_block *conf_block = NULL;
|
||||
char *unblock_style = NULL;
|
||||
|
@ -345,7 +272,7 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
|
|||
conf->lock_login = scconf_get_bool(conf_block, "lock_login", conf->lock_login);
|
||||
conf->soft_keygen_allowed = scconf_get_bool(conf_block, "soft_keygen_allowed", conf->soft_keygen_allowed);
|
||||
|
||||
unblock_style = (char *) scconf_get_str(conf_block, "user_pin_unblock_style", NULL);
|
||||
unblock_style = (char *)scconf_get_str(conf_block, "user_pin_unblock_style", NULL);
|
||||
if (unblock_style && !strcmp(unblock_style, "set_pin_in_unlogged_session"))
|
||||
conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_UNLOGGED_SETPIN;
|
||||
else if (unblock_style && !strcmp(unblock_style, "set_pin_in_specific_context"))
|
||||
|
@ -354,7 +281,7 @@ void load_pkcs11_parameters(struct sc_pkcs11_config *conf, sc_context_t *ctx)
|
|||
conf->pin_unblock_style = SC_PKCS11_PIN_UNBLOCK_SO_LOGGED_INITPIN;
|
||||
|
||||
sc_debug(ctx, "PKCS#11 options: plug_and_play=%d max_virtual_slots=%d slots_per_card=%d "
|
||||
"hide_empty_tokens=%d lock_login=%d pin_unblock_style=%d",
|
||||
conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card,
|
||||
conf->hide_empty_tokens, conf->lock_login, conf->pin_unblock_style);
|
||||
"hide_empty_tokens=%d lock_login=%d pin_unblock_style=%d",
|
||||
conf->plug_and_play, conf->max_virtual_slots, conf->slots_per_card,
|
||||
conf->hide_empty_tokens, conf->lock_login, conf->pin_unblock_style);
|
||||
}
|
||||
|
|
|
@ -30,14 +30,13 @@
|
|||
#include "sc-pkcs11.h"
|
||||
|
||||
sc_context_t *context = NULL;
|
||||
struct sc_pkcs11_pool session_pool;
|
||||
struct sc_pkcs11_slot *virtual_slots = NULL;
|
||||
struct sc_pkcs11_card card_table[SC_MAX_READERS];
|
||||
struct sc_pkcs11_config sc_pkcs11_conf;
|
||||
list_t sessions;
|
||||
list_t virtual_slots;
|
||||
#if !defined(_WIN32)
|
||||
pid_t initialized_pid = (pid_t)-1;
|
||||
#endif
|
||||
|
||||
static int in_finalize = 0;
|
||||
extern CK_FUNCTION_LIST pkcs11_function_list;
|
||||
|
||||
#if defined(HAVE_PTHREAD) && defined(PKCS11_THREAD_LOCKING)
|
||||
|
@ -170,13 +169,33 @@ static sc_thread_context_t sc_thread_ctx = {
|
|||
sc_unlock_mutex, sc_destroy_mutex, NULL
|
||||
};
|
||||
|
||||
/* simclist helpers to locate interesting objects by ID */
|
||||
static int session_list_seeker(const void *el, const void *key) {
|
||||
const struct sc_pkcs11_session *session = (struct sc_pkcs11_session *)el;
|
||||
if ((el == NULL) || (key == NULL))
|
||||
return 0;
|
||||
if (session->handle == *(CK_SESSION_HANDLE*)key)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
static int slot_list_seeker(const void *el, const void *key) {
|
||||
const struct sc_pkcs11_slot *slot = (struct sc_pkcs11_slot *)el;
|
||||
if ((el == NULL) || (key == NULL))
|
||||
return 0;
|
||||
if (slot->id == *(CK_SLOT_ID *)key)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
|
||||
{
|
||||
#if !defined(_WIN32)
|
||||
pid_t current_pid = getpid();
|
||||
#endif
|
||||
int rc, rv;
|
||||
unsigned int i;
|
||||
int rc, rv;
|
||||
sc_context_param_t ctx_opts;
|
||||
|
||||
/* Handle fork() exception */
|
||||
|
@ -185,6 +204,7 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
|
|||
C_Finalize(NULL_PTR);
|
||||
}
|
||||
initialized_pid = current_pid;
|
||||
in_finalize = 0;
|
||||
#endif
|
||||
|
||||
if (context != NULL) {
|
||||
|
@ -211,26 +231,32 @@ CK_RV C_Initialize(CK_VOID_PTR pInitArgs)
|
|||
/* Load configuration */
|
||||
load_pkcs11_parameters(&sc_pkcs11_conf, context);
|
||||
|
||||
first_free_slot = 0;
|
||||
virtual_slots = (struct sc_pkcs11_slot *)malloc(
|
||||
sizeof (*virtual_slots) * sc_pkcs11_conf.max_virtual_slots
|
||||
);
|
||||
if (virtual_slots == NULL) {
|
||||
rv = CKR_HOST_MEMORY;
|
||||
goto out;
|
||||
/* List of sessions */
|
||||
list_init(&sessions);
|
||||
list_attributes_seeker(&sessions, session_list_seeker);
|
||||
|
||||
/* List of slots */
|
||||
list_init(&virtual_slots);
|
||||
list_attributes_seeker(&virtual_slots, slot_list_seeker);
|
||||
|
||||
/* Create a slot for a future "PnP" stuff. */
|
||||
if (sc_pkcs11_conf.plug_and_play) {
|
||||
create_slot(NULL);
|
||||
}
|
||||
/* Create slots for readers found on initialization */
|
||||
for (i=0; i<sc_ctx_get_reader_count(context); i++) {
|
||||
initialize_reader(sc_ctx_get_reader(context, i));
|
||||
}
|
||||
pool_initialize(&session_pool, POOL_TYPE_SESSION);
|
||||
for (i=0; i<sc_pkcs11_conf.max_virtual_slots; i++)
|
||||
slot_initialize(i, &virtual_slots[i]);
|
||||
for (i=0; i<SC_MAX_READERS; i++)
|
||||
card_initialize(i);
|
||||
|
||||
/* Detect any card, but do not flag "insert" events */
|
||||
__card_detect_all(0);
|
||||
/* Set initial event state on slots */
|
||||
for (i=0; i<list_size(&virtual_slots); i++) {
|
||||
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
||||
slot->events = 0; /* Initially there are no events */
|
||||
}
|
||||
|
||||
out:
|
||||
if (context != NULL)
|
||||
sc_debug(context, "C_Initialize: result = %d\n", rv);
|
||||
sc_debug(context, "C_Initialize() = %s", lookup_enum ( RV_T, rv ));
|
||||
|
||||
if (rv != CKR_OK) {
|
||||
if (context != NULL) {
|
||||
|
@ -261,15 +287,19 @@ CK_RV C_Finalize(CK_VOID_PTR pReserved)
|
|||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "Shutting down Cryptoki\n");
|
||||
sc_debug(context, "C_Finalize()");
|
||||
|
||||
/* cancel pending calls */
|
||||
in_finalize = 1;
|
||||
sc_cancel(context);
|
||||
|
||||
/* remove all cards from readers */
|
||||
for (i=0; i < (int)sc_ctx_get_reader_count(context); i++)
|
||||
card_removed(i);
|
||||
|
||||
if (virtual_slots) {
|
||||
free(virtual_slots);
|
||||
virtual_slots = NULL;
|
||||
}
|
||||
card_removed(sc_ctx_get_reader(context, i));
|
||||
|
||||
list_destroy(&sessions);
|
||||
list_destroy(&virtual_slots);
|
||||
|
||||
sc_release_context(context);
|
||||
context = NULL;
|
||||
|
||||
|
@ -292,7 +322,7 @@ CK_RV C_GetInfo(CK_INFO_PTR pInfo)
|
|||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "Cryptoki info query\n");
|
||||
sc_debug(context, "C_GetInfo()");
|
||||
|
||||
memset(pInfo, 0, sizeof(CK_INFO));
|
||||
pInfo->cryptokiVersion.major = 2;
|
||||
|
@ -301,7 +331,7 @@ CK_RV C_GetInfo(CK_INFO_PTR pInfo)
|
|||
"OpenSC (www.opensc-project.org)",
|
||||
sizeof(pInfo->manufacturerID));
|
||||
strcpy_bp(pInfo->libraryDescription,
|
||||
"smart card PKCS#11 API",
|
||||
"Smart card PKCS#11 API",
|
||||
sizeof(pInfo->libraryDescription));
|
||||
pInfo->libraryVersion.major = 0;
|
||||
pInfo->libraryVersion.minor = 0; /* FIXME: use 0.116 for 0.11.6 from autoconf */
|
||||
|
@ -347,19 +377,23 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
|
|||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "Getting slot listing\n");
|
||||
sc_debug(context, "C_GetSlotList(token=%d, %s)", tokenPresent, (pSlotList==NULL_PTR && sc_pkcs11_conf.plug_and_play)? "plug-n-play":"refresh");
|
||||
|
||||
/* Slot list can only change in v2.20 */
|
||||
if (pSlotList == NULL_PTR && sc_pkcs11_conf.plug_and_play) {
|
||||
sc_ctx_detect_readers(context);
|
||||
/* Trick NSS into updating the slot list by changing the hotplug slot ID */
|
||||
sc_pkcs11_slot_t *hotplug_slot = list_get_at(&virtual_slots, 0);
|
||||
hotplug_slot->id--;
|
||||
sc_ctx_detect_readers(context);
|
||||
|
||||
}
|
||||
card_detect_all();
|
||||
|
||||
numMatches = 0;
|
||||
for (i=0; i<sc_pkcs11_conf.max_virtual_slots; i++) {
|
||||
slot = &virtual_slots[i];
|
||||
|
||||
if (!tokenPresent || (slot->slot_info.flags & CKF_TOKEN_PRESENT))
|
||||
found[numMatches++] = i;
|
||||
for (i=0; i<list_size(&virtual_slots); i++) {
|
||||
slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
||||
if (!tokenPresent || (slot->slot_info.flags & CKF_TOKEN_PRESENT))
|
||||
found[numMatches++] = slot->id;
|
||||
}
|
||||
|
||||
if (pSlotList == NULL_PTR) {
|
||||
|
@ -433,16 +467,20 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
|
|||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "Getting info about slot %d\n", slotID);
|
||||
sc_debug(context, "C_GetSlotInfo(0x%lx)", slotID);
|
||||
|
||||
rv = slot_get_slot(slotID, &slot);
|
||||
if (rv == CKR_OK){
|
||||
now = get_current_time();
|
||||
if (now >= card_table[slot->reader].slot_state_expires || now == 0) {
|
||||
/* Update slot status */
|
||||
rv = card_detect(slot->reader);
|
||||
/* Don't ask again within the next second */
|
||||
card_table[slot->reader].slot_state_expires = now + 1000;
|
||||
if (slot->reader == NULL)
|
||||
rv = CKR_TOKEN_NOT_PRESENT;
|
||||
else {
|
||||
now = get_current_time();
|
||||
if (now >= slot->slot_state_expires || now == 0) {
|
||||
/* Update slot status */
|
||||
rv = card_detect(slot->reader);
|
||||
/* Don't ask again within the next second */
|
||||
slot->slot_state_expires = now + 1000;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (rv == CKR_TOKEN_NOT_PRESENT || rv == CKR_TOKEN_NOT_RECOGNIZED)
|
||||
|
@ -451,7 +489,8 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
|
|||
if (rv == CKR_OK)
|
||||
memcpy(pInfo, &slot->slot_info, sizeof(CK_SLOT_INFO));
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out: sc_debug(context, "C_GetSlotInfo(0x%lx) = %s", slotID, lookup_enum ( RV_T, rv ));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -469,9 +508,10 @@ CK_RV C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
|
|||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "Getting info about token in slot %d\n", slotID);
|
||||
sc_debug(context, "C_GetTokenInfo(%lx)", slotID);
|
||||
|
||||
rv = slot_get_token(slotID, &slot);
|
||||
/* TODO: update token flags */
|
||||
if (rv == CKR_OK)
|
||||
memcpy(pInfo, &slot->token_info, sizeof(CK_TOKEN_INFO));
|
||||
|
||||
|
@ -526,10 +566,10 @@ CK_RV C_InitToken(CK_SLOT_ID slotID,
|
|||
CK_ULONG ulPinLen,
|
||||
CK_CHAR_PTR pLabel)
|
||||
{
|
||||
struct sc_pkcs11_pool_item *item;
|
||||
struct sc_pkcs11_session *session;
|
||||
struct sc_pkcs11_slot *slot;
|
||||
CK_RV rv;
|
||||
unsigned int i;
|
||||
|
||||
rv = sc_pkcs11_lock();
|
||||
if (rv != CKR_OK)
|
||||
|
@ -538,10 +578,10 @@ CK_RV C_InitToken(CK_SLOT_ID slotID,
|
|||
rv = slot_get_token(slotID, &slot);
|
||||
if (rv != CKR_OK)
|
||||
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;
|
||||
for (i=0; i<list_size(&sessions); i++) {
|
||||
session = (struct sc_pkcs11_session*)list_get_at(&sessions, i);
|
||||
if (session->slot == slot) {
|
||||
rv = CKR_SESSION_EXISTS;
|
||||
goto out;
|
||||
|
@ -568,68 +608,59 @@ CK_RV C_WaitForSlotEvent(CK_FLAGS flags, /* blocking/nonblocking flag */
|
|||
CK_SLOT_ID_PTR pSlot, /* location that receives the slot ID */
|
||||
CK_VOID_PTR pReserved) /* reserved. Should be NULL_PTR */
|
||||
{
|
||||
sc_reader_t *reader, *readers[SC_MAX_SLOTS * SC_MAX_READERS];
|
||||
int slots[SC_MAX_SLOTS * SC_MAX_READERS];
|
||||
int i, j, k, r, found;
|
||||
sc_reader_t *found;
|
||||
int r;
|
||||
unsigned int mask, events;
|
||||
CK_RV rv;
|
||||
|
||||
if (pReserved != NULL_PTR) {
|
||||
return CKR_ARGUMENTS_BAD;
|
||||
}
|
||||
|
||||
/* Firefox 1.5 (NSS 3.10) calls this function (blocking) from a seperate thread,
|
||||
* which gives 2 problems:
|
||||
* - on Windows/Mac: this waiting thread will log to a NULL context
|
||||
* after the 'main' thread does a C_Finalize() and sets the ctx to NULL.
|
||||
* - on Linux, things just hang (at least on Debian 'sid')
|
||||
* So we just return CKR_FUNCTION_NOT_SUPPORTED on a blocking call,
|
||||
* in which case FF just seems to default to polling in the main thread
|
||||
* as earlier NSS versions.
|
||||
*/
|
||||
sc_debug(context, "C_WaitForSlotEvent(block=%d)", !(flags & CKF_DONT_BLOCK));
|
||||
#if 0
|
||||
/* pcsc-lite does not implement it in a threaded way */
|
||||
if (!(flags & CKF_DONT_BLOCK))
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
|
||||
#endif
|
||||
rv = sc_pkcs11_lock();
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
if (pReserved != NULL_PTR) {
|
||||
rv = CKR_ARGUMENTS_BAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
mask = SC_EVENT_CARD_INSERTED|SC_EVENT_CARD_REMOVED;
|
||||
|
||||
/* Detect and add new slots for added readers v2.20 */
|
||||
if (sc_pkcs11_conf.plug_and_play) {
|
||||
mask |= SC_EVENT_READER_ATTACHED;
|
||||
}
|
||||
|
||||
if ((rv = slot_find_changed(pSlot, mask)) == CKR_OK
|
||||
|| (flags & CKF_DONT_BLOCK))
|
||||
goto out;
|
||||
|
||||
for (i = k = 0; i < (int)sc_ctx_get_reader_count(context); i++) {
|
||||
reader = sc_ctx_get_reader(context, i);
|
||||
if (reader == NULL) {
|
||||
rv = CKR_GENERAL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
for (j = 0; j < reader->slot_count; j++, k++) {
|
||||
readers[k] = reader;
|
||||
slots[k] = j;
|
||||
}
|
||||
}
|
||||
|
||||
again:
|
||||
/* Check if C_Finalize() has been called in another thread */
|
||||
if (context == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
sc_pkcs11_unlock();
|
||||
r = sc_wait_for_event(readers, slots, k, mask, &found, &events, -1);
|
||||
r = sc_wait_for_event(context, mask, &found, &events, -1);
|
||||
|
||||
/* There may have been a C_Finalize while we slept */
|
||||
if (context == NULL)
|
||||
if (sc_pkcs11_conf.plug_and_play && events & SC_EVENT_READER_ATTACHED) {
|
||||
/* NSS/Firefox Triggers a C_GetSlotList(NULL) only if a slot ID is returned that it does not know yet
|
||||
Change the first hotplug slot id on every call to make this happen.
|
||||
*/
|
||||
sc_pkcs11_slot_t *hotplug_slot = list_get_at(&virtual_slots, 0);
|
||||
*pSlot= hotplug_slot->id -1;
|
||||
rv = CKR_OK;
|
||||
goto out;
|
||||
}
|
||||
/* Was C_Finalize called ? */
|
||||
if (in_finalize == 1)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if ((rv = sc_pkcs11_lock()) != CKR_OK)
|
||||
return rv;
|
||||
|
||||
if (r != SC_SUCCESS) {
|
||||
sc_debug(context, "sc_wait_for_event() returned %d\n", r);
|
||||
rv = sc_to_cryptoki_error(r, -1);
|
||||
rv = sc_to_cryptoki_error(r);
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
@ -638,7 +669,8 @@ again:
|
|||
if ((rv = slot_find_changed(pSlot, mask)) != CKR_OK)
|
||||
goto again;
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out: sc_debug(context, "C_WaitForSlotEvent() = %s, event in 0x%lx", lookup_enum (RV_T, rv), *pSlot);
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,12 +23,20 @@
|
|||
#include <string.h>
|
||||
#include "sc-pkcs11.h"
|
||||
|
||||
CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */
|
||||
CK_FLAGS flags, /* defined in CK_SESSION_INFO */
|
||||
CK_VOID_PTR pApplication, /* pointer passed to callback */
|
||||
CK_NOTIFY Notify, /* notification callback function */
|
||||
CK_SESSION_HANDLE_PTR phSession) /* receives new session handle */
|
||||
CK_RV get_session(CK_SESSION_HANDLE hSession, struct sc_pkcs11_session **session)
|
||||
{
|
||||
*session = list_seek(&sessions, &hSession);
|
||||
if (!*session)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */
|
||||
CK_FLAGS flags, /* defined in CK_SESSION_INFO */
|
||||
CK_VOID_PTR pApplication, /* pointer passed to callback */
|
||||
CK_NOTIFY Notify, /* notification callback function */
|
||||
CK_SESSION_HANDLE_PTR phSession)
|
||||
{ /* receives new session handle */
|
||||
struct sc_pkcs11_slot *slot;
|
||||
struct sc_pkcs11_session *session;
|
||||
int rv;
|
||||
|
@ -37,7 +45,7 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */
|
|||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
sc_debug(context, "Opening new session for slot %d\n", slotID);
|
||||
sc_debug(context, "C_OpenSession(0x%lx)", slotID);
|
||||
|
||||
if (!(flags & CKF_SERIAL_SESSION)) {
|
||||
rv = CKR_SESSION_PARALLEL_NOT_SUPPORTED;
|
||||
|
@ -59,24 +67,23 @@ CK_RV C_OpenSession(CK_SLOT_ID slotID, /* the slot's ID */
|
|||
goto out;
|
||||
}
|
||||
|
||||
session = (struct sc_pkcs11_session*) calloc(1, sizeof(struct sc_pkcs11_session));
|
||||
session = (struct sc_pkcs11_session *)calloc(1, sizeof(struct sc_pkcs11_session));
|
||||
if (session == NULL) {
|
||||
rv = CKR_HOST_MEMORY;
|
||||
goto out;
|
||||
}
|
||||
|
||||
|
||||
session->slot = slot;
|
||||
session->notify_callback = Notify;
|
||||
session->notify_data = pApplication;
|
||||
session->flags = flags;
|
||||
|
||||
rv = pool_insert(&session_pool, session, phSession);
|
||||
if (rv != CKR_OK)
|
||||
free(session);
|
||||
else
|
||||
slot->nsessions++;
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
slot->nsessions++;
|
||||
session->handle = (CK_SESSION_HANDLE) session; // cast a pointer to long
|
||||
list_append(&sessions, session);
|
||||
*phSession = session->handle;
|
||||
sc_debug(context, "C_OpenSession handle: 0x%lx", session->handle);
|
||||
out:sc_debug(context, "C_OpenSession() = %s", lookup_enum(RV_T, rv));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
@ -86,11 +93,12 @@ static CK_RV sc_pkcs11_close_session(CK_SESSION_HANDLE hSession)
|
|||
{
|
||||
struct sc_pkcs11_slot *slot;
|
||||
struct sc_pkcs11_session *session;
|
||||
int rv;
|
||||
|
||||
rv = pool_find_and_delete(&session_pool, hSession, (void**) &session);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
sc_debug(context, "real C_CloseSession(0x%lx)", hSession);
|
||||
|
||||
session = list_seek(&sessions, &hSession);
|
||||
if (!session)
|
||||
return CKR_SESSION_HANDLE_INVALID;
|
||||
|
||||
/* If we're the last session using this slot, make sure
|
||||
* we log out */
|
||||
|
@ -101,6 +109,8 @@ static CK_RV sc_pkcs11_close_session(CK_SESSION_HANDLE hSession)
|
|||
slot->card->framework->logout(slot->card, slot->fw_data);
|
||||
}
|
||||
|
||||
if (list_delete(&sessions, session) != 0)
|
||||
sc_debug(context, "Could not delete session from list!");
|
||||
free(session);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
@ -109,26 +119,24 @@ static CK_RV sc_pkcs11_close_session(CK_SESSION_HANDLE hSession)
|
|||
* 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;
|
||||
|
||||
sc_debug(context, "C_CloseAllSessions(slot %d).\n", (int) slotID);
|
||||
for (item = session_pool.head; item != NULL; item = next) {
|
||||
session = (struct sc_pkcs11_session*) item->item;
|
||||
next = item->next;
|
||||
|
||||
if (session->slot->id == (int)slotID)
|
||||
sc_pkcs11_close_session(item->handle);
|
||||
CK_RV rv = CKR_OK;
|
||||
unsigned int i;
|
||||
sc_debug(context, "real C_CloseAllSessions(0x%lx) %d", slotID, list_size(&sessions));
|
||||
for (i = 0; i < list_size(&sessions); i++) {
|
||||
session = list_get_at(&sessions, i);
|
||||
if (session->slot->id == slotID)
|
||||
if ((rv = sc_pkcs11_close_session(session->handle)) != CKR_OK)
|
||||
return rv;
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */
|
||||
{
|
||||
CK_RV C_CloseSession(CK_SESSION_HANDLE hSession)
|
||||
{ /* the session's handle */
|
||||
int rv;
|
||||
|
||||
sc_debug(context, "C_CloseSession(%lx)\n", (long) hSession);
|
||||
sc_debug(context, "C_CloseSession(0x%lx)\n", hSession);
|
||||
|
||||
rv = sc_pkcs11_lock();
|
||||
if (rv == CKR_OK)
|
||||
|
@ -137,11 +145,12 @@ CK_RV C_CloseSession(CK_SESSION_HANDLE hSession) /* the session's handle */
|
|||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) /* the token's slot */
|
||||
{
|
||||
CK_RV C_CloseAllSessions(CK_SLOT_ID slotID)
|
||||
{ /* the token's slot */
|
||||
struct sc_pkcs11_slot *slot;
|
||||
int rv;
|
||||
|
||||
sc_debug(context, "C_CloseAllSessions(0x%lx)\n", slotID);
|
||||
rv = sc_pkcs11_lock();
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
@ -152,17 +161,18 @@ CK_RV C_CloseAllSessions(CK_SLOT_ID slotID) /* the token's slot */
|
|||
|
||||
rv = sc_pkcs11_close_all_sessions(slotID);
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out: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 */
|
||||
{
|
||||
CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_SESSION_INFO_PTR pInfo)
|
||||
{ /* receives session information */
|
||||
struct sc_pkcs11_session *session;
|
||||
struct sc_pkcs11_slot *slot;
|
||||
int rv;
|
||||
|
||||
sc_debug(context, "C_GetSessionInfo(0x%lx)", hSession);
|
||||
rv = sc_pkcs11_lock();
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
@ -172,11 +182,13 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
goto out;
|
||||
}
|
||||
|
||||
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||
if (rv != CKR_OK)
|
||||
session = list_seek(&sessions, &hSession);
|
||||
if (!session) {
|
||||
rv = CKR_SESSION_HANDLE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "C_GetSessionInfo(slot %d).\n", session->slot->id);
|
||||
sc_debug(context, "C_GetSessionInfo(slot 0x%lx).", session->slot->id);
|
||||
pInfo->slotID = session->slot->id;
|
||||
pInfo->flags = session->flags;
|
||||
pInfo->ulDeviceError = 0;
|
||||
|
@ -184,41 +196,41 @@ CK_RV C_GetSessionInfo(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
slot = session->slot;
|
||||
if (slot->login_user == CKU_SO) {
|
||||
pInfo->state = CKS_RW_SO_FUNCTIONS;
|
||||
} else
|
||||
if (slot->login_user == CKU_USER
|
||||
|| (!(slot->token_info.flags & CKF_LOGIN_REQUIRED))) {
|
||||
} else if (slot->login_user == CKU_USER || (!(slot->token_info.flags & CKF_LOGIN_REQUIRED))) {
|
||||
pInfo->state = (session->flags & CKF_RW_SESSION)
|
||||
? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS;
|
||||
? CKS_RW_USER_FUNCTIONS : CKS_RO_USER_FUNCTIONS;
|
||||
} else {
|
||||
pInfo->state = (session->flags & CKF_RW_SESSION)
|
||||
? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION;
|
||||
? CKS_RW_PUBLIC_SESSION : CKS_RO_PUBLIC_SESSION;
|
||||
}
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:
|
||||
sc_debug(context, "C_GetSessionInfo(0x%lx) = %s", hSession, lookup_enum(RV_T, rv));
|
||||
sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* location receiving state */
|
||||
CK_ULONG_PTR pulOperationStateLen) /* location receiving state length */
|
||||
{
|
||||
CK_RV C_GetOperationState(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* location receiving state */
|
||||
CK_ULONG_PTR pulOperationStateLen)
|
||||
{ /* location receiving state length */
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* the location holding the state */
|
||||
CK_ULONG ulOperationStateLen, /* location holding state length */
|
||||
CK_OBJECT_HANDLE hEncryptionKey, /* handle of en/decryption key */
|
||||
CK_OBJECT_HANDLE hAuthenticationKey) /* handle of sign/verify key */
|
||||
{
|
||||
CK_RV C_SetOperationState(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_BYTE_PTR pOperationState, /* the location holding the state */
|
||||
CK_ULONG ulOperationStateLen, /* location holding state length */
|
||||
CK_OBJECT_HANDLE hEncryptionKey, /* handle of en/decryption key */
|
||||
CK_OBJECT_HANDLE hAuthenticationKey)
|
||||
{ /* handle of sign/verify key */
|
||||
return CKR_FUNCTION_NOT_SUPPORTED;
|
||||
}
|
||||
|
||||
CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_USER_TYPE userType, /* the user type */
|
||||
CK_CHAR_PTR pPin, /* the user's PIN */
|
||||
CK_ULONG ulPinLen) /* the length of the PIN */
|
||||
{
|
||||
CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
|
||||
CK_USER_TYPE userType, /* the user type */
|
||||
CK_CHAR_PTR pPin, /* the user's PIN */
|
||||
CK_ULONG ulPinLen)
|
||||
{ /* the length of the PIN */
|
||||
int rv;
|
||||
struct sc_pkcs11_session *session;
|
||||
struct sc_pkcs11_slot *slot;
|
||||
|
@ -236,12 +248,13 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
rv = CKR_USER_TYPE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||
if (rv != CKR_OK)
|
||||
session = list_seek(&sessions, &hSession);
|
||||
if (!session) {
|
||||
rv = CKR_SESSION_HANDLE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "Login for session %d; userType %d\n", hSession, userType);
|
||||
sc_debug(context, "C_Login(0x%lx, %d)", hSession, userType);
|
||||
|
||||
slot = session->slot;
|
||||
|
||||
|
@ -250,25 +263,34 @@ CK_RV C_Login(CK_SESSION_HANDLE hSession, /* the session's handle */
|
|||
goto out;
|
||||
}
|
||||
|
||||
if (slot->login_user >= 0) {
|
||||
if ((CK_USER_TYPE)slot->login_user == userType)
|
||||
rv = CKR_USER_ALREADY_LOGGED_IN;
|
||||
else
|
||||
rv = CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
|
||||
goto out;
|
||||
/* TODO: check if context specific is valid */
|
||||
if (userType == CKU_CONTEXT_SPECIFIC) {
|
||||
if (slot->login_user == -1) {
|
||||
rv = CKR_OPERATION_NOT_INITIALIZED;
|
||||
goto out;
|
||||
} else
|
||||
userType = slot->login_user;
|
||||
} else {
|
||||
if (slot->login_user >= 0) {
|
||||
if ((CK_USER_TYPE) slot->login_user == userType)
|
||||
rv = CKR_USER_ALREADY_LOGGED_IN;
|
||||
else
|
||||
rv = CKR_USER_ANOTHER_ALREADY_LOGGED_IN;
|
||||
goto out;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
rv = slot->card->framework->login(slot->card, slot->fw_data,
|
||||
userType, pPin, ulPinLen);
|
||||
rv = slot->card->framework->login(slot->card, slot->fw_data, userType, pPin, ulPinLen);
|
||||
if (rv == CKR_OK)
|
||||
slot->login_user = userType;
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_Logout(CK_SESSION_HANDLE hSession) /* the session's handle */
|
||||
{
|
||||
CK_RV C_Logout(CK_SESSION_HANDLE hSession)
|
||||
{ /* the session's handle */
|
||||
int rv;
|
||||
struct sc_pkcs11_session *session;
|
||||
struct sc_pkcs11_slot *slot;
|
||||
|
@ -277,28 +299,27 @@ CK_RV C_Logout(CK_SESSION_HANDLE hSession) /* the session's handle */
|
|||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||
if (rv != CKR_OK)
|
||||
session = list_seek(&sessions, &hSession);
|
||||
if (!session) {
|
||||
rv = CKR_SESSION_HANDLE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "Logout for session %d\n", hSession);
|
||||
sc_debug(context, "C_Logout(0x%lx)", hSession);
|
||||
|
||||
slot = session->slot;
|
||||
|
||||
if (slot->login_user >= 0) {
|
||||
slot->login_user = -1;
|
||||
rv = slot->card->framework->logout(slot->card, slot->fw_data);
|
||||
}
|
||||
else
|
||||
} else
|
||||
rv = CKR_USER_NOT_LOGGED_IN;
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_InitPIN(CK_SESSION_HANDLE hSession,
|
||||
CK_CHAR_PTR pPin,
|
||||
CK_ULONG ulPinLen)
|
||||
CK_RV C_InitPIN(CK_SESSION_HANDLE hSession, CK_CHAR_PTR pPin, CK_ULONG ulPinLen)
|
||||
{
|
||||
struct sc_pkcs11_session *session;
|
||||
struct sc_pkcs11_slot *slot;
|
||||
|
@ -313,9 +334,11 @@ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession,
|
|||
goto out;
|
||||
}
|
||||
|
||||
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||
if (rv != CKR_OK)
|
||||
session = list_seek(&sessions, &hSession);
|
||||
if (!session) {
|
||||
rv = CKR_SESSION_HANDLE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (!(session->flags & CKF_RW_SESSION)) {
|
||||
rv = CKR_SESSION_READ_ONLY;
|
||||
|
@ -325,23 +348,18 @@ CK_RV C_InitPIN(CK_SESSION_HANDLE hSession,
|
|||
slot = session->slot;
|
||||
if (slot->login_user != CKU_SO) {
|
||||
rv = CKR_USER_NOT_LOGGED_IN;
|
||||
} else
|
||||
if (slot->card->framework->init_pin == NULL) {
|
||||
} 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);
|
||||
rv = slot->card->framework->init_pin(slot->card, slot, pPin, ulPinLen);
|
||||
}
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
|
||||
CK_CHAR_PTR pOldPin,
|
||||
CK_ULONG ulOldLen,
|
||||
CK_CHAR_PTR pNewPin,
|
||||
CK_ULONG ulNewLen)
|
||||
CK_CHAR_PTR pOldPin, CK_ULONG ulOldLen, CK_CHAR_PTR pNewPin, CK_ULONG ulNewLen)
|
||||
{
|
||||
int rv;
|
||||
struct sc_pkcs11_session *session;
|
||||
|
@ -352,17 +370,20 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
|
|||
return rv;
|
||||
|
||||
if ((pOldPin == NULL_PTR && ulOldLen > 0)
|
||||
|| (pNewPin == NULL_PTR && ulNewLen > 0)) {
|
||||
|| (pNewPin == NULL_PTR && ulNewLen > 0)) {
|
||||
rv = CKR_ARGUMENTS_BAD;
|
||||
goto out;
|
||||
}
|
||||
|
||||
rv = pool_find(&session_pool, hSession, (void**) &session);
|
||||
if (rv != CKR_OK)
|
||||
session = list_seek(&sessions, &hSession);
|
||||
if (!session) {
|
||||
rv = CKR_SESSION_HANDLE_INVALID;
|
||||
goto out;
|
||||
}
|
||||
|
||||
sc_debug(context, "Changing PIN (session 0x%lx; login user %d)\n", hSession,
|
||||
slot->login_user);
|
||||
slot = session->slot;
|
||||
sc_debug(context, "Changing PIN (session %d; login user %d)\n", hSession, slot->login_user);
|
||||
|
||||
if (!(session->flags & CKF_RW_SESSION)) {
|
||||
rv = CKR_SESSION_READ_ONLY;
|
||||
|
@ -370,8 +391,9 @@ CK_RV C_SetPIN(CK_SESSION_HANDLE hSession,
|
|||
}
|
||||
|
||||
rv = slot->card->framework->change_pin(slot->card, slot->fw_data,
|
||||
slot->login_user, pOldPin, ulOldLen, pNewPin, ulNewLen);
|
||||
slot->login_user, pOldPin, ulOldLen, pNewPin,
|
||||
ulNewLen);
|
||||
|
||||
out: sc_pkcs11_unlock();
|
||||
out:sc_pkcs11_unlock();
|
||||
return rv;
|
||||
}
|
||||
|
|
|
@ -34,6 +34,7 @@
|
|||
#define CRYPTOKI_EXPORTS
|
||||
#include <pkcs11.h>
|
||||
#include <pkcs11-opensc.h>
|
||||
#include "pkcs11-display.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -70,27 +71,6 @@ struct sc_pkcs11_session;
|
|||
struct sc_pkcs11_slot;
|
||||
struct sc_pkcs11_card;
|
||||
|
||||
/* Object Pool */
|
||||
struct sc_pkcs11_pool_item {
|
||||
unsigned long int handle;
|
||||
void *item;
|
||||
struct sc_pkcs11_pool_item *next;
|
||||
struct sc_pkcs11_pool_item *prev;
|
||||
};
|
||||
|
||||
enum {
|
||||
POOL_TYPE_SESSION,
|
||||
POOL_TYPE_OBJECT
|
||||
};
|
||||
|
||||
struct sc_pkcs11_pool {
|
||||
int type;
|
||||
int next_free_handle;
|
||||
int num_items;
|
||||
struct sc_pkcs11_pool_item *head;
|
||||
struct sc_pkcs11_pool_item *tail;
|
||||
};
|
||||
|
||||
struct sc_pkcs11_config {
|
||||
unsigned int plug_and_play;
|
||||
unsigned int max_virtual_slots;
|
||||
|
@ -136,6 +116,7 @@ struct sc_pkcs11_object_ops {
|
|||
};
|
||||
|
||||
struct sc_pkcs11_object {
|
||||
CK_OBJECT_HANDLE handle;
|
||||
int flags;
|
||||
struct sc_pkcs11_object_ops *ops;
|
||||
};
|
||||
|
@ -205,16 +186,10 @@ typedef unsigned __int64 sc_timestamp_t;
|
|||
#endif
|
||||
|
||||
struct sc_pkcs11_card {
|
||||
int reader;
|
||||
struct sc_card *card;
|
||||
sc_reader_t *reader;
|
||||
sc_card_t *card;
|
||||
struct sc_pkcs11_framework_ops *framework;
|
||||
void *fw_data;
|
||||
sc_timestamp_t slot_state_expires;
|
||||
|
||||
/* Number of slots owned by this card object */
|
||||
unsigned int num_slots;
|
||||
unsigned int max_slots;
|
||||
unsigned int first_slot;
|
||||
|
||||
/* List of supported mechanisms */
|
||||
struct sc_pkcs11_mechanism_type **mechanisms;
|
||||
|
@ -222,27 +197,17 @@ struct sc_pkcs11_card {
|
|||
};
|
||||
|
||||
struct sc_pkcs11_slot {
|
||||
int id;
|
||||
int login_user;
|
||||
/* Slot specific information (information about reader) */
|
||||
CK_SLOT_INFO slot_info;
|
||||
/* Token specific information (information about card) */
|
||||
CK_TOKEN_INFO token_info;
|
||||
|
||||
/* Reader to which card is allocated (same as card->reader
|
||||
* if there's a card present) */
|
||||
int reader;
|
||||
|
||||
/* The card associated with this slot */
|
||||
struct sc_pkcs11_card *card;
|
||||
/* Card events SC_EVENT_CARD_{INSERTED,REMOVED} */
|
||||
int events;
|
||||
/* Framework specific data */
|
||||
void *fw_data;
|
||||
/* Object pools */
|
||||
struct sc_pkcs11_pool object_pool;
|
||||
/* Number of sessions using this slot */
|
||||
unsigned int nsessions;
|
||||
CK_SLOT_ID id; /* ID of the slot */
|
||||
int login_user; /* Currently logged in user */
|
||||
CK_SLOT_INFO slot_info; /* Slot specific information (information about reader) */
|
||||
CK_TOKEN_INFO token_info; /* Token specific information (information about card) */
|
||||
sc_reader_t *reader; /* same as card->reader if there's a card present */
|
||||
struct sc_pkcs11_card *card; /* The card associated with this slot */
|
||||
unsigned int events; /* Card events SC_EVENT_CARD_{INSERTED,REMOVED} */
|
||||
void *fw_data; /* Framework specific data */
|
||||
list_t objects; /* Objects in this slot */
|
||||
unsigned int nsessions; /* Number of sessions using this slot */
|
||||
sc_timestamp_t slot_state_expires;
|
||||
};
|
||||
typedef struct sc_pkcs11_slot sc_pkcs11_slot_t;
|
||||
|
||||
|
@ -325,6 +290,7 @@ struct sc_pkcs11_find_operation {
|
|||
*/
|
||||
|
||||
struct sc_pkcs11_session {
|
||||
CK_SESSION_HANDLE handle;
|
||||
/* Session to this slot */
|
||||
struct sc_pkcs11_slot *slot;
|
||||
CK_FLAGS flags;
|
||||
|
@ -338,18 +304,17 @@ typedef struct sc_pkcs11_session sc_pkcs11_session_t;
|
|||
|
||||
/* Module variables */
|
||||
extern struct sc_context *context;
|
||||
extern struct sc_pkcs11_pool session_pool;
|
||||
extern struct sc_pkcs11_slot *virtual_slots;
|
||||
extern struct sc_pkcs11_card card_table[SC_MAX_READERS];
|
||||
extern struct sc_pkcs11_config sc_pkcs11_conf;
|
||||
extern unsigned int first_free_slot;
|
||||
extern list_t sessions;
|
||||
extern list_t virtual_slots;
|
||||
extern list_t cards;
|
||||
|
||||
/* Framework definitions */
|
||||
extern struct sc_pkcs11_framework_ops framework_pkcs15;
|
||||
extern struct sc_pkcs11_framework_ops framework_pkcs15init;
|
||||
|
||||
void strcpy_bp(u8 *dst, const char *src, size_t dstsize);
|
||||
CK_RV sc_to_cryptoki_error(int rc, int reader);
|
||||
CK_RV sc_to_cryptoki_error(int rc);
|
||||
void sc_pkcs11_print_attrs(const char *file, unsigned int line, const char *function,
|
||||
const char *info, CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount);
|
||||
#define dump_template(info, pTemplate, ulCount) \
|
||||
|
@ -357,25 +322,19 @@ void sc_pkcs11_print_attrs(const char *file, unsigned int line, const char *func
|
|||
info, pTemplate, ulCount)
|
||||
|
||||
/* Slot and card handling functions */
|
||||
CK_RV card_initialize(int reader);
|
||||
CK_RV card_detect_all(void);
|
||||
CK_RV __card_detect_all(int);
|
||||
CK_RV card_detect(int reader);
|
||||
CK_RV card_removed(int reader);
|
||||
CK_RV slot_initialize(int id, struct sc_pkcs11_slot *);
|
||||
CK_RV slot_get_slot(int id, struct sc_pkcs11_slot **);
|
||||
CK_RV slot_get_token(int id, struct sc_pkcs11_slot **);
|
||||
CK_RV slot_token_removed(int id);
|
||||
CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask);
|
||||
CK_RV card_removed(sc_reader_t *reader);
|
||||
CK_RV card_detect_all();
|
||||
CK_RV create_slot(sc_reader_t *reader);
|
||||
CK_RV initialize_reader(sc_reader_t *reader);
|
||||
CK_RV card_detect(sc_reader_t *reader);
|
||||
CK_RV slot_get_slot(CK_SLOT_ID id, struct sc_pkcs11_slot **);
|
||||
CK_RV slot_get_token(CK_SLOT_ID id, struct sc_pkcs11_slot **);
|
||||
CK_RV slot_token_removed(CK_SLOT_ID id);
|
||||
CK_RV slot_allocate(struct sc_pkcs11_slot **, struct sc_pkcs11_card *);
|
||||
|
||||
/* Pool */
|
||||
CK_RV pool_initialize(struct sc_pkcs11_pool *, int);
|
||||
CK_RV pool_insert(struct sc_pkcs11_pool *, void *, CK_ULONG_PTR);
|
||||
CK_RV pool_find(struct sc_pkcs11_pool *, CK_ULONG, void **);
|
||||
CK_RV pool_find_and_delete(struct sc_pkcs11_pool *, CK_ULONG, void **);
|
||||
CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask);
|
||||
|
||||
/* Session manipulation */
|
||||
CK_RV get_session(CK_SESSION_HANDLE hSession, struct sc_pkcs11_session ** session);
|
||||
CK_RV session_start_operation(struct sc_pkcs11_session *,
|
||||
int, sc_pkcs11_mechanism_type_t *,
|
||||
struct sc_pkcs11_operation **);
|
||||
|
@ -425,7 +384,7 @@ CK_RV sc_pkcs11_verif_final(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG);
|
|||
CK_RV sc_pkcs11_decr_init(struct sc_pkcs11_session *, CK_MECHANISM_PTR, struct sc_pkcs11_object *, CK_MECHANISM_TYPE);
|
||||
CK_RV sc_pkcs11_decr(struct sc_pkcs11_session *, CK_BYTE_PTR, CK_ULONG, CK_BYTE_PTR, CK_ULONG_PTR);
|
||||
sc_pkcs11_mechanism_type_t *sc_pkcs11_find_mechanism(struct sc_pkcs11_card *,
|
||||
CK_MECHANISM_TYPE, int);
|
||||
CK_MECHANISM_TYPE, unsigned int);
|
||||
sc_pkcs11_mechanism_type_t *sc_pkcs11_new_fw_mechanism(CK_MECHANISM_TYPE,
|
||||
CK_MECHANISM_INFO_PTR, CK_KEY_TYPE,
|
||||
void *);
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
/*
|
||||
* slot.c: smart card and slot related management functions
|
||||
* slot.c: reader, smart card and slot related management functions
|
||||
*
|
||||
* Copyright (C) 2002 Timo Teräs <timo.teras@iki.fi>
|
||||
* Copyright (C) 2009 Martin Paljak <martin@paljak.pri.ee>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
|
@ -19,6 +20,7 @@
|
|||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include "sc-pkcs11.h"
|
||||
|
||||
static struct sc_pkcs11_framework_ops *frameworks[] = {
|
||||
|
@ -31,11 +33,23 @@ static struct sc_pkcs11_framework_ops *frameworks[] = {
|
|||
NULL
|
||||
};
|
||||
|
||||
unsigned int first_free_slot = 0;
|
||||
static struct sc_pkcs11_slot * reader_get_slot(sc_reader_t *reader)
|
||||
{
|
||||
unsigned int i;
|
||||
|
||||
/* Locate a slot related to the reader */
|
||||
for (i = 0; i<list_size(&virtual_slots); i++) {
|
||||
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
||||
if (slot->reader == reader) {
|
||||
return slot;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void init_slot_info(CK_SLOT_INFO_PTR pInfo)
|
||||
{
|
||||
strcpy_bp(pInfo->slotDescription, "Virtual slot", 64);
|
||||
strcpy_bp(pInfo->slotDescription, "Virtual hotplug slot", 64);
|
||||
strcpy_bp(pInfo->manufacturerID, "OpenSC (www.opensc-project.org)", 32);
|
||||
pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
|
||||
pInfo->hardwareVersion.major = 0;
|
||||
|
@ -44,99 +58,157 @@ static void init_slot_info(CK_SLOT_INFO_PTR pInfo)
|
|||
pInfo->firmwareVersion.minor = 0;
|
||||
}
|
||||
|
||||
CK_RV card_initialize(int reader)
|
||||
/* simclist helpers to locate interesting objects by ID */
|
||||
static int object_list_seeker(const void *el, const void *key)
|
||||
{
|
||||
const struct sc_pkcs11_object *object = (struct sc_pkcs11_object *)el;
|
||||
|
||||
if ((el == NULL) || (key == NULL))
|
||||
return 0;
|
||||
if (object->handle == *(CK_OBJECT_HANDLE*)key)
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
CK_RV create_slot(sc_reader_t *reader)
|
||||
{
|
||||
struct sc_pkcs11_slot *slot;
|
||||
|
||||
slot = (struct sc_pkcs11_slot *)calloc(1, sizeof(struct sc_pkcs11_slot));
|
||||
if (!slot)
|
||||
return CKR_HOST_MEMORY;
|
||||
|
||||
list_append(&virtual_slots, slot);
|
||||
slot->login_user = -1;
|
||||
slot->id = (CK_SLOT_ID) list_locate(&virtual_slots, slot);
|
||||
sc_debug(context, "Creating slot with id 0x%lx", slot->id);
|
||||
|
||||
list_init(&slot->objects);
|
||||
list_attributes_seeker(&slot->objects, object_list_seeker);
|
||||
|
||||
init_slot_info(&slot->slot_info);
|
||||
if (reader != NULL) {
|
||||
slot->reader = reader;
|
||||
strcpy_bp(slot->slot_info.slotDescription, reader->name, 64);
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
/* create slots associated with a reader, called whenever a reader is seen. */
|
||||
CK_RV initialize_reader(sc_reader_t *reader)
|
||||
{
|
||||
struct sc_pkcs11_card *card = card_table + reader;
|
||||
unsigned int avail;
|
||||
unsigned int i;
|
||||
CK_RV rv;
|
||||
|
||||
if (reader < 0 || reader >= SC_MAX_READERS)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
|
||||
memset(card, 0, sizeof(struct sc_pkcs11_card));
|
||||
card->reader = reader;
|
||||
|
||||
/* Always allocate a fixed slot range to one reader/card.
|
||||
* Some applications get confused if readers pop up in
|
||||
* different slots. */
|
||||
avail = sc_pkcs11_conf.slots_per_card;
|
||||
|
||||
if (first_free_slot + avail > sc_pkcs11_conf.max_virtual_slots)
|
||||
avail = sc_pkcs11_conf.max_virtual_slots - first_free_slot;
|
||||
card->first_slot = first_free_slot;
|
||||
card->max_slots = avail;
|
||||
card->num_slots = 0;
|
||||
|
||||
for (i = 0; i < card->max_slots; i++) {
|
||||
struct sc_pkcs11_slot *slot = virtual_slots + card->first_slot + i;
|
||||
slot->reader = reader;
|
||||
for (i = 0; i < sc_pkcs11_conf.slots_per_card; i++) {
|
||||
rv = create_slot(reader);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (sc_detect_card_presence(reader)) {
|
||||
card_detect(reader);
|
||||
}
|
||||
|
||||
first_free_slot += card->max_slots;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV card_detect(int reader)
|
||||
|
||||
CK_RV card_removed(sc_reader_t * reader)
|
||||
{
|
||||
struct sc_pkcs11_card *card = &card_table[reader];
|
||||
int rc, rv, i, retry = 1;
|
||||
unsigned int i;
|
||||
struct sc_pkcs11_card *card = NULL;
|
||||
/* Mark all slots as "token not present" */
|
||||
sc_debug(context, "%s: card removed", reader->name);
|
||||
|
||||
|
||||
for (i=0; i < list_size(&virtual_slots); i++) {
|
||||
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
||||
if (slot->reader == reader) {
|
||||
/* Save the "card" object */
|
||||
if (slot->card)
|
||||
card = slot->card;
|
||||
slot_token_removed(slot->id);
|
||||
}
|
||||
}
|
||||
|
||||
if (card) {
|
||||
card->framework->unbind(card);
|
||||
sc_disconnect_card(card->card);
|
||||
free(card);
|
||||
}
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
|
||||
CK_RV card_detect(sc_reader_t *reader)
|
||||
{
|
||||
struct sc_pkcs11_card *p11card;
|
||||
int rc, rv;
|
||||
unsigned int i;
|
||||
|
||||
rv = CKR_OK;
|
||||
|
||||
sc_debug(context, "%d: Detecting smart card\n", reader);
|
||||
for (i = card->max_slots; i--; ) {
|
||||
struct sc_pkcs11_slot *slot;
|
||||
sc_reader_t *rdr = sc_ctx_get_reader(context, (unsigned int)reader);
|
||||
|
||||
if (rdr == NULL)
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
slot = virtual_slots + card->first_slot + i;
|
||||
strcpy_bp(slot->slot_info.slotDescription, rdr->name, 64);
|
||||
slot->reader = reader;
|
||||
}
|
||||
|
||||
|
||||
/* Check if someone inserted a card */
|
||||
again: rc = sc_detect_card_presence(sc_ctx_get_reader(context, reader), 0);
|
||||
sc_debug(context, "%s: Detecting smart card\n", reader->name);
|
||||
/* Check if someone inserted a card */
|
||||
again:rc = sc_detect_card_presence(reader);
|
||||
if (rc < 0) {
|
||||
sc_debug(context, "Card detection failed for reader %d: %s\n",
|
||||
reader, sc_strerror(rc));
|
||||
return sc_to_cryptoki_error(rc, reader);
|
||||
sc_debug(context, "%s: failed, %s\n", reader->name, sc_strerror(rc));
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
if (rc == 0) {
|
||||
sc_debug(context, "%d: Card absent\n", reader);
|
||||
card_removed(reader); /* Release all resources */
|
||||
sc_debug(context, "%s: card absent\n", reader->name);
|
||||
card_removed(reader); /* Release all resources */
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
}
|
||||
|
||||
/* If the card was changed, disconnect the current one */
|
||||
if (rc & SC_SLOT_CARD_CHANGED) {
|
||||
sc_debug(context, "%d: Card changed\n", reader);
|
||||
if (rc & SC_READER_CARD_CHANGED) {
|
||||
sc_debug(context, "%s: Card changed\n", reader->name);
|
||||
/* The following should never happen - but if it
|
||||
* does we'll be stuck in an endless loop.
|
||||
* So better be fussy. */
|
||||
* So better be fussy.
|
||||
if (!retry--)
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
return CKR_TOKEN_NOT_PRESENT; */
|
||||
card_removed(reader);
|
||||
goto again;
|
||||
}
|
||||
|
||||
/* Locate a slot related to the reader */
|
||||
for (i=0; i<list_size(&virtual_slots); i++) {
|
||||
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
||||
if (slot->reader == reader) {
|
||||
p11card = slot->card;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Detect the card if it's not known already */
|
||||
if (card->card == NULL) {
|
||||
sc_debug(context, "%d: Connecting to smart card\n", reader);
|
||||
rc = sc_connect_card(sc_ctx_get_reader(context, reader), 0, &card->card);
|
||||
if (p11card == NULL) {
|
||||
sc_debug(context, "%s: First seen the card ", reader->name);
|
||||
p11card = (struct sc_pkcs11_card *)calloc(1, sizeof(struct sc_pkcs11_card));
|
||||
if (!p11card)
|
||||
return CKR_HOST_MEMORY;
|
||||
p11card->reader = reader;
|
||||
}
|
||||
|
||||
if (p11card->card == NULL) {
|
||||
sc_debug(context, "%s: Connecting ... ", reader->name);
|
||||
rc = sc_connect_card(reader, &p11card->card);
|
||||
if (rc != SC_SUCCESS)
|
||||
return sc_to_cryptoki_error(rc, reader);
|
||||
return sc_to_cryptoki_error(rc);
|
||||
}
|
||||
|
||||
/* Detect the framework */
|
||||
if (card->framework == NULL) {
|
||||
sc_debug(context, "%d: Detecting Framework\n", reader);
|
||||
if (p11card->framework == NULL) {
|
||||
sc_debug(context, "%s: Detecting Framework\n", reader->name);
|
||||
|
||||
for (i = 0; frameworks[i]; i++) {
|
||||
if (frameworks[i]->bind == NULL)
|
||||
continue;
|
||||
rv = frameworks[i]->bind(card);
|
||||
rv = frameworks[i]->bind(p11card);
|
||||
if (rv == CKR_OK)
|
||||
break;
|
||||
}
|
||||
|
@ -145,117 +217,64 @@ again: rc = sc_detect_card_presence(sc_ctx_get_reader(context, reader), 0);
|
|||
return CKR_TOKEN_NOT_RECOGNIZED;
|
||||
|
||||
/* Initialize framework */
|
||||
sc_debug(context, "%d: Detected framework %d. Creating tokens.\n", reader, i);
|
||||
rv = frameworks[i]->create_tokens(card);
|
||||
sc_debug(context, "%s: Detected framework %d. Creating tokens.\n", reader->name, i);
|
||||
rv = frameworks[i]->create_tokens(p11card);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
card->framework = frameworks[i];
|
||||
p11card->framework = frameworks[i];
|
||||
}
|
||||
|
||||
sc_debug(context, "%d: Detection ended\n", reader);
|
||||
return rv;
|
||||
}
|
||||
|
||||
CK_RV __card_detect_all(int report_events)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (context == NULL_PTR)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
for (i = 0; i < (int)sc_ctx_get_reader_count(context); i++)
|
||||
card_detect(i);
|
||||
if (!report_events) {
|
||||
CK_SLOT_ID id;
|
||||
|
||||
for (id = 0; id < sc_pkcs11_conf.max_virtual_slots; id++)
|
||||
virtual_slots[id].events = 0;
|
||||
}
|
||||
|
||||
sc_debug(context, "%s: Detection ended\n", reader->name);
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV card_detect_all(void)
|
||||
{
|
||||
return __card_detect_all(1);
|
||||
CK_RV card_detect_all() {
|
||||
unsigned int i;
|
||||
|
||||
/* Detect cards in all initialized readers */
|
||||
for (i=0; i< sc_ctx_get_reader_count(context); i++) {
|
||||
sc_reader_t *reader = sc_ctx_get_reader(context, i);
|
||||
if (!reader_get_slot(reader))
|
||||
initialize_reader(reader);
|
||||
card_detect(sc_ctx_get_reader(context, i));
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV card_removed(int reader)
|
||||
/* Allocates an existing slot to a card */
|
||||
CK_RV slot_allocate(struct sc_pkcs11_slot ** slot, struct sc_pkcs11_card * card)
|
||||
{
|
||||
unsigned int i;
|
||||
struct sc_pkcs11_card *card;
|
||||
unsigned int i;
|
||||
struct sc_pkcs11_slot *tmp_slot = NULL;
|
||||
|
||||
sc_debug(context, "%d: smart card removed\n", reader);
|
||||
|
||||
for (i=0; i<sc_pkcs11_conf.max_virtual_slots; i++) {
|
||||
if (virtual_slots[i].card &&
|
||||
virtual_slots[i].card->reader == reader)
|
||||
slot_token_removed(i);
|
||||
/* Locate a free slot for this reader */
|
||||
for (i=0; i< list_size(&virtual_slots); i++) {
|
||||
tmp_slot = (struct sc_pkcs11_slot *)list_get_at(&virtual_slots, i);
|
||||
if (tmp_slot->reader == card->reader && tmp_slot->card == NULL)
|
||||
break;
|
||||
}
|
||||
|
||||
/* beware - do not clean the entire sc_pkcs11_card struct;
|
||||
* fields such as first_slot and max_slots are initialized
|
||||
* _once_ and need to be left untouched across card removal/
|
||||
* insertion */
|
||||
card = &card_table[reader];
|
||||
if (card->framework)
|
||||
card->framework->unbind(card);
|
||||
card->framework = NULL;
|
||||
card->fw_data = NULL;
|
||||
|
||||
if (card->card)
|
||||
sc_disconnect_card(card->card, 0);
|
||||
card->card = NULL;
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV slot_initialize(int id, struct sc_pkcs11_slot *slot)
|
||||
{
|
||||
memset(slot, 0, sizeof(*slot));
|
||||
slot->id = id;
|
||||
slot->login_user = -1;
|
||||
init_slot_info(&slot->slot_info);
|
||||
pool_initialize(&slot->object_pool, POOL_TYPE_OBJECT);
|
||||
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV slot_allocate(struct sc_pkcs11_slot **slot, struct sc_pkcs11_card *card)
|
||||
{
|
||||
unsigned int i, first, last;
|
||||
|
||||
if (card->num_slots >= card->max_slots)
|
||||
if (!tmp_slot)
|
||||
return CKR_FUNCTION_FAILED;
|
||||
first = card->first_slot;
|
||||
last = first + card->max_slots;
|
||||
|
||||
for (i = first; i < last; i++) {
|
||||
if (!virtual_slots[i].card) {
|
||||
sc_debug(context, "Allocated slot %d\n", i);
|
||||
virtual_slots[i].card = card;
|
||||
virtual_slots[i].events = SC_EVENT_CARD_INSERTED;
|
||||
*slot = &virtual_slots[i];
|
||||
card->num_slots++;
|
||||
return CKR_OK;
|
||||
}
|
||||
}
|
||||
return CKR_FUNCTION_FAILED;
|
||||
sc_debug(context, "Allocated slot 0x%lx for card in reader %s", tmp_slot->id,
|
||||
card->reader->name);
|
||||
tmp_slot->card = card;
|
||||
tmp_slot->events = SC_EVENT_CARD_INSERTED;
|
||||
*slot = tmp_slot;
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV slot_get_slot(int id, struct sc_pkcs11_slot **slot)
|
||||
CK_RV slot_get_slot(CK_SLOT_ID id, struct sc_pkcs11_slot ** slot)
|
||||
{
|
||||
if (context == NULL)
|
||||
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
||||
|
||||
if (id < 0 || id >= sc_pkcs11_conf.max_virtual_slots)
|
||||
*slot = list_seek(&virtual_slots, &id); // FIXME: check for null?
|
||||
if (!*slot)
|
||||
return CKR_SLOT_ID_INVALID;
|
||||
|
||||
*slot = &virtual_slots[id];
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV slot_get_token(int id, struct sc_pkcs11_slot **slot)
|
||||
CK_RV slot_get_token(CK_SLOT_ID id, struct sc_pkcs11_slot ** slot)
|
||||
{
|
||||
int rv;
|
||||
|
||||
|
@ -263,29 +282,29 @@ CK_RV slot_get_token(int id, struct sc_pkcs11_slot **slot)
|
|||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
||||
if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT))
|
||||
{
|
||||
rv = card_detect((*slot)->reader);
|
||||
if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT)) {
|
||||
if ((*slot)->reader == NULL)
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
rv = card_detect((*slot)->reader);
|
||||
if (rv != CKR_OK)
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
return rv;
|
||||
}
|
||||
|
||||
if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT))
|
||||
{
|
||||
if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT)) {
|
||||
sc_debug(context, "card detected, but slot not presenting token");
|
||||
return CKR_TOKEN_NOT_PRESENT;
|
||||
}
|
||||
return CKR_OK;
|
||||
}
|
||||
|
||||
CK_RV slot_token_removed(int id)
|
||||
CK_RV slot_token_removed(CK_SLOT_ID id)
|
||||
{
|
||||
int rv, token_was_present;
|
||||
unsigned int i;
|
||||
struct sc_pkcs11_slot *slot;
|
||||
struct sc_pkcs11_object *object;
|
||||
CK_SLOT_INFO saved_slot_info;
|
||||
int reader;
|
||||
|
||||
sc_debug(context, "slot_token_removed(0x%lx)", id);
|
||||
rv = slot_get_slot(id, &slot);
|
||||
if (rv != CKR_OK)
|
||||
return rv;
|
||||
|
@ -295,31 +314,24 @@ CK_RV slot_token_removed(int id)
|
|||
/* Terminate active sessions */
|
||||
sc_pkcs11_close_all_sessions(id);
|
||||
|
||||
/* Object pool */
|
||||
while (pool_find_and_delete(&slot->object_pool, 0, (void**) &object) == CKR_OK) {
|
||||
for (i=0; i<list_size(&slot->objects); i++) {
|
||||
object = (struct sc_pkcs11_object *)list_get_at(&slot->objects, i);
|
||||
if (object->ops->release)
|
||||
object->ops->release(object);
|
||||
}
|
||||
list_delete(&slot->objects, object);
|
||||
}
|
||||
|
||||
/* Release framework stuff */
|
||||
if (slot->card != NULL) {
|
||||
if (slot->fw_data != NULL &&
|
||||
slot->card->framework != NULL &&
|
||||
slot->card->framework->release_token != NULL)
|
||||
slot->card->framework != NULL && slot->card->framework->release_token != NULL)
|
||||
slot->card->framework->release_token(slot->card, slot->fw_data);
|
||||
slot->card->num_slots--;
|
||||
}
|
||||
|
||||
/* Zap everything else. Restore the slot_info afterwards (it contains the reader
|
||||
* name, for instance) but clear its flags */
|
||||
saved_slot_info = slot->slot_info;
|
||||
reader = slot->reader;
|
||||
memset(slot, 0, sizeof(*slot));
|
||||
slot->slot_info = saved_slot_info;
|
||||
slot->slot_info.flags = 0;
|
||||
/* Reset relevant slot properties */
|
||||
slot->slot_info.flags &= ~CKF_TOKEN_PRESENT;
|
||||
slot->login_user = -1;
|
||||
slot->reader = reader;
|
||||
pool_initialize(&slot->object_pool, POOL_TYPE_OBJECT);
|
||||
slot->card = NULL;
|
||||
|
||||
if (token_was_present)
|
||||
slot->events = SC_EVENT_CARD_REMOVED;
|
||||
|
@ -327,22 +339,28 @@ CK_RV slot_token_removed(int id)
|
|||
return CKR_OK;
|
||||
}
|
||||
|
||||
/* Called from C_WaitForSlotEvent */
|
||||
CK_RV slot_find_changed(CK_SLOT_ID_PTR idp, int mask)
|
||||
{
|
||||
sc_pkcs11_slot_t *slot;
|
||||
CK_SLOT_ID id;
|
||||
unsigned int i;
|
||||
SC_FUNC_CALLED(context, 3);
|
||||
|
||||
card_detect_all();
|
||||
for (id = 0; id < sc_pkcs11_conf.max_virtual_slots; id++) {
|
||||
slot = &virtual_slots[id];
|
||||
for (i=0; i<list_size(&virtual_slots); i++) {
|
||||
sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
|
||||
sc_debug(context, "slot 0x%lx token: %d events: 0x%02X",slot->id, (slot->slot_info.flags & CKF_TOKEN_PRESENT), slot->events);
|
||||
if ((slot->events & SC_EVENT_CARD_INSERTED)
|
||||
&& !(slot->slot_info.flags & CKF_TOKEN_PRESENT))
|
||||
&& !(slot->slot_info.flags & CKF_TOKEN_PRESENT)) {
|
||||
/* If a token has not been initialized, clear the inserted event */
|
||||
slot->events &= ~SC_EVENT_CARD_INSERTED;
|
||||
}
|
||||
sc_debug(context, "mask: 0x%02X events: 0x%02X result: %d", mask, slot->events, (slot->events & mask));
|
||||
|
||||
if (slot->events & mask) {
|
||||
slot->events &= ~mask;
|
||||
*idp = id;
|
||||
return CKR_OK;
|
||||
*idp = slot->id;
|
||||
SC_FUNC_RETURN(context, 3, CKR_OK);
|
||||
}
|
||||
}
|
||||
return CKR_NO_EVENT;
|
||||
SC_FUNC_RETURN(context, 3, CKR_NO_EVENT);
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue