2002-01-16 22:49:03 +00:00
|
|
|
|
/*
|
|
|
|
|
* slot.c: Smartcard and slot related management functions
|
|
|
|
|
*
|
|
|
|
|
* Copyright (C) 2002 Timo Ter<EFBFBD>s <timo.teras@iki.fi>
|
|
|
|
|
*
|
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
|
*
|
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
|
*
|
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
|
|
|
*/
|
|
|
|
|
|
2002-03-21 09:36:38 +00:00
|
|
|
|
#include <string.h>
|
2002-03-25 12:39:35 +00:00
|
|
|
|
#include "sc-pkcs11.h"
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
|
|
static struct sc_pkcs11_framework_ops *frameworks[] = {
|
|
|
|
|
&framework_pkcs15,
|
2002-06-20 13:16:22 +00:00
|
|
|
|
#ifdef USE_PKCS15_INIT
|
2002-04-05 15:03:03 +00:00
|
|
|
|
/* This should be the last framework, because it
|
|
|
|
|
* will assume the card is blank and try to initialize it */
|
2002-06-20 13:16:22 +00:00
|
|
|
|
&framework_pkcs15init,
|
|
|
|
|
#endif
|
2002-01-16 22:49:03 +00:00
|
|
|
|
NULL
|
|
|
|
|
};
|
|
|
|
|
|
2003-01-13 21:38:43 +00:00
|
|
|
|
static void init_slot_info(CK_SLOT_INFO_PTR pInfo)
|
2002-01-16 22:49:03 +00:00
|
|
|
|
{
|
|
|
|
|
strcpy_bp(pInfo->slotDescription, "Virtual slot", 64);
|
|
|
|
|
strcpy_bp(pInfo->manufacturerID, "OpenSC project (www.opensc.org)", 32);
|
|
|
|
|
pInfo->flags = CKF_REMOVABLE_DEVICE | CKF_HW_SLOT;
|
|
|
|
|
pInfo->hardwareVersion.major = 0;
|
|
|
|
|
pInfo->hardwareVersion.minor = 0;
|
|
|
|
|
pInfo->firmwareVersion.major = 0;
|
|
|
|
|
pInfo->firmwareVersion.minor = 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CK_RV card_initialize(int reader)
|
|
|
|
|
{
|
|
|
|
|
memset(&card_table[reader], 0, sizeof(struct sc_pkcs11_card));
|
|
|
|
|
card_table[reader].reader = reader;
|
|
|
|
|
return CKR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-20 09:50:33 +00:00
|
|
|
|
static CK_RV card_detect(int reader)
|
2002-01-16 22:49:03 +00:00
|
|
|
|
{
|
2002-04-05 15:03:03 +00:00
|
|
|
|
struct sc_pkcs11_card *card;
|
2003-01-19 17:47:07 +00:00
|
|
|
|
int rc, rv, i, retry = 1;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
|
|
rv = CKR_OK;
|
|
|
|
|
|
|
|
|
|
debug(context, "%d: Detecting SmartCard\n", reader);
|
|
|
|
|
|
2003-01-19 17:47:07 +00:00
|
|
|
|
/* Check if someone inserted a card */
|
|
|
|
|
again: rc = sc_detect_card_presence(context->reader[reader], 0);
|
|
|
|
|
if (rc < 0) {
|
|
|
|
|
debug(context, "Card detection failed for reader %d: %s\n",
|
|
|
|
|
reader, sc_strerror(rc));
|
|
|
|
|
return sc_to_cryptoki_error(rc, reader);
|
|
|
|
|
}
|
|
|
|
|
if (rc == 0) {
|
|
|
|
|
debug(context, "%d: Card absent\n", reader);
|
|
|
|
|
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) {
|
|
|
|
|
debug(context, "%d: Card changed\n", reader);
|
|
|
|
|
/* The following should never happen - but if it
|
|
|
|
|
* does we'll be stuck in an endless loop.
|
|
|
|
|
* So better be fussy. */
|
|
|
|
|
if (!retry--)
|
2002-01-16 22:49:03 +00:00
|
|
|
|
return CKR_TOKEN_NOT_PRESENT;
|
2003-01-19 17:47:07 +00:00
|
|
|
|
card_removed(reader);
|
|
|
|
|
goto again;
|
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
2003-01-19 17:47:07 +00:00
|
|
|
|
/* Detect the card if it's not known already */
|
|
|
|
|
if (card_table[reader].card == NULL) {
|
2002-01-16 22:49:03 +00:00
|
|
|
|
debug(context, "%d: Connecting to SmartCard\n", reader);
|
2002-02-25 12:04:39 +00:00
|
|
|
|
rc = sc_connect_card(context->reader[reader], 0, &card_table[reader].card);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
if (rc != SC_SUCCESS)
|
|
|
|
|
return sc_to_cryptoki_error(rc, reader);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* Detect the framework */
|
|
|
|
|
if (card_table[reader].framework == NULL) {
|
|
|
|
|
debug(context, "%d: Detecting Framework\n", reader);
|
|
|
|
|
|
2002-04-05 15:03:03 +00:00
|
|
|
|
card = &card_table[reader];
|
2002-12-21 16:45:37 +00:00
|
|
|
|
|
|
|
|
|
if (sc_pkcs11_conf.num_slots == 0)
|
2003-01-13 21:38:43 +00:00
|
|
|
|
card->max_slots = SC_PKCS11_DEF_SLOTS_PER_CARD;
|
2002-12-21 16:45:37 +00:00
|
|
|
|
else
|
|
|
|
|
card->max_slots = sc_pkcs11_conf.num_slots;
|
|
|
|
|
card->num_slots = 0;
|
|
|
|
|
|
2002-04-05 15:03:03 +00:00
|
|
|
|
for (i = 0; frameworks[i]; i++) {
|
2002-08-08 20:53:40 +00:00
|
|
|
|
if (frameworks[i]->bind == NULL)
|
|
|
|
|
continue;
|
2002-04-05 15:03:03 +00:00
|
|
|
|
rv = frameworks[i]->bind(card);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
if (rv == CKR_OK)
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (frameworks[i] == NULL)
|
|
|
|
|
return CKR_TOKEN_NOT_RECOGNIZED;
|
|
|
|
|
|
|
|
|
|
/* Initialize framework */
|
|
|
|
|
debug(context, "%d: Detected framework %d. Creating tokens.\n", reader, i);
|
2002-04-05 15:03:03 +00:00
|
|
|
|
rv = frameworks[i]->create_tokens(card);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
|
|
card_table[reader].framework = frameworks[i];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
debug(context, "%d: Detection ended\n", reader);
|
|
|
|
|
return rv;
|
|
|
|
|
}
|
|
|
|
|
|
2003-01-20 09:50:33 +00:00
|
|
|
|
CK_RV card_detect_all(void)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (context == NULL_PTR)
|
|
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
|
|
|
for (i = 0; i < context->reader_count; i++)
|
|
|
|
|
card_detect(i);
|
2003-01-27 13:17:08 +00:00
|
|
|
|
|
2003-01-27 13:43:06 +00:00
|
|
|
|
return CKR_OK;
|
2003-01-20 09:50:33 +00:00
|
|
|
|
}
|
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
|
CK_RV card_removed(int reader)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
struct sc_pkcs11_card *card;
|
|
|
|
|
|
|
|
|
|
debug(context, "%d: SmartCard removed\n", reader);
|
|
|
|
|
|
|
|
|
|
for (i=0; i<SC_PKCS11_MAX_VIRTUAL_SLOTS; i++) {
|
2002-01-22 14:44:56 +00:00
|
|
|
|
if (virtual_slots[i].card &&
|
|
|
|
|
virtual_slots[i].card->reader == reader)
|
2002-01-16 22:49:03 +00:00
|
|
|
|
slot_token_removed(i);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
card = &card_table[reader];
|
2002-04-05 15:03:03 +00:00
|
|
|
|
if (card->framework)
|
|
|
|
|
card->framework->unbind(card);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
card->framework = NULL;
|
|
|
|
|
card->fw_data = NULL;
|
|
|
|
|
|
2002-04-05 15:03:03 +00:00
|
|
|
|
if (card->card)
|
|
|
|
|
sc_disconnect_card(card->card, 0);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
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;
|
2003-01-13 21:38:43 +00:00
|
|
|
|
init_slot_info(&slot->slot_info);
|
2002-11-22 09:10:10 +00:00
|
|
|
|
pool_initialize(&slot->object_pool, POOL_TYPE_OBJECT);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
|
|
return CKR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CK_RV slot_allocate(struct sc_pkcs11_slot **slot, struct sc_pkcs11_card *card)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
2002-12-21 16:45:37 +00:00
|
|
|
|
|
|
|
|
|
if (card->num_slots >= card->max_slots)
|
|
|
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
|
|
2002-01-16 22:49:03 +00:00
|
|
|
|
for (i=0; i<SC_PKCS11_MAX_VIRTUAL_SLOTS; i++) {
|
2003-01-13 21:38:43 +00:00
|
|
|
|
if (!virtual_slots[i].card) {
|
2002-01-16 22:49:03 +00:00
|
|
|
|
debug(context, "Allocated slot %d\n", i);
|
|
|
|
|
|
|
|
|
|
virtual_slots[i].card = card;
|
|
|
|
|
*slot = &virtual_slots[i];
|
2003-01-28 15:39:47 +00:00
|
|
|
|
strcpy_bp((*slot)->slot_info.slotDescription,
|
|
|
|
|
card->card->reader->name, 64);
|
2002-12-21 16:45:37 +00:00
|
|
|
|
card->num_slots++;
|
|
|
|
|
return CKR_OK;
|
2002-01-16 22:49:03 +00:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return CKR_FUNCTION_FAILED;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CK_RV slot_get_slot(int id, struct sc_pkcs11_slot **slot)
|
|
|
|
|
{
|
|
|
|
|
if (context == NULL)
|
|
|
|
|
return CKR_CRYPTOKI_NOT_INITIALIZED;
|
|
|
|
|
|
|
|
|
|
if (id < 0 || id >= SC_PKCS11_MAX_VIRTUAL_SLOTS)
|
|
|
|
|
return CKR_SLOT_ID_INVALID;
|
|
|
|
|
|
|
|
|
|
*slot = &virtual_slots[id];
|
|
|
|
|
return CKR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CK_RV slot_get_token(int id, struct sc_pkcs11_slot **slot)
|
|
|
|
|
{
|
|
|
|
|
int rv;
|
|
|
|
|
|
|
|
|
|
rv = slot_get_slot(id, slot);
|
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
|
|
if (!((*slot)->slot_info.flags & CKF_TOKEN_PRESENT))
|
|
|
|
|
return CKR_TOKEN_NOT_PRESENT;
|
|
|
|
|
|
|
|
|
|
return CKR_OK;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
CK_RV slot_token_removed(int id)
|
|
|
|
|
{
|
|
|
|
|
int rv;
|
|
|
|
|
struct sc_pkcs11_slot *slot;
|
|
|
|
|
struct sc_pkcs11_object *object;
|
|
|
|
|
|
2003-01-27 13:17:08 +00:00
|
|
|
|
rv = slot_get_slot(id, &slot);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
if (rv != CKR_OK)
|
|
|
|
|
return rv;
|
|
|
|
|
|
|
|
|
|
/* Terminate active sessions */
|
|
|
|
|
C_CloseAllSessions(id);
|
|
|
|
|
|
|
|
|
|
/* Object pool */
|
2002-01-24 16:27:09 +00:00
|
|
|
|
while (pool_find_and_delete(&slot->object_pool, 0, (void**) &object) == CKR_OK) {
|
|
|
|
|
if (object->ops->release)
|
|
|
|
|
object->ops->release(object);
|
|
|
|
|
}
|
2002-01-16 22:49:03 +00:00
|
|
|
|
|
|
|
|
|
/* Release framework stuff */
|
2003-01-13 21:38:43 +00:00
|
|
|
|
if (slot->card != NULL && slot->fw_data != NULL)
|
2002-01-16 22:49:03 +00:00
|
|
|
|
slot->card->framework->release_token(slot->card, slot->fw_data);
|
|
|
|
|
|
|
|
|
|
/* Zap everything else */
|
2003-01-13 21:38:43 +00:00
|
|
|
|
memset(slot, 0, sizeof(*slot));
|
|
|
|
|
init_slot_info(&slot->slot_info);
|
2002-01-16 22:49:03 +00:00
|
|
|
|
slot->login_user = -1;
|
|
|
|
|
|
|
|
|
|
return CKR_OK;
|
|
|
|
|
|
|
|
|
|
}
|