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  */
21726fad2aSDina K Nimeh 
227c478bd9Sstevel@tonic-gate /*
23726fad2aSDina K Nimeh  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*cfcec266SJason King  * Copyright 2020 Joyent, Inc.
257c478bd9Sstevel@tonic-gate  */
267c478bd9Sstevel@tonic-gate 
277c478bd9Sstevel@tonic-gate #include <pthread.h>
287c478bd9Sstevel@tonic-gate #include <stdio.h>
297c478bd9Sstevel@tonic-gate #include <stdlib.h>
307c478bd9Sstevel@tonic-gate #include <string.h>
317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
32*cfcec266SJason King #include <sys/debug.h>
337c478bd9Sstevel@tonic-gate #include "softGlobal.h"
347c478bd9Sstevel@tonic-gate #include "softObject.h"
357c478bd9Sstevel@tonic-gate #include "softSession.h"
367c478bd9Sstevel@tonic-gate #include "softKeystore.h"
377c478bd9Sstevel@tonic-gate #include "softKeystoreUtil.h"
387c478bd9Sstevel@tonic-gate 
397c478bd9Sstevel@tonic-gate /*
407c478bd9Sstevel@tonic-gate  * Add an object to the session's object list.
417c478bd9Sstevel@tonic-gate  *
427c478bd9Sstevel@tonic-gate  * This function will acquire the lock on the session, and release
437c478bd9Sstevel@tonic-gate  * that lock after adding the object to the session's object list.
447c478bd9Sstevel@tonic-gate  */
457c478bd9Sstevel@tonic-gate void
soft_add_object_to_session(soft_object_t * objp,soft_session_t * sp)467c478bd9Sstevel@tonic-gate soft_add_object_to_session(soft_object_t *objp, soft_session_t *sp)
477c478bd9Sstevel@tonic-gate {
487c478bd9Sstevel@tonic-gate 
497c478bd9Sstevel@tonic-gate 	/* Acquire the session lock. */
507c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&sp->session_mutex);
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate 	/* Insert the new object in front of session's object list. */
537c478bd9Sstevel@tonic-gate 	if (sp->object_list == NULL) {
547c478bd9Sstevel@tonic-gate 		sp->object_list = objp;
557c478bd9Sstevel@tonic-gate 		objp->next = NULL;
567c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
577c478bd9Sstevel@tonic-gate 	} else {
587c478bd9Sstevel@tonic-gate 		sp->object_list->prev = objp;
597c478bd9Sstevel@tonic-gate 		objp->next = sp->object_list;
607c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
617c478bd9Sstevel@tonic-gate 		sp->object_list = objp;
627c478bd9Sstevel@tonic-gate 	}
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate 	/* Release the session lock. */
657c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&sp->session_mutex);
667c478bd9Sstevel@tonic-gate }
677c478bd9Sstevel@tonic-gate 
687c478bd9Sstevel@tonic-gate 
697c478bd9Sstevel@tonic-gate /*
707c478bd9Sstevel@tonic-gate  * Clean up and release the storage allocated to the object.
717c478bd9Sstevel@tonic-gate  *
727c478bd9Sstevel@tonic-gate  * The function is called either with the object lock being held
737c478bd9Sstevel@tonic-gate  * (by caller soft_delete_object()), or there is no object lock
747c478bd9Sstevel@tonic-gate  * yet (by soft_build_XXX_object() during creating an object).
757c478bd9Sstevel@tonic-gate  */
767c478bd9Sstevel@tonic-gate void
soft_cleanup_object(soft_object_t * objp)777c478bd9Sstevel@tonic-gate soft_cleanup_object(soft_object_t *objp)
787c478bd9Sstevel@tonic-gate {
797c478bd9Sstevel@tonic-gate 	/*
807c478bd9Sstevel@tonic-gate 	 * Free the storage allocated to big integer attributes.
817c478bd9Sstevel@tonic-gate 	 */
827c478bd9Sstevel@tonic-gate 	soft_cleanup_object_bigint_attrs(objp);
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 	/*
857c478bd9Sstevel@tonic-gate 	 * Free the storage allocated to the extra attribute list.
867c478bd9Sstevel@tonic-gate 	 */
877c478bd9Sstevel@tonic-gate 	soft_cleanup_extra_attr(objp);
887c478bd9Sstevel@tonic-gate 
897c478bd9Sstevel@tonic-gate 	/*
907c478bd9Sstevel@tonic-gate 	 * Free the storage allocated to certificate attributes.
917c478bd9Sstevel@tonic-gate 	 */
927c478bd9Sstevel@tonic-gate 	soft_cleanup_cert_object(objp);
937c478bd9Sstevel@tonic-gate }
947c478bd9Sstevel@tonic-gate 
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate /*
977c478bd9Sstevel@tonic-gate  * Create a new object. Copy the attributes that can be modified
987c478bd9Sstevel@tonic-gate  * (in the boolean attribute mask field and extra attribute list)
997c478bd9Sstevel@tonic-gate  * from the old object to the new object.
1007c478bd9Sstevel@tonic-gate  *
1017c478bd9Sstevel@tonic-gate  * The caller of this function holds the lock on the old object.
1027c478bd9Sstevel@tonic-gate  */
1037c478bd9Sstevel@tonic-gate CK_RV
soft_copy_object(soft_object_t * old_object,soft_object_t ** new_object,CK_ULONG object_func,soft_session_t * sp)1047c478bd9Sstevel@tonic-gate soft_copy_object(soft_object_t *old_object, soft_object_t **new_object,
1057c478bd9Sstevel@tonic-gate     CK_ULONG object_func, soft_session_t *sp)
1067c478bd9Sstevel@tonic-gate {
1077c478bd9Sstevel@tonic-gate 
1087c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1097c478bd9Sstevel@tonic-gate 	soft_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 (soft_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 	new_objp->cert_type = old_object->cert_type;
1207c478bd9Sstevel@tonic-gate 	new_objp->object_type = old_object->object_type;
1217c478bd9Sstevel@tonic-gate 
1227c478bd9Sstevel@tonic-gate 	attrp = old_object->extra_attrlistp;
1237c478bd9Sstevel@tonic-gate 	while (attrp) {
1247c478bd9Sstevel@tonic-gate 		/*
1257c478bd9Sstevel@tonic-gate 		 * Copy the attribute_info struct from the old
1267c478bd9Sstevel@tonic-gate 		 * object to a new attribute_info struct, and add
1277c478bd9Sstevel@tonic-gate 		 * that new struct to the extra attribute list
1287c478bd9Sstevel@tonic-gate 		 * of the new object.
1297c478bd9Sstevel@tonic-gate 		 */
1307c478bd9Sstevel@tonic-gate 		rv = soft_copy_extra_attr(attrp, new_objp);
1317c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1327c478bd9Sstevel@tonic-gate 			soft_cleanup_extra_attr(new_objp);
1337c478bd9Sstevel@tonic-gate 			free(new_objp);
1347c478bd9Sstevel@tonic-gate 			return (rv);
1357c478bd9Sstevel@tonic-gate 		}
1367c478bd9Sstevel@tonic-gate 		attrp = attrp->next;
1377c478bd9Sstevel@tonic-gate 	}
1387c478bd9Sstevel@tonic-gate 
1397c478bd9Sstevel@tonic-gate 	*new_object = new_objp;
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 	if (object_func == SOFT_SET_ATTR_VALUE) {
1427c478bd9Sstevel@tonic-gate 		/* done with copying all information that can be modified */
1437c478bd9Sstevel@tonic-gate 		return (CKR_OK);
1447c478bd9Sstevel@tonic-gate 	}
1457c478bd9Sstevel@tonic-gate 
1467c478bd9Sstevel@tonic-gate 	/*
1477c478bd9Sstevel@tonic-gate 	 * Copy the rest of the object.
1487c478bd9Sstevel@tonic-gate 	 * Certain fields that are not appropriate for coping will be
1497c478bd9Sstevel@tonic-gate 	 * initialized.
1507c478bd9Sstevel@tonic-gate 	 */
1517c478bd9Sstevel@tonic-gate 	new_objp->key_type = old_object->key_type;
1527c478bd9Sstevel@tonic-gate 	new_objp->magic_marker = old_object->magic_marker;
1537c478bd9Sstevel@tonic-gate 	new_objp->mechanism = old_object->mechanism;
1547c478bd9Sstevel@tonic-gate 
1557c478bd9Sstevel@tonic-gate 	switch (object_func) {
1567c478bd9Sstevel@tonic-gate 	case SOFT_COPY_OBJ_ORIG_SH:
1577c478bd9Sstevel@tonic-gate 		new_objp->session_handle = old_object->session_handle;
1587c478bd9Sstevel@tonic-gate 		break;
1597c478bd9Sstevel@tonic-gate 	case SOFT_COPY_OBJECT:
1607c478bd9Sstevel@tonic-gate 		/*
1617c478bd9Sstevel@tonic-gate 		 * Save the session handle of the C_CopyObject function
1627c478bd9Sstevel@tonic-gate 		 * in the new copy of the session object.
1637c478bd9Sstevel@tonic-gate 		 */
164*cfcec266SJason King 		new_objp->session_handle = sp->handle;
1657c478bd9Sstevel@tonic-gate 		break;
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 
1687c478bd9Sstevel@tonic-gate 	(void) pthread_cond_init(&(new_objp->obj_free_cond), NULL);
1697c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&(new_objp->object_mutex), NULL);
1707c478bd9Sstevel@tonic-gate 	/* copy key related information */
1717c478bd9Sstevel@tonic-gate 	switch (new_objp->class) {
1727c478bd9Sstevel@tonic-gate 		case CKO_PUBLIC_KEY:
1737c478bd9Sstevel@tonic-gate 			rv = soft_copy_public_key_attr(OBJ_PUB(old_object),
1747c478bd9Sstevel@tonic-gate 			    &(OBJ_PUB(new_objp)), new_objp->key_type);
1757c478bd9Sstevel@tonic-gate 			break;
1767c478bd9Sstevel@tonic-gate 		case CKO_PRIVATE_KEY:
1777c478bd9Sstevel@tonic-gate 			rv = soft_copy_private_key_attr(OBJ_PRI(old_object),
1787c478bd9Sstevel@tonic-gate 			    &(OBJ_PRI(new_objp)), new_objp->key_type);
1797c478bd9Sstevel@tonic-gate 			break;
1807c478bd9Sstevel@tonic-gate 		case CKO_SECRET_KEY:
1817c478bd9Sstevel@tonic-gate 			rv = soft_copy_secret_key_attr(OBJ_SEC(old_object),
1827c478bd9Sstevel@tonic-gate 			    &(OBJ_SEC(new_objp)));
1837c478bd9Sstevel@tonic-gate 			break;
1847c478bd9Sstevel@tonic-gate 		case CKO_DOMAIN_PARAMETERS:
1857c478bd9Sstevel@tonic-gate 			rv = soft_copy_domain_attr(OBJ_DOM(old_object),
1867c478bd9Sstevel@tonic-gate 			    &(OBJ_DOM(new_objp)), new_objp->key_type);
1877c478bd9Sstevel@tonic-gate 			break;
1887c478bd9Sstevel@tonic-gate 		case CKO_CERTIFICATE:
1897c478bd9Sstevel@tonic-gate 			rv = soft_copy_certificate(OBJ_CERT(old_object),
1907c478bd9Sstevel@tonic-gate 			    &(OBJ_CERT(new_objp)), new_objp->cert_type);
1917c478bd9Sstevel@tonic-gate 			break;
1927c478bd9Sstevel@tonic-gate 		default:
1937c478bd9Sstevel@tonic-gate 			/* should never be this case */
1947c478bd9Sstevel@tonic-gate 			break;
1957c478bd9Sstevel@tonic-gate 	}
1967c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1977c478bd9Sstevel@tonic-gate 		/*
1987c478bd9Sstevel@tonic-gate 		 * don't need to cleanup the memory from failure of copying
1997c478bd9Sstevel@tonic-gate 		 * any key related stuff.  Each individual function for
2007c478bd9Sstevel@tonic-gate 		 * copying key attr will free the memory if it fails
2017c478bd9Sstevel@tonic-gate 		 */
2027c478bd9Sstevel@tonic-gate 		soft_cleanup_extra_attr(new_objp);
2037c478bd9Sstevel@tonic-gate 		free(new_objp);
2047c478bd9Sstevel@tonic-gate 	}
2057c478bd9Sstevel@tonic-gate 	return (rv);
2067c478bd9Sstevel@tonic-gate }
2077c478bd9Sstevel@tonic-gate 
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate /*
2107c478bd9Sstevel@tonic-gate  * Copy the attributes (in the boolean attribute mask field and
2117c478bd9Sstevel@tonic-gate  * extra attribute list) from the new object back to the original
2127c478bd9Sstevel@tonic-gate  * object. Also, clean up and release all the storage in the extra
2137c478bd9Sstevel@tonic-gate  * attribute list of the original object.
2147c478bd9Sstevel@tonic-gate  *
2157c478bd9Sstevel@tonic-gate  * The caller of this function holds the lock on the old object.
2167c478bd9Sstevel@tonic-gate  */
2177c478bd9Sstevel@tonic-gate void
soft_merge_object(soft_object_t * old_object,soft_object_t * new_object)2187c478bd9Sstevel@tonic-gate soft_merge_object(soft_object_t *old_object, soft_object_t *new_object)
2197c478bd9Sstevel@tonic-gate {
2207c478bd9Sstevel@tonic-gate 	old_object->bool_attr_mask = new_object->bool_attr_mask;
2217c478bd9Sstevel@tonic-gate 	soft_cleanup_extra_attr(old_object);
2227c478bd9Sstevel@tonic-gate 	old_object->extra_attrlistp = new_object->extra_attrlistp;
2237c478bd9Sstevel@tonic-gate }
2247c478bd9Sstevel@tonic-gate 
225*cfcec266SJason King /*
226*cfcec266SJason King  * Sets *object_p to the soft_object_t corresponding to hObject. If
227*cfcec266SJason King  * hObject is valid, and not in the deleting state, CKR_OK is returned,
228*cfcec266SJason King  * otherwise an error is returned. If hObject is valid and refhold is B_TRUE,
229*cfcec266SJason King  * the object is also held.
230*cfcec266SJason King  */
231*cfcec266SJason King CK_RV
handle2object(CK_OBJECT_HANDLE hObject,soft_object_t ** object_p,boolean_t refhold)232*cfcec266SJason King handle2object(CK_OBJECT_HANDLE hObject, soft_object_t **object_p,
233*cfcec266SJason King     boolean_t refhold)
234*cfcec266SJason King {
235*cfcec266SJason King 	soft_object_t *obj;
236*cfcec266SJason King 	soft_object_t node;
237*cfcec266SJason King 
238*cfcec266SJason King 	(void) memset(&node, 0, sizeof (node));
239*cfcec266SJason King 	node.handle = hObject;
240*cfcec266SJason King 
241*cfcec266SJason King 	VERIFY0(pthread_mutex_lock(&soft_object_mutex));
242*cfcec266SJason King 	if ((obj = avl_find(&soft_object_tree, &node, NULL)) == NULL ||
243*cfcec266SJason King 	    obj->magic_marker != SOFTTOKEN_OBJECT_MAGIC) {
244*cfcec266SJason King 		VERIFY0(pthread_mutex_unlock(&soft_object_mutex));
245*cfcec266SJason King 		return (CKR_OBJECT_HANDLE_INVALID);
246*cfcec266SJason King 	}
247*cfcec266SJason King 
248*cfcec266SJason King 	(void) pthread_mutex_lock(&obj->object_mutex);
249*cfcec266SJason King 	VERIFY0(pthread_mutex_unlock(&soft_object_mutex));
250*cfcec266SJason King 
251*cfcec266SJason King 	if (obj->obj_delete_sync & OBJECT_IS_DELETING) {
252*cfcec266SJason King 		(void) pthread_mutex_unlock(&obj->object_mutex);
253*cfcec266SJason King 		return (CKR_OBJECT_HANDLE_INVALID);
254*cfcec266SJason King 	}
255*cfcec266SJason King 
256*cfcec266SJason King 	if (refhold)
257*cfcec266SJason King 		obj->obj_refcnt++;
258*cfcec266SJason King 
259*cfcec266SJason King 	(void) pthread_mutex_unlock(&obj->object_mutex);
260*cfcec266SJason King 
261*cfcec266SJason King 	*object_p = obj;
262*cfcec266SJason King 	return (CKR_OK);
263*cfcec266SJason King }
264*cfcec266SJason King 
265*cfcec266SJason King CK_ULONG
set_objecthandle(soft_object_t * obj)266*cfcec266SJason King set_objecthandle(soft_object_t *obj)
267*cfcec266SJason King {
268*cfcec266SJason King 	avl_index_t where;
269*cfcec266SJason King 
270*cfcec266SJason King 	(void) pthread_mutex_lock(&soft_object_mutex);
271*cfcec266SJason King 
272*cfcec266SJason King 	do {
273*cfcec266SJason King 		arc4random_buf(&obj->handle, sizeof (obj->handle));
274*cfcec266SJason King 		if (obj->handle == CK_INVALID_HANDLE)
275*cfcec266SJason King 			continue;
276*cfcec266SJason King 	} while (avl_find(&soft_object_tree, obj, &where) != NULL);
277*cfcec266SJason King 
278*cfcec266SJason King 	avl_insert(&soft_object_tree, obj, where);
279*cfcec266SJason King 
280*cfcec266SJason King 	(void) pthread_mutex_unlock(&soft_object_mutex);
281*cfcec266SJason King 
282*cfcec266SJason King 	return (obj->handle);
283*cfcec266SJason King }
2847c478bd9Sstevel@tonic-gate 
2857c478bd9Sstevel@tonic-gate /*
2867c478bd9Sstevel@tonic-gate  * Create a new object struct, and add it to the session's object list.
2877c478bd9Sstevel@tonic-gate  */
2887c478bd9Sstevel@tonic-gate CK_RV
soft_add_object(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR objecthandle_p,soft_session_t * sp)2897c478bd9Sstevel@tonic-gate soft_add_object(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
290*cfcec266SJason King     CK_OBJECT_HANDLE_PTR objecthandle_p, soft_session_t *sp)
2917c478bd9Sstevel@tonic-gate {
2927c478bd9Sstevel@tonic-gate 
2937c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
2947c478bd9Sstevel@tonic-gate 	soft_object_t *new_objp = NULL;
2957c478bd9Sstevel@tonic-gate 
2967c478bd9Sstevel@tonic-gate 	new_objp = calloc(1, sizeof (soft_object_t));
2977c478bd9Sstevel@tonic-gate 	if (new_objp == NULL) {
2987c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2997c478bd9Sstevel@tonic-gate 	}
3007c478bd9Sstevel@tonic-gate 
3017c478bd9Sstevel@tonic-gate 	new_objp->extra_attrlistp = NULL;
3027c478bd9Sstevel@tonic-gate 
3037c478bd9Sstevel@tonic-gate 	/*
3047c478bd9Sstevel@tonic-gate 	 * Validate attribute template and fill in the attributes
3057c478bd9Sstevel@tonic-gate 	 * in the soft_object_t.
3067c478bd9Sstevel@tonic-gate 	 */
3077c478bd9Sstevel@tonic-gate 	rv = soft_build_object(pTemplate, ulCount, new_objp);
3087c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3097c478bd9Sstevel@tonic-gate 		goto fail_cleanup1;
3107c478bd9Sstevel@tonic-gate 	}
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	rv = soft_pin_expired_check(new_objp);
3137c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3147c478bd9Sstevel@tonic-gate 		goto fail_cleanup2;
3157c478bd9Sstevel@tonic-gate 	}
3167c478bd9Sstevel@tonic-gate 
3177c478bd9Sstevel@tonic-gate 	rv = soft_object_write_access_check(sp, new_objp);
3187c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3197c478bd9Sstevel@tonic-gate 		goto fail_cleanup2;
3207c478bd9Sstevel@tonic-gate 	}
3217c478bd9Sstevel@tonic-gate 
3227c478bd9Sstevel@tonic-gate 	/* Initialize the rest of stuffs in soft_object_t. */
3237c478bd9Sstevel@tonic-gate 	(void) pthread_cond_init(&new_objp->obj_free_cond, NULL);
3247c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
3257c478bd9Sstevel@tonic-gate 	new_objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
3267c478bd9Sstevel@tonic-gate 	new_objp->obj_refcnt = 0;
3277c478bd9Sstevel@tonic-gate 	new_objp->obj_delete_sync = 0;
3287c478bd9Sstevel@tonic-gate 
3297c478bd9Sstevel@tonic-gate 	/* Write the new token object to the keystore */
3307c478bd9Sstevel@tonic-gate 	if (IS_TOKEN_OBJECT(new_objp)) {
33190e0e8c4Sizick 		if (!soft_keystore_status(KEYSTORE_INITIALIZED)) {
33290e0e8c4Sizick 			rv = CKR_DEVICE_REMOVED;
33390e0e8c4Sizick 			goto fail_cleanup2;
33490e0e8c4Sizick 		}
3357c478bd9Sstevel@tonic-gate 		new_objp->version = 1;
3367c478bd9Sstevel@tonic-gate 		rv = soft_put_object_to_keystore(new_objp);
3377c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
3387c478bd9Sstevel@tonic-gate 			(void) pthread_cond_destroy(&new_objp->obj_free_cond);
3397c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_destroy(&new_objp->object_mutex);
3407c478bd9Sstevel@tonic-gate 			goto fail_cleanup2;
3417c478bd9Sstevel@tonic-gate 		}
342*cfcec266SJason King 		new_objp->session_handle = CK_INVALID_HANDLE;
3437c478bd9Sstevel@tonic-gate 		soft_add_token_object_to_slot(new_objp);
344*cfcec266SJason King 
345*cfcec266SJason King 		*objecthandle_p = set_objecthandle(new_objp);
3467c478bd9Sstevel@tonic-gate 
3477c478bd9Sstevel@tonic-gate 		return (CKR_OK);
3487c478bd9Sstevel@tonic-gate 	}
3497c478bd9Sstevel@tonic-gate 
350*cfcec266SJason King 	new_objp->session_handle = sp->handle;
3517c478bd9Sstevel@tonic-gate 
3527c478bd9Sstevel@tonic-gate 	/* Add the new object to the session's object list. */
3537c478bd9Sstevel@tonic-gate 	soft_add_object_to_session(new_objp, sp);
3547c478bd9Sstevel@tonic-gate 
355*cfcec266SJason King 	*objecthandle_p = set_objecthandle(new_objp);
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	return (CKR_OK);
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate fail_cleanup2:
3607c478bd9Sstevel@tonic-gate 	/*
3617c478bd9Sstevel@tonic-gate 	 * When any error occurs after soft_build_object(), we will need to
3627c478bd9Sstevel@tonic-gate 	 * clean up the memory allocated by the soft_build_object().
3637c478bd9Sstevel@tonic-gate 	 */
3647c478bd9Sstevel@tonic-gate 	soft_cleanup_object(new_objp);
3657c478bd9Sstevel@tonic-gate 
3667c478bd9Sstevel@tonic-gate fail_cleanup1:
3677c478bd9Sstevel@tonic-gate 	if (new_objp) {
3687c478bd9Sstevel@tonic-gate 		/*
3697c478bd9Sstevel@tonic-gate 		 * The storage allocated inside of this object should have
3707c478bd9Sstevel@tonic-gate 		 * been cleaned up by the soft_build_object() if it failed.
3717c478bd9Sstevel@tonic-gate 		 * Therefore, we can safely free the object.
3727c478bd9Sstevel@tonic-gate 		 */
3737c478bd9Sstevel@tonic-gate 		free(new_objp);
3747c478bd9Sstevel@tonic-gate 	}
3757c478bd9Sstevel@tonic-gate 
3767c478bd9Sstevel@tonic-gate 	return (rv);
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate }
3797c478bd9Sstevel@tonic-gate 
3807c478bd9Sstevel@tonic-gate 
3817c478bd9Sstevel@tonic-gate /*
3827c478bd9Sstevel@tonic-gate  * Remove an object from the session's object list.
3837c478bd9Sstevel@tonic-gate  *
3847c478bd9Sstevel@tonic-gate  * The caller of this function holds the session lock.
3857c478bd9Sstevel@tonic-gate  */
3867c478bd9Sstevel@tonic-gate CK_RV
soft_remove_object_from_session(soft_object_t * objp,soft_session_t * sp)3877c478bd9Sstevel@tonic-gate soft_remove_object_from_session(soft_object_t *objp, soft_session_t *sp)
3887c478bd9Sstevel@tonic-gate {
3897c478bd9Sstevel@tonic-gate 	soft_object_t *tmp_objp;
3907c478bd9Sstevel@tonic-gate 	boolean_t found = B_FALSE;
3917c478bd9Sstevel@tonic-gate 
3927c478bd9Sstevel@tonic-gate 	/*
3937c478bd9Sstevel@tonic-gate 	 * Remove the object from the session's object list.
3947c478bd9Sstevel@tonic-gate 	 */
3957c478bd9Sstevel@tonic-gate 	if ((sp == NULL) ||
3967c478bd9Sstevel@tonic-gate 	    (sp->magic_marker != SOFTTOKEN_SESSION_MAGIC)) {
3977c478bd9Sstevel@tonic-gate 		return (CKR_SESSION_HANDLE_INVALID);
3987c478bd9Sstevel@tonic-gate 	}
3997c478bd9Sstevel@tonic-gate 
4007c478bd9Sstevel@tonic-gate 	if ((sp->object_list == NULL) || (objp == NULL) ||
4017c478bd9Sstevel@tonic-gate 	    (objp->magic_marker != SOFTTOKEN_OBJECT_MAGIC)) {
4027c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
4037c478bd9Sstevel@tonic-gate 	}
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate 	tmp_objp = sp->object_list;
4067c478bd9Sstevel@tonic-gate 	while (tmp_objp) {
4077c478bd9Sstevel@tonic-gate 		if (tmp_objp == objp) {
4087c478bd9Sstevel@tonic-gate 			found = B_TRUE;
4097c478bd9Sstevel@tonic-gate 			break;
4107c478bd9Sstevel@tonic-gate 		}
4117c478bd9Sstevel@tonic-gate 		tmp_objp = tmp_objp->next;
4127c478bd9Sstevel@tonic-gate 	}
4137c478bd9Sstevel@tonic-gate 	if (!found)
4147c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
4157c478bd9Sstevel@tonic-gate 
4167c478bd9Sstevel@tonic-gate 	if (sp->object_list == objp) {
4177c478bd9Sstevel@tonic-gate 		/* Object is the first one in the list. */
4187c478bd9Sstevel@tonic-gate 		if (objp->next) {
4197c478bd9Sstevel@tonic-gate 			sp->object_list = objp->next;
4207c478bd9Sstevel@tonic-gate 			objp->next->prev = NULL;
4217c478bd9Sstevel@tonic-gate 		} else {
4227c478bd9Sstevel@tonic-gate 			/* Object is the only one in the list. */
4237c478bd9Sstevel@tonic-gate 			sp->object_list = NULL;
4247c478bd9Sstevel@tonic-gate 		}
4257c478bd9Sstevel@tonic-gate 	} else {
4267c478bd9Sstevel@tonic-gate 		/* Object is not the first one in the list. */
4277c478bd9Sstevel@tonic-gate 		if (objp->next) {
4287c478bd9Sstevel@tonic-gate 			/* Object is in the middle of the list. */
4297c478bd9Sstevel@tonic-gate 			objp->prev->next = objp->next;
4307c478bd9Sstevel@tonic-gate 			objp->next->prev = objp->prev;
4317c478bd9Sstevel@tonic-gate 		} else {
4327c478bd9Sstevel@tonic-gate 			/* Object is the last one in the list. */
4337c478bd9Sstevel@tonic-gate 			objp->prev->next = NULL;
4347c478bd9Sstevel@tonic-gate 		}
4357c478bd9Sstevel@tonic-gate 	}
4367c478bd9Sstevel@tonic-gate 	return (CKR_OK);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate  * This function adds the to-be-freed session object to a linked list.
4417c478bd9Sstevel@tonic-gate  * When the number of objects queued in the linked list reaches the
4427c478bd9Sstevel@tonic-gate  * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
4437c478bd9Sstevel@tonic-gate  * object (FIFO) in the list.
4447c478bd9Sstevel@tonic-gate  */
4457c478bd9Sstevel@tonic-gate void
object_delay_free(soft_object_t * objp)4467c478bd9Sstevel@tonic-gate object_delay_free(soft_object_t *objp)
4477c478bd9Sstevel@tonic-gate {
4487c478bd9Sstevel@tonic-gate 	soft_object_t *tmp;
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
4517c478bd9Sstevel@tonic-gate 
4527c478bd9Sstevel@tonic-gate 	/* Add the newly deleted object at the end of the list */
4537c478bd9Sstevel@tonic-gate 	objp->next = NULL;
4547c478bd9Sstevel@tonic-gate 	if (obj_delay_freed.first == NULL) {
4557c478bd9Sstevel@tonic-gate 		obj_delay_freed.last = objp;
4567c478bd9Sstevel@tonic-gate 		obj_delay_freed.first = objp;
4577c478bd9Sstevel@tonic-gate 	} else {
4587c478bd9Sstevel@tonic-gate 		obj_delay_freed.last->next = objp;
4597c478bd9Sstevel@tonic-gate 		obj_delay_freed.last = objp;
4607c478bd9Sstevel@tonic-gate 	}
4617c478bd9Sstevel@tonic-gate 
4627c478bd9Sstevel@tonic-gate 	if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
4637c478bd9Sstevel@tonic-gate 		/*
4647c478bd9Sstevel@tonic-gate 		 * Free the first object in the list only if
4657c478bd9Sstevel@tonic-gate 		 * the total count reaches maximum threshold.
4667c478bd9Sstevel@tonic-gate 		 */
4677c478bd9Sstevel@tonic-gate 		obj_delay_freed.count--;
4687c478bd9Sstevel@tonic-gate 		tmp = obj_delay_freed.first->next;
4697c478bd9Sstevel@tonic-gate 		free(obj_delay_freed.first);
4707c478bd9Sstevel@tonic-gate 		obj_delay_freed.first = tmp;
4717c478bd9Sstevel@tonic-gate 	}
4727c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
4737c478bd9Sstevel@tonic-gate }
4747c478bd9Sstevel@tonic-gate 
4757c478bd9Sstevel@tonic-gate static void
soft_delete_object_cleanup(soft_object_t * objp,boolean_t force)4761f49a79aSZdenek Kotala soft_delete_object_cleanup(soft_object_t *objp, boolean_t force)
4777c478bd9Sstevel@tonic-gate {
4787c478bd9Sstevel@tonic-gate 	/* Acquire the lock on the object. */
4797c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&objp->object_mutex);
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	/*
4827c478bd9Sstevel@tonic-gate 	 * Make sure another thread hasn't freed the object.
4837c478bd9Sstevel@tonic-gate 	 */
4847c478bd9Sstevel@tonic-gate 	if (objp->magic_marker != SOFTTOKEN_OBJECT_MAGIC) {
4857c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&objp->object_mutex);
4867c478bd9Sstevel@tonic-gate 		return;
4877c478bd9Sstevel@tonic-gate 	}
4887c478bd9Sstevel@tonic-gate 
4897c478bd9Sstevel@tonic-gate 	/*
4907c478bd9Sstevel@tonic-gate 	 * The deletion of an object must be blocked when the object
4917c478bd9Sstevel@tonic-gate 	 * reference count is not zero. This means if any object related
4927c478bd9Sstevel@tonic-gate 	 * operation starts prior to the delete object operation gets in,
4937c478bd9Sstevel@tonic-gate 	 * the object deleting thread must wait for the non-deleting
4947c478bd9Sstevel@tonic-gate 	 * operation to be completed before it can proceed the delete
4957c478bd9Sstevel@tonic-gate 	 * operation.
4961f49a79aSZdenek Kotala 	 *
4971f49a79aSZdenek Kotala 	 * Unless we are being forced to shut everything down, this only
4981f49a79aSZdenek Kotala 	 * happens if the libraries _fini() is running not of someone
4991f49a79aSZdenek Kotala 	 * explicitly called C_Finalize().
5007c478bd9Sstevel@tonic-gate 	 */
5011f49a79aSZdenek Kotala 	if (force)
5021f49a79aSZdenek Kotala 		objp->obj_refcnt = 0;
5031f49a79aSZdenek Kotala 
5047c478bd9Sstevel@tonic-gate 	while (objp->obj_refcnt != 0) {
5057c478bd9Sstevel@tonic-gate 		/*
5067c478bd9Sstevel@tonic-gate 		 * We set the OBJECT_REFCNT_WAITING flag before we put
5077c478bd9Sstevel@tonic-gate 		 * this deleting thread in a wait state, so other non-deleting
5087c478bd9Sstevel@tonic-gate 		 * operation thread will signal to wake it up only when
5097c478bd9Sstevel@tonic-gate 		 * the object reference count becomes zero and this flag
5107c478bd9Sstevel@tonic-gate 		 * is set.
5117c478bd9Sstevel@tonic-gate 		 */
5127c478bd9Sstevel@tonic-gate 		objp->obj_delete_sync |= OBJECT_REFCNT_WAITING;
5137c478bd9Sstevel@tonic-gate 		(void) pthread_cond_wait(&objp->obj_free_cond,
514c2e31228SViswanathan Kannappan 		    &objp->object_mutex);
5157c478bd9Sstevel@tonic-gate 	}
5167c478bd9Sstevel@tonic-gate 
5177c478bd9Sstevel@tonic-gate 	objp->obj_delete_sync &= ~OBJECT_REFCNT_WAITING;
5187c478bd9Sstevel@tonic-gate 
5197c478bd9Sstevel@tonic-gate 	/* Mark object as no longer valid. */
5207c478bd9Sstevel@tonic-gate 	objp->magic_marker = 0;
5217c478bd9Sstevel@tonic-gate 
5227c478bd9Sstevel@tonic-gate 	(void) pthread_cond_destroy(&objp->obj_free_cond);
5237c478bd9Sstevel@tonic-gate 
5247c478bd9Sstevel@tonic-gate 	/*
5257c478bd9Sstevel@tonic-gate 	 * Cleanup the contents of this object such as free all the
5267c478bd9Sstevel@tonic-gate 	 * storage allocated for this object.
5277c478bd9Sstevel@tonic-gate 	 */
5287c478bd9Sstevel@tonic-gate 	soft_cleanup_object(objp);
5297c478bd9Sstevel@tonic-gate 
530*cfcec266SJason King 	(void) pthread_mutex_lock(&soft_object_mutex);
531*cfcec266SJason King 	avl_remove(&soft_object_tree, objp);
532*cfcec266SJason King 	(void) pthread_mutex_unlock(&soft_object_mutex);
533*cfcec266SJason King 
5347c478bd9Sstevel@tonic-gate 	/* Reset OBJECT_IS_DELETING flag. */
5357c478bd9Sstevel@tonic-gate 	objp->obj_delete_sync &= ~OBJECT_IS_DELETING;
5367c478bd9Sstevel@tonic-gate 
5377c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&objp->object_mutex);
5387c478bd9Sstevel@tonic-gate 	/* Destroy the object lock */
5397c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_destroy(&objp->object_mutex);
5407c478bd9Sstevel@tonic-gate 
5417c478bd9Sstevel@tonic-gate 	/* Free the object itself */
5427c478bd9Sstevel@tonic-gate 	if (IS_TOKEN_OBJECT(objp))
5437c478bd9Sstevel@tonic-gate 		free(objp);
5447c478bd9Sstevel@tonic-gate 	else
5457c478bd9Sstevel@tonic-gate 		/*
5467c478bd9Sstevel@tonic-gate 		 * Delay freeing the session object as S1WS/NSS uses session
5477c478bd9Sstevel@tonic-gate 		 * objects for its SSL Handshake.
5487c478bd9Sstevel@tonic-gate 		 */
5497c478bd9Sstevel@tonic-gate 		(void) object_delay_free(objp);
5507c478bd9Sstevel@tonic-gate }
5517c478bd9Sstevel@tonic-gate 
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate  * Delete an object:
5547c478bd9Sstevel@tonic-gate  * - Remove the object from the session's object list.
5557c478bd9Sstevel@tonic-gate  *   Holding the lock on the session which the object was created at
5567c478bd9Sstevel@tonic-gate  *   is needed to do this.
5577c478bd9Sstevel@tonic-gate  * - Release the storage allocated to the object.
5587c478bd9Sstevel@tonic-gate  *
5597c478bd9Sstevel@tonic-gate  * The boolean argument lock_held is used to indicate that whether
5607c478bd9Sstevel@tonic-gate  * the caller holds the session lock or not.
5617c478bd9Sstevel@tonic-gate  * - When called by soft_delete_all_objects_in_session() -- the
5627c478bd9Sstevel@tonic-gate  *   lock_held = TRUE.
5637c478bd9Sstevel@tonic-gate  *
5647c478bd9Sstevel@tonic-gate  * When the caller does not hold the session lock, this function
5657c478bd9Sstevel@tonic-gate  * will acquire that lock in order to proceed, and also release
5667c478bd9Sstevel@tonic-gate  * that lock before returning to caller.
5677c478bd9Sstevel@tonic-gate  */
5687c478bd9Sstevel@tonic-gate void
soft_delete_object(soft_session_t * sp,soft_object_t * objp,boolean_t force,boolean_t lock_held)5691f49a79aSZdenek Kotala soft_delete_object(soft_session_t *sp, soft_object_t *objp,
570*cfcec266SJason King     boolean_t force, boolean_t lock_held)
5717c478bd9Sstevel@tonic-gate {
5727c478bd9Sstevel@tonic-gate 
5737c478bd9Sstevel@tonic-gate 	/*
5747c478bd9Sstevel@tonic-gate 	 * Check to see if the caller holds the lock on the session.
5757c478bd9Sstevel@tonic-gate 	 * If not, we need to acquire that lock in order to proceed.
5767c478bd9Sstevel@tonic-gate 	 */
5777c478bd9Sstevel@tonic-gate 	if (!lock_held) {
5787c478bd9Sstevel@tonic-gate 		/* Acquire the session lock. */
5797c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&sp->session_mutex);
5807c478bd9Sstevel@tonic-gate 	}
5817c478bd9Sstevel@tonic-gate 
5827c478bd9Sstevel@tonic-gate 	/* Remove the object from the session's object list first. */
5837c478bd9Sstevel@tonic-gate 	if (soft_remove_object_from_session(objp, sp) != CKR_OK) {
5847c478bd9Sstevel@tonic-gate 		if (!lock_held) {
5857c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&sp->session_mutex);
5867c478bd9Sstevel@tonic-gate 		}
5877c478bd9Sstevel@tonic-gate 		return;
5887c478bd9Sstevel@tonic-gate 	}
5897c478bd9Sstevel@tonic-gate 
5907c478bd9Sstevel@tonic-gate 	if (!lock_held) {
5917c478bd9Sstevel@tonic-gate 		/*
5927c478bd9Sstevel@tonic-gate 		 * If the session lock is obtained by this function,
5937c478bd9Sstevel@tonic-gate 		 * then release that lock after removing the object
5947c478bd9Sstevel@tonic-gate 		 * from session's object list.
5957c478bd9Sstevel@tonic-gate 		 * We want the releasing of the object storage to
5967c478bd9Sstevel@tonic-gate 		 * be done without holding the session lock.
5977c478bd9Sstevel@tonic-gate 		 */
5987c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&sp->session_mutex);
5997c478bd9Sstevel@tonic-gate 	}
6007c478bd9Sstevel@tonic-gate 
6011f49a79aSZdenek Kotala 	soft_delete_object_cleanup(objp, force);
6027c478bd9Sstevel@tonic-gate }
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 
6057c478bd9Sstevel@tonic-gate /*
6067c478bd9Sstevel@tonic-gate  * Delete all the objects in a session. The caller holds the lock
6077c478bd9Sstevel@tonic-gate  * on the session.
6087c478bd9Sstevel@tonic-gate  */
6097c478bd9Sstevel@tonic-gate void
soft_delete_all_objects_in_session(soft_session_t * sp,boolean_t force)6101f49a79aSZdenek Kotala soft_delete_all_objects_in_session(soft_session_t *sp, boolean_t force)
6117c478bd9Sstevel@tonic-gate {
6127c478bd9Sstevel@tonic-gate 	soft_object_t *objp = sp->object_list;
6137c478bd9Sstevel@tonic-gate 	soft_object_t *objp1;
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 	/* Delete all the objects in the session. */
6167c478bd9Sstevel@tonic-gate 	while (objp) {
6177c478bd9Sstevel@tonic-gate 		objp1 = objp->next;
6187c478bd9Sstevel@tonic-gate 
6197c478bd9Sstevel@tonic-gate 		/*
6207c478bd9Sstevel@tonic-gate 		 * Delete an object by calling soft_delete_object()
6217c478bd9Sstevel@tonic-gate 		 * with a TRUE boolean argument indicating that
6227c478bd9Sstevel@tonic-gate 		 * the caller holds the lock on the session.
6237c478bd9Sstevel@tonic-gate 		 */
6241f49a79aSZdenek Kotala 		soft_delete_object(sp, objp, force, B_TRUE);
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		objp = objp1;
6277c478bd9Sstevel@tonic-gate 	}
6287c478bd9Sstevel@tonic-gate }
6297c478bd9Sstevel@tonic-gate 
6307c478bd9Sstevel@tonic-gate static CK_RV
add_to_search_result(soft_object_t * obj,find_context_t * fcontext,CK_ULONG * num_result_alloc)6317c478bd9Sstevel@tonic-gate add_to_search_result(soft_object_t *obj, find_context_t *fcontext,
6327c478bd9Sstevel@tonic-gate     CK_ULONG *num_result_alloc)
6337c478bd9Sstevel@tonic-gate {
6347c478bd9Sstevel@tonic-gate 	/*
6357c478bd9Sstevel@tonic-gate 	 * allocate space for storing results if the currently
6367c478bd9Sstevel@tonic-gate 	 * allocated space is not enough
6377c478bd9Sstevel@tonic-gate 	 */
6387c478bd9Sstevel@tonic-gate 	if (*num_result_alloc <= fcontext->num_results) {
6397c478bd9Sstevel@tonic-gate 		fcontext->objs_found = realloc(fcontext->objs_found,
6407c478bd9Sstevel@tonic-gate 		    sizeof (soft_object_t *) * (*num_result_alloc + BUFSIZ));
6417c478bd9Sstevel@tonic-gate 		if (fcontext->objs_found == NULL) {
6427c478bd9Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
6437c478bd9Sstevel@tonic-gate 		}
6447c478bd9Sstevel@tonic-gate 		*num_result_alloc += BUFSIZ;
6457c478bd9Sstevel@tonic-gate 	}
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 	(fcontext->objs_found)[(fcontext->num_results)++] = obj;
6487c478bd9Sstevel@tonic-gate 	return (CKR_OK);
6497c478bd9Sstevel@tonic-gate }
6507c478bd9Sstevel@tonic-gate 
6517c478bd9Sstevel@tonic-gate static CK_RV
search_for_objects(CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,find_context_t * fcontext)6527c478bd9Sstevel@tonic-gate search_for_objects(CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
6537c478bd9Sstevel@tonic-gate     find_context_t *fcontext)
6547c478bd9Sstevel@tonic-gate {
6557c478bd9Sstevel@tonic-gate 	soft_session_t *session_p;
6567c478bd9Sstevel@tonic-gate 	soft_object_t *obj;
657c2e31228SViswanathan Kannappan 	CK_OBJECT_CLASS pclasses[6]; /* classes attrs possibly exist */
6587c478bd9Sstevel@tonic-gate 	CK_ULONG num_pclasses;	/* number of possible classes */
6597c478bd9Sstevel@tonic-gate 	CK_ULONG num_result_alloc = 0; /* spaces allocated for results */
6607c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
6617c478bd9Sstevel@tonic-gate 	/* whether CKA_TOKEN flag specified or not */
6627c478bd9Sstevel@tonic-gate 	boolean_t token_specified = B_FALSE;
6637c478bd9Sstevel@tonic-gate 	/* value of CKA_TOKEN flag, if specified */
6647c478bd9Sstevel@tonic-gate 	boolean_t token_flag_val = B_FALSE;
6657c478bd9Sstevel@tonic-gate 	CK_ULONG i;
6667c478bd9Sstevel@tonic-gate 
6677c478bd9Sstevel@tonic-gate 	if (ulCount > 0) {
6687c478bd9Sstevel@tonic-gate 		/* there are some search requirement */
6697c478bd9Sstevel@tonic-gate 		soft_process_find_attr(pclasses, &num_pclasses,
6707c478bd9Sstevel@tonic-gate 		    pTemplate, ulCount);
6717c478bd9Sstevel@tonic-gate 	}
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
6747c478bd9Sstevel@tonic-gate 		if (pTemplate[i].type == CKA_PRIVATE) {
6757c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&soft_giant_mutex);
6767c478bd9Sstevel@tonic-gate 			if (soft_slot.userpin_change_needed) {
6777c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock(&soft_giant_mutex);
6787c478bd9Sstevel@tonic-gate 				return (CKR_PIN_EXPIRED);
6797c478bd9Sstevel@tonic-gate 			}
6807c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&soft_giant_mutex);
6817c478bd9Sstevel@tonic-gate 		}
6827c478bd9Sstevel@tonic-gate 	}
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 	/*
6857c478bd9Sstevel@tonic-gate 	 * look through template and see if it explicitly specifies
6867c478bd9Sstevel@tonic-gate 	 * whether we need to look for token objects or not
6877c478bd9Sstevel@tonic-gate 	 */
6887c478bd9Sstevel@tonic-gate 	for (i = 0; i < ulCount; i++) {
6897c478bd9Sstevel@tonic-gate 		if (pTemplate[i].type == CKA_TOKEN) {
6907c478bd9Sstevel@tonic-gate 			token_specified = B_TRUE;
6917c478bd9Sstevel@tonic-gate 			token_flag_val = *((CK_BBOOL *)pTemplate[i].pValue);
6927c478bd9Sstevel@tonic-gate 			break;
6937c478bd9Sstevel@tonic-gate 		}
6947c478bd9Sstevel@tonic-gate 	}
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 	/*
6977c478bd9Sstevel@tonic-gate 	 * Need go through token objects if it explicitly say so, or
6987c478bd9Sstevel@tonic-gate 	 * it is not mentioned in the template.  And this will ONLY be
6997c478bd9Sstevel@tonic-gate 	 * done when the keystore exists. Otherwise, we will skip re-loading
7007c478bd9Sstevel@tonic-gate 	 * the token objects.
7017c478bd9Sstevel@tonic-gate 	 *
7027c478bd9Sstevel@tonic-gate 	 * If a session has not logged into the token, only public
7037c478bd9Sstevel@tonic-gate 	 * objects, if any, will be searched.  If a session is logged
7047c478bd9Sstevel@tonic-gate 	 * into the token, all public and private objects in the keystore
7057c478bd9Sstevel@tonic-gate 	 * are searched.
7067c478bd9Sstevel@tonic-gate 	 */
70790e0e8c4Sizick 	if (((token_flag_val) || (!token_specified)) &&
70890e0e8c4Sizick 	    soft_keystore_status(KEYSTORE_INITIALIZED)) {
7097c478bd9Sstevel@tonic-gate 		/* acquire token session lock */
7107c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&soft_slot.slot_mutex);
7117c478bd9Sstevel@tonic-gate 		rv = refresh_token_objects();
7127c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
7137c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
7147c478bd9Sstevel@tonic-gate 			return (rv);
7157c478bd9Sstevel@tonic-gate 		}
7167c478bd9Sstevel@tonic-gate 		obj = soft_slot.token_object_list;
7177c478bd9Sstevel@tonic-gate 		while (obj) {
7187c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
7197c478bd9Sstevel@tonic-gate 			if (((token_specified) && (ulCount > 1)) ||
7207c478bd9Sstevel@tonic-gate 			    ((!token_specified) && (ulCount > 0))) {
7217c478bd9Sstevel@tonic-gate 				if (soft_find_match_attrs(obj, pclasses,
7227c478bd9Sstevel@tonic-gate 				    num_pclasses, pTemplate, ulCount)) {
7237c478bd9Sstevel@tonic-gate 					rv = add_to_search_result(
7247c478bd9Sstevel@tonic-gate 					    obj, fcontext, &num_result_alloc);
7257c478bd9Sstevel@tonic-gate 				}
7267c478bd9Sstevel@tonic-gate 			} else {
7277c478bd9Sstevel@tonic-gate 				/* no search criteria, just record the object */
7287c478bd9Sstevel@tonic-gate 				rv = add_to_search_result(obj, fcontext,
7297c478bd9Sstevel@tonic-gate 				    &num_result_alloc);
7307c478bd9Sstevel@tonic-gate 			}
7317c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
7327c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
7337c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock
7347c478bd9Sstevel@tonic-gate 				    (&soft_slot.slot_mutex);
7357c478bd9Sstevel@tonic-gate 				return (rv);
7367c478bd9Sstevel@tonic-gate 			}
7377c478bd9Sstevel@tonic-gate 			obj = obj->next;
7387c478bd9Sstevel@tonic-gate 		}
7397c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
7407c478bd9Sstevel@tonic-gate 	}
7417c478bd9Sstevel@tonic-gate 
7427c478bd9Sstevel@tonic-gate 	if (token_flag_val) {
7437c478bd9Sstevel@tonic-gate 		/* no need to look through session objects */
7447c478bd9Sstevel@tonic-gate 		return (rv);
7457c478bd9Sstevel@tonic-gate 	}
7467c478bd9Sstevel@tonic-gate 
7477c478bd9Sstevel@tonic-gate 	/* Acquire the global session list lock */
7487c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_sessionlist_mutex);
7497c478bd9Sstevel@tonic-gate 
7507c478bd9Sstevel@tonic-gate 	/*
7517c478bd9Sstevel@tonic-gate 	 * Go through all objects in each session.
7527c478bd9Sstevel@tonic-gate 	 * Acquire individual session lock for the session
7537c478bd9Sstevel@tonic-gate 	 * we are searching.
7547c478bd9Sstevel@tonic-gate 	 */
7557c478bd9Sstevel@tonic-gate 	session_p = soft_session_list;
7567c478bd9Sstevel@tonic-gate 	while (session_p) {
7577c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
7587c478bd9Sstevel@tonic-gate 
7597c478bd9Sstevel@tonic-gate 		obj = session_p->object_list;
7607c478bd9Sstevel@tonic-gate 		while (obj) {
7617c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
7627c478bd9Sstevel@tonic-gate 			if (ulCount > 0) {
7637c478bd9Sstevel@tonic-gate 				if (soft_find_match_attrs(obj, pclasses,
7647c478bd9Sstevel@tonic-gate 				    num_pclasses, pTemplate, ulCount)) {
7657c478bd9Sstevel@tonic-gate 					rv = add_to_search_result(
7667c478bd9Sstevel@tonic-gate 					    obj, fcontext, &num_result_alloc);
7677c478bd9Sstevel@tonic-gate 				}
7687c478bd9Sstevel@tonic-gate 			} else {
7697c478bd9Sstevel@tonic-gate 				/* no search criteria, just record the object */
7707c478bd9Sstevel@tonic-gate 				rv = add_to_search_result(obj, fcontext,
7717c478bd9Sstevel@tonic-gate 				    &num_result_alloc);
7727c478bd9Sstevel@tonic-gate 			}
7737c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
7747c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
7757c478bd9Sstevel@tonic-gate 				(void) pthread_mutex_unlock(
7767c478bd9Sstevel@tonic-gate 				    &session_p->session_mutex);
7777c478bd9Sstevel@tonic-gate 				goto cleanup;
7787c478bd9Sstevel@tonic-gate 			}
7797c478bd9Sstevel@tonic-gate 			obj = obj->next;
7807c478bd9Sstevel@tonic-gate 		}
7817c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
7827c478bd9Sstevel@tonic-gate 		session_p = session_p->next;
7837c478bd9Sstevel@tonic-gate 	}
7847c478bd9Sstevel@tonic-gate 
7857c478bd9Sstevel@tonic-gate cleanup:
7867c478bd9Sstevel@tonic-gate 	/* Release the global session list lock */
7877c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_sessionlist_mutex);
7887c478bd9Sstevel@tonic-gate 	return (rv);
7897c478bd9Sstevel@tonic-gate }
7907c478bd9Sstevel@tonic-gate 
7917c478bd9Sstevel@tonic-gate /*
7927c478bd9Sstevel@tonic-gate  * Initialize the context for C_FindObjects() calls
7937c478bd9Sstevel@tonic-gate  */
7947c478bd9Sstevel@tonic-gate CK_RV
soft_find_objects_init(soft_session_t * sp,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)7957c478bd9Sstevel@tonic-gate soft_find_objects_init(soft_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
7967c478bd9Sstevel@tonic-gate     CK_ULONG ulCount)
7977c478bd9Sstevel@tonic-gate {
7987c478bd9Sstevel@tonic-gate 
7997c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
8007c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class; /* for soft_validate_attr(). Value unused */
8017c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
8027c478bd9Sstevel@tonic-gate 
8037c478bd9Sstevel@tonic-gate 	if (ulCount) {
8047c478bd9Sstevel@tonic-gate 		rv = soft_validate_attr(pTemplate, ulCount, &class);
8057c478bd9Sstevel@tonic-gate 		/* Make sure all attributes in template are valid */
8067c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
8077c478bd9Sstevel@tonic-gate 			return (rv);
8087c478bd9Sstevel@tonic-gate 		}
8097c478bd9Sstevel@tonic-gate 	}
8107c478bd9Sstevel@tonic-gate 
8117c478bd9Sstevel@tonic-gate 
8127c478bd9Sstevel@tonic-gate 	/* prepare the find context */
8137c478bd9Sstevel@tonic-gate 	fcontext = calloc(1, sizeof (find_context_t));
8147c478bd9Sstevel@tonic-gate 	if (fcontext == NULL) {
8157c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
8167c478bd9Sstevel@tonic-gate 	}
8177c478bd9Sstevel@tonic-gate 
8187c478bd9Sstevel@tonic-gate 	rv = search_for_objects(pTemplate, ulCount, fcontext);
8197c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
8207c478bd9Sstevel@tonic-gate 		free(fcontext);
8217c478bd9Sstevel@tonic-gate 		return (rv);
8227c478bd9Sstevel@tonic-gate 	}
8237c478bd9Sstevel@tonic-gate 
8247c478bd9Sstevel@tonic-gate 	/* store the find_context in the session */
8257c478bd9Sstevel@tonic-gate 	sp->find_objects.context = (CK_VOID_PTR)fcontext;
8267c478bd9Sstevel@tonic-gate 
8277c478bd9Sstevel@tonic-gate 	return (rv);
8287c478bd9Sstevel@tonic-gate }
8297c478bd9Sstevel@tonic-gate 
8307c478bd9Sstevel@tonic-gate void
soft_find_objects_final(soft_session_t * sp)8317c478bd9Sstevel@tonic-gate soft_find_objects_final(soft_session_t *sp)
8327c478bd9Sstevel@tonic-gate {
8337c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	fcontext = sp->find_objects.context;
8367c478bd9Sstevel@tonic-gate 	sp->find_objects.context = NULL;
8377c478bd9Sstevel@tonic-gate 	sp->find_objects.flags = 0;
8387c478bd9Sstevel@tonic-gate 	if (fcontext->objs_found != NULL) {
8397c478bd9Sstevel@tonic-gate 		free(fcontext->objs_found);
8407c478bd9Sstevel@tonic-gate 	}
8417c478bd9Sstevel@tonic-gate 
8427c478bd9Sstevel@tonic-gate 	free(fcontext);
8437c478bd9Sstevel@tonic-gate }
8447c478bd9Sstevel@tonic-gate 
8457c478bd9Sstevel@tonic-gate void
soft_find_objects(soft_session_t * sp,CK_OBJECT_HANDLE * obj_found,CK_ULONG max_obj_requested,CK_ULONG * found_obj_count)8467c478bd9Sstevel@tonic-gate soft_find_objects(soft_session_t *sp, CK_OBJECT_HANDLE *obj_found,
8477c478bd9Sstevel@tonic-gate     CK_ULONG max_obj_requested, CK_ULONG *found_obj_count)
8487c478bd9Sstevel@tonic-gate {
8497c478bd9Sstevel@tonic-gate 	find_context_t *fcontext;
8507c478bd9Sstevel@tonic-gate 	CK_ULONG num_obj_found = 0;
8517c478bd9Sstevel@tonic-gate 	CK_ULONG i;
8527c478bd9Sstevel@tonic-gate 	soft_object_t *obj;
8537c478bd9Sstevel@tonic-gate 
8547c478bd9Sstevel@tonic-gate 	fcontext = sp->find_objects.context;
8557c478bd9Sstevel@tonic-gate 
8567c478bd9Sstevel@tonic-gate 	for (i = fcontext->next_result_index;
8577c478bd9Sstevel@tonic-gate 	    ((num_obj_found < max_obj_requested) &&
8587c478bd9Sstevel@tonic-gate 	    (i < fcontext->num_results));
8597c478bd9Sstevel@tonic-gate 	    i++) {
8607c478bd9Sstevel@tonic-gate 		obj = fcontext->objs_found[i];
8617c478bd9Sstevel@tonic-gate 		if (obj != NULL) {
8627c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_lock(&obj->object_mutex);
8637c478bd9Sstevel@tonic-gate 			/* a sanity check to make sure the obj is still valid */
8647c478bd9Sstevel@tonic-gate 			if (obj->magic_marker == SOFTTOKEN_OBJECT_MAGIC) {
865*cfcec266SJason King 				obj_found[num_obj_found] = obj->handle;
8667c478bd9Sstevel@tonic-gate 				num_obj_found++;
8677c478bd9Sstevel@tonic-gate 			}
8687c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&obj->object_mutex);
8697c478bd9Sstevel@tonic-gate 		}
8707c478bd9Sstevel@tonic-gate 	}
8717c478bd9Sstevel@tonic-gate 	fcontext->next_result_index = i;
8727c478bd9Sstevel@tonic-gate 	*found_obj_count = num_obj_found;
8737c478bd9Sstevel@tonic-gate }
8747c478bd9Sstevel@tonic-gate 
8757c478bd9Sstevel@tonic-gate /*
8767c478bd9Sstevel@tonic-gate  * Below are the token object related functions
8777c478bd9Sstevel@tonic-gate  */
8787c478bd9Sstevel@tonic-gate void
soft_add_token_object_to_slot(soft_object_t * objp)8797c478bd9Sstevel@tonic-gate soft_add_token_object_to_slot(soft_object_t *objp)
8807c478bd9Sstevel@tonic-gate {
8817c478bd9Sstevel@tonic-gate 
8827c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_slot.slot_mutex);
8837c478bd9Sstevel@tonic-gate 
8847c478bd9Sstevel@tonic-gate 	/* Insert the new object in front of slot's token object list. */
8857c478bd9Sstevel@tonic-gate 	if (soft_slot.token_object_list == NULL) {
8867c478bd9Sstevel@tonic-gate 		soft_slot.token_object_list = objp;
8877c478bd9Sstevel@tonic-gate 		objp->next = NULL;
8887c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
8897c478bd9Sstevel@tonic-gate 	} else {
8907c478bd9Sstevel@tonic-gate 		soft_slot.token_object_list->prev = objp;
8917c478bd9Sstevel@tonic-gate 		objp->next = soft_slot.token_object_list;
8927c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
8937c478bd9Sstevel@tonic-gate 		soft_slot.token_object_list = objp;
8947c478bd9Sstevel@tonic-gate 	}
8957c478bd9Sstevel@tonic-gate 
8967c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
8977c478bd9Sstevel@tonic-gate 
8987c478bd9Sstevel@tonic-gate }
8997c478bd9Sstevel@tonic-gate 
9007c478bd9Sstevel@tonic-gate void
soft_remove_token_object_from_slot(soft_object_t * objp,boolean_t lock_held)9017c478bd9Sstevel@tonic-gate soft_remove_token_object_from_slot(soft_object_t *objp, boolean_t lock_held)
9027c478bd9Sstevel@tonic-gate {
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 	if (!lock_held)
9057c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&soft_slot.slot_mutex);
9067c478bd9Sstevel@tonic-gate 
9077c478bd9Sstevel@tonic-gate 	/*
9087c478bd9Sstevel@tonic-gate 	 * Remove the object from the slot's token object list.
9097c478bd9Sstevel@tonic-gate 	 */
9107c478bd9Sstevel@tonic-gate 	if (soft_slot.token_object_list == objp) {
9117c478bd9Sstevel@tonic-gate 		/* Object is the first one in the list. */
9127c478bd9Sstevel@tonic-gate 		if (objp->next) {
9137c478bd9Sstevel@tonic-gate 			soft_slot.token_object_list = objp->next;
9147c478bd9Sstevel@tonic-gate 			objp->next->prev = NULL;
9157c478bd9Sstevel@tonic-gate 		} else {
9167c478bd9Sstevel@tonic-gate 			/* Object is the only one in the list. */
9177c478bd9Sstevel@tonic-gate 			soft_slot.token_object_list = NULL;
9187c478bd9Sstevel@tonic-gate 		}
9197c478bd9Sstevel@tonic-gate 	} else {
9207c478bd9Sstevel@tonic-gate 		/* Object is not the first one in the list. */
9217c478bd9Sstevel@tonic-gate 		if (objp->next) {
9227c478bd9Sstevel@tonic-gate 			/* Object is in the middle of the list. */
9237c478bd9Sstevel@tonic-gate 			objp->prev->next = objp->next;
9247c478bd9Sstevel@tonic-gate 			objp->next->prev = objp->prev;
9257c478bd9Sstevel@tonic-gate 		} else {
9267c478bd9Sstevel@tonic-gate 			/* Object is the last one in the list. */
9277c478bd9Sstevel@tonic-gate 			objp->prev->next = NULL;
9287c478bd9Sstevel@tonic-gate 		}
9297c478bd9Sstevel@tonic-gate 	}
9307c478bd9Sstevel@tonic-gate 
9317c478bd9Sstevel@tonic-gate 	if (!lock_held)
9327c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
9337c478bd9Sstevel@tonic-gate }
9347c478bd9Sstevel@tonic-gate 
9357c478bd9Sstevel@tonic-gate void
soft_delete_token_object(soft_object_t * objp,boolean_t persistent,boolean_t lock_held)9367c478bd9Sstevel@tonic-gate soft_delete_token_object(soft_object_t *objp, boolean_t persistent,
9377c478bd9Sstevel@tonic-gate     boolean_t lock_held)
9387c478bd9Sstevel@tonic-gate {
9397c478bd9Sstevel@tonic-gate 
9404d25c1d6Smcpowers 	if (!lock_held)
9414d25c1d6Smcpowers 		(void) pthread_mutex_lock(&soft_slot.slot_mutex);
9427c478bd9Sstevel@tonic-gate 	if (persistent)
9437c478bd9Sstevel@tonic-gate 		/* Delete the object from the keystore. */
9447c478bd9Sstevel@tonic-gate 		(void) soft_keystore_del_obj(&objp->ks_handle, B_FALSE);
9457c478bd9Sstevel@tonic-gate 
9467c478bd9Sstevel@tonic-gate 	/* Remove the object from the slot's token object list. */
9474d25c1d6Smcpowers 	soft_remove_token_object_from_slot(objp, B_TRUE);
9484d25c1d6Smcpowers 	if (!lock_held)
9494d25c1d6Smcpowers 		(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
9507c478bd9Sstevel@tonic-gate 
9511f49a79aSZdenek Kotala 	soft_delete_object_cleanup(objp, B_FALSE);
9527c478bd9Sstevel@tonic-gate }
9537c478bd9Sstevel@tonic-gate 
9547c478bd9Sstevel@tonic-gate void
soft_delete_all_in_core_token_objects(token_obj_type_t type)9557c478bd9Sstevel@tonic-gate soft_delete_all_in_core_token_objects(token_obj_type_t type)
9567c478bd9Sstevel@tonic-gate {
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 	soft_object_t *objp;
9597c478bd9Sstevel@tonic-gate 	soft_object_t *objp1;
9607c478bd9Sstevel@tonic-gate 
9617c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_slot.slot_mutex);
9627c478bd9Sstevel@tonic-gate 	objp = soft_slot.token_object_list;
9637c478bd9Sstevel@tonic-gate 
9647c478bd9Sstevel@tonic-gate 	switch (type) {
9657c478bd9Sstevel@tonic-gate 	case PRIVATE_TOKEN:
9667c478bd9Sstevel@tonic-gate 		while (objp) {
9677c478bd9Sstevel@tonic-gate 			objp1 = objp->next;
9687c478bd9Sstevel@tonic-gate 			if (objp->object_type == TOKEN_PRIVATE) {
9697c478bd9Sstevel@tonic-gate 				soft_delete_token_object(objp, B_FALSE, B_TRUE);
9707c478bd9Sstevel@tonic-gate 			}
9717c478bd9Sstevel@tonic-gate 			objp = objp1;
9727c478bd9Sstevel@tonic-gate 		}
9737c478bd9Sstevel@tonic-gate 		break;
9747c478bd9Sstevel@tonic-gate 
9757c478bd9Sstevel@tonic-gate 	case PUBLIC_TOKEN:
9767c478bd9Sstevel@tonic-gate 		while (objp) {
9777c478bd9Sstevel@tonic-gate 			objp1 = objp->next;
9787c478bd9Sstevel@tonic-gate 			if (objp->object_type == TOKEN_PUBLIC) {
9797c478bd9Sstevel@tonic-gate 				soft_delete_token_object(objp, B_FALSE, B_TRUE);
9807c478bd9Sstevel@tonic-gate 			}
9817c478bd9Sstevel@tonic-gate 			objp = objp1;
9827c478bd9Sstevel@tonic-gate 		}
9837c478bd9Sstevel@tonic-gate 		break;
9847c478bd9Sstevel@tonic-gate 
9857c478bd9Sstevel@tonic-gate 	case ALL_TOKEN:
9867c478bd9Sstevel@tonic-gate 		while (objp) {
9877c478bd9Sstevel@tonic-gate 			objp1 = objp->next;
9887c478bd9Sstevel@tonic-gate 			soft_delete_token_object(objp, B_FALSE, B_TRUE);
9897c478bd9Sstevel@tonic-gate 			objp = objp1;
9907c478bd9Sstevel@tonic-gate 		}
9917c478bd9Sstevel@tonic-gate 		break;
9927c478bd9Sstevel@tonic-gate 	}
9937c478bd9Sstevel@tonic-gate 
9947c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
9957c478bd9Sstevel@tonic-gate 
9967c478bd9Sstevel@tonic-gate }
9977c478bd9Sstevel@tonic-gate 
9987c478bd9Sstevel@tonic-gate /*
99990e0e8c4Sizick  * Mark all the token objects in the global list to be valid.
10007c478bd9Sstevel@tonic-gate  */
10017c478bd9Sstevel@tonic-gate void
soft_validate_token_objects(boolean_t validate)10027c478bd9Sstevel@tonic-gate soft_validate_token_objects(boolean_t validate)
10037c478bd9Sstevel@tonic-gate {
10047c478bd9Sstevel@tonic-gate 
10057c478bd9Sstevel@tonic-gate 	soft_object_t *objp;
10067c478bd9Sstevel@tonic-gate 
10077c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_slot.slot_mutex);
100890e0e8c4Sizick 
10097c478bd9Sstevel@tonic-gate 	objp = soft_slot.token_object_list;
10107c478bd9Sstevel@tonic-gate 
10117c478bd9Sstevel@tonic-gate 	while (objp) {
10127c478bd9Sstevel@tonic-gate 		if (validate)
10137c478bd9Sstevel@tonic-gate 			objp->magic_marker = SOFTTOKEN_OBJECT_MAGIC;
10147c478bd9Sstevel@tonic-gate 		else
10157c478bd9Sstevel@tonic-gate 			objp->magic_marker = 0;
10167c478bd9Sstevel@tonic-gate 
10177c478bd9Sstevel@tonic-gate 		objp = objp->next;
10187c478bd9Sstevel@tonic-gate 	}
10197c478bd9Sstevel@tonic-gate 
10207c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_slot.slot_mutex);
10217c478bd9Sstevel@tonic-gate 
10227c478bd9Sstevel@tonic-gate }
10237c478bd9Sstevel@tonic-gate 
10247c478bd9Sstevel@tonic-gate /*
10257c478bd9Sstevel@tonic-gate  * Verify user's write access rule to the token object.
10267c478bd9Sstevel@tonic-gate  */
10277c478bd9Sstevel@tonic-gate CK_RV
soft_object_write_access_check(soft_session_t * sp,soft_object_t * objp)10287c478bd9Sstevel@tonic-gate soft_object_write_access_check(soft_session_t *sp, soft_object_t *objp)
10297c478bd9Sstevel@tonic-gate {
10307c478bd9Sstevel@tonic-gate 
10317c478bd9Sstevel@tonic-gate 	/*
10327c478bd9Sstevel@tonic-gate 	 * This function is called by C_CreateObject, C_CopyObject,
10337c478bd9Sstevel@tonic-gate 	 * C_DestroyObject, C_SetAttributeValue, C_GenerateKey,
10347c478bd9Sstevel@tonic-gate 	 * C_GenerateKeyPairs, C_DeriveKey. All of them will write
10357c478bd9Sstevel@tonic-gate 	 * the token object to the keystore.
10367c478bd9Sstevel@tonic-gate 	 */
10377c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_giant_mutex);
10387c478bd9Sstevel@tonic-gate 	if (!soft_slot.authenticated) {
10397c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
10407c478bd9Sstevel@tonic-gate 		/* User is not logged in */
10417c478bd9Sstevel@tonic-gate 		if (sp->flags & CKF_RW_SESSION) {
10427c478bd9Sstevel@tonic-gate 			/*
10437c478bd9Sstevel@tonic-gate 			 * For R/W Public Session:
10447c478bd9Sstevel@tonic-gate 			 * we allow write access to public session or token
10457c478bd9Sstevel@tonic-gate 			 * object, but not for private token/session object.
10467c478bd9Sstevel@tonic-gate 			 */
10477c478bd9Sstevel@tonic-gate 			if ((objp->object_type == TOKEN_PRIVATE) ||
1048c2e31228SViswanathan Kannappan 			    (objp->object_type == SESSION_PRIVATE)) {
10497c478bd9Sstevel@tonic-gate 				return (CKR_USER_NOT_LOGGED_IN);
10507c478bd9Sstevel@tonic-gate 			}
10517c478bd9Sstevel@tonic-gate 		} else {
10527c478bd9Sstevel@tonic-gate 			/*
10537c478bd9Sstevel@tonic-gate 			 * For R/O Public Session:
10547c478bd9Sstevel@tonic-gate 			 * we allow write access to public session object.
10557c478bd9Sstevel@tonic-gate 			 */
10567c478bd9Sstevel@tonic-gate 			if (objp->object_type != SESSION_PUBLIC)
10577c478bd9Sstevel@tonic-gate 				return (CKR_SESSION_READ_ONLY);
10587c478bd9Sstevel@tonic-gate 		}
10597c478bd9Sstevel@tonic-gate 	} else {
10607c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
10617c478bd9Sstevel@tonic-gate 		/* User is logged in */
10627c478bd9Sstevel@tonic-gate 		if (!(sp->flags & CKF_RW_SESSION)) {
10637c478bd9Sstevel@tonic-gate 			/*
10647c478bd9Sstevel@tonic-gate 			 * For R/O User Function Session:
10657c478bd9Sstevel@tonic-gate 			 * we allow write access to public or private
10667c478bd9Sstevel@tonic-gate 			 * session object, but not for public or private
10677c478bd9Sstevel@tonic-gate 			 * token object.
10687c478bd9Sstevel@tonic-gate 			 */
10697c478bd9Sstevel@tonic-gate 			if ((objp->object_type == TOKEN_PUBLIC) ||
10707c478bd9Sstevel@tonic-gate 			    (objp->object_type == TOKEN_PRIVATE)) {
10717c478bd9Sstevel@tonic-gate 				return (CKR_SESSION_READ_ONLY);
10727c478bd9Sstevel@tonic-gate 			}
10737c478bd9Sstevel@tonic-gate 		}
10747c478bd9Sstevel@tonic-gate 	}
10757c478bd9Sstevel@tonic-gate 
10767c478bd9Sstevel@tonic-gate 	return (CKR_OK);
10777c478bd9Sstevel@tonic-gate }
10787c478bd9Sstevel@tonic-gate 
10797c478bd9Sstevel@tonic-gate /*
10807c478bd9Sstevel@tonic-gate  * Verify if user is required to setpin when accessing the
10817c478bd9Sstevel@tonic-gate  * private token/session object.
10827c478bd9Sstevel@tonic-gate  */
10837c478bd9Sstevel@tonic-gate CK_RV
soft_pin_expired_check(soft_object_t * objp)10847c478bd9Sstevel@tonic-gate soft_pin_expired_check(soft_object_t *objp)
10857c478bd9Sstevel@tonic-gate {
10867c478bd9Sstevel@tonic-gate 
10877c478bd9Sstevel@tonic-gate 	/*
10887c478bd9Sstevel@tonic-gate 	 * This function is called by C_CreateObject, C_CopyObject,
10897c478bd9Sstevel@tonic-gate 	 * C_DestroyObject, C_GenerateKey,
10907c478bd9Sstevel@tonic-gate 	 * C_GenerateKeyPairs, C_DeriveKey.
10917c478bd9Sstevel@tonic-gate 	 * All of them will return CKR_PIN_EXPIRED if the
10927c478bd9Sstevel@tonic-gate 	 * "userpin_change_needed" is set.
10937c478bd9Sstevel@tonic-gate 	 *
10947c478bd9Sstevel@tonic-gate 	 * The following functions will not be necessary to call
10957c478bd9Sstevel@tonic-gate 	 * this routine even though CKR_PIN_EXPIRED is one of the
10967c478bd9Sstevel@tonic-gate 	 * valid error code they might return. These functions are:
10977c478bd9Sstevel@tonic-gate 	 * C_EncryptInit, C_DecryptInit, C_DigestInit, C_SignInit,
10987c478bd9Sstevel@tonic-gate 	 * C_SignRecoverInit, C_VerifyInit, C_VerifyRecoverInit.
10997c478bd9Sstevel@tonic-gate 	 * This is because they will not get the object handle
11007c478bd9Sstevel@tonic-gate 	 * before the above functions are called.
11017c478bd9Sstevel@tonic-gate 	 */
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_giant_mutex);
11047c478bd9Sstevel@tonic-gate 	if (soft_slot.userpin_change_needed) {
11057c478bd9Sstevel@tonic-gate 		/*
11067c478bd9Sstevel@tonic-gate 		 * Access private token/session object but user's
11077c478bd9Sstevel@tonic-gate 		 * PIN is expired or never set.
11087c478bd9Sstevel@tonic-gate 		 */
11097c478bd9Sstevel@tonic-gate 		if ((objp->object_type == TOKEN_PRIVATE) ||
11107c478bd9Sstevel@tonic-gate 		    (objp->object_type == SESSION_PRIVATE)) {
11117c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&soft_giant_mutex);
11127c478bd9Sstevel@tonic-gate 			return (CKR_PIN_EXPIRED);
11137c478bd9Sstevel@tonic-gate 		}
11147c478bd9Sstevel@tonic-gate 	}
11157c478bd9Sstevel@tonic-gate 
11167c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&soft_giant_mutex);
11177c478bd9Sstevel@tonic-gate 	return (CKR_OK);
11187c478bd9Sstevel@tonic-gate }
11197c478bd9Sstevel@tonic-gate 
11207c478bd9Sstevel@tonic-gate /*
11217c478bd9Sstevel@tonic-gate  * Copy the selected fields from new token object to old
11227c478bd9Sstevel@tonic-gate  * token object.
11237c478bd9Sstevel@tonic-gate  */
11247c478bd9Sstevel@tonic-gate CK_RV
soft_copy_to_old_object(soft_object_t * new,soft_object_t * old)11257c478bd9Sstevel@tonic-gate soft_copy_to_old_object(soft_object_t *new, soft_object_t *old)
11267c478bd9Sstevel@tonic-gate {
11277c478bd9Sstevel@tonic-gate 
11287c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
11297c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE_INFO_PTR attrp;
11307c478bd9Sstevel@tonic-gate 
11317c478bd9Sstevel@tonic-gate 	old->class = new->class;
11327c478bd9Sstevel@tonic-gate 	old->bool_attr_mask = new->bool_attr_mask;
11337c478bd9Sstevel@tonic-gate 	soft_cleanup_extra_attr(old);
11347c478bd9Sstevel@tonic-gate 	attrp = new->extra_attrlistp;
11357c478bd9Sstevel@tonic-gate 	while (attrp) {
11367c478bd9Sstevel@tonic-gate 		rv = soft_copy_extra_attr(attrp, old);
11377c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
11387c478bd9Sstevel@tonic-gate 			soft_cleanup_extra_attr(old);
11397c478bd9Sstevel@tonic-gate 			return (rv);
11407c478bd9Sstevel@tonic-gate 		}
11417c478bd9Sstevel@tonic-gate 		attrp = attrp->next;
11427c478bd9Sstevel@tonic-gate 	}
11437c478bd9Sstevel@tonic-gate 
11447c478bd9Sstevel@tonic-gate 	/* Done with copying all information that can be modified */
11457c478bd9Sstevel@tonic-gate 	return (CKR_OK);
11467c478bd9Sstevel@tonic-gate }
11477c478bd9Sstevel@tonic-gate 
11487c478bd9Sstevel@tonic-gate /*
11497c478bd9Sstevel@tonic-gate  * Update an existing object with new data from keystore.
11507c478bd9Sstevel@tonic-gate  */
11517c478bd9Sstevel@tonic-gate CK_RV
soft_update_object(ks_obj_t * ks_obj,soft_object_t * old_obj)11527c478bd9Sstevel@tonic-gate soft_update_object(ks_obj_t *ks_obj, soft_object_t *old_obj)
11537c478bd9Sstevel@tonic-gate {
11547c478bd9Sstevel@tonic-gate 
11557c478bd9Sstevel@tonic-gate 	soft_object_t *new_object;
11567c478bd9Sstevel@tonic-gate 	CK_RV rv;
11577c478bd9Sstevel@tonic-gate 
11587c478bd9Sstevel@tonic-gate 	new_object = calloc(1, sizeof (soft_object_t));
11597c478bd9Sstevel@tonic-gate 	if (new_object == NULL)
11607c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	rv = soft_keystore_unpack_obj(new_object, ks_obj);
11637c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
11647c478bd9Sstevel@tonic-gate 		soft_cleanup_object(new_object);
11657c478bd9Sstevel@tonic-gate 		free(new_object);
11667c478bd9Sstevel@tonic-gate 		return (rv);
11677c478bd9Sstevel@tonic-gate 	}
11687c478bd9Sstevel@tonic-gate 	rv = soft_copy_to_old_object(new_object, old_obj);
11697c478bd9Sstevel@tonic-gate 
11707c478bd9Sstevel@tonic-gate 	soft_cleanup_object(new_object);
11717c478bd9Sstevel@tonic-gate 	free(new_object);
11727c478bd9Sstevel@tonic-gate 	return (CKR_OK);
11737c478bd9Sstevel@tonic-gate }
11747c478bd9Sstevel@tonic-gate 
11757c478bd9Sstevel@tonic-gate 
11767c478bd9Sstevel@tonic-gate CK_RV
soft_keystore_load_latest_object(soft_object_t * old_obj)11777c478bd9Sstevel@tonic-gate soft_keystore_load_latest_object(soft_object_t *old_obj)
11787c478bd9Sstevel@tonic-gate {
11797c478bd9Sstevel@tonic-gate 
11807c478bd9Sstevel@tonic-gate 	uint_t version;
11817c478bd9Sstevel@tonic-gate 	ks_obj_t *ks_obj = NULL;
11827c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 	/*
11857c478bd9Sstevel@tonic-gate 	 * Get the current version number from the keystore for
11867c478bd9Sstevel@tonic-gate 	 * the specified token object.
11877c478bd9Sstevel@tonic-gate 	 */
11887c478bd9Sstevel@tonic-gate 	if (soft_keystore_get_object_version(&old_obj->ks_handle, &version,
11897c478bd9Sstevel@tonic-gate 	    B_FALSE) == 1)
11907c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 	/*
11937c478bd9Sstevel@tonic-gate 	 * If the keystore version is newer than the in-core version,
11947c478bd9Sstevel@tonic-gate 	 * re-read the token object from the keystore.
11957c478bd9Sstevel@tonic-gate 	 */
11967c478bd9Sstevel@tonic-gate 	if (old_obj->version != version) {
11977c478bd9Sstevel@tonic-gate 		rv = soft_keystore_get_single_obj(&old_obj->ks_handle,
11987c478bd9Sstevel@tonic-gate 		    &ks_obj, B_FALSE);
11997c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
12007c478bd9Sstevel@tonic-gate 			return (rv);
12017c478bd9Sstevel@tonic-gate 		old_obj->version = version;
12027c478bd9Sstevel@tonic-gate 
12037c478bd9Sstevel@tonic-gate 		/*
12047c478bd9Sstevel@tonic-gate 		 * Update an existing object with new data from keystore.
12057c478bd9Sstevel@tonic-gate 		 */
12067c478bd9Sstevel@tonic-gate 		rv = soft_update_object(ks_obj, old_obj);
12077c478bd9Sstevel@tonic-gate 		free(ks_obj->buf);
12087c478bd9Sstevel@tonic-gate 		free(ks_obj);
12097c478bd9Sstevel@tonic-gate 	}
12107c478bd9Sstevel@tonic-gate 
12117c478bd9Sstevel@tonic-gate 	return (rv);
12127c478bd9Sstevel@tonic-gate }
12137c478bd9Sstevel@tonic-gate 
12147c478bd9Sstevel@tonic-gate /*
12157c478bd9Sstevel@tonic-gate  * Insert an object into a list of soft_object_t objects.  It is assumed
12167c478bd9Sstevel@tonic-gate  * that the object to be inserted doesn't previously belong to any list
12177c478bd9Sstevel@tonic-gate  */
12187c478bd9Sstevel@tonic-gate static void
insert_into_list(soft_object_t ** list,soft_object_t ** end_of_list,soft_object_t * objp)12197c478bd9Sstevel@tonic-gate insert_into_list(soft_object_t **list, soft_object_t **end_of_list,
12207c478bd9Sstevel@tonic-gate     soft_object_t *objp)
12217c478bd9Sstevel@tonic-gate {
12227c478bd9Sstevel@tonic-gate 	if (*list == NULL) {
12237c478bd9Sstevel@tonic-gate 		*list = objp;
12247c478bd9Sstevel@tonic-gate 		objp->next = NULL;
12257c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
12267c478bd9Sstevel@tonic-gate 		*end_of_list = objp;
12277c478bd9Sstevel@tonic-gate 	} else {
12287c478bd9Sstevel@tonic-gate 		(*list)->prev = objp;
12297c478bd9Sstevel@tonic-gate 		objp->next = *list;
12307c478bd9Sstevel@tonic-gate 		objp->prev = NULL;
12317c478bd9Sstevel@tonic-gate 		*list = objp;
12327c478bd9Sstevel@tonic-gate 	}
12337c478bd9Sstevel@tonic-gate }
12347c478bd9Sstevel@tonic-gate 
12357c478bd9Sstevel@tonic-gate /*
12367c478bd9Sstevel@tonic-gate  * Move an object from an existing list into a new list of
12377c478bd9Sstevel@tonic-gate  * soft_object_t objects.
12387c478bd9Sstevel@tonic-gate  */
12397c478bd9Sstevel@tonic-gate static void
move_into_list(soft_object_t ** existing_list,soft_object_t ** new_list,soft_object_t ** end_of_list,soft_object_t * objp)12407c478bd9Sstevel@tonic-gate move_into_list(soft_object_t **existing_list, soft_object_t **new_list,
12417c478bd9Sstevel@tonic-gate     soft_object_t **end_of_list, soft_object_t *objp)
12427c478bd9Sstevel@tonic-gate {
12437c478bd9Sstevel@tonic-gate 
12447c478bd9Sstevel@tonic-gate 	/* first, remove object from existing list */
12457c478bd9Sstevel@tonic-gate 	if (objp == *existing_list) {
12467c478bd9Sstevel@tonic-gate 		/* first item in list */
12477c478bd9Sstevel@tonic-gate 		if (objp->next) {
12487c478bd9Sstevel@tonic-gate 			*existing_list = objp->next;
12497c478bd9Sstevel@tonic-gate 			objp->next->prev = NULL;
12507c478bd9Sstevel@tonic-gate 		} else {
12517c478bd9Sstevel@tonic-gate 			*existing_list = NULL;
12527c478bd9Sstevel@tonic-gate 		}
12537c478bd9Sstevel@tonic-gate 	} else {
12547c478bd9Sstevel@tonic-gate 		if (objp->next) {
12557c478bd9Sstevel@tonic-gate 			objp->prev->next = objp->next;
12567c478bd9Sstevel@tonic-gate 			objp->next->prev = objp->prev;
12577c478bd9Sstevel@tonic-gate 		} else {
12587c478bd9Sstevel@tonic-gate 			objp->prev->next = NULL;
12597c478bd9Sstevel@tonic-gate 		}
12607c478bd9Sstevel@tonic-gate 	}
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 	/* then, add into new list */
12637c478bd9Sstevel@tonic-gate 	insert_into_list(new_list, end_of_list, objp);
12647c478bd9Sstevel@tonic-gate }
12657c478bd9Sstevel@tonic-gate 
12667c478bd9Sstevel@tonic-gate /*
12677c478bd9Sstevel@tonic-gate  * Insert "new_list" into "existing_list", new list will always be inserted
12687c478bd9Sstevel@tonic-gate  * into the front of existing list
12697c478bd9Sstevel@tonic-gate  */
12707c478bd9Sstevel@tonic-gate static void
insert_list_into_list(soft_object_t ** existing_list,soft_object_t * new_list,soft_object_t * end_new_list)12717c478bd9Sstevel@tonic-gate insert_list_into_list(soft_object_t **existing_list,
12727c478bd9Sstevel@tonic-gate     soft_object_t *new_list, soft_object_t *end_new_list)
12737c478bd9Sstevel@tonic-gate {
12747c478bd9Sstevel@tonic-gate 
12757c478bd9Sstevel@tonic-gate 	if (new_list == NULL) {
12767c478bd9Sstevel@tonic-gate 		return;
12777c478bd9Sstevel@tonic-gate 	}
12787c478bd9Sstevel@tonic-gate 
12797c478bd9Sstevel@tonic-gate 	if (*existing_list == NULL) {
12807c478bd9Sstevel@tonic-gate 		*existing_list = new_list;
12817c478bd9Sstevel@tonic-gate 	} else {
12827c478bd9Sstevel@tonic-gate 		(*existing_list)->prev = end_new_list;
12837c478bd9Sstevel@tonic-gate 		end_new_list->next = *existing_list;
12847c478bd9Sstevel@tonic-gate 		*existing_list = new_list;
12857c478bd9Sstevel@tonic-gate 	}
12867c478bd9Sstevel@tonic-gate }
12877c478bd9Sstevel@tonic-gate 
12887c478bd9Sstevel@tonic-gate static void
delete_all_objs_in_list(soft_object_t * list)12897c478bd9Sstevel@tonic-gate delete_all_objs_in_list(soft_object_t *list)
12907c478bd9Sstevel@tonic-gate {
12917c478bd9Sstevel@tonic-gate 	soft_object_t *objp, *objp_next;
12927c478bd9Sstevel@tonic-gate 
12937c478bd9Sstevel@tonic-gate 	if (list == NULL) {
12947c478bd9Sstevel@tonic-gate 		return;
12957c478bd9Sstevel@tonic-gate 	}
12967c478bd9Sstevel@tonic-gate 
12977c478bd9Sstevel@tonic-gate 	objp = list;
12987c478bd9Sstevel@tonic-gate 	while (objp) {
12997c478bd9Sstevel@tonic-gate 		objp_next = objp->next;
13001f49a79aSZdenek Kotala 		soft_delete_object_cleanup(objp, B_FALSE);
13017c478bd9Sstevel@tonic-gate 		objp = objp_next;
13027c478bd9Sstevel@tonic-gate 	}
13037c478bd9Sstevel@tonic-gate }
13047c478bd9Sstevel@tonic-gate 
13057c478bd9Sstevel@tonic-gate /*
13067c478bd9Sstevel@tonic-gate  * Makes sure that the list of in-core token objects are up to date
13077c478bd9Sstevel@tonic-gate  * with respect to the on disk keystore.  Other process/applications
13087c478bd9Sstevel@tonic-gate  * might have modified the keystore since the objects are last loaded
13097c478bd9Sstevel@tonic-gate  *
13107c478bd9Sstevel@tonic-gate  * If there's any error from refreshing the token object list (eg: unable
13117c478bd9Sstevel@tonic-gate  * to read, unable to unpack and object...etc), the in-core list
13127c478bd9Sstevel@tonic-gate  * will be restored back to the state before the refresh.  An error
13137c478bd9Sstevel@tonic-gate  * will be returned to indicate the failure.
13147c478bd9Sstevel@tonic-gate  *
13157c478bd9Sstevel@tonic-gate  * It is assumed that the caller holds the lock for the token slot
13167c478bd9Sstevel@tonic-gate  */
13177c478bd9Sstevel@tonic-gate CK_RV
refresh_token_objects()13187c478bd9Sstevel@tonic-gate refresh_token_objects()
13197c478bd9Sstevel@tonic-gate {
13207c478bd9Sstevel@tonic-gate 	uint_t on_disk_ks_version;
13217c478bd9Sstevel@tonic-gate 	ks_obj_t *on_disk_list = NULL, *tmp_on_disk, *next_on_disk;
13227c478bd9Sstevel@tonic-gate 	soft_object_t *in_core_obj, *tmp_incore_obj, *new_objp = NULL;
13237c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
13247c478bd9Sstevel@tonic-gate 
1325c2e31228SViswanathan Kannappan 	/* deleted in-core objects */
1326c2e31228SViswanathan Kannappan 	soft_object_t *del_objs_list = NULL;
1327c2e31228SViswanathan Kannappan 	soft_object_t *end_del_objs_list = NULL;
13287c478bd9Sstevel@tonic-gate 
1329c2e31228SViswanathan Kannappan 	/* modified in-core objects */
1330c2e31228SViswanathan Kannappan 	soft_object_t *mod_objs_list = NULL;
1331c2e31228SViswanathan Kannappan 	soft_object_t *end_mod_objs_list = NULL;
13327c478bd9Sstevel@tonic-gate 
1333c2e31228SViswanathan Kannappan 	/*
1334c2e31228SViswanathan Kannappan 	 * copy of modified in-core objects, in case we need
1335c2e31228SViswanathan Kannappan 	 * undo the change
1336c2e31228SViswanathan Kannappan 	 */
1337c2e31228SViswanathan Kannappan 	soft_object_t *copy_of_mod_objs_list = NULL;
1338c2e31228SViswanathan Kannappan 	soft_object_t *end_copy_of_mod_objs_list = NULL;
13397c478bd9Sstevel@tonic-gate 
1340c2e31228SViswanathan Kannappan 	/* objects to be added to the in-core list */
1341c2e31228SViswanathan Kannappan 	soft_object_t *added_objs_list = NULL;
1342c2e31228SViswanathan Kannappan 	soft_object_t *end_added_objs_list = NULL;
13437c478bd9Sstevel@tonic-gate 
13447c478bd9Sstevel@tonic-gate 	if (soft_keystore_get_version(&on_disk_ks_version, B_FALSE) != 0) {
13457c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
13467c478bd9Sstevel@tonic-gate 	}
13477c478bd9Sstevel@tonic-gate 
13487c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&soft_giant_mutex);
13497c478bd9Sstevel@tonic-gate 	if (on_disk_ks_version == soft_slot.ks_version) {
13507c478bd9Sstevel@tonic-gate 		/* no change */
13517c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
13527c478bd9Sstevel@tonic-gate 		return (CKR_OK);
13537c478bd9Sstevel@tonic-gate 	}
13547c478bd9Sstevel@tonic-gate 
13557c478bd9Sstevel@tonic-gate 	if (soft_slot.authenticated) {
13567c478bd9Sstevel@tonic-gate 		/* get both public and private objects */
13577c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
13587c478bd9Sstevel@tonic-gate 		rv = soft_keystore_get_objs(ALL_TOKENOBJS, &on_disk_list,
13597c478bd9Sstevel@tonic-gate 		    B_FALSE);
13607c478bd9Sstevel@tonic-gate 	} else {
13617c478bd9Sstevel@tonic-gate 		/* get both public objects only */
13627c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
13637c478bd9Sstevel@tonic-gate 		rv = soft_keystore_get_objs(PUB_TOKENOBJS, &on_disk_list,
13647c478bd9Sstevel@tonic-gate 		    B_FALSE);
13657c478bd9Sstevel@tonic-gate 	}
13667c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
13677c478bd9Sstevel@tonic-gate 		return (rv);
13687c478bd9Sstevel@tonic-gate 	}
13697c478bd9Sstevel@tonic-gate 
13707c478bd9Sstevel@tonic-gate 	/*
13717c478bd9Sstevel@tonic-gate 	 * The in-core tokens list will be updated as follows:
13727c478bd9Sstevel@tonic-gate 	 *
13737c478bd9Sstevel@tonic-gate 	 * Go through each item in the in-core tokens list.
13747c478bd9Sstevel@tonic-gate 	 * Try to match the in-core object with one of the
13757c478bd9Sstevel@tonic-gate 	 * objects from the on-disk list.  If a match is made,
13767c478bd9Sstevel@tonic-gate 	 * check the version number, and update in-core object
13777c478bd9Sstevel@tonic-gate 	 * as necessary.
13787c478bd9Sstevel@tonic-gate 	 *
13797c478bd9Sstevel@tonic-gate 	 * If there's no match between in-core object with on-disk
13807c478bd9Sstevel@tonic-gate 	 * object, that means the object is deleted since
13817c478bd9Sstevel@tonic-gate 	 * last loaded.  Will remove object from in-core list.
13827c478bd9Sstevel@tonic-gate 	 *
13837c478bd9Sstevel@tonic-gate 	 * When doing the matching of on-disk object list above,
13847c478bd9Sstevel@tonic-gate 	 * Delete every matched on-disk object from the on-disk list
13857c478bd9Sstevel@tonic-gate 	 * regardless the in-core object need to be deleted or not
13867c478bd9Sstevel@tonic-gate 	 *
13877c478bd9Sstevel@tonic-gate 	 * At the end of matching the in-core tokens list, if
13887c478bd9Sstevel@tonic-gate 	 * any object is still left on the on-disk object list,
13897c478bd9Sstevel@tonic-gate 	 * those are all new objects added since last load,
13907c478bd9Sstevel@tonic-gate 	 * include all of them to the in-core list
13917c478bd9Sstevel@tonic-gate 	 *
13927c478bd9Sstevel@tonic-gate 	 * Since we need to be able to revert the in-core list
13937c478bd9Sstevel@tonic-gate 	 * back to original state if there's any error with the refresh,
13947c478bd9Sstevel@tonic-gate 	 * we need to do the following.
13957c478bd9Sstevel@tonic-gate 	 * When an in-core object is "deleted", it is not immediately
13967c478bd9Sstevel@tonic-gate 	 * deleted.  It is moved to the list of "deleted_objects".
13977c478bd9Sstevel@tonic-gate 	 * When an in-core object is "modified", a copy of the
13987c478bd9Sstevel@tonic-gate 	 * unmodified object is made.  After the object is modified,
13997c478bd9Sstevel@tonic-gate 	 * it is temporarily moved to the "mod_objects" list
14007c478bd9Sstevel@tonic-gate 	 * from the in-core list.
14017c478bd9Sstevel@tonic-gate 	 * When the refresh is completed without any error,
14027c478bd9Sstevel@tonic-gate 	 * the actual deleted objects and unmodified objects is deleted.
14037c478bd9Sstevel@tonic-gate 	 */
14047c478bd9Sstevel@tonic-gate 	in_core_obj = soft_slot.token_object_list;
14057c478bd9Sstevel@tonic-gate 	while (in_core_obj) {
14067c478bd9Sstevel@tonic-gate 		/* try to match object with on_disk_list */
14077c478bd9Sstevel@tonic-gate 		ks_obj_t *ondisk_obj, *prev_ondisk_obj;
14087c478bd9Sstevel@tonic-gate 		boolean_t found = B_FALSE;
14097c478bd9Sstevel@tonic-gate 		soft_object_t *obj_copy;
14107c478bd9Sstevel@tonic-gate 
14117c478bd9Sstevel@tonic-gate 		ondisk_obj = on_disk_list;
14127c478bd9Sstevel@tonic-gate 		prev_ondisk_obj = NULL;
14137c478bd9Sstevel@tonic-gate 
14144d25c1d6Smcpowers 		/* larval object that has not been written to disk */
14154d25c1d6Smcpowers 		if (in_core_obj->ks_handle.name[0] == '\0') {
14164d25c1d6Smcpowers 			in_core_obj = in_core_obj->next;
14174d25c1d6Smcpowers 			continue;
14184d25c1d6Smcpowers 		}
14194d25c1d6Smcpowers 
14207c478bd9Sstevel@tonic-gate 		while ((!found) && (ondisk_obj != NULL)) {
14217c478bd9Sstevel@tonic-gate 
14227c478bd9Sstevel@tonic-gate 			if (strcmp((char *)((ondisk_obj->ks_handle).name),
14237c478bd9Sstevel@tonic-gate 			    (char *)((in_core_obj->ks_handle).name)) == 0) {
14247c478bd9Sstevel@tonic-gate 
14257c478bd9Sstevel@tonic-gate 				/* found a match */
14267c478bd9Sstevel@tonic-gate 				found = B_TRUE;
14277c478bd9Sstevel@tonic-gate 
14287c478bd9Sstevel@tonic-gate 				/* update in-core obj if necessary */
14297c478bd9Sstevel@tonic-gate 				if (ondisk_obj->obj_version !=
14307c478bd9Sstevel@tonic-gate 				    in_core_obj->version) {
14317c478bd9Sstevel@tonic-gate 					/* make a copy of before updating */
14327c478bd9Sstevel@tonic-gate 					rv = soft_copy_object(in_core_obj,
14337c478bd9Sstevel@tonic-gate 					    &obj_copy, SOFT_COPY_OBJ_ORIG_SH,
14347c478bd9Sstevel@tonic-gate 					    NULL);
14357c478bd9Sstevel@tonic-gate 					if (rv != CKR_OK) {
14367c478bd9Sstevel@tonic-gate 						goto cleanup;
14377c478bd9Sstevel@tonic-gate 					}
14387c478bd9Sstevel@tonic-gate 					insert_into_list(
14397c478bd9Sstevel@tonic-gate 					    &copy_of_mod_objs_list,
14407c478bd9Sstevel@tonic-gate 					    &end_copy_of_mod_objs_list,
14417c478bd9Sstevel@tonic-gate 					    obj_copy);
14427c478bd9Sstevel@tonic-gate 
14437c478bd9Sstevel@tonic-gate 					rv = soft_update_object(ondisk_obj,
14447c478bd9Sstevel@tonic-gate 					    in_core_obj);
14457c478bd9Sstevel@tonic-gate 					if (rv != CKR_OK) {
14467c478bd9Sstevel@tonic-gate 						goto cleanup;
14477c478bd9Sstevel@tonic-gate 					}
14487c478bd9Sstevel@tonic-gate 					move_into_list(
14497c478bd9Sstevel@tonic-gate 					    &(soft_slot.token_object_list),
14507c478bd9Sstevel@tonic-gate 					    &mod_objs_list, &end_mod_objs_list,
14517c478bd9Sstevel@tonic-gate 					    in_core_obj);
14527c478bd9Sstevel@tonic-gate 				}
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 				/* remove processed obj from on disk list */
14557c478bd9Sstevel@tonic-gate 				if (ondisk_obj == on_disk_list) {
14567c478bd9Sstevel@tonic-gate 					/* first item */
14577c478bd9Sstevel@tonic-gate 					on_disk_list = ondisk_obj->next;
14587c478bd9Sstevel@tonic-gate 				} else {
14597c478bd9Sstevel@tonic-gate 					prev_ondisk_obj->next =
14607c478bd9Sstevel@tonic-gate 					    ondisk_obj->next;
14617c478bd9Sstevel@tonic-gate 				}
14627c478bd9Sstevel@tonic-gate 				free(ondisk_obj->buf);
14637c478bd9Sstevel@tonic-gate 				free(ondisk_obj);
14647c478bd9Sstevel@tonic-gate 			} else {
14657c478bd9Sstevel@tonic-gate 				prev_ondisk_obj = ondisk_obj;
14667c478bd9Sstevel@tonic-gate 				ondisk_obj = ondisk_obj->next;
14677c478bd9Sstevel@tonic-gate 			}
14687c478bd9Sstevel@tonic-gate 		}
14697c478bd9Sstevel@tonic-gate 
14707c478bd9Sstevel@tonic-gate 		if (!found) {
14717c478bd9Sstevel@tonic-gate 			tmp_incore_obj = in_core_obj->next;
14727c478bd9Sstevel@tonic-gate 			move_into_list(&(soft_slot.token_object_list),
14737c478bd9Sstevel@tonic-gate 			    &del_objs_list, &end_del_objs_list, in_core_obj);
14747c478bd9Sstevel@tonic-gate 			in_core_obj = tmp_incore_obj;
14757c478bd9Sstevel@tonic-gate 		} else {
14767c478bd9Sstevel@tonic-gate 			in_core_obj = in_core_obj->next;
14777c478bd9Sstevel@tonic-gate 		}
14787c478bd9Sstevel@tonic-gate 	}
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	/*
14817c478bd9Sstevel@tonic-gate 	 * At this point, if there's still anything on the on_disk_list, they
14827c478bd9Sstevel@tonic-gate 	 * are all newly added objects since in-core list last loaded.
14837c478bd9Sstevel@tonic-gate 	 * include all of them into the in-core list
14847c478bd9Sstevel@tonic-gate 	 */
14857c478bd9Sstevel@tonic-gate 	next_on_disk = on_disk_list;
14867c478bd9Sstevel@tonic-gate 	while (next_on_disk) {
14877c478bd9Sstevel@tonic-gate 		new_objp = calloc(1, sizeof (soft_object_t));
14887c478bd9Sstevel@tonic-gate 		if (new_objp == NULL) {
14897c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
14907c478bd9Sstevel@tonic-gate 			goto cleanup;
14917c478bd9Sstevel@tonic-gate 		}
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 		/* Convert the keystore format to memory format */
14947c478bd9Sstevel@tonic-gate 		rv = soft_keystore_unpack_obj(new_objp, next_on_disk);
14957c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
14967c478bd9Sstevel@tonic-gate 			soft_cleanup_object(new_objp);
14977c478bd9Sstevel@tonic-gate 			free(new_objp);
14987c478bd9Sstevel@tonic-gate 			goto cleanup;
14997c478bd9Sstevel@tonic-gate 		}
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 		insert_into_list(&added_objs_list, &end_added_objs_list,
15027c478bd9Sstevel@tonic-gate 		    new_objp);
15037c478bd9Sstevel@tonic-gate 
15047c478bd9Sstevel@tonic-gate 		/* free the on_disk object */
15057c478bd9Sstevel@tonic-gate 		tmp_on_disk = next_on_disk;
15067c478bd9Sstevel@tonic-gate 		next_on_disk = tmp_on_disk->next;
15077c478bd9Sstevel@tonic-gate 		free(tmp_on_disk->buf);
15087c478bd9Sstevel@tonic-gate 		free(tmp_on_disk);
15097c478bd9Sstevel@tonic-gate 	}
15107c478bd9Sstevel@tonic-gate 
15117c478bd9Sstevel@tonic-gate 	if (rv == CKR_OK) {
15127c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&soft_giant_mutex);
15137c478bd9Sstevel@tonic-gate 		soft_slot.ks_version = on_disk_ks_version;
15147c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&soft_giant_mutex);
15157c478bd9Sstevel@tonic-gate 
15167c478bd9Sstevel@tonic-gate 		/* add the new objects into in-core list */
15177c478bd9Sstevel@tonic-gate 		insert_list_into_list(&(soft_slot.token_object_list),
15187c478bd9Sstevel@tonic-gate 		    added_objs_list, end_added_objs_list);
15197c478bd9Sstevel@tonic-gate 
15207c478bd9Sstevel@tonic-gate 		/* add modified objects back into the in-core list */
15217c478bd9Sstevel@tonic-gate 		insert_list_into_list(&(soft_slot.token_object_list),
15227c478bd9Sstevel@tonic-gate 		    mod_objs_list, end_mod_objs_list);
15237c478bd9Sstevel@tonic-gate 
15247c478bd9Sstevel@tonic-gate 		/* actually remove deleted objs, and copy of modified objs */
15257c478bd9Sstevel@tonic-gate 		delete_all_objs_in_list(copy_of_mod_objs_list);
15267c478bd9Sstevel@tonic-gate 		delete_all_objs_in_list(del_objs_list);
15277c478bd9Sstevel@tonic-gate 	}
15287c478bd9Sstevel@tonic-gate 
15297c478bd9Sstevel@tonic-gate 	return (rv);
15307c478bd9Sstevel@tonic-gate 
15317c478bd9Sstevel@tonic-gate cleanup:
15327c478bd9Sstevel@tonic-gate 	next_on_disk = on_disk_list;
15337c478bd9Sstevel@tonic-gate 	while (next_on_disk) {
15347c478bd9Sstevel@tonic-gate 		tmp_on_disk = next_on_disk;
15357c478bd9Sstevel@tonic-gate 		next_on_disk = tmp_on_disk->next;
15367c478bd9Sstevel@tonic-gate 		free(tmp_on_disk->buf);
15377c478bd9Sstevel@tonic-gate 		free(tmp_on_disk);
15387c478bd9Sstevel@tonic-gate 	}
15397c478bd9Sstevel@tonic-gate 
15407c478bd9Sstevel@tonic-gate 	/*
15417c478bd9Sstevel@tonic-gate 	 * restore the in-core list back to the original state by adding
15427c478bd9Sstevel@tonic-gate 	 * copy of original objects and deleted objects back to list
15437c478bd9Sstevel@tonic-gate 	 */
15447c478bd9Sstevel@tonic-gate 	insert_list_into_list(&(soft_slot.token_object_list),
15457c478bd9Sstevel@tonic-gate 	    del_objs_list, end_del_objs_list);
15467c478bd9Sstevel@tonic-gate 	insert_list_into_list(&(soft_slot.token_object_list),
15477c478bd9Sstevel@tonic-gate 	    copy_of_mod_objs_list, end_copy_of_mod_objs_list);
15487c478bd9Sstevel@tonic-gate 
15497c478bd9Sstevel@tonic-gate 	/*
15507c478bd9Sstevel@tonic-gate 	 * remove the modified objects, and newly objects list
15517c478bd9Sstevel@tonic-gate 	 */
15527c478bd9Sstevel@tonic-gate 	delete_all_objs_in_list(mod_objs_list);
15537c478bd9Sstevel@tonic-gate 	delete_all_objs_in_list(added_objs_list);
15547c478bd9Sstevel@tonic-gate 	return (rv);
15557c478bd9Sstevel@tonic-gate }
1556726fad2aSDina K Nimeh 
1557726fad2aSDina K Nimeh CK_RV
dup_bigint_attr(biginteger_t * bi,CK_BYTE * buf,CK_ULONG buflen)1558726fad2aSDina K Nimeh dup_bigint_attr(biginteger_t *bi, CK_BYTE *buf, CK_ULONG buflen)
1559726fad2aSDina K Nimeh {
1560726fad2aSDina K Nimeh 	bi->big_value_len = buflen;
1561726fad2aSDina K Nimeh 	if ((bi->big_value = malloc(buflen)) == NULL) {
1562726fad2aSDina K Nimeh 		return (CKR_HOST_MEMORY);
1563726fad2aSDina K Nimeh 	}
1564726fad2aSDina K Nimeh 	(void) memcpy(bi->big_value, buf, buflen);
1565726fad2aSDina K Nimeh 	return (CKR_OK);
1566726fad2aSDina K Nimeh }
1567