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
pkcs11_slottable_initialize()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
pkcs11_slottable_increase(ulong_t increment)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
pkcs11_slot_allocate(CK_SLOT_ID * pslot_id)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
pkcs11_slottable_delete()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
pkcs11_is_valid_slot(CK_SLOT_ID slot_id)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
pkcs11_validate_and_convert_slotid(CK_SLOT_ID slot_id,CK_SLOT_ID * real_slot_id)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