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