Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <dlfcn.h>
     27 #include <stdlib.h>
     28 #include <pthread.h>
     29 #include <strings.h>
     30 #include <security/cryptoki.h>
     31 #include "pkcs11Global.h"
     32 #include "pkcs11Slot.h"
     33 #include "metaGlobal.h"
     34 
     35 pkcs11_slottable_t *slottable = NULL;
     36 
     37 /*
     38  * pkcs11_slottable_initialize initizializes the global slottable.
     39  * This slottable will contain information about the plugged in
     40  * slots, including their mapped slotID.  This function should only
     41  * be called by C_Intialize.
     42  */
     43 CK_RV
     44 pkcs11_slottable_initialize() {
     45 
     46 
     47 	pkcs11_slottable_t *stmp = malloc(sizeof (pkcs11_slottable_t));
     48 
     49 	if (stmp == NULL)
     50 		return (CKR_HOST_MEMORY);
     51 
     52 	stmp->st_first = 1;
     53 	stmp->st_cur_size = 0;
     54 	stmp->st_last = 0;
     55 	stmp->st_slots = NULL;
     56 
     57 	if (pthread_mutex_init(&stmp->st_mutex, NULL) != 0) {
     58 		free(stmp);
     59 		return (CKR_FUNCTION_FAILED);
     60 	}
     61 	/* Set up for possible threads later */
     62 	stmp->st_event_slot = 0;
     63 	stmp->st_thr_count = 0;
     64 	stmp->st_wfse_active = B_FALSE;
     65 	stmp->st_blocking = B_FALSE;
     66 	stmp->st_list_signaled = B_FALSE;
     67 
     68 	(void) pthread_cond_init(&stmp->st_wait_cond, NULL);
     69 	(void) pthread_mutex_init(&stmp->st_start_mutex, NULL);
     70 	(void) pthread_cond_init(&stmp->st_start_cond, NULL);
     71 
     72 	slottable = stmp;
     73 
     74 	return (CKR_OK);
     75 
     76 }
     77 
     78 /*
     79  * pkcs11_slottable_increase should only be called from C_Initialize().
     80  * It is called after the first call to C_GetSlotList() and is used to
     81  * increase the size of the slottable, as needed, to contain the next
     82  * set of slots that C_Initialize() is currently mapping into the framework.
     83  */
     84 CK_RV
     85 pkcs11_slottable_increase(ulong_t increment) {
     86 
     87 	pkcs11_slot_t **tmpslots;
     88 	ulong_t newsize;
     89 
     90 	(void) pthread_mutex_lock(&slottable->st_mutex);
     91 
     92 	/* Add 1 to cover space for the metaslot */
     93 	newsize = slottable->st_last + increment + 1;
     94 
     95 	/* Check to see if we already have enough space */
     96 	if (slottable->st_cur_size >= newsize) {
     97 		(void) pthread_mutex_unlock(&slottable->st_mutex);
     98 		return (CKR_OK);
     99 	}
    100 
    101 	tmpslots = realloc
    102 	    (slottable->st_slots, newsize * sizeof (pkcs11_slot_t *));
    103 
    104 	if (tmpslots == NULL) {
    105 		(void) pthread_mutex_unlock(&slottable->st_mutex);
    106 		return (CKR_HOST_MEMORY);
    107 	}
    108 
    109 	slottable->st_slots = tmpslots;
    110 	slottable->st_cur_size = newsize;
    111 
    112 	(void) pthread_mutex_unlock(&slottable->st_mutex);
    113 
    114 	return (CKR_OK);
    115 }
    116 
    117 /*
    118  * pkcs11_slot_allocate should only be called from C_Initialize().
    119  * We won't know if the metaslot will be used until after all of
    120  * the other slots have been allocated.
    121  */
    122 CK_RV
    123 pkcs11_slot_allocate(CK_SLOT_ID *pslot_id) {
    124 
    125 	pkcs11_slot_t *tmpslot;
    126 
    127 	tmpslot = malloc(sizeof (pkcs11_slot_t));
    128 
    129 	if (tmpslot == NULL)
    130 		return (CKR_HOST_MEMORY);
    131 
    132 	bzero(tmpslot, sizeof (pkcs11_slot_t));
    133 
    134 	tmpslot->sl_wfse_state = WFSE_CLEAR;
    135 	tmpslot->sl_enabledpol = B_FALSE;
    136 	tmpslot->sl_no_wfse = B_FALSE;
    137 
    138 	/* Initialize this slot's mutex */
    139 	if (pthread_mutex_init(&tmpslot->sl_mutex, NULL) != 0) {
    140 		free(tmpslot);
    141 		return (CKR_FUNCTION_FAILED);
    142 	}
    143 
    144 	(void) pthread_mutex_lock(&slottable->st_mutex);
    145 
    146 	slottable->st_last++;
    147 
    148 	*pslot_id = slottable->st_last;
    149 
    150 	slottable->st_slots[*pslot_id] = tmpslot;
    151 
    152 	(void) pthread_mutex_unlock(&slottable->st_mutex);
    153 
    154 	return (CKR_OK);
    155 
    156 }
    157 
    158 /*
    159  * pkcs11_slottable_delete should only be called by C_Finalize(),
    160  * or by C_Initialize() in error conditions.
    161  */
    162 CK_RV
    163 pkcs11_slottable_delete() {
    164 
    165 	ulong_t i;
    166 	uint32_t prov_id;
    167 	int32_t last_prov_id = -1;
    168 	pkcs11_slot_t *cur_slot;
    169 
    170 	(void) pthread_mutex_lock(&slottable->st_mutex);
    171 
    172 	for (i = slottable->st_first; i <= slottable->st_last; i++) {
    173 
    174 		if (slottable->st_slots[i] != NULL) {
    175 
    176 			cur_slot = slottable->st_slots[i];
    177 			prov_id = cur_slot->sl_prov_id;
    178 
    179 			(void) pthread_mutex_lock(&cur_slot->sl_mutex);
    180 
    181 			/*
    182 			 * For the first slot from this provider, do
    183 			 * extra cleanup.
    184 			 */
    185 			if (prov_id != last_prov_id) {
    186 
    187 				if (cur_slot->sl_wfse_state == WFSE_ACTIVE) {
    188 					(void) pthread_cancel
    189 					    (cur_slot->sl_tid);
    190 				}
    191 
    192 				/*
    193 				 * Only call C_Finalize of plug-in if we
    194 				 * get here from an explicit C_Finalize
    195 				 * call from an application.  Otherwise,
    196 				 * there is a risk that the application may
    197 				 * have directly dlopened this provider and
    198 				 * we could interrupt their work.  Plug-ins
    199 				 * should have their own _fini function to
    200 				 * clean up when they are no longer referenced.
    201 				 */
    202 				if ((cur_slot->sl_func_list != NULL) &&
    203 				    (!fini_called)) {
    204 					(void) cur_slot->
    205 					    sl_func_list->C_Finalize(NULL);
    206 				}
    207 				(void) dlclose(cur_slot->sl_dldesc);
    208 
    209 				/*
    210 				 * Each provider maintains one disabled
    211 				 * mechanism list for each of its slots to use.
    212 				 */
    213 				if (cur_slot->sl_pol_mechs != NULL)
    214 					free(cur_slot->sl_pol_mechs);
    215 			}
    216 
    217 			if (cur_slot->sl_wfse_args != NULL) {
    218 				free(cur_slot->sl_wfse_args);
    219 			}
    220 
    221 			(void) pthread_mutex_unlock(&cur_slot->sl_mutex);
    222 
    223 			/*
    224 			 * Cleanup the session list.  This must
    225 			 * happen after the mutext is unlocked
    226 			 * because session_delete tries to lock it
    227 			 * again.
    228 			 */
    229 			pkcs11_sessionlist_delete(cur_slot);
    230 
    231 			(void) pthread_mutex_destroy(&cur_slot->sl_mutex);
    232 
    233 			free(cur_slot);
    234 			cur_slot = NULL;
    235 			last_prov_id = prov_id;
    236 		}
    237 	}
    238 
    239 	(void) pthread_cond_destroy(&slottable->st_wait_cond);
    240 	(void) pthread_mutex_destroy(&slottable->st_start_mutex);
    241 	(void) pthread_cond_destroy(&slottable->st_start_cond);
    242 
    243 	free(slottable->st_slots);
    244 
    245 	(void) pthread_mutex_unlock(&slottable->st_mutex);
    246 
    247 	(void) pthread_mutex_destroy(&slottable->st_mutex);
    248 
    249 	free(slottable);
    250 
    251 	slottable = NULL;
    252 
    253 	return (CKR_OK);
    254 
    255 }
    256 
    257 /*
    258  * pkcs11_is_valid_slot verifies that the slot ID passed to the
    259  * framework is valid.
    260  */
    261 CK_RV
    262 pkcs11_is_valid_slot(CK_SLOT_ID slot_id) {
    263 
    264 	if ((slot_id < slottable->st_first) ||
    265 	    (slot_id > slottable->st_last)) {
    266 		return (CKR_SLOT_ID_INVALID);
    267 	} else if (slottable->st_slots[slot_id] != NULL) {
    268 		return (CKR_OK);
    269 	} else {
    270 		return (CKR_SLOT_ID_INVALID);
    271 	}
    272 }
    273 
    274 
    275 /*
    276  * pkcs11_validate_and_convert_slotid verifies whether the slot ID
    277  * passed to the framework is valid, and convert it to the
    278  * true slot ID maintained in the framework data structures
    279  * accordingly.
    280  *
    281  * This is necessary because when metaslot is enabled, the slot
    282  * providing persistent object storage is "hidden".
    283  *
    284  * The real ID is returned in the "real_slot_id" argument regardless conversion
    285  * is done or not.
    286  */
    287 CK_RV
    288 pkcs11_validate_and_convert_slotid(CK_SLOT_ID slot_id,
    289     CK_SLOT_ID *real_slot_id) {
    290 
    291 	if (!metaslot_enabled) {
    292 		*real_slot_id = slot_id;
    293 	} else {
    294 		/* need to do conversion */
    295 		if (slot_id >= metaslot_keystore_slotid) {
    296 			*real_slot_id = slot_id + 1;
    297 		} else {
    298 			*real_slot_id = slot_id;
    299 		}
    300 	}
    301 	return (pkcs11_is_valid_slot(*real_slot_id));
    302 }
    303