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
57c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
67c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
77c478bd9Sstevel@tonic-gate  * with the License.
87c478bd9Sstevel@tonic-gate  *
97c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
107c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
117c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
127c478bd9Sstevel@tonic-gate  * and limitations under the License.
137c478bd9Sstevel@tonic-gate  *
147c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
157c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
167c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
177c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
187c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
197c478bd9Sstevel@tonic-gate  *
207c478bd9Sstevel@tonic-gate  * CDDL HEADER END
217c478bd9Sstevel@tonic-gate  */
227c478bd9Sstevel@tonic-gate /*
237c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
247c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <pthread.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <errno.h>
307c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
317c478bd9Sstevel@tonic-gate #include "kernelGlobal.h"
327c478bd9Sstevel@tonic-gate #include "kernelObject.h"
337c478bd9Sstevel@tonic-gate #include "kernelSession.h"
347c478bd9Sstevel@tonic-gate #include <errno.h>
357c478bd9Sstevel@tonic-gate #include <string.h>
367c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate CK_RV
C_CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject)397c478bd9Sstevel@tonic-gate C_CreateObject(CK_SESSION_HANDLE hSession,
407c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate,
417c478bd9Sstevel@tonic-gate     CK_ULONG ulCount,
427c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE_PTR phObject)
437c478bd9Sstevel@tonic-gate {
447c478bd9Sstevel@tonic-gate 
457c478bd9Sstevel@tonic-gate 	CK_RV rv;
467c478bd9Sstevel@tonic-gate 	kernel_session_t *session_p;
477c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
507c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate 	if ((pTemplate == NULL) || (ulCount == 0) ||
537c478bd9Sstevel@tonic-gate 	    (phObject == NULL)) {
547c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
557c478bd9Sstevel@tonic-gate 	}
567c478bd9Sstevel@tonic-gate 
577c478bd9Sstevel@tonic-gate 	/*
587c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
597c478bd9Sstevel@tonic-gate 	 * reference count.
607c478bd9Sstevel@tonic-gate 	 */
617c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
627c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
637c478bd9Sstevel@tonic-gate 		return (rv);
647c478bd9Sstevel@tonic-gate 
657c478bd9Sstevel@tonic-gate 	/* Create a new object. */
667c478bd9Sstevel@tonic-gate 	rv = kernel_add_object(pTemplate, ulCount, phObject, session_p);
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 	/*
697c478bd9Sstevel@tonic-gate 	 * Decrement the session reference count.
707c478bd9Sstevel@tonic-gate 	 * We do not hold the session lock.
717c478bd9Sstevel@tonic-gate 	 */
727c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
737c478bd9Sstevel@tonic-gate 
747c478bd9Sstevel@tonic-gate 	return (rv);
757c478bd9Sstevel@tonic-gate }
767c478bd9Sstevel@tonic-gate 
777c478bd9Sstevel@tonic-gate 
787c478bd9Sstevel@tonic-gate CK_RV
C_CopyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phNewObject)797c478bd9Sstevel@tonic-gate C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
807c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
817c478bd9Sstevel@tonic-gate     CK_OBJECT_HANDLE_PTR phNewObject)
827c478bd9Sstevel@tonic-gate {
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	CK_RV rv;
857c478bd9Sstevel@tonic-gate 	kernel_session_t *session_p;
867c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
877c478bd9Sstevel@tonic-gate 	kernel_object_t *old_object;
887c478bd9Sstevel@tonic-gate 	kernel_object_t *new_object = NULL;
897c478bd9Sstevel@tonic-gate 	crypto_object_copy_t  object_copy;
907c478bd9Sstevel@tonic-gate 	CK_BBOOL is_pri_obj = FALSE;
917c478bd9Sstevel@tonic-gate 	CK_BBOOL is_token_obj = FALSE;
927c478bd9Sstevel@tonic-gate 	kernel_slot_t	*pslot;
937c478bd9Sstevel@tonic-gate 	int i, r;
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
967c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	/* Check arguments */
997c478bd9Sstevel@tonic-gate 	if (((ulCount > 0) && (pTemplate == NULL)) ||
1007c478bd9Sstevel@tonic-gate 	    (phNewObject == NULL)) {
1017c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
1027c478bd9Sstevel@tonic-gate 	}
1037c478bd9Sstevel@tonic-gate 
1047c478bd9Sstevel@tonic-gate 	/*
1057c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
1067c478bd9Sstevel@tonic-gate 	 * reference count.
1077c478bd9Sstevel@tonic-gate 	 */
1087c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
1097c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1107c478bd9Sstevel@tonic-gate 		return (rv);
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	/* Obtain the object pointer. */
1137c478bd9Sstevel@tonic-gate 	HANDLE2OBJECT(hObject, old_object, rv);
1147c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1157c478bd9Sstevel@tonic-gate 		/*
1167c478bd9Sstevel@tonic-gate 		 * Decrement the session reference count.
1177c478bd9Sstevel@tonic-gate 		 * We do not hold the session lock.
1187c478bd9Sstevel@tonic-gate 		 */
1197c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
1207c478bd9Sstevel@tonic-gate 		return (rv);
1217c478bd9Sstevel@tonic-gate 	}
1227c478bd9Sstevel@tonic-gate 
1237c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&old_object->object_mutex);
1247c478bd9Sstevel@tonic-gate 
1257c478bd9Sstevel@tonic-gate 	if (old_object->is_lib_obj) {
1267c478bd9Sstevel@tonic-gate 		/*
1277c478bd9Sstevel@tonic-gate 		 * Copy the old object to a new object.
1287c478bd9Sstevel@tonic-gate 		 * The 3rd argument with TRUE value indicates that
1297c478bd9Sstevel@tonic-gate 		 * everything in the object will be duplicated.
1307c478bd9Sstevel@tonic-gate 		 */
1317c478bd9Sstevel@tonic-gate 		rv = kernel_copy_object(old_object, &new_object, B_TRUE,
1327c478bd9Sstevel@tonic-gate 		    session_p);
133*01223cbaSmcpowers 		(void) pthread_mutex_unlock(&old_object->object_mutex);
1347c478bd9Sstevel@tonic-gate 		if ((rv != CKR_OK) || (new_object == NULL)) {
1357c478bd9Sstevel@tonic-gate 			/*
136*01223cbaSmcpowers 			 * Most likely we ran out of space.
1377c478bd9Sstevel@tonic-gate 			 * Decrement the session reference count.
1387c478bd9Sstevel@tonic-gate 			 * We do not hold the session lock.
1397c478bd9Sstevel@tonic-gate 			 */
140*01223cbaSmcpowers 			OBJ_REFRELE(old_object);
1417c478bd9Sstevel@tonic-gate 			REFRELE(session_p, ses_lock_held);
1427c478bd9Sstevel@tonic-gate 			return (rv);
1437c478bd9Sstevel@tonic-gate 		}
1447c478bd9Sstevel@tonic-gate 
1457c478bd9Sstevel@tonic-gate 		new_object->is_lib_obj = B_TRUE;
1467c478bd9Sstevel@tonic-gate 
1477c478bd9Sstevel@tonic-gate 		/* Modify the object attribute if requested */
1487c478bd9Sstevel@tonic-gate 		for (i = 0; i < ulCount; i++) {
1497c478bd9Sstevel@tonic-gate 			/* Set the requested attribute into the new object. */
1507c478bd9Sstevel@tonic-gate 			rv = kernel_set_attribute(new_object, &pTemplate[i],
1517c478bd9Sstevel@tonic-gate 			    B_TRUE, session_p);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
1547c478bd9Sstevel@tonic-gate 				kernel_cleanup_object(new_object);
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 				/*
1577c478bd9Sstevel@tonic-gate 				 * Decrement the session reference count.
1587c478bd9Sstevel@tonic-gate 				 * We do not hold the session lock.
1597c478bd9Sstevel@tonic-gate 				 */
160*01223cbaSmcpowers 				OBJ_REFRELE(old_object);
1617c478bd9Sstevel@tonic-gate 				REFRELE(session_p, ses_lock_held);
1627c478bd9Sstevel@tonic-gate 				return (rv);
1637c478bd9Sstevel@tonic-gate 			}
1647c478bd9Sstevel@tonic-gate 		}
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 		/* Insert the new object into this session's object list. */
1677c478bd9Sstevel@tonic-gate 		kernel_add_object_to_session(new_object, session_p);
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 		/*
1707c478bd9Sstevel@tonic-gate 		 * Decrement the session reference count.
1717c478bd9Sstevel@tonic-gate 		 * We do not hold the session lock.
1727c478bd9Sstevel@tonic-gate 		 */
173*01223cbaSmcpowers 		OBJ_REFRELE(old_object);
1747c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 		/* set handle of the new object */
1777c478bd9Sstevel@tonic-gate 		*phNewObject = (CK_ULONG)new_object;
1787c478bd9Sstevel@tonic-gate 
1797c478bd9Sstevel@tonic-gate 	} else {
1807c478bd9Sstevel@tonic-gate 		/*
1817c478bd9Sstevel@tonic-gate 		 * The old object was created in the HW provider.
1827c478bd9Sstevel@tonic-gate 		 * First, create an object wrapper in library.
1837c478bd9Sstevel@tonic-gate 		 */
1847c478bd9Sstevel@tonic-gate 		new_object = calloc(1, sizeof (kernel_object_t));
1857c478bd9Sstevel@tonic-gate 		if (new_object == NULL) {
186*01223cbaSmcpowers 			(void) pthread_mutex_unlock(&old_object->object_mutex);
187*01223cbaSmcpowers 			OBJ_REFRELE(old_object);
188*01223cbaSmcpowers 			REFRELE(session_p, ses_lock_held);
189*01223cbaSmcpowers 			return (CKR_HOST_MEMORY);
1907c478bd9Sstevel@tonic-gate 		}
1917c478bd9Sstevel@tonic-gate 
1927c478bd9Sstevel@tonic-gate 		/* Call CRYPTO_OBJECT_COPY ioctl to get a new object. */
1937c478bd9Sstevel@tonic-gate 		object_copy.oc_session = session_p->k_session;
1947c478bd9Sstevel@tonic-gate 		object_copy.oc_handle = old_object->k_handle;
195*01223cbaSmcpowers 		(void) pthread_mutex_unlock(&old_object->object_mutex);
1967c478bd9Sstevel@tonic-gate 		object_copy.oc_count = ulCount;
1977c478bd9Sstevel@tonic-gate 		object_copy.oc_new_attributes = NULL;
1987c478bd9Sstevel@tonic-gate 		if (ulCount > 0) {
1997c478bd9Sstevel@tonic-gate 			rv = process_object_attributes(pTemplate, ulCount,
2007c478bd9Sstevel@tonic-gate 			    &object_copy.oc_new_attributes, &is_token_obj);
2017c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
2027c478bd9Sstevel@tonic-gate 				goto failed_cleanup;
2037c478bd9Sstevel@tonic-gate 			}
2047c478bd9Sstevel@tonic-gate 		}
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_COPY,
2077c478bd9Sstevel@tonic-gate 		    &object_copy)) < 0) {
2087c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
2097c478bd9Sstevel@tonic-gate 				break;
2107c478bd9Sstevel@tonic-gate 		}
2117c478bd9Sstevel@tonic-gate 		if (r < 0) {
2127c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
2137c478bd9Sstevel@tonic-gate 		} else {
2147c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
2157c478bd9Sstevel@tonic-gate 			    object_copy.oc_return_value);
2167c478bd9Sstevel@tonic-gate 		}
2177c478bd9Sstevel@tonic-gate 
2187c478bd9Sstevel@tonic-gate 		/* Free the attributes' space allocated for ioctl */
2197c478bd9Sstevel@tonic-gate 		free_object_attributes(object_copy.oc_new_attributes, ulCount);
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
2227c478bd9Sstevel@tonic-gate 			goto failed_cleanup;
2237c478bd9Sstevel@tonic-gate 		}
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 		/*
2267c478bd9Sstevel@tonic-gate 		 * Store the kernel object handle in the object wrapper and
2277c478bd9Sstevel@tonic-gate 		 * get the CKA_PRIVATE value of the new object.
2287c478bd9Sstevel@tonic-gate 		 */
2297c478bd9Sstevel@tonic-gate 		new_object->k_handle = object_copy.oc_new_handle;
2307c478bd9Sstevel@tonic-gate 		rv = get_cka_private_value(session_p, new_object->k_handle,
2317c478bd9Sstevel@tonic-gate 		    &is_pri_obj);
2327c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
2337c478bd9Sstevel@tonic-gate 			goto failed_cleanup;
2347c478bd9Sstevel@tonic-gate 		}
2357c478bd9Sstevel@tonic-gate 
2367c478bd9Sstevel@tonic-gate 		/*
2377c478bd9Sstevel@tonic-gate 		 * Initialize other field of the object wrapper.
2387c478bd9Sstevel@tonic-gate 		 */
2397c478bd9Sstevel@tonic-gate 		new_object->is_lib_obj = B_FALSE;
2407c478bd9Sstevel@tonic-gate 		new_object->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
2417c478bd9Sstevel@tonic-gate 		new_object->session_handle = (CK_SESSION_HANDLE)session_p;
2427c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_init(&new_object->object_mutex, NULL);
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 		if (is_pri_obj)
2457c478bd9Sstevel@tonic-gate 			new_object->bool_attr_mask |= PRIVATE_BOOL_ON;
2467c478bd9Sstevel@tonic-gate 		else
2477c478bd9Sstevel@tonic-gate 			new_object->bool_attr_mask &= ~PRIVATE_BOOL_ON;
2487c478bd9Sstevel@tonic-gate 
2497c478bd9Sstevel@tonic-gate 		if (is_token_obj)
2507c478bd9Sstevel@tonic-gate 			new_object->bool_attr_mask |= TOKEN_BOOL_ON;
2517c478bd9Sstevel@tonic-gate 		else
2527c478bd9Sstevel@tonic-gate 			new_object->bool_attr_mask &= ~TOKEN_BOOL_ON;
2537c478bd9Sstevel@tonic-gate 
2547c478bd9Sstevel@tonic-gate 		/*
2557c478bd9Sstevel@tonic-gate 		 * Add the new copied object into the slot's token list
2567c478bd9Sstevel@tonic-gate 		 * or the session list.  We don't hold the slot lock.
2577c478bd9Sstevel@tonic-gate 		 */
2587c478bd9Sstevel@tonic-gate 		if (is_token_obj) {
2597c478bd9Sstevel@tonic-gate 			pslot = slot_table[session_p->ses_slotid];
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 			/*
2627c478bd9Sstevel@tonic-gate 			 * Decrement the session reference count.
2637c478bd9Sstevel@tonic-gate 			 * We do not hold the session lock.
2647c478bd9Sstevel@tonic-gate 			 */
265*01223cbaSmcpowers 			OBJ_REFRELE(old_object);
2667c478bd9Sstevel@tonic-gate 			REFRELE(session_p, ses_lock_held);
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 			/* Add into the slot token object list. */
2697c478bd9Sstevel@tonic-gate 			kernel_add_token_object_to_slot(new_object, pslot);
2707c478bd9Sstevel@tonic-gate 		} else {
2717c478bd9Sstevel@tonic-gate 			kernel_add_object_to_session(new_object, session_p);
2727c478bd9Sstevel@tonic-gate 
2737c478bd9Sstevel@tonic-gate 			/*
2747c478bd9Sstevel@tonic-gate 			 * Decrement the session reference count.
2757c478bd9Sstevel@tonic-gate 			 * We do not hold the session lock.
2767c478bd9Sstevel@tonic-gate 			 */
277*01223cbaSmcpowers 			OBJ_REFRELE(old_object);
2787c478bd9Sstevel@tonic-gate 			REFRELE(session_p, ses_lock_held);
2797c478bd9Sstevel@tonic-gate 		}
2807c478bd9Sstevel@tonic-gate 
2817c478bd9Sstevel@tonic-gate 		/* set handle of the new object */
2827c478bd9Sstevel@tonic-gate 		*phNewObject = (CK_ULONG)new_object;
2837c478bd9Sstevel@tonic-gate 	}
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate 	return (rv);
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate failed_cleanup:
2887c478bd9Sstevel@tonic-gate 	if (new_object != NULL) {
2897c478bd9Sstevel@tonic-gate 		(void) free(new_object);
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate 
292*01223cbaSmcpowers 	OBJ_REFRELE(old_object);
2937c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
2947c478bd9Sstevel@tonic-gate 	return (rv);
2957c478bd9Sstevel@tonic-gate }
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 
2987c478bd9Sstevel@tonic-gate CK_RV
C_DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)2997c478bd9Sstevel@tonic-gate C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
3007c478bd9Sstevel@tonic-gate {
3017c478bd9Sstevel@tonic-gate 	CK_RV rv;
3027c478bd9Sstevel@tonic-gate 	kernel_object_t *object_p;
303*01223cbaSmcpowers 	kernel_session_t *session_p = (kernel_session_t *)(hSession);
3047c478bd9Sstevel@tonic-gate 	kernel_slot_t	*pslot;
3057c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
3067c478bd9Sstevel@tonic-gate 	CK_SESSION_HANDLE creating_session;
3077c478bd9Sstevel@tonic-gate 
3087c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
3097c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
3107c478bd9Sstevel@tonic-gate 
311*01223cbaSmcpowers 	/*
312*01223cbaSmcpowers 	 * The reason that we don't call handle2session is because
313*01223cbaSmcpowers 	 * the argument hSession may not be the creating_session of
314*01223cbaSmcpowers 	 * the object to be destroyed, and we want to avoid the lock
315*01223cbaSmcpowers 	 * contention. The handle2session will be called later for
316*01223cbaSmcpowers 	 * the creating_session.
317*01223cbaSmcpowers 	 */
318*01223cbaSmcpowers 	if ((session_p == NULL) ||
319*01223cbaSmcpowers 	    (session_p->magic_marker != KERNELTOKEN_SESSION_MAGIC)) {
320*01223cbaSmcpowers 		return (CKR_SESSION_HANDLE_INVALID);
321*01223cbaSmcpowers 	}
3227c478bd9Sstevel@tonic-gate 
323*01223cbaSmcpowers 	/* Obtain the object pointer without incrementing reference count. */
324*01223cbaSmcpowers 	HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
3257c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
326*01223cbaSmcpowers 		return (rv);
3277c478bd9Sstevel@tonic-gate 	}
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	/* Only session objects can be destroyed at a read-only session. */
3307c478bd9Sstevel@tonic-gate 	if ((session_p->ses_RO) &&
3317c478bd9Sstevel@tonic-gate 	    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
332*01223cbaSmcpowers 		return (CKR_SESSION_READ_ONLY);
3337c478bd9Sstevel@tonic-gate 	}
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	/*
3367c478bd9Sstevel@tonic-gate 	 * If the object is a session object, obtain the session handle
3377c478bd9Sstevel@tonic-gate 	 * which object belongs to.  For a token object, we will use the
3387c478bd9Sstevel@tonic-gate 	 * session handle from the caller, because the session used to
3397c478bd9Sstevel@tonic-gate 	 * create the token object may no longer exist.
3407c478bd9Sstevel@tonic-gate 	 */
341*01223cbaSmcpowers 	if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON))
3427c478bd9Sstevel@tonic-gate 		creating_session = object_p->session_handle;
343*01223cbaSmcpowers 	else
344*01223cbaSmcpowers 		creating_session = hSession;
345*01223cbaSmcpowers 
346*01223cbaSmcpowers 	rv = handle2session(creating_session, &session_p);
347*01223cbaSmcpowers 	if (rv != CKR_OK) {
348*01223cbaSmcpowers 		return (rv);
3497c478bd9Sstevel@tonic-gate 	}
3507c478bd9Sstevel@tonic-gate 
351*01223cbaSmcpowers 	/*
352*01223cbaSmcpowers 	 * Set OBJECT_IS_DELETING flag so any access to this
353*01223cbaSmcpowers 	 * object will be rejected.
354*01223cbaSmcpowers 	 */
355*01223cbaSmcpowers 	(void) pthread_mutex_lock(&object_p->object_mutex);
356*01223cbaSmcpowers 	if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
357*01223cbaSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
358*01223cbaSmcpowers 		REFRELE(session_p, ses_lock_held);
359*01223cbaSmcpowers 		return (CKR_OBJECT_HANDLE_INVALID);
360*01223cbaSmcpowers 	}
361*01223cbaSmcpowers 	object_p->obj_delete_sync |= OBJECT_IS_DELETING;
362*01223cbaSmcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
363*01223cbaSmcpowers 
3647c478bd9Sstevel@tonic-gate 	if (object_p->bool_attr_mask & TOKEN_BOOL_ON) {
3657c478bd9Sstevel@tonic-gate 		/*
3667c478bd9Sstevel@tonic-gate 		 * The first FALSE boolean argument indicates that the caller
3677c478bd9Sstevel@tonic-gate 		 * does not hold the slot lock.  The second FALSE boolean
3687c478bd9Sstevel@tonic-gate 		 * argument indicates that the caller wants to clean up the
3697c478bd9Sstevel@tonic-gate 		 * object in the HW provider also.
3707c478bd9Sstevel@tonic-gate 		 */
3717c478bd9Sstevel@tonic-gate 		pslot = slot_table[session_p->ses_slotid];
3727c478bd9Sstevel@tonic-gate 		rv = kernel_delete_token_object(pslot, session_p, object_p,
3737c478bd9Sstevel@tonic-gate 		    B_FALSE, B_FALSE);
3747c478bd9Sstevel@tonic-gate 	} else {
3757c478bd9Sstevel@tonic-gate 		/*
3767c478bd9Sstevel@tonic-gate 		 * The first FALSE boolean argument indicates that the caller
3777c478bd9Sstevel@tonic-gate 		 * does not hold the session lock.  The second FALSE boolean
3787c478bd9Sstevel@tonic-gate 		 * argument indicates that the caller wants to clean the object
3797c478bd9Sstevel@tonic-gate 		 * in the HW provider also.
3807c478bd9Sstevel@tonic-gate 		 */
3817c478bd9Sstevel@tonic-gate 		rv = kernel_delete_session_object(session_p, object_p, B_FALSE,
3827c478bd9Sstevel@tonic-gate 		    B_FALSE);
3837c478bd9Sstevel@tonic-gate 	}
3847c478bd9Sstevel@tonic-gate 	/*
3857c478bd9Sstevel@tonic-gate 	 * Decrement the session reference count.
3867c478bd9Sstevel@tonic-gate 	 * We do not hold the session lock.
3877c478bd9Sstevel@tonic-gate 	 */
3887c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
3897c478bd9Sstevel@tonic-gate 	return (rv);
3907c478bd9Sstevel@tonic-gate }
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate CK_RV
C_GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)3947c478bd9Sstevel@tonic-gate C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
3957c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
3967c478bd9Sstevel@tonic-gate {
3977c478bd9Sstevel@tonic-gate 
3987c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK, rv1 = CKR_OK;
3997c478bd9Sstevel@tonic-gate 	kernel_object_t *object_p;
4007c478bd9Sstevel@tonic-gate 	kernel_session_t *session_p;
4017c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
4027c478bd9Sstevel@tonic-gate 	crypto_object_get_attribute_value_t obj_get_attr;
4037c478bd9Sstevel@tonic-gate 	int i, r;
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
4067c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
4077c478bd9Sstevel@tonic-gate 
4087c478bd9Sstevel@tonic-gate 	if ((pTemplate == NULL) || (ulCount == 0))
4097c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
4107c478bd9Sstevel@tonic-gate 
4117c478bd9Sstevel@tonic-gate 	/*
4127c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
4137c478bd9Sstevel@tonic-gate 	 * reference count.
4147c478bd9Sstevel@tonic-gate 	 */
4157c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
4167c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
4177c478bd9Sstevel@tonic-gate 		return (rv);
4187c478bd9Sstevel@tonic-gate 
4197c478bd9Sstevel@tonic-gate 	/* Obtain the object pointer. */
4207c478bd9Sstevel@tonic-gate 	HANDLE2OBJECT(hObject, object_p, rv);
4217c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
4227c478bd9Sstevel@tonic-gate 		/*
4237c478bd9Sstevel@tonic-gate 		 * Decrement the session reference count.
4247c478bd9Sstevel@tonic-gate 		 * We do not hold the session lock.
4257c478bd9Sstevel@tonic-gate 		 */
4267c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
4277c478bd9Sstevel@tonic-gate 		return (rv);
4287c478bd9Sstevel@tonic-gate 	}
4297c478bd9Sstevel@tonic-gate 
4307c478bd9Sstevel@tonic-gate 	/* Acquire the lock on the object. */
4317c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	if (object_p->is_lib_obj) {
4347c478bd9Sstevel@tonic-gate 		/*
4357c478bd9Sstevel@tonic-gate 		 * The object was created in the library. The library
4367c478bd9Sstevel@tonic-gate 		 * contains the value information of each attribute.
4377c478bd9Sstevel@tonic-gate 		 */
4387c478bd9Sstevel@tonic-gate 		for (i = 0; i < ulCount; i++) {
4397c478bd9Sstevel@tonic-gate 			/*
4407c478bd9Sstevel@tonic-gate 			 * Get the value of each attribute in the template.
4417c478bd9Sstevel@tonic-gate 			 * (We must process EVERY attribute in the template.)
4427c478bd9Sstevel@tonic-gate 			 */
4437c478bd9Sstevel@tonic-gate 			rv = kernel_get_attribute(object_p, &pTemplate[i]);
4447c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK)
4457c478bd9Sstevel@tonic-gate 				/* At least we catch some type of error. */
4467c478bd9Sstevel@tonic-gate 				rv1 = rv;
4477c478bd9Sstevel@tonic-gate 		}
4487c478bd9Sstevel@tonic-gate 		rv = rv1;
449*01223cbaSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
4507c478bd9Sstevel@tonic-gate 	} else {
4517c478bd9Sstevel@tonic-gate 		/*
4527c478bd9Sstevel@tonic-gate 		 * The object was created in HW provider, call ioctl to get
4537c478bd9Sstevel@tonic-gate 		 * the values of attributes.
4547c478bd9Sstevel@tonic-gate 		 */
4557c478bd9Sstevel@tonic-gate 		obj_get_attr.og_session = session_p->k_session;
4567c478bd9Sstevel@tonic-gate 		obj_get_attr.og_handle = object_p->k_handle;
457*01223cbaSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
4587c478bd9Sstevel@tonic-gate 		obj_get_attr.og_count = ulCount;
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 		rv = process_object_attributes(pTemplate, ulCount,
4617c478bd9Sstevel@tonic-gate 		    &obj_get_attr.og_attributes, NULL);
4627c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
4637c478bd9Sstevel@tonic-gate 			goto clean_exit;
4647c478bd9Sstevel@tonic-gate 		}
4657c478bd9Sstevel@tonic-gate 
4667c478bd9Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
4677c478bd9Sstevel@tonic-gate 		    &obj_get_attr)) < 0) {
4687c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
4697c478bd9Sstevel@tonic-gate 				break;
4707c478bd9Sstevel@tonic-gate 		}
4717c478bd9Sstevel@tonic-gate 		if (r < 0) {
4727c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
4737c478bd9Sstevel@tonic-gate 		} else {
4747c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
4757c478bd9Sstevel@tonic-gate 			    obj_get_attr.og_return_value);
4767c478bd9Sstevel@tonic-gate 		}
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 		/*
4797c478bd9Sstevel@tonic-gate 		 * The error codes CKR_ATTRIBUTE_SENSITIVE,
4807c478bd9Sstevel@tonic-gate 		 * CKR_ATTRIBUTE_TYPE_INVALID, and CKR_BUFFER_TOO_SMALL
4817c478bd9Sstevel@tonic-gate 		 * do not denote true errors for this function. If a call
4827c478bd9Sstevel@tonic-gate 		 * returns any of these three values, then the call must
4837c478bd9Sstevel@tonic-gate 		 * nonetheless have processed every attribute in the
4847c478bd9Sstevel@tonic-gate 		 * template.  Every attribute in the template whose value
4857c478bd9Sstevel@tonic-gate 		 * can be returned will be returned.
4867c478bd9Sstevel@tonic-gate 		 */
4877c478bd9Sstevel@tonic-gate 		if ((rv == CKR_OK) ||
4887c478bd9Sstevel@tonic-gate 		    (rv == CKR_ATTRIBUTE_SENSITIVE) ||
4897c478bd9Sstevel@tonic-gate 		    (rv == CKR_ATTRIBUTE_TYPE_INVALID) ||
4907c478bd9Sstevel@tonic-gate 		    (rv == CKR_BUFFER_TOO_SMALL)) {
4917c478bd9Sstevel@tonic-gate 			rv1 = get_object_attributes(pTemplate, ulCount,
4927c478bd9Sstevel@tonic-gate 			    obj_get_attr.og_attributes);
4937c478bd9Sstevel@tonic-gate 			if (rv1 != CKR_OK) {
4947c478bd9Sstevel@tonic-gate 				rv = rv1;
4957c478bd9Sstevel@tonic-gate 			}
4967c478bd9Sstevel@tonic-gate 		}
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 		/* Free the attributes' allocated for the ioctl call. */
4997c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_get_attr.og_attributes, ulCount);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate clean_exit:
5037c478bd9Sstevel@tonic-gate 	/*
5047c478bd9Sstevel@tonic-gate 	 * Decrement the session reference count.
5057c478bd9Sstevel@tonic-gate 	 * We do not hold the session lock.
5067c478bd9Sstevel@tonic-gate 	 */
507*01223cbaSmcpowers 	OBJ_REFRELE(object_p);
5087c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
5097c478bd9Sstevel@tonic-gate 	return (rv);
5107c478bd9Sstevel@tonic-gate }
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate CK_RV
C_SetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)5147c478bd9Sstevel@tonic-gate C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
5157c478bd9Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
5167c478bd9Sstevel@tonic-gate {
5177c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
5187c478bd9Sstevel@tonic-gate 	kernel_object_t *object_p;
5197c478bd9Sstevel@tonic-gate 	kernel_object_t *new_object = NULL;
5207c478bd9Sstevel@tonic-gate 	kernel_session_t *session_p;
5217c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
5227c478bd9Sstevel@tonic-gate 	crypto_object_set_attribute_value_t obj_set_attr;
5237c478bd9Sstevel@tonic-gate 	int i, r;
5247c478bd9Sstevel@tonic-gate 
5257c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
5267c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 	if ((pTemplate == NULL) || (ulCount == 0))
5297c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	/*
5327c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
5337c478bd9Sstevel@tonic-gate 	 * reference count.
5347c478bd9Sstevel@tonic-gate 	 */
5357c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
5367c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
5377c478bd9Sstevel@tonic-gate 		return (rv);
5387c478bd9Sstevel@tonic-gate 
5397c478bd9Sstevel@tonic-gate 	/* Obtain the object pointer. */
5407c478bd9Sstevel@tonic-gate 	HANDLE2OBJECT(hObject, object_p, rv);
5417c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
5427c478bd9Sstevel@tonic-gate 		/*
5437c478bd9Sstevel@tonic-gate 		 * Decrement the session reference count.
5447c478bd9Sstevel@tonic-gate 		 * We do not hold the session lock.
5457c478bd9Sstevel@tonic-gate 		 */
5467c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
5477c478bd9Sstevel@tonic-gate 		return (rv);
5487c478bd9Sstevel@tonic-gate 	}
5497c478bd9Sstevel@tonic-gate 
5507c478bd9Sstevel@tonic-gate 	/* lock the object */
5517c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
5527c478bd9Sstevel@tonic-gate 
5537c478bd9Sstevel@tonic-gate 	/*
5547c478bd9Sstevel@tonic-gate 	 * If the object was created in the HW provider, changing its
5557c478bd9Sstevel@tonic-gate 	 * attributes' values need to be done in the provider too.
5567c478bd9Sstevel@tonic-gate 	 */
5577c478bd9Sstevel@tonic-gate 	if (!object_p->is_lib_obj) {
5587c478bd9Sstevel@tonic-gate 
5597c478bd9Sstevel@tonic-gate 		/* Cannot modify a token object with a READ-ONLY session */
5607c478bd9Sstevel@tonic-gate 		if (session_p->ses_RO &&
5617c478bd9Sstevel@tonic-gate 		    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
5627c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&object_p->object_mutex);
563*01223cbaSmcpowers 			rv = CKR_SESSION_READ_ONLY;
564*01223cbaSmcpowers 			goto clean_exit;
5657c478bd9Sstevel@tonic-gate 		}
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 		obj_set_attr.sa_session = session_p->k_session;
5687c478bd9Sstevel@tonic-gate 		obj_set_attr.sa_handle = object_p->k_handle;
569*01223cbaSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5707c478bd9Sstevel@tonic-gate 		obj_set_attr.sa_count = ulCount;
5717c478bd9Sstevel@tonic-gate 		rv = process_object_attributes(pTemplate, ulCount,
5727c478bd9Sstevel@tonic-gate 		    &obj_set_attr.sa_attributes, NULL);
5737c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
574*01223cbaSmcpowers 			goto clean_exit;
5757c478bd9Sstevel@tonic-gate 		}
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE,
5787c478bd9Sstevel@tonic-gate 		    &obj_set_attr)) < 0) {
5797c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
5807c478bd9Sstevel@tonic-gate 				break;
5817c478bd9Sstevel@tonic-gate 		}
5827c478bd9Sstevel@tonic-gate 		if (r < 0) {
5837c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
5847c478bd9Sstevel@tonic-gate 		} else {
5857c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
5867c478bd9Sstevel@tonic-gate 			    obj_set_attr.sa_return_value);
5877c478bd9Sstevel@tonic-gate 		}
5887c478bd9Sstevel@tonic-gate 
5897c478bd9Sstevel@tonic-gate 		/* Free the attributes' space allocated for the ioctl call. */
5907c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_set_attr.sa_attributes, ulCount);
591*01223cbaSmcpowers 		goto clean_exit;
5927c478bd9Sstevel@tonic-gate 	}
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	/*
5957c478bd9Sstevel@tonic-gate 	 * if we come here, the object must have been created in the
5967c478bd9Sstevel@tonic-gate 	 * library.  The work will be done completely in the library.
5977c478bd9Sstevel@tonic-gate 	 *
5987c478bd9Sstevel@tonic-gate 	 * Copy the old object to a new object. We work on the copied
5997c478bd9Sstevel@tonic-gate 	 * version because in case of error we still keep the old one
6007c478bd9Sstevel@tonic-gate 	 * intact.
6017c478bd9Sstevel@tonic-gate 	 */
6027c478bd9Sstevel@tonic-gate 	rv = kernel_copy_object(object_p, &new_object, B_FALSE, NULL);
603*01223cbaSmcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6047c478bd9Sstevel@tonic-gate 	if ((rv != CKR_OK) || (new_object == NULL)) {
6057c478bd9Sstevel@tonic-gate 		/*
606*01223cbaSmcpowers 		 * Most likely we ran out of space.
6077c478bd9Sstevel@tonic-gate 		 * Decrement the session reference count.
6087c478bd9Sstevel@tonic-gate 		 * We do not hold the session lock.
6097c478bd9Sstevel@tonic-gate 		 */
610*01223cbaSmcpowers 		goto clean_exit;
6117c478bd9Sstevel@tonic-gate 	}
6127c478bd9Sstevel@tonic-gate 
6137c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
6147c478bd9Sstevel@tonic-gate 		/* Set the requested attribute into the new object. */
6157c478bd9Sstevel@tonic-gate 		rv = kernel_set_attribute(new_object, &pTemplate[i], B_FALSE,
6167c478bd9Sstevel@tonic-gate 		    session_p);
6177c478bd9Sstevel@tonic-gate 
6187c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
6197c478bd9Sstevel@tonic-gate 			kernel_cleanup_object(new_object);
620*01223cbaSmcpowers 			goto clean_exit;
6217c478bd9Sstevel@tonic-gate 		}
6227c478bd9Sstevel@tonic-gate 	}
6237c478bd9Sstevel@tonic-gate 
6247c478bd9Sstevel@tonic-gate 	/*
6257c478bd9Sstevel@tonic-gate 	 * We've successfully set all the requested attributes.
6267c478bd9Sstevel@tonic-gate 	 * Merge the new object with the old object, then destory
6277c478bd9Sstevel@tonic-gate 	 * the new one. The reason to do the merging is because we
6287c478bd9Sstevel@tonic-gate 	 * have to keep the original object handle (address of object).
6297c478bd9Sstevel@tonic-gate 	 */
6307c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
6317c478bd9Sstevel@tonic-gate 	kernel_merge_object(object_p, new_object);
6327c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object_p->object_mutex);
633*01223cbaSmcpowers 
634*01223cbaSmcpowers clean_exit:
635*01223cbaSmcpowers 	if (new_object != NULL)
636*01223cbaSmcpowers 		(void) free(new_object);
6377c478bd9Sstevel@tonic-gate 
6387c478bd9Sstevel@tonic-gate 	/*
6397c478bd9Sstevel@tonic-gate 	 * Decrement the session reference count.
6407c478bd9Sstevel@tonic-gate 	 * We do not hold the session lock.
6417c478bd9Sstevel@tonic-gate 	 */
642*01223cbaSmcpowers 	OBJ_REFRELE(object_p);
6437c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 	return (rv);
6467c478bd9Sstevel@tonic-gate }
6477c478bd9Sstevel@tonic-gate 
6487c478bd9Sstevel@tonic-gate 
6497c478bd9Sstevel@tonic-gate CK_RV
C_GetObjectSize(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ULONG_PTR pulSize)6507c478bd9Sstevel@tonic-gate C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
6517c478bd9Sstevel@tonic-gate     CK_ULONG_PTR pulSize)
6527c478bd9Sstevel@tonic-gate {
6537c478bd9Sstevel@tonic-gate 
6547c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6557c478bd9Sstevel@tonic-gate 	kernel_object_t *object_p;
6567c478bd9Sstevel@tonic-gate 	kernel_session_t *session_p;
6577c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
6587c478bd9Sstevel@tonic-gate 	crypto_object_get_size_t obj_gs;
6597c478bd9Sstevel@tonic-gate 	int r;
6607c478bd9Sstevel@tonic-gate 
6617c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
6627c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
6637c478bd9Sstevel@tonic-gate 
6647c478bd9Sstevel@tonic-gate 	/* Check if pulSize is valid */
6657c478bd9Sstevel@tonic-gate 	if (pulSize == NULL) {
6667c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
6677c478bd9Sstevel@tonic-gate 	}
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate 	/*
6707c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
6717c478bd9Sstevel@tonic-gate 	 * reference count.
6727c478bd9Sstevel@tonic-gate 	 */
6737c478bd9Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
6747c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
6757c478bd9Sstevel@tonic-gate 		return (rv);
6767c478bd9Sstevel@tonic-gate 
6777c478bd9Sstevel@tonic-gate 	/* Obtain the object pointer. */
6787c478bd9Sstevel@tonic-gate 	HANDLE2OBJECT(hObject, object_p, rv);
6797c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
6807c478bd9Sstevel@tonic-gate 		/*
6817c478bd9Sstevel@tonic-gate 		 * Decrement the session reference count.
6827c478bd9Sstevel@tonic-gate 		 * We do not hold the session lock.
6837c478bd9Sstevel@tonic-gate 		 */
6847c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
6857c478bd9Sstevel@tonic-gate 		return (rv);
6867c478bd9Sstevel@tonic-gate 	}
6877c478bd9Sstevel@tonic-gate 
6887c478bd9Sstevel@tonic-gate 	/* Acquire the lock on the object. */
6897c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
6907c478bd9Sstevel@tonic-gate 
6917c478bd9Sstevel@tonic-gate 	if (!object_p->is_lib_obj) {
6927c478bd9Sstevel@tonic-gate 		/*
6937c478bd9Sstevel@tonic-gate 		 * The object was created in HW provider, call the
6947c478bd9Sstevel@tonic-gate 		 * CRYPTO_OBJECT_GET_SIZE ioctl.
6957c478bd9Sstevel@tonic-gate 		 */
6967c478bd9Sstevel@tonic-gate 		obj_gs.gs_session = session_p->k_session;
6977c478bd9Sstevel@tonic-gate 		obj_gs.gs_handle = object_p->k_handle;
698*01223cbaSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
6997c478bd9Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_SIZE,
7007c478bd9Sstevel@tonic-gate 		    &obj_gs)) < 0) {
7017c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
7027c478bd9Sstevel@tonic-gate 				break;
7037c478bd9Sstevel@tonic-gate 		}
7047c478bd9Sstevel@tonic-gate 		if (r < 0) {
7057c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
7067c478bd9Sstevel@tonic-gate 		} else {
7077c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
7087c478bd9Sstevel@tonic-gate 			    obj_gs.gs_return_value);
7097c478bd9Sstevel@tonic-gate 		}
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@tonic-gate 		if (rv == CKR_OK) {
7127c478bd9Sstevel@tonic-gate 			*pulSize = obj_gs.gs_size;
7137c478bd9Sstevel@tonic-gate 		}
7147c478bd9Sstevel@tonic-gate 
7157c478bd9Sstevel@tonic-gate 	} else {
7167c478bd9Sstevel@tonic-gate 		rv = kernel_get_object_size(object_p, pulSize);
717*01223cbaSmcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
7187c478bd9Sstevel@tonic-gate 	}
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	/*
7217c478bd9Sstevel@tonic-gate 	 * Decrement the session reference count.
7227c478bd9Sstevel@tonic-gate 	 * We do not hold the session lock.
7237c478bd9Sstevel@tonic-gate 	 */
724*01223cbaSmcpowers 	OBJ_REFRELE(object_p);
7257c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
7267c478bd9Sstevel@tonic-gate 	return (rv);
7277c478bd9Sstevel@tonic-gate }
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate CK_RV
C_FindObjectsInit(CK_SESSION_HANDLE sh,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)7317c478bd9Sstevel@tonic-gate C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
7327c478bd9Sstevel@tonic-gate     CK_ULONG ulCount)
7337c478bd9Sstevel@tonic-gate {
7347c478bd9Sstevel@tonic-gate 	CK_RV		rv;
7357c478bd9Sstevel@tonic-gate 	kernel_session_t	*session_p;
7367c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
7377c478bd9Sstevel@tonic-gate 	kernel_slot_t *pslot;
7387c478bd9Sstevel@tonic-gate 	crypto_object_find_init_t obj_fi;
7397c478bd9Sstevel@tonic-gate 	int r;
7407c478bd9Sstevel@tonic-gate 
7417c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
7427c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	/* Check the arguments */
7457c478bd9Sstevel@tonic-gate 	if ((ulCount > 0) && (pTemplate == NULL)) {
7467c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
7477c478bd9Sstevel@tonic-gate 	}
7487c478bd9Sstevel@tonic-gate 
7497c478bd9Sstevel@tonic-gate 	/*
7507c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
7517c478bd9Sstevel@tonic-gate 	 * reference count.
7527c478bd9Sstevel@tonic-gate 	 */
7537c478bd9Sstevel@tonic-gate 	rv = handle2session(sh, &session_p);
7547c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
7557c478bd9Sstevel@tonic-gate 		return (rv);
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	/* Acquire the session lock */
7587c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
7597c478bd9Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
7607c478bd9Sstevel@tonic-gate 
7617c478bd9Sstevel@tonic-gate 	/* Check to see if find operation is already active */
7627c478bd9Sstevel@tonic-gate 	if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
7637c478bd9Sstevel@tonic-gate 		/* decrement the session count, and unlock the mutex */
7647c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
7657c478bd9Sstevel@tonic-gate 		return (CKR_OPERATION_ACTIVE);
7667c478bd9Sstevel@tonic-gate 	} else {
7677c478bd9Sstevel@tonic-gate 		/*
7687c478bd9Sstevel@tonic-gate 		 * This active flag will remain ON until application calls
7697c478bd9Sstevel@tonic-gate 		 * C_FindObjectsFinal.
7707c478bd9Sstevel@tonic-gate 		 */
7717c478bd9Sstevel@tonic-gate 		session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
7727c478bd9Sstevel@tonic-gate 	}
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 
7757c478bd9Sstevel@tonic-gate 	/*
7767c478bd9Sstevel@tonic-gate 	 * If the HW provider supports object creation, we call the
7777c478bd9Sstevel@tonic-gate 	 * CRYPTO_OBJECT_FIND_INIT ioctl to initialize object finding.
7787c478bd9Sstevel@tonic-gate 	 * Otherwise, all the objects are created in the library and we
7797c478bd9Sstevel@tonic-gate 	 * do the find objects solely in the library.
7807c478bd9Sstevel@tonic-gate 	 */
7817c478bd9Sstevel@tonic-gate 	pslot = slot_table[session_p->ses_slotid];
7827c478bd9Sstevel@tonic-gate 	if (pslot->sl_func_list.fl_object_create) {
7837c478bd9Sstevel@tonic-gate 		obj_fi.fi_session = session_p->k_session;
7847c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
7857c478bd9Sstevel@tonic-gate 		ses_lock_held = B_FALSE;
7867c478bd9Sstevel@tonic-gate 		obj_fi.fi_count = ulCount;
7877c478bd9Sstevel@tonic-gate 		rv = process_object_attributes(pTemplate, ulCount,
7887c478bd9Sstevel@tonic-gate 		    &obj_fi.fi_attributes, NULL);
7897c478bd9Sstevel@tonic-gate 		if (rv == CKR_OK) {
7907c478bd9Sstevel@tonic-gate 			while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_INIT,
7917c478bd9Sstevel@tonic-gate 			    &obj_fi)) < 0) {
7927c478bd9Sstevel@tonic-gate 				if (errno != EINTR)
7937c478bd9Sstevel@tonic-gate 					break;
7947c478bd9Sstevel@tonic-gate 			}
7957c478bd9Sstevel@tonic-gate 			if (r < 0) {
7967c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
7977c478bd9Sstevel@tonic-gate 			} else {
7987c478bd9Sstevel@tonic-gate 				rv = crypto2pkcs11_error_number(
7997c478bd9Sstevel@tonic-gate 				    obj_fi.fi_return_value);
8007c478bd9Sstevel@tonic-gate 			}
8017c478bd9Sstevel@tonic-gate 		}
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 		/* Free the attributes' space allocated for the ioctl call. */
8047c478bd9Sstevel@tonic-gate 		free_object_attributes(obj_fi.fi_attributes, ulCount);
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 	} else {
8077c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
8087c478bd9Sstevel@tonic-gate 		ses_lock_held = B_FALSE;
8097c478bd9Sstevel@tonic-gate 		rv = kernel_find_objects_init(session_p,  pTemplate, ulCount);
8107c478bd9Sstevel@tonic-gate 	}
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
8137c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
8147c478bd9Sstevel@tonic-gate 		session_p->find_objects.flags = 0;
8157c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
8167c478bd9Sstevel@tonic-gate 	}
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	/* decrement the session count, and unlock the mutex */
8197c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
8207c478bd9Sstevel@tonic-gate 	return (rv);
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate }
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate CK_RV
C_FindObjects(CK_SESSION_HANDLE sh,CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)8257c478bd9Sstevel@tonic-gate C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject,
8267c478bd9Sstevel@tonic-gate     CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
8277c478bd9Sstevel@tonic-gate {
8287c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
8297c478bd9Sstevel@tonic-gate 	kernel_slot_t		*pslot;
8307c478bd9Sstevel@tonic-gate 	kernel_session_t	*session_p;
8317c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
8327c478bd9Sstevel@tonic-gate 	crypto_object_find_update_t obj_fu;
8337c478bd9Sstevel@tonic-gate 	int r;
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
8367c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate 	/* check for invalid arguments */
8397c478bd9Sstevel@tonic-gate 	if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
8407c478bd9Sstevel@tonic-gate 	    (pulObjectCount == NULL)) {
8417c478bd9Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
8427c478bd9Sstevel@tonic-gate 	}
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	if (ulMaxObjectCount == 0) {
8457c478bd9Sstevel@tonic-gate 		/* don't need to do anything, just return */
8467c478bd9Sstevel@tonic-gate 		*pulObjectCount = 0;
8477c478bd9Sstevel@tonic-gate 		return (CKR_OK);
8487c478bd9Sstevel@tonic-gate 	}
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	/*
8517c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
8527c478bd9Sstevel@tonic-gate 	 * reference count.
8537c478bd9Sstevel@tonic-gate 	 */
8547c478bd9Sstevel@tonic-gate 	rv = handle2session(sh, &session_p);
8557c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
8567c478bd9Sstevel@tonic-gate 		return (rv);
8577c478bd9Sstevel@tonic-gate 
8587c478bd9Sstevel@tonic-gate 	/* Acquire the slot lock */
8597c478bd9Sstevel@tonic-gate 	pslot = slot_table[session_p->ses_slotid];
8607c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&pslot->sl_mutex);
8617c478bd9Sstevel@tonic-gate 
8627c478bd9Sstevel@tonic-gate 	/* Acquire the session lock */
8637c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
8647c478bd9Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
8657c478bd9Sstevel@tonic-gate 
8667c478bd9Sstevel@tonic-gate 	/* Check to see if find operation is active */
8677c478bd9Sstevel@tonic-gate 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
8687c478bd9Sstevel@tonic-gate 		rv = CKR_OPERATION_NOT_INITIALIZED;
8697c478bd9Sstevel@tonic-gate 		goto clean_exit;
8707c478bd9Sstevel@tonic-gate 	}
8717c478bd9Sstevel@tonic-gate 
8727c478bd9Sstevel@tonic-gate 	/*
8737c478bd9Sstevel@tonic-gate 	 * Similar to C_FindObjectInit(), if the HW provider supports object
8747c478bd9Sstevel@tonic-gate 	 * creation, we call the respective ioctl to find objects.
8757c478bd9Sstevel@tonic-gate 	 * Otherwise, all the objects are created in the library and we do
8767c478bd9Sstevel@tonic-gate 	 * the find objects solely in the library.
8777c478bd9Sstevel@tonic-gate 	 */
8787c478bd9Sstevel@tonic-gate 	if (pslot->sl_func_list.fl_object_create) {
8797c478bd9Sstevel@tonic-gate 		obj_fu.fu_session = session_p->k_session;
8807c478bd9Sstevel@tonic-gate 		obj_fu.fu_max_count = ulMaxObjectCount;
8817c478bd9Sstevel@tonic-gate 		obj_fu.fu_handles = (char *)calloc(1,
8827c478bd9Sstevel@tonic-gate 		    ulMaxObjectCount * sizeof (crypto_object_id_t));
8837c478bd9Sstevel@tonic-gate 		if (obj_fu.fu_handles == NULL) {
8847c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
8857c478bd9Sstevel@tonic-gate 			goto clean_exit;
8867c478bd9Sstevel@tonic-gate 		}
8877c478bd9Sstevel@tonic-gate 
8887c478bd9Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_UPDATE,
8897c478bd9Sstevel@tonic-gate 		    &obj_fu)) < 0) {
8907c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
8917c478bd9Sstevel@tonic-gate 				break;
8927c478bd9Sstevel@tonic-gate 		}
8937c478bd9Sstevel@tonic-gate 		if (r < 0) {
8947c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
8957c478bd9Sstevel@tonic-gate 		} else {
8967c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
8977c478bd9Sstevel@tonic-gate 			    obj_fu.fu_return_value);
8987c478bd9Sstevel@tonic-gate 		}
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate 		if (rv == CKR_OK) {
9017c478bd9Sstevel@tonic-gate 			rv = process_found_objects(session_p, phObject,
9027c478bd9Sstevel@tonic-gate 			    pulObjectCount, obj_fu);
9037c478bd9Sstevel@tonic-gate 		}
9047c478bd9Sstevel@tonic-gate 		free(obj_fu.fu_handles);
9057c478bd9Sstevel@tonic-gate 
9067c478bd9Sstevel@tonic-gate 	} else {
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 		kernel_find_objects(session_p, phObject, ulMaxObjectCount,
9097c478bd9Sstevel@tonic-gate 		    pulObjectCount);
9107c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
9117c478bd9Sstevel@tonic-gate 	}
9127c478bd9Sstevel@tonic-gate 
9137c478bd9Sstevel@tonic-gate clean_exit:
9147c478bd9Sstevel@tonic-gate 	/* decrement the session count, and release the session lock */
9157c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
9167c478bd9Sstevel@tonic-gate 
9177c478bd9Sstevel@tonic-gate 	/* release the slot lock */
9187c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
9197c478bd9Sstevel@tonic-gate 
9207c478bd9Sstevel@tonic-gate 	return (rv);
9217c478bd9Sstevel@tonic-gate }
9227c478bd9Sstevel@tonic-gate 
9237c478bd9Sstevel@tonic-gate 
9247c478bd9Sstevel@tonic-gate CK_RV
C_FindObjectsFinal(CK_SESSION_HANDLE sh)9257c478bd9Sstevel@tonic-gate C_FindObjectsFinal(CK_SESSION_HANDLE sh)
9267c478bd9Sstevel@tonic-gate {
9277c478bd9Sstevel@tonic-gate 
9287c478bd9Sstevel@tonic-gate 	kernel_session_t	*session_p;
9297c478bd9Sstevel@tonic-gate 	CK_RV rv;
9307c478bd9Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
9317c478bd9Sstevel@tonic-gate 	kernel_slot_t *pslot;
9327c478bd9Sstevel@tonic-gate 	crypto_object_find_final_t obj_ff;
9337c478bd9Sstevel@tonic-gate 	int r;
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate 	if (!kernel_initialized)
9367c478bd9Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate 	/*
9397c478bd9Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
9407c478bd9Sstevel@tonic-gate 	 * reference count.
9417c478bd9Sstevel@tonic-gate 	 */
9427c478bd9Sstevel@tonic-gate 	rv = handle2session(sh, &session_p);
9437c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
9447c478bd9Sstevel@tonic-gate 		return (rv);
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	/* Acquire the session lock */
9477c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
9487c478bd9Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	/* Check to see if find operation is active */
9517c478bd9Sstevel@tonic-gate 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
9527c478bd9Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
9537c478bd9Sstevel@tonic-gate 		return (CKR_OPERATION_NOT_INITIALIZED);
9547c478bd9Sstevel@tonic-gate 	}
9557c478bd9Sstevel@tonic-gate 
9567c478bd9Sstevel@tonic-gate 	/*
9577c478bd9Sstevel@tonic-gate 	 * Similar to C_FindObjectInit(), if the HW provider supports object
9587c478bd9Sstevel@tonic-gate 	 * creation, we need to call the CRYPTO_OBJECT_FIND_FINAL ioctl.
9597c478bd9Sstevel@tonic-gate 	 */
9607c478bd9Sstevel@tonic-gate 	pslot = slot_table[session_p->ses_slotid];
9617c478bd9Sstevel@tonic-gate 	if (pslot->sl_func_list.fl_object_create) {
9627c478bd9Sstevel@tonic-gate 		obj_ff.ff_session = session_p->k_session;
9637c478bd9Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_FINAL,
9647c478bd9Sstevel@tonic-gate 		    &obj_ff)) < 0) {
9657c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
9667c478bd9Sstevel@tonic-gate 				break;
9677c478bd9Sstevel@tonic-gate 		}
9687c478bd9Sstevel@tonic-gate 		if (r < 0) {
9697c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
9707c478bd9Sstevel@tonic-gate 		} else {
9717c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
9727c478bd9Sstevel@tonic-gate 			    obj_ff.ff_return_value);
9737c478bd9Sstevel@tonic-gate 		}
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 		/* only need to reset find_objects.flags */
9767c478bd9Sstevel@tonic-gate 		if (rv == CKR_OK) {
9777c478bd9Sstevel@tonic-gate 			session_p->find_objects.flags = 0;
9787c478bd9Sstevel@tonic-gate 		}
9797c478bd9Sstevel@tonic-gate 
9807c478bd9Sstevel@tonic-gate 	} else {
9817c478bd9Sstevel@tonic-gate 		/*
9827c478bd9Sstevel@tonic-gate 		 * The find object operations were done in the library, we
9837c478bd9Sstevel@tonic-gate 		 * need to cleanup find_objects context.
9847c478bd9Sstevel@tonic-gate 		 */
9857c478bd9Sstevel@tonic-gate 		kernel_find_objects_final(session_p);
9867c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
9877c478bd9Sstevel@tonic-gate 	}
9887c478bd9Sstevel@tonic-gate 
9897c478bd9Sstevel@tonic-gate 	/* decrement the session count, and release the lock */
9907c478bd9Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
9917c478bd9Sstevel@tonic-gate 	return (rv);
9927c478bd9Sstevel@tonic-gate }
993