xref: /illumos-gate/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelSlottable.c (revision 24472db64c485d6744c0321b7581cf066556cf2d)
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  * To retrieve the crypto_function_list structure with boolean entries
73  * indicating which functions are supported by the hardware provider which
74  * is specified by the slot ID.
75  */
76 static CK_RV
77 kernel_get_func_list(kernel_slot_t *pslot)
78 {
79 	CK_RV rv = CKR_OK;
80 	crypto_get_function_list_t  fl;
81 	int r;
82 
83 	fl.fl_provider_id = pslot->sl_provider_id;
84 
85 	while ((r = ioctl(kernel_fd, CRYPTO_GET_FUNCTION_LIST, &fl)) < 0) {
86 		if (errno != EINTR)
87 			break;
88 	}
89 	if (r < 0) {
90 		rv = CKR_FUNCTION_FAILED;
91 	} else {
92 		if (fl.fl_return_value == 0) {
93 			rv = CKR_OK;
94 		} else {
95 			rv = crypto2pkcs11_error_number(fl.fl_return_value);
96 		}
97 	}
98 
99 	if (rv != CKR_OK) {
100 		return (rv);
101 	}
102 
103 	pslot->sl_func_list.fl_digest_init = fl.fl_list.fl_digest_init;
104 	pslot->sl_func_list.fl_digest = fl.fl_list.fl_digest;
105 	pslot->sl_func_list.fl_digest_update = fl.fl_list.fl_digest_update;
106 	pslot->sl_func_list.fl_digest_key = fl.fl_list.fl_digest_key;
107 	pslot->sl_func_list.fl_digest_final = fl.fl_list.fl_digest_final;
108 	pslot->sl_func_list.fl_encrypt_init = fl.fl_list.fl_encrypt_init;
109 	pslot->sl_func_list.fl_encrypt = fl.fl_list.fl_encrypt;
110 	pslot->sl_func_list.fl_encrypt_update = fl.fl_list.fl_encrypt_update;
111 	pslot->sl_func_list.fl_encrypt_final = fl.fl_list.fl_encrypt_final;
112 	pslot->sl_func_list.fl_decrypt_init = fl.fl_list.fl_decrypt_init;
113 	pslot->sl_func_list.fl_decrypt = fl.fl_list.fl_decrypt;
114 	pslot->sl_func_list.fl_decrypt_update = fl.fl_list.fl_decrypt_update;
115 	pslot->sl_func_list.fl_decrypt_final = fl.fl_list.fl_decrypt_final;
116 	pslot->sl_func_list.fl_mac_init = fl.fl_list.fl_mac_init;
117 	pslot->sl_func_list.fl_mac = fl.fl_list.fl_mac;
118 	pslot->sl_func_list.fl_mac_update = fl.fl_list.fl_mac_update;
119 	pslot->sl_func_list.fl_mac_final = fl.fl_list.fl_mac_final;
120 	pslot->sl_func_list.fl_sign_init = fl.fl_list.fl_sign_init;
121 	pslot->sl_func_list.fl_sign = fl.fl_list.fl_sign;
122 	pslot->sl_func_list.fl_sign_update = fl.fl_list.fl_sign_update;
123 	pslot->sl_func_list.fl_sign_final = fl.fl_list.fl_sign_final;
124 	pslot->sl_func_list.fl_sign_recover_init =
125 	    fl.fl_list.fl_sign_recover_init;
126 	pslot->sl_func_list.fl_sign_recover = fl.fl_list.fl_sign_recover;
127 	pslot->sl_func_list.fl_digest_encrypt_update =
128 	    fl.fl_list.fl_digest_encrypt_update;
129 	pslot->sl_func_list.fl_decrypt_digest_update =
130 	    fl.fl_list.fl_decrypt_digest_update;
131 	pslot->sl_func_list.fl_sign_encrypt_update =
132 	    fl.fl_list.fl_sign_encrypt_update;
133 	pslot->sl_func_list.fl_decrypt_verify_update =
134 	    fl.fl_list.fl_decrypt_verify_update;
135 	pslot->sl_func_list.fl_seed_random = fl.fl_list.fl_seed_random;
136 	pslot->sl_func_list.fl_generate_random = fl.fl_list.fl_generate_random;
137 	pslot->sl_func_list.fl_session_open = fl.fl_list.fl_session_open;
138 	pslot->sl_func_list.fl_session_close = fl.fl_list.fl_session_close;
139 	pslot->sl_func_list.fl_session_login = fl.fl_list.fl_session_login;
140 	pslot->sl_func_list.fl_session_logout = fl.fl_list.fl_session_logout;
141 	pslot->sl_func_list.fl_object_create = fl.fl_list.fl_object_create;
142 	pslot->sl_func_list.fl_object_copy = fl.fl_list.fl_object_copy;
143 	pslot->sl_func_list.fl_object_destroy = fl.fl_list.fl_object_destroy;
144 	pslot->sl_func_list.fl_object_get_size = fl.fl_list.fl_object_get_size;
145 	pslot->sl_func_list.fl_object_get_attribute_value =
146 	    fl.fl_list.fl_object_get_attribute_value;
147 	pslot->sl_func_list.fl_object_set_attribute_value =
148 	    fl.fl_list.fl_object_set_attribute_value;
149 	pslot->sl_func_list.fl_object_find_init =
150 	    fl.fl_list.fl_object_find_init;
151 	pslot->sl_func_list.fl_object_find = fl.fl_list.fl_object_find;
152 	pslot->sl_func_list.fl_object_find_final =
153 	    fl.fl_list.fl_object_find_final;
154 	pslot->sl_func_list.fl_key_generate = fl.fl_list.fl_key_generate;
155 	pslot->sl_func_list.fl_key_generate_pair =
156 	    fl.fl_list.fl_key_generate_pair;
157 	pslot->sl_func_list.fl_key_wrap = fl.fl_list.fl_key_wrap;
158 	pslot->sl_func_list.fl_key_unwrap = fl.fl_list.fl_key_unwrap;
159 	pslot->sl_func_list.fl_init_token = fl.fl_list.fl_init_token;
160 	pslot->sl_func_list.fl_init_pin = fl.fl_list.fl_init_pin;
161 	pslot->sl_func_list.fl_set_pin = fl.fl_list.fl_set_pin;
162 
163 	pslot->sl_flags = 0;
164 	if (fl.fl_list.prov_is_limited) {
165 		pslot->sl_flags = CRYPTO_LIMITED_HASH_SUPPORT;
166 		pslot->sl_threshold = fl.fl_list.prov_hash_threshold;
167 		pslot->sl_max_inlen = fl.fl_list.prov_hash_limit;
168 	}
169 
170 	return (CKR_OK);
171 }
172 
173 /*
174  * Initialize the slot table.
175  *
176  * This function is called from C_Initialize() only.  Since C_Initialize()
177  * holds the global mutex lock, there is no need to acquire another lock
178  * in this routine to protect the slot table.
179  */
180 CK_RV
181 kernel_slottable_init()
182 {
183 	int i, cur_slot_num = 0;
184 	CK_RV rv = CKR_OK;
185 	crypto_get_provider_list_t *pl = NULL;
186 	int r;
187 
188 	/*
189 	 * Find out how many slots are presented from kernel hardware
190 	 * providers. If there is no slot presented, just return.
191 	 */
192 	rv = kernel_get_slot_number();
193 	if (rv != CKR_OK || slot_count == 0) {
194 		return (rv);
195 	}
196 
197 	/* Allocate space for the slot table */
198 	slot_table = malloc(sizeof (kernel_slot_t *) * slot_count);
199 	if (slot_table == NULL) {
200 		return (CKR_HOST_MEMORY);
201 	}
202 
203 	/* For each slot, allocate space and initialize the slot's mutex. */
204 	for (i = 0; i < slot_count; i++) {
205 		slot_table[i] = malloc(sizeof (kernel_slot_t));
206 		if (slot_table[i] == NULL) {
207 			rv = CKR_HOST_MEMORY;
208 			goto failed;
209 		}
210 
211 		slot_table[i]->sl_sess_list = NULL;
212 		slot_table[i]->sl_tobj_list = NULL;
213 		slot_table[i]->sl_state = CKU_PUBLIC;
214 
215 		/* Initialize this slot's mutex */
216 		if (pthread_mutex_init(&slot_table[i]->sl_mutex, NULL) != 0) {
217 			rv = CKR_FUNCTION_FAILED;
218 			(void) free(slot_table[i]);
219 			goto failed;
220 		}
221 
222 		cur_slot_num = i;
223 	}
224 
225 	/*
226 	 * Get the provider ID for each slot from kernel and save it in the
227 	 * slot table.
228 	 */
229 	pl = malloc(slot_count * sizeof (crypto_get_provider_list_t));
230 	if (pl == NULL) {
231 		rv = CKR_HOST_MEMORY;
232 		goto failed;
233 	}
234 
235 	pl->pl_count = slot_count;
236 	while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_LIST, pl)) < 0) {
237 		if (errno != EINTR)
238 			break;
239 	}
240 	if (r < 0) {
241 		rv = CKR_FUNCTION_FAILED;
242 		goto failed;
243 	} else {
244 		if (pl->pl_return_value != CRYPTO_SUCCESS) {
245 			rv = crypto2pkcs11_error_number(pl->pl_return_value);
246 			goto failed;
247 		} else {
248 			rv = CKR_OK;
249 		}
250 	}
251 
252 	for (i = 0; i < slot_count; i++) {
253 		slot_table[i]->sl_provider_id = pl->pl_list[i].pe_provider_id;
254 	}
255 
256 	/*
257 	 * Get the function list for each slot from kernel and save it in
258 	 * the slot table.
259 	 */
260 	for (i = 0; i < slot_count; i++) {
261 		rv = kernel_get_func_list(slot_table[i]);
262 		if (rv != CKR_OK) {
263 			goto failed;
264 		}
265 	}
266 
267 	(void) free(pl);
268 	return (CKR_OK);
269 
270 failed:
271 	for (i = 0; i < cur_slot_num; i++) {
272 		(void) pthread_mutex_destroy(&slot_table[i]->sl_mutex);
273 		(void) free(slot_table[i]);
274 	}
275 
276 	(void) free(slot_table);
277 	(void) free(pl);
278 	return (rv);
279 }
280