xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelSlottable.c (revision 50981ffc7e4c5048d14890df805afee6ec113991)
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 2007 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 
26 #pragma ident	"%Z%%M%	%I%	%E% SMI"
27 
28 #include <errno.h>
29 #include <security/cryptoki.h>
30 #include <sys/crypto/ioctl.h>
31 #include "kernelGlobal.h"
32 #include "kernelSlot.h"
33 
34 CK_ULONG	slot_count = 0;
35 kernel_slot_t	**slot_table;
36 
37 static CK_RV
38 kernel_get_slot_number()
39 {
40 	CK_RV rv;
41 	crypto_get_provider_list_t *pl;
42 	int r;
43 
44 	pl = malloc(sizeof (crypto_get_provider_list_t));
45 	if (pl == NULL)
46 		return (CKR_HOST_MEMORY);
47 
48 	pl->pl_count = 0;
49 	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) {
50 		if (errno != EINTR)
51 			break;
52 	}
53 	if (r < 0) {
54 		rv = CKR_FUNCTION_FAILED;
55 	} else {
56 		if (pl->pl_return_value != CRYPTO_SUCCESS) {
57 			rv = crypto2pkcs11_error_number(pl->pl_return_value);
58 		} else {
59 			rv = CKR_OK;
60 		}
61 	}
62 
63 	if (rv == CKR_OK) {
64 		slot_count = pl->pl_count;
65 	}
66 
67 	(void) free(pl);
68 	return (rv);
69 }
70 
71 /*
72  * This function will be used by metaslot to get the kernel
73  * provider's threshold value for the supported mechanisms.
74  */
75 void
76 _SUNW_GetThreshold(void *thresholdp)
77 {
78 
79 	cipher_mechs_threshold_t *tp = (cipher_mechs_threshold_t *)thresholdp;
80 	kernel_slot_t *pslot;
81 	int i;
82 
83 	/*
84 	 * We alway use the 1st slot in the kernel to
85 	 * get the threshold because all the kernel
86 	 * slots will have the same threshold value
87 	 * with the same mechanism.
88 	 */
89 	pslot = slot_table[0];
90 
91 	for (i = 0; i < pslot->total_threshold_count; i++) {
92 		tp[i].mech_type =
93 		    pslot->sl_mechs_threshold[i].mech_type;
94 		tp[i].mech_threshold =
95 		    pslot->sl_mechs_threshold[i].mech_threshold;
96 	}
97 }
98 
99 /*
100  * To retrieve the crypto_function_list structure with boolean entries
101  * indicating which functions are supported by the hardware provider which
102  * is specified by the slot ID.
103  */
104 static CK_RV
105 kernel_get_func_list(kernel_slot_t *pslot)
106 {
107 	CK_RV rv = CKR_OK;
108 	crypto_get_function_list_t  fl;
109 	int r;
110 	int i;
111 
112 	fl.fl_provider_id = pslot->sl_provider_id;
113 
114 	while ((r = ioctl(kernel_fd, CRYPTO_GET_FUNCTION_LIST, &fl)) < 0) {
115 		if (errno != EINTR)
116 			break;
117 	}
118 	if (r < 0) {
119 		rv = CKR_FUNCTION_FAILED;
120 	} else {
121 		if (fl.fl_return_value == 0) {
122 			rv = CKR_OK;
123 		} else {
124 			rv = crypto2pkcs11_error_number(fl.fl_return_value);
125 		}
126 	}
127 
128 	if (rv != CKR_OK) {
129 		return (rv);
130 	}
131 
132 	pslot->sl_func_list.fl_digest_init = fl.fl_list.fl_digest_init;
133 	pslot->sl_func_list.fl_digest = fl.fl_list.fl_digest;
134 	pslot->sl_func_list.fl_digest_update = fl.fl_list.fl_digest_update;
135 	pslot->sl_func_list.fl_digest_key = fl.fl_list.fl_digest_key;
136 	pslot->sl_func_list.fl_digest_final = fl.fl_list.fl_digest_final;
137 	pslot->sl_func_list.fl_encrypt_init = fl.fl_list.fl_encrypt_init;
138 	pslot->sl_func_list.fl_encrypt = fl.fl_list.fl_encrypt;
139 	pslot->sl_func_list.fl_encrypt_update = fl.fl_list.fl_encrypt_update;
140 	pslot->sl_func_list.fl_encrypt_final = fl.fl_list.fl_encrypt_final;
141 	pslot->sl_func_list.fl_decrypt_init = fl.fl_list.fl_decrypt_init;
142 	pslot->sl_func_list.fl_decrypt = fl.fl_list.fl_decrypt;
143 	pslot->sl_func_list.fl_decrypt_update = fl.fl_list.fl_decrypt_update;
144 	pslot->sl_func_list.fl_decrypt_final = fl.fl_list.fl_decrypt_final;
145 	pslot->sl_func_list.fl_mac_init = fl.fl_list.fl_mac_init;
146 	pslot->sl_func_list.fl_mac = fl.fl_list.fl_mac;
147 	pslot->sl_func_list.fl_mac_update = fl.fl_list.fl_mac_update;
148 	pslot->sl_func_list.fl_mac_final = fl.fl_list.fl_mac_final;
149 	pslot->sl_func_list.fl_sign_init = fl.fl_list.fl_sign_init;
150 	pslot->sl_func_list.fl_sign = fl.fl_list.fl_sign;
151 	pslot->sl_func_list.fl_sign_update = fl.fl_list.fl_sign_update;
152 	pslot->sl_func_list.fl_sign_final = fl.fl_list.fl_sign_final;
153 	pslot->sl_func_list.fl_sign_recover_init =
154 	    fl.fl_list.fl_sign_recover_init;
155 	pslot->sl_func_list.fl_sign_recover = fl.fl_list.fl_sign_recover;
156 	pslot->sl_func_list.fl_digest_encrypt_update =
157 	    fl.fl_list.fl_digest_encrypt_update;
158 	pslot->sl_func_list.fl_decrypt_digest_update =
159 	    fl.fl_list.fl_decrypt_digest_update;
160 	pslot->sl_func_list.fl_sign_encrypt_update =
161 	    fl.fl_list.fl_sign_encrypt_update;
162 	pslot->sl_func_list.fl_decrypt_verify_update =
163 	    fl.fl_list.fl_decrypt_verify_update;
164 	pslot->sl_func_list.fl_seed_random = fl.fl_list.fl_seed_random;
165 	pslot->sl_func_list.fl_generate_random = fl.fl_list.fl_generate_random;
166 	pslot->sl_func_list.fl_session_open = fl.fl_list.fl_session_open;
167 	pslot->sl_func_list.fl_session_close = fl.fl_list.fl_session_close;
168 	pslot->sl_func_list.fl_session_login = fl.fl_list.fl_session_login;
169 	pslot->sl_func_list.fl_session_logout = fl.fl_list.fl_session_logout;
170 	pslot->sl_func_list.fl_object_create = fl.fl_list.fl_object_create;
171 	pslot->sl_func_list.fl_object_copy = fl.fl_list.fl_object_copy;
172 	pslot->sl_func_list.fl_object_destroy = fl.fl_list.fl_object_destroy;
173 	pslot->sl_func_list.fl_object_get_size = fl.fl_list.fl_object_get_size;
174 	pslot->sl_func_list.fl_object_get_attribute_value =
175 	    fl.fl_list.fl_object_get_attribute_value;
176 	pslot->sl_func_list.fl_object_set_attribute_value =
177 	    fl.fl_list.fl_object_set_attribute_value;
178 	pslot->sl_func_list.fl_object_find_init =
179 	    fl.fl_list.fl_object_find_init;
180 	pslot->sl_func_list.fl_object_find = fl.fl_list.fl_object_find;
181 	pslot->sl_func_list.fl_object_find_final =
182 	    fl.fl_list.fl_object_find_final;
183 	pslot->sl_func_list.fl_key_generate = fl.fl_list.fl_key_generate;
184 	pslot->sl_func_list.fl_key_generate_pair =
185 	    fl.fl_list.fl_key_generate_pair;
186 	pslot->sl_func_list.fl_key_wrap = fl.fl_list.fl_key_wrap;
187 	pslot->sl_func_list.fl_key_unwrap = fl.fl_list.fl_key_unwrap;
188 	pslot->sl_func_list.fl_init_token = fl.fl_list.fl_init_token;
189 	pslot->sl_func_list.fl_init_pin = fl.fl_list.fl_init_pin;
190 	pslot->sl_func_list.fl_set_pin = fl.fl_list.fl_set_pin;
191 
192 	pslot->sl_flags = 0;
193 	if (fl.fl_list.prov_is_limited) {
194 		pslot->sl_flags = CRYPTO_LIMITED_HASH_SUPPORT;
195 		pslot->sl_threshold = fl.fl_list.prov_hash_threshold;
196 		pslot->sl_max_inlen = fl.fl_list.prov_hash_limit;
197 	}
198 
199 	pslot->total_threshold_count = fl.fl_list.total_threshold_count;
200 
201 	for (i = 0; i < pslot->total_threshold_count; i++) {
202 		pslot->sl_mechs_threshold[i].mech_type =
203 		    fl.fl_list.fl_threshold[i].mech_type;
204 		pslot->sl_mechs_threshold[i].mech_threshold =
205 		    fl.fl_list.fl_threshold[i].mech_threshold;
206 	}
207 
208 	return (CKR_OK);
209 }
210 
211 /*
212  * Initialize the slot table.
213  *
214  * This function is called from C_Initialize() only.  Since C_Initialize()
215  * holds the global mutex lock, there is no need to acquire another lock
216  * in this routine to protect the slot table.
217  */
218 CK_RV
219 kernel_slottable_init()
220 {
221 	int i, cur_slot_num = 0;
222 	CK_RV rv = CKR_OK;
223 	crypto_get_provider_list_t *pl = NULL;
224 	int r;
225 
226 	/*
227 	 * Find out how many slots are presented from kernel hardware
228 	 * providers. If there is no slot presented, just return.
229 	 */
230 	rv = kernel_get_slot_number();
231 	if (rv != CKR_OK || slot_count == 0) {
232 		return (rv);
233 	}
234 
235 	/* Allocate space for the slot table */
236 	slot_table = malloc(sizeof (kernel_slot_t *) * slot_count);
237 	if (slot_table == NULL) {
238 		return (CKR_HOST_MEMORY);
239 	}
240 
241 	/* For each slot, allocate space and initialize the slot's mutex. */
242 	for (i = 0; i < slot_count; i++) {
243 		slot_table[i] = malloc(sizeof (kernel_slot_t));
244 		if (slot_table[i] == NULL) {
245 			rv = CKR_HOST_MEMORY;
246 			goto failed;
247 		}
248 
249 		slot_table[i]->sl_sess_list = NULL;
250 		slot_table[i]->sl_tobj_list = NULL;
251 		slot_table[i]->sl_state = CKU_PUBLIC;
252 
253 		/* Initialize this slot's mutex */
254 		if (pthread_mutex_init(&slot_table[i]->sl_mutex, NULL) != 0) {
255 			rv = CKR_FUNCTION_FAILED;
256 			(void) free(slot_table[i]);
257 			goto failed;
258 		}
259 
260 		cur_slot_num = i;
261 	}
262 
263 	/*
264 	 * Get the provider ID for each slot from kernel and save it in the
265 	 * slot table.
266 	 */
267 	pl = malloc(slot_count * sizeof (crypto_get_provider_list_t));
268 	if (pl == NULL) {
269 		rv = CKR_HOST_MEMORY;
270 		goto failed;
271 	}
272 
273 	pl->pl_count = slot_count;
274 	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) {
275 		if (errno != EINTR)
276 			break;
277 	}
278 	if (r < 0) {
279 		rv = CKR_FUNCTION_FAILED;
280 		goto failed;
281 	} else {
282 		if (pl->pl_return_value != CRYPTO_SUCCESS) {
283 			rv = crypto2pkcs11_error_number(pl->pl_return_value);
284 			goto failed;
285 		} else {
286 			rv = CKR_OK;
287 		}
288 	}
289 
290 	for (i = 0; i < slot_count; i++) {
291 		slot_table[i]->sl_provider_id = pl->pl_list[i].pe_provider_id;
292 	}
293 
294 	/*
295 	 * Get the function list for each slot from kernel and save it in
296 	 * the slot table.
297 	 */
298 	for (i = 0; i < slot_count; i++) {
299 		rv = kernel_get_func_list(slot_table[i]);
300 		if (rv != CKR_OK) {
301 			goto failed;
302 		}
303 	}
304 
305 	(void) free(pl);
306 	return (CKR_OK);
307 
308 failed:
309 	for (i = 0; i < cur_slot_num; i++) {
310 		(void) pthread_mutex_destroy(&slot_table[i]->sl_mutex);
311 		(void) free(slot_table[i]);
312 	}
313 
314 	(void) free(slot_table);
315 	(void) free(pl);
316 	return (rv);
317 }
318