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