17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate  * CDDL HEADER START
37c478bd9Sstevel@tonic-gate  *
47c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5034448feSmcpowers  * Common Development and Distribution License (the "License").
6034448feSmcpowers  * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate  *
87c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate  * and limitations under the License.
127c478bd9Sstevel@tonic-gate  *
137c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate  *
197c478bd9Sstevel@tonic-gate  * CDDL HEADER END
207c478bd9Sstevel@tonic-gate  */
217c478bd9Sstevel@tonic-gate /*
221f49a79aSZdenek Kotala  * Copyright 2009 Sun Microsystems, Inc.  All rights reserved.
237c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
24*a8793c76SJason King  * Copyright (c) 2018, Joyent, Inc.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <errno.h>
317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
327c478bd9Sstevel@tonic-gate #include <cryptoutil.h>
337c478bd9Sstevel@tonic-gate #include "kernelGlobal.h"
347c478bd9Sstevel@tonic-gate #include "kernelObject.h"
357c478bd9Sstevel@tonic-gate #include "kernelSession.h"
367c478bd9Sstevel@tonic-gate #include "kernelSlot.h"
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * Add an object to the session's object list.
407c478bd9Sstevel@tonic-gate  *
417c478bd9Sstevel@tonic-gate  * This function will acquire the lock on the session, and release
427c478bd9Sstevel@tonic-gate  * that lock after adding the object to the session's object list.
437c478bd9Sstevel@tonic-gate  */
447c478bd9Sstevel@tonic-gate void
kernel_add_object_to_session(kernel_object_t * objp,kernel_session_t * sp)457c478bd9Sstevel@tonic-gate kernel_add_object_to_session(kernel_object_t *objp, kernel_session_t *sp)
467c478bd9Sstevel@tonic-gate {
477c478bd9Sstevel@tonic-gate 	/* Acquire the session lock. */
487c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&sp->session_mutex);
497c478bd9Sstevel@tonic-gate 
507c478bd9Sstevel@tonic-gate 	/* Insert the new object in front of session's object list. */
517c478bd9Sstevel@tonic-gate 	if (sp->object_list == NULL) {
527c478bd9Sstevel@tonic-gate 		sp->object_list = objp;
537c478bd9Sstevel@tonic-gate 		objp->next = NULL;
547c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
557c478bd9Sstevel@tonic-gate 	} else {
567c478bd9Sstevel@tonic-gate 		sp->object_list->prev = objp;
577c478bd9Sstevel@tonic-gate 		objp->next = sp->object_list;
587c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
597c478bd9Sstevel@tonic-gate 		sp->object_list = objp;
607c478bd9Sstevel@tonic-gate 	}
617c478bd9Sstevel@tonic-gate 
627c478bd9Sstevel@tonic-gate 	/* Release the session lock. */
637c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&sp->session_mutex);
647c478bd9Sstevel@tonic-gate }
657c478bd9Sstevel@tonic-gate 
667c478bd9Sstevel@tonic-gate /*
677c478bd9Sstevel@tonic-gate  * Clean up and release the storage allocated to the object.
687c478bd9Sstevel@tonic-gate  *
697c478bd9Sstevel@tonic-gate  * The function is called either with the object lock being held
707c478bd9Sstevel@tonic-gate  * (by caller kernel_delete_object()), or there is no object lock
717c478bd9Sstevel@tonic-gate  * yet (by kernel_build_XXX_object() during creating an object).
727c478bd9Sstevel@tonic-gate  */
737c478bd9Sstevel@tonic-gate void
kernel_cleanup_object(kernel_object_t * objp)747c478bd9Sstevel@tonic-gate kernel_cleanup_object(kernel_object_t *objp)
757c478bd9Sstevel@tonic-gate {
767c478bd9Sstevel@tonic-gate 	/*
777c478bd9Sstevel@tonic-gate 	 * Free the storage allocated to a secret key object.
787c478bd9Sstevel@tonic-gate 	 */
79bbbb143bSmcpowers 	if (objp->class == CKO_SECRET_KEY) {
80034448feSmcpowers 		if (OBJ_SEC(objp) != NULL && OBJ_SEC_VALUE(objp) != NULL) {
81*a8793c76SJason King 			freezero(OBJ_SEC_VALUE(objp), OBJ_SEC_VALUE_LEN(objp));
827c478bd9Sstevel@tonic-gate 			OBJ_SEC_VALUE(objp) = NULL;
837c478bd9Sstevel@tonic-gate 			OBJ_SEC_VALUE_LEN(objp) = 0;
847c478bd9Sstevel@tonic-gate 		}
857c478bd9Sstevel@tonic-gate 		free(OBJ_SEC(objp));
867c478bd9Sstevel@tonic-gate 		OBJ_SEC(objp) = NULL;
877c478bd9Sstevel@tonic-gate 	} else {
887c478bd9Sstevel@tonic-gate 		kernel_cleanup_object_bigint_attrs(objp);
897c478bd9Sstevel@tonic-gate 	}
907c478bd9Sstevel@tonic-gate 
917c478bd9Sstevel@tonic-gate 	/*
927c478bd9Sstevel@tonic-gate 	 * Free the storage allocated to the extra attribute list.
937c478bd9Sstevel@tonic-gate 	 */
947c478bd9Sstevel@tonic-gate 	kernel_cleanup_extra_attr(objp);
957c478bd9Sstevel@tonic-gate }
967c478bd9Sstevel@tonic-gate 
977c478bd9Sstevel@tonic-gate /*
987c478bd9Sstevel@tonic-gate  * Create a new object. Copy the attributes that can be modified
997c478bd9Sstevel@tonic-gate  * (in the boolean attribute mask field and extra attribute list)
1007c478bd9Sstevel@tonic-gate  * from the old object to the new object.
1017c478bd9Sstevel@tonic-gate  *
1027c478bd9Sstevel@tonic-gate  * The caller of this function holds the lock on the old object.
1037c478bd9Sstevel@tonic-gate  */
1047c478bd9Sstevel@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)1057c478bd9Sstevel@tonic-gate kernel_copy_object(kernel_object_t *old_object, kernel_object_t **new_object,
1067c478bd9Sstevel@tonic-gate     boolean_t copy_everything, kernel_session_t *sp)
1077c478bd9Sstevel@tonic-gate {
1087c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1097c478bd9Sstevel@tonic-gate 	kernel_object_t *new_objp = NULL;
1107c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE_INFO_PTR attrp;
1117c478bd9Sstevel@tonic-gate 
1127c478bd9Sstevel@tonic-gate 	/* Allocate new object. */
1137c478bd9Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (kernel_object_t));
1147c478bd9Sstevel@tonic-gate 	if (new_objp == NULL)
1157c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 	new_objp->class = old_object->class;
1187c478bd9Sstevel@tonic-gate 	new_objp->bool_attr_mask = old_object->bool_attr_mask;
1197c478bd9Sstevel@tonic-gate 
1207c478bd9Sstevel@tonic-gate 	attrp = old_object->extra_attrlistp;
1217c478bd9Sstevel@tonic-gate 	while (attrp) {
1227c478bd9Sstevel@tonic-gate 		/*
1237c478bd9Sstevel@tonic-gate 		 * Copy the attribute_info struct from the old
1247c478bd9Sstevel@tonic-gate 		 * object to a new attribute_info struct, and add
1257c478bd9Sstevel@tonic-gate 		 * that new struct to the extra attribute list
1267c478bd9Sstevel@tonic-gate 		 * of the new object.
1277c478bd9Sstevel@tonic-gate 		 */
1287c478bd9Sstevel@tonic-gate 		rv = kernel_copy_extra_attr(attrp, new_objp);
1297c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1307c478bd9Sstevel@tonic-gate 			kernel_cleanup_extra_attr(new_objp);
1317c478bd9Sstevel@tonic-gate 			free(new_objp);
1327c478bd9Sstevel@tonic-gate 			return (rv);
1337c478bd9Sstevel@tonic-gate 		}
1347c478bd9Sstevel@tonic-gate 		attrp = attrp->next;
1357c478bd9Sstevel@tonic-gate 	}
1367c478bd9Sstevel@tonic-gate 
1377c478bd9Sstevel@tonic-gate 	*new_object = new_objp;
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	if (!copy_everything) {
1407c478bd9Sstevel@tonic-gate 		/* done with copying all information that can be modified */
1417c478bd9Sstevel@tonic-gate 		return (CKR_OK);
1427c478bd9Sstevel@tonic-gate 	}
1437c478bd9Sstevel@tonic-gate 
1447c478bd9Sstevel@tonic-gate 	/*
1457c478bd9Sstevel@tonic-gate 	 * Copy the rest of the object.
1467c478bd9Sstevel@tonic-gate 	 * Certain fields that are not appropriate for coping will be
1477c478bd9Sstevel@tonic-gate 	 * initialized.
1487c478bd9Sstevel@tonic-gate 	 */
1497c478bd9Sstevel@tonic-gate 	new_objp->key_type = old_object->key_type;
1507c478bd9Sstevel@tonic-gate 	new_objp->magic_marker = old_object->magic_marker;
1517c478bd9Sstevel@tonic-gate 	new_objp->mechanism = old_object->mechanism;
1527c478bd9Sstevel@tonic-gate 	new_objp->session_handle = (CK_SESSION_HANDLE)sp;
1537c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&(new_objp->object_mutex), NULL);
1547c478bd9Sstevel@tonic-gate 	/* copy key related information */
1557c478bd9Sstevel@tonic-gate 	switch (new_objp->class) {
1567c478bd9Sstevel@tonic-gate 		case CKO_PUBLIC_KEY:
1577c478bd9Sstevel@tonic-gate 			rv = kernel_copy_public_key_attr(OBJ_PUB(old_object),
1587c478bd9Sstevel@tonic-gate 			    &(OBJ_PUB(new_objp)), new_objp->key_type);
1597c478bd9Sstevel@tonic-gate 			break;
1607c478bd9Sstevel@tonic-gate 		case CKO_PRIVATE_KEY:
1617c478bd9Sstevel@tonic-gate 			rv = kernel_copy_private_key_attr(OBJ_PRI(old_object),
1627c478bd9Sstevel@tonic-gate 			    &(OBJ_PRI(new_objp)), new_objp->key_type);
1637c478bd9Sstevel@tonic-gate 			break;
1647c478bd9Sstevel@tonic-gate 		case CKO_SECRET_KEY:
1657c478bd9Sstevel@tonic-gate 			rv = kernel_copy_secret_key_attr(OBJ_SEC(old_object),
1667c478bd9Sstevel@tonic-gate 			    &(OBJ_SEC(new_objp)));
1677c478bd9Sstevel@tonic-gate 			break;
1687c478bd9Sstevel@tonic-gate 		default:
1697c478bd9Sstevel@tonic-gate 			/* should never be this case */
1707c478bd9Sstevel@tonic-gate 			break;
1717c478bd9Sstevel@tonic-gate 	}
1727c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1737c478bd9Sstevel@tonic-gate 		/*
1747c478bd9Sstevel@tonic-gate 		 * don't need to cleanup the memory from failure of copying
1757c478bd9Sstevel@tonic-gate 		 * any key related stuff.  Each individual function for
1767c478bd9Sstevel@tonic-gate 		 * copying key attr will free the memory if it fails
1777c478bd9Sstevel@tonic-gate 		 */
1787c478bd9Sstevel@tonic-gate 		kernel_cleanup_extra_attr(new_objp);
1797c478bd9Sstevel@tonic-gate 		free(new_objp);
1807c478bd9Sstevel@tonic-gate 	}
1817c478bd9Sstevel@tonic-gate 	return (rv);
1827c478bd9Sstevel@tonic-gate }
1837c478bd9Sstevel@tonic-gate 
1847c478bd9Sstevel@tonic-gate /*
1857c478bd9Sstevel@tonic-gate  * Copy the attributes (in the boolean attribute mask field and
1867c478bd9Sstevel@tonic-gate  * extra attribute list) from the new object back to the original
1877c478bd9Sstevel@tonic-gate  * object. Also, clean up and release all the storage in the extra
1887c478bd9Sstevel@tonic-gate  * attribute list of the original object.
1897c478bd9Sstevel@tonic-gate  *
1907c478bd9Sstevel@tonic-gate  * The caller of this function holds the lock on the old object.
1917c478bd9Sstevel@tonic-gate  */
1927c478bd9Sstevel@tonic-gate void
kernel_merge_object(kernel_object_t * old_object,kernel_object_t * new_object)1937c478bd9Sstevel@tonic-gate kernel_merge_object(kernel_object_t *old_object, kernel_object_t *new_object)
1947c478bd9Sstevel@tonic-gate {
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	old_object->bool_attr_mask = new_object->bool_attr_mask;
1977c478bd9Sstevel@tonic-gate 	kernel_cleanup_extra_attr(old_object);
1987c478bd9Sstevel@tonic-gate 	old_object->extra_attrlistp = new_object->extra_attrlistp;
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate }
2017c478bd9Sstevel@tonic-gate 
2027c478bd9Sstevel@tonic-gate /*
2037c478bd9Sstevel@tonic-gate  * Create a new object struct.  If it is a session object, add the object to
2047c478bd9Sstevel@tonic-gate  * the session's object list.  If it is a token object, add it to the slot's
2057c478bd9Sstevel@tonic-gate  * token object list.  The caller does not hold the slot lock.
2067c478bd9Sstevel@tonic-gate  */
2077c478bd9Sstevel@tonic-gate CK_RV
kernel_add_object(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_ULONG * objecthandle_p,kernel_session_t * sp)2087c478bd9Sstevel@tonic-gate kernel_add_object(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
209*a8793c76SJason King     CK_ULONG *objecthandle_p, kernel_session_t *sp)
2107c478bd9Sstevel@tonic-gate {
2117c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
2127c478bd9Sstevel@tonic-gate 	kernel_object_t *new_objp = NULL;
2137c478bd9Sstevel@tonic-gate 	kernel_slot_t	*pslot;
2147c478bd9Sstevel@tonic-gate 	crypto_object_create_t	objc;
2157c478bd9Sstevel@tonic-gate 	CK_BBOOL is_pri_obj;
2167c478bd9Sstevel@tonic-gate 	CK_BBOOL is_token_obj = B_FALSE;
2177c478bd9Sstevel@tonic-gate 	int r;
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (kernel_object_t));
2207c478bd9Sstevel@tonic-gate 	if (new_objp == NULL) {
2217c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
2227c478bd9Sstevel@tonic-gate 		goto fail_cleanup;
2237c478bd9Sstevel@tonic-gate 	}
2247c478bd9Sstevel@tonic-gate 
2257c478bd9Sstevel@tonic-gate 	new_objp->extra_attrlistp = NULL;
2267c478bd9Sstevel@tonic-gate 	new_objp->is_lib_obj = B_TRUE;
2277c478bd9Sstevel@tonic-gate 
2287c478bd9Sstevel@tonic-gate 	/*
2297c478bd9Sstevel@tonic-gate 	 * If the HW provider supports object creation, create the object
2307c478bd9Sstevel@tonic-gate 	 * in the HW provider by calling the CRYPTO_OBJECT_CREATE ioctl.
2317c478bd9Sstevel@tonic-gate 	 * Otherwise, create the object in the library.
2327c478bd9Sstevel@tonic-gate 	 */
2337c478bd9Sstevel@tonic-gate 	pslot = slot_table[sp->ses_slotid];
2347c478bd9Sstevel@tonic-gate 	if (pslot->sl_func_list.fl_object_create) {
2357c478bd9Sstevel@tonic-gate 		new_objp->is_lib_obj = B_FALSE;
2367c478bd9Sstevel@tonic-gate 		objc.oc_session = sp->k_session;
2377c478bd9Sstevel@tonic-gate 		objc.oc_count = ulCount;
2387c478bd9Sstevel@tonic-gate 		rv = process_object_attributes(pTemplate, ulCount,
2397c478bd9Sstevel@tonic-gate 		    &objc.oc_attributes, &is_token_obj);
2407c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
2417c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
2427c478bd9Sstevel@tonic-gate 		}
2437c478bd9Sstevel@tonic-gate 
2447c478bd9Sstevel@tonic-gate 		/* Cannot create a token object with a READ-ONLY session */
2457c478bd9Sstevel@tonic-gate 		if (is_token_obj && sp->ses_RO) {
2467c478bd9Sstevel@tonic-gate 			free_object_attributes(objc.oc_attributes, ulCount);
2477c478bd9Sstevel@tonic-gate 			rv = CKR_SESSION_READ_ONLY;
2487c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
2497c478bd9Sstevel@tonic-gate 		}
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_CREATE,
2527c478bd9Sstevel@tonic-gate 		    &objc)) < 0) {
2537c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
2547c478bd9Sstevel@tonic-gate 				break;
2557c478bd9Sstevel@tonic-gate 		}
2567c478bd9Sstevel@tonic-gate 		if (r < 0) {
2577c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
2587c478bd9Sstevel@tonic-gate 		} else {
2597c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(objc.oc_return_value);
2607c478bd9Sstevel@tonic-gate 		}
2617c478bd9Sstevel@tonic-gate 
2627c478bd9Sstevel@tonic-gate 		free_object_attributes(objc.oc_attributes, ulCount);
2637c478bd9Sstevel@tonic-gate 
2647c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
2657c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
2667c478bd9Sstevel@tonic-gate 		}
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 		/* Get the CKA_PRIVATE value of this object. */
2697c478bd9Sstevel@tonic-gate 		new_objp->k_handle = objc.oc_handle;
2707c478bd9Sstevel@tonic-gate 		rv = get_cka_private_value(sp, new_objp->k_handle,
2717c478bd9Sstevel@tonic-gate 		    &is_pri_obj);
2727c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
2737c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
2747c478bd9Sstevel@tonic-gate 		}
2757c478bd9Sstevel@tonic-gate 
2767c478bd9Sstevel@tonic-gate 		/* Set the PRIVATE_BOOL_ON and TOKEN_BOOL_ON attributes */
2777c478bd9Sstevel@tonic-gate 		if (is_pri_obj)
2787c478bd9Sstevel@tonic-gate 			new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
2797c478bd9Sstevel@tonic-gate 		else
2807c478bd9Sstevel@tonic-gate 			new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
2817c478bd9Sstevel@tonic-gate 
2827c478bd9Sstevel@tonic-gate 		if (is_token_obj)
2837c478bd9Sstevel@tonic-gate 			new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
2847c478bd9Sstevel@tonic-gate 		else
2857c478bd9Sstevel@tonic-gate 			new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
2867c478bd9Sstevel@tonic-gate 
2877c478bd9Sstevel@tonic-gate 	} else {
2887c478bd9Sstevel@tonic-gate 		/*
2897c478bd9Sstevel@tonic-gate 		 * Create the object in the library.
2907c478bd9Sstevel@tonic-gate 		 * Validate attribute template and fill in the attributes
2917c478bd9Sstevel@tonic-gate 		 * in the kernel_object_t.
2927c478bd9Sstevel@tonic-gate 		 */
293034448feSmcpowers 		rv = kernel_build_object(pTemplate, ulCount, new_objp, sp,
294034448feSmcpowers 		    KERNEL_CREATE_OBJ);
2957c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
2967c478bd9Sstevel@tonic-gate 			goto fail_cleanup;
2977c478bd9Sstevel@tonic-gate 		}
2987c478bd9Sstevel@tonic-gate 	}
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	/* Initialize the rest of stuffs in kernel_object_t. */
3017c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
3027c478bd9Sstevel@tonic-gate 	new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
3037c478bd9Sstevel@tonic-gate 	new_objp->session_handle = (CK_SESSION_HANDLE)sp;
3047c478bd9Sstevel@tonic-gate 
3057c478bd9Sstevel@tonic-gate 	if (is_token_obj) {
3067c478bd9Sstevel@tonic-gate 		/* Add the new object to the slot's token object list. */
3077c478bd9Sstevel@tonic-gate 		pslot = slot_table[sp->ses_slotid];
3087c478bd9Sstevel@tonic-gate 		kernel_add_token_object_to_slot(new_objp, pslot);
3097c478bd9Sstevel@tonic-gate 	} else {
3107c478bd9Sstevel@tonic-gate 		/* Add the new object to the session's object list. */
3117c478bd9Sstevel@tonic-gate 		kernel_add_object_to_session(new_objp, sp);
3127c478bd9Sstevel@tonic-gate 	}
3137c478bd9Sstevel@tonic-gate 
3147c478bd9Sstevel@tonic-gate 	/* Type casting the address of an object struct to an object handle. */
31501223cbaSmcpowers 	*objecthandle_p = (CK_ULONG)new_objp;
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	return (CKR_OK);
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate fail_cleanup:
3207c478bd9Sstevel@tonic-gate 	if (new_objp) {
3217c478bd9Sstevel@tonic-gate 		/*
3227c478bd9Sstevel@tonic-gate 		 * If the object is created in the HW provider, the storage
3237c478bd9Sstevel@tonic-gate 		 * allocated for the ioctl call is always cleaned up after
3247c478bd9Sstevel@tonic-gate 		 * the call.  If the object is created in the library,
3257c478bd9Sstevel@tonic-gate 		 * the storage allocated inside of this object should
3267c478bd9Sstevel@tonic-gate 		 * have been cleaned up in the kernel_build_object()
3277c478bd9Sstevel@tonic-gate 		 * after an error occurred. Therefore, we can safely
3287c478bd9Sstevel@tonic-gate 		 * free the object.
3297c478bd9Sstevel@tonic-gate 		 */
3307c478bd9Sstevel@tonic-gate 		free(new_objp);
3317c478bd9Sstevel@tonic-gate 	}
3327c478bd9Sstevel@tonic-gate 
3337c478bd9Sstevel@tonic-gate 	return (rv);
3347c478bd9Sstevel@tonic-gate }
3357c478bd9Sstevel@tonic-gate 
3367c478bd9Sstevel@tonic-gate /*
3377c478bd9Sstevel@tonic-gate  * Remove an object from the session's object list.
3387c478bd9Sstevel@tonic-gate  *
3397c478bd9Sstevel@tonic-gate  * The caller of this function holds the session lock.
3407c478bd9Sstevel@tonic-gate  */
34101223cbaSmcpowers CK_RV
kernel_remove_object_from_session(kernel_object_t * objp,kernel_session_t * sp)3427c478bd9Sstevel@tonic-gate kernel_remove_object_from_session(kernel_object_t *objp, kernel_session_t *sp)
3437c478bd9Sstevel@tonic-gate {
34401223cbaSmcpowers 	kernel_object_t *tmp_objp;
34501223cbaSmcpowers 	boolean_t found = B_FALSE;
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 	/*
3487c478bd9Sstevel@tonic-gate 	 * Remove the object from the session's object list.
3497c478bd9Sstevel@tonic-gate 	 */
35001223cbaSmcpowers 	if ((sp == NULL) ||
35101223cbaSmcpowers 	    (sp->magic_marker != KERNELTOKEN_SESSION_MAGIC)) {
35201223cbaSmcpowers 		return (CKR_SESSION_HANDLE_INVALID);
35301223cbaSmcpowers 	}
35401223cbaSmcpowers 
35501223cbaSmcpowers 	if ((sp->object_list == NULL) || (objp == NULL) ||
35601223cbaSmcpowers 	    (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC)) {
35701223cbaSmcpowers 		return (CKR_OBJECT_HANDLE_INVALID);
35801223cbaSmcpowers 	}
35901223cbaSmcpowers 
36001223cbaSmcpowers 	tmp_objp = sp->object_list;
36101223cbaSmcpowers 	while (tmp_objp) {
36201223cbaSmcpowers 		if (tmp_objp == objp) {
36301223cbaSmcpowers 			found = B_TRUE;
36401223cbaSmcpowers 			break;
36501223cbaSmcpowers 		}
36601223cbaSmcpowers 		tmp_objp = tmp_objp->next;
36701223cbaSmcpowers 	}
36801223cbaSmcpowers 	if (!found)
36901223cbaSmcpowers 		return (CKR_OBJECT_HANDLE_INVALID);
37001223cbaSmcpowers 
3717c478bd9Sstevel@tonic-gate 	if (sp->object_list == objp) {
3727c478bd9Sstevel@tonic-gate 		/* Object is the first one in the list. */
3737c478bd9Sstevel@tonic-gate 		if (objp->next) {
3747c478bd9Sstevel@tonic-gate 			sp->object_list = objp->next;
3757c478bd9Sstevel@tonic-gate 			objp->next->prev = NULL;
3767c478bd9Sstevel@tonic-gate 		} else {
3777c478bd9Sstevel@tonic-gate 			/* Object is the only one in the list. */
3787c478bd9Sstevel@tonic-gate 			sp->object_list = NULL;
3797c478bd9Sstevel@tonic-gate 		}
3807c478bd9Sstevel@tonic-gate 	} else {
3817c478bd9Sstevel@tonic-gate 		/* Object is not the first one in the list. */
3827c478bd9Sstevel@tonic-gate 		if (objp->next) {
3837c478bd9Sstevel@tonic-gate 			/* Object is in the middle of the list. */
3847c478bd9Sstevel@tonic-gate 			objp->prev->next = objp->next;
3857c478bd9Sstevel@tonic-gate 			objp->next->prev = objp->prev;
3867c478bd9Sstevel@tonic-gate 		} else {
3877c478bd9Sstevel@tonic-gate 			/* Object is the last one in the list. */
3887c478bd9Sstevel@tonic-gate 			objp->prev->next = NULL;
3897c478bd9Sstevel@tonic-gate 		}
3907c478bd9Sstevel@tonic-gate 	}
39101223cbaSmcpowers 	return (CKR_OK);
3927c478bd9Sstevel@tonic-gate }
3937c478bd9Sstevel@tonic-gate 
39401223cbaSmcpowers static void
kernel_delete_object_cleanup(kernel_object_t * objp,boolean_t wrapper_only)3951f49a79aSZdenek Kotala kernel_delete_object_cleanup(kernel_object_t *objp, boolean_t wrapper_only)
39601223cbaSmcpowers {
39701223cbaSmcpowers 	/* Acquire the lock on the object. */
39801223cbaSmcpowers 	(void) pthread_mutex_lock(&objp->object_mutex);
39901223cbaSmcpowers 
40001223cbaSmcpowers 	/*
40101223cbaSmcpowers 	 * Make sure another thread hasn't freed the object.
40201223cbaSmcpowers 	 */
40301223cbaSmcpowers 	if (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC) {
40401223cbaSmcpowers 		(void) pthread_mutex_unlock(&objp->object_mutex);
40501223cbaSmcpowers 		return;
40601223cbaSmcpowers 	}
40701223cbaSmcpowers 
40801223cbaSmcpowers 	/*
40901223cbaSmcpowers 	 * The deletion of an object must be blocked when the object
41001223cbaSmcpowers 	 * reference count is not zero. This means if any object related
41101223cbaSmcpowers 	 * operation starts prior to the delete object operation gets in,
41201223cbaSmcpowers 	 * the object deleting thread must wait for the non-deleting
41301223cbaSmcpowers 	 * operation to be completed before it can proceed the delete
41401223cbaSmcpowers 	 * operation.
4151f49a79aSZdenek Kotala 	 *
4161f49a79aSZdenek Kotala 	 * Unless we are being forced to shut everything down, this only
4171f49a79aSZdenek Kotala 	 * happens if the library's _fini() is running not if someone
4181f49a79aSZdenek Kotala 	 * explicitly called C_Finalize().
41901223cbaSmcpowers 	 */
4201f49a79aSZdenek Kotala 	if (wrapper_only) {
4211f49a79aSZdenek Kotala 		objp->obj_refcnt = 0;
4221f49a79aSZdenek Kotala 	}
4231f49a79aSZdenek Kotala 
42401223cbaSmcpowers 	while (objp->obj_refcnt != 0) {
42501223cbaSmcpowers 		/*
42601223cbaSmcpowers 		 * We set the OBJECT_REFCNT_WAITING flag before we put
42701223cbaSmcpowers 		 * this deleting thread in a wait state, so other non-deleting
42801223cbaSmcpowers 		 * operation thread will signal to wake it up only when
42901223cbaSmcpowers 		 * the object reference count becomes zero and this flag
43001223cbaSmcpowers 		 * is set.
43101223cbaSmcpowers 		 */
43201223cbaSmcpowers 		objp->obj_delete_sync |= OBJECT_REFCNT_WAITING;
43301223cbaSmcpowers 		(void) pthread_cond_wait(&objp->obj_free_cond,
434c2e31228SViswanathan Kannappan 		    &objp->object_mutex);
43501223cbaSmcpowers 	}
43601223cbaSmcpowers 
43701223cbaSmcpowers 	objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING;
43801223cbaSmcpowers 
43901223cbaSmcpowers 	/* Mark object as no longer valid. */
44001223cbaSmcpowers 	objp->magic_marker = 0;
44101223cbaSmcpowers 
44201223cbaSmcpowers 	(void) pthread_cond_destroy(&objp->obj_free_cond);
44301223cbaSmcpowers }
4447c478bd9Sstevel@tonic-gate 
4457c478bd9Sstevel@tonic-gate /*
4467c478bd9Sstevel@tonic-gate  * Delete a session object:
4477c478bd9Sstevel@tonic-gate  * - Remove the object from the session's object list.
4487c478bd9Sstevel@tonic-gate  * - Release the storage allocated to the object.
4497c478bd9Sstevel@tonic-gate  *
4507c478bd9Sstevel@tonic-gate  * The boolean argument ses_lock_held is used to indicate that whether
4517c478bd9Sstevel@tonic-gate  * the caller holds the session lock or not.
4527c478bd9Sstevel@tonic-gate  * - When called by kernel_delete_all_objects_in_session() or
4537c478bd9Sstevel@tonic-gate  *   kernel_delete_pri_objects_in_slot() -- ses_lock_held = TRUE.
4547c478bd9Sstevel@tonic-gate  *
4557c478bd9Sstevel@tonic-gate  * The boolean argument wrapper_only is used to indicate that whether
4567c478bd9Sstevel@tonic-gate  * the caller only wants to clean up the object wrapper from the library and
4577c478bd9Sstevel@tonic-gate  * needs not to make an ioctl call.
4587c478bd9Sstevel@tonic-gate  * - This argument only applies to the object created in the provider level.
4597c478bd9Sstevel@tonic-gate  * - When called by kernel_cleanup_pri_objects_in_slot(), wrapper_only is TRUE.
4607c478bd9Sstevel@tonic-gate  * - When called by C_DestroyObject(), wrapper_only is FALSE.
4617c478bd9Sstevel@tonic-gate  * - When called by kernel_delete_all_objects_in_session(), the value of
4627c478bd9Sstevel@tonic-gate  *   wrapper_only depends on its caller.
4637c478bd9Sstevel@tonic-gate  */
4647c478bd9Sstevel@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)4657c478bd9Sstevel@tonic-gate kernel_delete_session_object(kernel_session_t *sp, kernel_object_t *objp,
4667c478bd9Sstevel@tonic-gate     boolean_t ses_lock_held, boolean_t wrapper_only)
4677c478bd9Sstevel@tonic-gate {
4687c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
4697c478bd9Sstevel@tonic-gate 	crypto_object_destroy_t	obj_destroy;
4707c478bd9Sstevel@tonic-gate 
4717c478bd9Sstevel@tonic-gate 	/*
4727c478bd9Sstevel@tonic-gate 	 * Check to see if the caller holds the lock on the session.
4737c478bd9Sstevel@tonic-gate 	 * If not, we need to acquire that lock in order to proceed.
4747c478bd9Sstevel@tonic-gate 	 */
4757c478bd9Sstevel@tonic-gate 	if (!ses_lock_held) {
4767c478bd9Sstevel@tonic-gate 		/* Acquire the session lock. */
4777c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&sp->session_mutex);
4787c478bd9Sstevel@tonic-gate 	}
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	/* Remove the object from the session's object list first. */
48101223cbaSmcpowers 	rv = kernel_remove_object_from_session(objp, sp);
4827c478bd9Sstevel@tonic-gate 	if (!ses_lock_held) {
4837c478bd9Sstevel@tonic-gate 		/*
4847c478bd9Sstevel@tonic-gate 		 * If the session lock is obtained by this function,
4857c478bd9Sstevel@tonic-gate 		 * then release that lock after removing the object
4867c478bd9Sstevel@tonic-gate 		 * from session's object list.
4877c478bd9Sstevel@tonic-gate 		 * We want the releasing of the object storage to
4887c478bd9Sstevel@tonic-gate 		 * be done without holding the session lock.
4897c478bd9Sstevel@tonic-gate 		 */
4907c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&sp->session_mutex);
4917c478bd9Sstevel@tonic-gate 	}
4927c478bd9Sstevel@tonic-gate 
49301223cbaSmcpowers 	if (rv != CKR_OK)
49401223cbaSmcpowers 		return (rv);
4957c478bd9Sstevel@tonic-gate 
4961f49a79aSZdenek Kotala 	kernel_delete_object_cleanup(objp, wrapper_only);
4977c478bd9Sstevel@tonic-gate 
4987c478bd9Sstevel@tonic-gate 	/* Destroy the object. */
4997c478bd9Sstevel@tonic-gate 	if (objp->is_lib_obj) {
5007c478bd9Sstevel@tonic-gate 		/*
5017c478bd9Sstevel@tonic-gate 		 * If this object is created in the library, cleanup the
5027c478bd9Sstevel@tonic-gate 		 * contents of this object such as free all the storage
5037c478bd9Sstevel@tonic-gate 		 * allocated for this object.
5047c478bd9Sstevel@tonic-gate 		 */
5057c478bd9Sstevel@tonic-gate 		kernel_cleanup_object(objp);
5067c478bd9Sstevel@tonic-gate 	} else {
5077c478bd9Sstevel@tonic-gate 		/*
5087c478bd9Sstevel@tonic-gate 		 * This object is created in the HW provider. If wrapper_only
5097c478bd9Sstevel@tonic-gate 		 * is FALSE, make an ioctl call to destroy it in kernel.
5107c478bd9Sstevel@tonic-gate 		 */
5117c478bd9Sstevel@tonic-gate 		if (!wrapper_only) {
5127c478bd9Sstevel@tonic-gate 			obj_destroy.od_session = sp->k_session;
5137c478bd9Sstevel@tonic-gate 			obj_destroy.od_handle = objp->k_handle;
5147c478bd9Sstevel@tonic-gate 
51501223cbaSmcpowers 			while (ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY,
51601223cbaSmcpowers 			    &obj_destroy) < 0) {
5177c478bd9Sstevel@tonic-gate 				if (errno != EINTR)
5187c478bd9Sstevel@tonic-gate 					break;
5197c478bd9Sstevel@tonic-gate 			}
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 			/*
5227c478bd9Sstevel@tonic-gate 			 * Ignore ioctl return codes for a session object.
5237c478bd9Sstevel@tonic-gate 			 * If the kernel can not delete a session object, it
5247c478bd9Sstevel@tonic-gate 			 * is likely caused by the HW provider. There's not
5257c478bd9Sstevel@tonic-gate 			 * much that can be done.  The library will still
5267c478bd9Sstevel@tonic-gate 			 * cleanup the object wrapper in the library. The HW
5277c478bd9Sstevel@tonic-gate 			 * provider will destroy all session objects when
5287c478bd9Sstevel@tonic-gate 			 * the application exits.
5297c478bd9Sstevel@tonic-gate 			 */
5307c478bd9Sstevel@tonic-gate 		}
5317c478bd9Sstevel@tonic-gate 	}
5327c478bd9Sstevel@tonic-gate 
53301223cbaSmcpowers 	/* Reset OBJECT_IS_DELETING flag. */
53401223cbaSmcpowers 	objp->obj_delete_sync &= ~OBJECT_IS_DELETING;
5357c478bd9Sstevel@tonic-gate 
53601223cbaSmcpowers 	(void) pthread_mutex_unlock(&objp->object_mutex);
53701223cbaSmcpowers 	/* Destroy the object lock */
53801223cbaSmcpowers 	(void) pthread_mutex_destroy(&objp->object_mutex);
53901223cbaSmcpowers 	/* Free the object itself */
54001223cbaSmcpowers 	kernel_object_delay_free(objp);
5417c478bd9Sstevel@tonic-gate 
54201223cbaSmcpowers 	return (CKR_OK);
54301223cbaSmcpowers }
5447c478bd9Sstevel@tonic-gate 
5457c478bd9Sstevel@tonic-gate /*
5467c478bd9Sstevel@tonic-gate  * Delete all the objects in a session. The caller holds the lock
5477c478bd9Sstevel@tonic-gate  * on the session.   If the wrapper_only argument is TRUE, the caller only
5487c478bd9Sstevel@tonic-gate  * want to clean up object wrappers in the library.
5497c478bd9Sstevel@tonic-gate  */
5507c478bd9Sstevel@tonic-gate void
kernel_delete_all_objects_in_session(kernel_session_t * sp,boolean_t wrapper_only)5517c478bd9Sstevel@tonic-gate kernel_delete_all_objects_in_session(kernel_session_t *sp,
5527c478bd9Sstevel@tonic-gate     boolean_t wrapper_only)
5537c478bd9Sstevel@tonic-gate {
5547c478bd9Sstevel@tonic-gate 	kernel_object_t *objp = sp->object_list;
5557c478bd9Sstevel@tonic-gate 	kernel_object_t *objp1;
5567c478bd9Sstevel@tonic-gate 
5577c478bd9Sstevel@tonic-gate 	/* Delete all the objects in the session. */
5587c478bd9Sstevel@tonic-gate 	while (objp) {
5597c478bd9Sstevel@tonic-gate 		objp1 = objp->next;
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 		/*
5627c478bd9Sstevel@tonic-gate 		 * Delete an session object by calling
5637c478bd9Sstevel@tonic-gate 		 * kernel_delete_session_object():
5647c478bd9Sstevel@tonic-gate 		 * - The 3rd TRUE boolean argument indicates that the caller
5657c478bd9Sstevel@tonic-gate 		 *   holds the session lock.
5667c478bd9Sstevel@tonic-gate 		 * - The 4th boolean argument indicates whether we only want
5677c478bd9Sstevel@tonic-gate 		 *   clean up object wrappers in the library.
5687c478bd9Sstevel@tonic-gate 		 */
5697c478bd9Sstevel@tonic-gate 		(void) kernel_delete_session_object(sp, objp, B_TRUE,
5707c478bd9Sstevel@tonic-gate 		    wrapper_only);
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 		objp = objp1;
5737c478bd9Sstevel@tonic-gate 	}
5747c478bd9Sstevel@tonic-gate }
5757c478bd9Sstevel@tonic-gate 
5767c478bd9Sstevel@tonic-gate static CK_RV
add_to_search_result(kernel_object_t * obj,find_context_t * fcontext,CK_ULONG * num_result_alloc)5777c478bd9Sstevel@tonic-gate add_to_search_result(kernel_object_t *obj, find_context_t *fcontext,
5787c478bd9Sstevel@tonic-gate     CK_ULONG *num_result_alloc)
5797c478bd9Sstevel@tonic-gate {
5807c478bd9Sstevel@tonic-gate 	/*
5817c478bd9Sstevel@tonic-gate 	 * allocate space for storing results if the currently
5827c478bd9Sstevel@tonic-gate 	 * allocated space is not enough
5837c478bd9Sstevel@tonic-gate 	 */
5847c478bd9Sstevel@tonic-gate 	if (*num_result_alloc <= fcontext->num_results) {
5857c478bd9Sstevel@tonic-gate 		fcontext->objs_found = realloc(fcontext->objs_found,
5867c478bd9Sstevel@tonic-gate 		    sizeof (kernel_object_t *) * (*num_result_alloc + BUFSIZ));
5877c478bd9Sstevel@tonic-gate 		if (fcontext->objs_found == NULL) {
5887c478bd9Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
5897c478bd9Sstevel@tonic-gate 		}
5907c478bd9Sstevel@tonic-gate 		*num_result_alloc += BUFSIZ;
5917c478bd9Sstevel@tonic-gate 	}
5927c478bd9Sstevel@tonic-gate 
5937c478bd9Sstevel@tonic-gate 	(fcontext->objs_found)[(fcontext->num_results)++] = obj;
5947c478bd9Sstevel@tonic-gate 	return (CKR_OK);
5957c478bd9Sstevel@tonic-gate }
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate static CK_RV
search_for_objects(kernel_session_t * sp,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,find_context_t * fcontext)5987c478bd9Sstevel@tonic-gate search_for_objects(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
5997c478bd9Sstevel@tonic-gate     CK_ULONG ulCount, find_context_t *fcontext)
6007c478bd9Sstevel@tonic-gate {
6017c478bd9Sstevel@tonic-gate 	kernel_session_t *session_p;
6027c478bd9Sstevel@tonic-gate 	kernel_object_t *obj;
603c2e31228SViswanathan Kannappan 	CK_OBJECT_CLASS pclasses[6]; /* classes attrs possibly exist */
6047c478bd9Sstevel@tonic-gate 	CK_ULONG num_pclasses;	/* number of possible classes */
6057c478bd9Sstevel@tonic-gate 	CK_ULONG num_result_alloc = 0; /* spaces allocated for results */
6067c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6077c478bd9Sstevel@tonic-gate 	kernel_slot_t	*pslot;
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 	if (ulCount > 0) {
6107c478bd9Sstevel@tonic-gate 		/* there are some search requirement */
6117c478bd9Sstevel@tonic-gate 		kernel_process_find_attr(pclasses, &num_pclasses,
6127c478bd9Sstevel@tonic-gate 		    pTemplate, ulCount);
6137c478bd9Sstevel@tonic-gate 	}
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	/* Acquire the slot lock */
6167c478bd9Sstevel@tonic-gate 	pslot = slot_table[sp->ses_slotid];
6177c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&pslot->sl_mutex);
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 	/*
6207c478bd9Sstevel@tonic-gate 	 * Go through all objects in each session.
6217c478bd9Sstevel@tonic-gate 	 * Acquire individual session lock for the session
6227c478bd9Sstevel@tonic-gate 	 * we are searching.
6237c478bd9Sstevel@tonic-gate 	 */
6247c478bd9Sstevel@tonic-gate 	session_p = pslot->sl_sess_list;
6257c478bd9Sstevel@tonic-gate 	while (session_p) {
6267c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
6277c478bd9Sstevel@tonic-gate 		obj = session_p->object_list;
6287c478bd9Sstevel@tonic-gate 		while (obj) {
6297c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
6307c478bd9Sstevel@tonic-gate 			if (ulCount > 0) {
6317c478bd9Sstevel@tonic-gate 				if (kernel_find_match_attrs(obj, pclasses,
6327c478bd9Sstevel@tonic-gate 				    num_pclasses, pTemplate, ulCount)) {
6337c478bd9Sstevel@tonic-gate 					rv = add_to_search_result(
6347c478bd9Sstevel@tonic-gate 					    obj, fcontext, &num_result_alloc);
6357c478bd9Sstevel@tonic-gate 				}
6367c478bd9Sstevel@tonic-gate 			} else {
6377c478bd9Sstevel@tonic-gate 				/* no search criteria, just record the object */
6387c478bd9Sstevel@tonic-gate 				rv = add_to_search_result(obj, fcontext,
6397c478bd9Sstevel@tonic-gate 				    &num_result_alloc);
6407c478bd9Sstevel@tonic-gate 			}
6417c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
6427c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
6437c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock(
6447c478bd9Sstevel@tonic-gate 				    &session_p->session_mutex);
6457c478bd9Sstevel@tonic-gate 				goto cleanup;
6467c478bd9Sstevel@tonic-gate 			}
6477c478bd9Sstevel@tonic-gate 			obj = obj->next;
6487c478bd9Sstevel@tonic-gate 		}
6497c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
6507c478bd9Sstevel@tonic-gate 		session_p = session_p->next;
6517c478bd9Sstevel@tonic-gate 	}
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate cleanup:
6547c478bd9Sstevel@tonic-gate 	/* Release the slot lock */
6557c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
6567c478bd9Sstevel@tonic-gate 	return (rv);
6577c478bd9Sstevel@tonic-gate }
6587c478bd9Sstevel@tonic-gate 
6597c478bd9Sstevel@tonic-gate /*
6607c478bd9Sstevel@tonic-gate  * Initialize the context for C_FindObjects() calls
6617c478bd9Sstevel@tonic-gate  */
6627c478bd9Sstevel@tonic-gate CK_RV
kernel_find_objects_init(kernel_session_t * sp,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)6637c478bd9Sstevel@tonic-gate kernel_find_objects_init(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
6647c478bd9Sstevel@tonic-gate     CK_ULONG ulCount)
6657c478bd9Sstevel@tonic-gate {
6667c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6677c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class; /* for kernel_validate_attr(). Value unused */
6687c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 	if (ulCount) {
6717c478bd9Sstevel@tonic-gate 		rv = kernel_validate_attr(pTemplate, ulCount, &class);
6727c478bd9Sstevel@tonic-gate 		/* Make sure all attributes in template are valid */
6737c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
6747c478bd9Sstevel@tonic-gate 			return (rv);
6757c478bd9Sstevel@tonic-gate 		}
6767c478bd9Sstevel@tonic-gate 	}
6777c478bd9Sstevel@tonic-gate 
6787c478bd9Sstevel@tonic-gate 	/* prepare the find context */
6797c478bd9Sstevel@tonic-gate 	fcontext = calloc(1, sizeof (find_context_t));
6807c478bd9Sstevel@tonic-gate 	if (fcontext == NULL) {
6817c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
6827c478bd9Sstevel@tonic-gate 	}
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	rv = search_for_objects(sp, pTemplate, ulCount, fcontext);
6857c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
6867c478bd9Sstevel@tonic-gate 		free(fcontext);
6877c478bd9Sstevel@tonic-gate 		return (rv);
6887c478bd9Sstevel@tonic-gate 	}
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 	/* store the find_context in the session */
6917c478bd9Sstevel@tonic-gate 	sp->find_objects.context = (CK_VOID_PTR)fcontext;
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	return (rv);
6947c478bd9Sstevel@tonic-gate }
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate void
kernel_find_objects_final(kernel_session_t * sp)6977c478bd9Sstevel@tonic-gate kernel_find_objects_final(kernel_session_t *sp)
6987c478bd9Sstevel@tonic-gate {
6997c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 	fcontext = sp->find_objects.context;
7027c478bd9Sstevel@tonic-gate 	sp->find_objects.context = NULL;
7037c478bd9Sstevel@tonic-gate 	sp->find_objects.flags = 0;
7047c478bd9Sstevel@tonic-gate 	if (fcontext->objs_found != NULL) {
7057c478bd9Sstevel@tonic-gate 		free(fcontext->objs_found);
7067c478bd9Sstevel@tonic-gate 	}
7077c478bd9Sstevel@tonic-gate 
7087c478bd9Sstevel@tonic-gate 	free(fcontext);
7097c478bd9Sstevel@tonic-gate }
7107c478bd9Sstevel@tonic-gate 
7117c478bd9Sstevel@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)7127c478bd9Sstevel@tonic-gate kernel_find_objects(kernel_session_t *sp, CK_OBJECT_HANDLE *obj_found,
7137c478bd9Sstevel@tonic-gate     CK_ULONG max_obj_requested, CK_ULONG *found_obj_count)
7147c478bd9Sstevel@tonic-gate {
7157c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
7167c478bd9Sstevel@tonic-gate 	CK_ULONG num_obj_found = 0;
7177c478bd9Sstevel@tonic-gate 	CK_ULONG i;
7187c478bd9Sstevel@tonic-gate 	kernel_object_t *obj;
7197c478bd9Sstevel@tonic-gate 
7207c478bd9Sstevel@tonic-gate 	fcontext = sp->find_objects.context;
7217c478bd9Sstevel@tonic-gate 
7227c478bd9Sstevel@tonic-gate 	for (i = fcontext->next_result_index;
7237c478bd9Sstevel@tonic-gate 	    ((num_obj_found < max_obj_requested) &&
7247c478bd9Sstevel@tonic-gate 	    (i < fcontext->num_results));
7257c478bd9Sstevel@tonic-gate 	    i++) {
7267c478bd9Sstevel@tonic-gate 		obj = fcontext->objs_found[i];
7277c478bd9Sstevel@tonic-gate 		if (obj != NULL) {
7287c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
7297c478bd9Sstevel@tonic-gate 			/* a sanity check to make sure the obj is still valid */
7307c478bd9Sstevel@tonic-gate 			if (obj->magic_marker == KERNELTOKEN_OBJECT_MAGIC) {
7317c478bd9Sstevel@tonic-gate 				obj_found[num_obj_found] =
7327c478bd9Sstevel@tonic-gate 				    (CK_OBJECT_HANDLE)obj;
7337c478bd9Sstevel@tonic-gate 				num_obj_found++;
7347c478bd9Sstevel@tonic-gate 			}
7357c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
7367c478bd9Sstevel@tonic-gate 		}
7377c478bd9Sstevel@tonic-gate 	}
7387c478bd9Sstevel@tonic-gate 	fcontext->next_result_index = i;
7397c478bd9Sstevel@tonic-gate 	*found_obj_count = num_obj_found;
7407c478bd9Sstevel@tonic-gate }
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate /*
7437c478bd9Sstevel@tonic-gate  * Add an token object to the token object list in slot.
7447c478bd9Sstevel@tonic-gate  *
7457c478bd9Sstevel@tonic-gate  * This function will acquire the lock on the slot, and release
7467c478bd9Sstevel@tonic-gate  * that lock after adding the object to the slot's token object list.
7477c478bd9Sstevel@tonic-gate  */
7487c478bd9Sstevel@tonic-gate void
kernel_add_token_object_to_slot(kernel_object_t * objp,kernel_slot_t * pslot)7497c478bd9Sstevel@tonic-gate kernel_add_token_object_to_slot(kernel_object_t *objp, kernel_slot_t *pslot)
7507c478bd9Sstevel@tonic-gate {
7517c478bd9Sstevel@tonic-gate 	/* Acquire the slot lock. */
7527c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&pslot->sl_mutex);
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	/* Insert the new object in front of slot's token object list. */
7557c478bd9Sstevel@tonic-gate 	if (pslot->sl_tobj_list == NULL) {
7567c478bd9Sstevel@tonic-gate 		pslot->sl_tobj_list = objp;
7577c478bd9Sstevel@tonic-gate 		objp->next = NULL;
7587c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
7597c478bd9Sstevel@tonic-gate 	} else {
7607c478bd9Sstevel@tonic-gate 		pslot->sl_tobj_list->prev = objp;
7617c478bd9Sstevel@tonic-gate 		objp->next = pslot->sl_tobj_list;
7627c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
7637c478bd9Sstevel@tonic-gate 		pslot->sl_tobj_list = objp;
7647c478bd9Sstevel@tonic-gate 	}
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	/* Release the slot lock. */
7677c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
7687c478bd9Sstevel@tonic-gate }
7697c478bd9Sstevel@tonic-gate 
7707c478bd9Sstevel@tonic-gate /*
7717c478bd9Sstevel@tonic-gate  * Remove an token object from the slot's token object list.
7727c478bd9Sstevel@tonic-gate  * This routine is called by kernel_delete_token_object().
7737c478bd9Sstevel@tonic-gate  * The caller of this function hold the slot lock.
7747c478bd9Sstevel@tonic-gate  */
7757c478bd9Sstevel@tonic-gate void
kernel_remove_token_object_from_slot(kernel_slot_t * pslot,kernel_object_t * objp)7767c478bd9Sstevel@tonic-gate kernel_remove_token_object_from_slot(kernel_slot_t *pslot,
7777c478bd9Sstevel@tonic-gate     kernel_object_t *objp)
7787c478bd9Sstevel@tonic-gate {
7797c478bd9Sstevel@tonic-gate 
7807c478bd9Sstevel@tonic-gate 	if (pslot->sl_tobj_list == objp) {
7817c478bd9Sstevel@tonic-gate 		/* Object is the first one in the list */
7827c478bd9Sstevel@tonic-gate 		if (objp->next) {
7837c478bd9Sstevel@tonic-gate 			pslot->sl_tobj_list = objp->next;
7847c478bd9Sstevel@tonic-gate 			objp->next->prev = NULL;
7857c478bd9Sstevel@tonic-gate 		} else {
7867c478bd9Sstevel@tonic-gate 			/* Object is the only one in the list. */
7877c478bd9Sstevel@tonic-gate 			pslot->sl_tobj_list = NULL;
7887c478bd9Sstevel@tonic-gate 		}
7897c478bd9Sstevel@tonic-gate 	} else {
7907c478bd9Sstevel@tonic-gate 		/* Object is not the first one in the list. */
7917c478bd9Sstevel@tonic-gate 		if (objp->next) {
7927c478bd9Sstevel@tonic-gate 			/* Object is in the middle of the list. */
7937c478bd9Sstevel@tonic-gate 			objp->prev->next = objp->next;
7947c478bd9Sstevel@tonic-gate 			objp->next->prev = objp->prev;
7957c478bd9Sstevel@tonic-gate 		} else {
7967c478bd9Sstevel@tonic-gate 			/* Object is the last one in the list. */
7977c478bd9Sstevel@tonic-gate 			objp->prev->next = NULL;
7987c478bd9Sstevel@tonic-gate 		}
7997c478bd9Sstevel@tonic-gate 	}
8007c478bd9Sstevel@tonic-gate }
8017c478bd9Sstevel@tonic-gate 
8027c478bd9Sstevel@tonic-gate /*
8037c478bd9Sstevel@tonic-gate  * Delete a token object:
8047c478bd9Sstevel@tonic-gate  * - Remove the object from the slot's token object list.
8057c478bd9Sstevel@tonic-gate  * - Release the storage allocated to the object.
8067c478bd9Sstevel@tonic-gate  *
8077c478bd9Sstevel@tonic-gate  * The boolean argument slot_lock_held is used to indicate that whether
8087c478bd9Sstevel@tonic-gate  * the caller holds the slot lock or not. When the caller does not hold
8097c478bd9Sstevel@tonic-gate  * the slot lock, this function will acquire that lock in order to proceed,
8107c478bd9Sstevel@tonic-gate  * and also release that lock before returning to caller.
8117c478bd9Sstevel@tonic-gate  *
8127c478bd9Sstevel@tonic-gate  * The boolean argument wrapper_only is used to indicate that whether
8137c478bd9Sstevel@tonic-gate  * the caller only wants to the object wrapper from library.
8147c478bd9Sstevel@tonic-gate  */
8157c478bd9Sstevel@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)8167c478bd9Sstevel@tonic-gate kernel_delete_token_object(kernel_slot_t *pslot, kernel_session_t *sp,
8177c478bd9Sstevel@tonic-gate     kernel_object_t *objp, boolean_t slot_lock_held, boolean_t wrapper_only)
8187c478bd9Sstevel@tonic-gate {
8197c478bd9Sstevel@tonic-gate 	CK_RV rv;
8207c478bd9Sstevel@tonic-gate 	crypto_object_destroy_t	obj_destroy;
8217c478bd9Sstevel@tonic-gate 	int r;
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	/*
8247c478bd9Sstevel@tonic-gate 	 * Check to see if the caller holds the lock on the slot.
8257c478bd9Sstevel@tonic-gate 	 * If not, we need to acquire that lock in order to proceed.
8267c478bd9Sstevel@tonic-gate 	 */
8277c478bd9Sstevel@tonic-gate 	if (!slot_lock_held) {
8287c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&pslot->sl_mutex);
8297c478bd9Sstevel@tonic-gate 	}
8307c478bd9Sstevel@tonic-gate 
8317c478bd9Sstevel@tonic-gate 	/* Remove the object from the slot's token object list first. */
8327c478bd9Sstevel@tonic-gate 	kernel_remove_token_object_from_slot(pslot, objp);
8337c478bd9Sstevel@tonic-gate 
8347c478bd9Sstevel@tonic-gate 	/* Release the slot lock if the call doesn't hold the lock. */
8357c478bd9Sstevel@tonic-gate 	if (!slot_lock_held) {
8367c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&pslot->sl_mutex);
8377c478bd9Sstevel@tonic-gate 	}
8387c478bd9Sstevel@tonic-gate 
8391f49a79aSZdenek Kotala 	kernel_delete_object_cleanup(objp, wrapper_only);
8407c478bd9Sstevel@tonic-gate 
8417c478bd9Sstevel@tonic-gate 	if (!wrapper_only) {
8427c478bd9Sstevel@tonic-gate 		obj_destroy.od_session = sp->k_session;
8437c478bd9Sstevel@tonic-gate 		obj_destroy.od_handle = objp->k_handle;
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY,
8467c478bd9Sstevel@tonic-gate 		    &obj_destroy)) < 0) {
8477c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
8487c478bd9Sstevel@tonic-gate 				break;
8497c478bd9Sstevel@tonic-gate 		}
8507c478bd9Sstevel@tonic-gate 		if (r < 0) {
8517c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
8527c478bd9Sstevel@tonic-gate 		} else {
8537c478bd9Sstevel@tonic-gate 			rv = crypto2pkcs11_error_number(
8547c478bd9Sstevel@tonic-gate 			    obj_destroy.od_return_value);
8557c478bd9Sstevel@tonic-gate 		}
8567c478bd9Sstevel@tonic-gate 
8577c478bd9Sstevel@tonic-gate 		/*
8587c478bd9Sstevel@tonic-gate 		 * Could not destroy an object from kernel. Write a warning
8597c478bd9Sstevel@tonic-gate 		 * in syslog, but we still clean up the object wrapper in
8607c478bd9Sstevel@tonic-gate 		 * the library.
8617c478bd9Sstevel@tonic-gate 		 */
8627c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
8637c478bd9Sstevel@tonic-gate 			cryptoerror(LOG_ERR, "pkcs11_kernel: Could not "
8647c478bd9Sstevel@tonic-gate 			    "destroy an object in kernel.");
8657c478bd9Sstevel@tonic-gate 		}
8667c478bd9Sstevel@tonic-gate 	}
8677c478bd9Sstevel@tonic-gate 
86801223cbaSmcpowers 	(void) pthread_mutex_unlock(&objp->object_mutex);
86901223cbaSmcpowers 	/* Destroy the object lock */
87001223cbaSmcpowers 	(void) pthread_mutex_destroy(&objp->object_mutex);
87101223cbaSmcpowers 	/* Free the object itself */
87201223cbaSmcpowers 	kernel_object_delay_free(objp);
8737c478bd9Sstevel@tonic-gate 
87401223cbaSmcpowers 	return (CKR_OK);
8757c478bd9Sstevel@tonic-gate }
8767c478bd9Sstevel@tonic-gate 
8777c478bd9Sstevel@tonic-gate /*
8787c478bd9Sstevel@tonic-gate  * Clean up private object wrappers in this slot. The caller holds the slot
8797c478bd9Sstevel@tonic-gate  * lock.
8807c478bd9Sstevel@tonic-gate  */
8817c478bd9Sstevel@tonic-gate void
kernel_cleanup_pri_objects_in_slot(kernel_slot_t * pslot,kernel_session_t * cur_sp)8827c478bd9Sstevel@tonic-gate kernel_cleanup_pri_objects_in_slot(kernel_slot_t *pslot,
8837c478bd9Sstevel@tonic-gate     kernel_session_t *cur_sp)
8847c478bd9Sstevel@tonic-gate {
8857c478bd9Sstevel@tonic-gate 	kernel_session_t *session_p;
8867c478bd9Sstevel@tonic-gate 	kernel_object_t *objp;
8877c478bd9Sstevel@tonic-gate 	kernel_object_t *objp1;
8887c478bd9Sstevel@tonic-gate 
8897c478bd9Sstevel@tonic-gate 	/*
8907c478bd9Sstevel@tonic-gate 	 * Delete every private token object from the slot' token object list
8917c478bd9Sstevel@tonic-gate 	 */
8927c478bd9Sstevel@tonic-gate 	objp = pslot->sl_tobj_list;
8937c478bd9Sstevel@tonic-gate 	while (objp) {
8947c478bd9Sstevel@tonic-gate 		objp1 = objp->next;
8957c478bd9Sstevel@tonic-gate 		/*
8967c478bd9Sstevel@tonic-gate 		 * The first TRUE boolean argument indicates that the caller
8977c478bd9Sstevel@tonic-gate 		 * hold the slot lock.  The second TRUE boolean argument
8987c478bd9Sstevel@tonic-gate 		 * indicates that the caller just wants to clean up the object
8997c478bd9Sstevel@tonic-gate 		 * wrapper from the library only.
9007c478bd9Sstevel@tonic-gate 		 */
9017c478bd9Sstevel@tonic-gate 		if (objp->bool_attr_mask & PRIVATE_BOOL_ON) {
9027c478bd9Sstevel@tonic-gate 			(void) kernel_delete_token_object(pslot, cur_sp, objp,
9037c478bd9Sstevel@tonic-gate 			    B_TRUE, B_TRUE);
9047c478bd9Sstevel@tonic-gate 		}
9057c478bd9Sstevel@tonic-gate 		objp = objp1;
9067c478bd9Sstevel@tonic-gate 	}
9077c478bd9Sstevel@tonic-gate 
9087c478bd9Sstevel@tonic-gate 	/*
9097c478bd9Sstevel@tonic-gate 	 * Walk through all the sessions in this slot and delete every
9107c478bd9Sstevel@tonic-gate 	 * private object.
9117c478bd9Sstevel@tonic-gate 	 */
9127c478bd9Sstevel@tonic-gate 	session_p = pslot->sl_sess_list;
9137c478bd9Sstevel@tonic-gate 	while (session_p) {
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 		/* Delete all the objects in the session. */
9167c478bd9Sstevel@tonic-gate 		objp = session_p->object_list;
9177c478bd9Sstevel@tonic-gate 		while (objp) {
9187c478bd9Sstevel@tonic-gate 			objp1 = objp->next;
9197c478bd9Sstevel@tonic-gate 			/*
9207c478bd9Sstevel@tonic-gate 			 * The FALSE boolean argument indicates that the
9217c478bd9Sstevel@tonic-gate 			 * caller does not hold the session lock.  The TRUE
9227c478bd9Sstevel@tonic-gate 			 * boolean argument indicates that the caller just
9237c478bd9Sstevel@tonic-gate 			 * want to clean upt the object wrapper from the
9247c478bd9Sstevel@tonic-gate 			 * library only.
9257c478bd9Sstevel@tonic-gate 			 */
9267c478bd9Sstevel@tonic-gate 			if (objp->bool_attr_mask & PRIVATE_BOOL_ON) {
9277c478bd9Sstevel@tonic-gate 				(void) kernel_delete_session_object(session_p,
9287c478bd9Sstevel@tonic-gate 				    objp, B_FALSE, B_TRUE);
9297c478bd9Sstevel@tonic-gate 			}
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 			objp = objp1;
9327c478bd9Sstevel@tonic-gate 		}
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 		session_p = session_p->next;
9357c478bd9Sstevel@tonic-gate 	}
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate /*
9397c478bd9Sstevel@tonic-gate  * Get the object size in bytes for the objects created in the library.
9407c478bd9Sstevel@tonic-gate  */
9417c478bd9Sstevel@tonic-gate CK_RV
kernel_get_object_size(kernel_object_t * obj,CK_ULONG_PTR pulSize)9427c478bd9Sstevel@tonic-gate kernel_get_object_size(kernel_object_t *obj, CK_ULONG_PTR pulSize)
9437c478bd9Sstevel@tonic-gate {
9447c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
9457c478bd9Sstevel@tonic-gate 	CK_ULONG obj_size;
9467c478bd9Sstevel@tonic-gate 	biginteger_t *big;
9477c478bd9Sstevel@tonic-gate 
9487c478bd9Sstevel@tonic-gate 	obj_size = sizeof (kernel_object_t);
9497c478bd9Sstevel@tonic-gate 
9507c478bd9Sstevel@tonic-gate 	switch (obj->class) {
9517c478bd9Sstevel@tonic-gate 	case CKO_PUBLIC_KEY:
9527c478bd9Sstevel@tonic-gate 		if (obj->key_type == CKK_RSA) {
9537c478bd9Sstevel@tonic-gate 			big = OBJ_PUB_RSA_PUBEXPO(obj);
9547c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
9557c478bd9Sstevel@tonic-gate 			big = OBJ_PUB_RSA_MOD(obj);
9567c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 		} else if (obj->key_type == CKK_DSA) {
9597c478bd9Sstevel@tonic-gate 			big = OBJ_PUB_DSA_PRIME(obj);
9607c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
9617c478bd9Sstevel@tonic-gate 			big = OBJ_PUB_DSA_SUBPRIME(obj);
9627c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
9637c478bd9Sstevel@tonic-gate 			big = OBJ_PUB_DSA_BASE(obj);
9647c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
9657c478bd9Sstevel@tonic-gate 			big = OBJ_PUB_DSA_VALUE(obj);
9667c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
9677c478bd9Sstevel@tonic-gate 
968034448feSmcpowers 		} else if (obj->key_type == CKK_EC) {
969034448feSmcpowers 			big = OBJ_PUB_EC_POINT(obj);
970034448feSmcpowers 			obj_size += big->big_value_len;
971034448feSmcpowers 
9727c478bd9Sstevel@tonic-gate 		} else {
9737c478bd9Sstevel@tonic-gate 			rv = CKR_OBJECT_HANDLE_INVALID;
9747c478bd9Sstevel@tonic-gate 		}
9757c478bd9Sstevel@tonic-gate 		break;
9767c478bd9Sstevel@tonic-gate 
9777c478bd9Sstevel@tonic-gate 	case CKO_PRIVATE_KEY:
9787c478bd9Sstevel@tonic-gate 		if (obj->key_type == CKK_RSA) {
9797c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_RSA_MOD(obj);
9807c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
9817c478bd9Sstevel@tonic-gate 
9827c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_RSA_PUBEXPO(obj); /* optional */
9837c478bd9Sstevel@tonic-gate 			if (big != NULL) {
9847c478bd9Sstevel@tonic-gate 				obj_size += big->big_value_len;
9857c478bd9Sstevel@tonic-gate 			}
9867c478bd9Sstevel@tonic-gate 
9877c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_RSA_PRIEXPO(obj);
9887c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
9897c478bd9Sstevel@tonic-gate 
9907c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_RSA_PRIME1(obj); /* optional */
9917c478bd9Sstevel@tonic-gate 			if (big != NULL) {
9927c478bd9Sstevel@tonic-gate 				obj_size += big->big_value_len;
9937c478bd9Sstevel@tonic-gate 			}
9947c478bd9Sstevel@tonic-gate 
9957c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_RSA_PRIME2(obj); /* optional */
9967c478bd9Sstevel@tonic-gate 			if (big != NULL) {
9977c478bd9Sstevel@tonic-gate 				obj_size += big->big_value_len;
9987c478bd9Sstevel@tonic-gate 			}
9997c478bd9Sstevel@tonic-gate 
10007c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_RSA_EXPO1(obj); /* optional */
10017c478bd9Sstevel@tonic-gate 			if (big != NULL) {
10027c478bd9Sstevel@tonic-gate 				obj_size += big->big_value_len;
10037c478bd9Sstevel@tonic-gate 			}
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_RSA_EXPO2(obj); /* optional */
10067c478bd9Sstevel@tonic-gate 			if (big != NULL) {
10077c478bd9Sstevel@tonic-gate 				obj_size += big->big_value_len;
10087c478bd9Sstevel@tonic-gate 			}
10097c478bd9Sstevel@tonic-gate 
10107c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_RSA_COEF(obj); /* optional */
10117c478bd9Sstevel@tonic-gate 			if (big != NULL) {
10127c478bd9Sstevel@tonic-gate 				obj_size += big->big_value_len;
10137c478bd9Sstevel@tonic-gate 			}
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate 		} else if (obj->key_type == CKK_DSA) {
10167c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_DSA_PRIME(obj);
10177c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
10187c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_DSA_SUBPRIME(obj);
10197c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
10207c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_DSA_BASE(obj);
10217c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
10227c478bd9Sstevel@tonic-gate 			big = OBJ_PRI_DSA_VALUE(obj);
10237c478bd9Sstevel@tonic-gate 			obj_size += big->big_value_len;
10247c478bd9Sstevel@tonic-gate 
1025034448feSmcpowers 		} else if (obj->key_type == CKK_EC) {
1026034448feSmcpowers 			big = OBJ_PRI_EC_VALUE(obj);
1027034448feSmcpowers 			obj_size += big->big_value_len;
1028034448feSmcpowers 
10297c478bd9Sstevel@tonic-gate 		} else {
10307c478bd9Sstevel@tonic-gate 			rv = CKR_OBJECT_HANDLE_INVALID;
10317c478bd9Sstevel@tonic-gate 		}
10327c478bd9Sstevel@tonic-gate 		break;
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 	case CKO_SECRET_KEY:
10357c478bd9Sstevel@tonic-gate 		obj_size += OBJ_SEC_VALUE_LEN(obj);
10367c478bd9Sstevel@tonic-gate 		break;
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 	default:
10397c478bd9Sstevel@tonic-gate 		rv = CKR_OBJECT_HANDLE_INVALID;
10407c478bd9Sstevel@tonic-gate 	}
10417c478bd9Sstevel@tonic-gate 
10427c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
10437c478bd9Sstevel@tonic-gate 		*pulSize = obj_size;
10447c478bd9Sstevel@tonic-gate 	}
10457c478bd9Sstevel@tonic-gate 
10467c478bd9Sstevel@tonic-gate 	return (rv);
10477c478bd9Sstevel@tonic-gate }
104801223cbaSmcpowers 
104901223cbaSmcpowers /*
105001223cbaSmcpowers  * This function adds the to-be-freed session object to a linked list.
105101223cbaSmcpowers  * When the number of objects queued in the linked list reaches the
105201223cbaSmcpowers  * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
105301223cbaSmcpowers  * object (FIFO) in the list.
105401223cbaSmcpowers  */
105501223cbaSmcpowers void
kernel_object_delay_free(kernel_object_t * objp)105601223cbaSmcpowers kernel_object_delay_free(kernel_object_t *objp)
105701223cbaSmcpowers {
105801223cbaSmcpowers 	kernel_object_t *tmp;
105901223cbaSmcpowers 
106001223cbaSmcpowers 	(void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
106101223cbaSmcpowers 
106201223cbaSmcpowers 	/* Add the newly deleted object at the end of the list */
106301223cbaSmcpowers 	objp->next = NULL;
106401223cbaSmcpowers 	if (obj_delay_freed.first == NULL) {
106501223cbaSmcpowers 		obj_delay_freed.last = objp;
106601223cbaSmcpowers 		obj_delay_freed.first = objp;
106701223cbaSmcpowers 	} else {
106801223cbaSmcpowers 		obj_delay_freed.last->next = objp;
106901223cbaSmcpowers 		obj_delay_freed.last = objp;
107001223cbaSmcpowers 	}
107101223cbaSmcpowers 
107201223cbaSmcpowers 	if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
107301223cbaSmcpowers 		/*
107401223cbaSmcpowers 		 * Free the first object in the list only if
107501223cbaSmcpowers 		 * the total count reaches maximum threshold.
107601223cbaSmcpowers 		 */
107701223cbaSmcpowers 		obj_delay_freed.count--;
107801223cbaSmcpowers 		tmp = obj_delay_freed.first->next;
107901223cbaSmcpowers 		free(obj_delay_freed.first);
108001223cbaSmcpowers 		obj_delay_freed.first = tmp;
108101223cbaSmcpowers 	}
108201223cbaSmcpowers 	(void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
108301223cbaSmcpowers }
1084