8322 nl: misleading-indentation
[unleashed/tickless.git] / usr / src / lib / pkcs11 / pkcs11_kernel / common / kernelObject.c
blob1fe9bec23ab8e7f283ab96a28fe15123c3c14b64
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 <pthread.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <security/cryptoki.h>
33 #include "kernelGlobal.h"
34 #include "kernelObject.h"
35 #include "kernelSession.h"
36 #include <errno.h>
37 #include <string.h>
38 #include <cryptoutil.h>
40 CK_RV
41 C_CreateObject(CK_SESSION_HANDLE hSession,
42 CK_ATTRIBUTE_PTR pTemplate,
43 CK_ULONG ulCount,
44 CK_OBJECT_HANDLE_PTR phObject)
47 CK_RV rv;
48 kernel_session_t *session_p;
49 boolean_t ses_lock_held = B_FALSE;
51 if (!kernel_initialized)
52 return (CKR_CRYPTOKI_NOT_INITIALIZED);
54 if ((pTemplate == NULL) || (ulCount == 0) ||
55 (phObject == NULL)) {
56 return (CKR_ARGUMENTS_BAD);
60 * Obtain the session pointer. Also, increment the session
61 * reference count.
63 rv = handle2session(hSession, &session_p);
64 if (rv != CKR_OK)
65 return (rv);
67 /* Create a new object. */
68 rv = kernel_add_object(pTemplate, ulCount, phObject, session_p);
71 * Decrement the session reference count.
72 * We do not hold the session lock.
74 REFRELE(session_p, ses_lock_held);
76 return (rv);
80 CK_RV
81 C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
82 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
83 CK_OBJECT_HANDLE_PTR phNewObject)
86 CK_RV rv;
87 kernel_session_t *session_p;
88 boolean_t ses_lock_held = B_FALSE;
89 kernel_object_t *old_object;
90 kernel_object_t *new_object = NULL;
91 crypto_object_copy_t object_copy;
92 CK_BBOOL is_pri_obj = FALSE;
93 CK_BBOOL is_token_obj = FALSE;
94 kernel_slot_t *pslot;
95 int i, r;
97 if (!kernel_initialized)
98 return (CKR_CRYPTOKI_NOT_INITIALIZED);
100 /* Check arguments */
101 if (((ulCount > 0) && (pTemplate == NULL)) ||
102 (phNewObject == NULL)) {
103 return (CKR_ARGUMENTS_BAD);
107 * Obtain the session pointer. Also, increment the session
108 * reference count.
110 rv = handle2session(hSession, &session_p);
111 if (rv != CKR_OK)
112 return (rv);
114 /* Obtain the object pointer. */
115 HANDLE2OBJECT(hObject, old_object, rv);
116 if (rv != CKR_OK) {
118 * Decrement the session reference count.
119 * We do not hold the session lock.
121 REFRELE(session_p, ses_lock_held);
122 return (rv);
125 (void) pthread_mutex_lock(&old_object->object_mutex);
127 if (old_object->is_lib_obj) {
129 * Copy the old object to a new object.
130 * The 3rd argument with TRUE value indicates that
131 * everything in the object will be duplicated.
133 rv = kernel_copy_object(old_object, &new_object, B_TRUE,
134 session_p);
135 (void) pthread_mutex_unlock(&old_object->object_mutex);
136 if ((rv != CKR_OK) || (new_object == NULL)) {
138 * Most likely we ran out of space.
139 * Decrement the session reference count.
140 * We do not hold the session lock.
142 OBJ_REFRELE(old_object);
143 REFRELE(session_p, ses_lock_held);
144 return (rv);
147 new_object->is_lib_obj = B_TRUE;
149 /* Modify the object attribute if requested */
150 for (i = 0; i < ulCount; i++) {
151 /* Set the requested attribute into the new object. */
152 rv = kernel_set_attribute(new_object, &pTemplate[i],
153 B_TRUE, session_p);
155 if (rv != CKR_OK) {
156 kernel_cleanup_object(new_object);
159 * Decrement the session reference count.
160 * We do not hold the session lock.
162 OBJ_REFRELE(old_object);
163 REFRELE(session_p, ses_lock_held);
164 return (rv);
168 /* Insert the new object into this session's object list. */
169 kernel_add_object_to_session(new_object, session_p);
172 * Decrement the session reference count.
173 * We do not hold the session lock.
175 OBJ_REFRELE(old_object);
176 REFRELE(session_p, ses_lock_held);
178 /* set handle of the new object */
179 *phNewObject = (CK_ULONG)new_object;
181 } else {
183 * The old object was created in the HW provider.
184 * First, create an object wrapper in library.
186 new_object = calloc(1, sizeof (kernel_object_t));
187 if (new_object == NULL) {
188 (void) pthread_mutex_unlock(&old_object->object_mutex);
189 OBJ_REFRELE(old_object);
190 REFRELE(session_p, ses_lock_held);
191 return (CKR_HOST_MEMORY);
194 /* Call CRYPTO_OBJECT_COPY ioctl to get a new object. */
195 object_copy.oc_session = session_p->k_session;
196 object_copy.oc_handle = old_object->k_handle;
197 (void) pthread_mutex_unlock(&old_object->object_mutex);
198 object_copy.oc_count = ulCount;
199 object_copy.oc_new_attributes = NULL;
200 if (ulCount > 0) {
201 rv = process_object_attributes(pTemplate, ulCount,
202 &object_copy.oc_new_attributes, &is_token_obj);
203 if (rv != CKR_OK) {
204 goto failed_cleanup;
208 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_COPY,
209 &object_copy)) < 0) {
210 if (errno != EINTR)
211 break;
213 if (r < 0) {
214 rv = CKR_FUNCTION_FAILED;
215 } else {
216 rv = crypto2pkcs11_error_number(
217 object_copy.oc_return_value);
220 /* Free the attributes' space allocated for ioctl */
221 free_object_attributes(object_copy.oc_new_attributes, ulCount);
223 if (rv != CKR_OK) {
224 goto failed_cleanup;
228 * Store the kernel object handle in the object wrapper and
229 * get the CKA_PRIVATE value of the new object.
231 new_object->k_handle = object_copy.oc_new_handle;
232 rv = get_cka_private_value(session_p, new_object->k_handle,
233 &is_pri_obj);
234 if (rv != CKR_OK) {
235 goto failed_cleanup;
239 * Initialize other field of the object wrapper.
241 new_object->is_lib_obj = B_FALSE;
242 new_object->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
243 new_object->session_handle = (CK_SESSION_HANDLE)session_p;
244 (void) pthread_mutex_init(&new_object->object_mutex, NULL);
246 if (is_pri_obj)
247 new_object->bool_attr_mask |= PRIVATE_BOOL_ON;
248 else
249 new_object->bool_attr_mask &= ~PRIVATE_BOOL_ON;
251 if (is_token_obj)
252 new_object->bool_attr_mask |= TOKEN_BOOL_ON;
253 else
254 new_object->bool_attr_mask &= ~TOKEN_BOOL_ON;
257 * Add the new copied object into the slot's token list
258 * or the session list. We don't hold the slot lock.
260 if (is_token_obj) {
261 pslot = slot_table[session_p->ses_slotid];
264 * Decrement the session reference count.
265 * We do not hold the session lock.
267 OBJ_REFRELE(old_object);
268 REFRELE(session_p, ses_lock_held);
270 /* Add into the slot token object list. */
271 kernel_add_token_object_to_slot(new_object, pslot);
272 } else {
273 kernel_add_object_to_session(new_object, session_p);
276 * Decrement the session reference count.
277 * We do not hold the session lock.
279 OBJ_REFRELE(old_object);
280 REFRELE(session_p, ses_lock_held);
283 /* set handle of the new object */
284 *phNewObject = (CK_ULONG)new_object;
287 return (rv);
289 failed_cleanup:
290 if (new_object != NULL) {
291 (void) free(new_object);
294 OBJ_REFRELE(old_object);
295 REFRELE(session_p, ses_lock_held);
296 return (rv);
300 CK_RV
301 C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
303 CK_RV rv;
304 kernel_object_t *object_p;
305 kernel_session_t *session_p = (kernel_session_t *)(hSession);
306 kernel_slot_t *pslot;
307 boolean_t ses_lock_held = B_FALSE;
308 CK_SESSION_HANDLE creating_session;
310 if (!kernel_initialized)
311 return (CKR_CRYPTOKI_NOT_INITIALIZED);
314 * The reason that we don't call handle2session is because
315 * the argument hSession may not be the creating_session of
316 * the object to be destroyed, and we want to avoid the lock
317 * contention. The handle2session will be called later for
318 * the creating_session.
320 if ((session_p == NULL) ||
321 (session_p->magic_marker != KERNELTOKEN_SESSION_MAGIC)) {
322 return (CKR_SESSION_HANDLE_INVALID);
325 /* Obtain the object pointer without incrementing reference count. */
326 HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
327 if (rv != CKR_OK) {
328 return (rv);
331 /* Only session objects can be destroyed at a read-only session. */
332 if ((session_p->ses_RO) &&
333 (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
334 return (CKR_SESSION_READ_ONLY);
338 * If the object is a session object, obtain the session handle
339 * which object belongs to. For a token object, we will use the
340 * session handle from the caller, because the session used to
341 * create the token object may no longer exist.
343 if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON))
344 creating_session = object_p->session_handle;
345 else
346 creating_session = hSession;
348 rv = handle2session(creating_session, &session_p);
349 if (rv != CKR_OK) {
350 return (rv);
354 * Set OBJECT_IS_DELETING flag so any access to this
355 * object will be rejected.
357 (void) pthread_mutex_lock(&object_p->object_mutex);
358 if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
359 (void) pthread_mutex_unlock(&object_p->object_mutex);
360 REFRELE(session_p, ses_lock_held);
361 return (CKR_OBJECT_HANDLE_INVALID);
363 object_p->obj_delete_sync |= OBJECT_IS_DELETING;
364 (void) pthread_mutex_unlock(&object_p->object_mutex);
366 if (object_p->bool_attr_mask & TOKEN_BOOL_ON) {
368 * The first FALSE boolean argument indicates that the caller
369 * does not hold the slot lock. The second FALSE boolean
370 * argument indicates that the caller wants to clean up the
371 * object in the HW provider also.
373 pslot = slot_table[session_p->ses_slotid];
374 rv = kernel_delete_token_object(pslot, session_p, object_p,
375 B_FALSE, B_FALSE);
376 } else {
378 * The first FALSE boolean argument indicates that the caller
379 * does not hold the session lock. The second FALSE boolean
380 * argument indicates that the caller wants to clean the object
381 * in the HW provider also.
383 rv = kernel_delete_session_object(session_p, object_p, B_FALSE,
384 B_FALSE);
387 * Decrement the session reference count.
388 * We do not hold the session lock.
390 REFRELE(session_p, ses_lock_held);
391 return (rv);
395 CK_RV
396 C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
397 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
400 CK_RV rv = CKR_OK, rv1 = CKR_OK;
401 kernel_object_t *object_p;
402 kernel_session_t *session_p;
403 boolean_t ses_lock_held = B_FALSE;
404 crypto_object_get_attribute_value_t obj_get_attr;
405 int i, r;
407 if (!kernel_initialized)
408 return (CKR_CRYPTOKI_NOT_INITIALIZED);
410 if ((pTemplate == NULL) || (ulCount == 0))
411 return (CKR_ARGUMENTS_BAD);
414 * Obtain the session pointer. Also, increment the session
415 * reference count.
417 rv = handle2session(hSession, &session_p);
418 if (rv != CKR_OK)
419 return (rv);
421 /* Obtain the object pointer. */
422 HANDLE2OBJECT(hObject, object_p, rv);
423 if (rv != CKR_OK) {
425 * Decrement the session reference count.
426 * We do not hold the session lock.
428 REFRELE(session_p, ses_lock_held);
429 return (rv);
432 /* Acquire the lock on the object. */
433 (void) pthread_mutex_lock(&object_p->object_mutex);
435 if (object_p->is_lib_obj) {
437 * The object was created in the library. The library
438 * contains the value information of each attribute.
440 for (i = 0; i < ulCount; i++) {
442 * Get the value of each attribute in the template.
443 * (We must process EVERY attribute in the template.)
445 rv = kernel_get_attribute(object_p, &pTemplate[i]);
446 if (rv != CKR_OK)
447 /* At least we catch some type of error. */
448 rv1 = rv;
450 rv = rv1;
451 (void) pthread_mutex_unlock(&object_p->object_mutex);
452 } else {
454 * The object was created in HW provider, call ioctl to get
455 * the values of attributes.
457 obj_get_attr.og_session = session_p->k_session;
458 obj_get_attr.og_handle = object_p->k_handle;
459 (void) pthread_mutex_unlock(&object_p->object_mutex);
460 obj_get_attr.og_count = ulCount;
462 rv = process_object_attributes(pTemplate, ulCount,
463 &obj_get_attr.og_attributes, NULL);
464 if (rv != CKR_OK) {
465 goto clean_exit;
468 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
469 &obj_get_attr)) < 0) {
470 if (errno != EINTR)
471 break;
473 if (r < 0) {
474 rv = CKR_FUNCTION_FAILED;
475 } else {
476 rv = crypto2pkcs11_error_number(
477 obj_get_attr.og_return_value);
481 * The error codes CKR_ATTRIBUTE_SENSITIVE,
482 * CKR_ATTRIBUTE_TYPE_INVALID, and CKR_BUFFER_TOO_SMALL
483 * do not denote true errors for this function. If a call
484 * returns any of these three values, then the call must
485 * nonetheless have processed every attribute in the
486 * template. Every attribute in the template whose value
487 * can be returned will be returned.
489 if ((rv == CKR_OK) ||
490 (rv == CKR_ATTRIBUTE_SENSITIVE) ||
491 (rv == CKR_ATTRIBUTE_TYPE_INVALID) ||
492 (rv == CKR_BUFFER_TOO_SMALL)) {
493 rv1 = get_object_attributes(pTemplate, ulCount,
494 obj_get_attr.og_attributes);
495 if (rv1 != CKR_OK) {
496 rv = rv1;
500 /* Free the attributes' allocated for the ioctl call. */
501 free_object_attributes(obj_get_attr.og_attributes, ulCount);
504 clean_exit:
506 * Decrement the session reference count.
507 * We do not hold the session lock.
509 OBJ_REFRELE(object_p);
510 REFRELE(session_p, ses_lock_held);
511 return (rv);
515 CK_RV
516 C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
517 CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
519 CK_RV rv = CKR_OK;
520 kernel_object_t *object_p;
521 kernel_object_t *new_object = NULL;
522 kernel_session_t *session_p;
523 boolean_t ses_lock_held = B_FALSE;
524 crypto_object_set_attribute_value_t obj_set_attr;
525 int i, r;
527 if (!kernel_initialized)
528 return (CKR_CRYPTOKI_NOT_INITIALIZED);
530 if ((pTemplate == NULL) || (ulCount == 0))
531 return (CKR_ARGUMENTS_BAD);
534 * Obtain the session pointer. Also, increment the session
535 * reference count.
537 rv = handle2session(hSession, &session_p);
538 if (rv != CKR_OK)
539 return (rv);
541 /* Obtain the object pointer. */
542 HANDLE2OBJECT(hObject, object_p, rv);
543 if (rv != CKR_OK) {
545 * Decrement the session reference count.
546 * We do not hold the session lock.
548 REFRELE(session_p, ses_lock_held);
549 return (rv);
552 /* lock the object */
553 (void) pthread_mutex_lock(&object_p->object_mutex);
556 * If the object was created in the HW provider, changing its
557 * attributes' values need to be done in the provider too.
559 if (!object_p->is_lib_obj) {
561 /* Cannot modify a token object with a READ-ONLY session */
562 if (session_p->ses_RO &&
563 (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
564 (void) pthread_mutex_unlock(&object_p->object_mutex);
565 rv = CKR_SESSION_READ_ONLY;
566 goto clean_exit;
569 obj_set_attr.sa_session = session_p->k_session;
570 obj_set_attr.sa_handle = object_p->k_handle;
571 (void) pthread_mutex_unlock(&object_p->object_mutex);
572 obj_set_attr.sa_count = ulCount;
573 rv = process_object_attributes(pTemplate, ulCount,
574 &obj_set_attr.sa_attributes, NULL);
575 if (rv != CKR_OK) {
576 goto clean_exit;
579 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE,
580 &obj_set_attr)) < 0) {
581 if (errno != EINTR)
582 break;
584 if (r < 0) {
585 rv = CKR_FUNCTION_FAILED;
586 } else {
587 rv = crypto2pkcs11_error_number(
588 obj_set_attr.sa_return_value);
591 /* Free the attributes' space allocated for the ioctl call. */
592 free_object_attributes(obj_set_attr.sa_attributes, ulCount);
593 goto clean_exit;
597 * if we come here, the object must have been created in the
598 * library. The work will be done completely in the library.
600 * Copy the old object to a new object. We work on the copied
601 * version because in case of error we still keep the old one
602 * intact.
604 rv = kernel_copy_object(object_p, &new_object, B_FALSE, NULL);
605 (void) pthread_mutex_unlock(&object_p->object_mutex);
606 if ((rv != CKR_OK) || (new_object == NULL)) {
608 * Most likely we ran out of space.
609 * Decrement the session reference count.
610 * We do not hold the session lock.
612 goto clean_exit;
615 for (i = 0; i < ulCount; i++) {
616 /* Set the requested attribute into the new object. */
617 rv = kernel_set_attribute(new_object, &pTemplate[i], B_FALSE,
618 session_p);
620 if (rv != CKR_OK) {
621 kernel_cleanup_object(new_object);
622 goto clean_exit;
627 * We've successfully set all the requested attributes.
628 * Merge the new object with the old object, then destory
629 * the new one. The reason to do the merging is because we
630 * have to keep the original object handle (address of object).
632 (void) pthread_mutex_lock(&object_p->object_mutex);
633 kernel_merge_object(object_p, new_object);
634 (void) pthread_mutex_unlock(&object_p->object_mutex);
636 clean_exit:
637 if (new_object != NULL)
638 (void) free(new_object);
641 * Decrement the session reference count.
642 * We do not hold the session lock.
644 OBJ_REFRELE(object_p);
645 REFRELE(session_p, ses_lock_held);
647 return (rv);
651 CK_RV
652 C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
653 CK_ULONG_PTR pulSize)
656 CK_RV rv = CKR_OK;
657 kernel_object_t *object_p;
658 kernel_session_t *session_p;
659 boolean_t ses_lock_held = B_FALSE;
660 crypto_object_get_size_t obj_gs;
661 int r;
663 if (!kernel_initialized)
664 return (CKR_CRYPTOKI_NOT_INITIALIZED);
666 /* Check if pulSize is valid */
667 if (pulSize == NULL) {
668 return (CKR_ARGUMENTS_BAD);
672 * Obtain the session pointer. Also, increment the session
673 * reference count.
675 rv = handle2session(hSession, &session_p);
676 if (rv != CKR_OK)
677 return (rv);
679 /* Obtain the object pointer. */
680 HANDLE2OBJECT(hObject, object_p, rv);
681 if (rv != CKR_OK) {
683 * Decrement the session reference count.
684 * We do not hold the session lock.
686 REFRELE(session_p, ses_lock_held);
687 return (rv);
690 /* Acquire the lock on the object. */
691 (void) pthread_mutex_lock(&object_p->object_mutex);
693 if (!object_p->is_lib_obj) {
695 * The object was created in HW provider, call the
696 * CRYPTO_OBJECT_GET_SIZE ioctl.
698 obj_gs.gs_session = session_p->k_session;
699 obj_gs.gs_handle = object_p->k_handle;
700 (void) pthread_mutex_unlock(&object_p->object_mutex);
701 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_SIZE,
702 &obj_gs)) < 0) {
703 if (errno != EINTR)
704 break;
706 if (r < 0) {
707 rv = CKR_FUNCTION_FAILED;
708 } else {
709 rv = crypto2pkcs11_error_number(
710 obj_gs.gs_return_value);
713 if (rv == CKR_OK) {
714 *pulSize = obj_gs.gs_size;
717 } else {
718 rv = kernel_get_object_size(object_p, pulSize);
719 (void) pthread_mutex_unlock(&object_p->object_mutex);
723 * Decrement the session reference count.
724 * We do not hold the session lock.
726 OBJ_REFRELE(object_p);
727 REFRELE(session_p, ses_lock_held);
728 return (rv);
732 CK_RV
733 C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
734 CK_ULONG ulCount)
736 CK_RV rv;
737 kernel_session_t *session_p;
738 boolean_t ses_lock_held = B_FALSE;
739 kernel_slot_t *pslot;
740 crypto_object_find_init_t obj_fi;
741 int r;
743 if (!kernel_initialized)
744 return (CKR_CRYPTOKI_NOT_INITIALIZED);
746 /* Check the arguments */
747 if ((ulCount > 0) && (pTemplate == NULL)) {
748 return (CKR_ARGUMENTS_BAD);
752 * Obtain the session pointer. Also, increment the session
753 * reference count.
755 rv = handle2session(sh, &session_p);
756 if (rv != CKR_OK)
757 return (rv);
759 /* Acquire the session lock */
760 (void) pthread_mutex_lock(&session_p->session_mutex);
761 ses_lock_held = B_TRUE;
763 /* Check to see if find operation is already active */
764 if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
765 /* decrement the session count, and unlock the mutex */
766 REFRELE(session_p, ses_lock_held);
767 return (CKR_OPERATION_ACTIVE);
768 } else {
770 * This active flag will remain ON until application calls
771 * C_FindObjectsFinal.
773 session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
778 * If the HW provider supports object creation, we call the
779 * CRYPTO_OBJECT_FIND_INIT ioctl to initialize object finding.
780 * Otherwise, all the objects are created in the library and we
781 * do the find objects solely in the library.
783 pslot = slot_table[session_p->ses_slotid];
784 if (pslot->sl_func_list.fl_object_create) {
785 obj_fi.fi_session = session_p->k_session;
786 (void) pthread_mutex_unlock(&session_p->session_mutex);
787 ses_lock_held = B_FALSE;
788 obj_fi.fi_count = ulCount;
789 rv = process_object_attributes(pTemplate, ulCount,
790 &obj_fi.fi_attributes, NULL);
791 if (rv == CKR_OK) {
792 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_INIT,
793 &obj_fi)) < 0) {
794 if (errno != EINTR)
795 break;
797 if (r < 0) {
798 rv = CKR_FUNCTION_FAILED;
799 } else {
800 rv = crypto2pkcs11_error_number(
801 obj_fi.fi_return_value);
805 /* Free the attributes' space allocated for the ioctl call. */
806 free_object_attributes(obj_fi.fi_attributes, ulCount);
808 } else {
809 (void) pthread_mutex_unlock(&session_p->session_mutex);
810 ses_lock_held = B_FALSE;
811 rv = kernel_find_objects_init(session_p, pTemplate, ulCount);
814 if (rv != CKR_OK) {
815 (void) pthread_mutex_lock(&session_p->session_mutex);
816 session_p->find_objects.flags = 0;
817 (void) pthread_mutex_unlock(&session_p->session_mutex);
820 /* decrement the session count, and unlock the mutex */
821 REFRELE(session_p, ses_lock_held);
822 return (rv);
826 CK_RV
827 C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject,
828 CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
830 CK_RV rv = CKR_OK;
831 kernel_slot_t *pslot;
832 kernel_session_t *session_p;
833 boolean_t ses_lock_held = B_FALSE;
834 crypto_object_find_update_t obj_fu;
835 int r;
837 if (!kernel_initialized)
838 return (CKR_CRYPTOKI_NOT_INITIALIZED);
840 /* check for invalid arguments */
841 if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
842 (pulObjectCount == NULL)) {
843 return (CKR_ARGUMENTS_BAD);
846 if (ulMaxObjectCount == 0) {
847 /* don't need to do anything, just return */
848 *pulObjectCount = 0;
849 return (CKR_OK);
853 * Obtain the session pointer. Also, increment the session
854 * reference count.
856 rv = handle2session(sh, &session_p);
857 if (rv != CKR_OK)
858 return (rv);
860 /* Acquire the slot lock */
861 pslot = slot_table[session_p->ses_slotid];
862 (void) pthread_mutex_lock(&pslot->sl_mutex);
864 /* Acquire the session lock */
865 (void) pthread_mutex_lock(&session_p->session_mutex);
866 ses_lock_held = B_TRUE;
868 /* Check to see if find operation is active */
869 if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
870 rv = CKR_OPERATION_NOT_INITIALIZED;
871 goto clean_exit;
875 * Similar to C_FindObjectInit(), if the HW provider supports object
876 * creation, we call the respective ioctl to find objects.
877 * Otherwise, all the objects are created in the library and we do
878 * the find objects solely in the library.
880 if (pslot->sl_func_list.fl_object_create) {
881 obj_fu.fu_session = session_p->k_session;
882 obj_fu.fu_max_count = ulMaxObjectCount;
883 obj_fu.fu_handles = (char *)calloc(1,
884 ulMaxObjectCount * sizeof (crypto_object_id_t));
885 if (obj_fu.fu_handles == NULL) {
886 rv = CKR_HOST_MEMORY;
887 goto clean_exit;
890 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_UPDATE,
891 &obj_fu)) < 0) {
892 if (errno != EINTR)
893 break;
895 if (r < 0) {
896 rv = CKR_FUNCTION_FAILED;
897 } else {
898 rv = crypto2pkcs11_error_number(
899 obj_fu.fu_return_value);
902 if (rv == CKR_OK) {
903 rv = process_found_objects(session_p, phObject,
904 pulObjectCount, obj_fu);
906 free(obj_fu.fu_handles);
908 } else {
910 kernel_find_objects(session_p, phObject, ulMaxObjectCount,
911 pulObjectCount);
912 rv = CKR_OK;
915 clean_exit:
916 /* decrement the session count, and release the session lock */
917 REFRELE(session_p, ses_lock_held);
919 /* release the slot lock */
920 (void) pthread_mutex_unlock(&pslot->sl_mutex);
922 return (rv);
926 CK_RV
927 C_FindObjectsFinal(CK_SESSION_HANDLE sh)
930 kernel_session_t *session_p;
931 CK_RV rv;
932 boolean_t ses_lock_held = B_FALSE;
933 kernel_slot_t *pslot;
934 crypto_object_find_final_t obj_ff;
935 int r;
937 if (!kernel_initialized)
938 return (CKR_CRYPTOKI_NOT_INITIALIZED);
941 * Obtain the session pointer. Also, increment the session
942 * reference count.
944 rv = handle2session(sh, &session_p);
945 if (rv != CKR_OK)
946 return (rv);
948 /* Acquire the session lock */
949 (void) pthread_mutex_lock(&session_p->session_mutex);
950 ses_lock_held = B_TRUE;
952 /* Check to see if find operation is active */
953 if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
954 REFRELE(session_p, ses_lock_held);
955 return (CKR_OPERATION_NOT_INITIALIZED);
959 * Similar to C_FindObjectInit(), if the HW provider supports object
960 * creation, we need to call the CRYPTO_OBJECT_FIND_FINAL ioctl.
962 pslot = slot_table[session_p->ses_slotid];
963 if (pslot->sl_func_list.fl_object_create) {
964 obj_ff.ff_session = session_p->k_session;
965 while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_FINAL,
966 &obj_ff)) < 0) {
967 if (errno != EINTR)
968 break;
970 if (r < 0) {
971 rv = CKR_FUNCTION_FAILED;
972 } else {
973 rv = crypto2pkcs11_error_number(
974 obj_ff.ff_return_value);
977 /* only need to reset find_objects.flags */
978 if (rv == CKR_OK) {
979 session_p->find_objects.flags = 0;
982 } else {
984 * The find object operations were done in the library, we
985 * need to cleanup find_objects context.
987 kernel_find_objects_final(session_p);
988 rv = CKR_OK;
991 /* decrement the session count, and release the lock */
992 REFRELE(session_p, ses_lock_held);
993 return (rv);