17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5034448feSmcpowers  * Common Development and Distribution License (the "License").
6034448feSmcpowers  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
228cae6764SAnthony Scarpino  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate /*
277c478bd9Sstevel@tonic-gate  * Object Management Functions
287c478bd9Sstevel@tonic-gate  * (as defined in PKCS#11 spec section 11.7)
297c478bd9Sstevel@tonic-gate  */
307c478bd9Sstevel@tonic-gate 
317c478bd9Sstevel@tonic-gate #include <strings.h>
327c478bd9Sstevel@tonic-gate #include "metaGlobal.h"
337c478bd9Sstevel@tonic-gate #include <stdio.h>
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate #define	FIND_OBJ_BUF_SIZE	512	/* size of buf used for C_FindObjects */
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * Argument related return codes. Will return to the caller immediately,
397c478bd9Sstevel@tonic-gate  * and not try the operation on another slot.
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate static CK_RV stop_rv[] = {
427c478bd9Sstevel@tonic-gate 	CKR_ARGUMENTS_BAD,
437c478bd9Sstevel@tonic-gate 	CKR_ATTRIBUTE_TYPE_INVALID,
447c478bd9Sstevel@tonic-gate 	CKR_DOMAIN_PARAMS_INVALID,
457c478bd9Sstevel@tonic-gate 	CKR_TEMPLATE_INCOMPLETE
467c478bd9Sstevel@tonic-gate };
477c478bd9Sstevel@tonic-gate static int num_stop_rv = sizeof (stop_rv) / sizeof (CK_RV);
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate /*
507c478bd9Sstevel@tonic-gate  * Return codes that are related to a specific slot.
517c478bd9Sstevel@tonic-gate  * Will try to perform the operation in the next available slot.
527c478bd9Sstevel@tonic-gate  * If all attempts failed, will return the error code from the first slot.
537c478bd9Sstevel@tonic-gate  *
547c478bd9Sstevel@tonic-gate  * This list is here for reference only, it is commented out because
557c478bd9Sstevel@tonic-gate  * it doesn't need to be used by the code at this point.
567c478bd9Sstevel@tonic-gate  *
577c478bd9Sstevel@tonic-gate  * static CK_RV try_again_rv[] = {
587c478bd9Sstevel@tonic-gate  *	CKR_DEVICE_ERROR,
597c478bd9Sstevel@tonic-gate  *	CKR_DEVICE_MEMORY,
607c478bd9Sstevel@tonic-gate  *	CKR_DEVICE_REMOVED,
617c478bd9Sstevel@tonic-gate  *	CKR_FUNCTION_FAILED,
627c478bd9Sstevel@tonic-gate  *	CKR_GENERAL_ERROR,
637c478bd9Sstevel@tonic-gate  *	CKR_HOST_MEMORY,
647c478bd9Sstevel@tonic-gate  *	CKR_TEMPLATE_INCONSISTENT,
657c478bd9Sstevel@tonic-gate  *	CKR_ATTRIBUTE_READ_ONLY,
667c478bd9Sstevel@tonic-gate  *	CKR_ATTRIBUTE_VALUE_INVALID
677c478bd9Sstevel@tonic-gate  * };
687c478bd9Sstevel@tonic-gate  * static int num_try_again_rv = sizeof (try_again_rv) / sizeof (CK_RV);
697c478bd9Sstevel@tonic-gate  */
707c478bd9Sstevel@tonic-gate 
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate  * We should never get these return codes because
737c478bd9Sstevel@tonic-gate  * MetaSlot is the one that actually created the
747c478bd9Sstevel@tonic-gate  * sessions.  When we get these errors in C_CreateObject,
757c478bd9Sstevel@tonic-gate  * will try to create the object in the next available slot.
767c478bd9Sstevel@tonic-gate  * If all attempts failed, will return CKR_FUNCTION_FAILED
777c478bd9Sstevel@tonic-gate  * to the caller.
787c478bd9Sstevel@tonic-gate  */
797c478bd9Sstevel@tonic-gate static CK_RV other_rv[] = {
807c478bd9Sstevel@tonic-gate 	CKR_CRYPTOKI_NOT_INITIALIZED,
817c478bd9Sstevel@tonic-gate 	CKR_SESSION_CLOSED,
827c478bd9Sstevel@tonic-gate 	CKR_SESSION_HANDLE_INVALID,
837c478bd9Sstevel@tonic-gate 	CKR_SESSION_READ_ONLY
847c478bd9Sstevel@tonic-gate };
857c478bd9Sstevel@tonic-gate static int num_other_rv = sizeof (other_rv) / sizeof (CK_RV);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate /*
887c478bd9Sstevel@tonic-gate  * This function is only used by the C_CreateObject and C_CopyObject.
897c478bd9Sstevel@tonic-gate  *
907c478bd9Sstevel@tonic-gate  * It is used to determine if the operation should be tried on another slot
917c478bd9Sstevel@tonic-gate  * based on the return code
927c478bd9Sstevel@tonic-gate  */
937c478bd9Sstevel@tonic-gate static boolean_t
try_again(CK_RV rv)947c478bd9Sstevel@tonic-gate try_again(CK_RV rv)
957c478bd9Sstevel@tonic-gate {
967c478bd9Sstevel@tonic-gate 	int i;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_stop_rv; i++) {
997c478bd9Sstevel@tonic-gate 		if (rv == stop_rv[i]) {
1007c478bd9Sstevel@tonic-gate 			return (B_FALSE);
1017c478bd9Sstevel@tonic-gate 		}
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 	return (B_TRUE);
1047c478bd9Sstevel@tonic-gate }
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate /*
1087c478bd9Sstevel@tonic-gate  * meta_CreateObject
1097c478bd9Sstevel@tonic-gate  *
1107c478bd9Sstevel@tonic-gate  */
1117c478bd9Sstevel@tonic-gate CK_RV
meta_CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject)1127c478bd9Sstevel@tonic-gate meta_CreateObject(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
1137c478bd9Sstevel@tonic-gate     CK_ULONG ulCount, CK_OBJECT_HANDLE_PTR phObject)
1147c478bd9Sstevel@tonic-gate {
1157c478bd9Sstevel@tonic-gate 	CK_RV rv;
1167c478bd9Sstevel@tonic-gate 	meta_session_t *session;
1177c478bd9Sstevel@tonic-gate 	slot_session_t *slot_session = NULL;
1187c478bd9Sstevel@tonic-gate 	meta_object_t *object = NULL;
1197c478bd9Sstevel@tonic-gate 	slot_object_t *slot_object = NULL;
120034448feSmcpowers 	CK_OBJECT_HANDLE hNewObject;
121034448feSmcpowers 	CK_ULONG slot_num, keystore_slotnum;
122034448feSmcpowers 	CK_RV first_rv;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 	if (pTemplate == NULL || ulCount < 1 || phObject == NULL)
1257c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
1267c478bd9Sstevel@tonic-gate 
1277c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
1287c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1297c478bd9Sstevel@tonic-gate 		return (rv);
1307c478bd9Sstevel@tonic-gate 
1317c478bd9Sstevel@tonic-gate 	rv = meta_object_alloc(session, &object);
1327c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1337c478bd9Sstevel@tonic-gate 		goto cleanup;
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 	/*
1367c478bd9Sstevel@tonic-gate 	 * Create a clone of the object
1377c478bd9Sstevel@tonic-gate 	 */
1387c478bd9Sstevel@tonic-gate 	rv = meta_slot_object_alloc(&slot_object);
1397c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1407c478bd9Sstevel@tonic-gate 		goto cleanup;
1417c478bd9Sstevel@tonic-gate 
142034448feSmcpowers 	/*
143034448feSmcpowers 	 * Set to true (token object) if template has CKA_TOKEN=true;
144034448feSmcpowers 	 * otherwise, it is false (session object).
145034448feSmcpowers 	 */
1467c478bd9Sstevel@tonic-gate 	(void) get_template_boolean(CKA_TOKEN, pTemplate, ulCount,
1477c478bd9Sstevel@tonic-gate 	    &(object->isToken));
1487c478bd9Sstevel@tonic-gate 
1495b0c7657Sizick 	/* Can't create token objects in a read-only session. */
1505b0c7657Sizick 	if ((IS_READ_ONLY_SESSION(session->session_flags)) && object->isToken) {
1515b0c7657Sizick 		rv = CKR_SESSION_READ_ONLY;
1525b0c7657Sizick 		goto cleanup;
1535b0c7657Sizick 	}
1545b0c7657Sizick 
155034448feSmcpowers 	/*
156034448feSmcpowers 	 * Set to true (private object) if template has CKA_PRIVATE=true;
157034448feSmcpowers 	 * otherwise, it is false (public object).
158034448feSmcpowers 	 */
159034448feSmcpowers 	(void) get_template_boolean(CKA_PRIVATE, pTemplate, ulCount,
160034448feSmcpowers 	    &(object->isPrivate));
161034448feSmcpowers 
162034448feSmcpowers 	/* Assume object is extractable unless template has otherwise */
163034448feSmcpowers 	object->isExtractable = B_TRUE;
164034448feSmcpowers 	(void) get_template_boolean(CKA_EXTRACTABLE, pTemplate, ulCount,
165034448feSmcpowers 	    &(object->isExtractable));
166034448feSmcpowers 
167034448feSmcpowers 	/*
168034448feSmcpowers 	 * Set to true (sensitive object) if template has CKA_SENSITIVE=true;
169034448feSmcpowers 	 * otherwise, it is false.
170034448feSmcpowers 	 */
171034448feSmcpowers 	(void) get_template_boolean(CKA_SENSITIVE, pTemplate, ulCount,
172034448feSmcpowers 	    &(object->isSensitive));
173034448feSmcpowers 
174034448feSmcpowers 	/*
175034448feSmcpowers 	 * Check if this can be a FreeObject.
176034448feSmcpowers 	 *
177034448feSmcpowers 	 * For creating objects, this check is mostly for preventing
178034448feSmcpowers 	 * non-keystore hardware from creating CKA_PRIVATE objects without
179034448feSmcpowers 	 * logging in.
180034448feSmcpowers 	 */
181034448feSmcpowers 
182034448feSmcpowers 	if (meta_freeobject_check(session, object, NULL, pTemplate, ulCount,
183*07eb1aefSToomas Soome 	    0)) {
184034448feSmcpowers 		/*
185034448feSmcpowers 		 * Make sure we are logged into the keystore if this is a
186034448feSmcpowers 		 * private freetoken object.
187034448feSmcpowers 		 */
188034448feSmcpowers 		if (object->isPrivate && !metaslot_logged_in())
189034448feSmcpowers 			return (CKR_USER_NOT_LOGGED_IN);
190034448feSmcpowers 
191034448feSmcpowers 		if (!meta_freeobject_set(object, pTemplate, ulCount, B_TRUE))
192034448feSmcpowers 			goto cleanup;
193034448feSmcpowers 	}
194034448feSmcpowers 
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	keystore_slotnum = get_keystore_slotnum();
1977c478bd9Sstevel@tonic-gate 
198034448feSmcpowers 	if (object->isToken || object->isFreeToken == FREE_ENABLED) {
199034448feSmcpowers 
200034448feSmcpowers 		/*
201034448feSmcpowers 		 * If this is a token object or a FreeToken then create it
202034448feSmcpowers 		 * on the keystore slot.
203034448feSmcpowers 		 */
204034448feSmcpowers 
205034448feSmcpowers 		slot_num = keystore_slotnum;
206034448feSmcpowers 		rv = meta_get_slot_session(slot_num, &slot_session,
2077c478bd9Sstevel@tonic-gate 		    session->session_flags);
2087c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
2097c478bd9Sstevel@tonic-gate 			goto cleanup;
2107c478bd9Sstevel@tonic-gate 
211034448feSmcpowers 		object->tried_create_clone[slot_num] = B_TRUE;
2127c478bd9Sstevel@tonic-gate 		rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject(
2135b0c7657Sizick 		    slot_session->hSession, pTemplate, ulCount, &hNewObject);
214034448feSmcpowers 
215034448feSmcpowers 		if (rv != CKR_OK)
2167c478bd9Sstevel@tonic-gate 			goto cleanup;
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 	} else {
2197c478bd9Sstevel@tonic-gate 
2207c478bd9Sstevel@tonic-gate 		/*
2217c478bd9Sstevel@tonic-gate 		 * Create a clone of the object in the first available slot.
2227c478bd9Sstevel@tonic-gate 		 *
2237c478bd9Sstevel@tonic-gate 		 * If creating a clone in a specific slot failed, it will
2247c478bd9Sstevel@tonic-gate 		 * either stop and return the error to the user, or try
2257c478bd9Sstevel@tonic-gate 		 * again in the next available slot until it succeeds.  The
2267c478bd9Sstevel@tonic-gate 		 * decision to stop or continue is made based on the return
2277c478bd9Sstevel@tonic-gate 		 * code.
2287c478bd9Sstevel@tonic-gate 		 */
229034448feSmcpowers 		CK_ULONG num_slots = meta_slotManager_get_slotcount();
2307c478bd9Sstevel@tonic-gate 
2317c478bd9Sstevel@tonic-gate 		for (slot_num = 0; slot_num < num_slots; slot_num++) {
232034448feSmcpowers 			/*
233034448feSmcpowers 			 * If this is a free token and we are on the keystore
234034448feSmcpowers 			 * slot, bypass this because it was already created
235034448feSmcpowers 			 */
236034448feSmcpowers 
2377c478bd9Sstevel@tonic-gate 			rv = meta_get_slot_session(slot_num, &slot_session,
2387c478bd9Sstevel@tonic-gate 			    session->session_flags);
239034448feSmcpowers 			if (rv != CKR_OK)
2407c478bd9Sstevel@tonic-gate 				goto cleanup;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 			object->tried_create_clone[slot_num] = B_TRUE;
2437c478bd9Sstevel@tonic-gate 			rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject(
2447c478bd9Sstevel@tonic-gate 			    slot_session->hSession, pTemplate, ulCount,
2457c478bd9Sstevel@tonic-gate 			    &hNewObject);
246034448feSmcpowers 			if (rv == CKR_OK)
2477c478bd9Sstevel@tonic-gate 				break;
2487c478bd9Sstevel@tonic-gate 
249034448feSmcpowers 			if (!try_again(rv))
2507c478bd9Sstevel@tonic-gate 				goto cleanup;
2517c478bd9Sstevel@tonic-gate 
2527c478bd9Sstevel@tonic-gate 			/* save first rv for other errors */
253034448feSmcpowers 			if (slot_num == 0)
2547c478bd9Sstevel@tonic-gate 				first_rv = rv;
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 			meta_release_slot_session(slot_session);
2577c478bd9Sstevel@tonic-gate 			slot_session = NULL;
2587c478bd9Sstevel@tonic-gate 
2597c478bd9Sstevel@tonic-gate 		}
260034448feSmcpowers 	}
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
2637c478bd9Sstevel@tonic-gate 		slot_object->hObject = hNewObject;
2647c478bd9Sstevel@tonic-gate 		object->clones[slot_num] = slot_object;
2657c478bd9Sstevel@tonic-gate 		object->master_clone_slotnum = slot_num;
266034448feSmcpowers 
2678cae6764SAnthony Scarpino 		/* Allow FreeToken to activate onto token obj list */
2688cae6764SAnthony Scarpino 		if (object->isFreeToken == FREE_ENABLED)
2698cae6764SAnthony Scarpino 			object->isToken = B_TRUE;
2708cae6764SAnthony Scarpino 
2718cae6764SAnthony Scarpino 		meta_slot_object_activate(slot_object, slot_session,
2728cae6764SAnthony Scarpino 		    object->isToken);
273034448feSmcpowers 
2747c478bd9Sstevel@tonic-gate 		slot_object = NULL;
2757c478bd9Sstevel@tonic-gate 		meta_release_slot_session(slot_session);
2767c478bd9Sstevel@tonic-gate 		slot_session = NULL;
277034448feSmcpowers 
2787c478bd9Sstevel@tonic-gate 	} else {
2797c478bd9Sstevel@tonic-gate 		/*
2807c478bd9Sstevel@tonic-gate 		 * return either first error code or
2817c478bd9Sstevel@tonic-gate 		 * CKR_FUNCTION_FAILED depending on the failure
2827c478bd9Sstevel@tonic-gate 		 */
2837c478bd9Sstevel@tonic-gate 		int i;
2847c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_other_rv; i++) {
2857c478bd9Sstevel@tonic-gate 			if (rv == other_rv[i]) {
2867c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
2877c478bd9Sstevel@tonic-gate 				goto cleanup;
2887c478bd9Sstevel@tonic-gate 			}
2897c478bd9Sstevel@tonic-gate 		}
2907c478bd9Sstevel@tonic-gate 		/* need to return first rv */
2917c478bd9Sstevel@tonic-gate 		rv = first_rv;
2927c478bd9Sstevel@tonic-gate 		goto cleanup;
2937c478bd9Sstevel@tonic-gate 	}
2947c478bd9Sstevel@tonic-gate 
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	/*
2977c478bd9Sstevel@tonic-gate 	 * always keep a copy of the template for C_CreateObject,
2987c478bd9Sstevel@tonic-gate 	 * so clones can be created on other slots if necessary.
2997c478bd9Sstevel@tonic-gate 	 * This is done even when the CKA_EXTRACTABLE=FALSE flag
3007c478bd9Sstevel@tonic-gate 	 * is set for the object.  The supplied template is
3017c478bd9Sstevel@tonic-gate 	 * "owned" by metaslot.  The application should not be
3027c478bd9Sstevel@tonic-gate 	 * penalized just because metaslot choose to try creating
3037c478bd9Sstevel@tonic-gate 	 * the object in a slot that's not capable of performing
3047c478bd9Sstevel@tonic-gate 	 * any future operation.
3057c478bd9Sstevel@tonic-gate 	 */
3067c478bd9Sstevel@tonic-gate 	rv = get_master_attributes_by_template(pTemplate, ulCount,
3077c478bd9Sstevel@tonic-gate 	    &object->attributes, &object->num_attributes);
3087c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
3097c478bd9Sstevel@tonic-gate 		CK_ULONG i;
3107c478bd9Sstevel@tonic-gate 		for (i = 0; i < ulCount; i++) {
3117c478bd9Sstevel@tonic-gate 			rv = attribute_set_value(&(pTemplate[i]),
3127c478bd9Sstevel@tonic-gate 			    object->attributes, object->num_attributes);
3137c478bd9Sstevel@tonic-gate 		}
3147c478bd9Sstevel@tonic-gate 	}
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	meta_object_activate(object);
3177c478bd9Sstevel@tonic-gate 	*phObject = (CK_OBJECT_HANDLE) object;
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate 	return (CKR_OK);
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate cleanup:
3247c478bd9Sstevel@tonic-gate 	if (slot_object)
3257c478bd9Sstevel@tonic-gate 		meta_slot_object_dealloc(slot_object);
3267c478bd9Sstevel@tonic-gate 	if (slot_session)
3277c478bd9Sstevel@tonic-gate 		meta_release_slot_session(slot_session);
3287c478bd9Sstevel@tonic-gate 	if (object)
3298cae6764SAnthony Scarpino 		(void) meta_object_dealloc(session, object, B_TRUE);
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	return (rv);
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate 
3377c478bd9Sstevel@tonic-gate /*
3387c478bd9Sstevel@tonic-gate  * meta_CopyObject
3397c478bd9Sstevel@tonic-gate  *
3407c478bd9Sstevel@tonic-gate  */
3417c478bd9Sstevel@tonic-gate CK_RV
meta_CopyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phNewObject)3427c478bd9Sstevel@tonic-gate meta_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
3437c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
3447c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE_PTR phNewObject)
3457c478bd9Sstevel@tonic-gate {
3467c478bd9Sstevel@tonic-gate 	CK_RV rv, first_rv;
3477c478bd9Sstevel@tonic-gate 	meta_session_t *session;
3487c478bd9Sstevel@tonic-gate 	meta_object_t *src_object, *dst_object = NULL;
3497c478bd9Sstevel@tonic-gate 	slot_session_t *slot_session = NULL;
3507c478bd9Sstevel@tonic-gate 	slot_object_t *dst_slot_object = NULL;
3517c478bd9Sstevel@tonic-gate 	CK_ULONG i;
3527c478bd9Sstevel@tonic-gate 	slot_object_t *src_slot_object;
3537c478bd9Sstevel@tonic-gate 	CK_ULONG slotnum, num_slots;
3547c478bd9Sstevel@tonic-gate 	boolean_t found;
3557c478bd9Sstevel@tonic-gate 
3567c478bd9Sstevel@tonic-gate 	if (pTemplate == NULL && ulCount != 0)
3577c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
3587c478bd9Sstevel@tonic-gate 	if (phNewObject == NULL)
3597c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
3627c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
3637c478bd9Sstevel@tonic-gate 		return (rv);
3647c478bd9Sstevel@tonic-gate 
3657c478bd9Sstevel@tonic-gate 	rv = meta_handle2object(hObject, &src_object);
3667c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3677c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
3687c478bd9Sstevel@tonic-gate 		return (rv);
3697c478bd9Sstevel@tonic-gate 	}
3707c478bd9Sstevel@tonic-gate 
3717c478bd9Sstevel@tonic-gate 	rv = meta_object_alloc(session, &dst_object);
3727c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
3737c478bd9Sstevel@tonic-gate 		goto finish;
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 	found = get_template_boolean(CKA_TOKEN,
3767c478bd9Sstevel@tonic-gate 	    pTemplate, ulCount, &(dst_object->isToken));
3777c478bd9Sstevel@tonic-gate 	if (!found) {
3787c478bd9Sstevel@tonic-gate 		dst_object->isToken = src_object->isToken;
3795b0c7657Sizick 		if (src_object->isFreeToken == FREE_ENABLED)
3805b0c7657Sizick 			dst_object->isToken = TRUE;
3815b0c7657Sizick 		else
3825b0c7657Sizick 			dst_object->isToken = src_object->isToken;
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 
3857c478bd9Sstevel@tonic-gate 	/* Can't create token objects in a read-only session. */
3867c478bd9Sstevel@tonic-gate 	if ((IS_READ_ONLY_SESSION(session->session_flags)) &&
3877c478bd9Sstevel@tonic-gate 	    (dst_object->isToken)) {
3887c478bd9Sstevel@tonic-gate 		rv = CKR_SESSION_READ_ONLY;
3897c478bd9Sstevel@tonic-gate 		goto finish;
3907c478bd9Sstevel@tonic-gate 	}
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	if (dst_object->isToken) {
3937c478bd9Sstevel@tonic-gate 
3947c478bd9Sstevel@tonic-gate 		/*
3957c478bd9Sstevel@tonic-gate 		 * if the dst object is a token object, and the source
3967c478bd9Sstevel@tonic-gate 		 * object is not, the source object needs to be extractable.
3977c478bd9Sstevel@tonic-gate 		 * Otherwise, the source object needs to reside in the
3987c478bd9Sstevel@tonic-gate 		 * token object slot
3997c478bd9Sstevel@tonic-gate 		 */
4007c478bd9Sstevel@tonic-gate 		if ((!src_object->isExtractable) &&
4017c478bd9Sstevel@tonic-gate 		    (src_object->master_clone_slotnum
4027c478bd9Sstevel@tonic-gate 		    != get_keystore_slotnum())) {
4037c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
4047c478bd9Sstevel@tonic-gate 			goto finish;
4057c478bd9Sstevel@tonic-gate 		}
4067c478bd9Sstevel@tonic-gate 
4077c478bd9Sstevel@tonic-gate 		/* determine if dst is going to be private object or not */
4087c478bd9Sstevel@tonic-gate 		found = get_template_boolean(CKA_PRIVATE,
4097c478bd9Sstevel@tonic-gate 		    pTemplate, ulCount, &(dst_object->isPrivate));
4107c478bd9Sstevel@tonic-gate 		if (!found) {
4117c478bd9Sstevel@tonic-gate 			/* will be the same as the source object */
4127c478bd9Sstevel@tonic-gate 			dst_object->isPrivate = src_object->isPrivate;
4137c478bd9Sstevel@tonic-gate 		}
4147c478bd9Sstevel@tonic-gate 
4157c478bd9Sstevel@tonic-gate 		slotnum = get_keystore_slotnum();
4167c478bd9Sstevel@tonic-gate 	} else {
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate 		/* try create the obj in the same slot as the source obj */
4197c478bd9Sstevel@tonic-gate 		slotnum = src_object->master_clone_slotnum;
4207c478bd9Sstevel@tonic-gate 	}
4217c478bd9Sstevel@tonic-gate 
4227c478bd9Sstevel@tonic-gate 	rv = meta_slot_object_alloc(&dst_slot_object);
4237c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
4247c478bd9Sstevel@tonic-gate 		goto finish;
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 	rv = meta_get_slot_session(slotnum, &slot_session,
4277c478bd9Sstevel@tonic-gate 	    session->session_flags);
4287c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
4297c478bd9Sstevel@tonic-gate 		goto finish;
4307c478bd9Sstevel@tonic-gate 
4317c478bd9Sstevel@tonic-gate 	rv = meta_object_get_clone(src_object, slotnum,
4327c478bd9Sstevel@tonic-gate 	    slot_session, &src_slot_object);
4337c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
4347c478bd9Sstevel@tonic-gate 		goto finish;
4357c478bd9Sstevel@tonic-gate 
4367c478bd9Sstevel@tonic-gate 	dst_object->tried_create_clone[slotnum] = B_TRUE;
4377c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(slot_session->fw_st_id)->C_CopyObject(
4387c478bd9Sstevel@tonic-gate 	    slot_session->hSession, src_slot_object->hObject, pTemplate,
4397c478bd9Sstevel@tonic-gate 	    ulCount, &(dst_slot_object->hObject));
4407c478bd9Sstevel@tonic-gate 
4417c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
4427c478bd9Sstevel@tonic-gate 		if (dst_object->isToken) {
4437c478bd9Sstevel@tonic-gate 			/*
4447c478bd9Sstevel@tonic-gate 			 * token obj can only be created in the
4457c478bd9Sstevel@tonic-gate 			 * token slot.  No need to try anywhere else
4467c478bd9Sstevel@tonic-gate 			 */
4477c478bd9Sstevel@tonic-gate 			goto finish;
4487c478bd9Sstevel@tonic-gate 		}
4497c478bd9Sstevel@tonic-gate 		if ((!src_object->isExtractable) ||
4507c478bd9Sstevel@tonic-gate 		    ((src_object->isSensitive) && (src_object->isToken) &&
4517c478bd9Sstevel@tonic-gate 		    (!metaslot_auto_key_migrate))) {
4527c478bd9Sstevel@tonic-gate 			/* source object isn't clonable in another slot */
4537c478bd9Sstevel@tonic-gate 			goto finish;
4547c478bd9Sstevel@tonic-gate 		}
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 		if (!try_again(rv)) {
4577c478bd9Sstevel@tonic-gate 			goto finish;
4587c478bd9Sstevel@tonic-gate 		}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		first_rv = rv;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 		meta_release_slot_session(slot_session);
4637c478bd9Sstevel@tonic-gate 		slot_session = NULL;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 		num_slots = meta_slotManager_get_slotcount();
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 		/* Try operation on other slots if the object is clonable */
4687c478bd9Sstevel@tonic-gate 		for (slotnum = 0; slotnum < num_slots; slotnum++) {
4697c478bd9Sstevel@tonic-gate 
4707c478bd9Sstevel@tonic-gate 			if (slotnum == src_object->master_clone_slotnum) {
4717c478bd9Sstevel@tonic-gate 				/* already tried, don't need to try again */
4727c478bd9Sstevel@tonic-gate 				continue;
4737c478bd9Sstevel@tonic-gate 			}
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate 			rv = meta_get_slot_session(slotnum, &slot_session,
4767c478bd9Sstevel@tonic-gate 			    session->session_flags);
4777c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
4787c478bd9Sstevel@tonic-gate 				goto finish;
4797c478bd9Sstevel@tonic-gate 			}
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 			rv = meta_object_get_clone(src_object, slotnum,
4827c478bd9Sstevel@tonic-gate 			    slot_session, &src_slot_object);
4837c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK)
4847c478bd9Sstevel@tonic-gate 				goto finish;
4857c478bd9Sstevel@tonic-gate 
4867c478bd9Sstevel@tonic-gate 			dst_object->tried_create_clone[slotnum] = B_TRUE;
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 			rv = FUNCLIST(slot_session->fw_st_id)->C_CopyObject(
4897c478bd9Sstevel@tonic-gate 			    slot_session->hSession, src_slot_object->hObject,
4907c478bd9Sstevel@tonic-gate 			    pTemplate, ulCount, &dst_slot_object->hObject);
4917c478bd9Sstevel@tonic-gate 
4927c478bd9Sstevel@tonic-gate 			if (rv == CKR_OK) {
4937c478bd9Sstevel@tonic-gate 				break;
4947c478bd9Sstevel@tonic-gate 			}
4957c478bd9Sstevel@tonic-gate 
4967c478bd9Sstevel@tonic-gate 			if (!try_again(rv)) {
4977c478bd9Sstevel@tonic-gate 				goto finish;
4987c478bd9Sstevel@tonic-gate 			}
4997c478bd9Sstevel@tonic-gate 			meta_release_slot_session(slot_session);
5007c478bd9Sstevel@tonic-gate 			slot_session = NULL;
5017c478bd9Sstevel@tonic-gate 		}
5027c478bd9Sstevel@tonic-gate 	}
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
5057c478bd9Sstevel@tonic-gate 
5067c478bd9Sstevel@tonic-gate 		rv = meta_object_get_attr(slot_session,
5077c478bd9Sstevel@tonic-gate 		    dst_slot_object->hObject, dst_object);
5087c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
5097c478bd9Sstevel@tonic-gate 			goto finish;
5107c478bd9Sstevel@tonic-gate 		}
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 		if (src_object->attributes != NULL) {
5137c478bd9Sstevel@tonic-gate 
5147c478bd9Sstevel@tonic-gate 			/* Keep a copy of the template for the future */
5157c478bd9Sstevel@tonic-gate 
5167c478bd9Sstevel@tonic-gate 			/*
5177c478bd9Sstevel@tonic-gate 			 * Don't allow attributes to change while
5187c478bd9Sstevel@tonic-gate 			 * we look at them.
5197c478bd9Sstevel@tonic-gate 			 */
5207c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_rdlock(
5217c478bd9Sstevel@tonic-gate 			    &src_object->attribute_lock);
5227c478bd9Sstevel@tonic-gate 
5237c478bd9Sstevel@tonic-gate 			rv = get_master_attributes_by_duplication(
5247c478bd9Sstevel@tonic-gate 			    src_object->attributes,
5257c478bd9Sstevel@tonic-gate 			    src_object->num_attributes,
5267c478bd9Sstevel@tonic-gate 			    &dst_object->attributes,
5277c478bd9Sstevel@tonic-gate 			    &dst_object->num_attributes);
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(
5307c478bd9Sstevel@tonic-gate 			    &src_object->attribute_lock);
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK)
5337c478bd9Sstevel@tonic-gate 				goto finish;
5347c478bd9Sstevel@tonic-gate 
5357c478bd9Sstevel@tonic-gate 			for (i = 0; i < ulCount; i++) {
5367c478bd9Sstevel@tonic-gate 				rv = attribute_set_value(pTemplate + i,
5377c478bd9Sstevel@tonic-gate 				    dst_object->attributes,
5387c478bd9Sstevel@tonic-gate 				    dst_object->num_attributes);
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 				if (rv != CKR_OK)
5417c478bd9Sstevel@tonic-gate 					goto finish;
5427c478bd9Sstevel@tonic-gate 			}
5437c478bd9Sstevel@tonic-gate 		}
5447c478bd9Sstevel@tonic-gate 
5458cae6764SAnthony Scarpino 		/* Allow FreeToken to activate onto token obj list */
5468cae6764SAnthony Scarpino 		if (dst_object->isFreeToken == FREE_ENABLED)
5478cae6764SAnthony Scarpino 			dst_object->isToken = TRUE;
5488cae6764SAnthony Scarpino 
5497c478bd9Sstevel@tonic-gate 		meta_slot_object_activate(dst_slot_object,
5507c478bd9Sstevel@tonic-gate 		    slot_session, dst_object->isToken);
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate 		dst_object->clones[slotnum] = dst_slot_object;
5537c478bd9Sstevel@tonic-gate 		dst_object->master_clone_slotnum = slotnum;
5547c478bd9Sstevel@tonic-gate 		dst_slot_object = NULL; /* for error cleanup */
5557c478bd9Sstevel@tonic-gate 
5567c478bd9Sstevel@tonic-gate 		meta_release_slot_session(slot_session);
5577c478bd9Sstevel@tonic-gate 		slot_session = NULL; /* for error cleanup */
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 	} else {
5607c478bd9Sstevel@tonic-gate 		/*
5617c478bd9Sstevel@tonic-gate 		 * return either first error code or
5627c478bd9Sstevel@tonic-gate 		 * CKR_FUNCTION_FAILED depending on the failure
5637c478bd9Sstevel@tonic-gate 		 */
5647c478bd9Sstevel@tonic-gate 		int j;
5657c478bd9Sstevel@tonic-gate 		for (j = 0; j < num_other_rv; j++) {
5667c478bd9Sstevel@tonic-gate 			if (rv == other_rv[j]) {
5677c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
5687c478bd9Sstevel@tonic-gate 				goto finish;
5697c478bd9Sstevel@tonic-gate 			}
5707c478bd9Sstevel@tonic-gate 		}
5717c478bd9Sstevel@tonic-gate 		/* need to return first rv */
5727c478bd9Sstevel@tonic-gate 		rv = first_rv;
5737c478bd9Sstevel@tonic-gate 		goto finish;
5747c478bd9Sstevel@tonic-gate 	}
5757c478bd9Sstevel@tonic-gate 	meta_object_activate(dst_object);
5767c478bd9Sstevel@tonic-gate 	*phNewObject = (CK_OBJECT_HANDLE) dst_object;
5777c478bd9Sstevel@tonic-gate 
5787c478bd9Sstevel@tonic-gate finish:
5797c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
5807c478bd9Sstevel@tonic-gate 		if (dst_slot_object)
5817c478bd9Sstevel@tonic-gate 			meta_slot_object_dealloc(dst_slot_object);
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 		if (dst_object)
5848cae6764SAnthony Scarpino 			(void) meta_object_dealloc(session, dst_object,
5858cae6764SAnthony Scarpino 			    B_TRUE);
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 		if (slot_session)
5887c478bd9Sstevel@tonic-gate 			meta_release_slot_session(slot_session);
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	OBJRELEASE(src_object);
5927c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	return (rv);
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 
5987c478bd9Sstevel@tonic-gate /*
5997c478bd9Sstevel@tonic-gate  * meta_DestroyObject
6007c478bd9Sstevel@tonic-gate  *
6017c478bd9Sstevel@tonic-gate  * This function destroys an object by first removing it from the
6027c478bd9Sstevel@tonic-gate  * list of valid objects for a given session (if session object) or
6037c478bd9Sstevel@tonic-gate  * the global token object list.  And then, calling C_DestroyObject
6047c478bd9Sstevel@tonic-gate  * on all the slots on which we have created a clone of this object.
6057c478bd9Sstevel@tonic-gate  */
6067c478bd9Sstevel@tonic-gate CK_RV
meta_DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)6077c478bd9Sstevel@tonic-gate meta_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
6087c478bd9Sstevel@tonic-gate {
6097c478bd9Sstevel@tonic-gate 	CK_RV rv;
6107c478bd9Sstevel@tonic-gate 	meta_session_t *session;
6117c478bd9Sstevel@tonic-gate 	meta_object_t *object;
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
6147c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
6157c478bd9Sstevel@tonic-gate 		return (rv);
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 	rv = meta_handle2object(hObject, &object);
6187c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
6197c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
6207c478bd9Sstevel@tonic-gate 		return (rv);
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	/* Can't delete token objects from a read-only session. */
6245b0c7657Sizick 	if ((IS_READ_ONLY_SESSION(session->session_flags)) &&
6255b0c7657Sizick 	    (object->isToken || object->isFreeToken == FREE_ENABLED)) {
6267c478bd9Sstevel@tonic-gate 		OBJRELEASE(object);
6277c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
6287c478bd9Sstevel@tonic-gate 		return (CKR_SESSION_READ_ONLY);
6297c478bd9Sstevel@tonic-gate 	}
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 	/* Remove object from list of valid meta_objects */
6327c478bd9Sstevel@tonic-gate 	rv = meta_object_deactivate(object, B_FALSE, B_TRUE);
6337c478bd9Sstevel@tonic-gate 
6347c478bd9Sstevel@tonic-gate 	/*
6357c478bd9Sstevel@tonic-gate 	 * Actually call C_DestroyObject on all the slots on which we have
6367c478bd9Sstevel@tonic-gate 	 * created a clone of this object.
6377c478bd9Sstevel@tonic-gate 	 */
6387c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK)
6398cae6764SAnthony Scarpino 		rv = meta_object_dealloc(session, object, B_TRUE);
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
6427c478bd9Sstevel@tonic-gate 
6437c478bd9Sstevel@tonic-gate 	return (rv);
6447c478bd9Sstevel@tonic-gate }
6457c478bd9Sstevel@tonic-gate 
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate /*
6487c478bd9Sstevel@tonic-gate  * meta_GetObjectSize
6497c478bd9Sstevel@tonic-gate  *
6507c478bd9Sstevel@tonic-gate  * NOTES:
6517c478bd9Sstevel@tonic-gate  * 1) Because the "size" is so poorly defined in the spec, we have deemed
6527c478bd9Sstevel@tonic-gate  *    it useless and won't support it. This is especially true for the
6537c478bd9Sstevel@tonic-gate  *    metaslot, because the mulitple providers it uses may each interpret
6547c478bd9Sstevel@tonic-gate  *    the size differently.
6557c478bd9Sstevel@tonic-gate  */
6567c478bd9Sstevel@tonic-gate /* ARGSUSED */
6577c478bd9Sstevel@tonic-gate CK_RV
meta_GetObjectSize(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ULONG_PTR pulSize)6587c478bd9Sstevel@tonic-gate meta_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
6597c478bd9Sstevel@tonic-gate     CK_ULONG_PTR pulSize)
6607c478bd9Sstevel@tonic-gate {
6617c478bd9Sstevel@tonic-gate 	return (CKR_FUNCTION_NOT_SUPPORTED);
6627c478bd9Sstevel@tonic-gate }
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 
6657c478bd9Sstevel@tonic-gate /*
6667c478bd9Sstevel@tonic-gate  * meta_GetAttributeValue
6677c478bd9Sstevel@tonic-gate  *
6687c478bd9Sstevel@tonic-gate  */
6697c478bd9Sstevel@tonic-gate CK_RV
meta_GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)6707c478bd9Sstevel@tonic-gate meta_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
6717c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
6727c478bd9Sstevel@tonic-gate {
6737c478bd9Sstevel@tonic-gate 	CK_RV rv;
6747c478bd9Sstevel@tonic-gate 	meta_session_t *session;
6757c478bd9Sstevel@tonic-gate 	meta_object_t *object;
6767c478bd9Sstevel@tonic-gate 	CK_ULONG slotnum;
6777c478bd9Sstevel@tonic-gate 	slot_session_t *slot_session;
6787c478bd9Sstevel@tonic-gate 
6797c478bd9Sstevel@tonic-gate 	if (pTemplate == NULL || ulCount < 1)
6807c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
6817c478bd9Sstevel@tonic-gate 
6827c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
6837c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
6847c478bd9Sstevel@tonic-gate 		return (rv);
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	rv = meta_handle2object(hObject, &object);
6877c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
6887c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
6897c478bd9Sstevel@tonic-gate 		return (rv);
6907c478bd9Sstevel@tonic-gate 	}
6917c478bd9Sstevel@tonic-gate 
6927c478bd9Sstevel@tonic-gate 	slotnum = object->master_clone_slotnum;
6937c478bd9Sstevel@tonic-gate 
6947c478bd9Sstevel@tonic-gate 	rv = meta_get_slot_session(slotnum, &slot_session,
6957c478bd9Sstevel@tonic-gate 	    session->session_flags);
6967c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
6977c478bd9Sstevel@tonic-gate 		rv = FUNCLIST(slot_session->fw_st_id)->C_GetAttributeValue(
6987c478bd9Sstevel@tonic-gate 		    slot_session->hSession, object->clones[slotnum]->hObject,
6997c478bd9Sstevel@tonic-gate 		    pTemplate, ulCount);
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 		meta_release_slot_session(slot_session);
7027c478bd9Sstevel@tonic-gate 	}
7037c478bd9Sstevel@tonic-gate 
7047c478bd9Sstevel@tonic-gate 	OBJRELEASE(object);
7057c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
7067c478bd9Sstevel@tonic-gate 
7077c478bd9Sstevel@tonic-gate 	return (rv);
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 
7127c478bd9Sstevel@tonic-gate /*
7137c478bd9Sstevel@tonic-gate  * meta_SetAttributeValue
7147c478bd9Sstevel@tonic-gate  *
7157c478bd9Sstevel@tonic-gate  * Call C_SetAttributeValue on all the clones.  If the operation fails on
7167c478bd9Sstevel@tonic-gate  * all clones, return the failure.
7177c478bd9Sstevel@tonic-gate  *
7187c478bd9Sstevel@tonic-gate  * If the operation fails on some clones and not the others, delete all the
7197c478bd9Sstevel@tonic-gate  * clones that have failed the operation.  If any of the deleted clone is the
7207c478bd9Sstevel@tonic-gate  * master clone, use one of the remaining clone as the master clone.
7217c478bd9Sstevel@tonic-gate  *
7227c478bd9Sstevel@tonic-gate  * If the operation is successful and the master template already exists,
7237c478bd9Sstevel@tonic-gate  * update the master template with new values.
7247c478bd9Sstevel@tonic-gate  */
7257c478bd9Sstevel@tonic-gate CK_RV
meta_SetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)7267c478bd9Sstevel@tonic-gate meta_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
7277c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
7287c478bd9Sstevel@tonic-gate {
7297c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK, save_rv = CKR_OK;
7307c478bd9Sstevel@tonic-gate 	meta_session_t *session;
7317c478bd9Sstevel@tonic-gate 	meta_object_t *object;
7327c478bd9Sstevel@tonic-gate 	CK_ULONG slotnum, num_slots;
7337c478bd9Sstevel@tonic-gate 	/* Keep track of which slot's SetAttributeValue failed */
7347c478bd9Sstevel@tonic-gate 	boolean_t *clone_failed_op = NULL;
7357c478bd9Sstevel@tonic-gate 	int num_clones = 0, num_clones_failed = 0;
7367c478bd9Sstevel@tonic-gate 	slot_session_t *slot_session;
7377c478bd9Sstevel@tonic-gate 	slot_object_t *slot_object;
7387c478bd9Sstevel@tonic-gate 	boolean_t need_update_master_clone = B_FALSE;
7397c478bd9Sstevel@tonic-gate 
7407c478bd9Sstevel@tonic-gate 	if (pTemplate == NULL || ulCount < 1)
7417c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
7427c478bd9Sstevel@tonic-gate 
7437c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
7447c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
7457c478bd9Sstevel@tonic-gate 		return (rv);
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	rv = meta_handle2object(hObject, &object);
7487c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
7497c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
7507c478bd9Sstevel@tonic-gate 		return (rv);
7517c478bd9Sstevel@tonic-gate 	}
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 	if ((IS_READ_ONLY_SESSION(session->session_flags)) &&
7545b0c7657Sizick 	    (object->isToken || object->isFreeToken == FREE_ENABLED)) {
7557c478bd9Sstevel@tonic-gate 		rv = CKR_SESSION_READ_ONLY;
7567c478bd9Sstevel@tonic-gate 		goto finish;
7577c478bd9Sstevel@tonic-gate 	}
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 	if ((!object->isExtractable) && (object->attributes == NULL)) {
7607c478bd9Sstevel@tonic-gate 		/*
7617c478bd9Sstevel@tonic-gate 		 * object has no clone, just need to do the operation
7627c478bd9Sstevel@tonic-gate 		 * in the master clone slot
7637c478bd9Sstevel@tonic-gate 		 */
7647c478bd9Sstevel@tonic-gate 		slot_session_t *slot_session;
7657c478bd9Sstevel@tonic-gate 		slotnum = object->master_clone_slotnum;
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 		rv = meta_get_slot_session(slotnum, &slot_session,
7687c478bd9Sstevel@tonic-gate 		    session->session_flags);
7697c478bd9Sstevel@tonic-gate 		if (rv == CKR_OK) {
7707c478bd9Sstevel@tonic-gate 			rv = FUNCLIST(slot_session->fw_st_id)->\
7717c478bd9Sstevel@tonic-gate 			    C_SetAttributeValue(slot_session->hSession,
7727c478bd9Sstevel@tonic-gate 			    object->clones[slotnum]->hObject, pTemplate,
7737c478bd9Sstevel@tonic-gate 			    ulCount);
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 			meta_release_slot_session(slot_session);
7767c478bd9Sstevel@tonic-gate 		}
7777c478bd9Sstevel@tonic-gate 		goto finish;
7787c478bd9Sstevel@tonic-gate 	}
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	num_slots = meta_slotManager_get_slotcount();
7827c478bd9Sstevel@tonic-gate 
7837c478bd9Sstevel@tonic-gate 	/*
7847c478bd9Sstevel@tonic-gate 	 * object might have clones, need to do operation in all clones
7857c478bd9Sstevel@tonic-gate 	 *
7867c478bd9Sstevel@tonic-gate 	 * If the C_SetAttributeValue() call fails in a clone, the
7877c478bd9Sstevel@tonic-gate 	 * clone that failed the operation can not be deleted right
7887c478bd9Sstevel@tonic-gate 	 * away.  The clone with the failed operation is recorded, and
7897c478bd9Sstevel@tonic-gate 	 * the deletion will happen in a separate loop.
7907c478bd9Sstevel@tonic-gate 	 *
7917c478bd9Sstevel@tonic-gate 	 * This is necessary because if ALL the clones failed
7927c478bd9Sstevel@tonic-gate 	 * C_SetAttributeVAlue(), then, the app's call to C_SetAttributeValue()
7937c478bd9Sstevel@tonic-gate 	 * is considered failed, and there shouldn't be any changes to the
7947c478bd9Sstevel@tonic-gate 	 * object, none of the clones should be deleted.
7957c478bd9Sstevel@tonic-gate 	 * On the other hand, if C_SetAttributeValue() fails in some clones
7967c478bd9Sstevel@tonic-gate 	 * and succeeds in other clones, the C_SetAttributeValue() operation
7977c478bd9Sstevel@tonic-gate 	 * is considered successful, and those clones that failed the
7987c478bd9Sstevel@tonic-gate 	 * operation is deleted.
7997c478bd9Sstevel@tonic-gate 	 */
8007c478bd9Sstevel@tonic-gate 	clone_failed_op = calloc(num_slots, sizeof (boolean_t));
8017c478bd9Sstevel@tonic-gate 	if (clone_failed_op == NULL) {
8027c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
8037c478bd9Sstevel@tonic-gate 		goto finish;
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate 	for (slotnum = 0; slotnum < num_slots; slotnum++) {
8067c478bd9Sstevel@tonic-gate 		if (object->clones[slotnum] != NULL) {
8077c478bd9Sstevel@tonic-gate 			num_clones++;
8087c478bd9Sstevel@tonic-gate 			rv = meta_get_slot_session(slotnum, &slot_session,
8097c478bd9Sstevel@tonic-gate 			    session->session_flags);
8107c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
8117c478bd9Sstevel@tonic-gate 				goto finish;
8127c478bd9Sstevel@tonic-gate 			}
8137c478bd9Sstevel@tonic-gate 
8147c478bd9Sstevel@tonic-gate 			rv = FUNCLIST(slot_session->fw_st_id)->\
8157c478bd9Sstevel@tonic-gate 			    C_SetAttributeValue(slot_session->hSession,
8167c478bd9Sstevel@tonic-gate 			    object->clones[slotnum]->hObject, pTemplate,
8177c478bd9Sstevel@tonic-gate 			    ulCount);
8187c478bd9Sstevel@tonic-gate 
8197c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
8207c478bd9Sstevel@tonic-gate 				num_clones_failed++;
8217c478bd9Sstevel@tonic-gate 				clone_failed_op[slotnum] = B_TRUE;
8227c478bd9Sstevel@tonic-gate 				if (save_rv == CKR_OK) {
8237c478bd9Sstevel@tonic-gate 					save_rv = rv;
8247c478bd9Sstevel@tonic-gate 				}
8257c478bd9Sstevel@tonic-gate 			}
8267c478bd9Sstevel@tonic-gate 			meta_release_slot_session(slot_session);
8277c478bd9Sstevel@tonic-gate 		}
8287c478bd9Sstevel@tonic-gate 	}
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate 	if (num_clones_failed == num_clones) {
8317c478bd9Sstevel@tonic-gate 		/* all operations failed */
8327c478bd9Sstevel@tonic-gate 		rv = save_rv;
8337c478bd9Sstevel@tonic-gate 		goto finish;
8347c478bd9Sstevel@tonic-gate 	}
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	if (num_clones_failed > 0) {
8377c478bd9Sstevel@tonic-gate 		/*
8387c478bd9Sstevel@tonic-gate 		 * C_SetAttributeValue in some of the clones failed.
8397c478bd9Sstevel@tonic-gate 		 * Find out which ones failed, and delete the clones
8407c478bd9Sstevel@tonic-gate 		 * in those failed slots
8417c478bd9Sstevel@tonic-gate 		 */
8427c478bd9Sstevel@tonic-gate 		for (slotnum = 0; slotnum < num_slots; slotnum++) {
8437c478bd9Sstevel@tonic-gate 			if (clone_failed_op[slotnum]) {
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 				slot_object_t *clone = object->clones[slotnum];
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 				rv = meta_get_slot_session(slotnum,
8487c478bd9Sstevel@tonic-gate 				    &slot_session, session->session_flags);
8497c478bd9Sstevel@tonic-gate 				if (rv == CKR_OK) {
8507c478bd9Sstevel@tonic-gate 					(void) FUNCLIST(
8517c478bd9Sstevel@tonic-gate 					    slot_session->fw_st_id)->
8527c478bd9Sstevel@tonic-gate 					    C_DestroyObject(
8537c478bd9Sstevel@tonic-gate 					    slot_session->hSession,
8547c478bd9Sstevel@tonic-gate 					    clone->hObject);
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 					meta_release_slot_session(slot_session);
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 				}
8597c478bd9Sstevel@tonic-gate 
8607c478bd9Sstevel@tonic-gate 				meta_slot_object_deactivate(clone);
8617c478bd9Sstevel@tonic-gate 				meta_slot_object_dealloc(clone);
8627c478bd9Sstevel@tonic-gate 				object->clones[slotnum] = NULL;
8637c478bd9Sstevel@tonic-gate 
8647c478bd9Sstevel@tonic-gate 				if (slotnum == object->master_clone_slotnum) {
8657c478bd9Sstevel@tonic-gate 					need_update_master_clone = B_TRUE;
8667c478bd9Sstevel@tonic-gate 				}
8677c478bd9Sstevel@tonic-gate 			}
8687c478bd9Sstevel@tonic-gate 		}
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate 		if (need_update_master_clone) {
8717c478bd9Sstevel@tonic-gate 			/* make first available clone the master */
8727c478bd9Sstevel@tonic-gate 			for (slotnum = 0; slotnum < num_slots; slotnum++) {
8737c478bd9Sstevel@tonic-gate 				if (object->clones[slotnum]) {
8747c478bd9Sstevel@tonic-gate 					object->master_clone_slotnum = slotnum;
8757c478bd9Sstevel@tonic-gate 					need_update_master_clone = B_FALSE;
8767c478bd9Sstevel@tonic-gate 					break;
8777c478bd9Sstevel@tonic-gate 				}
8787c478bd9Sstevel@tonic-gate 			}
8797c478bd9Sstevel@tonic-gate 
8807c478bd9Sstevel@tonic-gate 		}
8817c478bd9Sstevel@tonic-gate 		if (need_update_master_clone) {
8827c478bd9Sstevel@tonic-gate 			/*
8837c478bd9Sstevel@tonic-gate 			 * something is very wrong, can't continue
8847c478bd9Sstevel@tonic-gate 			 * it should never be this case.
8857c478bd9Sstevel@tonic-gate 			 */
8867c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
8877c478bd9Sstevel@tonic-gate 			goto finish;
8887c478bd9Sstevel@tonic-gate 		}
8897c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
8907c478bd9Sstevel@tonic-gate 	}
8917c478bd9Sstevel@tonic-gate 
8927c478bd9Sstevel@tonic-gate 	/*
8937c478bd9Sstevel@tonic-gate 	 * Update the attribute information we keep in our metaslot object
8947c478bd9Sstevel@tonic-gate 	 */
8957c478bd9Sstevel@tonic-gate 	slot_object = object->clones[object->master_clone_slotnum];
8967c478bd9Sstevel@tonic-gate 	rv = meta_get_slot_session(object->master_clone_slotnum,
8977c478bd9Sstevel@tonic-gate 	    &slot_session, session->session_flags);
8987c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
8997c478bd9Sstevel@tonic-gate 		(void) meta_object_get_attr(slot_session,
9007c478bd9Sstevel@tonic-gate 		    slot_object->hObject, object);
9017c478bd9Sstevel@tonic-gate 		meta_release_slot_session(slot_session);
9027c478bd9Sstevel@tonic-gate 	}
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	/* if there's a copy of the attributes, keep it up to date */
9057c478bd9Sstevel@tonic-gate 	if (object->attributes != NULL) {
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 		CK_ULONG i;
9087c478bd9Sstevel@tonic-gate 
9097c478bd9Sstevel@tonic-gate 		/* Make sure no one else is looking at attributes. */
9107c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(&object->attribute_lock);
9117c478bd9Sstevel@tonic-gate 
9127c478bd9Sstevel@tonic-gate 		for (i = 0; i < ulCount; i++) {
9137c478bd9Sstevel@tonic-gate 			(void) attribute_set_value(pTemplate + i,
9147c478bd9Sstevel@tonic-gate 			    object->attributes, object->num_attributes);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 		}
9177c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&object->attribute_lock);
9187c478bd9Sstevel@tonic-gate 	}
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate finish:
9217c478bd9Sstevel@tonic-gate 	if (clone_failed_op) {
9227c478bd9Sstevel@tonic-gate 		free(clone_failed_op);
9237c478bd9Sstevel@tonic-gate 	}
9247c478bd9Sstevel@tonic-gate 	OBJRELEASE(object);
9257c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 	return (rv);
9287c478bd9Sstevel@tonic-gate }
9297c478bd9Sstevel@tonic-gate 
9307c478bd9Sstevel@tonic-gate static boolean_t
meta_object_in_list(meta_object_t * obj,meta_object_t ** objs_list,int num_objs)9317c478bd9Sstevel@tonic-gate meta_object_in_list(meta_object_t *obj, meta_object_t **objs_list, int num_objs)
9327c478bd9Sstevel@tonic-gate {
9337c478bd9Sstevel@tonic-gate 	int i;
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_objs; i++) {
9367c478bd9Sstevel@tonic-gate 		if (objs_list[i] == obj) {
9377c478bd9Sstevel@tonic-gate 			return (B_TRUE);
9387c478bd9Sstevel@tonic-gate 		}
9397c478bd9Sstevel@tonic-gate 	}
9407c478bd9Sstevel@tonic-gate 	return (B_FALSE);
9417c478bd9Sstevel@tonic-gate }
9427c478bd9Sstevel@tonic-gate 
9437c478bd9Sstevel@tonic-gate static CK_RV
add_to_search_result(meta_object_t * object,find_objs_info_t * info,int * num_results_alloc)9447c478bd9Sstevel@tonic-gate add_to_search_result(meta_object_t *object, find_objs_info_t *info,
9457c478bd9Sstevel@tonic-gate     int *num_results_alloc)
9467c478bd9Sstevel@tonic-gate {
9477c478bd9Sstevel@tonic-gate 	/*
9487c478bd9Sstevel@tonic-gate 	 * allocate space for storing results if the currently
9497c478bd9Sstevel@tonic-gate 	 * allocated space is not enough
9507c478bd9Sstevel@tonic-gate 	 */
9517c478bd9Sstevel@tonic-gate 	if (*num_results_alloc <= info->num_matched_objs) {
9527c478bd9Sstevel@tonic-gate 		*num_results_alloc += FIND_OBJ_BUF_SIZE;
9537c478bd9Sstevel@tonic-gate 		info->matched_objs = realloc(info->matched_objs,
9547c478bd9Sstevel@tonic-gate 		    sizeof (meta_object_t *) * (*num_results_alloc));
9557c478bd9Sstevel@tonic-gate 		if (info->matched_objs == NULL) {
9567c478bd9Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
9577c478bd9Sstevel@tonic-gate 		}
9587c478bd9Sstevel@tonic-gate 	}
9597c478bd9Sstevel@tonic-gate 	(info->matched_objs)[(info->num_matched_objs)++] = object;
9607c478bd9Sstevel@tonic-gate 	return (CKR_OK);
9617c478bd9Sstevel@tonic-gate }
9627c478bd9Sstevel@tonic-gate 
9637c478bd9Sstevel@tonic-gate static CK_RV
process_find_results(CK_OBJECT_HANDLE * results,CK_ULONG num_results,int * num_results_allocated,find_objs_info_t * info,CK_ULONG slotnum,boolean_t token_only,slot_session_t * slot_session,meta_session_t * session)9647c478bd9Sstevel@tonic-gate process_find_results(CK_OBJECT_HANDLE *results, CK_ULONG num_results,
9657c478bd9Sstevel@tonic-gate     int *num_results_allocated, find_objs_info_t *info, CK_ULONG slotnum,
9667c478bd9Sstevel@tonic-gate     boolean_t token_only, slot_session_t *slot_session,
9677c478bd9Sstevel@tonic-gate     meta_session_t *session)
9687c478bd9Sstevel@tonic-gate {
9697c478bd9Sstevel@tonic-gate 	CK_ULONG i;
9707c478bd9Sstevel@tonic-gate 	meta_object_t *object;
9717c478bd9Sstevel@tonic-gate 	CK_RV rv;
9727c478bd9Sstevel@tonic-gate 
9737c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_results; i++) {
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 		object = meta_object_find_by_handle(results[i], slotnum,
9767c478bd9Sstevel@tonic-gate 		    token_only);
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate 		/*
9797c478bd9Sstevel@tonic-gate 		 * a token object is found from the keystore,
9807c478bd9Sstevel@tonic-gate 		 * need to create a meta object for it
9817c478bd9Sstevel@tonic-gate 		 */
9827c478bd9Sstevel@tonic-gate 		if (object == NULL) {
9837c478bd9Sstevel@tonic-gate 			slot_object_t *slot_object;
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 			rv = meta_object_alloc(session, &object);
9867c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
9877c478bd9Sstevel@tonic-gate 				return (rv);
9887c478bd9Sstevel@tonic-gate 			}
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 			rv = meta_slot_object_alloc(&slot_object);
9917c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
9928cae6764SAnthony Scarpino 				(void) meta_object_dealloc(session, object,
9938cae6764SAnthony Scarpino 				    B_TRUE);
9947c478bd9Sstevel@tonic-gate 				return (rv);
9957c478bd9Sstevel@tonic-gate 			}
9967c478bd9Sstevel@tonic-gate 
9977c478bd9Sstevel@tonic-gate 			slot_object->hObject = results[i];
9987c478bd9Sstevel@tonic-gate 			object->master_clone_slotnum = slotnum;
9997c478bd9Sstevel@tonic-gate 			object->clones[slotnum] = slot_object;
10007c478bd9Sstevel@tonic-gate 
10017c478bd9Sstevel@tonic-gate 			/* get in the attributes we keep in meta_object */
10027c478bd9Sstevel@tonic-gate 
10037c478bd9Sstevel@tonic-gate 			rv = meta_object_get_attr(slot_session,
10047c478bd9Sstevel@tonic-gate 			    slot_object->hObject, object);
10057c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
10068cae6764SAnthony Scarpino 				(void) meta_object_dealloc(session, object,
10078cae6764SAnthony Scarpino 				    B_TRUE);
10087c478bd9Sstevel@tonic-gate 				return (rv);
10097c478bd9Sstevel@tonic-gate 			}
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 			meta_slot_object_activate(slot_object, slot_session,
10127c478bd9Sstevel@tonic-gate 			    B_TRUE);
10137c478bd9Sstevel@tonic-gate 			meta_object_activate(object);
10147c478bd9Sstevel@tonic-gate 			slot_object = NULL;
10157c478bd9Sstevel@tonic-gate 		}
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 		if (!meta_object_in_list(object, info->matched_objs,
10187c478bd9Sstevel@tonic-gate 		    info->num_matched_objs)) {
10197c478bd9Sstevel@tonic-gate 			rv = add_to_search_result(object, info,
10207c478bd9Sstevel@tonic-gate 			    num_results_allocated);
10217c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
10227c478bd9Sstevel@tonic-gate 				return (rv);
10237c478bd9Sstevel@tonic-gate 			}
10247c478bd9Sstevel@tonic-gate 		}
10257c478bd9Sstevel@tonic-gate 	}
10267c478bd9Sstevel@tonic-gate 	return (CKR_OK);
10277c478bd9Sstevel@tonic-gate }
10287c478bd9Sstevel@tonic-gate 
10297c478bd9Sstevel@tonic-gate static CK_RV
meta_search_for_objects(meta_session_t * session,find_objs_info_t * info,slot_session_t * slot_session,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_ULONG slotnum,boolean_t token_only,int * num_results_alloc)10307c478bd9Sstevel@tonic-gate meta_search_for_objects(meta_session_t *session, find_objs_info_t *info,
10317c478bd9Sstevel@tonic-gate     slot_session_t *slot_session, CK_ATTRIBUTE_PTR pTemplate,
10327c478bd9Sstevel@tonic-gate     CK_ULONG ulCount, CK_ULONG slotnum, boolean_t token_only,
10337c478bd9Sstevel@tonic-gate     int *num_results_alloc)
10347c478bd9Sstevel@tonic-gate {
10357c478bd9Sstevel@tonic-gate 	CK_ULONG tmp_num_results;
10367c478bd9Sstevel@tonic-gate 	CK_OBJECT_HANDLE tmp_results[FIND_OBJ_BUF_SIZE];
10377c478bd9Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession = slot_session->hSession;
10387c478bd9Sstevel@tonic-gate 	CK_RV rv;
10397c478bd9Sstevel@tonic-gate 	CK_SLOT_ID fw_st_id = slot_session->fw_st_id;
10407c478bd9Sstevel@tonic-gate 
10417c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_FindObjectsInit(hSession,
10427c478bd9Sstevel@tonic-gate 	    pTemplate, ulCount);
10437c478bd9Sstevel@tonic-gate 
10447c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
10457c478bd9Sstevel@tonic-gate 		return (rv);
10467c478bd9Sstevel@tonic-gate 	}
10477c478bd9Sstevel@tonic-gate 
10487c478bd9Sstevel@tonic-gate 	tmp_num_results = 0;
10497c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_FindObjects(hSession, tmp_results,
10507c478bd9Sstevel@tonic-gate 	    FIND_OBJ_BUF_SIZE, &tmp_num_results);
10517c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
10527c478bd9Sstevel@tonic-gate 		return (rv);
10537c478bd9Sstevel@tonic-gate 	}
10547c478bd9Sstevel@tonic-gate 
10557c478bd9Sstevel@tonic-gate 	rv = process_find_results(tmp_results, tmp_num_results,
10567c478bd9Sstevel@tonic-gate 	    num_results_alloc, info, slotnum, token_only,
10577c478bd9Sstevel@tonic-gate 	    slot_session, session);
10587c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
10597c478bd9Sstevel@tonic-gate 		return (rv);
10607c478bd9Sstevel@tonic-gate 	}
10617c478bd9Sstevel@tonic-gate 
10627c478bd9Sstevel@tonic-gate 	while (tmp_num_results == FIND_OBJ_BUF_SIZE) {
10637c478bd9Sstevel@tonic-gate 		/* might be more results, need to call C_FindObjects again */
10647c478bd9Sstevel@tonic-gate 		rv = FUNCLIST(fw_st_id)->C_FindObjects(hSession, tmp_results,
10657c478bd9Sstevel@tonic-gate 		    FIND_OBJ_BUF_SIZE, &tmp_num_results);
10667c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
10677c478bd9Sstevel@tonic-gate 			return (rv);
10687c478bd9Sstevel@tonic-gate 		}
10697c478bd9Sstevel@tonic-gate 
10707c478bd9Sstevel@tonic-gate 		rv = process_find_results(tmp_results, tmp_num_results,
10717c478bd9Sstevel@tonic-gate 		    num_results_alloc, info, slotnum, token_only,
10727c478bd9Sstevel@tonic-gate 		    slot_session, session);
10737c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
10747c478bd9Sstevel@tonic-gate 			return (rv);
10757c478bd9Sstevel@tonic-gate 		}
10767c478bd9Sstevel@tonic-gate 	}
10777c478bd9Sstevel@tonic-gate 
10787c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_FindObjectsFinal(hSession);
10797c478bd9Sstevel@tonic-gate 	return (rv);
10807c478bd9Sstevel@tonic-gate }
10817c478bd9Sstevel@tonic-gate 
10827c478bd9Sstevel@tonic-gate 
10837c478bd9Sstevel@tonic-gate /*
10847c478bd9Sstevel@tonic-gate  * meta_FindObjectsInit
10857c478bd9Sstevel@tonic-gate  *
10867c478bd9Sstevel@tonic-gate  * This function actually will do ALL the work of searching for objects
10877c478bd9Sstevel@tonic-gate  * that match all requirements specified in the template.
10887c478bd9Sstevel@tonic-gate  *
10897c478bd9Sstevel@tonic-gate  * Objects that matched the template will be stored in the
10907c478bd9Sstevel@tonic-gate  * session's data structure.  When the subsequent C_FindObjects()
10917c478bd9Sstevel@tonic-gate  * calls are made, results saved will be returned.
10927c478bd9Sstevel@tonic-gate  *
10937c478bd9Sstevel@tonic-gate  */
10947c478bd9Sstevel@tonic-gate CK_RV
meta_FindObjectsInit(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)10957c478bd9Sstevel@tonic-gate meta_FindObjectsInit(CK_SESSION_HANDLE hSession, CK_ATTRIBUTE_PTR pTemplate,
10967c478bd9Sstevel@tonic-gate     CK_ULONG ulCount)
10977c478bd9Sstevel@tonic-gate {
10987c478bd9Sstevel@tonic-gate 	CK_RV rv;
10997c478bd9Sstevel@tonic-gate 	meta_session_t *session;
11007c478bd9Sstevel@tonic-gate 	CK_ULONG slot_num = 0;
11017c478bd9Sstevel@tonic-gate 	boolean_t have_token_attr, tokenTrue = B_FALSE;
11027c478bd9Sstevel@tonic-gate 	slot_session_t *slot_find_session = NULL;
11037c478bd9Sstevel@tonic-gate 	int num_results_allocated = 0;
11047c478bd9Sstevel@tonic-gate 	CK_ULONG keystore_slotnum;
11057c478bd9Sstevel@tonic-gate 
11067c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
11077c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
11087c478bd9Sstevel@tonic-gate 		return (rv);
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	if ((session->find_objs_info).op_active) {
11117c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
11127c478bd9Sstevel@tonic-gate 		return (CKR_OPERATION_ACTIVE);
11137c478bd9Sstevel@tonic-gate 	}
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 	(session->find_objs_info).op_active = B_TRUE;
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
11187c478bd9Sstevel@tonic-gate 
11197c478bd9Sstevel@tonic-gate 	/* see if the template indicates token object only or not */
11207c478bd9Sstevel@tonic-gate 	have_token_attr = get_template_boolean(CKA_TOKEN, pTemplate, ulCount,
11217c478bd9Sstevel@tonic-gate 	    &tokenTrue);
11227c478bd9Sstevel@tonic-gate 
11237c478bd9Sstevel@tonic-gate 	keystore_slotnum = get_keystore_slotnum();
11247c478bd9Sstevel@tonic-gate 
11257c478bd9Sstevel@tonic-gate 	if (have_token_attr && tokenTrue) {
11267c478bd9Sstevel@tonic-gate 
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 		/*
11297c478bd9Sstevel@tonic-gate 		 * only interested in token objects, just need to search
11307c478bd9Sstevel@tonic-gate 		 * token object slot
11317c478bd9Sstevel@tonic-gate 		 */
11327c478bd9Sstevel@tonic-gate 		rv = meta_get_slot_session(keystore_slotnum,
11337c478bd9Sstevel@tonic-gate 		    &slot_find_session, session->session_flags);
11347c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)  {
11357c478bd9Sstevel@tonic-gate 			goto finish;
11367c478bd9Sstevel@tonic-gate 		}
11377c478bd9Sstevel@tonic-gate 		rv = meta_search_for_objects(session,
11387c478bd9Sstevel@tonic-gate 		    &(session->find_objs_info), slot_find_session, pTemplate,
11397c478bd9Sstevel@tonic-gate 		    ulCount, keystore_slotnum, B_TRUE, &num_results_allocated);
11407c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
11417c478bd9Sstevel@tonic-gate 			goto finish;
11427c478bd9Sstevel@tonic-gate 		}
11437c478bd9Sstevel@tonic-gate 	} else {
11447c478bd9Sstevel@tonic-gate 		CK_ULONG num_slots = meta_slotManager_get_slotcount();
11457c478bd9Sstevel@tonic-gate 		for (slot_num = 0; slot_num < num_slots; slot_num++) {
11467c478bd9Sstevel@tonic-gate 			rv = meta_get_slot_session(slot_num,
11477c478bd9Sstevel@tonic-gate 			    &slot_find_session, session->session_flags);
11487c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
11497c478bd9Sstevel@tonic-gate 				goto finish;
11507c478bd9Sstevel@tonic-gate 			}
11517c478bd9Sstevel@tonic-gate 
11527c478bd9Sstevel@tonic-gate 			/*
11537c478bd9Sstevel@tonic-gate 			 * if the slot is NOT the token object slot, and
11547c478bd9Sstevel@tonic-gate 			 * CKA_TOKEN is not specified, need to specified
11557c478bd9Sstevel@tonic-gate 			 * it to be false explicitly.  This will prevent
11567c478bd9Sstevel@tonic-gate 			 * us from using token objects that doesn't
11577c478bd9Sstevel@tonic-gate 			 * belong to the token slot in the case that
11587c478bd9Sstevel@tonic-gate 			 * more than one slot supports token objects.
11597c478bd9Sstevel@tonic-gate 			 */
11607c478bd9Sstevel@tonic-gate 
11617c478bd9Sstevel@tonic-gate 			if ((slot_num != keystore_slotnum) &&
11627c478bd9Sstevel@tonic-gate 			    (!have_token_attr)) {
11637c478bd9Sstevel@tonic-gate 				CK_BBOOL false = FALSE;
11647c478bd9Sstevel@tonic-gate 				CK_ATTRIBUTE_PTR newTemplate;
11657c478bd9Sstevel@tonic-gate 
11667c478bd9Sstevel@tonic-gate 				newTemplate = malloc((ulCount + 1) *
11677c478bd9Sstevel@tonic-gate 				    sizeof (CK_ATTRIBUTE));
11687c478bd9Sstevel@tonic-gate 				if (newTemplate == NULL) {
11697c478bd9Sstevel@tonic-gate 					rv = CKR_HOST_MEMORY;
11707c478bd9Sstevel@tonic-gate 					goto finish;
11717c478bd9Sstevel@tonic-gate 				}
11727c478bd9Sstevel@tonic-gate 				(void) memcpy(newTemplate + 1, pTemplate,
11737c478bd9Sstevel@tonic-gate 				    ulCount * sizeof (CK_ATTRIBUTE));
11747c478bd9Sstevel@tonic-gate 				newTemplate[0].type = CKA_TOKEN;
11757c478bd9Sstevel@tonic-gate 				newTemplate[0].pValue = &false;
11767c478bd9Sstevel@tonic-gate 				newTemplate[0].ulValueLen = sizeof (false);
11777c478bd9Sstevel@tonic-gate 
11787c478bd9Sstevel@tonic-gate 				rv = meta_search_for_objects(session,
11797c478bd9Sstevel@tonic-gate 				    &(session->find_objs_info),
11807c478bd9Sstevel@tonic-gate 				    slot_find_session, newTemplate,
11817c478bd9Sstevel@tonic-gate 				    ulCount+1, slot_num, B_FALSE,
11827c478bd9Sstevel@tonic-gate 				    &num_results_allocated);
11837c478bd9Sstevel@tonic-gate 				free(newTemplate);
11847c478bd9Sstevel@tonic-gate 			} else {
11857c478bd9Sstevel@tonic-gate 				rv = meta_search_for_objects(session,
11867c478bd9Sstevel@tonic-gate 				    &(session->find_objs_info),
11877c478bd9Sstevel@tonic-gate 				    slot_find_session, pTemplate, ulCount,
11887c478bd9Sstevel@tonic-gate 				    slot_num, B_FALSE,
11897c478bd9Sstevel@tonic-gate 				    &num_results_allocated);
11907c478bd9Sstevel@tonic-gate 			}
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
11937c478bd9Sstevel@tonic-gate 				goto finish;
11947c478bd9Sstevel@tonic-gate 			}
11957c478bd9Sstevel@tonic-gate 			meta_release_slot_session(slot_find_session);
11967c478bd9Sstevel@tonic-gate 			slot_find_session = NULL;
11977c478bd9Sstevel@tonic-gate 		}
11987c478bd9Sstevel@tonic-gate 	}
11997c478bd9Sstevel@tonic-gate 
12007c478bd9Sstevel@tonic-gate finish:
12017c478bd9Sstevel@tonic-gate 	if (slot_find_session != NULL) {
12027c478bd9Sstevel@tonic-gate 		meta_release_slot_session(slot_find_session);
12037c478bd9Sstevel@tonic-gate 	}
12047c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
12057c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(&session->session_lock);
12067c478bd9Sstevel@tonic-gate 		if (((session->find_objs_info).matched_objs) != NULL) {
12077c478bd9Sstevel@tonic-gate 			free((session->find_objs_info).matched_objs);
12087c478bd9Sstevel@tonic-gate 		}
12097c478bd9Sstevel@tonic-gate 		bzero(&(session->find_objs_info), sizeof (find_objs_info_t));
12107c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&(session->session_lock));
12117c478bd9Sstevel@tonic-gate 	}
12127c478bd9Sstevel@tonic-gate 
12137c478bd9Sstevel@tonic-gate 	return (rv);
12147c478bd9Sstevel@tonic-gate }
12157c478bd9Sstevel@tonic-gate 
12167c478bd9Sstevel@tonic-gate /*
12177c478bd9Sstevel@tonic-gate  * meta_FindObjects
12187c478bd9Sstevel@tonic-gate  *
12197c478bd9Sstevel@tonic-gate  * This function actually doesn't do any real work in search for the
12207c478bd9Sstevel@tonic-gate  * matching object.  All the work is done in FindObjectsInit().  This
12217c478bd9Sstevel@tonic-gate  * function will only return the matching objects store in the session's
12227c478bd9Sstevel@tonic-gate  * "find_objs_info" variable.
12237c478bd9Sstevel@tonic-gate  *
12247c478bd9Sstevel@tonic-gate  */
12257c478bd9Sstevel@tonic-gate CK_RV
meta_FindObjects(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)12267c478bd9Sstevel@tonic-gate meta_FindObjects(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE_PTR phObject,
12277c478bd9Sstevel@tonic-gate     CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
12287c478bd9Sstevel@tonic-gate {
12297c478bd9Sstevel@tonic-gate 	CK_RV rv;
12307c478bd9Sstevel@tonic-gate 	find_objs_info_t *info;
12317c478bd9Sstevel@tonic-gate 	CK_ULONG num_objs_found = 0;
12327c478bd9Sstevel@tonic-gate 	meta_object_t *obj;
12337c478bd9Sstevel@tonic-gate 	meta_session_t *session;
12347c478bd9Sstevel@tonic-gate 	int i;
12357c478bd9Sstevel@tonic-gate 
12367c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
12377c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
12387c478bd9Sstevel@tonic-gate 		return (rv);
12397c478bd9Sstevel@tonic-gate 
12407c478bd9Sstevel@tonic-gate 	info = &(session->find_objs_info);
12417c478bd9Sstevel@tonic-gate 
12427c478bd9Sstevel@tonic-gate 	if (!(info->op_active)) {
12437c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
12447c478bd9Sstevel@tonic-gate 		return (CKR_OPERATION_NOT_INITIALIZED);
12457c478bd9Sstevel@tonic-gate 	}
12467c478bd9Sstevel@tonic-gate 
12477c478bd9Sstevel@tonic-gate 	for (i = info->next_result_index;
12487c478bd9Sstevel@tonic-gate 	    ((num_objs_found < ulMaxObjectCount) &&
12497c478bd9Sstevel@tonic-gate 	    (i < info->num_matched_objs));
12507c478bd9Sstevel@tonic-gate 	    i++) {
12517c478bd9Sstevel@tonic-gate 		obj = info->matched_objs[i];
12527c478bd9Sstevel@tonic-gate 		if (obj != NULL) {
12537c478bd9Sstevel@tonic-gate 			/* sanity check to see if object is still valid */
12547c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_rdlock(&obj->object_lock);
12557c478bd9Sstevel@tonic-gate 			if (obj->magic_marker == METASLOT_OBJECT_MAGIC) {
12567c478bd9Sstevel@tonic-gate 				phObject[num_objs_found++] =
12577c478bd9Sstevel@tonic-gate 				    (CK_OBJECT_HANDLE)obj;
12587c478bd9Sstevel@tonic-gate 			}
12597c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(&obj->object_lock);
12607c478bd9Sstevel@tonic-gate 		}
12617c478bd9Sstevel@tonic-gate 	}
12627c478bd9Sstevel@tonic-gate 	info->next_result_index = i;
12637c478bd9Sstevel@tonic-gate 	*pulObjectCount	= num_objs_found;
12647c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
12657c478bd9Sstevel@tonic-gate 	return (rv);
12667c478bd9Sstevel@tonic-gate }
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate /*
12707c478bd9Sstevel@tonic-gate  * meta_FindObjectsFinal
12717c478bd9Sstevel@tonic-gate  *
12727c478bd9Sstevel@tonic-gate  */
12737c478bd9Sstevel@tonic-gate CK_RV
meta_FindObjectsFinal(CK_SESSION_HANDLE hSession)12747c478bd9Sstevel@tonic-gate meta_FindObjectsFinal(CK_SESSION_HANDLE hSession)
12757c478bd9Sstevel@tonic-gate {
12767c478bd9Sstevel@tonic-gate 	CK_RV rv;
12777c478bd9Sstevel@tonic-gate 	find_objs_info_t *info;
12787c478bd9Sstevel@tonic-gate 	meta_session_t *session;
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	rv = meta_handle2session(hSession, &session);
12817c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
12827c478bd9Sstevel@tonic-gate 		return (rv);
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	info = &(session->find_objs_info);
12857c478bd9Sstevel@tonic-gate 
12867c478bd9Sstevel@tonic-gate 	if (!info->op_active) {
12877c478bd9Sstevel@tonic-gate 		REFRELEASE(session);
12887c478bd9Sstevel@tonic-gate 		return (CKR_OPERATION_NOT_INITIALIZED);
12897c478bd9Sstevel@tonic-gate 	}
12907c478bd9Sstevel@tonic-gate 
12917c478bd9Sstevel@tonic-gate 	if (info->matched_objs) {
12927c478bd9Sstevel@tonic-gate 		free(info->matched_objs);
12937c478bd9Sstevel@tonic-gate 	}
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	bzero(info, sizeof (find_objs_info_t));
12967c478bd9Sstevel@tonic-gate 	REFRELEASE(session);
12977c478bd9Sstevel@tonic-gate 	return (rv);
12987c478bd9Sstevel@tonic-gate }
1299