pkcs11: reclaim unused slots based on reader description

When a reader is removed and reattached, this re-uses the old slot
without relying on the fact that the sc_reader_t is unchanged.
This commit is contained in:
Frank Morgner 2020-03-03 15:09:17 +01:00
parent ce704f5eb1
commit 5b9af96851
2 changed files with 41 additions and 10 deletions

View File

@ -468,8 +468,7 @@ CK_RV C_GetSlotList(CK_BBOOL tokenPresent, /* only slots with token prese
for (i=0; i<list_size(&virtual_slots); i++) { for (i=0; i<list_size(&virtual_slots); i++) {
slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i); slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
/* the list of available slots contains: /* the list of available slots contains:
* - if present, virtual hotplug slot; * - without token(s), at least one empty slot per reader;
* - without token(s), one empty slot per reader;
* - any slot with token; * - any slot with token;
* - any slot that has already been seen; * - any slot that has already been seen;
*/ */
@ -550,7 +549,7 @@ CK_RV C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
sc_log(context, "C_GetSlotInfo(0x%lx)", slotID); sc_log(context, "C_GetSlotInfo(0x%lx)", slotID);
if (sc_pkcs11_conf.init_sloppy) { if (sc_pkcs11_conf.init_sloppy) {
/* Most likely virtual_slots only contains the hotplug slot and has not /* Most likely virtual_slots is empty and has not
* been initialized because the caller has *not* called C_GetSlotList * been initialized because the caller has *not* called C_GetSlotList
* before C_GetSlotInfo, as required by PKCS#11. Initialize * before C_GetSlotInfo, as required by PKCS#11. Initialize
* virtual_slots to make things work and hope the caller knows what * virtual_slots to make things work and hope the caller knows what

View File

@ -37,15 +37,26 @@ static struct sc_pkcs11_framework_ops *frameworks[] = {
NULL NULL
}; };
static struct sc_pkcs11_slot * reader_get_slot(sc_reader_t *reader) static struct sc_pkcs11_slot * reader_reclaim_slot(sc_reader_t *reader)
{ {
unsigned int i; unsigned int i;
CK_UTF8CHAR slotDescription[64];
CK_UTF8CHAR manufacturerID[32];
strcpy_bp(slotDescription, reader->name, 64);
strcpy_bp(manufacturerID, reader->vendor, 32);
/* Locate a slot related to the reader */ /* Locate a slot related to the reader */
for (i = 0; i<list_size(&virtual_slots); i++) { 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_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
if (slot->reader == reader) if (slot->reader == reader)
return slot; return slot;
if (slot->reader == NULL && reader != NULL
&& 0 == memcmp(slot->slot_info.slotDescription, slotDescription, 64)
&& 0 == memcmp(slot->slot_info.manufacturerID, manufacturerID, 32)
&& slot->slot_info.hardwareVersion.major == reader->version_major
&& slot->slot_info.hardwareVersion.minor == reader->version_minor)
return slot;
} }
return NULL; return NULL;
} }
@ -82,8 +93,8 @@ static int object_list_seeker(const void *el, const void *key)
CK_RV create_slot(sc_reader_t *reader) CK_RV create_slot(sc_reader_t *reader)
{ {
/* find unused virtual hotplug slots */ /* find unused slots previously allocated for the same reader */
struct sc_pkcs11_slot *slot = reader_get_slot(NULL); struct sc_pkcs11_slot *slot = reader_reclaim_slot(reader);
/* create a new slot if no empty slot is available */ /* create a new slot if no empty slot is available */
if (!slot) { if (!slot) {
@ -373,11 +384,32 @@ card_detect_all(void)
* possible according to PKCS#11 2.20 and later, because NSS can't * possible according to PKCS#11 2.20 and later, because NSS can't
* handle a shrinking slot list * handle a shrinking slot list
* https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */ * https://bugzilla.mozilla.org/show_bug.cgi?id=1613632 */
/* Instead, remove the releation between reader and slot */
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) {
slot->reader = NULL;
}
}
} else { } else {
if (!reader_get_slot(reader)) /* Locate a slot related to the reader */
initialize_reader(reader); int found = 0;
else for (i = 0; i<list_size(&virtual_slots); i++) {
card_detect(sc_ctx_get_reader(context, i)); sc_pkcs11_slot_t *slot = (sc_pkcs11_slot_t *) list_get_at(&virtual_slots, i);
if (slot->reader == reader) {
found = 1;
break;
}
}
if (!found) {
for (i = 0; i < sc_pkcs11_conf.slots_per_card; i++) {
CK_RV rv = create_slot(reader);
if (rv != CKR_OK)
return rv;
}
}
card_detect(reader);
} }
} }
sc_log(context, "All cards detected"); sc_log(context, "All cards detected");