Author: Paul Wolneykien Date: Wed Sep 6 11:47:40 2017 +0300 Refresh the slot list each time C_GetSlotList() is called In order to make token insert and remove operations observable, it's necessary to call C_GetSlotList() with NULL pointer argument. The latter is a signal for each underlying PKCS#11 module to update the slot and token status information. The following is stated in the PKCS #11 Cryptographic Token Interface Base Specification Version 2.40, 5.5 Slot and token management functions: "The set of slots accessible through a Cryptoki library is checked at the time that C_GetSlotList, for list length prediction (NULL pSlotList argument) is called. If an application calls C_GetSlotList with a non-NULL pSlotList, and *then* the user adds or removes a hardware device, the changed slot list will only be visible and effective if C_GetSlotList is called again with NULL." (http://docs.oasis-open.org/pkcs11/pkcs11-base/v2.40/os/pkcs11-base-v2.40-os.html) diff --git a/p11-kit/proxy.c b/p11-kit/proxy.c index 8c437a0..6adc822 100644 --- a/p11-kit/proxy.c +++ b/p11-kit/proxy.c @@ -248,13 +248,58 @@ modules_dup (CK_FUNCTION_LIST **modules) } static CK_RV -proxy_create (Proxy **res) +proxy_refresh_slots (Proxy *py) { - CK_FUNCTION_LIST_PTR *f; + CK_FUNCTION_LIST_PTR *f; CK_FUNCTION_LIST_PTR funcs; CK_SLOT_ID_PTR slots; CK_ULONG i, count; - CK_RV rv = CKR_OK; + CK_RV rv = CKR_OK; + + py->n_mappings = 0; + + for (f = py->inited; *f; ++f) { + funcs = *f; + assert (funcs != NULL); + slots = NULL; + + /* Ask module for its slots */ + rv = (funcs->C_GetSlotList) (FALSE, NULL, &count); + if (rv == CKR_OK && count) { + slots = calloc (sizeof (CK_SLOT_ID), count); + rv = (funcs->C_GetSlotList) (FALSE, slots, &count); + } + + if (rv != CKR_OK) { + free (slots); + break; + } + + return_val_if_fail (count == 0 || slots != NULL, CKR_GENERAL_ERROR); + + if (count > 0) { + py->mappings = realloc (py->mappings, sizeof (Mapping) * (py->n_mappings + count)); + return_val_if_fail (py->mappings != NULL, CKR_HOST_MEMORY); + + /* And now add a mapping for each of those slots */ + for (i = 0; i < count; ++i) { + py->mappings[py->n_mappings].funcs = funcs; + py->mappings[py->n_mappings].wrap_slot = py->n_mappings + MAPPING_OFFSET; + py->mappings[py->n_mappings].real_slot = slots[i]; + ++py->n_mappings; + } + } + + free (slots); + } + + return rv; +} + +static CK_RV +proxy_create (Proxy **res) +{ + CK_RV rv = CKR_OK; Proxy *py; py = calloc (1, sizeof (Proxy)); @@ -268,40 +313,7 @@ proxy_create (Proxy **res) rv = p11_kit_modules_initialize (py->inited, NULL); if (rv == CKR_OK) { - for (f = py->inited; *f; ++f) { - funcs = *f; - assert (funcs != NULL); - slots = NULL; - - /* Ask module for its slots */ - rv = (funcs->C_GetSlotList) (FALSE, NULL, &count); - if (rv == CKR_OK && count) { - slots = calloc (sizeof (CK_SLOT_ID), count); - rv = (funcs->C_GetSlotList) (FALSE, slots, &count); - } - - if (rv != CKR_OK) { - free (slots); - break; - } - - return_val_if_fail (count == 0 || slots != NULL, CKR_GENERAL_ERROR); - - if (count > 0) { - py->mappings = realloc (py->mappings, sizeof (Mapping) * (py->n_mappings + count)); - return_val_if_fail (py->mappings != NULL, CKR_HOST_MEMORY); - - /* And now add a mapping for each of those slots */ - for (i = 0; i < count; ++i) { - py->mappings[py->n_mappings].funcs = funcs; - py->mappings[py->n_mappings].wrap_slot = py->n_mappings + MAPPING_OFFSET; - py->mappings[py->n_mappings].real_slot = slots[i]; - ++py->n_mappings; - } - } - - free (slots); - } + rv = proxy_refresh_slots (py); } if (rv != CKR_OK) { @@ -428,6 +440,14 @@ proxy_C_GetSlotList (CK_X_FUNCTION_LIST *self, } else { index = 0; + /* Refresh the slots: some tokens might be inserted + or removed. */ + rv = proxy_refresh_slots (state->px); + if ( CKR_OK != rv ) { + p11_unlock (); + return rv; + } + /* Go through and build up a map */ for (i = 0; i < state->px->n_mappings; ++i) { mapping = &state->px->mappings[i];