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
54219Smcpowers  * Common Development and Distribution License (the "License").
64219Smcpowers  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*9661SZdenek.Kotala@Sun.COM  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <stdio.h>
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <strings.h>
290Sstevel@tonic-gate #include <errno.h>
300Sstevel@tonic-gate #include <security/cryptoki.h>
310Sstevel@tonic-gate #include <cryptoutil.h>
320Sstevel@tonic-gate #include "kernelGlobal.h"
330Sstevel@tonic-gate #include "kernelObject.h"
340Sstevel@tonic-gate #include "kernelSession.h"
350Sstevel@tonic-gate #include "kernelSlot.h"
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * Add an object to the session's object list.
390Sstevel@tonic-gate  *
400Sstevel@tonic-gate  * This function will acquire the lock on the session, and release
410Sstevel@tonic-gate  * that lock after adding the object to the session's object list.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate void
kernel_add_object_to_session(kernel_object_t * objp,kernel_session_t * sp)440Sstevel@tonic-gate kernel_add_object_to_session(kernel_object_t *objp, kernel_session_t *sp)
450Sstevel@tonic-gate {
460Sstevel@tonic-gate 	/* Acquire the session lock. */
470Sstevel@tonic-gate 	(void) pthread_mutex_lock(&sp->session_mutex);
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	/* Insert the new object in front of session's object list. */
500Sstevel@tonic-gate 	if (sp->object_list == NULL) {
510Sstevel@tonic-gate 		sp->object_list = objp;
520Sstevel@tonic-gate 		objp->next = NULL;
530Sstevel@tonic-gate 		objp->prev = NULL;
540Sstevel@tonic-gate 	} else {
550Sstevel@tonic-gate 		sp->object_list->prev = objp;
560Sstevel@tonic-gate 		objp->next = sp->object_list;
570Sstevel@tonic-gate 		objp->prev = NULL;
580Sstevel@tonic-gate 		sp->object_list = objp;
590Sstevel@tonic-gate 	}
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	/* Release the session lock. */
620Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&sp->session_mutex);
630Sstevel@tonic-gate }
640Sstevel@tonic-gate 
650Sstevel@tonic-gate /*
660Sstevel@tonic-gate  * Clean up and release the storage allocated to the object.
670Sstevel@tonic-gate  *
680Sstevel@tonic-gate  * The function is called either with the object lock being held
690Sstevel@tonic-gate  * (by caller kernel_delete_object()), or there is no object lock
700Sstevel@tonic-gate  * yet (by kernel_build_XXX_object() during creating an object).
710Sstevel@tonic-gate  */
720Sstevel@tonic-gate void
kernel_cleanup_object(kernel_object_t * objp)730Sstevel@tonic-gate kernel_cleanup_object(kernel_object_t *objp)
740Sstevel@tonic-gate {
750Sstevel@tonic-gate 	/*
760Sstevel@tonic-gate 	 * Free the storage allocated to a secret key object.
770Sstevel@tonic-gate 	 */
78991Smcpowers 	if (objp->class == CKO_SECRET_KEY) {
794219Smcpowers 		if (OBJ_SEC(objp) != NULL && OBJ_SEC_VALUE(objp) != NULL) {
800Sstevel@tonic-gate 			bzero(OBJ_SEC_VALUE(objp), OBJ_SEC_VALUE_LEN(objp));
810Sstevel@tonic-gate 			free(OBJ_SEC_VALUE(objp));
820Sstevel@tonic-gate 			OBJ_SEC_VALUE(objp) = NULL;
830Sstevel@tonic-gate 			OBJ_SEC_VALUE_LEN(objp) = 0;
840Sstevel@tonic-gate 		}
850Sstevel@tonic-gate 		free(OBJ_SEC(objp));
860Sstevel@tonic-gate 		OBJ_SEC(objp) = NULL;
870Sstevel@tonic-gate 	} else {
880Sstevel@tonic-gate 		kernel_cleanup_object_bigint_attrs(objp);
890Sstevel@tonic-gate 	}
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 	/*
920Sstevel@tonic-gate 	 * Free the storage allocated to the extra attribute list.
930Sstevel@tonic-gate 	 */
940Sstevel@tonic-gate 	kernel_cleanup_extra_attr(objp);
950Sstevel@tonic-gate }
960Sstevel@tonic-gate 
970Sstevel@tonic-gate /*
980Sstevel@tonic-gate  * Create a new object. Copy the attributes that can be modified
990Sstevel@tonic-gate  * (in the boolean attribute mask field and extra attribute list)
1000Sstevel@tonic-gate  * from the old object to the new object.
1010Sstevel@tonic-gate  *
1020Sstevel@tonic-gate  * The caller of this function holds the lock on the old object.
1030Sstevel@tonic-gate  */
1040Sstevel@tonic-gate CK_RV
kernel_copy_object(kernel_object_t * old_object,kernel_object_t ** new_object,boolean_t copy_everything,kernel_session_t * sp)1050Sstevel@tonic-gate kernel_copy_object(kernel_object_t *old_object, kernel_object_t **new_object,
1060Sstevel@tonic-gate     boolean_t copy_everything, kernel_session_t *sp)
1070Sstevel@tonic-gate {
1080Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1090Sstevel@tonic-gate 	kernel_object_t *new_objp = NULL;
1100Sstevel@tonic-gate 	CK_ATTRIBUTE_INFO_PTR attrp;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	/* Allocate new object. */
1130Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (kernel_object_t));
1140Sstevel@tonic-gate 	if (new_objp == NULL)
1150Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 	new_objp->class = old_object->class;
1180Sstevel@tonic-gate 	new_objp->bool_attr_mask = old_object->bool_attr_mask;
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	attrp = old_object->extra_attrlistp;
1210Sstevel@tonic-gate 	while (attrp) {
1220Sstevel@tonic-gate 		/*
1230Sstevel@tonic-gate 		 * Copy the attribute_info struct from the old
1240Sstevel@tonic-gate 		 * object to a new attribute_info struct, and add
1250Sstevel@tonic-gate 		 * that new struct to the extra attribute list
1260Sstevel@tonic-gate 		 * of the new object.
1270Sstevel@tonic-gate 		 */
1280Sstevel@tonic-gate 		rv = kernel_copy_extra_attr(attrp, new_objp);
1290Sstevel@tonic-gate 		if (rv != CKR_OK) {
1300Sstevel@tonic-gate 			kernel_cleanup_extra_attr(new_objp);
1310Sstevel@tonic-gate 			free(new_objp);
1320Sstevel@tonic-gate 			return (rv);
1330Sstevel@tonic-gate 		}
1340Sstevel@tonic-gate 		attrp = attrp->next;
1350Sstevel@tonic-gate 	}
1360Sstevel@tonic-gate 
1370Sstevel@tonic-gate 	*new_object = new_objp;
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 	if (!copy_everything) {
1400Sstevel@tonic-gate 		/* done with copying all information that can be modified */
1410Sstevel@tonic-gate 		return (CKR_OK);
1420Sstevel@tonic-gate 	}
1430Sstevel@tonic-gate 
1440Sstevel@tonic-gate 	/*
1450Sstevel@tonic-gate 	 * Copy the rest of the object.
1460Sstevel@tonic-gate 	 * Certain fields that are not appropriate for coping will be
1470Sstevel@tonic-gate 	 * initialized.
1480Sstevel@tonic-gate 	 */
1490Sstevel@tonic-gate 	new_objp->key_type = old_object->key_type;
1500Sstevel@tonic-gate 	new_objp->magic_marker = old_object->magic_marker;
1510Sstevel@tonic-gate 	new_objp->mechanism = old_object->mechanism;
1520Sstevel@tonic-gate 	new_objp->session_handle = (CK_SESSION_HANDLE)sp;
1530Sstevel@tonic-gate 	(void) pthread_mutex_init(&(new_objp->object_mutex), NULL);
1540Sstevel@tonic-gate 	/* copy key related information */
1550Sstevel@tonic-gate 	switch (new_objp->class) {
1560Sstevel@tonic-gate 		case CKO_PUBLIC_KEY:
1570Sstevel@tonic-gate 			rv = kernel_copy_public_key_attr(OBJ_PUB(old_object),
1580Sstevel@tonic-gate 			    &(OBJ_PUB(new_objp)), new_objp->key_type);
1590Sstevel@tonic-gate 			break;
1600Sstevel@tonic-gate 		case CKO_PRIVATE_KEY:
1610Sstevel@tonic-gate 			rv = kernel_copy_private_key_attr(OBJ_PRI(old_object),
1620Sstevel@tonic-gate 			    &(OBJ_PRI(new_objp)), new_objp->key_type);
1630Sstevel@tonic-gate 			break;
1640Sstevel@tonic-gate 		case CKO_SECRET_KEY:
1650Sstevel@tonic-gate 			rv = kernel_copy_secret_key_attr(OBJ_SEC(old_object),
1660Sstevel@tonic-gate 			    &(OBJ_SEC(new_objp)));
1670Sstevel@tonic-gate 			break;
1680Sstevel@tonic-gate 		default:
1690Sstevel@tonic-gate 			/* should never be this case */
1700Sstevel@tonic-gate 			break;
1710Sstevel@tonic-gate 	}
1720Sstevel@tonic-gate 	if (rv != CKR_OK) {
1730Sstevel@tonic-gate 		/*
1740Sstevel@tonic-gate 		 * don't need to cleanup the memory from failure of copying
1750Sstevel@tonic-gate 		 * any key related stuff.  Each individual function for
1760Sstevel@tonic-gate 		 * copying key attr will free the memory if it fails
1770Sstevel@tonic-gate 		 */
1780Sstevel@tonic-gate 		kernel_cleanup_extra_attr(new_objp);
1790Sstevel@tonic-gate 		free(new_objp);
1800Sstevel@tonic-gate 	}
1810Sstevel@tonic-gate 	return (rv);
1820Sstevel@tonic-gate }
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate /*
1850Sstevel@tonic-gate  * Copy the attributes (in the boolean attribute mask field and
1860Sstevel@tonic-gate  * extra attribute list) from the new object back to the original
1870Sstevel@tonic-gate  * object. Also, clean up and release all the storage in the extra
1880Sstevel@tonic-gate  * attribute list of the original object.
1890Sstevel@tonic-gate  *
1900Sstevel@tonic-gate  * The caller of this function holds the lock on the old object.
1910Sstevel@tonic-gate  */
1920Sstevel@tonic-gate void
kernel_merge_object(kernel_object_t * old_object,kernel_object_t * new_object)1930Sstevel@tonic-gate kernel_merge_object(kernel_object_t *old_object, kernel_object_t *new_object)
1940Sstevel@tonic-gate {
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	old_object->bool_attr_mask = new_object->bool_attr_mask;
1970Sstevel@tonic-gate 	kernel_cleanup_extra_attr(old_object);
1980Sstevel@tonic-gate 	old_object->extra_attrlistp = new_object->extra_attrlistp;
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate }
2010Sstevel@tonic-gate 
2020Sstevel@tonic-gate /*
2030Sstevel@tonic-gate  * Create a new object struct.  If it is a session object, add the object to
2040Sstevel@tonic-gate  * the session's object list.  If it is a token object, add it to the slot's
2050Sstevel@tonic-gate  * token object list.  The caller does not hold the slot lock.
2060Sstevel@tonic-gate  */
2070Sstevel@tonic-gate CK_RV
kernel_add_object(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_ULONG * objecthandle_p,kernel_session_t * sp)2080Sstevel@tonic-gate kernel_add_object(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
2090Sstevel@tonic-gate 	CK_ULONG *objecthandle_p, kernel_session_t *sp)
2100Sstevel@tonic-gate {
2110Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
2120Sstevel@tonic-gate 	kernel_object_t *new_objp = NULL;
2130Sstevel@tonic-gate 	kernel_slot_t	*pslot;
2140Sstevel@tonic-gate 	crypto_object_create_t	objc;
2150Sstevel@tonic-gate 	CK_BBOOL is_pri_obj;
2160Sstevel@tonic-gate 	CK_BBOOL is_token_obj = B_FALSE;
2170Sstevel@tonic-gate 	int r;
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (kernel_object_t));
2200Sstevel@tonic-gate 	if (new_objp == NULL) {
2210Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
2220Sstevel@tonic-gate 		goto fail_cleanup;
2230Sstevel@tonic-gate 	}
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 	new_objp->extra_attrlistp = NULL;
2260Sstevel@tonic-gate 	new_objp->is_lib_obj = B_TRUE;
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	/*
2290Sstevel@tonic-gate 	 * If the HW provider supports object creation, create the object
2300Sstevel@tonic-gate 	 * in the HW provider by calling the CRYPTO_OBJECT_CREATE ioctl.
2310Sstevel@tonic-gate 	 * Otherwise, create the object in the library.
2320Sstevel@tonic-gate 	 */
2330Sstevel@tonic-gate 	pslot = slot_table[sp->ses_slotid];
2340Sstevel@tonic-gate 	if (pslot->sl_func_list.fl_object_create) {
2350Sstevel@tonic-gate 		new_objp->is_lib_obj = B_FALSE;
2360Sstevel@tonic-gate 		objc.oc_session = sp->k_session;
2370Sstevel@tonic-gate 		objc.oc_count = ulCount;
2380Sstevel@tonic-gate 		rv = process_object_attributes(pTemplate, ulCount,
2390Sstevel@tonic-gate 		    &objc.oc_attributes, &is_token_obj);
2400Sstevel@tonic-gate 		if (rv != CKR_OK) {
2410Sstevel@tonic-gate 			goto fail_cleanup;
2420Sstevel@tonic-gate 		}
2430Sstevel@tonic-gate 
2440Sstevel@tonic-gate 		/* Cannot create a token object with a READ-ONLY session */
2450Sstevel@tonic-gate 		if (is_token_obj && sp->ses_RO) {
2460Sstevel@tonic-gate 			free_object_attributes(objc.oc_attributes, ulCount);
2470Sstevel@tonic-gate 			rv = CKR_SESSION_READ_ONLY;
2480Sstevel@tonic-gate 			goto fail_cleanup;
2490Sstevel@tonic-gate 		}
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_CREATE,
2520Sstevel@tonic-gate 		    &objc)) < 0) {
2530Sstevel@tonic-gate 			if (errno != EINTR)
2540Sstevel@tonic-gate 				break;
2550Sstevel@tonic-gate 		}
2560Sstevel@tonic-gate 		if (r < 0) {
2570Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
2580Sstevel@tonic-gate 		} else {
2590Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(objc.oc_return_value);
2600Sstevel@tonic-gate 		}
2610Sstevel@tonic-gate 
2620Sstevel@tonic-gate 		free_object_attributes(objc.oc_attributes, ulCount);
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 		if (rv != CKR_OK) {
2650Sstevel@tonic-gate 			goto fail_cleanup;
2660Sstevel@tonic-gate 		}
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 		/* Get the CKA_PRIVATE value of this object. */
2690Sstevel@tonic-gate 		new_objp->k_handle = objc.oc_handle;
2700Sstevel@tonic-gate 		rv = get_cka_private_value(sp, new_objp->k_handle,
2710Sstevel@tonic-gate 		    &is_pri_obj);
2720Sstevel@tonic-gate 		if (rv != CKR_OK) {
2730Sstevel@tonic-gate 			goto fail_cleanup;
2740Sstevel@tonic-gate 		}
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 		/* Set the PRIVATE_BOOL_ON and TOKEN_BOOL_ON attributes */
2770Sstevel@tonic-gate 		if (is_pri_obj)
2780Sstevel@tonic-gate 			new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
2790Sstevel@tonic-gate 		else
2800Sstevel@tonic-gate 			new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
2810Sstevel@tonic-gate 
2820Sstevel@tonic-gate 		if (is_token_obj)
2830Sstevel@tonic-gate 			new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
2840Sstevel@tonic-gate 		else
2850Sstevel@tonic-gate 			new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
2860Sstevel@tonic-gate 
2870Sstevel@tonic-gate 	} else {
2880Sstevel@tonic-gate 		/*
2890Sstevel@tonic-gate 		 * Create the object in the library.
2900Sstevel@tonic-gate 		 * Validate attribute template and fill in the attributes
2910Sstevel@tonic-gate 		 * in the kernel_object_t.
2920Sstevel@tonic-gate 		 */
2934219Smcpowers 		rv = kernel_build_object(pTemplate, ulCount, new_objp, sp,
2944219Smcpowers 		    KERNEL_CREATE_OBJ);
2950Sstevel@tonic-gate 		if (rv != CKR_OK) {
2960Sstevel@tonic-gate 			goto fail_cleanup;
2970Sstevel@tonic-gate 		}
2980Sstevel@tonic-gate 	}
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	/* Initialize the rest of stuffs in kernel_object_t. */
3010Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
3020Sstevel@tonic-gate 	new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
3030Sstevel@tonic-gate 	new_objp->session_handle = (CK_SESSION_HANDLE)sp;
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	if (is_token_obj) {
3060Sstevel@tonic-gate 		/* Add the new object to the slot's token object list. */
3070Sstevel@tonic-gate 		pslot = slot_table[sp->ses_slotid];
3080Sstevel@tonic-gate 		kernel_add_token_object_to_slot(new_objp, pslot);
3090Sstevel@tonic-gate 	} else {
3100Sstevel@tonic-gate 		/* Add the new object to the session's object list. */
3110Sstevel@tonic-gate 		kernel_add_object_to_session(new_objp, sp);
3120Sstevel@tonic-gate 	}
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	/* Type casting the address of an object struct to an object handle. */
315214Smcpowers 	*objecthandle_p = (CK_ULONG)new_objp;
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 	return (CKR_OK);
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate fail_cleanup:
3200Sstevel@tonic-gate 	if (new_objp) {
3210Sstevel@tonic-gate 		/*
3220Sstevel@tonic-gate 		 * If the object is created in the HW provider, the storage
3230Sstevel@tonic-gate 		 * allocated for the ioctl call is always cleaned up after
3240Sstevel@tonic-gate 		 * the call.  If the object is created in the library,
3250Sstevel@tonic-gate 		 * the storage allocated inside of this object should
3260Sstevel@tonic-gate 		 * have been cleaned up in the kernel_build_object()
3270Sstevel@tonic-gate 		 * after an error occurred. Therefore, we can safely
3280Sstevel@tonic-gate 		 * free the object.
3290Sstevel@tonic-gate 		 */
3300Sstevel@tonic-gate 		free(new_objp);
3310Sstevel@tonic-gate 	}
3320Sstevel@tonic-gate 
3330Sstevel@tonic-gate 	return (rv);
3340Sstevel@tonic-gate }
3350Sstevel@tonic-gate 
3360Sstevel@tonic-gate /*
3370Sstevel@tonic-gate  * Remove an object from the session's object list.
3380Sstevel@tonic-gate  *
3390Sstevel@tonic-gate  * The caller of this function holds the session lock.
3400Sstevel@tonic-gate  */
341214Smcpowers CK_RV
kernel_remove_object_from_session(kernel_object_t * objp,kernel_session_t * sp)3420Sstevel@tonic-gate kernel_remove_object_from_session(kernel_object_t *objp, kernel_session_t *sp)
3430Sstevel@tonic-gate {
344214Smcpowers 	kernel_object_t *tmp_objp;
345214Smcpowers 	boolean_t found = B_FALSE;
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	/*
3480Sstevel@tonic-gate 	 * Remove the object from the session's object list.
3490Sstevel@tonic-gate 	 */
350214Smcpowers 	if ((sp == NULL) ||
351214Smcpowers 	    (sp->magic_marker != KERNELTOKEN_SESSION_MAGIC)) {
352214Smcpowers 		return (CKR_SESSION_HANDLE_INVALID);
353214Smcpowers 	}
354214Smcpowers 
355214Smcpowers 	if ((sp->object_list == NULL) || (objp == NULL) ||
356214Smcpowers 	    (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC)) {
357214Smcpowers 		return (CKR_OBJECT_HANDLE_INVALID);
358214Smcpowers 	}
359214Smcpowers 
360214Smcpowers 	tmp_objp = sp->object_list;
361214Smcpowers 	while (tmp_objp) {
362214Smcpowers 		if (tmp_objp == objp) {
363214Smcpowers 			found = B_TRUE;
364214Smcpowers 			break;
365214Smcpowers 		}
366214Smcpowers 		tmp_objp = tmp_objp->next;
367214Smcpowers 	}
368214Smcpowers 	if (!found)
369214Smcpowers 		return (CKR_OBJECT_HANDLE_INVALID);
370214Smcpowers 
3710Sstevel@tonic-gate 	if (sp->object_list == objp) {
3720Sstevel@tonic-gate 		/* Object is the first one in the list. */
3730Sstevel@tonic-gate 		if (objp->next) {
3740Sstevel@tonic-gate 			sp->object_list = objp->next;
3750Sstevel@tonic-gate 			objp->next->prev = NULL;
3760Sstevel@tonic-gate 		} else {
3770Sstevel@tonic-gate 			/* Object is the only one in the list. */
3780Sstevel@tonic-gate 			sp->object_list = NULL;
3790Sstevel@tonic-gate 		}
3800Sstevel@tonic-gate 	} else {
3810Sstevel@tonic-gate 		/* Object is not the first one in the list. */
3820Sstevel@tonic-gate 		if (objp->next) {
3830Sstevel@tonic-gate 			/* Object is in the middle of the list. */
3840Sstevel@tonic-gate 			objp->prev->next = objp->next;
3850Sstevel@tonic-gate 			objp->next->prev = objp->prev;
3860Sstevel@tonic-gate 		} else {
3870Sstevel@tonic-gate 			/* Object is the last one in the list. */
3880Sstevel@tonic-gate 			objp->prev->next = NULL;
3890Sstevel@tonic-gate 		}
3900Sstevel@tonic-gate 	}
391214Smcpowers 	return (CKR_OK);
3920Sstevel@tonic-gate }
3930Sstevel@tonic-gate 
394214Smcpowers static void
kernel_delete_object_cleanup(kernel_object_t * objp,boolean_t wrapper_only)395*9661SZdenek.Kotala@Sun.COM kernel_delete_object_cleanup(kernel_object_t *objp, boolean_t wrapper_only)
396214Smcpowers {
397214Smcpowers 	/* Acquire the lock on the object. */
398214Smcpowers 	(void) pthread_mutex_lock(&objp->object_mutex);
399214Smcpowers 
400214Smcpowers 	/*
401214Smcpowers 	 * Make sure another thread hasn't freed the object.
402214Smcpowers 	 */
403214Smcpowers 	if (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC) {
404214Smcpowers 		(void) pthread_mutex_unlock(&objp->object_mutex);
405214Smcpowers 		return;
406214Smcpowers 	}
407214Smcpowers 
408214Smcpowers 	/*
409214Smcpowers 	 * The deletion of an object must be blocked when the object
410214Smcpowers 	 * reference count is not zero. This means if any object related
411214Smcpowers 	 * operation starts prior to the delete object operation gets in,
412214Smcpowers 	 * the object deleting thread must wait for the non-deleting
413214Smcpowers 	 * operation to be completed before it can proceed the delete
414214Smcpowers 	 * operation.
415*9661SZdenek.Kotala@Sun.COM 	 *
416*9661SZdenek.Kotala@Sun.COM 	 * Unless we are being forced to shut everything down, this only
417*9661SZdenek.Kotala@Sun.COM 	 * happens if the library's _fini() is running not if someone
418*9661SZdenek.Kotala@Sun.COM 	 * explicitly called C_Finalize().
419214Smcpowers 	 */
420*9661SZdenek.Kotala@Sun.COM 	if (wrapper_only) {
421*9661SZdenek.Kotala@Sun.COM 		objp->obj_refcnt = 0;
422*9661SZdenek.Kotala@Sun.COM 	}
423*9661SZdenek.Kotala@Sun.COM 
424214Smcpowers 	while (objp->obj_refcnt != 0) {
425214Smcpowers 		/*
426214Smcpowers 		 * We set the OBJECT_REFCNT_WAITING flag before we put
427214Smcpowers 		 * this deleting thread in a wait state, so other non-deleting
428214Smcpowers 		 * operation thread will signal to wake it up only when
429214Smcpowers 		 * the object reference count becomes zero and this flag
430214Smcpowers 		 * is set.
431214Smcpowers 		 */
432214Smcpowers 		objp->obj_delete_sync |= OBJECT_REFCNT_WAITING;
433214Smcpowers 		(void) pthread_cond_wait(&objp->obj_free_cond,
4347518SViswanathan.Kannappan@Sun.COM 		    &objp->object_mutex);
435214Smcpowers 	}
436214Smcpowers 
437214Smcpowers 	objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING;
438214Smcpowers 
439214Smcpowers 	/* Mark object as no longer valid. */
440214Smcpowers 	objp->magic_marker = 0;
441214Smcpowers 
442214Smcpowers 	(void) pthread_cond_destroy(&objp->obj_free_cond);
443214Smcpowers }
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate /*
4460Sstevel@tonic-gate  * Delete a session object:
4470Sstevel@tonic-gate  * - Remove the object from the session's object list.
4480Sstevel@tonic-gate  * - Release the storage allocated to the object.
4490Sstevel@tonic-gate  *
4500Sstevel@tonic-gate  * The boolean argument ses_lock_held is used to indicate that whether
4510Sstevel@tonic-gate  * the caller holds the session lock or not.
4520Sstevel@tonic-gate  * - When called by kernel_delete_all_objects_in_session() or
4530Sstevel@tonic-gate  *   kernel_delete_pri_objects_in_slot() -- ses_lock_held = TRUE.
4540Sstevel@tonic-gate  *
4550Sstevel@tonic-gate  * The boolean argument wrapper_only is used to indicate that whether
4560Sstevel@tonic-gate  * the caller only wants to clean up the object wrapper from the library and
4570Sstevel@tonic-gate  * needs not to make an ioctl call.
4580Sstevel@tonic-gate  * - This argument only applies to the object created in the provider level.
4590Sstevel@tonic-gate  * - When called by kernel_cleanup_pri_objects_in_slot(), wrapper_only is TRUE.
4600Sstevel@tonic-gate  * - When called by C_DestroyObject(), wrapper_only is FALSE.
4610Sstevel@tonic-gate  * - When called by kernel_delete_all_objects_in_session(), the value of
4620Sstevel@tonic-gate  *   wrapper_only depends on its caller.
4630Sstevel@tonic-gate  */
4640Sstevel@tonic-gate CK_RV
kernel_delete_session_object(kernel_session_t * sp,kernel_object_t * objp,boolean_t ses_lock_held,boolean_t wrapper_only)4650Sstevel@tonic-gate kernel_delete_session_object(kernel_session_t *sp, kernel_object_t *objp,
4660Sstevel@tonic-gate     boolean_t ses_lock_held, boolean_t wrapper_only)
4670Sstevel@tonic-gate {
4680Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
4690Sstevel@tonic-gate 	crypto_object_destroy_t	obj_destroy;
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 	/*
4720Sstevel@tonic-gate 	 * Check to see if the caller holds the lock on the session.
4730Sstevel@tonic-gate 	 * If not, we need to acquire that lock in order to proceed.
4740Sstevel@tonic-gate 	 */
4750Sstevel@tonic-gate 	if (!ses_lock_held) {
4760Sstevel@tonic-gate 		/* Acquire the session lock. */
4770Sstevel@tonic-gate 		(void) pthread_mutex_lock(&sp->session_mutex);
4780Sstevel@tonic-gate 	}
4790Sstevel@tonic-gate 
4800Sstevel@tonic-gate 	/* Remove the object from the session's object list first. */
481214Smcpowers 	rv = kernel_remove_object_from_session(objp, sp);
4820Sstevel@tonic-gate 	if (!ses_lock_held) {
4830Sstevel@tonic-gate 		/*
4840Sstevel@tonic-gate 		 * If the session lock is obtained by this function,
4850Sstevel@tonic-gate 		 * then release that lock after removing the object
4860Sstevel@tonic-gate 		 * from session's object list.
4870Sstevel@tonic-gate 		 * We want the releasing of the object storage to
4880Sstevel@tonic-gate 		 * be done without holding the session lock.
4890Sstevel@tonic-gate 		 */
4900Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&sp->session_mutex);
4910Sstevel@tonic-gate 	}
4920Sstevel@tonic-gate 
493214Smcpowers 	if (rv != CKR_OK)
494214Smcpowers 		return (rv);
4950Sstevel@tonic-gate 
496*9661SZdenek.Kotala@Sun.COM 	kernel_delete_object_cleanup(objp, wrapper_only);
4970Sstevel@tonic-gate 
4980Sstevel@tonic-gate 	/* Destroy the object. */
4990Sstevel@tonic-gate 	if (objp->is_lib_obj) {
5000Sstevel@tonic-gate 		/*
5010Sstevel@tonic-gate 		 * If this object is created in the library, cleanup the
5020Sstevel@tonic-gate 		 * contents of this object such as free all the storage
5030Sstevel@tonic-gate 		 * allocated for this object.
5040Sstevel@tonic-gate 		 */
5050Sstevel@tonic-gate 		kernel_cleanup_object(objp);
5060Sstevel@tonic-gate 	} else {
5070Sstevel@tonic-gate 		/*
5080Sstevel@tonic-gate 		 * This object is created in the HW provider. If wrapper_only
5090Sstevel@tonic-gate 		 * is FALSE, make an ioctl call to destroy it in kernel.
5100Sstevel@tonic-gate 		 */
5110Sstevel@tonic-gate 		if (!wrapper_only) {
5120Sstevel@tonic-gate 			obj_destroy.od_session = sp->k_session;
5130Sstevel@tonic-gate 			obj_destroy.od_handle = objp->k_handle;
5140Sstevel@tonic-gate 
515214Smcpowers 			while (ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY,
516214Smcpowers 			    &obj_destroy) < 0) {
5170Sstevel@tonic-gate 				if (errno != EINTR)
5180Sstevel@tonic-gate 					break;
5190Sstevel@tonic-gate 			}
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 			/*
5220Sstevel@tonic-gate 			 * Ignore ioctl return codes for a session object.
5230Sstevel@tonic-gate 			 * If the kernel can not delete a session object, it
5240Sstevel@tonic-gate 			 * is likely caused by the HW provider. There's not
5250Sstevel@tonic-gate 			 * much that can be done.  The library will still
5260Sstevel@tonic-gate 			 * cleanup the object wrapper in the library. The HW
5270Sstevel@tonic-gate 			 * provider will destroy all session objects when
5280Sstevel@tonic-gate 			 * the application exits.
5290Sstevel@tonic-gate 			 */
5300Sstevel@tonic-gate 		}
5310Sstevel@tonic-gate 	}
5320Sstevel@tonic-gate 
533214Smcpowers 	/* Reset OBJECT_IS_DELETING flag. */
534214Smcpowers 	objp->obj_delete_sync &= ~OBJECT_IS_DELETING;
5350Sstevel@tonic-gate 
536214Smcpowers 	(void) pthread_mutex_unlock(&objp->object_mutex);
537214Smcpowers 	/* Destroy the object lock */
538214Smcpowers 	(void) pthread_mutex_destroy(&objp->object_mutex);
539214Smcpowers 	/* Free the object itself */
540214Smcpowers 	kernel_object_delay_free(objp);
541214Smcpowers 
542214Smcpowers 	return (CKR_OK);
5430Sstevel@tonic-gate }
5440Sstevel@tonic-gate 
5450Sstevel@tonic-gate /*
5460Sstevel@tonic-gate  * Delete all the objects in a session. The caller holds the lock
5470Sstevel@tonic-gate  * on the session.   If the wrapper_only argument is TRUE, the caller only
5480Sstevel@tonic-gate  * want to clean up object wrappers in the library.
5490Sstevel@tonic-gate  */
5500Sstevel@tonic-gate void
kernel_delete_all_objects_in_session(kernel_session_t * sp,boolean_t wrapper_only)5510Sstevel@tonic-gate kernel_delete_all_objects_in_session(kernel_session_t *sp,
5520Sstevel@tonic-gate     boolean_t wrapper_only)
5530Sstevel@tonic-gate {
5540Sstevel@tonic-gate 	kernel_object_t *objp = sp->object_list;
5550Sstevel@tonic-gate 	kernel_object_t *objp1;
5560Sstevel@tonic-gate 
5570Sstevel@tonic-gate 	/* Delete all the objects in the session. */
5580Sstevel@tonic-gate 	while (objp) {
5590Sstevel@tonic-gate 		objp1 = objp->next;
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 		/*
5620Sstevel@tonic-gate 		 * Delete an session object by calling
5630Sstevel@tonic-gate 		 * kernel_delete_session_object():
5640Sstevel@tonic-gate 		 * - The 3rd TRUE boolean argument indicates that the caller
5650Sstevel@tonic-gate 		 *   holds the session lock.
5660Sstevel@tonic-gate 		 * - The 4th boolean argument indicates whether we only want
5670Sstevel@tonic-gate 		 *   clean up object wrappers in the library.
5680Sstevel@tonic-gate 		 */
5690Sstevel@tonic-gate 		(void) kernel_delete_session_object(sp, objp, B_TRUE,
5700Sstevel@tonic-gate 		    wrapper_only);
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 		objp = objp1;
5730Sstevel@tonic-gate 	}
5740Sstevel@tonic-gate }
5750Sstevel@tonic-gate 
5760Sstevel@tonic-gate static CK_RV
add_to_search_result(kernel_object_t * obj,find_context_t * fcontext,CK_ULONG * num_result_alloc)5770Sstevel@tonic-gate add_to_search_result(kernel_object_t *obj, find_context_t *fcontext,
5780Sstevel@tonic-gate     CK_ULONG *num_result_alloc)
5790Sstevel@tonic-gate {
5800Sstevel@tonic-gate 	/*
5810Sstevel@tonic-gate 	 * allocate space for storing results if the currently
5820Sstevel@tonic-gate 	 * allocated space is not enough
5830Sstevel@tonic-gate 	 */
5840Sstevel@tonic-gate 	if (*num_result_alloc <= fcontext->num_results) {
5850Sstevel@tonic-gate 		fcontext->objs_found = realloc(fcontext->objs_found,
5860Sstevel@tonic-gate 		    sizeof (kernel_object_t *) * (*num_result_alloc + BUFSIZ));
5870Sstevel@tonic-gate 		if (fcontext->objs_found == NULL) {
5880Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
5890Sstevel@tonic-gate 		}
5900Sstevel@tonic-gate 		*num_result_alloc += BUFSIZ;
5910Sstevel@tonic-gate 	}
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 	(fcontext->objs_found)[(fcontext->num_results)++] = obj;
5940Sstevel@tonic-gate 	return (CKR_OK);
5950Sstevel@tonic-gate }
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate static CK_RV
search_for_objects(kernel_session_t * sp,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,find_context_t * fcontext)5980Sstevel@tonic-gate search_for_objects(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
5990Sstevel@tonic-gate     CK_ULONG ulCount, find_context_t *fcontext)
6000Sstevel@tonic-gate {
6010Sstevel@tonic-gate 	kernel_session_t *session_p;
6020Sstevel@tonic-gate 	kernel_object_t *obj;
6037518SViswanathan.Kannappan@Sun.COM 	CK_OBJECT_CLASS pclasses[6]; /* classes attrs possibly exist */
6040Sstevel@tonic-gate 	CK_ULONG num_pclasses;	/* number of possible classes */
6050Sstevel@tonic-gate 	CK_ULONG num_result_alloc = 0; /* spaces allocated for results */
6060Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6070Sstevel@tonic-gate 	kernel_slot_t	*pslot;
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 	if (ulCount > 0) {
6100Sstevel@tonic-gate 		/* there are some search requirement */
6110Sstevel@tonic-gate 		kernel_process_find_attr(pclasses, &num_pclasses,
6120Sstevel@tonic-gate 		    pTemplate, ulCount);
6130Sstevel@tonic-gate 	}
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 	/* Acquire the slot lock */
6160Sstevel@tonic-gate 	pslot = slot_table[sp->ses_slotid];
6170Sstevel@tonic-gate 	(void) pthread_mutex_lock(&pslot->sl_mutex);
6180Sstevel@tonic-gate 
6190Sstevel@tonic-gate 	/*
6200Sstevel@tonic-gate 	 * Go through all objects in each session.
6210Sstevel@tonic-gate 	 * Acquire individual session lock for the session
6220Sstevel@tonic-gate 	 * we are searching.
6230Sstevel@tonic-gate 	 */
6240Sstevel@tonic-gate 	session_p = pslot->sl_sess_list;
6250Sstevel@tonic-gate 	while (session_p) {
6260Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
6270Sstevel@tonic-gate 		obj = session_p->object_list;
6280Sstevel@tonic-gate 		while (obj) {
6290Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
6300Sstevel@tonic-gate 			if (ulCount > 0) {
6310Sstevel@tonic-gate 				if (kernel_find_match_attrs(obj, pclasses,
6320Sstevel@tonic-gate 				    num_pclasses, pTemplate, ulCount)) {
6330Sstevel@tonic-gate 					rv = add_to_search_result(
6340Sstevel@tonic-gate 					    obj, fcontext, &num_result_alloc);
6350Sstevel@tonic-gate 				}
6360Sstevel@tonic-gate 			} else {
6370Sstevel@tonic-gate 				/* no search criteria, just record the object */
6380Sstevel@tonic-gate 				rv = add_to_search_result(obj, fcontext,
6390Sstevel@tonic-gate 				    &num_result_alloc);
6400Sstevel@tonic-gate 			}
6410Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
6420Sstevel@tonic-gate 			if (rv != CKR_OK) {
6430Sstevel@tonic-gate 				(void) pthread_mutex_unlock(
6440Sstevel@tonic-gate 				    &session_p->session_mutex);
6450Sstevel@tonic-gate 				goto cleanup;
6460Sstevel@tonic-gate 			}
6470Sstevel@tonic-gate 			obj = obj->next;
6480Sstevel@tonic-gate 		}
6490Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
6500Sstevel@tonic-gate 		session_p = session_p->next;
6510Sstevel@tonic-gate 	}
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate cleanup:
6540Sstevel@tonic-gate 	/* Release the slot lock */
6550Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
6560Sstevel@tonic-gate 	return (rv);
6570Sstevel@tonic-gate }
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate /*
6600Sstevel@tonic-gate  * Initialize the context for C_FindObjects() calls
6610Sstevel@tonic-gate  */
6620Sstevel@tonic-gate CK_RV
kernel_find_objects_init(kernel_session_t * sp,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)6630Sstevel@tonic-gate kernel_find_objects_init(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
6640Sstevel@tonic-gate     CK_ULONG ulCount)
6650Sstevel@tonic-gate {
6660Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6670Sstevel@tonic-gate 	CK_OBJECT_CLASS class; /* for kernel_validate_attr(). Value unused */
6680Sstevel@tonic-gate 	find_context_t *fcontext;
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 	if (ulCount) {
6710Sstevel@tonic-gate 		rv = kernel_validate_attr(pTemplate, ulCount, &class);
6720Sstevel@tonic-gate 		/* Make sure all attributes in template are valid */
6730Sstevel@tonic-gate 		if (rv != CKR_OK) {
6740Sstevel@tonic-gate 			return (rv);
6750Sstevel@tonic-gate 		}
6760Sstevel@tonic-gate 	}
6770Sstevel@tonic-gate 
6780Sstevel@tonic-gate 	/* prepare the find context */
6790Sstevel@tonic-gate 	fcontext = calloc(1, sizeof (find_context_t));
6800Sstevel@tonic-gate 	if (fcontext == NULL) {
6810Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
6820Sstevel@tonic-gate 	}
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 	rv = search_for_objects(sp, pTemplate, ulCount, fcontext);
6850Sstevel@tonic-gate 	if (rv != CKR_OK) {
6860Sstevel@tonic-gate 		free(fcontext);
6870Sstevel@tonic-gate 		return (rv);
6880Sstevel@tonic-gate 	}
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 	/* store the find_context in the session */
6910Sstevel@tonic-gate 	sp->find_objects.context = (CK_VOID_PTR)fcontext;
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	return (rv);
6940Sstevel@tonic-gate }
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate void
kernel_find_objects_final(kernel_session_t * sp)6970Sstevel@tonic-gate kernel_find_objects_final(kernel_session_t *sp)
6980Sstevel@tonic-gate {
6990Sstevel@tonic-gate 	find_context_t *fcontext;
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 	fcontext = sp->find_objects.context;
7020Sstevel@tonic-gate 	sp->find_objects.context = NULL;
7030Sstevel@tonic-gate 	sp->find_objects.flags = 0;
7040Sstevel@tonic-gate 	if (fcontext->objs_found != NULL) {
7050Sstevel@tonic-gate 		free(fcontext->objs_found);
7060Sstevel@tonic-gate 	}
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 	free(fcontext);
7090Sstevel@tonic-gate }
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate void
kernel_find_objects(kernel_session_t * sp,CK_OBJECT_HANDLE * obj_found,CK_ULONG max_obj_requested,CK_ULONG * found_obj_count)7120Sstevel@tonic-gate kernel_find_objects(kernel_session_t *sp, CK_OBJECT_HANDLE *obj_found,
7130Sstevel@tonic-gate     CK_ULONG max_obj_requested, CK_ULONG *found_obj_count)
7140Sstevel@tonic-gate {
7150Sstevel@tonic-gate 	find_context_t *fcontext;
7160Sstevel@tonic-gate 	CK_ULONG num_obj_found = 0;
7170Sstevel@tonic-gate 	CK_ULONG i;
7180Sstevel@tonic-gate 	kernel_object_t *obj;
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate 	fcontext = sp->find_objects.context;
7210Sstevel@tonic-gate 
7220Sstevel@tonic-gate 	for (i = fcontext->next_result_index;
7230Sstevel@tonic-gate 	    ((num_obj_found < max_obj_requested) &&
7240Sstevel@tonic-gate 	    (i < fcontext->num_results));
7250Sstevel@tonic-gate 	    i++) {
7260Sstevel@tonic-gate 		obj = fcontext->objs_found[i];
7270Sstevel@tonic-gate 		if (obj != NULL) {
7280Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
7290Sstevel@tonic-gate 			/* a sanity check to make sure the obj is still valid */
7300Sstevel@tonic-gate 			if (obj->magic_marker == KERNELTOKEN_OBJECT_MAGIC) {
7310Sstevel@tonic-gate 				obj_found[num_obj_found] =
7320Sstevel@tonic-gate 				    (CK_OBJECT_HANDLE)obj;
7330Sstevel@tonic-gate 				num_obj_found++;
7340Sstevel@tonic-gate 			}
7350Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
7360Sstevel@tonic-gate 		}
7370Sstevel@tonic-gate 	}
7380Sstevel@tonic-gate 	fcontext->next_result_index = i;
7390Sstevel@tonic-gate 	*found_obj_count = num_obj_found;
7400Sstevel@tonic-gate }
7410Sstevel@tonic-gate 
7420Sstevel@tonic-gate /*
7430Sstevel@tonic-gate  * Add an token object to the token object list in slot.
7440Sstevel@tonic-gate  *
7450Sstevel@tonic-gate  * This function will acquire the lock on the slot, and release
7460Sstevel@tonic-gate  * that lock after adding the object to the slot's token object list.
7470Sstevel@tonic-gate  */
7480Sstevel@tonic-gate void
kernel_add_token_object_to_slot(kernel_object_t * objp,kernel_slot_t * pslot)7490Sstevel@tonic-gate kernel_add_token_object_to_slot(kernel_object_t *objp, kernel_slot_t *pslot)
7500Sstevel@tonic-gate {
7510Sstevel@tonic-gate 	/* Acquire the slot lock. */
7520Sstevel@tonic-gate 	(void) pthread_mutex_lock(&pslot->sl_mutex);
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	/* Insert the new object in front of slot's token object list. */
7550Sstevel@tonic-gate 	if (pslot->sl_tobj_list == NULL) {
7560Sstevel@tonic-gate 		pslot->sl_tobj_list = objp;
7570Sstevel@tonic-gate 		objp->next = NULL;
7580Sstevel@tonic-gate 		objp->prev = NULL;
7590Sstevel@tonic-gate 	} else {
7600Sstevel@tonic-gate 		pslot->sl_tobj_list->prev = objp;
7610Sstevel@tonic-gate 		objp->next = pslot->sl_tobj_list;
7620Sstevel@tonic-gate 		objp->prev = NULL;
7630Sstevel@tonic-gate 		pslot->sl_tobj_list = objp;
7640Sstevel@tonic-gate 	}
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 	/* Release the slot lock. */
7670Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
7680Sstevel@tonic-gate }
7690Sstevel@tonic-gate 
7700Sstevel@tonic-gate /*
7710Sstevel@tonic-gate  * Remove an token object from the slot's token object list.
7720Sstevel@tonic-gate  * This routine is called by kernel_delete_token_object().
7730Sstevel@tonic-gate  * The caller of this function hold the slot lock.
7740Sstevel@tonic-gate  */
7750Sstevel@tonic-gate void
kernel_remove_token_object_from_slot(kernel_slot_t * pslot,kernel_object_t * objp)7760Sstevel@tonic-gate kernel_remove_token_object_from_slot(kernel_slot_t *pslot,
7770Sstevel@tonic-gate     kernel_object_t *objp)
7780Sstevel@tonic-gate {
7790Sstevel@tonic-gate 
7800Sstevel@tonic-gate 	if (pslot->sl_tobj_list == objp) {
7810Sstevel@tonic-gate 		/* Object is the first one in the list */
7820Sstevel@tonic-gate 		if (objp->next) {
7830Sstevel@tonic-gate 			pslot->sl_tobj_list = objp->next;
7840Sstevel@tonic-gate 			objp->next->prev = NULL;
7850Sstevel@tonic-gate 		} else {
7860Sstevel@tonic-gate 			/* Object is the only one in the list. */
7870Sstevel@tonic-gate 			pslot->sl_tobj_list = NULL;
7880Sstevel@tonic-gate 		}
7890Sstevel@tonic-gate 	} else {
7900Sstevel@tonic-gate 		/* Object is not the first one in the list. */
7910Sstevel@tonic-gate 		if (objp->next) {
7920Sstevel@tonic-gate 			/* Object is in the middle of the list. */
7930Sstevel@tonic-gate 			objp->prev->next = objp->next;
7940Sstevel@tonic-gate 			objp->next->prev = objp->prev;
7950Sstevel@tonic-gate 		} else {
7960Sstevel@tonic-gate 			/* Object is the last one in the list. */
7970Sstevel@tonic-gate 			objp->prev->next = NULL;
7980Sstevel@tonic-gate 		}
7990Sstevel@tonic-gate 	}
8000Sstevel@tonic-gate }
8010Sstevel@tonic-gate 
8020Sstevel@tonic-gate /*
8030Sstevel@tonic-gate  * Delete a token object:
8040Sstevel@tonic-gate  * - Remove the object from the slot's token object list.
8050Sstevel@tonic-gate  * - Release the storage allocated to the object.
8060Sstevel@tonic-gate  *
8070Sstevel@tonic-gate  * The boolean argument slot_lock_held is used to indicate that whether
8080Sstevel@tonic-gate  * the caller holds the slot lock or not. When the caller does not hold
8090Sstevel@tonic-gate  * the slot lock, this function will acquire that lock in order to proceed,
8100Sstevel@tonic-gate  * and also release that lock before returning to caller.
8110Sstevel@tonic-gate  *
8120Sstevel@tonic-gate  * The boolean argument wrapper_only is used to indicate that whether
8130Sstevel@tonic-gate  * the caller only wants to the object wrapper from library.
8140Sstevel@tonic-gate  */
8150Sstevel@tonic-gate CK_RV
kernel_delete_token_object(kernel_slot_t * pslot,kernel_session_t * sp,kernel_object_t * objp,boolean_t slot_lock_held,boolean_t wrapper_only)8160Sstevel@tonic-gate kernel_delete_token_object(kernel_slot_t *pslot, kernel_session_t *sp,
8170Sstevel@tonic-gate     kernel_object_t *objp, boolean_t slot_lock_held, boolean_t wrapper_only)
8180Sstevel@tonic-gate {
8190Sstevel@tonic-gate 	CK_RV rv;
8200Sstevel@tonic-gate 	crypto_object_destroy_t	obj_destroy;
8210Sstevel@tonic-gate 	int r;
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	/*
8240Sstevel@tonic-gate 	 * Check to see if the caller holds the lock on the slot.
8250Sstevel@tonic-gate 	 * If not, we need to acquire that lock in order to proceed.
8260Sstevel@tonic-gate 	 */
8270Sstevel@tonic-gate 	if (!slot_lock_held) {
8280Sstevel@tonic-gate 		(void) pthread_mutex_lock(&pslot->sl_mutex);
8290Sstevel@tonic-gate 	}
8300Sstevel@tonic-gate 
8310Sstevel@tonic-gate 	/* Remove the object from the slot's token object list first. */
8320Sstevel@tonic-gate 	kernel_remove_token_object_from_slot(pslot, objp);
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	/* Release the slot lock if the call doesn't hold the lock. */
8350Sstevel@tonic-gate 	if (!slot_lock_held) {
8360Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&pslot->sl_mutex);
8370Sstevel@tonic-gate 	}
8380Sstevel@tonic-gate 
839*9661SZdenek.Kotala@Sun.COM 	kernel_delete_object_cleanup(objp, wrapper_only);
8400Sstevel@tonic-gate 
8410Sstevel@tonic-gate 	if (!wrapper_only) {
8420Sstevel@tonic-gate 		obj_destroy.od_session = sp->k_session;
8430Sstevel@tonic-gate 		obj_destroy.od_handle = objp->k_handle;
8440Sstevel@tonic-gate 
8450Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY,
8460Sstevel@tonic-gate 		    &obj_destroy)) < 0) {
8470Sstevel@tonic-gate 			if (errno != EINTR)
8480Sstevel@tonic-gate 				break;
8490Sstevel@tonic-gate 		}
8500Sstevel@tonic-gate 		if (r < 0) {
8510Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
8520Sstevel@tonic-gate 		} else {
8530Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
8540Sstevel@tonic-gate 			    obj_destroy.od_return_value);
8550Sstevel@tonic-gate 		}
8560Sstevel@tonic-gate 
8570Sstevel@tonic-gate 		/*
8580Sstevel@tonic-gate 		 * Could not destroy an object from kernel. Write a warning
8590Sstevel@tonic-gate 		 * in syslog, but we still clean up the object wrapper in
8600Sstevel@tonic-gate 		 * the library.
8610Sstevel@tonic-gate 		 */
8620Sstevel@tonic-gate 		if (rv != CKR_OK) {
8630Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "pkcs11_kernel: Could not "
8640Sstevel@tonic-gate 			    "destroy an object in kernel.");
8650Sstevel@tonic-gate 		}
8660Sstevel@tonic-gate 	}
8670Sstevel@tonic-gate 
868214Smcpowers 	(void) pthread_mutex_unlock(&objp->object_mutex);
869214Smcpowers 	/* Destroy the object lock */
870214Smcpowers 	(void) pthread_mutex_destroy(&objp->object_mutex);
871214Smcpowers 	/* Free the object itself */
872214Smcpowers 	kernel_object_delay_free(objp);
8730Sstevel@tonic-gate 
874214Smcpowers 	return (CKR_OK);
8750Sstevel@tonic-gate }
8760Sstevel@tonic-gate 
8770Sstevel@tonic-gate /*
8780Sstevel@tonic-gate  * Clean up private object wrappers in this slot. The caller holds the slot
8790Sstevel@tonic-gate  * lock.
8800Sstevel@tonic-gate  */
8810Sstevel@tonic-gate void
kernel_cleanup_pri_objects_in_slot(kernel_slot_t * pslot,kernel_session_t * cur_sp)8820Sstevel@tonic-gate kernel_cleanup_pri_objects_in_slot(kernel_slot_t *pslot,
8830Sstevel@tonic-gate     kernel_session_t *cur_sp)
8840Sstevel@tonic-gate {
8850Sstevel@tonic-gate 	kernel_session_t *session_p;
8860Sstevel@tonic-gate 	kernel_object_t *objp;
8870Sstevel@tonic-gate 	kernel_object_t *objp1;
8880Sstevel@tonic-gate 
8890Sstevel@tonic-gate 	/*
8900Sstevel@tonic-gate 	 * Delete every private token object from the slot' token object list
8910Sstevel@tonic-gate 	 */
8920Sstevel@tonic-gate 	objp = pslot->sl_tobj_list;
8930Sstevel@tonic-gate 	while (objp) {
8940Sstevel@tonic-gate 		objp1 = objp->next;
8950Sstevel@tonic-gate 		/*
8960Sstevel@tonic-gate 		 * The first TRUE boolean argument indicates that the caller
8970Sstevel@tonic-gate 		 * hold the slot lock.  The second TRUE boolean argument
8980Sstevel@tonic-gate 		 * indicates that the caller just wants to clean up the object
8990Sstevel@tonic-gate 		 * wrapper from the library only.
9000Sstevel@tonic-gate 		 */
9010Sstevel@tonic-gate 		if (objp->bool_attr_mask & PRIVATE_BOOL_ON) {
9020Sstevel@tonic-gate 			(void) kernel_delete_token_object(pslot, cur_sp, objp,
9030Sstevel@tonic-gate 			    B_TRUE, B_TRUE);
9040Sstevel@tonic-gate 		}
9050Sstevel@tonic-gate 		objp = objp1;
9060Sstevel@tonic-gate 	}
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	/*
9090Sstevel@tonic-gate 	 * Walk through all the sessions in this slot and delete every
9100Sstevel@tonic-gate 	 * private object.
9110Sstevel@tonic-gate 	 */
9120Sstevel@tonic-gate 	session_p = pslot->sl_sess_list;
9130Sstevel@tonic-gate 	while (session_p) {
9140Sstevel@tonic-gate 
9150Sstevel@tonic-gate 		/* Delete all the objects in the session. */
9160Sstevel@tonic-gate 		objp = session_p->object_list;
9170Sstevel@tonic-gate 		while (objp) {
9180Sstevel@tonic-gate 			objp1 = objp->next;
9190Sstevel@tonic-gate 			/*
9200Sstevel@tonic-gate 			 * The FALSE boolean argument indicates that the
9210Sstevel@tonic-gate 			 * caller does not hold the session lock.  The TRUE
9220Sstevel@tonic-gate 			 * boolean argument indicates that the caller just
9230Sstevel@tonic-gate 			 * want to clean upt the object wrapper from the
9240Sstevel@tonic-gate 			 * library only.
9250Sstevel@tonic-gate 			 */
9260Sstevel@tonic-gate 			if (objp->bool_attr_mask & PRIVATE_BOOL_ON) {
9270Sstevel@tonic-gate 				(void) kernel_delete_session_object(session_p,
9280Sstevel@tonic-gate 				    objp, B_FALSE, B_TRUE);
9290Sstevel@tonic-gate 			}
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 			objp = objp1;
9320Sstevel@tonic-gate 		}
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate 		session_p = session_p->next;
9350Sstevel@tonic-gate 	}
9360Sstevel@tonic-gate }
9370Sstevel@tonic-gate 
9380Sstevel@tonic-gate /*
9390Sstevel@tonic-gate  * Get the object size in bytes for the objects created in the library.
9400Sstevel@tonic-gate  */
9410Sstevel@tonic-gate CK_RV
kernel_get_object_size(kernel_object_t * obj,CK_ULONG_PTR pulSize)9420Sstevel@tonic-gate kernel_get_object_size(kernel_object_t *obj, CK_ULONG_PTR pulSize)
9430Sstevel@tonic-gate {
9440Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
9450Sstevel@tonic-gate 	CK_ULONG obj_size;
9460Sstevel@tonic-gate 	biginteger_t *big;
9470Sstevel@tonic-gate 
9480Sstevel@tonic-gate 	obj_size = sizeof (kernel_object_t);
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	switch (obj->class) {
9510Sstevel@tonic-gate 	case CKO_PUBLIC_KEY:
9520Sstevel@tonic-gate 		if (obj->key_type == CKK_RSA) {
9530Sstevel@tonic-gate 			big = OBJ_PUB_RSA_PUBEXPO(obj);
9540Sstevel@tonic-gate 			obj_size += big->big_value_len;
9550Sstevel@tonic-gate 			big = OBJ_PUB_RSA_MOD(obj);
9560Sstevel@tonic-gate 			obj_size += big->big_value_len;
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 		} else if (obj->key_type == CKK_DSA) {
9590Sstevel@tonic-gate 			big = OBJ_PUB_DSA_PRIME(obj);
9600Sstevel@tonic-gate 			obj_size += big->big_value_len;
9610Sstevel@tonic-gate 			big = OBJ_PUB_DSA_SUBPRIME(obj);
9620Sstevel@tonic-gate 			obj_size += big->big_value_len;
9630Sstevel@tonic-gate 			big = OBJ_PUB_DSA_BASE(obj);
9640Sstevel@tonic-gate 			obj_size += big->big_value_len;
9650Sstevel@tonic-gate 			big = OBJ_PUB_DSA_VALUE(obj);
9660Sstevel@tonic-gate 			obj_size += big->big_value_len;
9670Sstevel@tonic-gate 
9684219Smcpowers 		} else if (obj->key_type == CKK_EC) {
9694219Smcpowers 			big = OBJ_PUB_EC_POINT(obj);
9704219Smcpowers 			obj_size += big->big_value_len;
9714219Smcpowers 
9720Sstevel@tonic-gate 		} else {
9730Sstevel@tonic-gate 			rv = CKR_OBJECT_HANDLE_INVALID;
9740Sstevel@tonic-gate 		}
9750Sstevel@tonic-gate 		break;
9760Sstevel@tonic-gate 
9770Sstevel@tonic-gate 	case CKO_PRIVATE_KEY:
9780Sstevel@tonic-gate 		if (obj->key_type == CKK_RSA) {
9790Sstevel@tonic-gate 			big = OBJ_PRI_RSA_MOD(obj);
9800Sstevel@tonic-gate 			obj_size += big->big_value_len;
9810Sstevel@tonic-gate 
9820Sstevel@tonic-gate 			big = OBJ_PRI_RSA_PUBEXPO(obj); /* optional */
9830Sstevel@tonic-gate 			if (big != NULL) {
9840Sstevel@tonic-gate 				obj_size += big->big_value_len;
9850Sstevel@tonic-gate 			}
9860Sstevel@tonic-gate 
9870Sstevel@tonic-gate 			big = OBJ_PRI_RSA_PRIEXPO(obj);
9880Sstevel@tonic-gate 			obj_size += big->big_value_len;
9890Sstevel@tonic-gate 
9900Sstevel@tonic-gate 			big = OBJ_PRI_RSA_PRIME1(obj); /* optional */
9910Sstevel@tonic-gate 			if (big != NULL) {
9920Sstevel@tonic-gate 				obj_size += big->big_value_len;
9930Sstevel@tonic-gate 			}
9940Sstevel@tonic-gate 
9950Sstevel@tonic-gate 			big = OBJ_PRI_RSA_PRIME2(obj); /* optional */
9960Sstevel@tonic-gate 			if (big != NULL) {
9970Sstevel@tonic-gate 				obj_size += big->big_value_len;
9980Sstevel@tonic-gate 			}
9990Sstevel@tonic-gate 
10000Sstevel@tonic-gate 			big = OBJ_PRI_RSA_EXPO1(obj); /* optional */
10010Sstevel@tonic-gate 			if (big != NULL) {
10020Sstevel@tonic-gate 				obj_size += big->big_value_len;
10030Sstevel@tonic-gate 			}
10040Sstevel@tonic-gate 
10050Sstevel@tonic-gate 			big = OBJ_PRI_RSA_EXPO2(obj); /* optional */
10060Sstevel@tonic-gate 			if (big != NULL) {
10070Sstevel@tonic-gate 				obj_size += big->big_value_len;
10080Sstevel@tonic-gate 			}
10090Sstevel@tonic-gate 
10100Sstevel@tonic-gate 			big = OBJ_PRI_RSA_COEF(obj); /* optional */
10110Sstevel@tonic-gate 			if (big != NULL) {
10120Sstevel@tonic-gate 				obj_size += big->big_value_len;
10130Sstevel@tonic-gate 			}
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate 		} else if (obj->key_type == CKK_DSA) {
10160Sstevel@tonic-gate 			big = OBJ_PRI_DSA_PRIME(obj);
10170Sstevel@tonic-gate 			obj_size += big->big_value_len;
10180Sstevel@tonic-gate 			big = OBJ_PRI_DSA_SUBPRIME(obj);
10190Sstevel@tonic-gate 			obj_size += big->big_value_len;
10200Sstevel@tonic-gate 			big = OBJ_PRI_DSA_BASE(obj);
10210Sstevel@tonic-gate 			obj_size += big->big_value_len;
10220Sstevel@tonic-gate 			big = OBJ_PRI_DSA_VALUE(obj);
10230Sstevel@tonic-gate 			obj_size += big->big_value_len;
10240Sstevel@tonic-gate 
10254219Smcpowers 		} else if (obj->key_type == CKK_EC) {
10264219Smcpowers 			big = OBJ_PRI_EC_VALUE(obj);
10274219Smcpowers 			obj_size += big->big_value_len;
10284219Smcpowers 
10290Sstevel@tonic-gate 		} else {
10300Sstevel@tonic-gate 			rv = CKR_OBJECT_HANDLE_INVALID;
10310Sstevel@tonic-gate 		}
10320Sstevel@tonic-gate 		break;
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 	case CKO_SECRET_KEY:
10350Sstevel@tonic-gate 		obj_size += OBJ_SEC_VALUE_LEN(obj);
10360Sstevel@tonic-gate 		break;
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate 	default:
10390Sstevel@tonic-gate 		rv = CKR_OBJECT_HANDLE_INVALID;
10400Sstevel@tonic-gate 	}
10410Sstevel@tonic-gate 
10420Sstevel@tonic-gate 	if (rv == CKR_OK) {
10430Sstevel@tonic-gate 		*pulSize = obj_size;
10440Sstevel@tonic-gate 	}
10450Sstevel@tonic-gate 
10460Sstevel@tonic-gate 	return (rv);
10470Sstevel@tonic-gate }
1048214Smcpowers 
1049214Smcpowers /*
1050214Smcpowers  * This function adds the to-be-freed session object to a linked list.
1051214Smcpowers  * When the number of objects queued in the linked list reaches the
1052214Smcpowers  * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
1053214Smcpowers  * object (FIFO) in the list.
1054214Smcpowers  */
1055214Smcpowers void
kernel_object_delay_free(kernel_object_t * objp)1056214Smcpowers kernel_object_delay_free(kernel_object_t *objp)
1057214Smcpowers {
1058214Smcpowers 	kernel_object_t *tmp;
1059214Smcpowers 
1060214Smcpowers 	(void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
1061214Smcpowers 
1062214Smcpowers 	/* Add the newly deleted object at the end of the list */
1063214Smcpowers 	objp->next = NULL;
1064214Smcpowers 	if (obj_delay_freed.first == NULL) {
1065214Smcpowers 		obj_delay_freed.last = objp;
1066214Smcpowers 		obj_delay_freed.first = objp;
1067214Smcpowers 	} else {
1068214Smcpowers 		obj_delay_freed.last->next = objp;
1069214Smcpowers 		obj_delay_freed.last = objp;
1070214Smcpowers 	}
1071214Smcpowers 
1072214Smcpowers 	if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
1073214Smcpowers 		/*
1074214Smcpowers 		 * Free the first object in the list only if
1075214Smcpowers 		 * the total count reaches maximum threshold.
1076214Smcpowers 		 */
1077214Smcpowers 		obj_delay_freed.count--;
1078214Smcpowers 		tmp = obj_delay_freed.first->next;
1079214Smcpowers 		free(obj_delay_freed.first);
1080214Smcpowers 		obj_delay_freed.first = tmp;
1081214Smcpowers 	}
1082214Smcpowers 	(void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
1083214Smcpowers }
1084