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