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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 #include <dlfcn.h> 30 #include <stdlib.h> 31 #include <pthread.h> 32 #include <strings.h> 33 #include <security/cryptoki.h> 34 #include "pkcs11Global.h" 35 #include "pkcs11Slot.h" 36 #include "metaGlobal.h" 37 38 pkcs11_slottable_t *slottable = NULL; 39 40 /* 41 * pkcs11_slottable_initialize initizializes the global slottable. 42 * This slottable will contain information about the plugged in 43 * slots, including their mapped slotID. This function should only 44 * be called by C_Intialize. 45 */ 46 CK_RV 47 pkcs11_slottable_initialize() { 48 49 50 pkcs11_slottable_t *stmp = malloc(sizeof (pkcs11_slottable_t)); 51 52 if (stmp == NULL) 53 return (CKR_HOST_MEMORY); 54 55 stmp->st_first = 1; 56 stmp->st_cur_size = 0; 57 stmp->st_last = 0; 58 stmp->st_slots = NULL; 59 60 if (pthread_mutex_init(&stmp->st_mutex, NULL) != 0) { 61 free(stmp); 62 return (CKR_FUNCTION_FAILED); 63 } 64 /* Set up for possible threads later */ 65 stmp->st_event_slot = 0; 66 stmp->st_thr_count = 0; 67 stmp->st_wfse_active = B_FALSE; 68 stmp->st_blocking = B_FALSE; 69 stmp->st_list_signaled = B_FALSE; 70 71 (void) pthread_cond_init(&stmp->st_wait_cond, NULL); 72 (void) pthread_mutex_init(&stmp->st_start_mutex, NULL); 73 (void) pthread_cond_init(&stmp->st_start_cond, NULL); 74 75 slottable = stmp; 76 77 return (CKR_OK); 78 79 } 80 81 /* 82 * pkcs11_slottable_increase should only be called from C_Initialize(). 83 * It is called after the first call to C_GetSlotList() and is used to 84 * increase the size of the slottable, as needed, to contain the next 85 * set of slots that C_Initialize() is currently mapping into the framework. 86 */ 87 CK_RV 88 pkcs11_slottable_increase(ulong_t increment) { 89 90 pkcs11_slot_t **tmpslots; 91 ulong_t newsize; 92 93 (void) pthread_mutex_lock(&slottable->st_mutex); 94 95 /* Add 1 to cover space for the metaslot */ 96 newsize = slottable->st_last + increment + 1; 97 98 /* Check to see if we already have enough space */ 99 if (slottable->st_cur_size >= newsize) { 100 (void) pthread_mutex_unlock(&slottable->st_mutex); 101 return (CKR_OK); 102 } 103 104 tmpslots = realloc 105 (slottable->st_slots, newsize * sizeof (pkcs11_slot_t *)); 106 107 if (tmpslots == NULL) { 108 (void) pthread_mutex_unlock(&slottable->st_mutex); 109 return (CKR_HOST_MEMORY); 110 } 111 112 slottable->st_slots = tmpslots; 113 slottable->st_cur_size = newsize; 114 115 (void) pthread_mutex_unlock(&slottable->st_mutex); 116 117 return (CKR_OK); 118 } 119 120 /* 121 * pkcs11_slot_allocate should only be called from C_Initialize(). 122 * We won't know if the metaslot will be used until after all of 123 * the other slots have been allocated. 124 */ 125 CK_RV 126 pkcs11_slot_allocate(CK_SLOT_ID *pslot_id) { 127 128 pkcs11_slot_t *tmpslot; 129 130 tmpslot = malloc(sizeof (pkcs11_slot_t)); 131 132 if (tmpslot == NULL) 133 return (CKR_HOST_MEMORY); 134 135 bzero(tmpslot, sizeof (pkcs11_slot_t)); 136 137 tmpslot->sl_wfse_state = WFSE_CLEAR; 138 tmpslot->sl_enabledpol = B_FALSE; 139 tmpslot->sl_no_wfse = B_FALSE; 140 141 /* Initialize this slot's mutex */ 142 if (pthread_mutex_init(&tmpslot->sl_mutex, NULL) != 0) { 143 free(tmpslot); 144 return (CKR_FUNCTION_FAILED); 145 } 146 147 (void) pthread_mutex_lock(&slottable->st_mutex); 148 149 slottable->st_last++; 150 151 *pslot_id = slottable->st_last; 152 153 slottable->st_slots[*pslot_id] = tmpslot; 154 155 (void) pthread_mutex_unlock(&slottable->st_mutex); 156 157 return (CKR_OK); 158 159 } 160 161 /* 162 * pkcs11_slottable_delete should only be called by C_Finalize(), 163 * or by C_Initialize() in error conditions. 164 */ 165 CK_RV 166 pkcs11_slottable_delete() { 167 168 ulong_t i; 169 uint32_t prov_id; 170 int32_t last_prov_id = -1; 171 pkcs11_slot_t *cur_slot; 172 173 (void) pthread_mutex_lock(&slottable->st_mutex); 174 175 for (i = slottable->st_first; i <= slottable->st_last; i++) { 176 177 if (slottable->st_slots[i] != NULL) { 178 179 cur_slot = slottable->st_slots[i]; 180 prov_id = cur_slot->sl_prov_id; 181 182 (void) pthread_mutex_lock(&cur_slot->sl_mutex); 183 184 /* 185 * For the first slot from this provider, do 186 * extra cleanup. 187 */ 188 if (prov_id != last_prov_id) { 189 190 if (cur_slot->sl_wfse_state == WFSE_ACTIVE) { 191 (void) pthread_cancel 192 (cur_slot->sl_tid); 193 } 194 195 /* 196 * Only call C_Finalize of plug-in if we 197 * get here from an explicit C_Finalize 198 * call from an application. Otherwise, 199 * there is a risk that the application may 200 * have directly dlopened this provider and 201 * we could interrupt their work. Plug-ins 202 * should have their own _fini function to 203 * clean up when they are no longer referenced. 204 */ 205 if ((cur_slot->sl_func_list != NULL) && 206 (!fini_called)) { 207 (void) cur_slot-> 208 sl_func_list->C_Finalize(NULL); 209 } 210 (void) dlclose(cur_slot->sl_dldesc); 211 } 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