xref: /titanic_52/usr/src/lib/pkcs11/pkcs11_softtoken/common/softObjectUtil.c (revision 726fad2a65f16c200a03969c29cb5c86c2d427db)
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
590e0e8c4Sizick  * Common Development and Distribution License (the "License").
690e0e8c4Sizick  * 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  */
21*726fad2aSDina K Nimeh 
227c478bd9Sstevel@tonic-gate /*
23*726fad2aSDina K Nimeh  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
247c478bd9Sstevel@tonic-gate  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <pthread.h>
277c478bd9Sstevel@tonic-gate #include <stdio.h>
287c478bd9Sstevel@tonic-gate #include <stdlib.h>
297c478bd9Sstevel@tonic-gate #include <string.h>
307c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
317c478bd9Sstevel@tonic-gate #include "softGlobal.h"
327c478bd9Sstevel@tonic-gate #include "softObject.h"
337c478bd9Sstevel@tonic-gate #include "softSession.h"
347c478bd9Sstevel@tonic-gate #include "softKeystore.h"
357c478bd9Sstevel@tonic-gate #include "softKeystoreUtil.h"
367c478bd9Sstevel@tonic-gate 
377c478bd9Sstevel@tonic-gate /*
387c478bd9Sstevel@tonic-gate  * Add an object to the session's object list.
397c478bd9Sstevel@tonic-gate  *
407c478bd9Sstevel@tonic-gate  * This function will acquire the lock on the session, and release
417c478bd9Sstevel@tonic-gate  * that lock after adding the object to the session's object list.
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate void
447c478bd9Sstevel@tonic-gate soft_add_object_to_session(soft_object_t *objp, soft_session_t *sp)
457c478bd9Sstevel@tonic-gate {
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 /*
687c478bd9Sstevel@tonic-gate  * Clean up and release the storage allocated to the object.
697c478bd9Sstevel@tonic-gate  *
707c478bd9Sstevel@tonic-gate  * The function is called either with the object lock being held
717c478bd9Sstevel@tonic-gate  * (by caller soft_delete_object()), or there is no object lock
727c478bd9Sstevel@tonic-gate  * yet (by soft_build_XXX_object() during creating an object).
737c478bd9Sstevel@tonic-gate  */
747c478bd9Sstevel@tonic-gate void
757c478bd9Sstevel@tonic-gate soft_cleanup_object(soft_object_t *objp)
767c478bd9Sstevel@tonic-gate {
777c478bd9Sstevel@tonic-gate 	/*
787c478bd9Sstevel@tonic-gate 	 * Free the storage allocated to big integer attributes.
797c478bd9Sstevel@tonic-gate 	 */
807c478bd9Sstevel@tonic-gate 	soft_cleanup_object_bigint_attrs(objp);
817c478bd9Sstevel@tonic-gate 
827c478bd9Sstevel@tonic-gate 	/*
837c478bd9Sstevel@tonic-gate 	 * Free the storage allocated to the extra attribute list.
847c478bd9Sstevel@tonic-gate 	 */
857c478bd9Sstevel@tonic-gate 	soft_cleanup_extra_attr(objp);
867c478bd9Sstevel@tonic-gate 
877c478bd9Sstevel@tonic-gate 	/*
887c478bd9Sstevel@tonic-gate 	 * Free the storage allocated to certificate attributes.
897c478bd9Sstevel@tonic-gate 	 */
907c478bd9Sstevel@tonic-gate 	soft_cleanup_cert_object(objp);
917c478bd9Sstevel@tonic-gate }
927c478bd9Sstevel@tonic-gate 
937c478bd9Sstevel@tonic-gate 
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate  * Create a new object. Copy the attributes that can be modified
967c478bd9Sstevel@tonic-gate  * (in the boolean attribute mask field and extra attribute list)
977c478bd9Sstevel@tonic-gate  * from the old object to the new object.
987c478bd9Sstevel@tonic-gate  *
997c478bd9Sstevel@tonic-gate  * The caller of this function holds the lock on the old object.
1007c478bd9Sstevel@tonic-gate  */
1017c478bd9Sstevel@tonic-gate CK_RV
1027c478bd9Sstevel@tonic-gate soft_copy_object(soft_object_t *old_object, soft_object_t **new_object,
1037c478bd9Sstevel@tonic-gate     CK_ULONG object_func, soft_session_t *sp)
1047c478bd9Sstevel@tonic-gate {
1057c478bd9Sstevel@tonic-gate 
1067c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1077c478bd9Sstevel@tonic-gate 	soft_object_t *new_objp = NULL;
1087c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE_INFO_PTR attrp;
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	/* Allocate new object. */
1117c478bd9Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (soft_object_t));
1127c478bd9Sstevel@tonic-gate 	if (new_objp == NULL)
1137c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
1147c478bd9Sstevel@tonic-gate 
1157c478bd9Sstevel@tonic-gate 	new_objp->class = old_object->class;
1167c478bd9Sstevel@tonic-gate 	new_objp->bool_attr_mask = old_object->bool_attr_mask;
1177c478bd9Sstevel@tonic-gate 	new_objp->cert_type = old_object->cert_type;
1187c478bd9Sstevel@tonic-gate 	new_objp->object_type = old_object->object_type;
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 = soft_copy_extra_attr(attrp, new_objp);
1297c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1307c478bd9Sstevel@tonic-gate 			soft_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 (object_func == SOFT_SET_ATTR_VALUE) {
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 
1537c478bd9Sstevel@tonic-gate 	switch (object_func) {
1547c478bd9Sstevel@tonic-gate 	case SOFT_COPY_OBJ_ORIG_SH:
1557c478bd9Sstevel@tonic-gate 		new_objp->session_handle = old_object->session_handle;
1567c478bd9Sstevel@tonic-gate 		break;
1577c478bd9Sstevel@tonic-gate 	case SOFT_COPY_OBJECT:
1587c478bd9Sstevel@tonic-gate 		/*
1597c478bd9Sstevel@tonic-gate 		 * Save the session handle of the C_CopyObject function
1607c478bd9Sstevel@tonic-gate 		 * in the new copy of the session object.
1617c478bd9Sstevel@tonic-gate 		 */
1627c478bd9Sstevel@tonic-gate 		new_objp->session_handle = (CK_SESSION_HANDLE)sp;
1637c478bd9Sstevel@tonic-gate 		break;
1647c478bd9Sstevel@tonic-gate 	}
1657c478bd9Sstevel@tonic-gate 
1667c478bd9Sstevel@tonic-gate 	(void) pthread_cond_init(&(new_objp->obj_free_cond), NULL);
1677c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&(new_objp->object_mutex), NULL);
1687c478bd9Sstevel@tonic-gate 	/* copy key related information */
1697c478bd9Sstevel@tonic-gate 	switch (new_objp->class) {
1707c478bd9Sstevel@tonic-gate 		case CKO_PUBLIC_KEY:
1717c478bd9Sstevel@tonic-gate 			rv = soft_copy_public_key_attr(OBJ_PUB(old_object),
1727c478bd9Sstevel@tonic-gate 			    &(OBJ_PUB(new_objp)), new_objp->key_type);
1737c478bd9Sstevel@tonic-gate 			break;
1747c478bd9Sstevel@tonic-gate 		case CKO_PRIVATE_KEY:
1757c478bd9Sstevel@tonic-gate 			rv = soft_copy_private_key_attr(OBJ_PRI(old_object),
1767c478bd9Sstevel@tonic-gate 			    &(OBJ_PRI(new_objp)), new_objp->key_type);
1777c478bd9Sstevel@tonic-gate 			break;
1787c478bd9Sstevel@tonic-gate 		case CKO_SECRET_KEY:
1797c478bd9Sstevel@tonic-gate 			rv = soft_copy_secret_key_attr(OBJ_SEC(old_object),
1807c478bd9Sstevel@tonic-gate 			    &(OBJ_SEC(new_objp)));
1817c478bd9Sstevel@tonic-gate 			break;
1827c478bd9Sstevel@tonic-gate 		case CKO_DOMAIN_PARAMETERS:
1837c478bd9Sstevel@tonic-gate 			rv = soft_copy_domain_attr(OBJ_DOM(old_object),
1847c478bd9Sstevel@tonic-gate 			    &(OBJ_DOM(new_objp)), new_objp->key_type);
1857c478bd9Sstevel@tonic-gate 			break;
1867c478bd9Sstevel@tonic-gate 		case CKO_CERTIFICATE:
1877c478bd9Sstevel@tonic-gate 			rv = soft_copy_certificate(OBJ_CERT(old_object),
1887c478bd9Sstevel@tonic-gate 			    &(OBJ_CERT(new_objp)), new_objp->cert_type);
1897c478bd9Sstevel@tonic-gate 			break;
1907c478bd9Sstevel@tonic-gate 		default:
1917c478bd9Sstevel@tonic-gate 			/* should never be this case */
1927c478bd9Sstevel@tonic-gate 			break;
1937c478bd9Sstevel@tonic-gate 	}
1947c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1957c478bd9Sstevel@tonic-gate 		/*
1967c478bd9Sstevel@tonic-gate 		 * don't need to cleanup the memory from failure of copying
1977c478bd9Sstevel@tonic-gate 		 * any key related stuff.  Each individual function for
1987c478bd9Sstevel@tonic-gate 		 * copying key attr will free the memory if it fails
1997c478bd9Sstevel@tonic-gate 		 */
2007c478bd9Sstevel@tonic-gate 		soft_cleanup_extra_attr(new_objp);
2017c478bd9Sstevel@tonic-gate 		free(new_objp);
2027c478bd9Sstevel@tonic-gate 	}
2037c478bd9Sstevel@tonic-gate 	return (rv);
2047c478bd9Sstevel@tonic-gate }
2057c478bd9Sstevel@tonic-gate 
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate /*
2087c478bd9Sstevel@tonic-gate  * Copy the attributes (in the boolean attribute mask field and
2097c478bd9Sstevel@tonic-gate  * extra attribute list) from the new object back to the original
2107c478bd9Sstevel@tonic-gate  * object. Also, clean up and release all the storage in the extra
2117c478bd9Sstevel@tonic-gate  * attribute list of the original object.
2127c478bd9Sstevel@tonic-gate  *
2137c478bd9Sstevel@tonic-gate  * The caller of this function holds the lock on the old object.
2147c478bd9Sstevel@tonic-gate  */
2157c478bd9Sstevel@tonic-gate void
2167c478bd9Sstevel@tonic-gate soft_merge_object(soft_object_t *old_object, soft_object_t *new_object)
2177c478bd9Sstevel@tonic-gate {
2187c478bd9Sstevel@tonic-gate 	old_object->bool_attr_mask = new_object->bool_attr_mask;
2197c478bd9Sstevel@tonic-gate 	soft_cleanup_extra_attr(old_object);
2207c478bd9Sstevel@tonic-gate 	old_object->extra_attrlistp = new_object->extra_attrlistp;
2217c478bd9Sstevel@tonic-gate }
2227c478bd9Sstevel@tonic-gate 
2237c478bd9Sstevel@tonic-gate 
2247c478bd9Sstevel@tonic-gate /*
2257c478bd9Sstevel@tonic-gate  * Create a new object struct, and add it to the session's object list.
2267c478bd9Sstevel@tonic-gate  */
2277c478bd9Sstevel@tonic-gate CK_RV
2287c478bd9Sstevel@tonic-gate soft_add_object(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
2297c478bd9Sstevel@tonic-gate 	CK_ULONG *objecthandle_p, soft_session_t *sp)
2307c478bd9Sstevel@tonic-gate {
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
2337c478bd9Sstevel@tonic-gate 	soft_object_t *new_objp = NULL;
2347c478bd9Sstevel@tonic-gate 
2357c478bd9Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (soft_object_t));
2367c478bd9Sstevel@tonic-gate 	if (new_objp == NULL) {
2377c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2387c478bd9Sstevel@tonic-gate 	}
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	new_objp->extra_attrlistp = NULL;
2417c478bd9Sstevel@tonic-gate 
2427c478bd9Sstevel@tonic-gate 	/*
2437c478bd9Sstevel@tonic-gate 	 * Validate attribute template and fill in the attributes
2447c478bd9Sstevel@tonic-gate 	 * in the soft_object_t.
2457c478bd9Sstevel@tonic-gate 	 */
2467c478bd9Sstevel@tonic-gate 	rv = soft_build_object(pTemplate, ulCount, new_objp);
2477c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
2487c478bd9Sstevel@tonic-gate 		goto fail_cleanup1;
2497c478bd9Sstevel@tonic-gate 	}
2507c478bd9Sstevel@tonic-gate 
2517c478bd9Sstevel@tonic-gate 	rv = soft_pin_expired_check(new_objp);
2527c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
2537c478bd9Sstevel@tonic-gate 		goto fail_cleanup2;
2547c478bd9Sstevel@tonic-gate 	}
2557c478bd9Sstevel@tonic-gate 
2567c478bd9Sstevel@tonic-gate 	rv = soft_object_write_access_check(sp, new_objp);
2577c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
2587c478bd9Sstevel@tonic-gate 		goto fail_cleanup2;
2597c478bd9Sstevel@tonic-gate 	}
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate 	/* Initialize the rest of stuffs in soft_object_t. */
2627c478bd9Sstevel@tonic-gate 	(void) pthread_cond_init(&new_objp->obj_free_cond, NULL);
2637c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
2647c478bd9Sstevel@tonic-gate 	new_objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
2657c478bd9Sstevel@tonic-gate 	new_objp->obj_refcnt = 0;
2667c478bd9Sstevel@tonic-gate 	new_objp->obj_delete_sync = 0;
2677c478bd9Sstevel@tonic-gate 
2687c478bd9Sstevel@tonic-gate 	/* Write the new token object to the keystore */
2697c478bd9Sstevel@tonic-gate 	if (IS_TOKEN_OBJECT(new_objp)) {
27090e0e8c4Sizick 		if (!soft_keystore_status(KEYSTORE_INITIALIZED)) {
27190e0e8c4Sizick 			rv = CKR_DEVICE_REMOVED;
27290e0e8c4Sizick 			goto fail_cleanup2;
27390e0e8c4Sizick 		}
2747c478bd9Sstevel@tonic-gate 		new_objp->version = 1;
2757c478bd9Sstevel@tonic-gate 		rv = soft_put_object_to_keystore(new_objp);
2767c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
2777c478bd9Sstevel@tonic-gate 			(void) pthread_cond_destroy(&new_objp->obj_free_cond);
2787c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_destroy(&new_objp->object_mutex);
2797c478bd9Sstevel@tonic-gate 			goto fail_cleanup2;
2807c478bd9Sstevel@tonic-gate 		}
2817c478bd9Sstevel@tonic-gate 		new_objp->session_handle = (CK_SESSION_HANDLE)NULL;
2827c478bd9Sstevel@tonic-gate 		soft_add_token_object_to_slot(new_objp);
2837c478bd9Sstevel@tonic-gate 		/*
2847c478bd9Sstevel@tonic-gate 		 * Type casting the address of an object struct to
2857c478bd9Sstevel@tonic-gate 		 * an object handle.
2867c478bd9Sstevel@tonic-gate 		 */
2877c478bd9Sstevel@tonic-gate 		*objecthandle_p = (CK_ULONG)new_objp;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 		return (CKR_OK);
2907c478bd9Sstevel@tonic-gate 	}
2917c478bd9Sstevel@tonic-gate 
2927c478bd9Sstevel@tonic-gate 	new_objp->session_handle = (CK_SESSION_HANDLE)sp;
2937c478bd9Sstevel@tonic-gate 
2947c478bd9Sstevel@tonic-gate 	/* Add the new object to the session's object list. */
2957c478bd9Sstevel@tonic-gate 	soft_add_object_to_session(new_objp, sp);
2967c478bd9Sstevel@tonic-gate 
2977c478bd9Sstevel@tonic-gate 	/* Type casting the address of an object struct to an object handle. */
2987c478bd9Sstevel@tonic-gate 	*objecthandle_p =  (CK_ULONG)new_objp;
2997c478bd9Sstevel@tonic-gate 
3007c478bd9Sstevel@tonic-gate 	return (CKR_OK);
3017c478bd9Sstevel@tonic-gate 
3027c478bd9Sstevel@tonic-gate fail_cleanup2:
3037c478bd9Sstevel@tonic-gate 	/*
3047c478bd9Sstevel@tonic-gate 	 * When any error occurs after soft_build_object(), we will need to
3057c478bd9Sstevel@tonic-gate 	 * clean up the memory allocated by the soft_build_object().
3067c478bd9Sstevel@tonic-gate 	 */
3077c478bd9Sstevel@tonic-gate 	soft_cleanup_object(new_objp);
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate fail_cleanup1:
3107c478bd9Sstevel@tonic-gate 	if (new_objp) {
3117c478bd9Sstevel@tonic-gate 		/*
3127c478bd9Sstevel@tonic-gate 		 * The storage allocated inside of this object should have
3137c478bd9Sstevel@tonic-gate 		 * been cleaned up by the soft_build_object() if it failed.
3147c478bd9Sstevel@tonic-gate 		 * Therefore, we can safely free the object.
3157c478bd9Sstevel@tonic-gate 		 */
3167c478bd9Sstevel@tonic-gate 		free(new_objp);
3177c478bd9Sstevel@tonic-gate 	}
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 	return (rv);
3207c478bd9Sstevel@tonic-gate 
3217c478bd9Sstevel@tonic-gate }
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 
3247c478bd9Sstevel@tonic-gate /*
3257c478bd9Sstevel@tonic-gate  * Remove an object from the session's object list.
3267c478bd9Sstevel@tonic-gate  *
3277c478bd9Sstevel@tonic-gate  * The caller of this function holds the session lock.
3287c478bd9Sstevel@tonic-gate  */
3297c478bd9Sstevel@tonic-gate CK_RV
3307c478bd9Sstevel@tonic-gate soft_remove_object_from_session(soft_object_t *objp, soft_session_t *sp)
3317c478bd9Sstevel@tonic-gate {
3327c478bd9Sstevel@tonic-gate 	soft_object_t *tmp_objp;
3337c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
3347c478bd9Sstevel@tonic-gate 
3357c478bd9Sstevel@tonic-gate 	/*
3367c478bd9Sstevel@tonic-gate 	 * Remove the object from the session's object list.
3377c478bd9Sstevel@tonic-gate 	 */
3387c478bd9Sstevel@tonic-gate 	if ((sp == NULL) ||
3397c478bd9Sstevel@tonic-gate 	    (sp->magic_marker != SOFTTOKEN_SESSION_MAGIC)) {
3407c478bd9Sstevel@tonic-gate 		return (CKR_SESSION_HANDLE_INVALID);
3417c478bd9Sstevel@tonic-gate 	}
3427c478bd9Sstevel@tonic-gate 
3437c478bd9Sstevel@tonic-gate 	if ((sp->object_list == NULL) || (objp == NULL) ||
3447c478bd9Sstevel@tonic-gate 	    (objp->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
3457c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
3467c478bd9Sstevel@tonic-gate 	}
3477c478bd9Sstevel@tonic-gate 
3487c478bd9Sstevel@tonic-gate 	tmp_objp = sp->object_list;
3497c478bd9Sstevel@tonic-gate 	while (tmp_objp) {
3507c478bd9Sstevel@tonic-gate 		if (tmp_objp == objp) {
3517c478bd9Sstevel@tonic-gate 			found = B_TRUE;
3527c478bd9Sstevel@tonic-gate 			break;
3537c478bd9Sstevel@tonic-gate 		}
3547c478bd9Sstevel@tonic-gate 		tmp_objp = tmp_objp->next;
3557c478bd9Sstevel@tonic-gate 	}
3567c478bd9Sstevel@tonic-gate 	if (!found)
3577c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	if (sp->object_list == objp) {
3607c478bd9Sstevel@tonic-gate 		/* Object is the first one in the list. */
3617c478bd9Sstevel@tonic-gate 		if (objp->next) {
3627c478bd9Sstevel@tonic-gate 			sp->object_list = objp->next;
3637c478bd9Sstevel@tonic-gate 			objp->next->prev = NULL;
3647c478bd9Sstevel@tonic-gate 		} else {
3657c478bd9Sstevel@tonic-gate 			/* Object is the only one in the list. */
3667c478bd9Sstevel@tonic-gate 			sp->object_list = NULL;
3677c478bd9Sstevel@tonic-gate 		}
3687c478bd9Sstevel@tonic-gate 	} else {
3697c478bd9Sstevel@tonic-gate 		/* Object is not the first one in the list. */
3707c478bd9Sstevel@tonic-gate 		if (objp->next) {
3717c478bd9Sstevel@tonic-gate 			/* Object is in the middle of the list. */
3727c478bd9Sstevel@tonic-gate 			objp->prev->next = objp->next;
3737c478bd9Sstevel@tonic-gate 			objp->next->prev = objp->prev;
3747c478bd9Sstevel@tonic-gate 		} else {
3757c478bd9Sstevel@tonic-gate 			/* Object is the last one in the list. */
3767c478bd9Sstevel@tonic-gate 			objp->prev->next = NULL;
3777c478bd9Sstevel@tonic-gate 		}
3787c478bd9Sstevel@tonic-gate 	}
3797c478bd9Sstevel@tonic-gate 	return (CKR_OK);
3807c478bd9Sstevel@tonic-gate }
3817c478bd9Sstevel@tonic-gate 
3827c478bd9Sstevel@tonic-gate /*
3837c478bd9Sstevel@tonic-gate  * This function adds the to-be-freed session object to a linked list.
3847c478bd9Sstevel@tonic-gate  * When the number of objects queued in the linked list reaches the
3857c478bd9Sstevel@tonic-gate  * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
3867c478bd9Sstevel@tonic-gate  * object (FIFO) in the list.
3877c478bd9Sstevel@tonic-gate  */
3887c478bd9Sstevel@tonic-gate void
3897c478bd9Sstevel@tonic-gate object_delay_free(soft_object_t *objp)
3907c478bd9Sstevel@tonic-gate {
3917c478bd9Sstevel@tonic-gate 	soft_object_t *tmp;
3927c478bd9Sstevel@tonic-gate 
3937c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
3947c478bd9Sstevel@tonic-gate 
3957c478bd9Sstevel@tonic-gate 	/* Add the newly deleted object at the end of the list */
3967c478bd9Sstevel@tonic-gate 	objp->next = NULL;
3977c478bd9Sstevel@tonic-gate 	if (obj_delay_freed.first == NULL) {
3987c478bd9Sstevel@tonic-gate 		obj_delay_freed.last = objp;
3997c478bd9Sstevel@tonic-gate 		obj_delay_freed.first = objp;
4007c478bd9Sstevel@tonic-gate 	} else {
4017c478bd9Sstevel@tonic-gate 		obj_delay_freed.last->next = objp;
4027c478bd9Sstevel@tonic-gate 		obj_delay_freed.last = objp;
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
4067c478bd9Sstevel@tonic-gate 		/*
4077c478bd9Sstevel@tonic-gate 		 * Free the first object in the list only if
4087c478bd9Sstevel@tonic-gate 		 * the total count reaches maximum threshold.
4097c478bd9Sstevel@tonic-gate 		 */
4107c478bd9Sstevel@tonic-gate 		obj_delay_freed.count--;
4117c478bd9Sstevel@tonic-gate 		tmp = obj_delay_freed.first->next;
4127c478bd9Sstevel@tonic-gate 		free(obj_delay_freed.first);
4137c478bd9Sstevel@tonic-gate 		obj_delay_freed.first = tmp;
4147c478bd9Sstevel@tonic-gate 	}
4157c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
4167c478bd9Sstevel@tonic-gate }
4177c478bd9Sstevel@tonic-gate 
4187c478bd9Sstevel@tonic-gate static void
4191f49a79aSZdenek Kotala soft_delete_object_cleanup(soft_object_t *objp, boolean_t force)
4207c478bd9Sstevel@tonic-gate {
4217c478bd9Sstevel@tonic-gate 	/* Acquire the lock on the object. */
4227c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&objp->object_mutex);
4237c478bd9Sstevel@tonic-gate 
4247c478bd9Sstevel@tonic-gate 	/*
4257c478bd9Sstevel@tonic-gate 	 * Make sure another thread hasn't freed the object.
4267c478bd9Sstevel@tonic-gate 	 */
4277c478bd9Sstevel@tonic-gate 	if (objp->magic_marker != SOFTTOKEN_OBJECT_MAGIC) {
4287c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&objp->object_mutex);
4297c478bd9Sstevel@tonic-gate 		return;
4307c478bd9Sstevel@tonic-gate 	}
4317c478bd9Sstevel@tonic-gate 
4327c478bd9Sstevel@tonic-gate 	/*
4337c478bd9Sstevel@tonic-gate 	 * The deletion of an object must be blocked when the object
4347c478bd9Sstevel@tonic-gate 	 * reference count is not zero. This means if any object related
4357c478bd9Sstevel@tonic-gate 	 * operation starts prior to the delete object operation gets in,
4367c478bd9Sstevel@tonic-gate 	 * the object deleting thread must wait for the non-deleting
4377c478bd9Sstevel@tonic-gate 	 * operation to be completed before it can proceed the delete
4387c478bd9Sstevel@tonic-gate 	 * operation.
4391f49a79aSZdenek Kotala 	 *
4401f49a79aSZdenek Kotala 	 * Unless we are being forced to shut everything down, this only
4411f49a79aSZdenek Kotala 	 * happens if the libraries _fini() is running not of someone
4421f49a79aSZdenek Kotala 	 * explicitly called C_Finalize().
4437c478bd9Sstevel@tonic-gate 	 */
4441f49a79aSZdenek Kotala 	if (force)
4451f49a79aSZdenek Kotala 		objp->obj_refcnt = 0;
4461f49a79aSZdenek Kotala 
4477c478bd9Sstevel@tonic-gate 	while (objp->obj_refcnt != 0) {
4487c478bd9Sstevel@tonic-gate 		/*
4497c478bd9Sstevel@tonic-gate 		 * We set the OBJECT_REFCNT_WAITING flag before we put
4507c478bd9Sstevel@tonic-gate 		 * this deleting thread in a wait state, so other non-deleting
4517c478bd9Sstevel@tonic-gate 		 * operation thread will signal to wake it up only when
4527c478bd9Sstevel@tonic-gate 		 * the object reference count becomes zero and this flag
4537c478bd9Sstevel@tonic-gate 		 * is set.
4547c478bd9Sstevel@tonic-gate 		 */
4557c478bd9Sstevel@tonic-gate 		objp->obj_delete_sync |= OBJECT_REFCNT_WAITING;
4567c478bd9Sstevel@tonic-gate 		(void) pthread_cond_wait(&objp->obj_free_cond,
4577c478bd9Sstevel@tonic-gate 		    &objp->object_mutex);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING;
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	/* Mark object as no longer valid. */
4637c478bd9Sstevel@tonic-gate 	objp->magic_marker = 0;
4647c478bd9Sstevel@tonic-gate 
4657c478bd9Sstevel@tonic-gate 	(void) pthread_cond_destroy(&objp->obj_free_cond);
4667c478bd9Sstevel@tonic-gate 
4677c478bd9Sstevel@tonic-gate 	/*
4687c478bd9Sstevel@tonic-gate 	 * Cleanup the contents of this object such as free all the
4697c478bd9Sstevel@tonic-gate 	 * storage allocated for this object.
4707c478bd9Sstevel@tonic-gate 	 */
4717c478bd9Sstevel@tonic-gate 	soft_cleanup_object(objp);
4727c478bd9Sstevel@tonic-gate 
4737c478bd9Sstevel@tonic-gate 	/* Reset OBJECT_IS_DELETING flag. */
4747c478bd9Sstevel@tonic-gate 	objp->obj_delete_sync &= ~OBJECT_IS_DELETING;
4757c478bd9Sstevel@tonic-gate 
4767c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&objp->object_mutex);
4777c478bd9Sstevel@tonic-gate 	/* Destroy the object lock */
4787c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_destroy(&objp->object_mutex);
4797c478bd9Sstevel@tonic-gate 
4807c478bd9Sstevel@tonic-gate 	/* Free the object itself */
4817c478bd9Sstevel@tonic-gate 	if (IS_TOKEN_OBJECT(objp))
4827c478bd9Sstevel@tonic-gate 		free(objp);
4837c478bd9Sstevel@tonic-gate 	else
4847c478bd9Sstevel@tonic-gate 		/*
4857c478bd9Sstevel@tonic-gate 		 * Delay freeing the session object as S1WS/NSS uses session
4867c478bd9Sstevel@tonic-gate 		 * objects for its SSL Handshake.
4877c478bd9Sstevel@tonic-gate 		 */
4887c478bd9Sstevel@tonic-gate 		(void) object_delay_free(objp);
4897c478bd9Sstevel@tonic-gate }
4907c478bd9Sstevel@tonic-gate 
4917c478bd9Sstevel@tonic-gate /*
4927c478bd9Sstevel@tonic-gate  * Delete an object:
4937c478bd9Sstevel@tonic-gate  * - Remove the object from the session's object list.
4947c478bd9Sstevel@tonic-gate  *   Holding the lock on the session which the object was created at
4957c478bd9Sstevel@tonic-gate  *   is needed to do this.
4967c478bd9Sstevel@tonic-gate  * - Release the storage allocated to the object.
4977c478bd9Sstevel@tonic-gate  *
4987c478bd9Sstevel@tonic-gate  * The boolean argument lock_held is used to indicate that whether
4997c478bd9Sstevel@tonic-gate  * the caller holds the session lock or not.
5007c478bd9Sstevel@tonic-gate  * - When called by soft_delete_all_objects_in_session() -- the
5017c478bd9Sstevel@tonic-gate  *   lock_held = TRUE.
5027c478bd9Sstevel@tonic-gate  *
5037c478bd9Sstevel@tonic-gate  * When the caller does not hold the session lock, this function
5047c478bd9Sstevel@tonic-gate  * will acquire that lock in order to proceed, and also release
5057c478bd9Sstevel@tonic-gate  * that lock before returning to caller.
5067c478bd9Sstevel@tonic-gate  */
5077c478bd9Sstevel@tonic-gate void
5081f49a79aSZdenek Kotala soft_delete_object(soft_session_t *sp, soft_object_t *objp,
5091f49a79aSZdenek Kotala 	boolean_t force, boolean_t lock_held)
5107c478bd9Sstevel@tonic-gate {
5117c478bd9Sstevel@tonic-gate 
5127c478bd9Sstevel@tonic-gate 	/*
5137c478bd9Sstevel@tonic-gate 	 * Check to see if the caller holds the lock on the session.
5147c478bd9Sstevel@tonic-gate 	 * If not, we need to acquire that lock in order to proceed.
5157c478bd9Sstevel@tonic-gate 	 */
5167c478bd9Sstevel@tonic-gate 	if (!lock_held) {
5177c478bd9Sstevel@tonic-gate 		/* Acquire the session lock. */
5187c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&sp->session_mutex);
5197c478bd9Sstevel@tonic-gate 	}
5207c478bd9Sstevel@tonic-gate 
5217c478bd9Sstevel@tonic-gate 	/* Remove the object from the session's object list first. */
5227c478bd9Sstevel@tonic-gate 	if (soft_remove_object_from_session(objp, sp) != CKR_OK) {
5237c478bd9Sstevel@tonic-gate 		if (!lock_held) {
5247c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&sp->session_mutex);
5257c478bd9Sstevel@tonic-gate 		}
5267c478bd9Sstevel@tonic-gate 		return;
5277c478bd9Sstevel@tonic-gate 	}
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	if (!lock_held) {
5307c478bd9Sstevel@tonic-gate 		/*
5317c478bd9Sstevel@tonic-gate 		 * If the session lock is obtained by this function,
5327c478bd9Sstevel@tonic-gate 		 * then release that lock after removing the object
5337c478bd9Sstevel@tonic-gate 		 * from session's object list.
5347c478bd9Sstevel@tonic-gate 		 * We want the releasing of the object storage to
5357c478bd9Sstevel@tonic-gate 		 * be done without holding the session lock.
5367c478bd9Sstevel@tonic-gate 		 */
5377c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&sp->session_mutex);
5387c478bd9Sstevel@tonic-gate 	}
5397c478bd9Sstevel@tonic-gate 
5401f49a79aSZdenek Kotala 	soft_delete_object_cleanup(objp, force);
5417c478bd9Sstevel@tonic-gate }
5427c478bd9Sstevel@tonic-gate 
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate /*
5457c478bd9Sstevel@tonic-gate  * Delete all the objects in a session. The caller holds the lock
5467c478bd9Sstevel@tonic-gate  * on the session.
5477c478bd9Sstevel@tonic-gate  */
5487c478bd9Sstevel@tonic-gate void
5491f49a79aSZdenek Kotala soft_delete_all_objects_in_session(soft_session_t *sp, boolean_t force)
5507c478bd9Sstevel@tonic-gate {
5517c478bd9Sstevel@tonic-gate 	soft_object_t *objp = sp->object_list;
5527c478bd9Sstevel@tonic-gate 	soft_object_t *objp1;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	/* Delete all the objects in the session. */
5557c478bd9Sstevel@tonic-gate 	while (objp) {
5567c478bd9Sstevel@tonic-gate 		objp1 = objp->next;
5577c478bd9Sstevel@tonic-gate 
5587c478bd9Sstevel@tonic-gate 		/*
5597c478bd9Sstevel@tonic-gate 		 * Delete an object by calling soft_delete_object()
5607c478bd9Sstevel@tonic-gate 		 * with a TRUE boolean argument indicating that
5617c478bd9Sstevel@tonic-gate 		 * the caller holds the lock on the session.
5627c478bd9Sstevel@tonic-gate 		 */
5631f49a79aSZdenek Kotala 		soft_delete_object(sp, objp, force, B_TRUE);
5647c478bd9Sstevel@tonic-gate 
5657c478bd9Sstevel@tonic-gate 		objp = objp1;
5667c478bd9Sstevel@tonic-gate 	}
5677c478bd9Sstevel@tonic-gate }
5687c478bd9Sstevel@tonic-gate 
5697c478bd9Sstevel@tonic-gate static CK_RV
5707c478bd9Sstevel@tonic-gate add_to_search_result(soft_object_t *obj, find_context_t *fcontext,
5717c478bd9Sstevel@tonic-gate     CK_ULONG *num_result_alloc)
5727c478bd9Sstevel@tonic-gate {
5737c478bd9Sstevel@tonic-gate 	/*
5747c478bd9Sstevel@tonic-gate 	 * allocate space for storing results if the currently
5757c478bd9Sstevel@tonic-gate 	 * allocated space is not enough
5767c478bd9Sstevel@tonic-gate 	 */
5777c478bd9Sstevel@tonic-gate 	if (*num_result_alloc <= fcontext->num_results) {
5787c478bd9Sstevel@tonic-gate 		fcontext->objs_found = realloc(fcontext->objs_found,
5797c478bd9Sstevel@tonic-gate 		    sizeof (soft_object_t *) * (*num_result_alloc + BUFSIZ));
5807c478bd9Sstevel@tonic-gate 		if (fcontext->objs_found == NULL) {
5817c478bd9Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
5827c478bd9Sstevel@tonic-gate 		}
5837c478bd9Sstevel@tonic-gate 		*num_result_alloc += BUFSIZ;
5847c478bd9Sstevel@tonic-gate 	}
5857c478bd9Sstevel@tonic-gate 
5867c478bd9Sstevel@tonic-gate 	(fcontext->objs_found)[(fcontext->num_results)++] = obj;
5877c478bd9Sstevel@tonic-gate 	return (CKR_OK);
5887c478bd9Sstevel@tonic-gate }
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate static CK_RV
5917c478bd9Sstevel@tonic-gate search_for_objects(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
5927c478bd9Sstevel@tonic-gate     find_context_t *fcontext)
5937c478bd9Sstevel@tonic-gate {
5947c478bd9Sstevel@tonic-gate 	soft_session_t *session_p;
5957c478bd9Sstevel@tonic-gate 	soft_object_t *obj;
596c2e31228SViswanathan Kannappan 	CK_OBJECT_CLASS pclasses[6]; /* classes attrs possibly exist */
5977c478bd9Sstevel@tonic-gate 	CK_ULONG num_pclasses;	/* number of possible classes */
5987c478bd9Sstevel@tonic-gate 	CK_ULONG num_result_alloc = 0; /* spaces allocated for results */
5997c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6007c478bd9Sstevel@tonic-gate 	/* whether CKA_TOKEN flag specified or not */
6017c478bd9Sstevel@tonic-gate 	boolean_t token_specified = B_FALSE;
6027c478bd9Sstevel@tonic-gate 	/* value of CKA_TOKEN flag, if specified */
6037c478bd9Sstevel@tonic-gate 	boolean_t token_flag_val = B_FALSE;
6047c478bd9Sstevel@tonic-gate 	CK_ULONG i;
6057c478bd9Sstevel@tonic-gate 
6067c478bd9Sstevel@tonic-gate 	if (ulCount > 0) {
6077c478bd9Sstevel@tonic-gate 		/* there are some search requirement */
6087c478bd9Sstevel@tonic-gate 		soft_process_find_attr(pclasses, &num_pclasses,
6097c478bd9Sstevel@tonic-gate 		    pTemplate, ulCount);
6107c478bd9Sstevel@tonic-gate 	}
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
6137c478bd9Sstevel@tonic-gate 		if (pTemplate[i].type == CKA_PRIVATE) {
6147c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&soft_giant_mutex);
6157c478bd9Sstevel@tonic-gate 			if (soft_slot.userpin_change_needed) {
6167c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock(&soft_giant_mutex);
6177c478bd9Sstevel@tonic-gate 				return (CKR_PIN_EXPIRED);
6187c478bd9Sstevel@tonic-gate 			}
6197c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&soft_giant_mutex);
6207c478bd9Sstevel@tonic-gate 		}
6217c478bd9Sstevel@tonic-gate 	}
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	/*
6247c478bd9Sstevel@tonic-gate 	 * look through template and see if it explicitly specifies
6257c478bd9Sstevel@tonic-gate 	 * whether we need to look for token objects or not
6267c478bd9Sstevel@tonic-gate 	 */
6277c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
6287c478bd9Sstevel@tonic-gate 		if (pTemplate[i].type == CKA_TOKEN) {
6297c478bd9Sstevel@tonic-gate 			token_specified = B_TRUE;
6307c478bd9Sstevel@tonic-gate 			token_flag_val = *((CK_BBOOL *)pTemplate[i].pValue);
6317c478bd9Sstevel@tonic-gate 			break;
6327c478bd9Sstevel@tonic-gate 		}
6337c478bd9Sstevel@tonic-gate 	}
6347c478bd9Sstevel@tonic-gate 
6357c478bd9Sstevel@tonic-gate 	/*
6367c478bd9Sstevel@tonic-gate 	 * Need go through token objects if it explicitly say so, or
6377c478bd9Sstevel@tonic-gate 	 * it is not mentioned in the template.  And this will ONLY be
6387c478bd9Sstevel@tonic-gate 	 * done when the keystore exists. Otherwise, we will skip re-loading
6397c478bd9Sstevel@tonic-gate 	 * the token objects.
6407c478bd9Sstevel@tonic-gate 	 *
6417c478bd9Sstevel@tonic-gate 	 * If a session has not logged into the token, only public
6427c478bd9Sstevel@tonic-gate 	 * objects, if any, will be searched.  If a session is logged
6437c478bd9Sstevel@tonic-gate 	 * into the token, all public and private objects in the keystore
6447c478bd9Sstevel@tonic-gate 	 * are searched.
6457c478bd9Sstevel@tonic-gate 	 */
64690e0e8c4Sizick 	if (((token_flag_val) || (!token_specified)) &&
64790e0e8c4Sizick 	    soft_keystore_status(KEYSTORE_INITIALIZED)) {
6487c478bd9Sstevel@tonic-gate 		/* acquire token session lock */
6497c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&soft_slot.slot_mutex);
6507c478bd9Sstevel@tonic-gate 		rv = refresh_token_objects();
6517c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
6527c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
6537c478bd9Sstevel@tonic-gate 			return (rv);
6547c478bd9Sstevel@tonic-gate 		}
6557c478bd9Sstevel@tonic-gate 		obj = soft_slot.token_object_list;
6567c478bd9Sstevel@tonic-gate 		while (obj) {
6577c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
6587c478bd9Sstevel@tonic-gate 			if (((token_specified) && (ulCount > 1)) ||
6597c478bd9Sstevel@tonic-gate 			    ((!token_specified) && (ulCount > 0))) {
6607c478bd9Sstevel@tonic-gate 				if (soft_find_match_attrs(obj, pclasses,
6617c478bd9Sstevel@tonic-gate 				    num_pclasses, pTemplate, ulCount)) {
6627c478bd9Sstevel@tonic-gate 					rv = add_to_search_result(
6637c478bd9Sstevel@tonic-gate 					    obj, fcontext, &num_result_alloc);
6647c478bd9Sstevel@tonic-gate 				}
6657c478bd9Sstevel@tonic-gate 			} else {
6667c478bd9Sstevel@tonic-gate 				/* no search criteria, just record the object */
6677c478bd9Sstevel@tonic-gate 				rv = add_to_search_result(obj, fcontext,
6687c478bd9Sstevel@tonic-gate 				    &num_result_alloc);
6697c478bd9Sstevel@tonic-gate 			}
6707c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
6717c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
6727c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock
6737c478bd9Sstevel@tonic-gate 				    (&soft_slot.slot_mutex);
6747c478bd9Sstevel@tonic-gate 				return (rv);
6757c478bd9Sstevel@tonic-gate 			}
6767c478bd9Sstevel@tonic-gate 			obj = obj->next;
6777c478bd9Sstevel@tonic-gate 		}
6787c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
6797c478bd9Sstevel@tonic-gate 	}
6807c478bd9Sstevel@tonic-gate 
6817c478bd9Sstevel@tonic-gate 	if (token_flag_val) {
6827c478bd9Sstevel@tonic-gate 		/* no need to look through session objects */
6837c478bd9Sstevel@tonic-gate 		return (rv);
6847c478bd9Sstevel@tonic-gate 	}
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 	/* Acquire the global session list lock */
6877c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_sessionlist_mutex);
6887c478bd9Sstevel@tonic-gate 
6897c478bd9Sstevel@tonic-gate 	/*
6907c478bd9Sstevel@tonic-gate 	 * Go through all objects in each session.
6917c478bd9Sstevel@tonic-gate 	 * Acquire individual session lock for the session
6927c478bd9Sstevel@tonic-gate 	 * we are searching.
6937c478bd9Sstevel@tonic-gate 	 */
6947c478bd9Sstevel@tonic-gate 	session_p = soft_session_list;
6957c478bd9Sstevel@tonic-gate 	while (session_p) {
6967c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 		obj = session_p->object_list;
6997c478bd9Sstevel@tonic-gate 		while (obj) {
7007c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
7017c478bd9Sstevel@tonic-gate 			if (ulCount > 0) {
7027c478bd9Sstevel@tonic-gate 				if (soft_find_match_attrs(obj, pclasses,
7037c478bd9Sstevel@tonic-gate 				    num_pclasses, pTemplate, ulCount)) {
7047c478bd9Sstevel@tonic-gate 					rv = add_to_search_result(
7057c478bd9Sstevel@tonic-gate 					    obj, fcontext, &num_result_alloc);
7067c478bd9Sstevel@tonic-gate 				}
7077c478bd9Sstevel@tonic-gate 			} else {
7087c478bd9Sstevel@tonic-gate 				/* no search criteria, just record the object */
7097c478bd9Sstevel@tonic-gate 				rv = add_to_search_result(obj, fcontext,
7107c478bd9Sstevel@tonic-gate 				    &num_result_alloc);
7117c478bd9Sstevel@tonic-gate 			}
7127c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
7137c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
7147c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock(
7157c478bd9Sstevel@tonic-gate 				    &session_p->session_mutex);
7167c478bd9Sstevel@tonic-gate 				goto cleanup;
7177c478bd9Sstevel@tonic-gate 			}
7187c478bd9Sstevel@tonic-gate 			obj = obj->next;
7197c478bd9Sstevel@tonic-gate 		}
7207c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
7217c478bd9Sstevel@tonic-gate 		session_p = session_p->next;
7227c478bd9Sstevel@tonic-gate 	}
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate cleanup:
7257c478bd9Sstevel@tonic-gate 	/* Release the global session list lock */
7267c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_sessionlist_mutex);
7277c478bd9Sstevel@tonic-gate 	return (rv);
7287c478bd9Sstevel@tonic-gate }
7297c478bd9Sstevel@tonic-gate 
7307c478bd9Sstevel@tonic-gate /*
7317c478bd9Sstevel@tonic-gate  * Initialize the context for C_FindObjects() calls
7327c478bd9Sstevel@tonic-gate  */
7337c478bd9Sstevel@tonic-gate CK_RV
7347c478bd9Sstevel@tonic-gate soft_find_objects_init(soft_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
7357c478bd9Sstevel@tonic-gate     CK_ULONG ulCount)
7367c478bd9Sstevel@tonic-gate {
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
7397c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class; /* for soft_validate_attr(). Value unused */
7407c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	if (ulCount) {
7437c478bd9Sstevel@tonic-gate 		rv = soft_validate_attr(pTemplate, ulCount, &class);
7447c478bd9Sstevel@tonic-gate 		/* Make sure all attributes in template are valid */
7457c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
7467c478bd9Sstevel@tonic-gate 			return (rv);
7477c478bd9Sstevel@tonic-gate 		}
7487c478bd9Sstevel@tonic-gate 	}
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 
7517c478bd9Sstevel@tonic-gate 	/* prepare the find context */
7527c478bd9Sstevel@tonic-gate 	fcontext = calloc(1, sizeof (find_context_t));
7537c478bd9Sstevel@tonic-gate 	if (fcontext == NULL) {
7547c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
7557c478bd9Sstevel@tonic-gate 	}
7567c478bd9Sstevel@tonic-gate 
7577c478bd9Sstevel@tonic-gate 	rv = search_for_objects(pTemplate, ulCount, fcontext);
7587c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
7597c478bd9Sstevel@tonic-gate 		free(fcontext);
7607c478bd9Sstevel@tonic-gate 		return (rv);
7617c478bd9Sstevel@tonic-gate 	}
7627c478bd9Sstevel@tonic-gate 
7637c478bd9Sstevel@tonic-gate 	/* store the find_context in the session */
7647c478bd9Sstevel@tonic-gate 	sp->find_objects.context = (CK_VOID_PTR)fcontext;
7657c478bd9Sstevel@tonic-gate 
7667c478bd9Sstevel@tonic-gate 	return (rv);
7677c478bd9Sstevel@tonic-gate }
7687c478bd9Sstevel@tonic-gate 
7697c478bd9Sstevel@tonic-gate void
7707c478bd9Sstevel@tonic-gate soft_find_objects_final(soft_session_t *sp)
7717c478bd9Sstevel@tonic-gate {
7727c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	fcontext = sp->find_objects.context;
7757c478bd9Sstevel@tonic-gate 	sp->find_objects.context = NULL;
7767c478bd9Sstevel@tonic-gate 	sp->find_objects.flags = 0;
7777c478bd9Sstevel@tonic-gate 	if (fcontext->objs_found != NULL) {
7787c478bd9Sstevel@tonic-gate 		free(fcontext->objs_found);
7797c478bd9Sstevel@tonic-gate 	}
7807c478bd9Sstevel@tonic-gate 
7817c478bd9Sstevel@tonic-gate 	free(fcontext);
7827c478bd9Sstevel@tonic-gate }
7837c478bd9Sstevel@tonic-gate 
7847c478bd9Sstevel@tonic-gate void
7857c478bd9Sstevel@tonic-gate soft_find_objects(soft_session_t *sp, CK_OBJECT_HANDLE *obj_found,
7867c478bd9Sstevel@tonic-gate     CK_ULONG max_obj_requested, CK_ULONG *found_obj_count)
7877c478bd9Sstevel@tonic-gate {
7887c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
7897c478bd9Sstevel@tonic-gate 	CK_ULONG num_obj_found = 0;
7907c478bd9Sstevel@tonic-gate 	CK_ULONG i;
7917c478bd9Sstevel@tonic-gate 	soft_object_t *obj;
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	fcontext = sp->find_objects.context;
7947c478bd9Sstevel@tonic-gate 
7957c478bd9Sstevel@tonic-gate 	for (i = fcontext->next_result_index;
7967c478bd9Sstevel@tonic-gate 	    ((num_obj_found < max_obj_requested) &&
7977c478bd9Sstevel@tonic-gate 	    (i < fcontext->num_results));
7987c478bd9Sstevel@tonic-gate 	    i++) {
7997c478bd9Sstevel@tonic-gate 		obj = fcontext->objs_found[i];
8007c478bd9Sstevel@tonic-gate 		if (obj != NULL) {
8017c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
8027c478bd9Sstevel@tonic-gate 			/* a sanity check to make sure the obj is still valid */
8037c478bd9Sstevel@tonic-gate 			if (obj->magic_marker == SOFTTOKEN_OBJECT_MAGIC) {
8047c478bd9Sstevel@tonic-gate 				obj_found[num_obj_found] =
8057c478bd9Sstevel@tonic-gate 				    (CK_OBJECT_HANDLE)obj;
8067c478bd9Sstevel@tonic-gate 				num_obj_found++;
8077c478bd9Sstevel@tonic-gate 			}
8087c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
8097c478bd9Sstevel@tonic-gate 		}
8107c478bd9Sstevel@tonic-gate 	}
8117c478bd9Sstevel@tonic-gate 	fcontext->next_result_index = i;
8127c478bd9Sstevel@tonic-gate 	*found_obj_count = num_obj_found;
8137c478bd9Sstevel@tonic-gate }
8147c478bd9Sstevel@tonic-gate 
8157c478bd9Sstevel@tonic-gate /*
8167c478bd9Sstevel@tonic-gate  * Below are the token object related functions
8177c478bd9Sstevel@tonic-gate  */
8187c478bd9Sstevel@tonic-gate void
8197c478bd9Sstevel@tonic-gate soft_add_token_object_to_slot(soft_object_t *objp)
8207c478bd9Sstevel@tonic-gate {
8217c478bd9Sstevel@tonic-gate 
8227c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_slot.slot_mutex);
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	/* Insert the new object in front of slot's token object list. */
8257c478bd9Sstevel@tonic-gate 	if (soft_slot.token_object_list == NULL) {
8267c478bd9Sstevel@tonic-gate 		soft_slot.token_object_list = objp;
8277c478bd9Sstevel@tonic-gate 		objp->next = NULL;
8287c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
8297c478bd9Sstevel@tonic-gate 	} else {
8307c478bd9Sstevel@tonic-gate 		soft_slot.token_object_list->prev = objp;
8317c478bd9Sstevel@tonic-gate 		objp->next = soft_slot.token_object_list;
8327c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
8337c478bd9Sstevel@tonic-gate 		soft_slot.token_object_list = objp;
8347c478bd9Sstevel@tonic-gate 	}
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate }
8397c478bd9Sstevel@tonic-gate 
8407c478bd9Sstevel@tonic-gate void
8417c478bd9Sstevel@tonic-gate soft_remove_token_object_from_slot(soft_object_t *objp, boolean_t lock_held)
8427c478bd9Sstevel@tonic-gate {
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate 	if (!lock_held)
8457c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&soft_slot.slot_mutex);
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	/*
8487c478bd9Sstevel@tonic-gate 	 * Remove the object from the slot's token object list.
8497c478bd9Sstevel@tonic-gate 	 */
8507c478bd9Sstevel@tonic-gate 	if (soft_slot.token_object_list == objp) {
8517c478bd9Sstevel@tonic-gate 		/* Object is the first one in the list. */
8527c478bd9Sstevel@tonic-gate 		if (objp->next) {
8537c478bd9Sstevel@tonic-gate 			soft_slot.token_object_list = objp->next;
8547c478bd9Sstevel@tonic-gate 			objp->next->prev = NULL;
8557c478bd9Sstevel@tonic-gate 		} else {
8567c478bd9Sstevel@tonic-gate 			/* Object is the only one in the list. */
8577c478bd9Sstevel@tonic-gate 			soft_slot.token_object_list = NULL;
8587c478bd9Sstevel@tonic-gate 		}
8597c478bd9Sstevel@tonic-gate 	} else {
8607c478bd9Sstevel@tonic-gate 		/* Object is not the first one in the list. */
8617c478bd9Sstevel@tonic-gate 		if (objp->next) {
8627c478bd9Sstevel@tonic-gate 			/* Object is in the middle of the list. */
8637c478bd9Sstevel@tonic-gate 			objp->prev->next = objp->next;
8647c478bd9Sstevel@tonic-gate 			objp->next->prev = objp->prev;
8657c478bd9Sstevel@tonic-gate 		} else {
8667c478bd9Sstevel@tonic-gate 			/* Object is the last one in the list. */
8677c478bd9Sstevel@tonic-gate 			objp->prev->next = NULL;
8687c478bd9Sstevel@tonic-gate 		}
8697c478bd9Sstevel@tonic-gate 	}
8707c478bd9Sstevel@tonic-gate 
8717c478bd9Sstevel@tonic-gate 	if (!lock_held)
8727c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate void
8767c478bd9Sstevel@tonic-gate soft_delete_token_object(soft_object_t *objp, boolean_t persistent,
8777c478bd9Sstevel@tonic-gate     boolean_t lock_held)
8787c478bd9Sstevel@tonic-gate {
8797c478bd9Sstevel@tonic-gate 
8804d25c1d6Smcpowers 	if (!lock_held)
8814d25c1d6Smcpowers 		(void) pthread_mutex_lock(&soft_slot.slot_mutex);
8827c478bd9Sstevel@tonic-gate 	if (persistent)
8837c478bd9Sstevel@tonic-gate 		/* Delete the object from the keystore. */
8847c478bd9Sstevel@tonic-gate 		(void) soft_keystore_del_obj(&objp->ks_handle, B_FALSE);
8857c478bd9Sstevel@tonic-gate 
8867c478bd9Sstevel@tonic-gate 	/* Remove the object from the slot's token object list. */
8874d25c1d6Smcpowers 	soft_remove_token_object_from_slot(objp, B_TRUE);
8884d25c1d6Smcpowers 	if (!lock_held)
8894d25c1d6Smcpowers 		(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
8907c478bd9Sstevel@tonic-gate 
8911f49a79aSZdenek Kotala 	soft_delete_object_cleanup(objp, B_FALSE);
8927c478bd9Sstevel@tonic-gate }
8937c478bd9Sstevel@tonic-gate 
8947c478bd9Sstevel@tonic-gate void
8957c478bd9Sstevel@tonic-gate soft_delete_all_in_core_token_objects(token_obj_type_t type)
8967c478bd9Sstevel@tonic-gate {
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate 	soft_object_t *objp;
8997c478bd9Sstevel@tonic-gate 	soft_object_t *objp1;
9007c478bd9Sstevel@tonic-gate 
9017c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_slot.slot_mutex);
9027c478bd9Sstevel@tonic-gate 	objp = soft_slot.token_object_list;
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	switch (type) {
9057c478bd9Sstevel@tonic-gate 	case PRIVATE_TOKEN:
9067c478bd9Sstevel@tonic-gate 		while (objp) {
9077c478bd9Sstevel@tonic-gate 			objp1 = objp->next;
9087c478bd9Sstevel@tonic-gate 			if (objp->object_type == TOKEN_PRIVATE) {
9097c478bd9Sstevel@tonic-gate 				soft_delete_token_object(objp, B_FALSE, B_TRUE);
9107c478bd9Sstevel@tonic-gate 			}
9117c478bd9Sstevel@tonic-gate 			objp = objp1;
9127c478bd9Sstevel@tonic-gate 		}
9137c478bd9Sstevel@tonic-gate 		break;
9147c478bd9Sstevel@tonic-gate 
9157c478bd9Sstevel@tonic-gate 	case PUBLIC_TOKEN:
9167c478bd9Sstevel@tonic-gate 		while (objp) {
9177c478bd9Sstevel@tonic-gate 			objp1 = objp->next;
9187c478bd9Sstevel@tonic-gate 			if (objp->object_type == TOKEN_PUBLIC) {
9197c478bd9Sstevel@tonic-gate 				soft_delete_token_object(objp, B_FALSE, B_TRUE);
9207c478bd9Sstevel@tonic-gate 			}
9217c478bd9Sstevel@tonic-gate 			objp = objp1;
9227c478bd9Sstevel@tonic-gate 		}
9237c478bd9Sstevel@tonic-gate 		break;
9247c478bd9Sstevel@tonic-gate 
9257c478bd9Sstevel@tonic-gate 	case ALL_TOKEN:
9267c478bd9Sstevel@tonic-gate 		while (objp) {
9277c478bd9Sstevel@tonic-gate 			objp1 = objp->next;
9287c478bd9Sstevel@tonic-gate 			soft_delete_token_object(objp, B_FALSE, B_TRUE);
9297c478bd9Sstevel@tonic-gate 			objp = objp1;
9307c478bd9Sstevel@tonic-gate 		}
9317c478bd9Sstevel@tonic-gate 		break;
9327c478bd9Sstevel@tonic-gate 	}
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
9357c478bd9Sstevel@tonic-gate 
9367c478bd9Sstevel@tonic-gate }
9377c478bd9Sstevel@tonic-gate 
9387c478bd9Sstevel@tonic-gate /*
93990e0e8c4Sizick  * Mark all the token objects in the global list to be valid.
9407c478bd9Sstevel@tonic-gate  */
9417c478bd9Sstevel@tonic-gate void
9427c478bd9Sstevel@tonic-gate soft_validate_token_objects(boolean_t validate)
9437c478bd9Sstevel@tonic-gate {
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 	soft_object_t *objp;
9467c478bd9Sstevel@tonic-gate 
9477c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_slot.slot_mutex);
94890e0e8c4Sizick 
9497c478bd9Sstevel@tonic-gate 	objp = soft_slot.token_object_list;
9507c478bd9Sstevel@tonic-gate 
9517c478bd9Sstevel@tonic-gate 	while (objp) {
9527c478bd9Sstevel@tonic-gate 		if (validate)
9537c478bd9Sstevel@tonic-gate 			objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
9547c478bd9Sstevel@tonic-gate 		else
9557c478bd9Sstevel@tonic-gate 			objp->magic_marker = 0;
9567c478bd9Sstevel@tonic-gate 
9577c478bd9Sstevel@tonic-gate 		objp = objp->next;
9587c478bd9Sstevel@tonic-gate 	}
9597c478bd9Sstevel@tonic-gate 
9607c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
9617c478bd9Sstevel@tonic-gate 
9627c478bd9Sstevel@tonic-gate }
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate /*
9657c478bd9Sstevel@tonic-gate  * Verify user's write access rule to the token object.
9667c478bd9Sstevel@tonic-gate  */
9677c478bd9Sstevel@tonic-gate CK_RV
9687c478bd9Sstevel@tonic-gate soft_object_write_access_check(soft_session_t *sp, soft_object_t *objp)
9697c478bd9Sstevel@tonic-gate {
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	/*
9727c478bd9Sstevel@tonic-gate 	 * This function is called by C_CreateObject, C_CopyObject,
9737c478bd9Sstevel@tonic-gate 	 * C_DestroyObject, C_SetAttributeValue, C_GenerateKey,
9747c478bd9Sstevel@tonic-gate 	 * C_GenerateKeyPairs, C_DeriveKey. All of them will write
9757c478bd9Sstevel@tonic-gate 	 * the token object to the keystore.
9767c478bd9Sstevel@tonic-gate 	 */
9777c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_giant_mutex);
9787c478bd9Sstevel@tonic-gate 	if (!soft_slot.authenticated) {
9797c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
9807c478bd9Sstevel@tonic-gate 		/* User is not logged in */
9817c478bd9Sstevel@tonic-gate 		if (sp->flags & CKF_RW_SESSION) {
9827c478bd9Sstevel@tonic-gate 			/*
9837c478bd9Sstevel@tonic-gate 			 * For R/W Public Session:
9847c478bd9Sstevel@tonic-gate 			 * we allow write access to public session or token
9857c478bd9Sstevel@tonic-gate 			 * object, but not for private token/session object.
9867c478bd9Sstevel@tonic-gate 			 */
9877c478bd9Sstevel@tonic-gate 			if ((objp->object_type == TOKEN_PRIVATE) ||
9887c478bd9Sstevel@tonic-gate 			    (objp->object_type == SESSION_PRIVATE)) {
9897c478bd9Sstevel@tonic-gate 				return (CKR_USER_NOT_LOGGED_IN);
9907c478bd9Sstevel@tonic-gate 			}
9917c478bd9Sstevel@tonic-gate 		} else {
9927c478bd9Sstevel@tonic-gate 			/*
9937c478bd9Sstevel@tonic-gate 			 * For R/O Public Session:
9947c478bd9Sstevel@tonic-gate 			 * we allow write access to public session object.
9957c478bd9Sstevel@tonic-gate 			 */
9967c478bd9Sstevel@tonic-gate 			if (objp->object_type != SESSION_PUBLIC)
9977c478bd9Sstevel@tonic-gate 				return (CKR_SESSION_READ_ONLY);
9987c478bd9Sstevel@tonic-gate 		}
9997c478bd9Sstevel@tonic-gate 	} else {
10007c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
10017c478bd9Sstevel@tonic-gate 		/* User is logged in */
10027c478bd9Sstevel@tonic-gate 		if (!(sp->flags & CKF_RW_SESSION)) {
10037c478bd9Sstevel@tonic-gate 			/*
10047c478bd9Sstevel@tonic-gate 			 * For R/O User Function Session:
10057c478bd9Sstevel@tonic-gate 			 * we allow write access to public or private
10067c478bd9Sstevel@tonic-gate 			 * session object, but not for public or private
10077c478bd9Sstevel@tonic-gate 			 * token object.
10087c478bd9Sstevel@tonic-gate 			 */
10097c478bd9Sstevel@tonic-gate 			if ((objp->object_type == TOKEN_PUBLIC) ||
10107c478bd9Sstevel@tonic-gate 			    (objp->object_type == TOKEN_PRIVATE)) {
10117c478bd9Sstevel@tonic-gate 				return (CKR_SESSION_READ_ONLY);
10127c478bd9Sstevel@tonic-gate 			}
10137c478bd9Sstevel@tonic-gate 		}
10147c478bd9Sstevel@tonic-gate 	}
10157c478bd9Sstevel@tonic-gate 
10167c478bd9Sstevel@tonic-gate 	return (CKR_OK);
10177c478bd9Sstevel@tonic-gate }
10187c478bd9Sstevel@tonic-gate 
10197c478bd9Sstevel@tonic-gate /*
10207c478bd9Sstevel@tonic-gate  * Verify if user is required to setpin when accessing the
10217c478bd9Sstevel@tonic-gate  * private token/session object.
10227c478bd9Sstevel@tonic-gate  */
10237c478bd9Sstevel@tonic-gate CK_RV
10247c478bd9Sstevel@tonic-gate soft_pin_expired_check(soft_object_t *objp)
10257c478bd9Sstevel@tonic-gate {
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	/*
10287c478bd9Sstevel@tonic-gate 	 * This function is called by C_CreateObject, C_CopyObject,
10297c478bd9Sstevel@tonic-gate 	 * C_DestroyObject, C_GenerateKey,
10307c478bd9Sstevel@tonic-gate 	 * C_GenerateKeyPairs, C_DeriveKey.
10317c478bd9Sstevel@tonic-gate 	 * All of them will return CKR_PIN_EXPIRED if the
10327c478bd9Sstevel@tonic-gate 	 * "userpin_change_needed" is set.
10337c478bd9Sstevel@tonic-gate 	 *
10347c478bd9Sstevel@tonic-gate 	 * The following functions will not be necessary to call
10357c478bd9Sstevel@tonic-gate 	 * this routine even though CKR_PIN_EXPIRED is one of the
10367c478bd9Sstevel@tonic-gate 	 * valid error code they might return. These functions are:
10377c478bd9Sstevel@tonic-gate 	 * C_EncryptInit, C_DecryptInit, C_DigestInit, C_SignInit,
10387c478bd9Sstevel@tonic-gate 	 * C_SignRecoverInit, C_VerifyInit, C_VerifyRecoverInit.
10397c478bd9Sstevel@tonic-gate 	 * This is because they will not get the object handle
10407c478bd9Sstevel@tonic-gate 	 * before the above functions are called.
10417c478bd9Sstevel@tonic-gate 	 */
10427c478bd9Sstevel@tonic-gate 
10437c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_giant_mutex);
10447c478bd9Sstevel@tonic-gate 	if (soft_slot.userpin_change_needed) {
10457c478bd9Sstevel@tonic-gate 		/*
10467c478bd9Sstevel@tonic-gate 		 * Access private token/session object but user's
10477c478bd9Sstevel@tonic-gate 		 * PIN is expired or never set.
10487c478bd9Sstevel@tonic-gate 		 */
10497c478bd9Sstevel@tonic-gate 		if ((objp->object_type == TOKEN_PRIVATE) ||
10507c478bd9Sstevel@tonic-gate 		    (objp->object_type == SESSION_PRIVATE)) {
10517c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&soft_giant_mutex);
10527c478bd9Sstevel@tonic-gate 			return (CKR_PIN_EXPIRED);
10537c478bd9Sstevel@tonic-gate 		}
10547c478bd9Sstevel@tonic-gate 	}
10557c478bd9Sstevel@tonic-gate 
10567c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_giant_mutex);
10577c478bd9Sstevel@tonic-gate 	return (CKR_OK);
10587c478bd9Sstevel@tonic-gate }
10597c478bd9Sstevel@tonic-gate 
10607c478bd9Sstevel@tonic-gate /*
10617c478bd9Sstevel@tonic-gate  * Copy the selected fields from new token object to old
10627c478bd9Sstevel@tonic-gate  * token object.
10637c478bd9Sstevel@tonic-gate  */
10647c478bd9Sstevel@tonic-gate CK_RV
10657c478bd9Sstevel@tonic-gate soft_copy_to_old_object(soft_object_t *new, soft_object_t *old)
10667c478bd9Sstevel@tonic-gate {
10677c478bd9Sstevel@tonic-gate 
10687c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
10697c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE_INFO_PTR attrp;
10707c478bd9Sstevel@tonic-gate 
10717c478bd9Sstevel@tonic-gate 	old->class = new->class;
10727c478bd9Sstevel@tonic-gate 	old->bool_attr_mask = new->bool_attr_mask;
10737c478bd9Sstevel@tonic-gate 	soft_cleanup_extra_attr(old);
10747c478bd9Sstevel@tonic-gate 	attrp = new->extra_attrlistp;
10757c478bd9Sstevel@tonic-gate 	while (attrp) {
10767c478bd9Sstevel@tonic-gate 		rv = soft_copy_extra_attr(attrp, old);
10777c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
10787c478bd9Sstevel@tonic-gate 			soft_cleanup_extra_attr(old);
10797c478bd9Sstevel@tonic-gate 			return (rv);
10807c478bd9Sstevel@tonic-gate 		}
10817c478bd9Sstevel@tonic-gate 		attrp = attrp->next;
10827c478bd9Sstevel@tonic-gate 	}
10837c478bd9Sstevel@tonic-gate 
10847c478bd9Sstevel@tonic-gate 	/* Done with copying all information that can be modified */
10857c478bd9Sstevel@tonic-gate 	return (CKR_OK);
10867c478bd9Sstevel@tonic-gate }
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate /*
10897c478bd9Sstevel@tonic-gate  * Update an existing object with new data from keystore.
10907c478bd9Sstevel@tonic-gate  */
10917c478bd9Sstevel@tonic-gate CK_RV
10927c478bd9Sstevel@tonic-gate soft_update_object(ks_obj_t *ks_obj, soft_object_t *old_obj)
10937c478bd9Sstevel@tonic-gate {
10947c478bd9Sstevel@tonic-gate 
10957c478bd9Sstevel@tonic-gate 	soft_object_t *new_object;
10967c478bd9Sstevel@tonic-gate 	CK_RV rv;
10977c478bd9Sstevel@tonic-gate 
10987c478bd9Sstevel@tonic-gate 	new_object = calloc(1, sizeof (soft_object_t));
10997c478bd9Sstevel@tonic-gate 	if (new_object == NULL)
11007c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
11017c478bd9Sstevel@tonic-gate 
11027c478bd9Sstevel@tonic-gate 	rv = soft_keystore_unpack_obj(new_object, ks_obj);
11037c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
11047c478bd9Sstevel@tonic-gate 		soft_cleanup_object(new_object);
11057c478bd9Sstevel@tonic-gate 		free(new_object);
11067c478bd9Sstevel@tonic-gate 		return (rv);
11077c478bd9Sstevel@tonic-gate 	}
11087c478bd9Sstevel@tonic-gate 	rv = soft_copy_to_old_object(new_object, old_obj);
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 	soft_cleanup_object(new_object);
11117c478bd9Sstevel@tonic-gate 	free(new_object);
11127c478bd9Sstevel@tonic-gate 	return (CKR_OK);
11137c478bd9Sstevel@tonic-gate }
11147c478bd9Sstevel@tonic-gate 
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate CK_RV
11177c478bd9Sstevel@tonic-gate soft_keystore_load_latest_object(soft_object_t *old_obj)
11187c478bd9Sstevel@tonic-gate {
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate 	uint_t version;
11217c478bd9Sstevel@tonic-gate 	ks_obj_t *ks_obj = NULL;
11227c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
11237c478bd9Sstevel@tonic-gate 
11247c478bd9Sstevel@tonic-gate 	/*
11257c478bd9Sstevel@tonic-gate 	 * Get the current version number from the keystore for
11267c478bd9Sstevel@tonic-gate 	 * the specified token object.
11277c478bd9Sstevel@tonic-gate 	 */
11287c478bd9Sstevel@tonic-gate 	if (soft_keystore_get_object_version(&old_obj->ks_handle, &version,
11297c478bd9Sstevel@tonic-gate 	    B_FALSE) == 1)
11307c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
11317c478bd9Sstevel@tonic-gate 
11327c478bd9Sstevel@tonic-gate 	/*
11337c478bd9Sstevel@tonic-gate 	 * If the keystore version is newer than the in-core version,
11347c478bd9Sstevel@tonic-gate 	 * re-read the token object from the keystore.
11357c478bd9Sstevel@tonic-gate 	 */
11367c478bd9Sstevel@tonic-gate 	if (old_obj->version != version) {
11377c478bd9Sstevel@tonic-gate 		rv = soft_keystore_get_single_obj(&old_obj->ks_handle,
11387c478bd9Sstevel@tonic-gate 		    &ks_obj, B_FALSE);
11397c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
11407c478bd9Sstevel@tonic-gate 			return (rv);
11417c478bd9Sstevel@tonic-gate 		old_obj->version = version;
11427c478bd9Sstevel@tonic-gate 
11437c478bd9Sstevel@tonic-gate 		/*
11447c478bd9Sstevel@tonic-gate 		 * Update an existing object with new data from keystore.
11457c478bd9Sstevel@tonic-gate 		 */
11467c478bd9Sstevel@tonic-gate 		rv = soft_update_object(ks_obj, old_obj);
11477c478bd9Sstevel@tonic-gate 		free(ks_obj->buf);
11487c478bd9Sstevel@tonic-gate 		free(ks_obj);
11497c478bd9Sstevel@tonic-gate 	}
11507c478bd9Sstevel@tonic-gate 
11517c478bd9Sstevel@tonic-gate 	return (rv);
11527c478bd9Sstevel@tonic-gate }
11537c478bd9Sstevel@tonic-gate 
11547c478bd9Sstevel@tonic-gate /*
11557c478bd9Sstevel@tonic-gate  * Insert an object into a list of soft_object_t objects.  It is assumed
11567c478bd9Sstevel@tonic-gate  * that the object to be inserted doesn't previously belong to any list
11577c478bd9Sstevel@tonic-gate  */
11587c478bd9Sstevel@tonic-gate static void
11597c478bd9Sstevel@tonic-gate insert_into_list(soft_object_t **list, soft_object_t **end_of_list,
11607c478bd9Sstevel@tonic-gate     soft_object_t *objp)
11617c478bd9Sstevel@tonic-gate {
11627c478bd9Sstevel@tonic-gate 	if (*list == NULL) {
11637c478bd9Sstevel@tonic-gate 		*list = objp;
11647c478bd9Sstevel@tonic-gate 		objp->next = NULL;
11657c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
11667c478bd9Sstevel@tonic-gate 		*end_of_list = objp;
11677c478bd9Sstevel@tonic-gate 	} else {
11687c478bd9Sstevel@tonic-gate 		(*list)->prev = objp;
11697c478bd9Sstevel@tonic-gate 		objp->next = *list;
11707c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
11717c478bd9Sstevel@tonic-gate 		*list = objp;
11727c478bd9Sstevel@tonic-gate 	}
11737c478bd9Sstevel@tonic-gate }
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate /*
11767c478bd9Sstevel@tonic-gate  * Move an object from an existing list into a new list of
11777c478bd9Sstevel@tonic-gate  * soft_object_t objects.
11787c478bd9Sstevel@tonic-gate  */
11797c478bd9Sstevel@tonic-gate static void
11807c478bd9Sstevel@tonic-gate move_into_list(soft_object_t **existing_list, soft_object_t **new_list,
11817c478bd9Sstevel@tonic-gate     soft_object_t **end_of_list, soft_object_t *objp)
11827c478bd9Sstevel@tonic-gate {
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	/* first, remove object from existing list */
11857c478bd9Sstevel@tonic-gate 	if (objp == *existing_list) {
11867c478bd9Sstevel@tonic-gate 		/* first item in list */
11877c478bd9Sstevel@tonic-gate 		if (objp->next) {
11887c478bd9Sstevel@tonic-gate 			*existing_list = objp->next;
11897c478bd9Sstevel@tonic-gate 			objp->next->prev = NULL;
11907c478bd9Sstevel@tonic-gate 		} else {
11917c478bd9Sstevel@tonic-gate 			*existing_list = NULL;
11927c478bd9Sstevel@tonic-gate 		}
11937c478bd9Sstevel@tonic-gate 	} else {
11947c478bd9Sstevel@tonic-gate 		if (objp->next) {
11957c478bd9Sstevel@tonic-gate 			objp->prev->next = objp->next;
11967c478bd9Sstevel@tonic-gate 			objp->next->prev = objp->prev;
11977c478bd9Sstevel@tonic-gate 		} else {
11987c478bd9Sstevel@tonic-gate 			objp->prev->next = NULL;
11997c478bd9Sstevel@tonic-gate 		}
12007c478bd9Sstevel@tonic-gate 	}
12017c478bd9Sstevel@tonic-gate 
12027c478bd9Sstevel@tonic-gate 	/* then, add into new list */
12037c478bd9Sstevel@tonic-gate 	insert_into_list(new_list, end_of_list, objp);
12047c478bd9Sstevel@tonic-gate }
12057c478bd9Sstevel@tonic-gate 
12067c478bd9Sstevel@tonic-gate /*
12077c478bd9Sstevel@tonic-gate  * Insert "new_list" into "existing_list", new list will always be inserted
12087c478bd9Sstevel@tonic-gate  * into the front of existing list
12097c478bd9Sstevel@tonic-gate  */
12107c478bd9Sstevel@tonic-gate static void
12117c478bd9Sstevel@tonic-gate insert_list_into_list(soft_object_t **existing_list,
12127c478bd9Sstevel@tonic-gate     soft_object_t *new_list, soft_object_t *end_new_list)
12137c478bd9Sstevel@tonic-gate {
12147c478bd9Sstevel@tonic-gate 
12157c478bd9Sstevel@tonic-gate 	if (new_list == NULL) {
12167c478bd9Sstevel@tonic-gate 		return;
12177c478bd9Sstevel@tonic-gate 	}
12187c478bd9Sstevel@tonic-gate 
12197c478bd9Sstevel@tonic-gate 	if (*existing_list == NULL) {
12207c478bd9Sstevel@tonic-gate 		*existing_list = new_list;
12217c478bd9Sstevel@tonic-gate 	} else {
12227c478bd9Sstevel@tonic-gate 		(*existing_list)->prev = end_new_list;
12237c478bd9Sstevel@tonic-gate 		end_new_list->next = *existing_list;
12247c478bd9Sstevel@tonic-gate 		*existing_list = new_list;
12257c478bd9Sstevel@tonic-gate 	}
12267c478bd9Sstevel@tonic-gate }
12277c478bd9Sstevel@tonic-gate 
12287c478bd9Sstevel@tonic-gate static void
12297c478bd9Sstevel@tonic-gate delete_all_objs_in_list(soft_object_t *list)
12307c478bd9Sstevel@tonic-gate {
12317c478bd9Sstevel@tonic-gate 	soft_object_t *objp, *objp_next;
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 	if (list == NULL) {
12347c478bd9Sstevel@tonic-gate 		return;
12357c478bd9Sstevel@tonic-gate 	}
12367c478bd9Sstevel@tonic-gate 
12377c478bd9Sstevel@tonic-gate 	objp = list;
12387c478bd9Sstevel@tonic-gate 	while (objp) {
12397c478bd9Sstevel@tonic-gate 		objp_next = objp->next;
12401f49a79aSZdenek Kotala 		soft_delete_object_cleanup(objp, B_FALSE);
12417c478bd9Sstevel@tonic-gate 		objp = objp_next;
12427c478bd9Sstevel@tonic-gate 	}
12437c478bd9Sstevel@tonic-gate }
12447c478bd9Sstevel@tonic-gate 
12457c478bd9Sstevel@tonic-gate /*
12467c478bd9Sstevel@tonic-gate  * Makes sure that the list of in-core token objects are up to date
12477c478bd9Sstevel@tonic-gate  * with respect to the on disk keystore.  Other process/applications
12487c478bd9Sstevel@tonic-gate  * might have modified the keystore since the objects are last loaded
12497c478bd9Sstevel@tonic-gate  *
12507c478bd9Sstevel@tonic-gate  * If there's any error from refreshing the token object list (eg: unable
12517c478bd9Sstevel@tonic-gate  * to read, unable to unpack and object...etc), the in-core list
12527c478bd9Sstevel@tonic-gate  * will be restored back to the state before the refresh.  An error
12537c478bd9Sstevel@tonic-gate  * will be returned to indicate the failure.
12547c478bd9Sstevel@tonic-gate  *
12557c478bd9Sstevel@tonic-gate  * It is assumed that the caller holds the lock for the token slot
12567c478bd9Sstevel@tonic-gate  */
12577c478bd9Sstevel@tonic-gate CK_RV
12587c478bd9Sstevel@tonic-gate refresh_token_objects()
12597c478bd9Sstevel@tonic-gate {
12607c478bd9Sstevel@tonic-gate 	uint_t on_disk_ks_version;
12617c478bd9Sstevel@tonic-gate 	ks_obj_t *on_disk_list = NULL, *tmp_on_disk, *next_on_disk;
12627c478bd9Sstevel@tonic-gate 	soft_object_t *in_core_obj, *tmp_incore_obj, *new_objp = NULL;
12637c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
12647c478bd9Sstevel@tonic-gate 
12657c478bd9Sstevel@tonic-gate 	/* deleted in-core objects */
1266c2e31228SViswanathan Kannappan 	soft_object_t *del_objs_list = NULL;
1267c2e31228SViswanathan Kannappan 	soft_object_t *end_del_objs_list = NULL;
12687c478bd9Sstevel@tonic-gate 
12697c478bd9Sstevel@tonic-gate 	/* modified in-core objects */
1270c2e31228SViswanathan Kannappan 	soft_object_t *mod_objs_list = NULL;
1271c2e31228SViswanathan Kannappan 	soft_object_t *end_mod_objs_list = NULL;
12727c478bd9Sstevel@tonic-gate 
12737c478bd9Sstevel@tonic-gate 	/*
12747c478bd9Sstevel@tonic-gate 	 * copy of modified in-core objects, in case we need
12757c478bd9Sstevel@tonic-gate 	 * undo the change
12767c478bd9Sstevel@tonic-gate 	 */
1277c2e31228SViswanathan Kannappan 	soft_object_t *copy_of_mod_objs_list = NULL;
1278c2e31228SViswanathan Kannappan 	soft_object_t *end_copy_of_mod_objs_list = NULL;
12797c478bd9Sstevel@tonic-gate 
12807c478bd9Sstevel@tonic-gate 	/* objects to be added to the in-core list */
1281c2e31228SViswanathan Kannappan 	soft_object_t *added_objs_list = NULL;
1282c2e31228SViswanathan Kannappan 	soft_object_t *end_added_objs_list = NULL;
12837c478bd9Sstevel@tonic-gate 
12847c478bd9Sstevel@tonic-gate 	if (soft_keystore_get_version(&on_disk_ks_version, B_FALSE) != 0) {
12857c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
12867c478bd9Sstevel@tonic-gate 	}
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_giant_mutex);
12897c478bd9Sstevel@tonic-gate 	if (on_disk_ks_version == soft_slot.ks_version) {
12907c478bd9Sstevel@tonic-gate 		/* no change */
12917c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
12927c478bd9Sstevel@tonic-gate 		return (CKR_OK);
12937c478bd9Sstevel@tonic-gate 	}
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	if (soft_slot.authenticated) {
12967c478bd9Sstevel@tonic-gate 		/* get both public and private objects */
12977c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
12987c478bd9Sstevel@tonic-gate 		rv = soft_keystore_get_objs(ALL_TOKENOBJS, &on_disk_list,
12997c478bd9Sstevel@tonic-gate 		    B_FALSE);
13007c478bd9Sstevel@tonic-gate 	} else {
13017c478bd9Sstevel@tonic-gate 		/* get both public objects only */
13027c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
13037c478bd9Sstevel@tonic-gate 		rv = soft_keystore_get_objs(PUB_TOKENOBJS, &on_disk_list,
13047c478bd9Sstevel@tonic-gate 		    B_FALSE);
13057c478bd9Sstevel@tonic-gate 	}
13067c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
13077c478bd9Sstevel@tonic-gate 		return (rv);
13087c478bd9Sstevel@tonic-gate 	}
13097c478bd9Sstevel@tonic-gate 
13107c478bd9Sstevel@tonic-gate 	/*
13117c478bd9Sstevel@tonic-gate 	 * The in-core tokens list will be updated as follows:
13127c478bd9Sstevel@tonic-gate 	 *
13137c478bd9Sstevel@tonic-gate 	 * Go through each item in the in-core tokens list.
13147c478bd9Sstevel@tonic-gate 	 * Try to match the in-core object with one of the
13157c478bd9Sstevel@tonic-gate 	 * objects from the on-disk list.  If a match is made,
13167c478bd9Sstevel@tonic-gate 	 * check the version number, and update in-core object
13177c478bd9Sstevel@tonic-gate 	 * as necessary.
13187c478bd9Sstevel@tonic-gate 	 *
13197c478bd9Sstevel@tonic-gate 	 * If there's no match between in-core object with on-disk
13207c478bd9Sstevel@tonic-gate 	 * object, that means the object is deleted since
13217c478bd9Sstevel@tonic-gate 	 * last loaded.  Will remove object from in-core list.
13227c478bd9Sstevel@tonic-gate 	 *
13237c478bd9Sstevel@tonic-gate 	 * When doing the matching of on-disk object list above,
13247c478bd9Sstevel@tonic-gate 	 * Delete every matched on-disk object from the on-disk list
13257c478bd9Sstevel@tonic-gate 	 * regardless the in-core object need to be deleted or not
13267c478bd9Sstevel@tonic-gate 	 *
13277c478bd9Sstevel@tonic-gate 	 * At the end of matching the in-core tokens list, if
13287c478bd9Sstevel@tonic-gate 	 * any object is still left on the on-disk object list,
13297c478bd9Sstevel@tonic-gate 	 * those are all new objects added since last load,
13307c478bd9Sstevel@tonic-gate 	 * include all of them to the in-core list
13317c478bd9Sstevel@tonic-gate 	 *
13327c478bd9Sstevel@tonic-gate 	 * Since we need to be able to revert the in-core list
13337c478bd9Sstevel@tonic-gate 	 * back to original state if there's any error with the refresh,
13347c478bd9Sstevel@tonic-gate 	 * we need to do the following.
13357c478bd9Sstevel@tonic-gate 	 * When an in-core object is "deleted", it is not immediately
13367c478bd9Sstevel@tonic-gate 	 * deleted.  It is moved to the list of "deleted_objects".
13377c478bd9Sstevel@tonic-gate 	 * When an in-core object is "modified", a copy of the
13387c478bd9Sstevel@tonic-gate 	 * unmodified object is made.  After the object is modified,
13397c478bd9Sstevel@tonic-gate 	 * it is temporarily moved to the "mod_objects" list
13407c478bd9Sstevel@tonic-gate 	 * from the in-core list.
13417c478bd9Sstevel@tonic-gate 	 * When the refresh is completed without any error,
13427c478bd9Sstevel@tonic-gate 	 * the actual deleted objects and unmodified objects is deleted.
13437c478bd9Sstevel@tonic-gate 	 */
13447c478bd9Sstevel@tonic-gate 	in_core_obj = soft_slot.token_object_list;
13457c478bd9Sstevel@tonic-gate 	while (in_core_obj) {
13467c478bd9Sstevel@tonic-gate 		/* try to match object with on_disk_list */
13477c478bd9Sstevel@tonic-gate 		ks_obj_t *ondisk_obj, *prev_ondisk_obj;
13487c478bd9Sstevel@tonic-gate 		boolean_t found = B_FALSE;
13497c478bd9Sstevel@tonic-gate 		soft_object_t *obj_copy;
13507c478bd9Sstevel@tonic-gate 
13517c478bd9Sstevel@tonic-gate 		ondisk_obj = on_disk_list;
13527c478bd9Sstevel@tonic-gate 		prev_ondisk_obj = NULL;
13537c478bd9Sstevel@tonic-gate 
13544d25c1d6Smcpowers 		/* larval object that has not been written to disk */
13554d25c1d6Smcpowers 		if (in_core_obj->ks_handle.name[0] == '\0') {
13564d25c1d6Smcpowers 			in_core_obj = in_core_obj->next;
13574d25c1d6Smcpowers 			continue;
13584d25c1d6Smcpowers 		}
13594d25c1d6Smcpowers 
13607c478bd9Sstevel@tonic-gate 		while ((!found) && (ondisk_obj != NULL)) {
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 			if (strcmp((char *)((ondisk_obj->ks_handle).name),
13637c478bd9Sstevel@tonic-gate 			    (char *)((in_core_obj->ks_handle).name)) == 0) {
13647c478bd9Sstevel@tonic-gate 
13657c478bd9Sstevel@tonic-gate 				/* found a match */
13667c478bd9Sstevel@tonic-gate 				found = B_TRUE;
13677c478bd9Sstevel@tonic-gate 
13687c478bd9Sstevel@tonic-gate 				/* update in-core obj if necessary */
13697c478bd9Sstevel@tonic-gate 				if (ondisk_obj->obj_version !=
13707c478bd9Sstevel@tonic-gate 				    in_core_obj->version) {
13717c478bd9Sstevel@tonic-gate 					/* make a copy of before updating */
13727c478bd9Sstevel@tonic-gate 					rv = soft_copy_object(in_core_obj,
13737c478bd9Sstevel@tonic-gate 					    &obj_copy, SOFT_COPY_OBJ_ORIG_SH,
13747c478bd9Sstevel@tonic-gate 					    NULL);
13757c478bd9Sstevel@tonic-gate 					if (rv != CKR_OK) {
13767c478bd9Sstevel@tonic-gate 						goto cleanup;
13777c478bd9Sstevel@tonic-gate 					}
13787c478bd9Sstevel@tonic-gate 					insert_into_list(
13797c478bd9Sstevel@tonic-gate 					    &copy_of_mod_objs_list,
13807c478bd9Sstevel@tonic-gate 					    &end_copy_of_mod_objs_list,
13817c478bd9Sstevel@tonic-gate 					    obj_copy);
13827c478bd9Sstevel@tonic-gate 
13837c478bd9Sstevel@tonic-gate 					rv = soft_update_object(ondisk_obj,
13847c478bd9Sstevel@tonic-gate 					    in_core_obj);
13857c478bd9Sstevel@tonic-gate 					if (rv != CKR_OK) {
13867c478bd9Sstevel@tonic-gate 						goto cleanup;
13877c478bd9Sstevel@tonic-gate 					}
13887c478bd9Sstevel@tonic-gate 					move_into_list(
13897c478bd9Sstevel@tonic-gate 					    &(soft_slot.token_object_list),
13907c478bd9Sstevel@tonic-gate 					    &mod_objs_list, &end_mod_objs_list,
13917c478bd9Sstevel@tonic-gate 					    in_core_obj);
13927c478bd9Sstevel@tonic-gate 				}
13937c478bd9Sstevel@tonic-gate 
13947c478bd9Sstevel@tonic-gate 				/* remove processed obj from on disk list */
13957c478bd9Sstevel@tonic-gate 				if (ondisk_obj == on_disk_list) {
13967c478bd9Sstevel@tonic-gate 					/* first item */
13977c478bd9Sstevel@tonic-gate 					on_disk_list = ondisk_obj->next;
13987c478bd9Sstevel@tonic-gate 				} else {
13997c478bd9Sstevel@tonic-gate 					prev_ondisk_obj->next =
14007c478bd9Sstevel@tonic-gate 					    ondisk_obj->next;
14017c478bd9Sstevel@tonic-gate 				}
14027c478bd9Sstevel@tonic-gate 				free(ondisk_obj->buf);
14037c478bd9Sstevel@tonic-gate 				free(ondisk_obj);
14047c478bd9Sstevel@tonic-gate 			} else {
14057c478bd9Sstevel@tonic-gate 				prev_ondisk_obj = ondisk_obj;
14067c478bd9Sstevel@tonic-gate 				ondisk_obj = ondisk_obj->next;
14077c478bd9Sstevel@tonic-gate 			}
14087c478bd9Sstevel@tonic-gate 		}
14097c478bd9Sstevel@tonic-gate 
14107c478bd9Sstevel@tonic-gate 		if (!found) {
14117c478bd9Sstevel@tonic-gate 			tmp_incore_obj = in_core_obj->next;
14127c478bd9Sstevel@tonic-gate 			move_into_list(&(soft_slot.token_object_list),
14137c478bd9Sstevel@tonic-gate 			    &del_objs_list, &end_del_objs_list, in_core_obj);
14147c478bd9Sstevel@tonic-gate 			in_core_obj = tmp_incore_obj;
14157c478bd9Sstevel@tonic-gate 		} else {
14167c478bd9Sstevel@tonic-gate 			in_core_obj = in_core_obj->next;
14177c478bd9Sstevel@tonic-gate 		}
14187c478bd9Sstevel@tonic-gate 	}
14197c478bd9Sstevel@tonic-gate 
14207c478bd9Sstevel@tonic-gate 	/*
14217c478bd9Sstevel@tonic-gate 	 * At this point, if there's still anything on the on_disk_list, they
14227c478bd9Sstevel@tonic-gate 	 * are all newly added objects since in-core list last loaded.
14237c478bd9Sstevel@tonic-gate 	 * include all of them into the in-core list
14247c478bd9Sstevel@tonic-gate 	 */
14257c478bd9Sstevel@tonic-gate 	next_on_disk = on_disk_list;
14267c478bd9Sstevel@tonic-gate 	while (next_on_disk) {
14277c478bd9Sstevel@tonic-gate 		new_objp = calloc(1, sizeof (soft_object_t));
14287c478bd9Sstevel@tonic-gate 		if (new_objp == NULL) {
14297c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
14307c478bd9Sstevel@tonic-gate 			goto cleanup;
14317c478bd9Sstevel@tonic-gate 		}
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate 		/* Convert the keystore format to memory format */
14347c478bd9Sstevel@tonic-gate 		rv = soft_keystore_unpack_obj(new_objp, next_on_disk);
14357c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
14367c478bd9Sstevel@tonic-gate 			soft_cleanup_object(new_objp);
14377c478bd9Sstevel@tonic-gate 			free(new_objp);
14387c478bd9Sstevel@tonic-gate 			goto cleanup;
14397c478bd9Sstevel@tonic-gate 		}
14407c478bd9Sstevel@tonic-gate 
14417c478bd9Sstevel@tonic-gate 		insert_into_list(&added_objs_list, &end_added_objs_list,
14427c478bd9Sstevel@tonic-gate 		    new_objp);
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 		/* free the on_disk object */
14457c478bd9Sstevel@tonic-gate 		tmp_on_disk = next_on_disk;
14467c478bd9Sstevel@tonic-gate 		next_on_disk = tmp_on_disk->next;
14477c478bd9Sstevel@tonic-gate 		free(tmp_on_disk->buf);
14487c478bd9Sstevel@tonic-gate 		free(tmp_on_disk);
14497c478bd9Sstevel@tonic-gate 	}
14507c478bd9Sstevel@tonic-gate 
14517c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
14527c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&soft_giant_mutex);
14537c478bd9Sstevel@tonic-gate 		soft_slot.ks_version = on_disk_ks_version;
14547c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
14557c478bd9Sstevel@tonic-gate 
14567c478bd9Sstevel@tonic-gate 		/* add the new objects into in-core list */
14577c478bd9Sstevel@tonic-gate 		insert_list_into_list(&(soft_slot.token_object_list),
14587c478bd9Sstevel@tonic-gate 		    added_objs_list, end_added_objs_list);
14597c478bd9Sstevel@tonic-gate 
14607c478bd9Sstevel@tonic-gate 		/* add modified objects back into the in-core list */
14617c478bd9Sstevel@tonic-gate 		insert_list_into_list(&(soft_slot.token_object_list),
14627c478bd9Sstevel@tonic-gate 		    mod_objs_list, end_mod_objs_list);
14637c478bd9Sstevel@tonic-gate 
14647c478bd9Sstevel@tonic-gate 		/* actually remove deleted objs, and copy of modified objs */
14657c478bd9Sstevel@tonic-gate 		delete_all_objs_in_list(copy_of_mod_objs_list);
14667c478bd9Sstevel@tonic-gate 		delete_all_objs_in_list(del_objs_list);
14677c478bd9Sstevel@tonic-gate 	}
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate 	return (rv);
14707c478bd9Sstevel@tonic-gate 
14717c478bd9Sstevel@tonic-gate cleanup:
14727c478bd9Sstevel@tonic-gate 	next_on_disk = on_disk_list;
14737c478bd9Sstevel@tonic-gate 	while (next_on_disk) {
14747c478bd9Sstevel@tonic-gate 		tmp_on_disk = next_on_disk;
14757c478bd9Sstevel@tonic-gate 		next_on_disk = tmp_on_disk->next;
14767c478bd9Sstevel@tonic-gate 		free(tmp_on_disk->buf);
14777c478bd9Sstevel@tonic-gate 		free(tmp_on_disk);
14787c478bd9Sstevel@tonic-gate 	}
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	/*
14817c478bd9Sstevel@tonic-gate 	 * restore the in-core list back to the original state by adding
14827c478bd9Sstevel@tonic-gate 	 * copy of original objects and deleted objects back to list
14837c478bd9Sstevel@tonic-gate 	 */
14847c478bd9Sstevel@tonic-gate 	insert_list_into_list(&(soft_slot.token_object_list),
14857c478bd9Sstevel@tonic-gate 	    del_objs_list, end_del_objs_list);
14867c478bd9Sstevel@tonic-gate 	insert_list_into_list(&(soft_slot.token_object_list),
14877c478bd9Sstevel@tonic-gate 	    copy_of_mod_objs_list, end_copy_of_mod_objs_list);
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 	/*
14907c478bd9Sstevel@tonic-gate 	 * remove the modified objects, and newly objects list
14917c478bd9Sstevel@tonic-gate 	 */
14927c478bd9Sstevel@tonic-gate 	delete_all_objs_in_list(mod_objs_list);
14937c478bd9Sstevel@tonic-gate 	delete_all_objs_in_list(added_objs_list);
14947c478bd9Sstevel@tonic-gate 	return (rv);
14957c478bd9Sstevel@tonic-gate }
1496*726fad2aSDina K Nimeh 
1497*726fad2aSDina K Nimeh CK_RV
1498*726fad2aSDina K Nimeh dup_bigint_attr(biginteger_t *bi, CK_BYTE *buf, CK_ULONG buflen)
1499*726fad2aSDina K Nimeh {
1500*726fad2aSDina K Nimeh 	bi->big_value_len = buflen;
1501*726fad2aSDina K Nimeh 	if ((bi->big_value = malloc(buflen)) == NULL) {
1502*726fad2aSDina K Nimeh 		return (CKR_HOST_MEMORY);
1503*726fad2aSDina K Nimeh 	}
1504*726fad2aSDina K Nimeh 	(void) memcpy(bi->big_value, buf, buflen);
1505*726fad2aSDina K Nimeh 	return (CKR_OK);
1506*726fad2aSDina K Nimeh }
1507