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