10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
230Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate #include <pthread.h>
300Sstevel@tonic-gate #include <stdlib.h>
310Sstevel@tonic-gate #include <errno.h>
320Sstevel@tonic-gate #include <security/cryptoki.h>
330Sstevel@tonic-gate #include "kernelGlobal.h"
340Sstevel@tonic-gate #include "kernelObject.h"
350Sstevel@tonic-gate #include "kernelSession.h"
360Sstevel@tonic-gate #include <errno.h>
370Sstevel@tonic-gate #include <string.h>
380Sstevel@tonic-gate #include <cryptoutil.h>
390Sstevel@tonic-gate 
400Sstevel@tonic-gate CK_RV
C_CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject)410Sstevel@tonic-gate C_CreateObject(CK_SESSION_HANDLE hSession,
420Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate,
430Sstevel@tonic-gate     CK_ULONG ulCount,
440Sstevel@tonic-gate     CK_OBJECT_HANDLE_PTR phObject)
450Sstevel@tonic-gate {
460Sstevel@tonic-gate 
470Sstevel@tonic-gate 	CK_RV rv;
480Sstevel@tonic-gate 	kernel_session_t *session_p;
490Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
500Sstevel@tonic-gate 
510Sstevel@tonic-gate 	if (!kernel_initialized)
520Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	if ((pTemplate == NULL) || (ulCount == 0) ||
550Sstevel@tonic-gate 	    (phObject == NULL)) {
560Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
570Sstevel@tonic-gate 	}
580Sstevel@tonic-gate 
590Sstevel@tonic-gate 	/*
600Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
610Sstevel@tonic-gate 	 * reference count.
620Sstevel@tonic-gate 	 */
630Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
640Sstevel@tonic-gate 	if (rv != CKR_OK)
650Sstevel@tonic-gate 		return (rv);
660Sstevel@tonic-gate 
670Sstevel@tonic-gate 	/* Create a new object. */
680Sstevel@tonic-gate 	rv = kernel_add_object(pTemplate, ulCount, phObject, session_p);
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	/*
710Sstevel@tonic-gate 	 * Decrement the session reference count.
720Sstevel@tonic-gate 	 * We do not hold the session lock.
730Sstevel@tonic-gate 	 */
740Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	return (rv);
770Sstevel@tonic-gate }
780Sstevel@tonic-gate 
790Sstevel@tonic-gate 
800Sstevel@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)810Sstevel@tonic-gate C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
820Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
830Sstevel@tonic-gate     CK_OBJECT_HANDLE_PTR phNewObject)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	CK_RV rv;
870Sstevel@tonic-gate 	kernel_session_t *session_p;
880Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
890Sstevel@tonic-gate 	kernel_object_t *old_object;
900Sstevel@tonic-gate 	kernel_object_t *new_object = NULL;
910Sstevel@tonic-gate 	crypto_object_copy_t  object_copy;
920Sstevel@tonic-gate 	CK_BBOOL is_pri_obj = FALSE;
930Sstevel@tonic-gate 	CK_BBOOL is_token_obj = FALSE;
940Sstevel@tonic-gate 	kernel_slot_t	*pslot;
950Sstevel@tonic-gate 	int i, r;
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 	if (!kernel_initialized)
980Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 	/* Check arguments */
1010Sstevel@tonic-gate 	if (((ulCount > 0) && (pTemplate == NULL)) ||
1020Sstevel@tonic-gate 	    (phNewObject == NULL)) {
1030Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
1040Sstevel@tonic-gate 	}
1050Sstevel@tonic-gate 
1060Sstevel@tonic-gate 	/*
1070Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
1080Sstevel@tonic-gate 	 * reference count.
1090Sstevel@tonic-gate 	 */
1100Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
1110Sstevel@tonic-gate 	if (rv != CKR_OK)
1120Sstevel@tonic-gate 		return (rv);
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	/* Obtain the object pointer. */
1150Sstevel@tonic-gate 	HANDLE2OBJECT(hObject, old_object, rv);
1160Sstevel@tonic-gate 	if (rv != CKR_OK) {
1170Sstevel@tonic-gate 		/*
1180Sstevel@tonic-gate 		 * Decrement the session reference count.
1190Sstevel@tonic-gate 		 * We do not hold the session lock.
1200Sstevel@tonic-gate 		 */
1210Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
1220Sstevel@tonic-gate 		return (rv);
1230Sstevel@tonic-gate 	}
1240Sstevel@tonic-gate 
1250Sstevel@tonic-gate 	(void) pthread_mutex_lock(&old_object->object_mutex);
1260Sstevel@tonic-gate 
1270Sstevel@tonic-gate 	if (old_object->is_lib_obj) {
1280Sstevel@tonic-gate 		/*
1290Sstevel@tonic-gate 		 * Copy the old object to a new object.
1300Sstevel@tonic-gate 		 * The 3rd argument with TRUE value indicates that
1310Sstevel@tonic-gate 		 * everything in the object will be duplicated.
1320Sstevel@tonic-gate 		 */
1330Sstevel@tonic-gate 		rv = kernel_copy_object(old_object, &new_object, B_TRUE,
1340Sstevel@tonic-gate 		    session_p);
135*214Smcpowers 		(void) pthread_mutex_unlock(&old_object->object_mutex);
1360Sstevel@tonic-gate 		if ((rv != CKR_OK) || (new_object == NULL)) {
1370Sstevel@tonic-gate 			/*
138*214Smcpowers 			 * Most likely we ran out of space.
1390Sstevel@tonic-gate 			 * Decrement the session reference count.
1400Sstevel@tonic-gate 			 * We do not hold the session lock.
1410Sstevel@tonic-gate 			 */
142*214Smcpowers 			OBJ_REFRELE(old_object);
1430Sstevel@tonic-gate 			REFRELE(session_p, ses_lock_held);
1440Sstevel@tonic-gate 			return (rv);
1450Sstevel@tonic-gate 		}
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 		new_object->is_lib_obj = B_TRUE;
1480Sstevel@tonic-gate 
1490Sstevel@tonic-gate 		/* Modify the object attribute if requested */
1500Sstevel@tonic-gate 		for (i = 0; i < ulCount; i++) {
1510Sstevel@tonic-gate 			/* Set the requested attribute into the new object. */
1520Sstevel@tonic-gate 			rv = kernel_set_attribute(new_object, &pTemplate[i],
1530Sstevel@tonic-gate 			    B_TRUE, session_p);
1540Sstevel@tonic-gate 
1550Sstevel@tonic-gate 			if (rv != CKR_OK) {
1560Sstevel@tonic-gate 				kernel_cleanup_object(new_object);
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 				/*
1590Sstevel@tonic-gate 				 * Decrement the session reference count.
1600Sstevel@tonic-gate 				 * We do not hold the session lock.
1610Sstevel@tonic-gate 				 */
162*214Smcpowers 				OBJ_REFRELE(old_object);
1630Sstevel@tonic-gate 				REFRELE(session_p, ses_lock_held);
1640Sstevel@tonic-gate 				return (rv);
1650Sstevel@tonic-gate 			}
1660Sstevel@tonic-gate 		}
1670Sstevel@tonic-gate 
1680Sstevel@tonic-gate 		/* Insert the new object into this session's object list. */
1690Sstevel@tonic-gate 		kernel_add_object_to_session(new_object, session_p);
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 		/*
1720Sstevel@tonic-gate 		 * Decrement the session reference count.
1730Sstevel@tonic-gate 		 * We do not hold the session lock.
1740Sstevel@tonic-gate 		 */
175*214Smcpowers 		OBJ_REFRELE(old_object);
1760Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
1770Sstevel@tonic-gate 
1780Sstevel@tonic-gate 		/* set handle of the new object */
1790Sstevel@tonic-gate 		*phNewObject = (CK_ULONG)new_object;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	} else {
1820Sstevel@tonic-gate 		/*
1830Sstevel@tonic-gate 		 * The old object was created in the HW provider.
1840Sstevel@tonic-gate 		 * First, create an object wrapper in library.
1850Sstevel@tonic-gate 		 */
1860Sstevel@tonic-gate 		new_object = calloc(1, sizeof (kernel_object_t));
1870Sstevel@tonic-gate 		if (new_object == NULL) {
188*214Smcpowers 			(void) pthread_mutex_unlock(&old_object->object_mutex);
189*214Smcpowers 			OBJ_REFRELE(old_object);
190*214Smcpowers 			REFRELE(session_p, ses_lock_held);
191*214Smcpowers 			return (CKR_HOST_MEMORY);
1920Sstevel@tonic-gate 		}
1930Sstevel@tonic-gate 
1940Sstevel@tonic-gate 		/* Call CRYPTO_OBJECT_COPY ioctl to get a new object. */
1950Sstevel@tonic-gate 		object_copy.oc_session = session_p->k_session;
1960Sstevel@tonic-gate 		object_copy.oc_handle = old_object->k_handle;
197*214Smcpowers 		(void) pthread_mutex_unlock(&old_object->object_mutex);
1980Sstevel@tonic-gate 		object_copy.oc_count = ulCount;
1990Sstevel@tonic-gate 		object_copy.oc_new_attributes = NULL;
2000Sstevel@tonic-gate 		if (ulCount > 0) {
2010Sstevel@tonic-gate 			rv = process_object_attributes(pTemplate, ulCount,
2020Sstevel@tonic-gate 			    &object_copy.oc_new_attributes, &is_token_obj);
2030Sstevel@tonic-gate 			if (rv != CKR_OK) {
2040Sstevel@tonic-gate 				goto failed_cleanup;
2050Sstevel@tonic-gate 			}
2060Sstevel@tonic-gate 		}
2070Sstevel@tonic-gate 
2080Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_COPY,
2090Sstevel@tonic-gate 		    &object_copy)) < 0) {
2100Sstevel@tonic-gate 			if (errno != EINTR)
2110Sstevel@tonic-gate 				break;
2120Sstevel@tonic-gate 		}
2130Sstevel@tonic-gate 		if (r < 0) {
2140Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
2150Sstevel@tonic-gate 		} else {
2160Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
2170Sstevel@tonic-gate 			    object_copy.oc_return_value);
2180Sstevel@tonic-gate 		}
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 		/* Free the attributes' space allocated for ioctl */
2210Sstevel@tonic-gate 		free_object_attributes(object_copy.oc_new_attributes, ulCount);
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 		if (rv != CKR_OK) {
2240Sstevel@tonic-gate 			goto failed_cleanup;
2250Sstevel@tonic-gate 		}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 		/*
2280Sstevel@tonic-gate 		 * Store the kernel object handle in the object wrapper and
2290Sstevel@tonic-gate 		 * get the CKA_PRIVATE value of the new object.
2300Sstevel@tonic-gate 		 */
2310Sstevel@tonic-gate 		new_object->k_handle = object_copy.oc_new_handle;
2320Sstevel@tonic-gate 		rv = get_cka_private_value(session_p, new_object->k_handle,
2330Sstevel@tonic-gate 		    &is_pri_obj);
2340Sstevel@tonic-gate 		if (rv != CKR_OK) {
2350Sstevel@tonic-gate 			goto failed_cleanup;
2360Sstevel@tonic-gate 		}
2370Sstevel@tonic-gate 
2380Sstevel@tonic-gate 		/*
2390Sstevel@tonic-gate 		 * Initialize other field of the object wrapper.
2400Sstevel@tonic-gate 		 */
2410Sstevel@tonic-gate 		new_object->is_lib_obj = B_FALSE;
2420Sstevel@tonic-gate 		new_object->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
2430Sstevel@tonic-gate 		new_object->session_handle = (CK_SESSION_HANDLE)session_p;
2440Sstevel@tonic-gate 		(void) pthread_mutex_init(&new_object->object_mutex, NULL);
2450Sstevel@tonic-gate 
2460Sstevel@tonic-gate 		if (is_pri_obj)
2470Sstevel@tonic-gate 			new_object->bool_attr_mask |= PRIVATE_BOOL_ON;
2480Sstevel@tonic-gate 		else
2490Sstevel@tonic-gate 			new_object->bool_attr_mask &= ~PRIVATE_BOOL_ON;
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 		if (is_token_obj)
2520Sstevel@tonic-gate 			new_object->bool_attr_mask |= TOKEN_BOOL_ON;
2530Sstevel@tonic-gate 		else
2540Sstevel@tonic-gate 			new_object->bool_attr_mask &= ~TOKEN_BOOL_ON;
2550Sstevel@tonic-gate 
2560Sstevel@tonic-gate 		/*
2570Sstevel@tonic-gate 		 * Add the new copied object into the slot's token list
2580Sstevel@tonic-gate 		 * or the session list.  We don't hold the slot lock.
2590Sstevel@tonic-gate 		 */
2600Sstevel@tonic-gate 		if (is_token_obj) {
2610Sstevel@tonic-gate 			pslot = slot_table[session_p->ses_slotid];
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 			/*
2640Sstevel@tonic-gate 			 * Decrement the session reference count.
2650Sstevel@tonic-gate 			 * We do not hold the session lock.
2660Sstevel@tonic-gate 			 */
267*214Smcpowers 			OBJ_REFRELE(old_object);
2680Sstevel@tonic-gate 			REFRELE(session_p, ses_lock_held);
2690Sstevel@tonic-gate 
2700Sstevel@tonic-gate 			/* Add into the slot token object list. */
2710Sstevel@tonic-gate 			kernel_add_token_object_to_slot(new_object, pslot);
2720Sstevel@tonic-gate 		} else {
2730Sstevel@tonic-gate 			kernel_add_object_to_session(new_object, session_p);
2740Sstevel@tonic-gate 
2750Sstevel@tonic-gate 			/*
2760Sstevel@tonic-gate 			 * Decrement the session reference count.
2770Sstevel@tonic-gate 			 * We do not hold the session lock.
2780Sstevel@tonic-gate 			 */
279*214Smcpowers 			OBJ_REFRELE(old_object);
2800Sstevel@tonic-gate 			REFRELE(session_p, ses_lock_held);
2810Sstevel@tonic-gate 		}
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 		/* set handle of the new object */
2840Sstevel@tonic-gate 		*phNewObject = (CK_ULONG)new_object;
2850Sstevel@tonic-gate 	}
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	return (rv);
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate failed_cleanup:
2900Sstevel@tonic-gate 	if (new_object != NULL) {
2910Sstevel@tonic-gate 		(void) free(new_object);
2920Sstevel@tonic-gate 	}
2930Sstevel@tonic-gate 
294*214Smcpowers 	OBJ_REFRELE(old_object);
2950Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
2960Sstevel@tonic-gate 	return (rv);
2970Sstevel@tonic-gate }
2980Sstevel@tonic-gate 
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate CK_RV
C_DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)3010Sstevel@tonic-gate C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
3020Sstevel@tonic-gate {
3030Sstevel@tonic-gate 	CK_RV rv;
3040Sstevel@tonic-gate 	kernel_object_t *object_p;
305*214Smcpowers 	kernel_session_t *session_p = (kernel_session_t *)(hSession);
3060Sstevel@tonic-gate 	kernel_slot_t	*pslot;
3070Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
3080Sstevel@tonic-gate 	CK_SESSION_HANDLE creating_session;
3090Sstevel@tonic-gate 
3100Sstevel@tonic-gate 	if (!kernel_initialized)
3110Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
3120Sstevel@tonic-gate 
313*214Smcpowers 	/*
314*214Smcpowers 	 * The reason that we don't call handle2session is because
315*214Smcpowers 	 * the argument hSession may not be the creating_session of
316*214Smcpowers 	 * the object to be destroyed, and we want to avoid the lock
317*214Smcpowers 	 * contention. The handle2session will be called later for
318*214Smcpowers 	 * the creating_session.
319*214Smcpowers 	 */
320*214Smcpowers 	if ((session_p == NULL) ||
321*214Smcpowers 	    (session_p->magic_marker != KERNELTOKEN_SESSION_MAGIC)) {
322*214Smcpowers 		return (CKR_SESSION_HANDLE_INVALID);
323*214Smcpowers 	}
3240Sstevel@tonic-gate 
325*214Smcpowers 	/* Obtain the object pointer without incrementing reference count. */
326*214Smcpowers 	HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
3270Sstevel@tonic-gate 	if (rv != CKR_OK) {
328*214Smcpowers 		return (rv);
3290Sstevel@tonic-gate 	}
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 	/* Only session objects can be destroyed at a read-only session. */
3320Sstevel@tonic-gate 	if ((session_p->ses_RO) &&
3330Sstevel@tonic-gate 	    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
334*214Smcpowers 		return (CKR_SESSION_READ_ONLY);
3350Sstevel@tonic-gate 	}
3360Sstevel@tonic-gate 
3370Sstevel@tonic-gate 	/*
3380Sstevel@tonic-gate 	 * If the object is a session object, obtain the session handle
3390Sstevel@tonic-gate 	 * which object belongs to.  For a token object, we will use the
3400Sstevel@tonic-gate 	 * session handle from the caller, because the session used to
3410Sstevel@tonic-gate 	 * create the token object may no longer exist.
3420Sstevel@tonic-gate 	 */
343*214Smcpowers 	if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON))
3440Sstevel@tonic-gate 		creating_session = object_p->session_handle;
345*214Smcpowers 	else
346*214Smcpowers 		creating_session = hSession;
347*214Smcpowers 
348*214Smcpowers 	rv = handle2session(creating_session, &session_p);
349*214Smcpowers 	if (rv != CKR_OK) {
350*214Smcpowers 		return (rv);
3510Sstevel@tonic-gate 	}
3520Sstevel@tonic-gate 
353*214Smcpowers 	/*
354*214Smcpowers 	 * Set OBJECT_IS_DELETING flag so any access to this
355*214Smcpowers 	 * object will be rejected.
356*214Smcpowers 	 */
357*214Smcpowers 	(void) pthread_mutex_lock(&object_p->object_mutex);
358*214Smcpowers 	if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
359*214Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
360*214Smcpowers 		REFRELE(session_p, ses_lock_held);
361*214Smcpowers 		return (CKR_OBJECT_HANDLE_INVALID);
362*214Smcpowers 	}
363*214Smcpowers 	object_p->obj_delete_sync |= OBJECT_IS_DELETING;
364*214Smcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
365*214Smcpowers 
3660Sstevel@tonic-gate 	if (object_p->bool_attr_mask & TOKEN_BOOL_ON) {
3670Sstevel@tonic-gate 		/*
3680Sstevel@tonic-gate 		 * The first FALSE boolean argument indicates that the caller
3690Sstevel@tonic-gate 		 * does not hold the slot lock.  The second FALSE boolean
3700Sstevel@tonic-gate 		 * argument indicates that the caller wants to clean up the
3710Sstevel@tonic-gate 		 * object in the HW provider also.
3720Sstevel@tonic-gate 		 */
3730Sstevel@tonic-gate 		pslot = slot_table[session_p->ses_slotid];
3740Sstevel@tonic-gate 		rv = kernel_delete_token_object(pslot, session_p, object_p,
3750Sstevel@tonic-gate 		    B_FALSE, B_FALSE);
3760Sstevel@tonic-gate 	} else {
3770Sstevel@tonic-gate 		/*
3780Sstevel@tonic-gate 		 * The first FALSE boolean argument indicates that the caller
3790Sstevel@tonic-gate 		 * does not hold the session lock.  The second FALSE boolean
3800Sstevel@tonic-gate 		 * argument indicates that the caller wants to clean the object
3810Sstevel@tonic-gate 		 * in the HW provider also.
3820Sstevel@tonic-gate 		 */
3830Sstevel@tonic-gate 		rv = kernel_delete_session_object(session_p, object_p, B_FALSE,
3840Sstevel@tonic-gate 		    B_FALSE);
3850Sstevel@tonic-gate 	}
3860Sstevel@tonic-gate 	/*
3870Sstevel@tonic-gate 	 * Decrement the session reference count.
3880Sstevel@tonic-gate 	 * We do not hold the session lock.
3890Sstevel@tonic-gate 	 */
3900Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
3910Sstevel@tonic-gate 	return (rv);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 
3950Sstevel@tonic-gate CK_RV
C_GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)3960Sstevel@tonic-gate C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
3970Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
3980Sstevel@tonic-gate {
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	CK_RV rv = CKR_OK, rv1 = CKR_OK;
4010Sstevel@tonic-gate 	kernel_object_t *object_p;
4020Sstevel@tonic-gate 	kernel_session_t *session_p;
4030Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
4040Sstevel@tonic-gate 	crypto_object_get_attribute_value_t obj_get_attr;
4050Sstevel@tonic-gate 	int i, r;
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 	if (!kernel_initialized)
4080Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
4090Sstevel@tonic-gate 
4100Sstevel@tonic-gate 	if ((pTemplate == NULL) || (ulCount == 0))
4110Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
4120Sstevel@tonic-gate 
4130Sstevel@tonic-gate 	/*
4140Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
4150Sstevel@tonic-gate 	 * reference count.
4160Sstevel@tonic-gate 	 */
4170Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
4180Sstevel@tonic-gate 	if (rv != CKR_OK)
4190Sstevel@tonic-gate 		return (rv);
4200Sstevel@tonic-gate 
4210Sstevel@tonic-gate 	/* Obtain the object pointer. */
4220Sstevel@tonic-gate 	HANDLE2OBJECT(hObject, object_p, rv);
4230Sstevel@tonic-gate 	if (rv != CKR_OK) {
4240Sstevel@tonic-gate 		/*
4250Sstevel@tonic-gate 		 * Decrement the session reference count.
4260Sstevel@tonic-gate 		 * We do not hold the session lock.
4270Sstevel@tonic-gate 		 */
4280Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
4290Sstevel@tonic-gate 		return (rv);
4300Sstevel@tonic-gate 	}
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	/* Acquire the lock on the object. */
4330Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 	if (object_p->is_lib_obj) {
4360Sstevel@tonic-gate 		/*
4370Sstevel@tonic-gate 		 * The object was created in the library. The library
4380Sstevel@tonic-gate 		 * contains the value information of each attribute.
4390Sstevel@tonic-gate 		 */
4400Sstevel@tonic-gate 		for (i = 0; i < ulCount; i++) {
4410Sstevel@tonic-gate 			/*
4420Sstevel@tonic-gate 			 * Get the value of each attribute in the template.
4430Sstevel@tonic-gate 			 * (We must process EVERY attribute in the template.)
4440Sstevel@tonic-gate 			 */
4450Sstevel@tonic-gate 			rv = kernel_get_attribute(object_p, &pTemplate[i]);
4460Sstevel@tonic-gate 			if (rv != CKR_OK)
4470Sstevel@tonic-gate 				/* At least we catch some type of error. */
4480Sstevel@tonic-gate 				rv1 = rv;
4490Sstevel@tonic-gate 		}
4500Sstevel@tonic-gate 		rv = rv1;
451*214Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
4520Sstevel@tonic-gate 	} else {
4530Sstevel@tonic-gate 		/*
4540Sstevel@tonic-gate 		 * The object was created in HW provider, call ioctl to get
4550Sstevel@tonic-gate 		 * the values of attributes.
4560Sstevel@tonic-gate 		 */
4570Sstevel@tonic-gate 		obj_get_attr.og_session = session_p->k_session;
4580Sstevel@tonic-gate 		obj_get_attr.og_handle = object_p->k_handle;
459*214Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
4600Sstevel@tonic-gate 		obj_get_attr.og_count = ulCount;
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 		rv = process_object_attributes(pTemplate, ulCount,
4630Sstevel@tonic-gate 		    &obj_get_attr.og_attributes, NULL);
4640Sstevel@tonic-gate 		if (rv != CKR_OK) {
4650Sstevel@tonic-gate 			goto clean_exit;
4660Sstevel@tonic-gate 		}
4670Sstevel@tonic-gate 
4680Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
4690Sstevel@tonic-gate 		    &obj_get_attr)) < 0) {
4700Sstevel@tonic-gate 			if (errno != EINTR)
4710Sstevel@tonic-gate 				break;
4720Sstevel@tonic-gate 		}
4730Sstevel@tonic-gate 		if (r < 0) {
4740Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
4750Sstevel@tonic-gate 		} else {
4760Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
4770Sstevel@tonic-gate 			    obj_get_attr.og_return_value);
4780Sstevel@tonic-gate 		}
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 		/*
4810Sstevel@tonic-gate 		 * The error codes CKR_ATTRIBUTE_SENSITIVE,
4820Sstevel@tonic-gate 		 * CKR_ATTRIBUTE_TYPE_INVALID, and CKR_BUFFER_TOO_SMALL
4830Sstevel@tonic-gate 		 * do not denote true errors for this function. If a call
4840Sstevel@tonic-gate 		 * returns any of these three values, then the call must
4850Sstevel@tonic-gate 		 * nonetheless have processed every attribute in the
4860Sstevel@tonic-gate 		 * template.  Every attribute in the template whose value
4870Sstevel@tonic-gate 		 * can be returned will be returned.
4880Sstevel@tonic-gate 		 */
4890Sstevel@tonic-gate 		if ((rv == CKR_OK) ||
4900Sstevel@tonic-gate 		    (rv == CKR_ATTRIBUTE_SENSITIVE) ||
4910Sstevel@tonic-gate 		    (rv == CKR_ATTRIBUTE_TYPE_INVALID) ||
4920Sstevel@tonic-gate 		    (rv == CKR_BUFFER_TOO_SMALL)) {
4930Sstevel@tonic-gate 			rv1 = get_object_attributes(pTemplate, ulCount,
4940Sstevel@tonic-gate 			    obj_get_attr.og_attributes);
4950Sstevel@tonic-gate 			if (rv1 != CKR_OK) {
4960Sstevel@tonic-gate 				rv = rv1;
4970Sstevel@tonic-gate 			}
4980Sstevel@tonic-gate 		}
4990Sstevel@tonic-gate 
5000Sstevel@tonic-gate 		/* Free the attributes' allocated for the ioctl call. */
5010Sstevel@tonic-gate 		free_object_attributes(obj_get_attr.og_attributes, ulCount);
5020Sstevel@tonic-gate 	}
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate clean_exit:
5050Sstevel@tonic-gate 	/*
5060Sstevel@tonic-gate 	 * Decrement the session reference count.
5070Sstevel@tonic-gate 	 * We do not hold the session lock.
5080Sstevel@tonic-gate 	 */
509*214Smcpowers 	OBJ_REFRELE(object_p);
5100Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
5110Sstevel@tonic-gate 	return (rv);
5120Sstevel@tonic-gate }
5130Sstevel@tonic-gate 
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate CK_RV
C_SetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)5160Sstevel@tonic-gate C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
5170Sstevel@tonic-gate     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
5180Sstevel@tonic-gate {
5190Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
5200Sstevel@tonic-gate 	kernel_object_t *object_p;
5210Sstevel@tonic-gate 	kernel_object_t *new_object = NULL;
5220Sstevel@tonic-gate 	kernel_session_t *session_p;
5230Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
5240Sstevel@tonic-gate 	crypto_object_set_attribute_value_t obj_set_attr;
5250Sstevel@tonic-gate 	int i, r;
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 	if (!kernel_initialized)
5280Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
5290Sstevel@tonic-gate 
5300Sstevel@tonic-gate 	if ((pTemplate == NULL) || (ulCount == 0))
5310Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	/*
5340Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
5350Sstevel@tonic-gate 	 * reference count.
5360Sstevel@tonic-gate 	 */
5370Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
5380Sstevel@tonic-gate 	if (rv != CKR_OK)
5390Sstevel@tonic-gate 		return (rv);
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	/* Obtain the object pointer. */
5420Sstevel@tonic-gate 	HANDLE2OBJECT(hObject, object_p, rv);
5430Sstevel@tonic-gate 	if (rv != CKR_OK) {
5440Sstevel@tonic-gate 		/*
5450Sstevel@tonic-gate 		 * Decrement the session reference count.
5460Sstevel@tonic-gate 		 * We do not hold the session lock.
5470Sstevel@tonic-gate 		 */
5480Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
5490Sstevel@tonic-gate 		return (rv);
5500Sstevel@tonic-gate 	}
5510Sstevel@tonic-gate 
5520Sstevel@tonic-gate 	/* lock the object */
5530Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
5540Sstevel@tonic-gate 
5550Sstevel@tonic-gate 	/*
5560Sstevel@tonic-gate 	 * If the object was created in the HW provider, changing its
5570Sstevel@tonic-gate 	 * attributes' values need to be done in the provider too.
5580Sstevel@tonic-gate 	 */
5590Sstevel@tonic-gate 	if (!object_p->is_lib_obj) {
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 		/* Cannot modify a token object with a READ-ONLY session */
5620Sstevel@tonic-gate 		if (session_p->ses_RO &&
5630Sstevel@tonic-gate 		    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
564*214Smcpowers 			(void) pthread_mutex_unlock(&object_p->object_mutex);
5650Sstevel@tonic-gate 			rv = CKR_SESSION_READ_ONLY;
566*214Smcpowers 			goto clean_exit;
5670Sstevel@tonic-gate 		}
5680Sstevel@tonic-gate 
5690Sstevel@tonic-gate 		obj_set_attr.sa_session = session_p->k_session;
5700Sstevel@tonic-gate 		obj_set_attr.sa_handle = object_p->k_handle;
571*214Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
5720Sstevel@tonic-gate 		obj_set_attr.sa_count = ulCount;
5730Sstevel@tonic-gate 		rv = process_object_attributes(pTemplate, ulCount,
5740Sstevel@tonic-gate 		    &obj_set_attr.sa_attributes, NULL);
5750Sstevel@tonic-gate 		if (rv != CKR_OK) {
576*214Smcpowers 			goto clean_exit;
5770Sstevel@tonic-gate 		}
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE,
5800Sstevel@tonic-gate 		    &obj_set_attr)) < 0) {
5810Sstevel@tonic-gate 			if (errno != EINTR)
5820Sstevel@tonic-gate 				break;
5830Sstevel@tonic-gate 		}
5840Sstevel@tonic-gate 		if (r < 0) {
5850Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
5860Sstevel@tonic-gate 		} else {
5870Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
5880Sstevel@tonic-gate 			    obj_set_attr.sa_return_value);
5890Sstevel@tonic-gate 		}
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 		/* Free the attributes' space allocated for the ioctl call. */
5920Sstevel@tonic-gate 		free_object_attributes(obj_set_attr.sa_attributes, ulCount);
593*214Smcpowers 		goto clean_exit;
5940Sstevel@tonic-gate 	}
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 	/*
5970Sstevel@tonic-gate 	 * if we come here, the object must have been created in the
5980Sstevel@tonic-gate 	 * library.  The work will be done completely in the library.
5990Sstevel@tonic-gate 	 *
6000Sstevel@tonic-gate 	 * Copy the old object to a new object. We work on the copied
6010Sstevel@tonic-gate 	 * version because in case of error we still keep the old one
6020Sstevel@tonic-gate 	 * intact.
6030Sstevel@tonic-gate 	 */
6040Sstevel@tonic-gate 	rv = kernel_copy_object(object_p, &new_object, B_FALSE, NULL);
605*214Smcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6060Sstevel@tonic-gate 	if ((rv != CKR_OK) || (new_object == NULL)) {
6070Sstevel@tonic-gate 		/*
608*214Smcpowers 		 * Most likely we ran out of space.
6090Sstevel@tonic-gate 		 * Decrement the session reference count.
6100Sstevel@tonic-gate 		 * We do not hold the session lock.
6110Sstevel@tonic-gate 		 */
612*214Smcpowers 		goto clean_exit;
6130Sstevel@tonic-gate 	}
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
6160Sstevel@tonic-gate 		/* Set the requested attribute into the new object. */
6170Sstevel@tonic-gate 		rv = kernel_set_attribute(new_object, &pTemplate[i], B_FALSE,
6180Sstevel@tonic-gate 		    session_p);
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 		if (rv != CKR_OK) {
6210Sstevel@tonic-gate 			kernel_cleanup_object(new_object);
622*214Smcpowers 			goto clean_exit;
6230Sstevel@tonic-gate 		}
6240Sstevel@tonic-gate 	}
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 	/*
6270Sstevel@tonic-gate 	 * We've successfully set all the requested attributes.
6280Sstevel@tonic-gate 	 * Merge the new object with the old object, then destory
6290Sstevel@tonic-gate 	 * the new one. The reason to do the merging is because we
6300Sstevel@tonic-gate 	 * have to keep the original object handle (address of object).
6310Sstevel@tonic-gate 	 */
6320Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
6330Sstevel@tonic-gate 	kernel_merge_object(object_p, new_object);
634*214Smcpowers 	(void) pthread_mutex_unlock(&object_p->object_mutex);
6350Sstevel@tonic-gate 
636*214Smcpowers clean_exit:
637*214Smcpowers 	if (new_object != NULL)
638*214Smcpowers 		(void) free(new_object);
6390Sstevel@tonic-gate 
6400Sstevel@tonic-gate 	/*
6410Sstevel@tonic-gate 	 * Decrement the session reference count.
6420Sstevel@tonic-gate 	 * We do not hold the session lock.
6430Sstevel@tonic-gate 	 */
644*214Smcpowers 	OBJ_REFRELE(object_p);
6450Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 	return (rv);
6480Sstevel@tonic-gate }
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 
6510Sstevel@tonic-gate CK_RV
C_GetObjectSize(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ULONG_PTR pulSize)6520Sstevel@tonic-gate C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
6530Sstevel@tonic-gate     CK_ULONG_PTR pulSize)
6540Sstevel@tonic-gate {
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6570Sstevel@tonic-gate 	kernel_object_t *object_p;
6580Sstevel@tonic-gate 	kernel_session_t *session_p;
6590Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
6600Sstevel@tonic-gate 	crypto_object_get_size_t obj_gs;
6610Sstevel@tonic-gate 	int r;
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 	if (!kernel_initialized)
6640Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
6650Sstevel@tonic-gate 
6660Sstevel@tonic-gate 	/* Check if pulSize is valid */
6670Sstevel@tonic-gate 	if (pulSize == NULL) {
6680Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
6690Sstevel@tonic-gate 	}
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 	/*
6720Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
6730Sstevel@tonic-gate 	 * reference count.
6740Sstevel@tonic-gate 	 */
6750Sstevel@tonic-gate 	rv = handle2session(hSession, &session_p);
6760Sstevel@tonic-gate 	if (rv != CKR_OK)
6770Sstevel@tonic-gate 		return (rv);
6780Sstevel@tonic-gate 
6790Sstevel@tonic-gate 	/* Obtain the object pointer. */
6800Sstevel@tonic-gate 	HANDLE2OBJECT(hObject, object_p, rv);
6810Sstevel@tonic-gate 	if (rv != CKR_OK) {
6820Sstevel@tonic-gate 		/*
6830Sstevel@tonic-gate 		 * Decrement the session reference count.
6840Sstevel@tonic-gate 		 * We do not hold the session lock.
6850Sstevel@tonic-gate 		 */
6860Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
6870Sstevel@tonic-gate 		return (rv);
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	/* Acquire the lock on the object. */
6910Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object_p->object_mutex);
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	if (!object_p->is_lib_obj) {
6940Sstevel@tonic-gate 		/*
6950Sstevel@tonic-gate 		 * The object was created in HW provider, call the
6960Sstevel@tonic-gate 		 * CRYPTO_OBJECT_GET_SIZE ioctl.
6970Sstevel@tonic-gate 		 */
6980Sstevel@tonic-gate 		obj_gs.gs_session = session_p->k_session;
6990Sstevel@tonic-gate 		obj_gs.gs_handle = object_p->k_handle;
700*214Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
7010Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_SIZE,
7020Sstevel@tonic-gate 		    &obj_gs)) < 0) {
7030Sstevel@tonic-gate 			if (errno != EINTR)
7040Sstevel@tonic-gate 				break;
7050Sstevel@tonic-gate 		}
7060Sstevel@tonic-gate 		if (r < 0) {
7070Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
7080Sstevel@tonic-gate 		} else {
7090Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
7100Sstevel@tonic-gate 			    obj_gs.gs_return_value);
7110Sstevel@tonic-gate 		}
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 		if (rv == CKR_OK) {
7140Sstevel@tonic-gate 			*pulSize = obj_gs.gs_size;
7150Sstevel@tonic-gate 		}
7160Sstevel@tonic-gate 
7170Sstevel@tonic-gate 	} else {
7180Sstevel@tonic-gate 		rv = kernel_get_object_size(object_p, pulSize);
719*214Smcpowers 		(void) pthread_mutex_unlock(&object_p->object_mutex);
7200Sstevel@tonic-gate 	}
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 	/*
7230Sstevel@tonic-gate 	 * Decrement the session reference count.
7240Sstevel@tonic-gate 	 * We do not hold the session lock.
7250Sstevel@tonic-gate 	 */
726*214Smcpowers 	OBJ_REFRELE(object_p);
7270Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
7280Sstevel@tonic-gate 	return (rv);
7290Sstevel@tonic-gate }
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 
7320Sstevel@tonic-gate CK_RV
C_FindObjectsInit(CK_SESSION_HANDLE sh,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)7330Sstevel@tonic-gate C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
7340Sstevel@tonic-gate     CK_ULONG ulCount)
7350Sstevel@tonic-gate {
7360Sstevel@tonic-gate 	CK_RV		rv;
7370Sstevel@tonic-gate 	kernel_session_t	*session_p;
7380Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
7390Sstevel@tonic-gate 	kernel_slot_t *pslot;
7400Sstevel@tonic-gate 	crypto_object_find_init_t obj_fi;
7410Sstevel@tonic-gate 	int r;
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 	if (!kernel_initialized)
7440Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
7450Sstevel@tonic-gate 
7460Sstevel@tonic-gate 	/* Check the arguments */
7470Sstevel@tonic-gate 	if ((ulCount > 0) && (pTemplate == NULL)) {
7480Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
7490Sstevel@tonic-gate 	}
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	/*
7520Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
7530Sstevel@tonic-gate 	 * reference count.
7540Sstevel@tonic-gate 	 */
7550Sstevel@tonic-gate 	rv = handle2session(sh, &session_p);
7560Sstevel@tonic-gate 	if (rv != CKR_OK)
7570Sstevel@tonic-gate 		return (rv);
7580Sstevel@tonic-gate 
7590Sstevel@tonic-gate 	/* Acquire the session lock */
7600Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
7610Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
7620Sstevel@tonic-gate 
7630Sstevel@tonic-gate 	/* Check to see if find operation is already active */
7640Sstevel@tonic-gate 	if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
7650Sstevel@tonic-gate 		/* decrement the session count, and unlock the mutex */
7660Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
7670Sstevel@tonic-gate 		return (CKR_OPERATION_ACTIVE);
7680Sstevel@tonic-gate 	} else {
7690Sstevel@tonic-gate 		/*
7700Sstevel@tonic-gate 		 * This active flag will remain ON until application calls
7710Sstevel@tonic-gate 		 * C_FindObjectsFinal.
7720Sstevel@tonic-gate 		 */
7730Sstevel@tonic-gate 		session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
7740Sstevel@tonic-gate 	}
7750Sstevel@tonic-gate 
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	/*
7780Sstevel@tonic-gate 	 * If the HW provider supports object creation, we call the
7790Sstevel@tonic-gate 	 * CRYPTO_OBJECT_FIND_INIT ioctl to initialize object finding.
7800Sstevel@tonic-gate 	 * Otherwise, all the objects are created in the library and we
7810Sstevel@tonic-gate 	 * do the find objects solely in the library.
7820Sstevel@tonic-gate 	 */
7830Sstevel@tonic-gate 	pslot = slot_table[session_p->ses_slotid];
7840Sstevel@tonic-gate 	if (pslot->sl_func_list.fl_object_create) {
7850Sstevel@tonic-gate 		obj_fi.fi_session = session_p->k_session;
7860Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
7870Sstevel@tonic-gate 		ses_lock_held = B_FALSE;
7880Sstevel@tonic-gate 		obj_fi.fi_count = ulCount;
7890Sstevel@tonic-gate 		rv = process_object_attributes(pTemplate, ulCount,
7900Sstevel@tonic-gate 		    &obj_fi.fi_attributes, NULL);
7910Sstevel@tonic-gate 		if (rv == CKR_OK) {
7920Sstevel@tonic-gate 			while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_INIT,
7930Sstevel@tonic-gate 			    &obj_fi)) < 0) {
7940Sstevel@tonic-gate 				if (errno != EINTR)
7950Sstevel@tonic-gate 					break;
7960Sstevel@tonic-gate 			}
7970Sstevel@tonic-gate 			if (r < 0) {
7980Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
7990Sstevel@tonic-gate 			} else {
8000Sstevel@tonic-gate 				rv = crypto2pkcs11_error_number(
8010Sstevel@tonic-gate 				    obj_fi.fi_return_value);
8020Sstevel@tonic-gate 			}
8030Sstevel@tonic-gate 		}
8040Sstevel@tonic-gate 
8050Sstevel@tonic-gate 		/* Free the attributes' space allocated for the ioctl call. */
8060Sstevel@tonic-gate 		free_object_attributes(obj_fi.fi_attributes, ulCount);
8070Sstevel@tonic-gate 
8080Sstevel@tonic-gate 	} else {
8090Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
8100Sstevel@tonic-gate 		ses_lock_held = B_FALSE;
8110Sstevel@tonic-gate 		rv = kernel_find_objects_init(session_p,  pTemplate, ulCount);
8120Sstevel@tonic-gate 	}
8130Sstevel@tonic-gate 
8140Sstevel@tonic-gate 	if (rv != CKR_OK) {
8150Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
8160Sstevel@tonic-gate 		session_p->find_objects.flags = 0;
8170Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
8180Sstevel@tonic-gate 	}
8190Sstevel@tonic-gate 
8200Sstevel@tonic-gate 	/* decrement the session count, and unlock the mutex */
8210Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
8220Sstevel@tonic-gate 	return (rv);
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate }
8250Sstevel@tonic-gate 
8260Sstevel@tonic-gate CK_RV
C_FindObjects(CK_SESSION_HANDLE sh,CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)8270Sstevel@tonic-gate C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject,
8280Sstevel@tonic-gate     CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
8290Sstevel@tonic-gate {
8300Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
8310Sstevel@tonic-gate 	kernel_slot_t		*pslot;
8320Sstevel@tonic-gate 	kernel_session_t	*session_p;
8330Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
8340Sstevel@tonic-gate 	crypto_object_find_update_t obj_fu;
8350Sstevel@tonic-gate 	int r;
8360Sstevel@tonic-gate 
8370Sstevel@tonic-gate 	if (!kernel_initialized)
8380Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
8390Sstevel@tonic-gate 
8400Sstevel@tonic-gate 	/* check for invalid arguments */
8410Sstevel@tonic-gate 	if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
8420Sstevel@tonic-gate 	    (pulObjectCount == NULL)) {
8430Sstevel@tonic-gate 		return (CKR_ARGUMENTS_BAD);
8440Sstevel@tonic-gate 	}
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	if (ulMaxObjectCount == 0) {
8470Sstevel@tonic-gate 		/* don't need to do anything, just return */
8480Sstevel@tonic-gate 		*pulObjectCount = 0;
8490Sstevel@tonic-gate 		return (CKR_OK);
8500Sstevel@tonic-gate 	}
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate 	/*
8530Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
8540Sstevel@tonic-gate 	 * reference count.
8550Sstevel@tonic-gate 	 */
8560Sstevel@tonic-gate 	rv = handle2session(sh, &session_p);
8570Sstevel@tonic-gate 	if (rv != CKR_OK)
8580Sstevel@tonic-gate 		return (rv);
8590Sstevel@tonic-gate 
8600Sstevel@tonic-gate 	/* Acquire the slot lock */
8610Sstevel@tonic-gate 	pslot = slot_table[session_p->ses_slotid];
8620Sstevel@tonic-gate 	(void) pthread_mutex_lock(&pslot->sl_mutex);
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 	/* Acquire the session lock */
8650Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
8660Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 	/* Check to see if find operation is active */
8690Sstevel@tonic-gate 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
8700Sstevel@tonic-gate 		rv = CKR_OPERATION_NOT_INITIALIZED;
8710Sstevel@tonic-gate 		goto clean_exit;
8720Sstevel@tonic-gate 	}
8730Sstevel@tonic-gate 
8740Sstevel@tonic-gate 	/*
8750Sstevel@tonic-gate 	 * Similar to C_FindObjectInit(), if the HW provider supports object
8760Sstevel@tonic-gate 	 * creation, we call the respective ioctl to find objects.
8770Sstevel@tonic-gate 	 * Otherwise, all the objects are created in the library and we do
8780Sstevel@tonic-gate 	 * the find objects solely in the library.
8790Sstevel@tonic-gate 	 */
8800Sstevel@tonic-gate 	if (pslot->sl_func_list.fl_object_create) {
8810Sstevel@tonic-gate 		obj_fu.fu_session = session_p->k_session;
8820Sstevel@tonic-gate 		obj_fu.fu_max_count = ulMaxObjectCount;
8830Sstevel@tonic-gate 		obj_fu.fu_handles = (char *)calloc(1,
8840Sstevel@tonic-gate 		    ulMaxObjectCount * sizeof (crypto_object_id_t));
8850Sstevel@tonic-gate 		if (obj_fu.fu_handles == NULL) {
8860Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
8870Sstevel@tonic-gate 			goto clean_exit;
8880Sstevel@tonic-gate 		}
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_UPDATE,
8910Sstevel@tonic-gate 		    &obj_fu)) < 0) {
8920Sstevel@tonic-gate 			if (errno != EINTR)
8930Sstevel@tonic-gate 				break;
8940Sstevel@tonic-gate 		}
8950Sstevel@tonic-gate 		if (r < 0) {
8960Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
8970Sstevel@tonic-gate 		} else {
8980Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
8990Sstevel@tonic-gate 			    obj_fu.fu_return_value);
9000Sstevel@tonic-gate 		}
9010Sstevel@tonic-gate 
9020Sstevel@tonic-gate 		if (rv == CKR_OK) {
9030Sstevel@tonic-gate 			rv = process_found_objects(session_p, phObject,
9040Sstevel@tonic-gate 			    pulObjectCount, obj_fu);
9050Sstevel@tonic-gate 		}
9060Sstevel@tonic-gate 		free(obj_fu.fu_handles);
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	} else {
9090Sstevel@tonic-gate 
9100Sstevel@tonic-gate 		kernel_find_objects(session_p, phObject, ulMaxObjectCount,
9110Sstevel@tonic-gate 		    pulObjectCount);
9120Sstevel@tonic-gate 		rv = CKR_OK;
9130Sstevel@tonic-gate 	}
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate clean_exit:
9160Sstevel@tonic-gate 	/* decrement the session count, and release the session lock */
9170Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
9180Sstevel@tonic-gate 
9190Sstevel@tonic-gate 	/* release the slot lock */
9200Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
9210Sstevel@tonic-gate 
9220Sstevel@tonic-gate 	return (rv);
9230Sstevel@tonic-gate }
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 
9260Sstevel@tonic-gate CK_RV
C_FindObjectsFinal(CK_SESSION_HANDLE sh)9270Sstevel@tonic-gate C_FindObjectsFinal(CK_SESSION_HANDLE sh)
9280Sstevel@tonic-gate {
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 	kernel_session_t	*session_p;
9310Sstevel@tonic-gate 	CK_RV rv;
9320Sstevel@tonic-gate 	boolean_t ses_lock_held = B_FALSE;
9330Sstevel@tonic-gate 	kernel_slot_t *pslot;
9340Sstevel@tonic-gate 	crypto_object_find_final_t obj_ff;
9350Sstevel@tonic-gate 	int r;
9360Sstevel@tonic-gate 
9370Sstevel@tonic-gate 	if (!kernel_initialized)
9380Sstevel@tonic-gate 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
9390Sstevel@tonic-gate 
9400Sstevel@tonic-gate 	/*
9410Sstevel@tonic-gate 	 * Obtain the session pointer. Also, increment the session
9420Sstevel@tonic-gate 	 * reference count.
9430Sstevel@tonic-gate 	 */
9440Sstevel@tonic-gate 	rv = handle2session(sh, &session_p);
9450Sstevel@tonic-gate 	if (rv != CKR_OK)
9460Sstevel@tonic-gate 		return (rv);
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate 	/* Acquire the session lock */
9490Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
9500Sstevel@tonic-gate 	ses_lock_held = B_TRUE;
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	/* Check to see if find operation is active */
9530Sstevel@tonic-gate 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
9540Sstevel@tonic-gate 		REFRELE(session_p, ses_lock_held);
9550Sstevel@tonic-gate 		return (CKR_OPERATION_NOT_INITIALIZED);
9560Sstevel@tonic-gate 	}
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 	/*
9590Sstevel@tonic-gate 	 * Similar to C_FindObjectInit(), if the HW provider supports object
9600Sstevel@tonic-gate 	 * creation, we need to call the CRYPTO_OBJECT_FIND_FINAL ioctl.
9610Sstevel@tonic-gate 	 */
9620Sstevel@tonic-gate 	pslot = slot_table[session_p->ses_slotid];
9630Sstevel@tonic-gate 	if (pslot->sl_func_list.fl_object_create) {
9640Sstevel@tonic-gate 		obj_ff.ff_session = session_p->k_session;
9650Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_FINAL,
9660Sstevel@tonic-gate 		    &obj_ff)) < 0) {
9670Sstevel@tonic-gate 			if (errno != EINTR)
9680Sstevel@tonic-gate 				break;
9690Sstevel@tonic-gate 		}
9700Sstevel@tonic-gate 		if (r < 0) {
9710Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
9720Sstevel@tonic-gate 		} else {
9730Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
9740Sstevel@tonic-gate 			    obj_ff.ff_return_value);
9750Sstevel@tonic-gate 		}
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 		/* only need to reset find_objects.flags */
9780Sstevel@tonic-gate 		if (rv == CKR_OK) {
9790Sstevel@tonic-gate 			session_p->find_objects.flags = 0;
9800Sstevel@tonic-gate 		}
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 	} else {
9830Sstevel@tonic-gate 		/*
9840Sstevel@tonic-gate 		 * The find object operations were done in the library, we
9850Sstevel@tonic-gate 		 * need to cleanup find_objects context.
9860Sstevel@tonic-gate 		 */
9870Sstevel@tonic-gate 		kernel_find_objects_final(session_p);
9880Sstevel@tonic-gate 		rv = CKR_OK;
9890Sstevel@tonic-gate 	}
9900Sstevel@tonic-gate 
9910Sstevel@tonic-gate 	/* decrement the session count, and release the lock */
9920Sstevel@tonic-gate 	REFRELE(session_p, ses_lock_held);
9930Sstevel@tonic-gate 	return (rv);
9940Sstevel@tonic-gate }
995