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 /* 23 * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved. 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 208 /* metaslot won't have a sl_dldesc! */ 209 if (cur_slot->sl_dldesc != NULL) { 210 (void) dlclose(cur_slot->sl_dldesc); 211 } 212 213 /* 214 * Each provider maintains one disabled 215 * mechanism list for each of its slots to use. 216 */ 217 if (cur_slot->sl_pol_mechs != NULL) 218 free(cur_slot->sl_pol_mechs); 219 } 220 221 if (cur_slot->sl_wfse_args != NULL) { 222 free(cur_slot->sl_wfse_args); 223 } 224 225 (void) pthread_mutex_unlock(&cur_slot->sl_mutex); 226 227 /* 228 * Cleanup the session list. This must 229 * happen after the mutext is unlocked 230 * because session_delete tries to lock it 231 * again. 232 */ 233 pkcs11_sessionlist_delete(cur_slot); 234 235 (void) pthread_mutex_destroy(&cur_slot->sl_mutex); 236 237 free(cur_slot); 238 cur_slot = NULL; 239 last_prov_id = prov_id; 240 } 241 } 242 243 (void) pthread_cond_destroy(&slottable->st_wait_cond); 244 (void) pthread_mutex_destroy(&slottable->st_start_mutex); 245 (void) pthread_cond_destroy(&slottable->st_start_cond); 246 247 free(slottable->st_slots); 248 249 (void) pthread_mutex_unlock(&slottable->st_mutex); 250 251 (void) pthread_mutex_destroy(&slottable->st_mutex); 252 253 free(slottable); 254 255 slottable = NULL; 256 257 return (CKR_OK); 258 259 } 260 261 /* 262 * pkcs11_is_valid_slot verifies that the slot ID passed to the 263 * framework is valid. 264 */ 265 CK_RV 266 pkcs11_is_valid_slot(CK_SLOT_ID slot_id) { 267 268 if ((slot_id < slottable->st_first) || 269 (slot_id > slottable->st_last)) { 270 return (CKR_SLOT_ID_INVALID); 271 } else if (slottable->st_slots[slot_id] != NULL) { 272 return (CKR_OK); 273 } else { 274 return (CKR_SLOT_ID_INVALID); 275 } 276 } 277 278 279 /* 280 * pkcs11_validate_and_convert_slotid verifies whether the slot ID 281 * passed to the framework is valid, and convert it to the 282 * true slot ID maintained in the framework data structures 283 * accordingly. 284 * 285 * This is necessary because when metaslot is enabled, the slot 286 * providing persistent object storage is "hidden". 287 * 288 * The real ID is returned in the "real_slot_id" argument regardless conversion 289 * is done or not. 290 */ 291 CK_RV 292 pkcs11_validate_and_convert_slotid(CK_SLOT_ID slot_id, 293 CK_SLOT_ID *real_slot_id) { 294 295 if (!metaslot_enabled) { 296 *real_slot_id = slot_id; 297 } else { 298 /* need to do conversion */ 299 if (slot_id >= metaslot_keystore_slotid) { 300 *real_slot_id = slot_id + 1; 301 } else { 302 *real_slot_id = slot_id; 303 } 304 } 305 return (pkcs11_is_valid_slot(*real_slot_id)); 306 } 307