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 <stdlib.h>
30 #include <strings.h>
31 #include <security/cryptoki.h>
32 #include <cryptoutil.h>
33 #include <errno.h>
34 #include <sys/crypto/api.h>
35 #include <sys/crypto/common.h>
36 #include <sys/crypto/ioctl.h>
37 #include <sys/crypto/spi.h>
38 #include "kernelGlobal.h"
39 #include "kernelSlot.h"
40
41
42 /* ARGSUSED */
43 CK_RV
C_GetSlotList(CK_BBOOL tokenPresent,CK_SLOT_ID_PTR pSlotList,CK_ULONG_PTR pulCount)44 C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
45 CK_ULONG_PTR pulCount)
46 {
47 int i;
48
49 if (!kernel_initialized)
50 return (CKR_CRYPTOKI_NOT_INITIALIZED);
51
52 if (pulCount == NULL) {
53 return (CKR_ARGUMENTS_BAD);
54 }
55
56 if (pSlotList == NULL) {
57 *pulCount = slot_count;
58 return (CKR_OK);
59 }
60
61 if (*pulCount < slot_count) {
62 *pulCount = slot_count;
63 return (CKR_BUFFER_TOO_SMALL);
64 }
65
66 *pulCount = slot_count;
67
68 /*
69 * The slotID returned to an application will be the index to
70 * the slot_table. The library will map to the provider_id when
71 * making any ioctl call.
72 */
73 for (i = 0; i < slot_count; i++) {
74 pSlotList[i] = i;
75 }
76
77 return (CKR_OK);
78 }
79
80
81 CK_RV
C_GetSlotInfo(CK_SLOT_ID slotID,CK_SLOT_INFO_PTR pInfo)82 C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
83 {
84 CK_RV rv;
85 crypto_get_provider_info_t gi;
86 int r;
87
88 if (!kernel_initialized)
89 return (CKR_CRYPTOKI_NOT_INITIALIZED);
90
91 if (slotID >= slot_count) {
92 return (CKR_SLOT_ID_INVALID);
93 }
94
95 if (pInfo == NULL)
96 return (CKR_ARGUMENTS_BAD);
97
98 /* kernel provider numbers start with 0 */
99 gi.gi_provider_id = slot_table[slotID]->sl_provider_id;
100 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_INFO, &gi)) < 0) {
101 if (errno != EINTR)
102 break;
103 }
104 if (r < 0) {
105 rv = CKR_FUNCTION_FAILED;
106 } else {
107 if (gi.gi_return_value != CRYPTO_SUCCESS) {
108 rv = crypto2pkcs11_error_number(
109 gi.gi_return_value);
110 } else {
111 rv = CKR_OK;
112 }
113 }
114
115 if (rv == CKR_OK) {
116 bcopy(gi.gi_provider_data.pd_prov_desc,
117 pInfo->slotDescription, CRYPTO_PROVIDER_DESCR_MAX_LEN);
118 bcopy(gi.gi_provider_data.pd_manufacturerID,
119 pInfo->manufacturerID, CRYPTO_EXT_SIZE_MANUF);
120 pInfo->flags = CKF_TOKEN_PRESENT | CKF_HW_SLOT;
121 pInfo->hardwareVersion.major =
122 gi.gi_provider_data.pd_hardware_version.cv_major;
123 pInfo->hardwareVersion.minor =
124 gi.gi_provider_data.pd_hardware_version.cv_minor;
125 pInfo->firmwareVersion.major =
126 gi.gi_provider_data.pd_firmware_version.cv_major;
127 pInfo->firmwareVersion.minor =
128 gi.gi_provider_data.pd_firmware_version.cv_minor;
129 }
130
131 return (rv);
132 }
133
134
135 CK_RV
C_GetTokenInfo(CK_SLOT_ID slotID,CK_TOKEN_INFO_PTR pInfo)136 C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
137 {
138 CK_RV rv;
139 crypto_get_provider_info_t gi;
140 int r;
141
142 if (!kernel_initialized)
143 return (CKR_CRYPTOKI_NOT_INITIALIZED);
144
145 if (slotID >= slot_count)
146 return (CKR_SLOT_ID_INVALID);
147
148 if (pInfo == NULL)
149 return (CKR_ARGUMENTS_BAD);
150
151 gi.gi_provider_id = slot_table[slotID]->sl_provider_id;
152 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_INFO, &gi)) < 0) {
153 if (errno != EINTR)
154 break;
155 }
156 if (r < 0) {
157 rv = CKR_FUNCTION_FAILED;
158 } else {
159 rv = crypto2pkcs11_error_number(gi.gi_return_value);
160 }
161
162 if (rv == CKR_OK) {
163 bcopy(gi.gi_provider_data.pd_label, pInfo->label,
164 CRYPTO_EXT_SIZE_LABEL);
165 bcopy(gi.gi_provider_data.pd_manufacturerID,
166 pInfo->manufacturerID, CRYPTO_EXT_SIZE_MANUF);
167 bcopy(gi.gi_provider_data.pd_model, pInfo->model,
168 CRYPTO_EXT_SIZE_MODEL);
169 bcopy(gi.gi_provider_data.pd_serial_number,
170 pInfo->serialNumber, CRYPTO_EXT_SIZE_SERIAL);
171 pInfo->flags = gi.gi_provider_data.pd_flags;
172 pInfo->ulMaxSessionCount =
173 gi.gi_provider_data.pd_max_session_count;
174 pInfo->ulSessionCount =
175 gi.gi_provider_data.pd_session_count;
176 pInfo->ulMaxRwSessionCount =
177 gi.gi_provider_data.pd_max_rw_session_count;
178 pInfo->ulRwSessionCount =
179 gi.gi_provider_data.pd_rw_session_count;
180 pInfo->ulMaxPinLen =
181 gi.gi_provider_data.pd_max_pin_len;
182 pInfo->ulMinPinLen =
183 gi.gi_provider_data.pd_min_pin_len;
184 pInfo->ulTotalPublicMemory =
185 gi.gi_provider_data.pd_total_public_memory;
186 pInfo->ulFreePublicMemory =
187 gi.gi_provider_data.pd_free_public_memory;
188 pInfo->ulTotalPrivateMemory =
189 gi.gi_provider_data.pd_total_private_memory;
190 pInfo->ulFreePrivateMemory =
191 gi.gi_provider_data.pd_free_private_memory;
192 pInfo->hardwareVersion.major =
193 gi.gi_provider_data.pd_hardware_version.cv_major;
194 pInfo->hardwareVersion.minor =
195 gi.gi_provider_data.pd_hardware_version.cv_minor;
196 pInfo->firmwareVersion.major =
197 gi.gi_provider_data.pd_firmware_version.cv_major;
198 pInfo->firmwareVersion.minor =
199 gi.gi_provider_data.pd_firmware_version.cv_minor;
200 (void) strncpy((char *)pInfo->utcTime,
201 (const char *)gi.gi_provider_data.pd_time,
202 CRYPTO_EXT_SIZE_TIME);
203
204 }
205
206 return (rv);
207
208
209 }
210
211 /*ARGSUSED*/
212 CK_RV
C_WaitForSlotEvent(CK_FLAGS flags,CK_SLOT_ID_PTR pSlot,CK_VOID_PTR pReserved)213 C_WaitForSlotEvent(CK_FLAGS flags, CK_SLOT_ID_PTR pSlot, CK_VOID_PTR pReserved)
214 {
215 if (!kernel_initialized)
216 return (CKR_CRYPTOKI_NOT_INITIALIZED);
217
218 return (CKR_FUNCTION_NOT_SUPPORTED);
219 }
220
221
222 CK_RV
C_GetMechanismList(CK_SLOT_ID slotID,CK_MECHANISM_TYPE_PTR pMechanismList,CK_ULONG_PTR pulCount)223 C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
224 CK_ULONG_PTR pulCount)
225 {
226 CK_MECHANISM_TYPE type;
227 CK_RV rv;
228 CK_FLAGS flags;
229 CK_ULONG specified_count, count = 0;
230 crypto_get_provider_mechanisms_t *pm, tmp;
231 crypto_get_provider_mechanism_info_t mechanism_info;
232 crypto_provider_id_t provider_id;
233 size_t alloc_bytes;
234 int i, r;
235
236 if (!kernel_initialized)
237 return (CKR_CRYPTOKI_NOT_INITIALIZED);
238
239 if (slotID >= slot_count)
240 return (CKR_SLOT_ID_INVALID);
241
242 /* kernel provider numbers start with 0 */
243 provider_id = slot_table[slotID]->sl_provider_id;
244
245 if (pMechanismList != NULL) {
246 if (pulCount == NULL) {
247 return (CKR_ARGUMENTS_BAD);
248 } else if (*pulCount == 0) {
249 return (CKR_ARGUMENTS_BAD);
250 }
251 }
252 specified_count = *pulCount;
253 tmp.pm_provider_id = provider_id;
254 tmp.pm_count = 0;
255 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISMS,
256 &tmp)) < 0) {
257 if (errno != EINTR)
258 break;
259 }
260 if (r < 0) {
261 return (CKR_FUNCTION_FAILED);
262 } else {
263 if (tmp.pm_return_value != CRYPTO_SUCCESS) {
264 rv = crypto2pkcs11_error_number(tmp.pm_return_value);
265 return (rv);
266 }
267 alloc_bytes = sizeof (crypto_get_provider_mechanisms_t) +
268 (tmp.pm_count - 1) * sizeof (crypto_mech_name_t);
269 }
270
271 pm = malloc(alloc_bytes);
272 if (pm == NULL)
273 return (CKR_HOST_MEMORY);
274
275 pm->pm_provider_id = provider_id;
276 pm->pm_count = tmp.pm_count;
277
278 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISMS, pm)) < 0) {
279 if (errno != EINTR)
280 break;
281 }
282 if (r < 0) {
283 rv = CKR_FUNCTION_FAILED;
284 } else {
285 rv = crypto2pkcs11_error_number(pm->pm_return_value);
286 }
287
288 if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL)
289 goto clean_exit;
290
291 for (i = 0; i < pm->pm_count; i++) {
292 mechanism_info.mi_provider_id = provider_id;
293 bcopy(&pm->pm_list[i][0], mechanism_info.mi_mechanism_name,
294 sizeof (crypto_mech_name_t));
295
296 /*
297 * Get each mechanism's flags.
298 * The ioctl should not fail since the mechanism info is
299 * already in the kernel and a call doesn't have to be made
300 * to the provider. If it fails, nothing can be done other
301 * than skip the mechanism.
302 */
303 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISM_INFO,
304 &mechanism_info)) < 0) {
305 if (errno != EINTR)
306 break;
307 }
308 if (r < 0) {
309 continue;
310 }
311
312 if (mechanism_info.mi_return_value != CRYPTO_SUCCESS)
313 continue;
314
315 flags = mechanism_info.mi_flags;
316
317 /*
318 * Atomic flags are not part of PKCS#11 so we filter
319 * them out here.
320 */
321 flags &= ~(CRYPTO_FG_DIGEST_ATOMIC | CRYPTO_FG_ENCRYPT_ATOMIC |
322 CRYPTO_FG_DECRYPT_ATOMIC | CRYPTO_FG_MAC_ATOMIC |
323 CRYPTO_FG_SIGN_ATOMIC | CRYPTO_FG_VERIFY_ATOMIC |
324 CRYPTO_FG_SIGN_RECOVER_ATOMIC |
325 CRYPTO_FG_VERIFY_RECOVER_ATOMIC |
326 CRYPTO_FG_ENCRYPT_MAC_ATOMIC |
327 CRYPTO_FG_MAC_DECRYPT_ATOMIC);
328
329 /* mechanism has no PKCS#11 flags, so don't report it */
330 if (flags == 0)
331 continue;
332
333 /*
334 * The kernel framework has a pseudo mechanism
335 * for RNG which we remove from the list of mechanisms.
336 */
337 if (strcmp(&pm->pm_list[i][0], "random") != 0) {
338
339 if (pkcs11_str2mech(&pm->pm_list[i][0],
340 &type) != CKR_OK)
341 continue;
342
343 if (pMechanismList != NULL && rv == CKR_OK &&
344 (count < specified_count))
345 pMechanismList[count] = type;
346
347 count++;
348 }
349
350 }
351
352 if (pMechanismList != NULL && (count > specified_count))
353 rv = CKR_BUFFER_TOO_SMALL;
354
355 *pulCount = count;
356
357 clean_exit:
358 free(pm);
359 return (rv);
360 }
361
362
363 CK_RV
C_GetMechanismInfo(CK_SLOT_ID slotID,CK_MECHANISM_TYPE type,CK_MECHANISM_INFO_PTR pInfo)364 C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
365 CK_MECHANISM_INFO_PTR pInfo)
366 {
367 uint32_t k_mi_flags;
368 CK_RV rv;
369
370 if (!kernel_initialized)
371 return (CKR_CRYPTOKI_NOT_INITIALIZED);
372
373 if (slotID >= slot_count)
374 return (CKR_SLOT_ID_INVALID);
375
376 if (pInfo == NULL) {
377 return (CKR_ARGUMENTS_BAD);
378 }
379
380 rv = get_mechanism_info(slot_table[slotID], type, pInfo, &k_mi_flags);
381
382 return (rv);
383 }
384
385
386 /*ARGSUSED*/
387 CK_RV
C_InitToken(CK_SLOT_ID slotID,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen,CK_UTF8CHAR_PTR pLabel)388 C_InitToken(CK_SLOT_ID slotID, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen,
389 CK_UTF8CHAR_PTR pLabel)
390 {
391 if (!kernel_initialized)
392 return (CKR_CRYPTOKI_NOT_INITIALIZED);
393
394 return (CKR_FUNCTION_NOT_SUPPORTED);
395 }
396
397 /*ARGSUSED*/
398 CK_RV
C_InitPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pPin,CK_ULONG ulPinLen)399 C_InitPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pPin, CK_ULONG ulPinLen)
400 {
401 if (!kernel_initialized)
402 return (CKR_CRYPTOKI_NOT_INITIALIZED);
403
404 return (CKR_FUNCTION_NOT_SUPPORTED);
405 }
406
407
408 CK_RV
C_SetPIN(CK_SESSION_HANDLE hSession,CK_UTF8CHAR_PTR pOldPin,CK_ULONG ulOldLen,CK_UTF8CHAR_PTR pNewPin,CK_ULONG ulNewLen)409 C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
410 CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
411 {
412 CK_RV rv = CKR_OK;
413 kernel_session_t *session_p;
414 boolean_t ses_lock_held = B_FALSE;
415 crypto_set_pin_t setpin;
416 int r;
417
418 if (!kernel_initialized)
419 return (CKR_CRYPTOKI_NOT_INITIALIZED);
420
421 /*
422 * Obtain the session pointer. Also, increment the session
423 * reference count.
424 */
425 rv = handle2session(hSession, &session_p);
426 if (rv != CKR_OK)
427 return (rv);
428
429 /* Make sure it is a RW session. */
430 if (session_p->ses_RO) {
431 rv = CKR_SESSION_READ_ONLY;
432 REFRELE(session_p, ses_lock_held);
433 return (rv);
434 }
435
436 /* Lock the session and make the CRYPTO_SET_PIN ioctl call. */
437 (void) pthread_mutex_lock(&session_p->session_mutex);
438 ses_lock_held = B_TRUE;
439
440 setpin.sp_session = session_p->k_session;
441 setpin.sp_old_pin = (char *)pOldPin;
442 setpin.sp_old_len = ulOldLen;
443 setpin.sp_new_pin = (char *)pNewPin;
444 setpin.sp_new_len = ulNewLen;
445
446 while ((r = ioctl(kernel_fd, CRYPTO_SET_PIN, &setpin)) < 0) {
447 if (errno != EINTR)
448 break;
449 }
450 if (r < 0) {
451 rv = CKR_FUNCTION_FAILED;
452 } else {
453 rv = crypto2pkcs11_error_number(setpin.sp_return_value);
454 }
455
456 REFRELE(session_p, ses_lock_held);
457 return (rv);
458 }
459