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
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.
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
31 #include <security/cryptoki.h>
32 #include <cryptoutil.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"
44 C_GetSlotList(CK_BBOOL tokenPresent
, CK_SLOT_ID_PTR pSlotList
,
45 CK_ULONG_PTR pulCount
)
49 if (!kernel_initialized
)
50 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
52 if (pulCount
== NULL
) {
53 return (CKR_ARGUMENTS_BAD
);
56 if (pSlotList
== NULL
) {
57 *pulCount
= slot_count
;
61 if (*pulCount
< slot_count
) {
62 *pulCount
= slot_count
;
63 return (CKR_BUFFER_TOO_SMALL
);
66 *pulCount
= slot_count
;
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.
73 for (i
= 0; i
< slot_count
; i
++) {
82 C_GetSlotInfo(CK_SLOT_ID slotID
, CK_SLOT_INFO_PTR pInfo
)
85 crypto_get_provider_info_t gi
;
88 if (!kernel_initialized
)
89 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
91 if (slotID
>= slot_count
) {
92 return (CKR_SLOT_ID_INVALID
);
96 return (CKR_ARGUMENTS_BAD
);
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) {
105 rv
= CKR_FUNCTION_FAILED
;
107 if (gi
.gi_return_value
!= CRYPTO_SUCCESS
) {
108 rv
= crypto2pkcs11_error_number(
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
;
136 C_GetTokenInfo(CK_SLOT_ID slotID
, CK_TOKEN_INFO_PTR pInfo
)
139 crypto_get_provider_info_t gi
;
142 if (!kernel_initialized
)
143 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
145 if (slotID
>= slot_count
)
146 return (CKR_SLOT_ID_INVALID
);
149 return (CKR_ARGUMENTS_BAD
);
151 gi
.gi_provider_id
= slot_table
[slotID
]->sl_provider_id
;
152 while ((r
= ioctl(kernel_fd
, CRYPTO_GET_PROVIDER_INFO
, &gi
)) < 0) {
157 rv
= CKR_FUNCTION_FAILED
;
159 rv
= crypto2pkcs11_error_number(gi
.gi_return_value
);
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
;
181 gi
.gi_provider_data
.pd_max_pin_len
;
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
);
213 C_WaitForSlotEvent(CK_FLAGS flags
, CK_SLOT_ID_PTR pSlot
, CK_VOID_PTR pReserved
)
215 if (!kernel_initialized
)
216 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
218 return (CKR_FUNCTION_NOT_SUPPORTED
);
223 C_GetMechanismList(CK_SLOT_ID slotID
, CK_MECHANISM_TYPE_PTR pMechanismList
,
224 CK_ULONG_PTR pulCount
)
226 CK_MECHANISM_TYPE type
;
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
;
236 if (!kernel_initialized
)
237 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
239 if (slotID
>= slot_count
)
240 return (CKR_SLOT_ID_INVALID
);
242 /* kernel provider numbers start with 0 */
243 provider_id
= slot_table
[slotID
]->sl_provider_id
;
245 if (pMechanismList
!= NULL
) {
246 if (pulCount
== NULL
) {
247 return (CKR_ARGUMENTS_BAD
);
248 } else if (*pulCount
== 0) {
249 return (CKR_ARGUMENTS_BAD
);
252 specified_count
= *pulCount
;
253 tmp
.pm_provider_id
= provider_id
;
255 while ((r
= ioctl(kernel_fd
, CRYPTO_GET_PROVIDER_MECHANISMS
,
261 return (CKR_FUNCTION_FAILED
);
263 if (tmp
.pm_return_value
!= CRYPTO_SUCCESS
) {
264 rv
= crypto2pkcs11_error_number(tmp
.pm_return_value
);
267 alloc_bytes
= sizeof (crypto_get_provider_mechanisms_t
) +
268 (tmp
.pm_count
- 1) * sizeof (crypto_mech_name_t
);
271 pm
= malloc(alloc_bytes
);
273 return (CKR_HOST_MEMORY
);
275 pm
->pm_provider_id
= provider_id
;
276 pm
->pm_count
= tmp
.pm_count
;
278 while ((r
= ioctl(kernel_fd
, CRYPTO_GET_PROVIDER_MECHANISMS
, pm
)) < 0) {
283 rv
= CKR_FUNCTION_FAILED
;
285 rv
= crypto2pkcs11_error_number(pm
->pm_return_value
);
288 if (rv
!= CKR_OK
&& rv
!= CKR_BUFFER_TOO_SMALL
)
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
));
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.
303 while ((r
= ioctl(kernel_fd
, CRYPTO_GET_PROVIDER_MECHANISM_INFO
,
304 &mechanism_info
)) < 0) {
312 if (mechanism_info
.mi_return_value
!= CRYPTO_SUCCESS
)
315 flags
= mechanism_info
.mi_flags
;
318 * Atomic flags are not part of PKCS#11 so we filter
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
);
329 /* mechanism has no PKCS#11 flags, so don't report it */
334 * The kernel framework has a pseudo mechanism
335 * for RNG which we remove from the list of mechanisms.
337 if (strcmp(&pm
->pm_list
[i
][0], "random") != 0) {
339 if (pkcs11_str2mech(&pm
->pm_list
[i
][0],
343 if (pMechanismList
!= NULL
&& rv
== CKR_OK
&&
344 (count
< specified_count
))
345 pMechanismList
[count
] = type
;
352 if (pMechanismList
!= NULL
&& (count
> specified_count
))
353 rv
= CKR_BUFFER_TOO_SMALL
;
364 C_GetMechanismInfo(CK_SLOT_ID slotID
, CK_MECHANISM_TYPE type
,
365 CK_MECHANISM_INFO_PTR pInfo
)
370 if (!kernel_initialized
)
371 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
373 if (slotID
>= slot_count
)
374 return (CKR_SLOT_ID_INVALID
);
377 return (CKR_ARGUMENTS_BAD
);
380 rv
= get_mechanism_info(slot_table
[slotID
], type
, pInfo
, &k_mi_flags
);
388 C_InitToken(CK_SLOT_ID slotID
, CK_UTF8CHAR_PTR pPin
, CK_ULONG ulPinLen
,
389 CK_UTF8CHAR_PTR pLabel
)
391 if (!kernel_initialized
)
392 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
394 return (CKR_FUNCTION_NOT_SUPPORTED
);
399 C_InitPIN(CK_SESSION_HANDLE hSession
, CK_UTF8CHAR_PTR pPin
, CK_ULONG ulPinLen
)
401 if (!kernel_initialized
)
402 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
404 return (CKR_FUNCTION_NOT_SUPPORTED
);
409 C_SetPIN(CK_SESSION_HANDLE hSession
, CK_UTF8CHAR_PTR pOldPin
,
410 CK_ULONG ulOldLen
, CK_UTF8CHAR_PTR pNewPin
, CK_ULONG ulNewLen
)
413 kernel_session_t
*session_p
;
414 boolean_t ses_lock_held
= B_FALSE
;
415 crypto_set_pin_t setpin
;
418 if (!kernel_initialized
)
419 return (CKR_CRYPTOKI_NOT_INITIALIZED
);
422 * Obtain the session pointer. Also, increment the session
425 rv
= handle2session(hSession
, &session_p
);
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
);
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
;
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
;
446 while ((r
= ioctl(kernel_fd
, CRYPTO_SET_PIN
, &setpin
)) < 0) {
451 rv
= CKR_FUNCTION_FAILED
;
453 rv
= crypto2pkcs11_error_number(setpin
.sp_return_value
);
456 REFRELE(session_p
, ses_lock_held
);