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