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 ©_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