8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_kernel / common / kernelSlotToken.c
blob76709a58a1304f4dc0a09f29fb810ea9f3b6755a
1 /*
2 * CDDL HEADER START
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.
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]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
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"
42 /* ARGSUSED */
43 CK_RV
44 C_GetSlotList(CK_BBOOL tokenPresent, CK_SLOT_ID_PTR pSlotList,
45 CK_ULONG_PTR pulCount)
47 int i;
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;
58 return (CKR_OK);
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++) {
74 pSlotList[i] = i;
77 return (CKR_OK);
81 CK_RV
82 C_GetSlotInfo(CK_SLOT_ID slotID, CK_SLOT_INFO_PTR pInfo)
84 CK_RV rv;
85 crypto_get_provider_info_t gi;
86 int r;
88 if (!kernel_initialized)
89 return (CKR_CRYPTOKI_NOT_INITIALIZED);
91 if (slotID >= slot_count) {
92 return (CKR_SLOT_ID_INVALID);
95 if (pInfo == NULL)
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) {
101 if (errno != EINTR)
102 break;
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;
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;
131 return (rv);
135 CK_RV
136 C_GetTokenInfo(CK_SLOT_ID slotID, CK_TOKEN_INFO_PTR pInfo)
138 CK_RV rv;
139 crypto_get_provider_info_t gi;
140 int r;
142 if (!kernel_initialized)
143 return (CKR_CRYPTOKI_NOT_INITIALIZED);
145 if (slotID >= slot_count)
146 return (CKR_SLOT_ID_INVALID);
148 if (pInfo == NULL)
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) {
153 if (errno != EINTR)
154 break;
156 if (r < 0) {
157 rv = CKR_FUNCTION_FAILED;
158 } else {
159 rv = crypto2pkcs11_error_number(gi.gi_return_value);
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);
206 return (rv);
211 /*ARGSUSED*/
212 CK_RV
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);
222 CK_RV
223 C_GetMechanismList(CK_SLOT_ID slotID, CK_MECHANISM_TYPE_PTR pMechanismList,
224 CK_ULONG_PTR pulCount)
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;
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;
254 tmp.pm_count = 0;
255 while ((r = ioctl(kernel_fd, CRYPTO_GET_PROVIDER_MECHANISMS,
256 &tmp)) < 0) {
257 if (errno != EINTR)
258 break;
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);
267 alloc_bytes = sizeof (crypto_get_provider_mechanisms_t) +
268 (tmp.pm_count - 1) * sizeof (crypto_mech_name_t);
271 pm = malloc(alloc_bytes);
272 if (pm == NULL)
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) {
279 if (errno != EINTR)
280 break;
282 if (r < 0) {
283 rv = CKR_FUNCTION_FAILED;
284 } else {
285 rv = crypto2pkcs11_error_number(pm->pm_return_value);
288 if (rv != CKR_OK && rv != CKR_BUFFER_TOO_SMALL)
289 goto clean_exit;
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) {
305 if (errno != EINTR)
306 break;
308 if (r < 0) {
309 continue;
312 if (mechanism_info.mi_return_value != CRYPTO_SUCCESS)
313 continue;
315 flags = mechanism_info.mi_flags;
318 * Atomic flags are not part of PKCS#11 so we filter
319 * them out here.
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 */
330 if (flags == 0)
331 continue;
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],
340 &type) != CKR_OK)
341 continue;
343 if (pMechanismList != NULL && rv == CKR_OK &&
344 (count < specified_count))
345 pMechanismList[count] = type;
347 count++;
352 if (pMechanismList != NULL && (count > specified_count))
353 rv = CKR_BUFFER_TOO_SMALL;
355 *pulCount = count;
357 clean_exit:
358 free(pm);
359 return (rv);
363 CK_RV
364 C_GetMechanismInfo(CK_SLOT_ID slotID, CK_MECHANISM_TYPE type,
365 CK_MECHANISM_INFO_PTR pInfo)
367 uint32_t k_mi_flags;
368 CK_RV rv;
370 if (!kernel_initialized)
371 return (CKR_CRYPTOKI_NOT_INITIALIZED);
373 if (slotID >= slot_count)
374 return (CKR_SLOT_ID_INVALID);
376 if (pInfo == NULL) {
377 return (CKR_ARGUMENTS_BAD);
380 rv = get_mechanism_info(slot_table[slotID], type, pInfo, &k_mi_flags);
382 return (rv);
386 /*ARGSUSED*/
387 CK_RV
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);
397 /*ARGSUSED*/
398 CK_RV
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);
408 CK_RV
409 C_SetPIN(CK_SESSION_HANDLE hSession, CK_UTF8CHAR_PTR pOldPin,
410 CK_ULONG ulOldLen, CK_UTF8CHAR_PTR pNewPin, CK_ULONG ulNewLen)
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;
418 if (!kernel_initialized)
419 return (CKR_CRYPTOKI_NOT_INITIALIZED);
422 * Obtain the session pointer. Also, increment the session
423 * reference count.
425 rv = handle2session(hSession, &session_p);
426 if (rv != CKR_OK)
427 return (rv);
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);
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) {
447 if (errno != EINTR)
448 break;
450 if (r < 0) {
451 rv = CKR_FUNCTION_FAILED;
452 } else {
453 rv = crypto2pkcs11_error_number(setpin.sp_return_value);
456 REFRELE(session_p, ses_lock_held);
457 return (rv);