4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * Object Management Functions
28 * (as defined in PKCS#11 spec section 11.7)
32 #include "metaGlobal.h"
35 #define FIND_OBJ_BUF_SIZE 512 /* size of buf used for C_FindObjects */
38 * Argument related return codes. Will return to the caller immediately,
39 * and not try the operation on another slot.
41 static CK_RV stop_rv
[] = {
43 CKR_ATTRIBUTE_TYPE_INVALID
,
44 CKR_DOMAIN_PARAMS_INVALID
,
45 CKR_TEMPLATE_INCOMPLETE
47 static int num_stop_rv
= sizeof (stop_rv
) / sizeof (CK_RV
);
50 * Return codes that are related to a specific slot.
51 * Will try to perform the operation in the next available slot.
52 * If all attempts failed, will return the error code from the first slot.
54 * This list is here for reference only, it is commented out because
55 * it doesn't need to be used by the code at this point.
57 * static CK_RV try_again_rv[] = {
61 * CKR_FUNCTION_FAILED,
64 * CKR_TEMPLATE_INCONSISTENT,
65 * CKR_ATTRIBUTE_READ_ONLY,
66 * CKR_ATTRIBUTE_VALUE_INVALID
68 * static int num_try_again_rv = sizeof (try_again_rv) / sizeof (CK_RV);
72 * We should never get these return codes because
73 * MetaSlot is the one that actually created the
74 * sessions. When we get these errors in C_CreateObject,
75 * will try to create the object in the next available slot.
76 * If all attempts failed, will return CKR_FUNCTION_FAILED
79 static CK_RV other_rv
[] = {
80 CKR_CRYPTOKI_NOT_INITIALIZED
,
82 CKR_SESSION_HANDLE_INVALID
,
85 static int num_other_rv
= sizeof (other_rv
) / sizeof (CK_RV
);
88 * This function is only used by the C_CreateObject and C_CopyObject.
90 * It is used to determine if the operation should be tried on another slot
91 * based on the return code
98 for (i
= 0; i
< num_stop_rv
; i
++) {
99 if (rv
== stop_rv
[i
]) {
112 meta_CreateObject(CK_SESSION_HANDLE hSession
, CK_ATTRIBUTE_PTR pTemplate
,
113 CK_ULONG ulCount
, CK_OBJECT_HANDLE_PTR phObject
)
116 meta_session_t
*session
;
117 slot_session_t
*slot_session
= NULL
;
118 meta_object_t
*object
= NULL
;
119 slot_object_t
*slot_object
= NULL
;
120 CK_OBJECT_HANDLE hNewObject
;
121 CK_ULONG slot_num
, keystore_slotnum
;
124 if (pTemplate
== NULL
|| ulCount
< 1 || phObject
== NULL
)
125 return (CKR_ARGUMENTS_BAD
);
127 rv
= meta_handle2session(hSession
, &session
);
131 rv
= meta_object_alloc(session
, &object
);
136 * Create a clone of the object
138 rv
= meta_slot_object_alloc(&slot_object
);
143 * Set to true (token object) if template has CKA_TOKEN=true;
144 * otherwise, it is false (session object).
146 (void) get_template_boolean(CKA_TOKEN
, pTemplate
, ulCount
,
149 /* Can't create token objects in a read-only session. */
150 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) && object
->isToken
) {
151 rv
= CKR_SESSION_READ_ONLY
;
156 * Set to true (private object) if template has CKA_PRIVATE=true;
157 * otherwise, it is false (public object).
159 (void) get_template_boolean(CKA_PRIVATE
, pTemplate
, ulCount
,
160 &(object
->isPrivate
));
162 /* Assume object is extractable unless template has otherwise */
163 object
->isExtractable
= B_TRUE
;
164 (void) get_template_boolean(CKA_EXTRACTABLE
, pTemplate
, ulCount
,
165 &(object
->isExtractable
));
168 * Set to true (sensitive object) if template has CKA_SENSITIVE=true;
169 * otherwise, it is false.
171 (void) get_template_boolean(CKA_SENSITIVE
, pTemplate
, ulCount
,
172 &(object
->isSensitive
));
175 * Check if this can be a FreeObject.
177 * For creating objects, this check is mostly for preventing
178 * non-keystore hardware from creating CKA_PRIVATE objects without
182 if (meta_freeobject_check(session
, object
, NULL
, pTemplate
, ulCount
,
185 * Make sure we are logged into the keystore if this is a
186 * private freetoken object.
188 if (object
->isPrivate
&& !metaslot_logged_in())
189 return (CKR_USER_NOT_LOGGED_IN
);
191 if (!meta_freeobject_set(object
, pTemplate
, ulCount
, B_TRUE
))
196 keystore_slotnum
= get_keystore_slotnum();
198 if (object
->isToken
|| object
->isFreeToken
== FREE_ENABLED
) {
201 * If this is a token object or a FreeToken then create it
202 * on the keystore slot.
205 slot_num
= keystore_slotnum
;
206 rv
= meta_get_slot_session(slot_num
, &slot_session
,
207 session
->session_flags
);
211 object
->tried_create_clone
[slot_num
] = B_TRUE
;
212 rv
= FUNCLIST(slot_session
->fw_st_id
)->C_CreateObject(
213 slot_session
->hSession
, pTemplate
, ulCount
, &hNewObject
);
221 * Create a clone of the object in the first available slot.
223 * If creating a clone in a specific slot failed, it will
224 * either stop and return the error to the user, or try
225 * again in the next available slot until it succeeds. The
226 * decision to stop or continue is made based on the return
229 CK_ULONG num_slots
= meta_slotManager_get_slotcount();
231 for (slot_num
= 0; slot_num
< num_slots
; slot_num
++) {
233 * If this is a free token and we are on the keystore
234 * slot, bypass this because it was already created
237 rv
= meta_get_slot_session(slot_num
, &slot_session
,
238 session
->session_flags
);
242 object
->tried_create_clone
[slot_num
] = B_TRUE
;
243 rv
= FUNCLIST(slot_session
->fw_st_id
)->C_CreateObject(
244 slot_session
->hSession
, pTemplate
, ulCount
,
252 /* save first rv for other errors */
256 meta_release_slot_session(slot_session
);
263 slot_object
->hObject
= hNewObject
;
264 object
->clones
[slot_num
] = slot_object
;
265 object
->master_clone_slotnum
= slot_num
;
267 /* Allow FreeToken to activate onto token obj list */
268 if (object
->isFreeToken
== FREE_ENABLED
)
269 object
->isToken
= B_TRUE
;
271 meta_slot_object_activate(slot_object
, slot_session
,
275 meta_release_slot_session(slot_session
);
280 * return either first error code or
281 * CKR_FUNCTION_FAILED depending on the failure
284 for (i
= 0; i
< num_other_rv
; i
++) {
285 if (rv
== other_rv
[i
]) {
286 rv
= CKR_FUNCTION_FAILED
;
290 /* need to return first rv */
297 * always keep a copy of the template for C_CreateObject,
298 * so clones can be created on other slots if necessary.
299 * This is done even when the CKA_EXTRACTABLE=FALSE flag
300 * is set for the object. The supplied template is
301 * "owned" by metaslot. The application should not be
302 * penalized just because metaslot choose to try creating
303 * the object in a slot that's not capable of performing
304 * any future operation.
306 rv
= get_master_attributes_by_template(pTemplate
, ulCount
,
307 &object
->attributes
, &object
->num_attributes
);
310 for (i
= 0; i
< ulCount
; i
++) {
311 rv
= attribute_set_value(&(pTemplate
[i
]),
312 object
->attributes
, object
->num_attributes
);
316 meta_object_activate(object
);
317 *phObject
= (CK_OBJECT_HANDLE
) object
;
325 meta_slot_object_dealloc(slot_object
);
327 meta_release_slot_session(slot_session
);
329 (void) meta_object_dealloc(session
, object
, B_TRUE
);
342 meta_CopyObject(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
343 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
,
344 CK_OBJECT_HANDLE_PTR phNewObject
)
347 meta_session_t
*session
;
348 meta_object_t
*src_object
, *dst_object
= NULL
;
349 slot_session_t
*slot_session
= NULL
;
350 slot_object_t
*dst_slot_object
= NULL
;
352 slot_object_t
*src_slot_object
;
353 CK_ULONG slotnum
, num_slots
;
356 if (pTemplate
== NULL
&& ulCount
!= 0)
357 return (CKR_ARGUMENTS_BAD
);
358 if (phNewObject
== NULL
)
359 return (CKR_ARGUMENTS_BAD
);
361 rv
= meta_handle2session(hSession
, &session
);
365 rv
= meta_handle2object(hObject
, &src_object
);
371 rv
= meta_object_alloc(session
, &dst_object
);
375 found
= get_template_boolean(CKA_TOKEN
,
376 pTemplate
, ulCount
, &(dst_object
->isToken
));
378 dst_object
->isToken
= src_object
->isToken
;
379 if (src_object
->isFreeToken
== FREE_ENABLED
)
380 dst_object
->isToken
= TRUE
;
382 dst_object
->isToken
= src_object
->isToken
;
385 /* Can't create token objects in a read-only session. */
386 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
387 (dst_object
->isToken
)) {
388 rv
= CKR_SESSION_READ_ONLY
;
392 if (dst_object
->isToken
) {
395 * if the dst object is a token object, and the source
396 * object is not, the source object needs to be extractable.
397 * Otherwise, the source object needs to reside in the
400 if ((!src_object
->isExtractable
) &&
401 (src_object
->master_clone_slotnum
402 != get_keystore_slotnum())) {
403 rv
= CKR_FUNCTION_FAILED
;
407 /* determine if dst is going to be private object or not */
408 found
= get_template_boolean(CKA_PRIVATE
,
409 pTemplate
, ulCount
, &(dst_object
->isPrivate
));
411 /* will be the same as the source object */
412 dst_object
->isPrivate
= src_object
->isPrivate
;
415 slotnum
= get_keystore_slotnum();
418 /* try create the obj in the same slot as the source obj */
419 slotnum
= src_object
->master_clone_slotnum
;
422 rv
= meta_slot_object_alloc(&dst_slot_object
);
426 rv
= meta_get_slot_session(slotnum
, &slot_session
,
427 session
->session_flags
);
431 rv
= meta_object_get_clone(src_object
, slotnum
,
432 slot_session
, &src_slot_object
);
436 dst_object
->tried_create_clone
[slotnum
] = B_TRUE
;
437 rv
= FUNCLIST(slot_session
->fw_st_id
)->C_CopyObject(
438 slot_session
->hSession
, src_slot_object
->hObject
, pTemplate
,
439 ulCount
, &(dst_slot_object
->hObject
));
442 if (dst_object
->isToken
) {
444 * token obj can only be created in the
445 * token slot. No need to try anywhere else
449 if ((!src_object
->isExtractable
) ||
450 ((src_object
->isSensitive
) && (src_object
->isToken
) &&
451 (!metaslot_auto_key_migrate
))) {
452 /* source object isn't clonable in another slot */
456 if (!try_again(rv
)) {
462 meta_release_slot_session(slot_session
);
465 num_slots
= meta_slotManager_get_slotcount();
467 /* Try operation on other slots if the object is clonable */
468 for (slotnum
= 0; slotnum
< num_slots
; slotnum
++) {
470 if (slotnum
== src_object
->master_clone_slotnum
) {
471 /* already tried, don't need to try again */
475 rv
= meta_get_slot_session(slotnum
, &slot_session
,
476 session
->session_flags
);
481 rv
= meta_object_get_clone(src_object
, slotnum
,
482 slot_session
, &src_slot_object
);
486 dst_object
->tried_create_clone
[slotnum
] = B_TRUE
;
488 rv
= FUNCLIST(slot_session
->fw_st_id
)->C_CopyObject(
489 slot_session
->hSession
, src_slot_object
->hObject
,
490 pTemplate
, ulCount
, &dst_slot_object
->hObject
);
496 if (!try_again(rv
)) {
499 meta_release_slot_session(slot_session
);
506 rv
= meta_object_get_attr(slot_session
,
507 dst_slot_object
->hObject
, dst_object
);
512 if (src_object
->attributes
!= NULL
) {
514 /* Keep a copy of the template for the future */
517 * Don't allow attributes to change while
520 (void) pthread_rwlock_rdlock(
521 &src_object
->attribute_lock
);
523 rv
= get_master_attributes_by_duplication(
524 src_object
->attributes
,
525 src_object
->num_attributes
,
526 &dst_object
->attributes
,
527 &dst_object
->num_attributes
);
529 (void) pthread_rwlock_unlock(
530 &src_object
->attribute_lock
);
535 for (i
= 0; i
< ulCount
; i
++) {
536 rv
= attribute_set_value(pTemplate
+ i
,
537 dst_object
->attributes
,
538 dst_object
->num_attributes
);
545 /* Allow FreeToken to activate onto token obj list */
546 if (dst_object
->isFreeToken
== FREE_ENABLED
)
547 dst_object
->isToken
= TRUE
;
549 meta_slot_object_activate(dst_slot_object
,
550 slot_session
, dst_object
->isToken
);
552 dst_object
->clones
[slotnum
] = dst_slot_object
;
553 dst_object
->master_clone_slotnum
= slotnum
;
554 dst_slot_object
= NULL
; /* for error cleanup */
556 meta_release_slot_session(slot_session
);
557 slot_session
= NULL
; /* for error cleanup */
561 * return either first error code or
562 * CKR_FUNCTION_FAILED depending on the failure
565 for (j
= 0; j
< num_other_rv
; j
++) {
566 if (rv
== other_rv
[j
]) {
567 rv
= CKR_FUNCTION_FAILED
;
571 /* need to return first rv */
575 meta_object_activate(dst_object
);
576 *phNewObject
= (CK_OBJECT_HANDLE
) dst_object
;
581 meta_slot_object_dealloc(dst_slot_object
);
584 (void) meta_object_dealloc(session
, dst_object
,
588 meta_release_slot_session(slot_session
);
591 OBJRELEASE(src_object
);
601 * This function destroys an object by first removing it from the
602 * list of valid objects for a given session (if session object) or
603 * the global token object list. And then, calling C_DestroyObject
604 * on all the slots on which we have created a clone of this object.
607 meta_DestroyObject(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
)
610 meta_session_t
*session
;
611 meta_object_t
*object
;
613 rv
= meta_handle2session(hSession
, &session
);
617 rv
= meta_handle2object(hObject
, &object
);
623 /* Can't delete token objects from a read-only session. */
624 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
625 (object
->isToken
|| object
->isFreeToken
== FREE_ENABLED
)) {
628 return (CKR_SESSION_READ_ONLY
);
631 /* Remove object from list of valid meta_objects */
632 rv
= meta_object_deactivate(object
, B_FALSE
, B_TRUE
);
635 * Actually call C_DestroyObject on all the slots on which we have
636 * created a clone of this object.
639 rv
= meta_object_dealloc(session
, object
, B_TRUE
);
651 * 1) Because the "size" is so poorly defined in the spec, we have deemed
652 * it useless and won't support it. This is especially true for the
653 * metaslot, because the mulitple providers it uses may each interpret
654 * the size differently.
658 meta_GetObjectSize(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
659 CK_ULONG_PTR pulSize
)
661 return (CKR_FUNCTION_NOT_SUPPORTED
);
666 * meta_GetAttributeValue
670 meta_GetAttributeValue(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
671 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
)
674 meta_session_t
*session
;
675 meta_object_t
*object
;
677 slot_session_t
*slot_session
;
679 if (pTemplate
== NULL
|| ulCount
< 1)
680 return (CKR_ARGUMENTS_BAD
);
682 rv
= meta_handle2session(hSession
, &session
);
686 rv
= meta_handle2object(hObject
, &object
);
692 slotnum
= object
->master_clone_slotnum
;
694 rv
= meta_get_slot_session(slotnum
, &slot_session
,
695 session
->session_flags
);
697 rv
= FUNCLIST(slot_session
->fw_st_id
)->C_GetAttributeValue(
698 slot_session
->hSession
, object
->clones
[slotnum
]->hObject
,
701 meta_release_slot_session(slot_session
);
713 * meta_SetAttributeValue
715 * Call C_SetAttributeValue on all the clones. If the operation fails on
716 * all clones, return the failure.
718 * If the operation fails on some clones and not the others, delete all the
719 * clones that have failed the operation. If any of the deleted clone is the
720 * master clone, use one of the remaining clone as the master clone.
722 * If the operation is successful and the master template already exists,
723 * update the master template with new values.
726 meta_SetAttributeValue(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE hObject
,
727 CK_ATTRIBUTE_PTR pTemplate
, CK_ULONG ulCount
)
729 CK_RV rv
= CKR_OK
, save_rv
= CKR_OK
;
730 meta_session_t
*session
;
731 meta_object_t
*object
;
732 CK_ULONG slotnum
, num_slots
;
733 /* Keep track of which slot's SetAttributeValue failed */
734 boolean_t
*clone_failed_op
= NULL
;
735 int num_clones
= 0, num_clones_failed
= 0;
736 slot_session_t
*slot_session
;
737 slot_object_t
*slot_object
;
738 boolean_t need_update_master_clone
= B_FALSE
;
740 if (pTemplate
== NULL
|| ulCount
< 1)
741 return (CKR_ARGUMENTS_BAD
);
743 rv
= meta_handle2session(hSession
, &session
);
747 rv
= meta_handle2object(hObject
, &object
);
753 if ((IS_READ_ONLY_SESSION(session
->session_flags
)) &&
754 (object
->isToken
|| object
->isFreeToken
== FREE_ENABLED
)) {
755 rv
= CKR_SESSION_READ_ONLY
;
759 if ((!object
->isExtractable
) && (object
->attributes
== NULL
)) {
761 * object has no clone, just need to do the operation
762 * in the master clone slot
764 slot_session_t
*slot_session
;
765 slotnum
= object
->master_clone_slotnum
;
767 rv
= meta_get_slot_session(slotnum
, &slot_session
,
768 session
->session_flags
);
770 rv
= FUNCLIST(slot_session
->fw_st_id
)->\
771 C_SetAttributeValue(slot_session
->hSession
,
772 object
->clones
[slotnum
]->hObject
, pTemplate
,
775 meta_release_slot_session(slot_session
);
781 num_slots
= meta_slotManager_get_slotcount();
784 * object might have clones, need to do operation in all clones
786 * If the C_SetAttributeValue() call fails in a clone, the
787 * clone that failed the operation can not be deleted right
788 * away. The clone with the failed operation is recorded, and
789 * the deletion will happen in a separate loop.
791 * This is necessary because if ALL the clones failed
792 * C_SetAttributeVAlue(), then, the app's call to C_SetAttributeValue()
793 * is considered failed, and there shouldn't be any changes to the
794 * object, none of the clones should be deleted.
795 * On the other hand, if C_SetAttributeValue() fails in some clones
796 * and succeeds in other clones, the C_SetAttributeValue() operation
797 * is considered successful, and those clones that failed the
798 * operation is deleted.
800 clone_failed_op
= calloc(num_slots
, sizeof (boolean_t
));
801 if (clone_failed_op
== NULL
) {
802 rv
= CKR_HOST_MEMORY
;
805 for (slotnum
= 0; slotnum
< num_slots
; slotnum
++) {
806 if (object
->clones
[slotnum
] != NULL
) {
808 rv
= meta_get_slot_session(slotnum
, &slot_session
,
809 session
->session_flags
);
814 rv
= FUNCLIST(slot_session
->fw_st_id
)->\
815 C_SetAttributeValue(slot_session
->hSession
,
816 object
->clones
[slotnum
]->hObject
, pTemplate
,
821 clone_failed_op
[slotnum
] = B_TRUE
;
822 if (save_rv
== CKR_OK
) {
826 meta_release_slot_session(slot_session
);
830 if (num_clones_failed
== num_clones
) {
831 /* all operations failed */
836 if (num_clones_failed
> 0) {
838 * C_SetAttributeValue in some of the clones failed.
839 * Find out which ones failed, and delete the clones
840 * in those failed slots
842 for (slotnum
= 0; slotnum
< num_slots
; slotnum
++) {
843 if (clone_failed_op
[slotnum
]) {
845 slot_object_t
*clone
= object
->clones
[slotnum
];
847 rv
= meta_get_slot_session(slotnum
,
848 &slot_session
, session
->session_flags
);
851 slot_session
->fw_st_id
)->
853 slot_session
->hSession
,
856 meta_release_slot_session(slot_session
);
860 meta_slot_object_deactivate(clone
);
861 meta_slot_object_dealloc(clone
);
862 object
->clones
[slotnum
] = NULL
;
864 if (slotnum
== object
->master_clone_slotnum
) {
865 need_update_master_clone
= B_TRUE
;
870 if (need_update_master_clone
) {
871 /* make first available clone the master */
872 for (slotnum
= 0; slotnum
< num_slots
; slotnum
++) {
873 if (object
->clones
[slotnum
]) {
874 object
->master_clone_slotnum
= slotnum
;
875 need_update_master_clone
= B_FALSE
;
881 if (need_update_master_clone
) {
883 * something is very wrong, can't continue
884 * it should never be this case.
886 rv
= CKR_FUNCTION_FAILED
;
893 * Update the attribute information we keep in our metaslot object
895 slot_object
= object
->clones
[object
->master_clone_slotnum
];
896 rv
= meta_get_slot_session(object
->master_clone_slotnum
,
897 &slot_session
, session
->session_flags
);
899 (void) meta_object_get_attr(slot_session
,
900 slot_object
->hObject
, object
);
901 meta_release_slot_session(slot_session
);
904 /* if there's a copy of the attributes, keep it up to date */
905 if (object
->attributes
!= NULL
) {
909 /* Make sure no one else is looking at attributes. */
910 (void) pthread_rwlock_wrlock(&object
->attribute_lock
);
912 for (i
= 0; i
< ulCount
; i
++) {
913 (void) attribute_set_value(pTemplate
+ i
,
914 object
->attributes
, object
->num_attributes
);
917 (void) pthread_rwlock_unlock(&object
->attribute_lock
);
921 if (clone_failed_op
) {
922 free(clone_failed_op
);
931 meta_object_in_list(meta_object_t
*obj
, meta_object_t
**objs_list
, int num_objs
)
935 for (i
= 0; i
< num_objs
; i
++) {
936 if (objs_list
[i
] == obj
) {
944 add_to_search_result(meta_object_t
*object
, find_objs_info_t
*info
,
945 int *num_results_alloc
)
948 * allocate space for storing results if the currently
949 * allocated space is not enough
951 if (*num_results_alloc
<= info
->num_matched_objs
) {
952 *num_results_alloc
+= FIND_OBJ_BUF_SIZE
;
953 info
->matched_objs
= reallocarray(info
->matched_objs
,
954 *num_results_alloc
, sizeof (meta_object_t
*));
955 if (info
->matched_objs
== NULL
) {
956 return (CKR_HOST_MEMORY
);
959 (info
->matched_objs
)[(info
->num_matched_objs
)++] = object
;
964 process_find_results(CK_OBJECT_HANDLE
*results
, CK_ULONG num_results
,
965 int *num_results_allocated
, find_objs_info_t
*info
, CK_ULONG slotnum
,
966 boolean_t token_only
, slot_session_t
*slot_session
,
967 meta_session_t
*session
)
970 meta_object_t
*object
;
973 for (i
= 0; i
< num_results
; i
++) {
975 object
= meta_object_find_by_handle(results
[i
], slotnum
,
979 * a token object is found from the keystore,
980 * need to create a meta object for it
982 if (object
== NULL
) {
983 slot_object_t
*slot_object
;
985 rv
= meta_object_alloc(session
, &object
);
990 rv
= meta_slot_object_alloc(&slot_object
);
992 (void) meta_object_dealloc(session
, object
,
997 slot_object
->hObject
= results
[i
];
998 object
->master_clone_slotnum
= slotnum
;
999 object
->clones
[slotnum
] = slot_object
;
1001 /* get in the attributes we keep in meta_object */
1003 rv
= meta_object_get_attr(slot_session
,
1004 slot_object
->hObject
, object
);
1006 (void) meta_object_dealloc(session
, object
,
1011 meta_slot_object_activate(slot_object
, slot_session
,
1013 meta_object_activate(object
);
1017 if (!meta_object_in_list(object
, info
->matched_objs
,
1018 info
->num_matched_objs
)) {
1019 rv
= add_to_search_result(object
, info
,
1020 num_results_allocated
);
1030 meta_search_for_objects(meta_session_t
*session
, find_objs_info_t
*info
,
1031 slot_session_t
*slot_session
, CK_ATTRIBUTE_PTR pTemplate
,
1032 CK_ULONG ulCount
, CK_ULONG slotnum
, boolean_t token_only
,
1033 int *num_results_alloc
)
1035 CK_ULONG tmp_num_results
;
1036 CK_OBJECT_HANDLE tmp_results
[FIND_OBJ_BUF_SIZE
];
1037 CK_SESSION_HANDLE hSession
= slot_session
->hSession
;
1039 CK_SLOT_ID fw_st_id
= slot_session
->fw_st_id
;
1041 rv
= FUNCLIST(fw_st_id
)->C_FindObjectsInit(hSession
,
1042 pTemplate
, ulCount
);
1048 tmp_num_results
= 0;
1049 rv
= FUNCLIST(fw_st_id
)->C_FindObjects(hSession
, tmp_results
,
1050 FIND_OBJ_BUF_SIZE
, &tmp_num_results
);
1055 rv
= process_find_results(tmp_results
, tmp_num_results
,
1056 num_results_alloc
, info
, slotnum
, token_only
,
1057 slot_session
, session
);
1062 while (tmp_num_results
== FIND_OBJ_BUF_SIZE
) {
1063 /* might be more results, need to call C_FindObjects again */
1064 rv
= FUNCLIST(fw_st_id
)->C_FindObjects(hSession
, tmp_results
,
1065 FIND_OBJ_BUF_SIZE
, &tmp_num_results
);
1070 rv
= process_find_results(tmp_results
, tmp_num_results
,
1071 num_results_alloc
, info
, slotnum
, token_only
,
1072 slot_session
, session
);
1078 rv
= FUNCLIST(fw_st_id
)->C_FindObjectsFinal(hSession
);
1084 * meta_FindObjectsInit
1086 * This function actually will do ALL the work of searching for objects
1087 * that match all requirements specified in the template.
1089 * Objects that matched the template will be stored in the
1090 * session's data structure. When the subsequent C_FindObjects()
1091 * calls are made, results saved will be returned.
1095 meta_FindObjectsInit(CK_SESSION_HANDLE hSession
, CK_ATTRIBUTE_PTR pTemplate
,
1099 meta_session_t
*session
;
1100 CK_ULONG slot_num
= 0;
1101 boolean_t have_token_attr
, tokenTrue
= B_FALSE
;
1102 slot_session_t
*slot_find_session
= NULL
;
1103 int num_results_allocated
= 0;
1104 CK_ULONG keystore_slotnum
;
1106 rv
= meta_handle2session(hSession
, &session
);
1110 if ((session
->find_objs_info
).op_active
) {
1111 REFRELEASE(session
);
1112 return (CKR_OPERATION_ACTIVE
);
1115 (session
->find_objs_info
).op_active
= B_TRUE
;
1117 REFRELEASE(session
);
1119 /* see if the template indicates token object only or not */
1120 have_token_attr
= get_template_boolean(CKA_TOKEN
, pTemplate
, ulCount
,
1123 keystore_slotnum
= get_keystore_slotnum();
1125 if (have_token_attr
&& tokenTrue
) {
1129 * only interested in token objects, just need to search
1132 rv
= meta_get_slot_session(keystore_slotnum
,
1133 &slot_find_session
, session
->session_flags
);
1137 rv
= meta_search_for_objects(session
,
1138 &(session
->find_objs_info
), slot_find_session
, pTemplate
,
1139 ulCount
, keystore_slotnum
, B_TRUE
, &num_results_allocated
);
1144 CK_ULONG num_slots
= meta_slotManager_get_slotcount();
1145 for (slot_num
= 0; slot_num
< num_slots
; slot_num
++) {
1146 rv
= meta_get_slot_session(slot_num
,
1147 &slot_find_session
, session
->session_flags
);
1153 * if the slot is NOT the token object slot, and
1154 * CKA_TOKEN is not specified, need to specified
1155 * it to be false explicitly. This will prevent
1156 * us from using token objects that doesn't
1157 * belong to the token slot in the case that
1158 * more than one slot supports token objects.
1161 if ((slot_num
!= keystore_slotnum
) &&
1162 (!have_token_attr
)) {
1163 CK_BBOOL
false = FALSE
;
1164 CK_ATTRIBUTE_PTR newTemplate
;
1166 newTemplate
= malloc((ulCount
+ 1) *
1167 sizeof (CK_ATTRIBUTE
));
1168 if (newTemplate
== NULL
) {
1169 rv
= CKR_HOST_MEMORY
;
1172 (void) memcpy(newTemplate
+ 1, pTemplate
,
1173 ulCount
* sizeof (CK_ATTRIBUTE
));
1174 newTemplate
[0].type
= CKA_TOKEN
;
1175 newTemplate
[0].pValue
= &false;
1176 newTemplate
[0].ulValueLen
= sizeof (false);
1178 rv
= meta_search_for_objects(session
,
1179 &(session
->find_objs_info
),
1180 slot_find_session
, newTemplate
,
1181 ulCount
+1, slot_num
, B_FALSE
,
1182 &num_results_allocated
);
1185 rv
= meta_search_for_objects(session
,
1186 &(session
->find_objs_info
),
1187 slot_find_session
, pTemplate
, ulCount
,
1189 &num_results_allocated
);
1195 meta_release_slot_session(slot_find_session
);
1196 slot_find_session
= NULL
;
1201 if (slot_find_session
!= NULL
) {
1202 meta_release_slot_session(slot_find_session
);
1205 (void) pthread_rwlock_wrlock(&session
->session_lock
);
1206 if (((session
->find_objs_info
).matched_objs
) != NULL
) {
1207 free((session
->find_objs_info
).matched_objs
);
1209 bzero(&(session
->find_objs_info
), sizeof (find_objs_info_t
));
1210 (void) pthread_rwlock_unlock(&(session
->session_lock
));
1219 * This function actually doesn't do any real work in search for the
1220 * matching object. All the work is done in FindObjectsInit(). This
1221 * function will only return the matching objects store in the session's
1222 * "find_objs_info" variable.
1226 meta_FindObjects(CK_SESSION_HANDLE hSession
, CK_OBJECT_HANDLE_PTR phObject
,
1227 CK_ULONG ulMaxObjectCount
, CK_ULONG_PTR pulObjectCount
)
1230 find_objs_info_t
*info
;
1231 CK_ULONG num_objs_found
= 0;
1233 meta_session_t
*session
;
1236 rv
= meta_handle2session(hSession
, &session
);
1240 info
= &(session
->find_objs_info
);
1242 if (!(info
->op_active
)) {
1243 REFRELEASE(session
);
1244 return (CKR_OPERATION_NOT_INITIALIZED
);
1247 for (i
= info
->next_result_index
;
1248 ((num_objs_found
< ulMaxObjectCount
) &&
1249 (i
< info
->num_matched_objs
));
1251 obj
= info
->matched_objs
[i
];
1253 /* sanity check to see if object is still valid */
1254 (void) pthread_rwlock_rdlock(&obj
->object_lock
);
1255 if (obj
->magic_marker
== METASLOT_OBJECT_MAGIC
) {
1256 phObject
[num_objs_found
++] =
1257 (CK_OBJECT_HANDLE
)obj
;
1259 (void) pthread_rwlock_unlock(&obj
->object_lock
);
1262 info
->next_result_index
= i
;
1263 *pulObjectCount
= num_objs_found
;
1264 REFRELEASE(session
);
1270 * meta_FindObjectsFinal
1274 meta_FindObjectsFinal(CK_SESSION_HANDLE hSession
)
1277 find_objs_info_t
*info
;
1278 meta_session_t
*session
;
1280 rv
= meta_handle2session(hSession
, &session
);
1284 info
= &(session
->find_objs_info
);
1286 if (!info
->op_active
) {
1287 REFRELEASE(session
);
1288 return (CKR_OPERATION_NOT_INITIALIZED
);
1291 if (info
->matched_objs
) {
1292 free(info
->matched_objs
);
1295 bzero(info
, sizeof (find_objs_info_t
));
1296 REFRELEASE(session
);