pkcs11SlotToken.c revision d288ba7491829a622697c947c3f1a30aec18c133
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * CDDL HEADER START
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The contents of this file are subject to the terms of the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Common Development and Distribution License (the "License").
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You may not use this file except in compliance with the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * See the License for the specific language governing permissions
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * and limitations under the License.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * When distributing Covered Code, include this CDDL HEADER in each
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If applicable, add the following below this CDDL HEADER, with the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * fields enclosed by brackets "[]" replaced with your own identifying
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * information: Portions Copyright [yyyy] [name of copyright owner]
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * CDDL HEADER END
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Use is subject to license terms.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Fosterstatic void *listener_waitforslotevent(void *arg);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * C_GetSlotList is implemented entirely within this framework,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * using the slottable that was created during the call to
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * C_Initialize in pkcs11_slot_mapping(). The plugged in providers
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * are only queried when tokenPresent is set.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If metaslot is enabled, the slot that provides keystore support
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * needs to be hidden. Therefore, even when fastpath is enabled,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * we can't go through fastpath because the slot needs to be
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterC_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CK_SLOT_ID slot_id; /* slot ID for returning to the application */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Check for a fastpath */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((purefastpath || policyfastpath) && (!metaslot_enabled)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (fast_funcs->C_GetSlotList(tokenPresent, pSlotList,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Need to allocate memory for pinfo */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Count the number of valid slots for returning to the application.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If metaslot is enabled, the slot providing keystore support for
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * metaslot is skipped. Therefore, we can't simply sequentially
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * assign "i" as the slot id to be returned to the application.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * The variable "slot_id" is used for keeping track of the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * next slot id to be assigned.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = slottable->st_first; i <= slottable->st_last; i++) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster ((!metaslot_enabled) || (i != metaslot_keystore_slotid))) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Check if token present is required */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Check with provider */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Fill in the given buffer if it is sufficient */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* pSlotList set to NULL means caller only wants count */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((*pulCount < count) && (pSlotList != NULL)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterC_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Check for a fastpath */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((purefastpath || policyfastpath) && !metaslot_enabled)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (fast_funcs->C_GetSlotInfo(slotID, pInfo));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* just need to get metaslot information */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (meta_GetSlotInfo(METASLOT_SLOTID, pInfo));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Check that slotID is valid */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster rv = FUNCLIST(fw_st_id)->C_GetSlotInfo(TRUEID(fw_st_id), pInfo);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Present consistent interface to the application */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterC_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster CK_SLOT_ID fw_st_id; /* id for accessing framework's slottable */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Check for a fastpath */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((purefastpath || policyfastpath) && !metaslot_enabled)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (fast_funcs->C_GetTokenInfo(slotID, pInfo));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* just need to get metaslot information */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (meta_GetTokenInfo(METASLOT_SLOTID, pInfo));
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Check that slotID is valid */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if (pkcs11_validate_and_convert_slotid(slotID, &fw_st_id) != CKR_OK) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster rv = FUNCLIST(fw_st_id)->C_GetTokenInfo(TRUEID(fw_st_id), pInfo);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Present consistent interface to the application */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * C_WaitForSlotEvent cannot be a direct pass through to the underlying
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * provider (except in the case of fastpath), due to the complex nature
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * of this function. The calling application is asking to be alerted
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * when an event has occurred on any of the slots in the framework, so
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * we need to check with all underlying providers and ask for events
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * on any of their slots. If this is called in blocking mode, we will
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * need to start threads to wait for slot events for each provider
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * plugged into the framework.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan FosterC_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Check for a fastpath */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster return (fast_funcs->C_WaitForSlotEvent(flags, pSlot,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Check to see if we're already blocking on another threads
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * call to this function. If so, behaviour is undefined so
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * we should return to application.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((slottable->st_blocking) || (slottable->st_wfse_active)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Check first to see if any events have been recorded
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * already on any of the slots, regardless of blocking or
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * thread status.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = slottable->st_first; i <= slottable->st_last; i++) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* found one, clear event and notify application */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&cur_slot->sl_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&cur_slot->sl_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * This event has been captured, clear the function's
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * active status. Other threads may now enter this
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * We could not find any existing event, so let's see
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * if we can block and start threads to watch for events.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Application does not want us to block so check with
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * underlying providers to see if any events have occurred.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Not every provider will have implemented this function,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * so error codes or CKR_NO_EVENT can be ignored.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = slottable->st_first; i <= slottable->st_last; i++) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Only do process once per provider.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Check to make sure a child thread is not already
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * running, due to another of the application's
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * thread calling this function.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&cur_slot->sl_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Release the hold on the slot's mutex while we
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * are waiting for this function to complete.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&cur_slot->sl_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&cur_slot->sl_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&cur_slot->sl_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* See if we've found a slot with an event */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Try to map the returned slotid to a slot
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * allocated by the framework. All slots from
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * one provider are adjacent in the framework's
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * slottable, so search for a mapping while
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * the prov_id field is the same.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Find the slot, remap pSlot */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * If we reach this part of the loop, this
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * provider either had no events, did not support
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * this function, or set pSlot to a value we
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * could not find in the slots associated with
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * this provider. Continue checking with remaining
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * providers.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* No provider had any events */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster } else if (!(flags & CKF_DONT_BLOCK) && (pkcs11_cant_create_threads)) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Application has asked us to block, but forbidden
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * us from creating threads. This is too risky to perform
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * with underlying providers (we may block indefinitely),
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * so will return an error in this case.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Grab the st_start_mutex now, which will prevent the listener
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * thread from signaling on st_start_cond before we're ready to
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * wait for it.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&slottable->st_start_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Application allows us to create threads and has
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * asked us to block. Create listener thread to wait for
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * child threads to return.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_start_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Wait for the listening thread to get started before
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * we spawn child threads.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_cond_wait(&slottable->st_start_cond,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&slottable->st_start_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Need to hold the mutex on the entire slottable for the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * entire setup of the child threads. Otherwise, the first
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * child thread may complete before a later child thread is
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * fully started, resulting in an inaccurate value of
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * st_thr_count and a potential race condition.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&slottable->st_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Create child threads to check with the plugged in providers
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * to check for events. Keep a count of the current open threads,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * so the listener thread knows when there are no more children
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * to listen for. Also, make sure a thread is not already active
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * for that provider.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster for (i = slottable->st_first; i <= slottable->st_last; i++) {
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Only do process once per provider.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Check to make sure a child thread is not already running,
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * due to another of the application's threads calling
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * this function. Also, check that the provider has actually
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * implemented this function.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_lock(&cur_slot->sl_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster if ((cur_slot->sl_wfse_state == WFSE_ACTIVE) ||
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster (void) pthread_mutex_unlock(&cur_slot->sl_mutex);
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster /* Set slot to active */
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * set up variable to pass arguments to child threads.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * Only need to set up once, as values will remain the
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster * same for each successive call.
a688bcbb4bcff5398fdd29b86f83450257dc0df4Allan Foster cur_slot->sl_wfse_args = malloc(sizeof (wfse_args_t));
(void) pthread_mutex_unlock(
return (CKR_HOST_MEMORY);
return (CKR_NO_EVENT);
if (!pkcs11_initialized) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (CKR_OK);
return (CKR_NO_EVENT);
CK_ULONG i;
if (!pkcs11_initialized) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
pulCount));
return (CKR_SLOT_ID_INVALID);
if (policyfastpath) {
mech_count = 0;
return (CKR_HOST_MEMORY);
return (CKR_HOST_MEMORY);
*pulCount = 0;
return (CKR_OK);
for (i = 0; i < tmpmech_count; i++) {
mech_count++;
return (CKR_BUFFER_TOO_SMALL);
return (CKR_OK);
if (!pkcs11_initialized) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (CKR_SLOT_ID_INVALID);
if (policyfastpath) {
return (CKR_MECHANISM_INVALID);
return (CKR_FUNCTION_FAILED);
return (rv);
if (!pkcs11_initialized) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
pLabel));
pLabel));
return (CKR_SLOT_ID_INVALID);
pLabel);
return (CKR_FUNCTION_FAILED);
return (rv);
if (!pkcs11_initialized) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (rv);
return (CKR_FUNCTION_FAILED);
return (rv);
if (!pkcs11_initialized) {
return (CKR_CRYPTOKI_NOT_INITIALIZED);
return (rv);
return (CKR_FUNCTION_FAILED);
return (rv);
if (!pkcs11_initialized) {
return (NULL);
(void) pthread_mutex_unlock(
pthread_exit(0);
pthread_exit(0);
return (NULL);
CK_SLOT_ID i;
(void) pthread_mutex_unlock(
pthread_exit(0);
pthread_exit(0);
return (NULL);