xref: /titanic_51/usr/src/lib/pkcs11/libpkcs11/common/metaObjectManager.c (revision 5893fa693b6b67559d0bfdbcab5e1cf0307e6133)
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 /*
22*5893fa69SDan OpenSolaris Anderson  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
237c478bd9Sstevel@tonic-gate  */
247c478bd9Sstevel@tonic-gate 
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <stdlib.h>
277c478bd9Sstevel@tonic-gate #include <string.h>
287c478bd9Sstevel@tonic-gate #include <strings.h>
297c478bd9Sstevel@tonic-gate #include <errno.h>
307c478bd9Sstevel@tonic-gate #include <fcntl.h>
317c478bd9Sstevel@tonic-gate #include <sys/types.h>
327c478bd9Sstevel@tonic-gate #include <sys/stat.h>
337c478bd9Sstevel@tonic-gate #include "metaGlobal.h"
347c478bd9Sstevel@tonic-gate 
357c478bd9Sstevel@tonic-gate /* Size of the template for creating key used for wrap/unwrap */
367c478bd9Sstevel@tonic-gate #define	WRAP_KEY_TEMPLATE_SIZE	7
377c478bd9Sstevel@tonic-gate 
387c478bd9Sstevel@tonic-gate /*
397c478bd9Sstevel@tonic-gate  * Information necessary to create keys for C_WrapKey/C_UnwrapKey
407c478bd9Sstevel@tonic-gate  */
417c478bd9Sstevel@tonic-gate typedef struct _wrap_info {
427c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS		class; /* class of the key for wrap/unwrap */
437c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE		key_type; /* key type of key for wrap/unwrap */
447c478bd9Sstevel@tonic-gate 	CK_ULONG		key_length; /* length of key */
457c478bd9Sstevel@tonic-gate 	CK_MECHANISM_TYPE	mech_type; /* mech used for wrap/unwrap */
467c478bd9Sstevel@tonic-gate 	CK_ULONG		iv_length; /* length of iv for mech */
477c478bd9Sstevel@tonic-gate 
487c478bd9Sstevel@tonic-gate 	boolean_t		src_supports;
497c478bd9Sstevel@tonic-gate 	boolean_t		dst_supports;
507c478bd9Sstevel@tonic-gate } wrap_info_t;
517c478bd9Sstevel@tonic-gate 
527c478bd9Sstevel@tonic-gate extern pthread_rwlock_t meta_sessionlist_lock;
537c478bd9Sstevel@tonic-gate extern meta_session_t *meta_sessionlist_head;
547c478bd9Sstevel@tonic-gate 
557c478bd9Sstevel@tonic-gate static wrap_info_t common_wrap_info[] = {
567c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_AES, 16, CKM_AES_CBC_PAD, 16, B_FALSE, B_FALSE},
577c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_DES3, 24, CKM_DES3_CBC_PAD, 8, B_FALSE, B_FALSE},
587c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_DES, 8, CKM_DES_CBC_PAD, 8, B_FALSE, B_FALSE},
597c478bd9Sstevel@tonic-gate };
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate static unsigned int num_common_wrap_info =
627c478bd9Sstevel@tonic-gate     sizeof (common_wrap_info) / sizeof (wrap_info_t);
637c478bd9Sstevel@tonic-gate 
647c478bd9Sstevel@tonic-gate static wrap_info_t special_wrap_info[] = {
657c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_SKIPJACK, 12,  CKM_SKIPJACK_WRAP, 0,
667c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
677c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_BATON, 40, CKM_BATON_WRAP, 0,
687c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
697c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_JUNIPER, 40, CKM_JUNIPER_WRAP, 0,
707c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
717c478bd9Sstevel@tonic-gate };
727c478bd9Sstevel@tonic-gate static unsigned int num_special_wrap_info =
737c478bd9Sstevel@tonic-gate     sizeof (special_wrap_info) / sizeof (wrap_info_t);
747c478bd9Sstevel@tonic-gate 
757c478bd9Sstevel@tonic-gate static wrap_info_t rsa_wrap_info[] = {
767c478bd9Sstevel@tonic-gate 	{CKO_PUBLIC_KEY, CKK_RSA, 0,  CKM_RSA_PKCS, 0,
777c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
787c478bd9Sstevel@tonic-gate 	{CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_X_509, 0,
797c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
807c478bd9Sstevel@tonic-gate };
817c478bd9Sstevel@tonic-gate static unsigned int num_rsa_wrap_info =
827c478bd9Sstevel@tonic-gate     sizeof (rsa_wrap_info) / sizeof (wrap_info_t);
837c478bd9Sstevel@tonic-gate 
847c478bd9Sstevel@tonic-gate 
857c478bd9Sstevel@tonic-gate static pthread_rwlock_t meta_objectclose_lock;
867c478bd9Sstevel@tonic-gate static pthread_rwlock_t tokenobject_list_lock;
877c478bd9Sstevel@tonic-gate static meta_object_t *tokenobject_list_head;
887c478bd9Sstevel@tonic-gate 
89034448feSmcpowers CK_BBOOL falsevalue = FALSE;
90034448feSmcpowers CK_BBOOL truevalue = TRUE;
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate /*
937c478bd9Sstevel@tonic-gate  * Public and private exponent, and Module value for
947c478bd9Sstevel@tonic-gate  * creating the RSA public/private key.
957c478bd9Sstevel@tonic-gate  *
967c478bd9Sstevel@tonic-gate  */
977c478bd9Sstevel@tonic-gate static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01};
987c478bd9Sstevel@tonic-gate CK_BYTE PriExpo[128] = {
997c478bd9Sstevel@tonic-gate 	0x8e, 0xc9, 0x70, 0x57, 0x6b, 0xcd, 0xfb, 0xa9,
1007c478bd9Sstevel@tonic-gate 	0x19, 0xad, 0xcd, 0x91, 0x69, 0xd5, 0x52, 0xec,
1017c478bd9Sstevel@tonic-gate 	0x72, 0x1e, 0x45, 0x15, 0x06, 0xdc, 0x65, 0x2d,
1027c478bd9Sstevel@tonic-gate 	0x98, 0xc4, 0xce, 0x33, 0x54, 0x15, 0x70, 0x8d,
1037c478bd9Sstevel@tonic-gate 	0xfa, 0x65, 0xea, 0x53, 0x44, 0xf3, 0x3e, 0x3f,
1047c478bd9Sstevel@tonic-gate 	0xb4, 0x4c, 0x60, 0xd5, 0x01, 0x2d, 0xa4, 0x12,
1057c478bd9Sstevel@tonic-gate 	0x99, 0xbf, 0x3f, 0x0b, 0xcd, 0xbb, 0x24, 0x10,
1067c478bd9Sstevel@tonic-gate 	0x60, 0x30, 0x5e, 0x58, 0xf8, 0x59, 0xaa, 0xd1,
1077c478bd9Sstevel@tonic-gate 	0x63, 0x3b, 0xbc, 0xcb, 0x94, 0x58, 0x38, 0x24,
1087c478bd9Sstevel@tonic-gate 	0xfc, 0x65, 0x25, 0xc5, 0xa6, 0x51, 0xa2, 0x2e,
1097c478bd9Sstevel@tonic-gate 	0xf1, 0x5e, 0xf5, 0xc1, 0xf5, 0x46, 0xf7, 0xbd,
1107c478bd9Sstevel@tonic-gate 	0xc7, 0x62, 0xa8, 0xe2, 0x27, 0xd6, 0x94, 0x5b,
1117c478bd9Sstevel@tonic-gate 	0xd3, 0xa2, 0xb5, 0x76, 0x42, 0x67, 0x6b, 0x86,
1127c478bd9Sstevel@tonic-gate 	0x91, 0x97, 0x4d, 0x07, 0x92, 0x00, 0x4a, 0xdf,
1137c478bd9Sstevel@tonic-gate 	0x0b, 0x65, 0x64, 0x05, 0x03, 0x48, 0x27, 0xeb,
1147c478bd9Sstevel@tonic-gate 	0xce, 0x9a, 0x49, 0x7f, 0x3e, 0x10, 0xe0, 0x01};
1157c478bd9Sstevel@tonic-gate 
1167c478bd9Sstevel@tonic-gate static CK_BYTE Modulus[128] = {
1177c478bd9Sstevel@tonic-gate 	0x94, 0x32, 0xb9, 0x12, 0x1d, 0x68, 0x2c, 0xda,
1187c478bd9Sstevel@tonic-gate 	0x2b, 0xe0, 0xe4, 0x97, 0x1b, 0x4d, 0xdc, 0x43,
1197c478bd9Sstevel@tonic-gate 	0xdf, 0x38, 0x6e, 0x7b, 0x9f, 0x07, 0x58, 0xae,
1207c478bd9Sstevel@tonic-gate 	0x9d, 0x82, 0x1e, 0xc7, 0xbc, 0x92, 0xbf, 0xd3,
1217c478bd9Sstevel@tonic-gate 	0xce, 0x00, 0xbb, 0x91, 0xc9, 0x79, 0x06, 0x03,
1227c478bd9Sstevel@tonic-gate 	0x1f, 0xbc, 0x9f, 0x94, 0x75, 0x29, 0x5f, 0xd7,
1237c478bd9Sstevel@tonic-gate 	0xc5, 0xf3, 0x73, 0x8a, 0xa4, 0x35, 0x43, 0x7a,
1247c478bd9Sstevel@tonic-gate 	0x00, 0x32, 0x97, 0x3e, 0x86, 0xef, 0x70, 0x6f,
1257c478bd9Sstevel@tonic-gate 	0x18, 0x56, 0x15, 0xaa, 0x6a, 0x87, 0xe7, 0x8d,
1267c478bd9Sstevel@tonic-gate 	0x7d, 0xdd, 0x1f, 0xa4, 0xe4, 0x31, 0xd4, 0x7a,
1277c478bd9Sstevel@tonic-gate 	0x8c, 0x0e, 0x20, 0xd2, 0x23, 0xf5, 0x57, 0x3c,
1287c478bd9Sstevel@tonic-gate 	0x1b, 0xa8, 0x44, 0xa4, 0x57, 0x8f, 0x33, 0x52,
1297c478bd9Sstevel@tonic-gate 	0xad, 0x83, 0xae, 0x4a, 0x97, 0xa6, 0x1e, 0xa6,
1307c478bd9Sstevel@tonic-gate 	0x2b, 0xfa, 0xea, 0xeb, 0x6e, 0x71, 0xb8, 0xb6,
1317c478bd9Sstevel@tonic-gate 	0x0a, 0x36, 0xed, 0x83, 0xce, 0xb0, 0xdf, 0xc1,
1327c478bd9Sstevel@tonic-gate 	0xd4, 0x3a, 0xe9, 0x99, 0x6f, 0xf3, 0x96, 0xb7};
1337c478bd9Sstevel@tonic-gate 
1347c478bd9Sstevel@tonic-gate static CK_RV
1357c478bd9Sstevel@tonic-gate meta_clone_template_setup(meta_object_t *object,
1367c478bd9Sstevel@tonic-gate     const generic_attr_t *attributes, size_t num_attributes);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate /*
1397c478bd9Sstevel@tonic-gate  * meta_objectManager_initialize
1407c478bd9Sstevel@tonic-gate  *
1417c478bd9Sstevel@tonic-gate  * Called from meta_Initialize.  Initializes all the variables used
1427c478bd9Sstevel@tonic-gate  * by the object manager.
1437c478bd9Sstevel@tonic-gate  */
1447c478bd9Sstevel@tonic-gate CK_RV
1457c478bd9Sstevel@tonic-gate meta_objectManager_initialize()
1467c478bd9Sstevel@tonic-gate {
1477c478bd9Sstevel@tonic-gate 	if (pthread_rwlock_init(&meta_objectclose_lock, NULL) != 0) {
1487c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
1497c478bd9Sstevel@tonic-gate 	}
1507c478bd9Sstevel@tonic-gate 
1517c478bd9Sstevel@tonic-gate 	if (pthread_rwlock_init(&tokenobject_list_lock, NULL) != 0) {
1527c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_destroy(&meta_objectclose_lock);
1537c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
1547c478bd9Sstevel@tonic-gate 	}
1557c478bd9Sstevel@tonic-gate 
1567c478bd9Sstevel@tonic-gate 	tokenobject_list_head = NULL;
1577c478bd9Sstevel@tonic-gate 
1587c478bd9Sstevel@tonic-gate 	return (CKR_OK);
1597c478bd9Sstevel@tonic-gate }
1607c478bd9Sstevel@tonic-gate 
1617c478bd9Sstevel@tonic-gate void
1627c478bd9Sstevel@tonic-gate meta_objectManager_finalize()
1637c478bd9Sstevel@tonic-gate {
1647c478bd9Sstevel@tonic-gate 	/*
1657c478bd9Sstevel@tonic-gate 	 * If there are still any token object in the list, need to
1667c478bd9Sstevel@tonic-gate 	 * deactivate all of them.
1677c478bd9Sstevel@tonic-gate 	 */
1687c478bd9Sstevel@tonic-gate 	(void) meta_token_object_deactivate(ALL_TOKEN);
1697c478bd9Sstevel@tonic-gate 
1707c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&meta_objectclose_lock);
1717c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&tokenobject_list_lock);
1727c478bd9Sstevel@tonic-gate }
1737c478bd9Sstevel@tonic-gate 
1747c478bd9Sstevel@tonic-gate 
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate /*
1777c478bd9Sstevel@tonic-gate  * meta_handle2object
1787c478bd9Sstevel@tonic-gate  *
1797c478bd9Sstevel@tonic-gate  * Convert a CK_OBJECT_HANDLE to the corresponding metaobject. If
1807c478bd9Sstevel@tonic-gate  * successful, a reader-lock on the object will be held to indicate
1817c478bd9Sstevel@tonic-gate  * that it's in use. Call OBJRELEASE() when finished.
1827c478bd9Sstevel@tonic-gate  *
1837c478bd9Sstevel@tonic-gate  */
1847c478bd9Sstevel@tonic-gate CK_RV
1857c478bd9Sstevel@tonic-gate meta_handle2object(CK_OBJECT_HANDLE hObject, meta_object_t **object)
1867c478bd9Sstevel@tonic-gate {
1877c478bd9Sstevel@tonic-gate 	meta_object_t *tmp_object = (meta_object_t *)(hObject);
1887c478bd9Sstevel@tonic-gate 
1897c478bd9Sstevel@tonic-gate 	/* Check for bad args (eg CK_INVALID_HANDLE, which is 0/NULL). */
1907c478bd9Sstevel@tonic-gate 	if (tmp_object == NULL) {
1917c478bd9Sstevel@tonic-gate 		*object = NULL;
1927c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
1937c478bd9Sstevel@tonic-gate 	}
1947c478bd9Sstevel@tonic-gate 
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 	/* Lock to ensure the magic-check + read-lock is atomic. */
1977c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&meta_objectclose_lock);
1987c478bd9Sstevel@tonic-gate 
1997c478bd9Sstevel@tonic-gate 	if (tmp_object->magic_marker != METASLOT_OBJECT_MAGIC) {
2007c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&meta_objectclose_lock);
2017c478bd9Sstevel@tonic-gate 		*object = NULL;
2027c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
2037c478bd9Sstevel@tonic-gate 	}
2047c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&tmp_object->object_lock);
2057c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&meta_objectclose_lock);
2067c478bd9Sstevel@tonic-gate 
2077c478bd9Sstevel@tonic-gate 	*object = tmp_object;
2087c478bd9Sstevel@tonic-gate 	return (CKR_OK);
2097c478bd9Sstevel@tonic-gate }
2107c478bd9Sstevel@tonic-gate 
2117c478bd9Sstevel@tonic-gate 
2127c478bd9Sstevel@tonic-gate /*
2137c478bd9Sstevel@tonic-gate  * meta_object_alloc
2147c478bd9Sstevel@tonic-gate  *
2157c478bd9Sstevel@tonic-gate  * Creates a new metaobject, but does not yet add it to the object list.
2167c478bd9Sstevel@tonic-gate  * Once the caller has finished initializing the object (by setting
2177c478bd9Sstevel@tonic-gate  * object attributes), meta_object_add should be called. This two-step
2187c478bd9Sstevel@tonic-gate  * process prevents others from seeing the object until fully intitialized.
2197c478bd9Sstevel@tonic-gate  *
2207c478bd9Sstevel@tonic-gate  */
2217c478bd9Sstevel@tonic-gate CK_RV
2227c478bd9Sstevel@tonic-gate meta_object_alloc(meta_session_t *session, meta_object_t **object)
2237c478bd9Sstevel@tonic-gate {
2247c478bd9Sstevel@tonic-gate 	meta_object_t *new_object;
2257c478bd9Sstevel@tonic-gate 	CK_ULONG num_slots;
2267c478bd9Sstevel@tonic-gate 
2277c478bd9Sstevel@tonic-gate 	/* Allocate memory for the object. */
2287c478bd9Sstevel@tonic-gate 	new_object = calloc(1, sizeof (meta_object_t));
2297c478bd9Sstevel@tonic-gate 	if (new_object == NULL)
2307c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2317c478bd9Sstevel@tonic-gate 
2327c478bd9Sstevel@tonic-gate 	num_slots = meta_slotManager_get_slotcount();
2337c478bd9Sstevel@tonic-gate 
2347c478bd9Sstevel@tonic-gate 	new_object->clones = calloc(num_slots, sizeof (slot_object_t *));
2357c478bd9Sstevel@tonic-gate 	if (new_object->clones == NULL) {
2367c478bd9Sstevel@tonic-gate 		free(new_object);
2377c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2387c478bd9Sstevel@tonic-gate 	}
2397c478bd9Sstevel@tonic-gate 
2407c478bd9Sstevel@tonic-gate 	new_object->tried_create_clone = calloc(num_slots, sizeof (boolean_t));
2417c478bd9Sstevel@tonic-gate 	if (new_object->tried_create_clone == NULL) {
2427c478bd9Sstevel@tonic-gate 		free(new_object->clones);
2437c478bd9Sstevel@tonic-gate 		free(new_object);
2447c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2457c478bd9Sstevel@tonic-gate 	}
2467c478bd9Sstevel@tonic-gate 
2477c478bd9Sstevel@tonic-gate 	/* Initialize the object fields. */
2487c478bd9Sstevel@tonic-gate 	new_object->magic_marker = METASLOT_OBJECT_MAGIC;
2497c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_init(&new_object->object_lock, NULL);
2507c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_init(&new_object->attribute_lock, NULL);
2517c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_object->clone_create_lock, NULL);
2527c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_object->isClosingObject_lock, NULL);
2537c478bd9Sstevel@tonic-gate 	new_object->creator_session = session;
2547c478bd9Sstevel@tonic-gate 
2557c478bd9Sstevel@tonic-gate 	*object = new_object;
2567c478bd9Sstevel@tonic-gate 
2577c478bd9Sstevel@tonic-gate 	return (CKR_OK);
2587c478bd9Sstevel@tonic-gate }
2597c478bd9Sstevel@tonic-gate 
2607c478bd9Sstevel@tonic-gate 
2617c478bd9Sstevel@tonic-gate /*
2627c478bd9Sstevel@tonic-gate  * meta_object_get_attr
2637c478bd9Sstevel@tonic-gate  *
2647c478bd9Sstevel@tonic-gate  * Get attribute values to fill in attribute values
2657c478bd9Sstevel@tonic-gate  * being kept in the metaslot object.  The following 4 attributes
2667c478bd9Sstevel@tonic-gate  * in the meta_object_t structure will be filled in:
2677c478bd9Sstevel@tonic-gate  * isToken, isPrivate, isSensitive, isExtractable
2687c478bd9Sstevel@tonic-gate  *
2697c478bd9Sstevel@tonic-gate  * It's basically an easy way to do a C_GetAttributeValue.
2707c478bd9Sstevel@tonic-gate  * So, the hSession argument is assumed
2717c478bd9Sstevel@tonic-gate  * to be valid, and the pointer to meta_object_t is also assumed
2727c478bd9Sstevel@tonic-gate  * to be valid.
2737c478bd9Sstevel@tonic-gate  */
2747c478bd9Sstevel@tonic-gate CK_RV
2757c478bd9Sstevel@tonic-gate meta_object_get_attr(slot_session_t *slot_session, CK_OBJECT_HANDLE hObject,
2767c478bd9Sstevel@tonic-gate     meta_object_t *object)
2777c478bd9Sstevel@tonic-gate {
278034448feSmcpowers 	CK_BBOOL is_sensitive = object->isSensitive;
279034448feSmcpowers 	CK_BBOOL is_extractable = object->isExtractable;
280034448feSmcpowers 	CK_BBOOL is_token = B_FALSE, is_private = B_FALSE;
281034448feSmcpowers 	CK_KEY_TYPE keytype;
2827c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class;
2837c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE attrs[3];
2847c478bd9Sstevel@tonic-gate 	CK_RV rv;
2857c478bd9Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession = slot_session->hSession;
2867c478bd9Sstevel@tonic-gate 	CK_SLOT_ID fw_st_id = slot_session->fw_st_id;
287034448feSmcpowers 	int count = 1;
2887c478bd9Sstevel@tonic-gate 
2897c478bd9Sstevel@tonic-gate 	attrs[0].type = CKA_CLASS;
2907c478bd9Sstevel@tonic-gate 	attrs[0].pValue = &class;
2917c478bd9Sstevel@tonic-gate 	attrs[0].ulValueLen = sizeof (class);
2927c478bd9Sstevel@tonic-gate 
293034448feSmcpowers 	if (object->isFreeObject != FREE_ENABLED) {
2947c478bd9Sstevel@tonic-gate 		attrs[1].type = CKA_TOKEN;
2957c478bd9Sstevel@tonic-gate 		attrs[1].pValue = &is_token;
2967c478bd9Sstevel@tonic-gate 		attrs[1].ulValueLen = sizeof (is_token);
297034448feSmcpowers 		count++;
298034448feSmcpowers 	}
2997c478bd9Sstevel@tonic-gate 
300034448feSmcpowers 	/*
301034448feSmcpowers 	 * If this is a freeobject, we already know the Private value
302034448feSmcpowers 	 * and we don't want to overwrite it with the wrong value
303034448feSmcpowers 	 */
304034448feSmcpowers 	if (object->isFreeObject <= FREE_DISABLED) {
305034448feSmcpowers 		attrs[count].type = CKA_PRIVATE;
306034448feSmcpowers 		attrs[count].pValue = &is_private;
307034448feSmcpowers 		attrs[count].ulValueLen = sizeof (is_private);
308034448feSmcpowers 		count++;
309034448feSmcpowers 	} else
310034448feSmcpowers 		is_private = object->isPrivate;
3117c478bd9Sstevel@tonic-gate 
3127c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
313034448feSmcpowers 	    attrs, count);
3147c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
3157c478bd9Sstevel@tonic-gate 		return (rv);
3167c478bd9Sstevel@tonic-gate 	}
3177c478bd9Sstevel@tonic-gate 
318034448feSmcpowers 	count = 0;
319034448feSmcpowers 	switch (class) {
320034448feSmcpowers 	case CKO_PRIVATE_KEY:
321034448feSmcpowers 	case CKO_SECRET_KEY:
322034448feSmcpowers 		/* Only need to check these for private & secret keys */
323034448feSmcpowers 		attrs[0].type = CKA_EXTRACTABLE;
324034448feSmcpowers 		attrs[0].pValue = &is_extractable;
325034448feSmcpowers 		attrs[0].ulValueLen = sizeof (is_extractable);
326034448feSmcpowers 		count = 1;
3277c478bd9Sstevel@tonic-gate 
3287c478bd9Sstevel@tonic-gate 		/*
329034448feSmcpowers 		 * If this is a freeobject, we already know the Sensitive
330034448feSmcpowers 		 * value and we don't want to overwrite it with the wrong
331034448feSmcpowers 		 * value.
3327c478bd9Sstevel@tonic-gate 		 */
3337c478bd9Sstevel@tonic-gate 
334034448feSmcpowers 		if (object->isFreeObject <= FREE_DISABLED) {
335034448feSmcpowers 			attrs[1].type = CKA_SENSITIVE;
336034448feSmcpowers 			attrs[1].pValue = &is_sensitive;
337034448feSmcpowers 			attrs[1].ulValueLen = sizeof (is_sensitive);
338034448feSmcpowers 			count = 2;
3397c478bd9Sstevel@tonic-gate 
340034448feSmcpowers 			/*
341034448feSmcpowers 			 * We only need the key type if this is the first
342034448feSmcpowers 			 * time we've looked at the object
343034448feSmcpowers 			 */
344034448feSmcpowers 			if (object->isFreeObject == FREE_UNCHECKED) {
345034448feSmcpowers 				attrs[2].type = CKA_KEY_TYPE;
346034448feSmcpowers 				attrs[2].pValue = &keytype;
347034448feSmcpowers 				attrs[2].ulValueLen = sizeof (keytype);
348034448feSmcpowers 				count = 3;
3497c478bd9Sstevel@tonic-gate 			}
350034448feSmcpowers 		}
351034448feSmcpowers 
352034448feSmcpowers 		break;
353034448feSmcpowers 
354034448feSmcpowers 	case CKO_PUBLIC_KEY:
355034448feSmcpowers 		if (object->isFreeObject == FREE_UNCHECKED) {
356034448feSmcpowers 			attrs[count].type = CKA_KEY_TYPE;
357034448feSmcpowers 			attrs[count].pValue = &keytype;
358034448feSmcpowers 			attrs[count].ulValueLen = sizeof (keytype);
359034448feSmcpowers 			count++;
360034448feSmcpowers 		}
3617c478bd9Sstevel@tonic-gate 		is_sensitive = CK_FALSE;
3627c478bd9Sstevel@tonic-gate 		is_extractable = CK_TRUE;
363034448feSmcpowers 		break;
364034448feSmcpowers 
365034448feSmcpowers 	default:
366034448feSmcpowers 		object->isFreeObject = FREE_DISABLED;
367034448feSmcpowers 		is_sensitive = CK_FALSE;
368034448feSmcpowers 		is_extractable = CK_TRUE;
369034448feSmcpowers 	};
370034448feSmcpowers 
371034448feSmcpowers 	if (count > 0) {
372034448feSmcpowers 		rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
373034448feSmcpowers 		    attrs, count);
374034448feSmcpowers 		if (rv != CKR_OK) {
375034448feSmcpowers 			return (rv);
376034448feSmcpowers 		}
377034448feSmcpowers 
378034448feSmcpowers 		if (object->isFreeObject == FREE_UNCHECKED) {
379034448feSmcpowers 			if (keytype == CKK_EC || keytype == CKK_RSA ||
380034448feSmcpowers 			    keytype == CKK_DH) {
381034448feSmcpowers 				if (metaslot_config.auto_key_migrate) {
382034448feSmcpowers 					object->isFreeObject = FREE_DISABLED;
383034448feSmcpowers 					object->isFreeToken = FREE_DISABLED;
384034448feSmcpowers 				}
385034448feSmcpowers 
386034448feSmcpowers 				object->isFreeObject = FREE_ENABLED;
387034448feSmcpowers 				if (is_token)
388034448feSmcpowers 					object->isFreeToken = FREE_ENABLED;
389034448feSmcpowers 			} else
390034448feSmcpowers 				object->isFreeObject = FREE_DISABLED;
391034448feSmcpowers 
392034448feSmcpowers 		}
393034448feSmcpowers 
3947c478bd9Sstevel@tonic-gate 	}
3957c478bd9Sstevel@tonic-gate 
3967c478bd9Sstevel@tonic-gate 	object->isToken = is_token;
3977c478bd9Sstevel@tonic-gate 	object->isPrivate = is_private;
3987c478bd9Sstevel@tonic-gate 	object->isSensitive = is_sensitive;
3997c478bd9Sstevel@tonic-gate 	object->isExtractable = is_extractable;
4007c478bd9Sstevel@tonic-gate 
4017c478bd9Sstevel@tonic-gate 	return (CKR_OK);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate 
4047c478bd9Sstevel@tonic-gate 
4057c478bd9Sstevel@tonic-gate /*
4067c478bd9Sstevel@tonic-gate  * meta_object_activate
4077c478bd9Sstevel@tonic-gate  *
4087c478bd9Sstevel@tonic-gate  * Add a new metaobject to the list of objects. See also meta_object_create,
4097c478bd9Sstevel@tonic-gate  * which would be called to create an object before it is added.
4107c478bd9Sstevel@tonic-gate  */
4117c478bd9Sstevel@tonic-gate void
4127c478bd9Sstevel@tonic-gate meta_object_activate(meta_object_t *new_object)
4137c478bd9Sstevel@tonic-gate {
4147c478bd9Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
4157c478bd9Sstevel@tonic-gate 	meta_object_t **list_head;
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 	/*
4187c478bd9Sstevel@tonic-gate 	 * For session objects, we keep the list in the session that created
4197c478bd9Sstevel@tonic-gate 	 * this object, because this object will be destroyed when that session
4207c478bd9Sstevel@tonic-gate 	 * is closed.
4217c478bd9Sstevel@tonic-gate 	 *
4227c478bd9Sstevel@tonic-gate 	 * For token objects, the list is global (ie, not associated with any
4237c478bd9Sstevel@tonic-gate 	 * particular session).
4247c478bd9Sstevel@tonic-gate 	 */
4257c478bd9Sstevel@tonic-gate 	if (new_object->isToken) {
4267c478bd9Sstevel@tonic-gate 		list_lock = &tokenobject_list_lock;
4277c478bd9Sstevel@tonic-gate 		list_head = &tokenobject_list_head;
4287c478bd9Sstevel@tonic-gate 	} else {
4297c478bd9Sstevel@tonic-gate 		list_lock = &new_object->creator_session->object_list_lock;
4307c478bd9Sstevel@tonic-gate 		list_head = &new_object->creator_session->object_list_head;
4317c478bd9Sstevel@tonic-gate 	}
4327c478bd9Sstevel@tonic-gate 
4337c478bd9Sstevel@tonic-gate 	/* Add object to the list of objects. */
4347c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(list_lock);
4357c478bd9Sstevel@tonic-gate 	INSERT_INTO_LIST(*list_head, new_object);
4367c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(list_lock);
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate 
4397c478bd9Sstevel@tonic-gate 
4407c478bd9Sstevel@tonic-gate /*
4417c478bd9Sstevel@tonic-gate  * meta_object_deactivate
4427c478bd9Sstevel@tonic-gate  *
4437c478bd9Sstevel@tonic-gate  * Removes the object from the list of valid meta objects.  Note
4447c478bd9Sstevel@tonic-gate  * that this function does not clean up any allocated
4457c478bd9Sstevel@tonic-gate  * resources (memory, object clones, etc).   Cleaning up of
4468cae6764SAnthony Scarpino  * allocated resources is done by calling the meta_object_dealloc()
4477c478bd9Sstevel@tonic-gate  *
4487c478bd9Sstevel@tonic-gate  */
4497c478bd9Sstevel@tonic-gate CK_RV
4507c478bd9Sstevel@tonic-gate meta_object_deactivate(meta_object_t *object, boolean_t have_list_lock,
4517c478bd9Sstevel@tonic-gate     boolean_t have_object_lock)
4527c478bd9Sstevel@tonic-gate {
4537c478bd9Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
4547c478bd9Sstevel@tonic-gate 	meta_object_t **list_head;
4557c478bd9Sstevel@tonic-gate 
4567c478bd9Sstevel@tonic-gate 	if (!have_object_lock) {
4577c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&object->object_lock);
4587c478bd9Sstevel@tonic-gate 	}
4597c478bd9Sstevel@tonic-gate 
4607c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object->isClosingObject_lock);
4617c478bd9Sstevel@tonic-gate 	if (object->isClosingObject) {
4627c478bd9Sstevel@tonic-gate 		/* Lost a delete race. */
4637c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object->isClosingObject_lock);
4647c478bd9Sstevel@tonic-gate 		OBJRELEASE(object);
4657c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
4667c478bd9Sstevel@tonic-gate 	}
4677c478bd9Sstevel@tonic-gate 	object->isClosingObject = B_TRUE;
4687c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object->isClosingObject_lock);
4697c478bd9Sstevel@tonic-gate 
4708cae6764SAnthony Scarpino 	if (object->isToken || (object->isFreeToken == FREE_ENABLED)) {
4717c478bd9Sstevel@tonic-gate 		list_lock = &tokenobject_list_lock;
4727c478bd9Sstevel@tonic-gate 		list_head = &tokenobject_list_head;
4737c478bd9Sstevel@tonic-gate 	} else {
4747c478bd9Sstevel@tonic-gate 		list_lock = &object->creator_session->object_list_lock;
4757c478bd9Sstevel@tonic-gate 		list_head = &object->creator_session->object_list_head;
4767c478bd9Sstevel@tonic-gate 	}
4777c478bd9Sstevel@tonic-gate 
4787c478bd9Sstevel@tonic-gate 	/*
4797c478bd9Sstevel@tonic-gate 	 * Remove object from the object list. Once removed, it will not
4807c478bd9Sstevel@tonic-gate 	 * be possible for another thread to begin using the object.
4817c478bd9Sstevel@tonic-gate 	 */
4827c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&meta_objectclose_lock);
4837c478bd9Sstevel@tonic-gate 	if (!have_list_lock) {
4847c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(list_lock);
4857c478bd9Sstevel@tonic-gate 	}
4867c478bd9Sstevel@tonic-gate 
4877c478bd9Sstevel@tonic-gate 
4887c478bd9Sstevel@tonic-gate 	object->magic_marker = METASLOT_OBJECT_BADMAGIC;
4897c478bd9Sstevel@tonic-gate 	/*
4907c478bd9Sstevel@tonic-gate 	 * Can't use the regular REMOVE_FROM_LIST() function because
4917c478bd9Sstevel@tonic-gate 	 * that will miss the "error cleanup" situation where object is not yet
4927c478bd9Sstevel@tonic-gate 	 * in the list (object->next == NULL && object->prev == NULL)
4937c478bd9Sstevel@tonic-gate 	 */
4947c478bd9Sstevel@tonic-gate 	if (*list_head == object) {
4957c478bd9Sstevel@tonic-gate 		/* Object is the first one in the list */
4967c478bd9Sstevel@tonic-gate 		if (object->next) {
4977c478bd9Sstevel@tonic-gate 			*list_head = object->next;
4987c478bd9Sstevel@tonic-gate 			object->next->prev = NULL;
4997c478bd9Sstevel@tonic-gate 		} else {
5007c478bd9Sstevel@tonic-gate 			/* Object is the only one in the list */
5017c478bd9Sstevel@tonic-gate 			*list_head = NULL;
5027c478bd9Sstevel@tonic-gate 		}
5037c478bd9Sstevel@tonic-gate 	} else if (object->next != NULL || object->prev != NULL) {
5047c478bd9Sstevel@tonic-gate 		if (object->next) {
5057c478bd9Sstevel@tonic-gate 			object->prev->next = object->next;
5067c478bd9Sstevel@tonic-gate 			object->next->prev = object->prev;
5077c478bd9Sstevel@tonic-gate 		} else {
5087c478bd9Sstevel@tonic-gate 			/* Object is the last one in the list */
5097c478bd9Sstevel@tonic-gate 			object->prev->next = NULL;
5107c478bd9Sstevel@tonic-gate 		}
5117c478bd9Sstevel@tonic-gate 	}
5127c478bd9Sstevel@tonic-gate 
5137c478bd9Sstevel@tonic-gate 	if (!have_list_lock) {
5147c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(list_lock);
5157c478bd9Sstevel@tonic-gate 	}
5167c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&meta_objectclose_lock);
5177c478bd9Sstevel@tonic-gate 
5187c478bd9Sstevel@tonic-gate 	/*
5197c478bd9Sstevel@tonic-gate 	 * Wait for anyone already using object to finish, by obtaining
5207c478bd9Sstevel@tonic-gate 	 * a writer-lock (need to release our reader-lock first). Once we
5217c478bd9Sstevel@tonic-gate 	 * get the write lock, we can just release it and finish cleaning
5227c478bd9Sstevel@tonic-gate 	 * up the object.
5237c478bd9Sstevel@tonic-gate 	 */
5247c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->object_lock); /* rdlock */
5257c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&object->object_lock);
5267c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->object_lock); /* wrlock */
5277c478bd9Sstevel@tonic-gate 
5287c478bd9Sstevel@tonic-gate 
5297c478bd9Sstevel@tonic-gate 	return (CKR_OK);
5307c478bd9Sstevel@tonic-gate }
5317c478bd9Sstevel@tonic-gate 
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate /*
5347c478bd9Sstevel@tonic-gate  * meta_object_dealloc
5357c478bd9Sstevel@tonic-gate  *
5367c478bd9Sstevel@tonic-gate  * Performs final object cleanup, releasing any allocated memory and
5377c478bd9Sstevel@tonic-gate  * destroying any clones on other slots. Caller is assumed to have
5387c478bd9Sstevel@tonic-gate  * called meta_object_deactivate() before this function.
5397c478bd9Sstevel@tonic-gate  *
5407c478bd9Sstevel@tonic-gate  * Caller is assumed to have only reference to object, but should have
5417c478bd9Sstevel@tonic-gate  * released any lock.
5427c478bd9Sstevel@tonic-gate  *
5437c478bd9Sstevel@tonic-gate  * If "nukeSourceObj" argument is true, we will actually delete the
5447c478bd9Sstevel@tonic-gate  * object from the underlying slot.
5457c478bd9Sstevel@tonic-gate  */
5467c478bd9Sstevel@tonic-gate CK_RV
5478cae6764SAnthony Scarpino meta_object_dealloc(meta_session_t *session, meta_object_t *object,
5488cae6764SAnthony Scarpino     boolean_t nukeSourceObj)
5497c478bd9Sstevel@tonic-gate {
5507c478bd9Sstevel@tonic-gate 	CK_RV rv, save_rv = CKR_OK;
5517c478bd9Sstevel@tonic-gate 	CK_ULONG slotnum, num_slots;
5527c478bd9Sstevel@tonic-gate 	CK_ULONG i;
5537c478bd9Sstevel@tonic-gate 
5547c478bd9Sstevel@tonic-gate 	/* First, delete all the clones of this object on other slots. */
5557c478bd9Sstevel@tonic-gate 	num_slots = meta_slotManager_get_slotcount();
5567c478bd9Sstevel@tonic-gate 	for (slotnum = 0; slotnum < num_slots; slotnum++) {
5577c478bd9Sstevel@tonic-gate 		slot_session_t *obj_session;
5587c478bd9Sstevel@tonic-gate 		slot_object_t *clone;
5597c478bd9Sstevel@tonic-gate 
5607c478bd9Sstevel@tonic-gate 		clone = object->clones[slotnum];
5617c478bd9Sstevel@tonic-gate 		if (clone == NULL)
5627c478bd9Sstevel@tonic-gate 			continue;
563034448feSmcpowers 		if (nukeSourceObj || (!object->isToken &&
564034448feSmcpowers 		    !(object->isFreeToken == FREE_ENABLED &&
565034448feSmcpowers 		    get_keystore_slotnum() == slotnum))) {
5667c478bd9Sstevel@tonic-gate 
5677c478bd9Sstevel@tonic-gate 			rv = meta_get_slot_session(slotnum, &obj_session,
5688cae6764SAnthony Scarpino 			    (session == NULL) ?
5698cae6764SAnthony Scarpino 			    object->creator_session->session_flags :
5708cae6764SAnthony Scarpino 			    session->session_flags);
5717c478bd9Sstevel@tonic-gate 
5727c478bd9Sstevel@tonic-gate 			if (rv == CKR_OK) {
5737c478bd9Sstevel@tonic-gate 				rv = FUNCLIST(obj_session->fw_st_id)->\
5747c478bd9Sstevel@tonic-gate 				    C_DestroyObject(obj_session->hSession,
5757c478bd9Sstevel@tonic-gate 				    clone->hObject);
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 				meta_release_slot_session(obj_session);
5787c478bd9Sstevel@tonic-gate 				if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
5797c478bd9Sstevel@tonic-gate 					save_rv = rv;
5807c478bd9Sstevel@tonic-gate 				}
5817c478bd9Sstevel@tonic-gate 			}
5827c478bd9Sstevel@tonic-gate 
5837c478bd9Sstevel@tonic-gate 		}
5847c478bd9Sstevel@tonic-gate 
5857c478bd9Sstevel@tonic-gate 		meta_slot_object_deactivate(clone);
5867c478bd9Sstevel@tonic-gate 		meta_slot_object_dealloc(clone);
5877c478bd9Sstevel@tonic-gate 
5887c478bd9Sstevel@tonic-gate 		object->clones[slotnum] = NULL;
5897c478bd9Sstevel@tonic-gate 	}
5907c478bd9Sstevel@tonic-gate 
5917c478bd9Sstevel@tonic-gate 	/* Now erase and delete any attributes in the metaobject. */
5927c478bd9Sstevel@tonic-gate 	dealloc_attributes(object->attributes, object->num_attributes);
5937c478bd9Sstevel@tonic-gate 
5947c478bd9Sstevel@tonic-gate 	free(object->clones);
5957c478bd9Sstevel@tonic-gate 	free(object->tried_create_clone);
5967c478bd9Sstevel@tonic-gate 
5977c478bd9Sstevel@tonic-gate 	if (object->clone_template) {
5987c478bd9Sstevel@tonic-gate 		for (i = 0; i < object->clone_template_size; i++) {
5997c478bd9Sstevel@tonic-gate 			free(((object->clone_template)[i]).pValue);
6007c478bd9Sstevel@tonic-gate 		}
6017c478bd9Sstevel@tonic-gate 		free(object->clone_template);
6027c478bd9Sstevel@tonic-gate 	}
6037c478bd9Sstevel@tonic-gate 
6047c478bd9Sstevel@tonic-gate 	/* Cleanup remaining object fields. */
6057c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&object->object_lock);
6067c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&object->attribute_lock);
6077c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_destroy(&object->isClosingObject_lock);
6087c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_destroy(&object->clone_create_lock);
6097c478bd9Sstevel@tonic-gate 
6107c478bd9Sstevel@tonic-gate 	meta_object_delay_free(object);
6117c478bd9Sstevel@tonic-gate 
6127c478bd9Sstevel@tonic-gate 	return (save_rv);
6137c478bd9Sstevel@tonic-gate }
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 
6167c478bd9Sstevel@tonic-gate /*
6177c478bd9Sstevel@tonic-gate  * meta_slot_object_alloc
6187c478bd9Sstevel@tonic-gate  */
6197c478bd9Sstevel@tonic-gate CK_RV
6207c478bd9Sstevel@tonic-gate meta_slot_object_alloc(slot_object_t **object) {
6217c478bd9Sstevel@tonic-gate 	slot_object_t *new_object;
6227c478bd9Sstevel@tonic-gate 
6237c478bd9Sstevel@tonic-gate 	new_object = calloc(1, sizeof (slot_object_t));
6247c478bd9Sstevel@tonic-gate 	if (new_object == NULL)
6257c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
6267c478bd9Sstevel@tonic-gate 
6277c478bd9Sstevel@tonic-gate 	*object = new_object;
6287c478bd9Sstevel@tonic-gate 	return (CKR_OK);
6297c478bd9Sstevel@tonic-gate }
6307c478bd9Sstevel@tonic-gate 
6317c478bd9Sstevel@tonic-gate 
6327c478bd9Sstevel@tonic-gate /*
6337c478bd9Sstevel@tonic-gate  * meta_slot_object_activate
6347c478bd9Sstevel@tonic-gate  */
6357c478bd9Sstevel@tonic-gate void
6367c478bd9Sstevel@tonic-gate meta_slot_object_activate(slot_object_t *object,
6377c478bd9Sstevel@tonic-gate 	slot_session_t *creator_session, boolean_t isToken)
6387c478bd9Sstevel@tonic-gate {
6397c478bd9Sstevel@tonic-gate 	object->creator_session = creator_session;
6407c478bd9Sstevel@tonic-gate 
6417c478bd9Sstevel@tonic-gate 	if (isToken) {
6427c478bd9Sstevel@tonic-gate 		extern slot_data_t *slots;
6437c478bd9Sstevel@tonic-gate 		slot_data_t *slot;
6447c478bd9Sstevel@tonic-gate 
6457c478bd9Sstevel@tonic-gate 		slot = &(slots[object->creator_session->slotnum]);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(&slot->tokenobject_list_lock);
6487c478bd9Sstevel@tonic-gate 		INSERT_INTO_LIST(slot->tokenobject_list_head, object);
6497c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&slot->tokenobject_list_lock);
6507c478bd9Sstevel@tonic-gate 	} else {
6517c478bd9Sstevel@tonic-gate 		slot_session_t *session = object->creator_session;
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 		/* Add to session's list of session objects. */
6547c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(&session->object_list_lock);
6557c478bd9Sstevel@tonic-gate 		INSERT_INTO_LIST(session->object_list_head, object);
6567c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&session->object_list_lock);
6577c478bd9Sstevel@tonic-gate 	}
658034448feSmcpowers 
659034448feSmcpowers 	/*
660034448feSmcpowers 	 * This set tells the slot object that we are in the token list,
661034448feSmcpowers 	 * but does not cause harm with the metaobject knowing the object
662034448feSmcpowers 	 * isn't a token, but a freetoken
663034448feSmcpowers 	 */
664034448feSmcpowers 
6657c478bd9Sstevel@tonic-gate 	object->isToken = isToken;
6667c478bd9Sstevel@tonic-gate }
6677c478bd9Sstevel@tonic-gate 
6687c478bd9Sstevel@tonic-gate 
6697c478bd9Sstevel@tonic-gate /*
6707c478bd9Sstevel@tonic-gate  * meta_slot_object_deactivate
6717c478bd9Sstevel@tonic-gate  *
6727c478bd9Sstevel@tonic-gate  * Remove the specified slot object from the appropriate object list.
6737c478bd9Sstevel@tonic-gate  */
6747c478bd9Sstevel@tonic-gate void
6757c478bd9Sstevel@tonic-gate meta_slot_object_deactivate(slot_object_t *object)
6767c478bd9Sstevel@tonic-gate {
6777c478bd9Sstevel@tonic-gate 	slot_object_t **list_head;
6787c478bd9Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
6797c478bd9Sstevel@tonic-gate 
6807c478bd9Sstevel@tonic-gate 	if (object->isToken) {
6817c478bd9Sstevel@tonic-gate 		extern slot_data_t *slots;
6827c478bd9Sstevel@tonic-gate 		slot_data_t *slot;
6837c478bd9Sstevel@tonic-gate 
6847c478bd9Sstevel@tonic-gate 		slot = &(slots[object->creator_session->slotnum]);
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 		list_head = &slot->tokenobject_list_head;
6877c478bd9Sstevel@tonic-gate 		list_lock = &slot->tokenobject_list_lock;
6887c478bd9Sstevel@tonic-gate 	} else {
6897c478bd9Sstevel@tonic-gate 		list_head = &object->creator_session->object_list_head;
6907c478bd9Sstevel@tonic-gate 		list_lock = &object->creator_session->object_list_lock;
6917c478bd9Sstevel@tonic-gate 	}
6927c478bd9Sstevel@tonic-gate 
6937c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(list_lock);
6947c478bd9Sstevel@tonic-gate 	REMOVE_FROM_LIST(*list_head, object);
6957c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(list_lock);
6967c478bd9Sstevel@tonic-gate }
6977c478bd9Sstevel@tonic-gate 
6987c478bd9Sstevel@tonic-gate 
6997c478bd9Sstevel@tonic-gate /*
7007c478bd9Sstevel@tonic-gate  * meta_slot_object_dealloc
7017c478bd9Sstevel@tonic-gate  */
7027c478bd9Sstevel@tonic-gate void
7037c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slot_object_t *object)
7047c478bd9Sstevel@tonic-gate {
7057c478bd9Sstevel@tonic-gate 	/* Not much cleanup for slot objects, unlike meta objects... */
7067c478bd9Sstevel@tonic-gate 	free(object);
7077c478bd9Sstevel@tonic-gate }
7087c478bd9Sstevel@tonic-gate 
7097c478bd9Sstevel@tonic-gate 
7107c478bd9Sstevel@tonic-gate /*
7117c478bd9Sstevel@tonic-gate  * meta_object_copyin
7127c478bd9Sstevel@tonic-gate  *
7137c478bd9Sstevel@tonic-gate  * When a key is generated/derived/unwrapped, the attribute values
7147c478bd9Sstevel@tonic-gate  * created by the token are not immediately read into our copy of the
7157c478bd9Sstevel@tonic-gate  * attributes. We defer this work until we actually need to know.
7167c478bd9Sstevel@tonic-gate  */
7177c478bd9Sstevel@tonic-gate CK_RV
7187c478bd9Sstevel@tonic-gate meta_object_copyin(meta_object_t *object)
7197c478bd9Sstevel@tonic-gate {
7207c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
7217c478bd9Sstevel@tonic-gate 	slot_session_t *session = NULL;
7227c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE *attrs = NULL, *attrs_with_val = NULL;
7237c478bd9Sstevel@tonic-gate 	slot_object_t *slot_object = NULL;
7247c478bd9Sstevel@tonic-gate 	CK_ULONG num_attrs = 0, i, num_attrs_with_val;
7257c478bd9Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession;
7267c478bd9Sstevel@tonic-gate 	CK_SLOT_ID fw_st_id;
7277c478bd9Sstevel@tonic-gate 
7287c478bd9Sstevel@tonic-gate 	/* Make sure no one else is looking at attributes. */
7297c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&object->attribute_lock);
7307c478bd9Sstevel@tonic-gate 
7317c478bd9Sstevel@tonic-gate 	/* Did we just lose a copyin race with another thread */
7327c478bd9Sstevel@tonic-gate 	if (object->attributes != NULL) {
7337c478bd9Sstevel@tonic-gate 		goto finish;
7347c478bd9Sstevel@tonic-gate 	}
7357c478bd9Sstevel@tonic-gate 
7367c478bd9Sstevel@tonic-gate 	slot_object = object->clones[object->master_clone_slotnum];
7377c478bd9Sstevel@tonic-gate 
7387c478bd9Sstevel@tonic-gate 	rv = meta_get_slot_session(object->master_clone_slotnum, &session,
7397c478bd9Sstevel@tonic-gate 	    object->creator_session->session_flags);
7407c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
7417c478bd9Sstevel@tonic-gate 		goto finish;
7427c478bd9Sstevel@tonic-gate 	}
7437c478bd9Sstevel@tonic-gate 
7447c478bd9Sstevel@tonic-gate 	/*
7457c478bd9Sstevel@tonic-gate 	 * first, get the master template of all the attributes
7467c478bd9Sstevel@tonic-gate 	 * for this object
7477c478bd9Sstevel@tonic-gate 	 */
7487c478bd9Sstevel@tonic-gate 	rv = get_master_attributes_by_object(session, slot_object,
7497c478bd9Sstevel@tonic-gate 	    &(object->attributes), &(object->num_attributes));
7507c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
7517c478bd9Sstevel@tonic-gate 		goto finish;
7527c478bd9Sstevel@tonic-gate 	}
7537c478bd9Sstevel@tonic-gate 
7547c478bd9Sstevel@tonic-gate 	/*
7557c478bd9Sstevel@tonic-gate 	 * Get value for each attribute items.
7567c478bd9Sstevel@tonic-gate 	 *
7577c478bd9Sstevel@tonic-gate 	 * Some attributes are required by the given object type.
7587c478bd9Sstevel@tonic-gate 	 * Some are optional.  Get all the values first, and then
7597c478bd9Sstevel@tonic-gate 	 * make sure we have value for all required values,
7607c478bd9Sstevel@tonic-gate 	 */
7617c478bd9Sstevel@tonic-gate 	attrs = calloc(object->num_attributes, sizeof (CK_ATTRIBUTE));
7627c478bd9Sstevel@tonic-gate 	if (attrs == NULL) {
7637c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
7647c478bd9Sstevel@tonic-gate 		goto finish;
7657c478bd9Sstevel@tonic-gate 	}
7667c478bd9Sstevel@tonic-gate 
7677c478bd9Sstevel@tonic-gate 
7687c478bd9Sstevel@tonic-gate 	for (i = 0; i < object->num_attributes; i++) {
7697c478bd9Sstevel@tonic-gate 		attrs[i].type =
7707c478bd9Sstevel@tonic-gate 		    ((object->attributes[i]).attribute).type;
7717c478bd9Sstevel@tonic-gate 	}
7727c478bd9Sstevel@tonic-gate 	num_attrs = object->num_attributes;
7737c478bd9Sstevel@tonic-gate 
7747c478bd9Sstevel@tonic-gate 	hSession = session->hSession;
7757c478bd9Sstevel@tonic-gate 	fw_st_id = session->fw_st_id;
7767c478bd9Sstevel@tonic-gate 
7777c478bd9Sstevel@tonic-gate 	/* first, call C_GetAttributeValue() to get size for each attribute */
7787c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
7797c478bd9Sstevel@tonic-gate 	    slot_object->hObject, attrs, num_attrs);
7807c478bd9Sstevel@tonic-gate 	/*
7817c478bd9Sstevel@tonic-gate 	 * If the return value is not CKR_OK, allow it to be
7827c478bd9Sstevel@tonic-gate 	 * CKR_ATTRIBUTE_TYPE_INVALID for now.
7837c478bd9Sstevel@tonic-gate 	 * Some attributes defined in PKCS#11 version 2.11
7847c478bd9Sstevel@tonic-gate 	 * might not be defined in earlier versions.  We will
7857c478bd9Sstevel@tonic-gate 	 * TRY to work with those providers if the attribute
7867c478bd9Sstevel@tonic-gate 	 * is optional.
7877c478bd9Sstevel@tonic-gate 	 */
7887c478bd9Sstevel@tonic-gate 	if ((rv != CKR_OK) && (rv != CKR_ATTRIBUTE_TYPE_INVALID)) {
7897c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED; /* make sure rv is appropriate */
7907c478bd9Sstevel@tonic-gate 		goto finish;
7917c478bd9Sstevel@tonic-gate 	}
7927c478bd9Sstevel@tonic-gate 
7937c478bd9Sstevel@tonic-gate 	/*
7947c478bd9Sstevel@tonic-gate 	 * allocate space.
7957c478bd9Sstevel@tonic-gate 	 * Since we don't know how many attributes have
7967c478bd9Sstevel@tonic-gate 	 * values at this time, just assume all of them
7977c478bd9Sstevel@tonic-gate 	 * have values so we save one loop to count the number
7987c478bd9Sstevel@tonic-gate 	 * of attributes that have value.
7997c478bd9Sstevel@tonic-gate 	 */
8007c478bd9Sstevel@tonic-gate 	attrs_with_val = calloc(num_attrs, sizeof (CK_ATTRIBUTE));
8017c478bd9Sstevel@tonic-gate 	if (attrs_with_val == NULL) {
8027c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
8037c478bd9Sstevel@tonic-gate 		goto finish;
8047c478bd9Sstevel@tonic-gate 	}
8057c478bd9Sstevel@tonic-gate 
8067c478bd9Sstevel@tonic-gate 
8077c478bd9Sstevel@tonic-gate 	num_attrs_with_val = 0;
8087c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attrs; i++) {
8097c478bd9Sstevel@tonic-gate 		if (!(((CK_LONG)(attrs[i].ulValueLen)) > 0)) {
8107c478bd9Sstevel@tonic-gate 			/* if it isn't an optional attr, len should be > 0 */
8117c478bd9Sstevel@tonic-gate 			if (!object->attributes[i].canBeEmptyValue) {
8127c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
8137c478bd9Sstevel@tonic-gate 				goto finish;
8147c478bd9Sstevel@tonic-gate 			}
8157c478bd9Sstevel@tonic-gate 		} else {
8167c478bd9Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].type = attrs[i].type;
8177c478bd9Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].ulValueLen =
8187c478bd9Sstevel@tonic-gate 			    attrs[i].ulValueLen;
8197c478bd9Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].pValue =
8207c478bd9Sstevel@tonic-gate 			    malloc(attrs[i].ulValueLen);
8217c478bd9Sstevel@tonic-gate 			if (attrs_with_val[num_attrs_with_val].pValue == NULL) {
8227c478bd9Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
8237c478bd9Sstevel@tonic-gate 				goto finish;
8247c478bd9Sstevel@tonic-gate 			}
8257c478bd9Sstevel@tonic-gate 			num_attrs_with_val++;
8267c478bd9Sstevel@tonic-gate 		}
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
8307c478bd9Sstevel@tonic-gate 	    slot_object->hObject, attrs_with_val, num_attrs_with_val);
8317c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
8327c478bd9Sstevel@tonic-gate 		goto finish;
8337c478bd9Sstevel@tonic-gate 	}
8347c478bd9Sstevel@tonic-gate 
8357c478bd9Sstevel@tonic-gate 	/* store these values into the meta object */
8367c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attrs_with_val; i++) {
8377c478bd9Sstevel@tonic-gate 		rv = attribute_set_value(&(attrs_with_val[i]),
8387c478bd9Sstevel@tonic-gate 		    object->attributes, object->num_attributes);
8397c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
8407c478bd9Sstevel@tonic-gate 			goto finish;
8417c478bd9Sstevel@tonic-gate 		}
8427c478bd9Sstevel@tonic-gate 	}
8437c478bd9Sstevel@tonic-gate 
8447c478bd9Sstevel@tonic-gate finish:
8457c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->attribute_lock);
8467c478bd9Sstevel@tonic-gate 
8477c478bd9Sstevel@tonic-gate 	if (session)
8487c478bd9Sstevel@tonic-gate 		meta_release_slot_session(session);
8497c478bd9Sstevel@tonic-gate 
8507c478bd9Sstevel@tonic-gate 	if (attrs) {
8517c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_attrs; i++) {
8527c478bd9Sstevel@tonic-gate 			if (attrs[i].pValue != NULL) {
8537c478bd9Sstevel@tonic-gate 				free(attrs[i].pValue);
8547c478bd9Sstevel@tonic-gate 			}
8557c478bd9Sstevel@tonic-gate 		}
8567c478bd9Sstevel@tonic-gate 		free(attrs);
8577c478bd9Sstevel@tonic-gate 	}
8587c478bd9Sstevel@tonic-gate 
8597c478bd9Sstevel@tonic-gate 	if (attrs_with_val) {
8607c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_attrs; i++) {
8617c478bd9Sstevel@tonic-gate 			if (attrs_with_val[i].pValue != NULL) {
8627c478bd9Sstevel@tonic-gate 				free(attrs_with_val[i].pValue);
8637c478bd9Sstevel@tonic-gate 			}
8647c478bd9Sstevel@tonic-gate 		}
8657c478bd9Sstevel@tonic-gate 		free(attrs_with_val);
8667c478bd9Sstevel@tonic-gate 	}
8677c478bd9Sstevel@tonic-gate 	return (rv);
8687c478bd9Sstevel@tonic-gate }
8697c478bd9Sstevel@tonic-gate 
8707c478bd9Sstevel@tonic-gate /*
8717c478bd9Sstevel@tonic-gate  * Create an object to be used for wrapping and unwrapping.
8727c478bd9Sstevel@tonic-gate  * The same template will be used for all wrapping/unwrapping keys all
8737c478bd9Sstevel@tonic-gate  * the time
8747c478bd9Sstevel@tonic-gate  */
8757c478bd9Sstevel@tonic-gate 
8767c478bd9Sstevel@tonic-gate static CK_RV
8777c478bd9Sstevel@tonic-gate create_wrap_unwrap_key(slot_session_t *slot_session, CK_OBJECT_HANDLE *hObject,
8787c478bd9Sstevel@tonic-gate     wrap_info_t *wrap_info, char *key_data, CK_ULONG key_len)
8797c478bd9Sstevel@tonic-gate {
8807c478bd9Sstevel@tonic-gate 
8817c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS objclass;
8827c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE keytype;
8837c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
8847c478bd9Sstevel@tonic-gate 	int i;
8857c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE template[WRAP_KEY_TEMPLATE_SIZE];
8867c478bd9Sstevel@tonic-gate 
8877c478bd9Sstevel@tonic-gate 	i = 0;
8887c478bd9Sstevel@tonic-gate 	objclass = wrap_info->class;
8897c478bd9Sstevel@tonic-gate 	template[i].type = CKA_CLASS;
8907c478bd9Sstevel@tonic-gate 	template[i].pValue = &objclass;
8917c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (objclass);
8927c478bd9Sstevel@tonic-gate 
8937c478bd9Sstevel@tonic-gate 	i++;
8947c478bd9Sstevel@tonic-gate 	keytype = wrap_info->key_type;
8957c478bd9Sstevel@tonic-gate 	template[i].type = CKA_KEY_TYPE;
8967c478bd9Sstevel@tonic-gate 	template[i].pValue = &keytype;
8977c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (keytype);
8987c478bd9Sstevel@tonic-gate 
8997c478bd9Sstevel@tonic-gate 	i++;
9007c478bd9Sstevel@tonic-gate 	template[i].type = CKA_TOKEN;
9017c478bd9Sstevel@tonic-gate 	template[i].pValue = &falsevalue;
9027c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (falsevalue);
9037c478bd9Sstevel@tonic-gate 
9047c478bd9Sstevel@tonic-gate 
9057c478bd9Sstevel@tonic-gate 	if (objclass == CKO_SECRET_KEY) {
9067c478bd9Sstevel@tonic-gate 		i++;
9077c478bd9Sstevel@tonic-gate 		template[i].type = CKA_VALUE;
9087c478bd9Sstevel@tonic-gate 		template[i].pValue = key_data;
9097c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = key_len;
9107c478bd9Sstevel@tonic-gate 
9117c478bd9Sstevel@tonic-gate 		i++;
9127c478bd9Sstevel@tonic-gate 		template[i].type = CKA_WRAP;
9137c478bd9Sstevel@tonic-gate 		template[i].pValue = &truevalue;
9147c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (truevalue);
9157c478bd9Sstevel@tonic-gate 
9167c478bd9Sstevel@tonic-gate 		i++;
9177c478bd9Sstevel@tonic-gate 		template[i].type = CKA_UNWRAP;
9187c478bd9Sstevel@tonic-gate 		template[i].pValue = &truevalue;
9197c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (truevalue);
9207c478bd9Sstevel@tonic-gate 	} else {
9217c478bd9Sstevel@tonic-gate 		/* Modulus is the same for rsa public and private key */
9227c478bd9Sstevel@tonic-gate 		i++;
9237c478bd9Sstevel@tonic-gate 		template[i].type = CKA_MODULUS;
9247c478bd9Sstevel@tonic-gate 		template[i].pValue = Modulus;
9257c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (Modulus);
9267c478bd9Sstevel@tonic-gate 
9277c478bd9Sstevel@tonic-gate 		if (objclass == CKO_PUBLIC_KEY) {
9287c478bd9Sstevel@tonic-gate 			/* RSA public key */
9297c478bd9Sstevel@tonic-gate 			i++;
9307c478bd9Sstevel@tonic-gate 			template[i].type = CKA_PUBLIC_EXPONENT;
9317c478bd9Sstevel@tonic-gate 			template[i].pValue = PubExpo;
9327c478bd9Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (PubExpo);
9337c478bd9Sstevel@tonic-gate 
9347c478bd9Sstevel@tonic-gate 			i++;
9357c478bd9Sstevel@tonic-gate 			template[i].type = CKA_WRAP;
9367c478bd9Sstevel@tonic-gate 			template[i].pValue = &truevalue;
9377c478bd9Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (truevalue);
9387c478bd9Sstevel@tonic-gate 		} else {
9397c478bd9Sstevel@tonic-gate 			/* RSA private key */
9407c478bd9Sstevel@tonic-gate 			i++;
9417c478bd9Sstevel@tonic-gate 			template[i].type = CKA_PRIVATE_EXPONENT;
9427c478bd9Sstevel@tonic-gate 			template[i].pValue = PriExpo;
9437c478bd9Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (PriExpo);
9447c478bd9Sstevel@tonic-gate 
9457c478bd9Sstevel@tonic-gate 			i++;
9467c478bd9Sstevel@tonic-gate 			template[i].type = CKA_UNWRAP;
9477c478bd9Sstevel@tonic-gate 			template[i].pValue = &truevalue;
9487c478bd9Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (truevalue);
9497c478bd9Sstevel@tonic-gate 		}
9507c478bd9Sstevel@tonic-gate 	}
9517c478bd9Sstevel@tonic-gate 
9527c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject(
9537c478bd9Sstevel@tonic-gate 	    slot_session->hSession, template, i + 1, hObject);
9547c478bd9Sstevel@tonic-gate 
9557c478bd9Sstevel@tonic-gate 	return (rv);
9567c478bd9Sstevel@tonic-gate }
9577c478bd9Sstevel@tonic-gate 
9587c478bd9Sstevel@tonic-gate 
9597c478bd9Sstevel@tonic-gate /*
9607c478bd9Sstevel@tonic-gate  * Create a clone of a non-sensitive and extractable object.
9617c478bd9Sstevel@tonic-gate  * If the template required for creating the clone doesn't exist,
9627c478bd9Sstevel@tonic-gate  * it will be retrieved from the master clone.
9637c478bd9Sstevel@tonic-gate  */
9647c478bd9Sstevel@tonic-gate static CK_RV
9657c478bd9Sstevel@tonic-gate clone_by_create(meta_object_t *object, slot_object_t *new_clone,
9667c478bd9Sstevel@tonic-gate     slot_session_t *dst_slot_session)
9677c478bd9Sstevel@tonic-gate {
9687c478bd9Sstevel@tonic-gate 	CK_RV rv;
969034448feSmcpowers 	int free_token_index = -1;
9707c478bd9Sstevel@tonic-gate 
9717c478bd9Sstevel@tonic-gate 	if (object->attributes == NULL) {
9727c478bd9Sstevel@tonic-gate 		rv = meta_object_copyin(object);
9737c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
9747c478bd9Sstevel@tonic-gate 			return (rv);
9757c478bd9Sstevel@tonic-gate 		}
9767c478bd9Sstevel@tonic-gate 	}
9777c478bd9Sstevel@tonic-gate 
9787c478bd9Sstevel@tonic-gate 	if (object->clone_template == NULL) {
9797c478bd9Sstevel@tonic-gate 		rv = meta_clone_template_setup(object, object->attributes,
9807c478bd9Sstevel@tonic-gate 		    object->num_attributes);
9817c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
9827c478bd9Sstevel@tonic-gate 			return (rv);
9837c478bd9Sstevel@tonic-gate 		}
9847c478bd9Sstevel@tonic-gate 	}
9857c478bd9Sstevel@tonic-gate 
986034448feSmcpowers 	if (object->isFreeToken == FREE_ENABLED) {
987034448feSmcpowers 		if (dst_slot_session->slotnum == get_keystore_slotnum())
988034448feSmcpowers 			free_token_index = set_template_boolean(CKA_TOKEN,
989034448feSmcpowers 			    object->clone_template,
990034448feSmcpowers 			    object->clone_template_size, B_FALSE, &truevalue);
991034448feSmcpowers 		else
992034448feSmcpowers 			free_token_index = set_template_boolean(CKA_TOKEN,
993034448feSmcpowers 			    object->clone_template,
994034448feSmcpowers 			    object->clone_template_size, B_FALSE, &falsevalue);
995034448feSmcpowers 	}
996034448feSmcpowers 
9977c478bd9Sstevel@tonic-gate 	/* Create the clone... */
9987c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(dst_slot_session->fw_st_id)->C_CreateObject(
9997c478bd9Sstevel@tonic-gate 	    dst_slot_session->hSession, object->clone_template,
10007c478bd9Sstevel@tonic-gate 	    object->clone_template_size, &(new_clone->hObject));
1001034448feSmcpowers 
1002034448feSmcpowers 	if (free_token_index != -1) {
1003d3a28a55Sdinak 			free_token_index = set_template_boolean(CKA_TOKEN,
1004d3a28a55Sdinak 			    object->clone_template, object->clone_template_size,
1005034448feSmcpowers 			    B_FALSE, &falsevalue);
1006034448feSmcpowers 	}
1007034448feSmcpowers 
10087c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
10097c478bd9Sstevel@tonic-gate 		return (rv);
10107c478bd9Sstevel@tonic-gate 	}
10117c478bd9Sstevel@tonic-gate 
10127c478bd9Sstevel@tonic-gate 	return (CKR_OK);
10137c478bd9Sstevel@tonic-gate }
10147c478bd9Sstevel@tonic-gate 
10157c478bd9Sstevel@tonic-gate /*
10167c478bd9Sstevel@tonic-gate  * Goes through the list of wraping mechanisms, and returns the first
10177c478bd9Sstevel@tonic-gate  * one that is supported by both the source and the destination slot.
10187c478bd9Sstevel@tonic-gate  * If none of the mechanisms are supported by both slot, return the
10197c478bd9Sstevel@tonic-gate  * first mechanism that's supported by the source slot
10207c478bd9Sstevel@tonic-gate  */
10217c478bd9Sstevel@tonic-gate static CK_RV
10227c478bd9Sstevel@tonic-gate find_best_match_wrap_mech(wrap_info_t *wrap_info, int num_info,
10237c478bd9Sstevel@tonic-gate 	CK_ULONG src_slotnum, CK_ULONG dst_slotnum, int *first_both_mech,
10247c478bd9Sstevel@tonic-gate 	int *first_src_mech)
10257c478bd9Sstevel@tonic-gate {
10267c478bd9Sstevel@tonic-gate 
10277c478bd9Sstevel@tonic-gate 	int i;
10287c478bd9Sstevel@tonic-gate 	boolean_t src_supports, dst_supports;
10297c478bd9Sstevel@tonic-gate 	CK_RV rv;
1030d3a28a55Sdinak 	CK_MECHANISM_INFO mech_info;
1031d3a28a55Sdinak 
1032d3a28a55Sdinak 	mech_info.flags = CKF_WRAP;
10337c478bd9Sstevel@tonic-gate 
10347c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_info; i++) {
10357c478bd9Sstevel@tonic-gate 		src_supports = B_FALSE;
10367c478bd9Sstevel@tonic-gate 		dst_supports = B_FALSE;
10377c478bd9Sstevel@tonic-gate 
10387c478bd9Sstevel@tonic-gate 		rv = meta_mechManager_slot_supports_mech(
10397c478bd9Sstevel@tonic-gate 		    (wrap_info[i]).mech_type, src_slotnum,
1040d3a28a55Sdinak 		    &src_supports, NULL, B_FALSE, &mech_info);
10417c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
10427c478bd9Sstevel@tonic-gate 			return (rv);
10437c478bd9Sstevel@tonic-gate 		}
10447c478bd9Sstevel@tonic-gate 
10457c478bd9Sstevel@tonic-gate 		rv = meta_mechManager_slot_supports_mech(
10467c478bd9Sstevel@tonic-gate 		    (wrap_info[i]).mech_type, dst_slotnum,
1047d3a28a55Sdinak 		    &dst_supports, NULL, B_FALSE, &mech_info);
10487c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
10497c478bd9Sstevel@tonic-gate 			return (rv);
10507c478bd9Sstevel@tonic-gate 		}
10517c478bd9Sstevel@tonic-gate 
10527c478bd9Sstevel@tonic-gate 		/* both source and destination supports the mech */
10537c478bd9Sstevel@tonic-gate 		if ((src_supports) && (dst_supports)) {
10547c478bd9Sstevel@tonic-gate 			*first_both_mech = i;
10557c478bd9Sstevel@tonic-gate 			return (CKR_OK);
10567c478bd9Sstevel@tonic-gate 		}
10577c478bd9Sstevel@tonic-gate 
10587c478bd9Sstevel@tonic-gate 		if ((src_supports) && (*first_src_mech == -1)) {
10597c478bd9Sstevel@tonic-gate 			*first_src_mech = i;
10607c478bd9Sstevel@tonic-gate 		}
10617c478bd9Sstevel@tonic-gate 	}
10627c478bd9Sstevel@tonic-gate 	return (CKR_OK);
10637c478bd9Sstevel@tonic-gate }
10647c478bd9Sstevel@tonic-gate 
10657c478bd9Sstevel@tonic-gate /*
10667c478bd9Sstevel@tonic-gate  * Determine the wrapping/unwrapping mechanism to be used
10677c478bd9Sstevel@tonic-gate  *
10687c478bd9Sstevel@tonic-gate  * If possible, select a mechanism that's supported by both source
10697c478bd9Sstevel@tonic-gate  * and destination slot.  If none of the mechanisms are supported
10707c478bd9Sstevel@tonic-gate  * by both slot, then, select the first one supported by
10717c478bd9Sstevel@tonic-gate  * the source slot.
10727c478bd9Sstevel@tonic-gate  */
10737c478bd9Sstevel@tonic-gate 
10747c478bd9Sstevel@tonic-gate static CK_RV
10757c478bd9Sstevel@tonic-gate get_wrap_mechanism(CK_OBJECT_CLASS obj_class, CK_KEY_TYPE key_type,
10767c478bd9Sstevel@tonic-gate     CK_ULONG src_slotnum, CK_ULONG dst_slotnum, wrap_info_t *wrap_info)
10777c478bd9Sstevel@tonic-gate {
10787c478bd9Sstevel@tonic-gate 	wrap_info_t *wrap_info_to_search = NULL;
10797c478bd9Sstevel@tonic-gate 	unsigned int num_wrap_info;
10807c478bd9Sstevel@tonic-gate 	CK_RV rv;
10817c478bd9Sstevel@tonic-gate 	int i;
10827c478bd9Sstevel@tonic-gate 	boolean_t src_supports = B_FALSE, dst_supports = B_FALSE;
10837c478bd9Sstevel@tonic-gate 	int first_src_mech, rsa_first_src_mech, first_both_mech;
1084d3a28a55Sdinak 	CK_MECHANISM_INFO mech_info;
1085d3a28a55Sdinak 
1086d3a28a55Sdinak 	mech_info.flags = CKF_WRAP;
10877c478bd9Sstevel@tonic-gate 
10887c478bd9Sstevel@tonic-gate 	if ((obj_class == CKO_PRIVATE_KEY) && (key_type == CKK_KEA)) {
10897c478bd9Sstevel@tonic-gate 		/*
10907c478bd9Sstevel@tonic-gate 		 * only SKIPJACK keys can be used for wrapping
10917c478bd9Sstevel@tonic-gate 		 * KEA private keys
10927c478bd9Sstevel@tonic-gate 		 */
10937c478bd9Sstevel@tonic-gate 
10947c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_special_wrap_info; i++) {
10957c478bd9Sstevel@tonic-gate 			if ((special_wrap_info[i]).mech_type
10967c478bd9Sstevel@tonic-gate 			    != CKM_SKIPJACK_WRAP) {
10977c478bd9Sstevel@tonic-gate 				continue;
10987c478bd9Sstevel@tonic-gate 			}
10997c478bd9Sstevel@tonic-gate 
11007c478bd9Sstevel@tonic-gate 			src_supports = B_FALSE;
11017c478bd9Sstevel@tonic-gate 			dst_supports = B_FALSE;
11027c478bd9Sstevel@tonic-gate 
11037c478bd9Sstevel@tonic-gate 			rv = meta_mechManager_slot_supports_mech(
11047c478bd9Sstevel@tonic-gate 			    (special_wrap_info[i]).mech_type, src_slotnum,
1105d3a28a55Sdinak 			    &src_supports, NULL, B_FALSE, &mech_info);
11067c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
11077c478bd9Sstevel@tonic-gate 				goto finish;
11087c478bd9Sstevel@tonic-gate 			}
11097c478bd9Sstevel@tonic-gate 
11107c478bd9Sstevel@tonic-gate 			rv = meta_mechManager_slot_supports_mech(
11117c478bd9Sstevel@tonic-gate 			    (special_wrap_info[i]).mech_type, dst_slotnum,
1112d3a28a55Sdinak 			    &dst_supports, NULL, B_FALSE, &mech_info);
11137c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
11147c478bd9Sstevel@tonic-gate 				goto finish;
11157c478bd9Sstevel@tonic-gate 			}
11167c478bd9Sstevel@tonic-gate 
11177c478bd9Sstevel@tonic-gate 			if (src_supports) {
11187c478bd9Sstevel@tonic-gate 				/*
11197c478bd9Sstevel@tonic-gate 				 * both src and dst supports the mech or
11207c478bd9Sstevel@tonic-gate 				 * only the src supports the mech
11217c478bd9Sstevel@tonic-gate 				 */
11227c478bd9Sstevel@tonic-gate 				(void) memcpy(wrap_info,
11237c478bd9Sstevel@tonic-gate 				    &(special_wrap_info[i]),
11247c478bd9Sstevel@tonic-gate 				    sizeof (wrap_info_t));
11257c478bd9Sstevel@tonic-gate 
11267c478bd9Sstevel@tonic-gate 				wrap_info->src_supports = src_supports;
11277c478bd9Sstevel@tonic-gate 				wrap_info->dst_supports = dst_supports;
11287c478bd9Sstevel@tonic-gate 				rv = CKR_OK;
11297c478bd9Sstevel@tonic-gate 				goto finish;
11307c478bd9Sstevel@tonic-gate 			}
11317c478bd9Sstevel@tonic-gate 
11327c478bd9Sstevel@tonic-gate 		}
11337c478bd9Sstevel@tonic-gate 
11347c478bd9Sstevel@tonic-gate 		/*
11357c478bd9Sstevel@tonic-gate 		 * if we are here, that means neither the source slot
1136*5893fa69SDan OpenSolaris Anderson 		 * nor the destination slots supports CKM_SKIPJACK_WRAP.
11377c478bd9Sstevel@tonic-gate 		 */
11387c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
11397c478bd9Sstevel@tonic-gate 		goto finish;
11407c478bd9Sstevel@tonic-gate 	}
11417c478bd9Sstevel@tonic-gate 
11427c478bd9Sstevel@tonic-gate 	if ((key_type == CKK_SKIPJACK) || (key_type == CKK_BATON) ||
11437c478bd9Sstevel@tonic-gate 	    (key_type == CKK_JUNIPER)) {
11447c478bd9Sstevel@tonic-gate 		/* special key types */
11457c478bd9Sstevel@tonic-gate 		wrap_info_to_search = special_wrap_info;
11467c478bd9Sstevel@tonic-gate 		num_wrap_info = num_special_wrap_info;
11477c478bd9Sstevel@tonic-gate 	} else {
11487c478bd9Sstevel@tonic-gate 		/* use the regular wrapping mechanisms */
11497c478bd9Sstevel@tonic-gate 		wrap_info_to_search = common_wrap_info;
11507c478bd9Sstevel@tonic-gate 		num_wrap_info = num_common_wrap_info;
11517c478bd9Sstevel@tonic-gate 	}
11527c478bd9Sstevel@tonic-gate 
11537c478bd9Sstevel@tonic-gate 	first_both_mech = -1;
11547c478bd9Sstevel@tonic-gate 	first_src_mech = -1;
11557c478bd9Sstevel@tonic-gate 
11567c478bd9Sstevel@tonic-gate 	rv = find_best_match_wrap_mech(wrap_info_to_search, num_wrap_info,
11577c478bd9Sstevel@tonic-gate 	    src_slotnum, dst_slotnum, &first_both_mech, &first_src_mech);
11587c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
11597c478bd9Sstevel@tonic-gate 		goto finish;
11607c478bd9Sstevel@tonic-gate 	}
11617c478bd9Sstevel@tonic-gate 
11627c478bd9Sstevel@tonic-gate 	if (first_both_mech != -1) {
11637c478bd9Sstevel@tonic-gate 		(void) memcpy(wrap_info,
11647c478bd9Sstevel@tonic-gate 		    &(wrap_info_to_search[first_both_mech]),
11657c478bd9Sstevel@tonic-gate 		    sizeof (wrap_info_t));
11667c478bd9Sstevel@tonic-gate 
11677c478bd9Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
11687c478bd9Sstevel@tonic-gate 		wrap_info->dst_supports = B_TRUE;
11697c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
11707c478bd9Sstevel@tonic-gate 		goto finish;
11717c478bd9Sstevel@tonic-gate 	}
11727c478bd9Sstevel@tonic-gate 
11737c478bd9Sstevel@tonic-gate 	/*
11747c478bd9Sstevel@tonic-gate 	 * If we are here, we did not find a mechanism that's supported
11757c478bd9Sstevel@tonic-gate 	 * by both source and destination slot.
11767c478bd9Sstevel@tonic-gate 	 *
11777c478bd9Sstevel@tonic-gate 	 * If it is a secret key, can also try to wrap it with
11787c478bd9Sstevel@tonic-gate 	 * a RSA public key
11797c478bd9Sstevel@tonic-gate 	 */
11807c478bd9Sstevel@tonic-gate 	if (obj_class == CKO_SECRET_KEY) {
11817c478bd9Sstevel@tonic-gate 		first_both_mech = -1;
11827c478bd9Sstevel@tonic-gate 		rsa_first_src_mech = -1;
11837c478bd9Sstevel@tonic-gate 
11847c478bd9Sstevel@tonic-gate 		rv = find_best_match_wrap_mech(rsa_wrap_info,
11857c478bd9Sstevel@tonic-gate 		    num_rsa_wrap_info, src_slotnum, dst_slotnum,
11867c478bd9Sstevel@tonic-gate 		    &first_both_mech, &rsa_first_src_mech);
11877c478bd9Sstevel@tonic-gate 
11887c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
11897c478bd9Sstevel@tonic-gate 			goto finish;
11907c478bd9Sstevel@tonic-gate 		}
11917c478bd9Sstevel@tonic-gate 
11927c478bd9Sstevel@tonic-gate 		if (first_both_mech > -1) {
11937c478bd9Sstevel@tonic-gate 			(void) memcpy(wrap_info,
11947c478bd9Sstevel@tonic-gate 			    &(rsa_wrap_info[first_both_mech]),
11957c478bd9Sstevel@tonic-gate 			    sizeof (wrap_info_t));
11967c478bd9Sstevel@tonic-gate 
11977c478bd9Sstevel@tonic-gate 			wrap_info->src_supports = B_TRUE;
11987c478bd9Sstevel@tonic-gate 			wrap_info->dst_supports = B_TRUE;
11997c478bd9Sstevel@tonic-gate 			rv = CKR_OK;
12007c478bd9Sstevel@tonic-gate 			goto finish;
12017c478bd9Sstevel@tonic-gate 		}
12027c478bd9Sstevel@tonic-gate 	}
12037c478bd9Sstevel@tonic-gate 
12047c478bd9Sstevel@tonic-gate 	/*
12057c478bd9Sstevel@tonic-gate 	 * if we are here, that means none of the mechanisms are supported
12067c478bd9Sstevel@tonic-gate 	 * by both the source and the destination
12077c478bd9Sstevel@tonic-gate 	 */
12087c478bd9Sstevel@tonic-gate 	if (first_src_mech > -1) {
12097c478bd9Sstevel@tonic-gate 		/* source slot support one of the secret key mechs */
12107c478bd9Sstevel@tonic-gate 		(void) memcpy(wrap_info,
12117c478bd9Sstevel@tonic-gate 		    &(wrap_info_to_search[first_src_mech]),
12127c478bd9Sstevel@tonic-gate 		    sizeof (wrap_info_t));
12137c478bd9Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
12147c478bd9Sstevel@tonic-gate 		wrap_info->dst_supports = B_FALSE;
12157c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
12167c478bd9Sstevel@tonic-gate 	} else if (rsa_first_src_mech > -1) {
12177c478bd9Sstevel@tonic-gate 		/* source slot support one of the RSA mechs */
12187c478bd9Sstevel@tonic-gate 		(void) memcpy(wrap_info, &(rsa_wrap_info[rsa_first_src_mech]),
12197c478bd9Sstevel@tonic-gate 		    sizeof (wrap_info_t));
12207c478bd9Sstevel@tonic-gate 
12217c478bd9Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
12227c478bd9Sstevel@tonic-gate 		wrap_info->dst_supports = B_FALSE;
12237c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
12247c478bd9Sstevel@tonic-gate 	} else {
12257c478bd9Sstevel@tonic-gate 		/* neither source nor destination support any wrap mechs */
12267c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
12277c478bd9Sstevel@tonic-gate 	}
12287c478bd9Sstevel@tonic-gate 
12297c478bd9Sstevel@tonic-gate finish:
12307c478bd9Sstevel@tonic-gate 	return (rv);
12317c478bd9Sstevel@tonic-gate }
12327c478bd9Sstevel@tonic-gate 
12337c478bd9Sstevel@tonic-gate 
12347c478bd9Sstevel@tonic-gate /*
12357c478bd9Sstevel@tonic-gate  * This is called if the object to be cloned is a sensitive object
12367c478bd9Sstevel@tonic-gate  */
12377c478bd9Sstevel@tonic-gate static CK_RV
12387c478bd9Sstevel@tonic-gate clone_by_wrap(meta_object_t *object, slot_object_t *new_clone,
12397c478bd9Sstevel@tonic-gate     slot_session_t *dst_slot_session)
12407c478bd9Sstevel@tonic-gate {
12417c478bd9Sstevel@tonic-gate 	slot_session_t *src_slot_session = NULL;
12427c478bd9Sstevel@tonic-gate 	CK_OBJECT_HANDLE wrappingKey = NULL, unwrappingKey = NULL;
12437c478bd9Sstevel@tonic-gate 	CK_MECHANISM wrappingMech;
12447c478bd9Sstevel@tonic-gate 	CK_BYTE *wrappedKey = NULL;
12457c478bd9Sstevel@tonic-gate 	CK_ULONG wrappedKeyLen = 0;
12467c478bd9Sstevel@tonic-gate 	slot_object_t *slot_object = NULL;
12477c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
12487c478bd9Sstevel@tonic-gate 	CK_OBJECT_HANDLE unwrapped_obj;
12497c478bd9Sstevel@tonic-gate 	meta_object_t *tmp_meta_obj = NULL;
12507c478bd9Sstevel@tonic-gate 	slot_object_t *tmp_slot_obj = NULL;
12517c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS obj_class;
12527c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE key_type;
12537c478bd9Sstevel@tonic-gate 	meta_session_t *tmp_meta_session = NULL;
12547c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE unwrap_template[4];
12557c478bd9Sstevel@tonic-gate 	char key_data[1024]; /* should be big enough for any key size */
12567c478bd9Sstevel@tonic-gate 	char ivbuf[1024]; /* should be big enough for any mech */
12577c478bd9Sstevel@tonic-gate 	wrap_info_t wrap_info;
12587c478bd9Sstevel@tonic-gate 	CK_ULONG key_len, unwrap_template_size;
12597c478bd9Sstevel@tonic-gate 
12607c478bd9Sstevel@tonic-gate 	slot_object = object->clones[object->master_clone_slotnum];
12617c478bd9Sstevel@tonic-gate 
12627c478bd9Sstevel@tonic-gate 	rv = meta_get_slot_session(object->master_clone_slotnum,
12637c478bd9Sstevel@tonic-gate 	    &src_slot_session, object->creator_session->session_flags);
12647c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
12657c478bd9Sstevel@tonic-gate 		return (rv);
12667c478bd9Sstevel@tonic-gate 	}
12677c478bd9Sstevel@tonic-gate 
12687c478bd9Sstevel@tonic-gate 	/*
12697c478bd9Sstevel@tonic-gate 	 * get the object class and key type for unwrap template
12707c478bd9Sstevel@tonic-gate 	 * This information will also be used for determining
12717c478bd9Sstevel@tonic-gate 	 * which wrap mechanism and which key to use for
12727c478bd9Sstevel@tonic-gate 	 * doing the wrapping
12737c478bd9Sstevel@tonic-gate 	 */
12747c478bd9Sstevel@tonic-gate 	unwrap_template[0].type = CKA_CLASS;
12757c478bd9Sstevel@tonic-gate 	unwrap_template[0].pValue = &obj_class;
12767c478bd9Sstevel@tonic-gate 	unwrap_template[0].ulValueLen = sizeof (obj_class);
12777c478bd9Sstevel@tonic-gate 
12787c478bd9Sstevel@tonic-gate 	unwrap_template[1].type = CKA_KEY_TYPE;
12797c478bd9Sstevel@tonic-gate 	unwrap_template[1].pValue = &key_type;
12807c478bd9Sstevel@tonic-gate 	unwrap_template[1].ulValueLen = sizeof (key_type);
12817c478bd9Sstevel@tonic-gate 
12827c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_GetAttributeValue(
12837c478bd9Sstevel@tonic-gate 	    src_slot_session->hSession, slot_object->hObject,
12847c478bd9Sstevel@tonic-gate 	    unwrap_template, 2);
12857c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
12867c478bd9Sstevel@tonic-gate 		goto finish;
12877c478bd9Sstevel@tonic-gate 	}
12887c478bd9Sstevel@tonic-gate 
12897c478bd9Sstevel@tonic-gate 	rv = get_wrap_mechanism(obj_class, key_type, src_slot_session->slotnum,
12907c478bd9Sstevel@tonic-gate 	    dst_slot_session->slotnum, &wrap_info);
12917c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
12927c478bd9Sstevel@tonic-gate 		goto finish;
12937c478bd9Sstevel@tonic-gate 	}
12947c478bd9Sstevel@tonic-gate 
12957c478bd9Sstevel@tonic-gate 	/*
12967b79d846SDina K Nimeh 	 * read number of bytes required from random device for
12977c478bd9Sstevel@tonic-gate 	 * creating a secret key for wrapping and unwrapping
12987c478bd9Sstevel@tonic-gate 	 */
12997c478bd9Sstevel@tonic-gate 	if (wrap_info.class == CKO_SECRET_KEY) {
13007c478bd9Sstevel@tonic-gate 
13017c478bd9Sstevel@tonic-gate 		/*
13027c478bd9Sstevel@tonic-gate 		 * /dev/urandom will be used for generating the key used
13037c478bd9Sstevel@tonic-gate 		 * for doing the wrap/unwrap.  It's should be ok to
13047c478bd9Sstevel@tonic-gate 		 * use /dev/urandom because this key is used for this
13057c478bd9Sstevel@tonic-gate 		 * one time operation only.  It doesn't need to be stored.
13067c478bd9Sstevel@tonic-gate 		 */
13077c478bd9Sstevel@tonic-gate 		key_len = wrap_info.key_length;
13087b79d846SDina K Nimeh 		if (pkcs11_get_urandom(key_data, key_len) < 0) {
13097c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
13107c478bd9Sstevel@tonic-gate 			goto finish;
13117c478bd9Sstevel@tonic-gate 		}
13127c478bd9Sstevel@tonic-gate 
13137c478bd9Sstevel@tonic-gate 		if (wrap_info.iv_length > 0) {
13147b79d846SDina K Nimeh 			if (pkcs11_get_urandom(
13157b79d846SDina K Nimeh 			    ivbuf, wrap_info.iv_length) < 0) {
13167c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
13177c478bd9Sstevel@tonic-gate 				goto finish;
13187c478bd9Sstevel@tonic-gate 			}
13197c478bd9Sstevel@tonic-gate 		}
13207c478bd9Sstevel@tonic-gate 	}
13217c478bd9Sstevel@tonic-gate 
13227c478bd9Sstevel@tonic-gate 	/* create the wrapping key */
13237c478bd9Sstevel@tonic-gate 	rv = create_wrap_unwrap_key(src_slot_session, &wrappingKey,
13247c478bd9Sstevel@tonic-gate 	    &wrap_info, key_data, key_len);
13257c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
13267c478bd9Sstevel@tonic-gate 		goto finish;
13277c478bd9Sstevel@tonic-gate 	}
13287c478bd9Sstevel@tonic-gate 
13297c478bd9Sstevel@tonic-gate 	wrappingMech.mechanism = wrap_info.mech_type;
13307c478bd9Sstevel@tonic-gate 	wrappingMech.pParameter = ((wrap_info.iv_length > 0) ? ivbuf : NULL);
13317c478bd9Sstevel@tonic-gate 	wrappingMech.ulParameterLen = wrap_info.iv_length;
13327c478bd9Sstevel@tonic-gate 
13337c478bd9Sstevel@tonic-gate 	/* get the size of the wrapped key */
13347c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
13357c478bd9Sstevel@tonic-gate 	    src_slot_session->hSession, &wrappingMech,
13367c478bd9Sstevel@tonic-gate 	    wrappingKey, slot_object->hObject, NULL, &wrappedKeyLen);
13377c478bd9Sstevel@tonic-gate 
13387c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
13397c478bd9Sstevel@tonic-gate 		goto finish;
13407c478bd9Sstevel@tonic-gate 	}
13417c478bd9Sstevel@tonic-gate 
13427c478bd9Sstevel@tonic-gate 	wrappedKey = malloc(wrappedKeyLen * sizeof (CK_BYTE));
13437c478bd9Sstevel@tonic-gate 	if (wrappedKey == NULL) {
13447c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
13457c478bd9Sstevel@tonic-gate 		goto finish;
13467c478bd9Sstevel@tonic-gate 	}
13477c478bd9Sstevel@tonic-gate 
13487c478bd9Sstevel@tonic-gate 	/* do the actual key wrapping */
13497c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
13507c478bd9Sstevel@tonic-gate 	    src_slot_session->hSession, &wrappingMech,
13517c478bd9Sstevel@tonic-gate 	    wrappingKey, slot_object->hObject, wrappedKey, &wrappedKeyLen);
13527c478bd9Sstevel@tonic-gate 
13537c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
13547c478bd9Sstevel@tonic-gate 		goto finish;
13557c478bd9Sstevel@tonic-gate 	}
13567c478bd9Sstevel@tonic-gate 
13577c478bd9Sstevel@tonic-gate 	/* explicitly force the unwrapped object to be not sensitive */
13587c478bd9Sstevel@tonic-gate 	unwrap_template[2].type = CKA_SENSITIVE;
13597c478bd9Sstevel@tonic-gate 	unwrap_template[2].pValue = &falsevalue;
13607c478bd9Sstevel@tonic-gate 	unwrap_template[2].ulValueLen = sizeof (falsevalue);
13617c478bd9Sstevel@tonic-gate 
13627c478bd9Sstevel@tonic-gate 	unwrap_template[3].type = CKA_TOKEN;
13637c478bd9Sstevel@tonic-gate 	unwrap_template[3].pValue = &falsevalue;
13647c478bd9Sstevel@tonic-gate 	unwrap_template[3].ulValueLen = sizeof (falsevalue);
13657c478bd9Sstevel@tonic-gate 
13667c478bd9Sstevel@tonic-gate 	unwrap_template_size =
13677c478bd9Sstevel@tonic-gate 	    sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE);
13687c478bd9Sstevel@tonic-gate 
13697c478bd9Sstevel@tonic-gate 	if (!wrap_info.dst_supports) {
13707c478bd9Sstevel@tonic-gate 		/*
13717c478bd9Sstevel@tonic-gate 		 * if we know for sure that the destination slot doesn't
13727c478bd9Sstevel@tonic-gate 		 * support the wrapping mechanism, no point in trying.
13737c478bd9Sstevel@tonic-gate 		 * go directly to unwrap in source slot, and create key
13747c478bd9Sstevel@tonic-gate 		 * in destination
13757c478bd9Sstevel@tonic-gate 		 */
13767c478bd9Sstevel@tonic-gate 		goto unwrap_in_source;
13777c478bd9Sstevel@tonic-gate 	}
13787c478bd9Sstevel@tonic-gate 
13797c478bd9Sstevel@tonic-gate 	/* create the unwrapping key in destination slot */
13807c478bd9Sstevel@tonic-gate 	if (wrap_info.key_type == CKK_RSA) {
13817c478bd9Sstevel@tonic-gate 		/* for RSA key, the unwrapping key need to be private key */
13827c478bd9Sstevel@tonic-gate 		wrap_info.class = CKO_PRIVATE_KEY;
13837c478bd9Sstevel@tonic-gate 	}
13847c478bd9Sstevel@tonic-gate 	rv = create_wrap_unwrap_key(dst_slot_session,
13857c478bd9Sstevel@tonic-gate 	    &unwrappingKey, &wrap_info, key_data, key_len);
13867c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
13877c478bd9Sstevel@tonic-gate 		goto finish;
13887c478bd9Sstevel@tonic-gate 	}
13897c478bd9Sstevel@tonic-gate 
13907c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(dst_slot_session->fw_st_id)->C_UnwrapKey(
13917c478bd9Sstevel@tonic-gate 	    dst_slot_session->hSession, &wrappingMech,
13927c478bd9Sstevel@tonic-gate 	    unwrappingKey, wrappedKey, wrappedKeyLen, unwrap_template,
13937c478bd9Sstevel@tonic-gate 	    unwrap_template_size, &(new_clone->hObject));
13947c478bd9Sstevel@tonic-gate 
13957c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
13967c478bd9Sstevel@tonic-gate unwrap_in_source:
13977c478bd9Sstevel@tonic-gate 
13987c478bd9Sstevel@tonic-gate 		/*
13997c478bd9Sstevel@tonic-gate 		 * There seemed to be a problem with unwrapping in the
14007c478bd9Sstevel@tonic-gate 		 * destination slot.
14017c478bd9Sstevel@tonic-gate 		 * Try to do the unwrap in the src slot so it becomes
14027c478bd9Sstevel@tonic-gate 		 * a non-sensitive object, then, get all the attributes
14037c478bd9Sstevel@tonic-gate 		 * and create the object in the destination slot
14047c478bd9Sstevel@tonic-gate 		 */
14057c478bd9Sstevel@tonic-gate 
14067c478bd9Sstevel@tonic-gate 
14077c478bd9Sstevel@tonic-gate 		if (wrap_info.class == CKO_SECRET_KEY) {
14087c478bd9Sstevel@tonic-gate 			/* unwrap with same key used for wrapping */
14097c478bd9Sstevel@tonic-gate 			rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
14107c478bd9Sstevel@tonic-gate 			    src_slot_session->hSession,
14117c478bd9Sstevel@tonic-gate 			    &wrappingMech, wrappingKey, wrappedKey,
14127c478bd9Sstevel@tonic-gate 			    wrappedKeyLen, unwrap_template,
14137c478bd9Sstevel@tonic-gate 			    unwrap_template_size, &(unwrapped_obj));
14147c478bd9Sstevel@tonic-gate 		} else {
14157c478bd9Sstevel@tonic-gate 			/*
14167c478bd9Sstevel@tonic-gate 			 * If the object is wrapping with RSA public key, need
14177c478bd9Sstevel@tonic-gate 			 * need to create RSA private key for unwrapping
14187c478bd9Sstevel@tonic-gate 			 */
14197c478bd9Sstevel@tonic-gate 			wrap_info.class = CKO_PRIVATE_KEY;
14207c478bd9Sstevel@tonic-gate 			rv = create_wrap_unwrap_key(src_slot_session,
14217c478bd9Sstevel@tonic-gate 			    &unwrappingKey, &wrap_info, key_data, key_len);
14227c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
14237c478bd9Sstevel@tonic-gate 				goto finish;
14247c478bd9Sstevel@tonic-gate 			}
14257c478bd9Sstevel@tonic-gate 			rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
14267c478bd9Sstevel@tonic-gate 			    src_slot_session->hSession,
14277c478bd9Sstevel@tonic-gate 			    &wrappingMech, unwrappingKey, wrappedKey,
14287c478bd9Sstevel@tonic-gate 			    wrappedKeyLen, unwrap_template,
14297c478bd9Sstevel@tonic-gate 			    unwrap_template_size, &(unwrapped_obj));
14307c478bd9Sstevel@tonic-gate 		}
14317c478bd9Sstevel@tonic-gate 
14327c478bd9Sstevel@tonic-gate 
14337c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
14347c478bd9Sstevel@tonic-gate 			goto finish;
14357c478bd9Sstevel@tonic-gate 		}
14367c478bd9Sstevel@tonic-gate 
14377c478bd9Sstevel@tonic-gate 		rv = meta_session_alloc(&tmp_meta_session);
14387c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
14397c478bd9Sstevel@tonic-gate 			goto finish;
14407c478bd9Sstevel@tonic-gate 		}
14417c478bd9Sstevel@tonic-gate 
14427c478bd9Sstevel@tonic-gate 		tmp_meta_session->session_flags = CKF_SERIAL_SESSION;
14437c478bd9Sstevel@tonic-gate 
14447c478bd9Sstevel@tonic-gate 		rv = meta_object_alloc(tmp_meta_session, &tmp_meta_obj);
14457c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
14467c478bd9Sstevel@tonic-gate 			goto finish;
14477c478bd9Sstevel@tonic-gate 		}
14487c478bd9Sstevel@tonic-gate 
14497c478bd9Sstevel@tonic-gate 		rv = meta_slot_object_alloc(&tmp_slot_obj);
14507c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
14517c478bd9Sstevel@tonic-gate 			goto finish;
14527c478bd9Sstevel@tonic-gate 		}
14537c478bd9Sstevel@tonic-gate 
14547c478bd9Sstevel@tonic-gate 		tmp_meta_obj->master_clone_slotnum = src_slot_session->slotnum;
14557c478bd9Sstevel@tonic-gate 		tmp_slot_obj->hObject = unwrapped_obj;
14567c478bd9Sstevel@tonic-gate 		tmp_meta_obj->clones[tmp_meta_obj->master_clone_slotnum]
14577c478bd9Sstevel@tonic-gate 		    = tmp_slot_obj;
14587c478bd9Sstevel@tonic-gate 		meta_slot_object_activate(tmp_slot_obj, src_slot_session,
14597c478bd9Sstevel@tonic-gate 		    B_FALSE);
14607c478bd9Sstevel@tonic-gate 		tmp_slot_obj = NULL;
14617c478bd9Sstevel@tonic-gate 
14627c478bd9Sstevel@tonic-gate 		rv = clone_by_create(tmp_meta_obj, new_clone,
14637c478bd9Sstevel@tonic-gate 		    dst_slot_session);
14647c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
14657c478bd9Sstevel@tonic-gate 			goto finish;
14667c478bd9Sstevel@tonic-gate 		}
14677c478bd9Sstevel@tonic-gate 	}
14687c478bd9Sstevel@tonic-gate 
14697c478bd9Sstevel@tonic-gate finish:
14707c478bd9Sstevel@tonic-gate 	if (unwrappingKey) {
14717c478bd9Sstevel@tonic-gate 		(void) FUNCLIST(dst_slot_session->fw_st_id)->C_DestroyObject(
14727c478bd9Sstevel@tonic-gate 		    dst_slot_session->hSession, unwrappingKey);
14737c478bd9Sstevel@tonic-gate 	}
14747c478bd9Sstevel@tonic-gate 
14757c478bd9Sstevel@tonic-gate 	if (wrappingKey) {
14767c478bd9Sstevel@tonic-gate 		(void) FUNCLIST(src_slot_session->fw_st_id)->C_DestroyObject(
14777c478bd9Sstevel@tonic-gate 		    src_slot_session->hSession, wrappingKey);
14787c478bd9Sstevel@tonic-gate 	}
14797c478bd9Sstevel@tonic-gate 
14807c478bd9Sstevel@tonic-gate 	if (tmp_slot_obj) {
14817c478bd9Sstevel@tonic-gate 		(void) meta_slot_object_dealloc(tmp_slot_obj);
14827c478bd9Sstevel@tonic-gate 	}
14837c478bd9Sstevel@tonic-gate 
14847c478bd9Sstevel@tonic-gate 	if (tmp_meta_obj) {
14858cae6764SAnthony Scarpino 		(void) meta_object_dealloc(tmp_meta_session, tmp_meta_obj,
14868cae6764SAnthony Scarpino 		    B_TRUE);
14877c478bd9Sstevel@tonic-gate 	}
14887c478bd9Sstevel@tonic-gate 
14897c478bd9Sstevel@tonic-gate 	if (tmp_meta_session) {
14907c478bd9Sstevel@tonic-gate 		(void) meta_session_dealloc(tmp_meta_session);
14917c478bd9Sstevel@tonic-gate 	}
14927c478bd9Sstevel@tonic-gate 
14937c478bd9Sstevel@tonic-gate 	if (wrappedKey) {
14947c478bd9Sstevel@tonic-gate 		free(wrappedKey);
14957c478bd9Sstevel@tonic-gate 	}
14967c478bd9Sstevel@tonic-gate 
14977c478bd9Sstevel@tonic-gate 	if (src_slot_session) {
14987c478bd9Sstevel@tonic-gate 		meta_release_slot_session(src_slot_session);
14997c478bd9Sstevel@tonic-gate 	}
15007c478bd9Sstevel@tonic-gate 
15017c478bd9Sstevel@tonic-gate 	return (rv);
15027c478bd9Sstevel@tonic-gate 
15037c478bd9Sstevel@tonic-gate }
15047c478bd9Sstevel@tonic-gate 
15057c478bd9Sstevel@tonic-gate 
15067c478bd9Sstevel@tonic-gate /*
15077c478bd9Sstevel@tonic-gate  * meta_object_get_clone
15087c478bd9Sstevel@tonic-gate  *
15097c478bd9Sstevel@tonic-gate  * Creates a "clone" of a metaobject on the specified slot. A clone is a
15107c478bd9Sstevel@tonic-gate  * copy of the object.
15117c478bd9Sstevel@tonic-gate  *
1512*5893fa69SDan OpenSolaris Anderson  * Clones are cached, so that they can be reused with subsequent operations.
15137c478bd9Sstevel@tonic-gate  */
15147c478bd9Sstevel@tonic-gate CK_RV
15157c478bd9Sstevel@tonic-gate meta_object_get_clone(meta_object_t *object,
15167c478bd9Sstevel@tonic-gate 	CK_ULONG slot_num, slot_session_t *slot_session,
15177c478bd9Sstevel@tonic-gate 	slot_object_t **clone)
15187c478bd9Sstevel@tonic-gate {
15197c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
15207c478bd9Sstevel@tonic-gate 	slot_object_t *newclone = NULL;
15217c478bd9Sstevel@tonic-gate 
15227c478bd9Sstevel@tonic-gate 	/* Does a clone already exist? */
15237c478bd9Sstevel@tonic-gate 	if (object->clones[slot_num] != NULL) {
15247c478bd9Sstevel@tonic-gate 		*clone = object->clones[slot_num];
15257c478bd9Sstevel@tonic-gate 		return (CKR_OK);
15267c478bd9Sstevel@tonic-gate 	}
15277c478bd9Sstevel@tonic-gate 
15287c478bd9Sstevel@tonic-gate 	if ((object->isSensitive) && (object->isToken) &&
15297c478bd9Sstevel@tonic-gate 	    (!metaslot_auto_key_migrate)) {
15307c478bd9Sstevel@tonic-gate 		/*
15317c478bd9Sstevel@tonic-gate 		 * if the object is a sensitive token object, and auto
15327c478bd9Sstevel@tonic-gate 		 * key migrate is not allowed, will not create the clone
15337c478bd9Sstevel@tonic-gate 		 * in another slot
15347c478bd9Sstevel@tonic-gate 		 */
15357c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
15367c478bd9Sstevel@tonic-gate 	}
15377c478bd9Sstevel@tonic-gate 
15387c478bd9Sstevel@tonic-gate 	/* object attributes can't be extracted and attributes are not known */
15397c478bd9Sstevel@tonic-gate 	if ((!object->isExtractable) && (object->attributes == NULL)) {
15407c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
15417c478bd9Sstevel@tonic-gate 	}
15427c478bd9Sstevel@tonic-gate 
15437c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object->clone_create_lock);
15447c478bd9Sstevel@tonic-gate 
15457c478bd9Sstevel@tonic-gate 	/* Maybe someone just created one? */
15467c478bd9Sstevel@tonic-gate 	if (object->clones[slot_num] != NULL) {
15477c478bd9Sstevel@tonic-gate 		*clone = object->clones[slot_num];
15487c478bd9Sstevel@tonic-gate 		goto finish;
15497c478bd9Sstevel@tonic-gate 	}
15507c478bd9Sstevel@tonic-gate 
155189a7715aSkrishna 	/*
155289a7715aSkrishna 	 * has an attempt already been made to create this object in
155389a7715aSkrishna 	 * slot?  If yes, and there's no clone, as indicated above,
155489a7715aSkrishna 	 * that means this object can't be created in this slot.
155589a7715aSkrishna 	 */
155689a7715aSkrishna 	if (object->tried_create_clone[slot_num]) {
155789a7715aSkrishna 		(void) pthread_mutex_unlock(&object->clone_create_lock);
155889a7715aSkrishna 		return (CKR_FUNCTION_FAILED);
155989a7715aSkrishna 	}
156089a7715aSkrishna 
15617c478bd9Sstevel@tonic-gate 	rv = meta_slot_object_alloc(&newclone);
15627c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
15637c478bd9Sstevel@tonic-gate 		goto finish;
15647c478bd9Sstevel@tonic-gate 
15657c478bd9Sstevel@tonic-gate 	object->tried_create_clone[slot_num] = B_TRUE;
15667c478bd9Sstevel@tonic-gate 
1567034448feSmcpowers 	/*
1568034448feSmcpowers 	 * If this object is sensitive and we do not have not copied in the
1569034448feSmcpowers 	 * attributes via FreeObject functionality, then we need to wrap it off
1570034448feSmcpowers 	 * the provider.  If we do have attributes, we can just create the
1571034448feSmcpowers 	 * clone
1572034448feSmcpowers 	 */
1573034448feSmcpowers 
1574034448feSmcpowers 	if (object->isSensitive && object->attributes == NULL) {
15757c478bd9Sstevel@tonic-gate 		rv = clone_by_wrap(object, newclone, slot_session);
15767c478bd9Sstevel@tonic-gate 	} else {
15777c478bd9Sstevel@tonic-gate 		rv = clone_by_create(object, newclone, slot_session);
15787c478bd9Sstevel@tonic-gate 	}
15797c478bd9Sstevel@tonic-gate 
15807c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
15817c478bd9Sstevel@tonic-gate 		goto finish;
15827c478bd9Sstevel@tonic-gate 	}
15837c478bd9Sstevel@tonic-gate 
15847c478bd9Sstevel@tonic-gate 	object->clones[slot_num] = newclone;
15857c478bd9Sstevel@tonic-gate 	meta_slot_object_activate(newclone, slot_session, object->isToken);
15867c478bd9Sstevel@tonic-gate 
15877c478bd9Sstevel@tonic-gate 	*clone = newclone;
15887c478bd9Sstevel@tonic-gate 	newclone = NULL;
15897c478bd9Sstevel@tonic-gate finish:
15907c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object->clone_create_lock);
15917c478bd9Sstevel@tonic-gate 
15927c478bd9Sstevel@tonic-gate 	if (newclone)
15937c478bd9Sstevel@tonic-gate 		meta_slot_object_dealloc(newclone);
15947c478bd9Sstevel@tonic-gate 
15957c478bd9Sstevel@tonic-gate 	return (rv);
15967c478bd9Sstevel@tonic-gate }
15977c478bd9Sstevel@tonic-gate 
15987c478bd9Sstevel@tonic-gate 
15997c478bd9Sstevel@tonic-gate /*
16007c478bd9Sstevel@tonic-gate  * meta_setup_clone_template
16017c478bd9Sstevel@tonic-gate  *
16027c478bd9Sstevel@tonic-gate  * Create a clone template for the specified object.
16037c478bd9Sstevel@tonic-gate  */
16047c478bd9Sstevel@tonic-gate static CK_RV
16057c478bd9Sstevel@tonic-gate meta_clone_template_setup(meta_object_t *object,
16067c478bd9Sstevel@tonic-gate     const generic_attr_t *attributes, size_t num_attributes)
16077c478bd9Sstevel@tonic-gate {
16087c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
16097c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE *clone_template;
16107c478bd9Sstevel@tonic-gate 	size_t i, c = 0;
16117c478bd9Sstevel@tonic-gate 
16127c478bd9Sstevel@tonic-gate 	clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE));
16137c478bd9Sstevel@tonic-gate 	if (clone_template == NULL) {
16147c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
16157c478bd9Sstevel@tonic-gate 		goto finish;
16167c478bd9Sstevel@tonic-gate 	}
16177c478bd9Sstevel@tonic-gate 
16187c478bd9Sstevel@tonic-gate 	/* Don't allow attributes to change while we look at them. */
16197c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&object->attribute_lock);
16207c478bd9Sstevel@tonic-gate 
16217c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attributes; i++) {
1622034448feSmcpowers 		if (!attributes[i].isCloneAttr ||
1623034448feSmcpowers 		    (attributes[i].attribute.type == CKA_TOKEN &&
1624034448feSmcpowers 		    object->isFreeToken == FREE_DISABLED)) {
16257c478bd9Sstevel@tonic-gate 			continue;
16267c478bd9Sstevel@tonic-gate 		}
16277c478bd9Sstevel@tonic-gate 		if ((!(attributes[i].hasValueForClone)) &&
16287c478bd9Sstevel@tonic-gate 		    (attributes[i].canBeEmptyValue)) {
16297c478bd9Sstevel@tonic-gate 			continue;
16307c478bd9Sstevel@tonic-gate 		}
16317c478bd9Sstevel@tonic-gate 
16327c478bd9Sstevel@tonic-gate 		clone_template[c].type = attributes[i].attribute.type;
16337c478bd9Sstevel@tonic-gate 		clone_template[c].ulValueLen =
16347c478bd9Sstevel@tonic-gate 		    attributes[i].attribute.ulValueLen;
16357c478bd9Sstevel@tonic-gate 		/* Allocate space to store the attribute value. */
16367c478bd9Sstevel@tonic-gate 		clone_template[c].pValue = malloc(clone_template[c].ulValueLen);
16377c478bd9Sstevel@tonic-gate 		if (clone_template[c].pValue == NULL) {
1638*5893fa69SDan OpenSolaris Anderson 			free(clone_template);
16397c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
16407c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(&object->attribute_lock);
16417c478bd9Sstevel@tonic-gate 			goto finish;
16427c478bd9Sstevel@tonic-gate 		}
16437c478bd9Sstevel@tonic-gate 
16447c478bd9Sstevel@tonic-gate 		(void) memcpy(clone_template[c].pValue,
16457c478bd9Sstevel@tonic-gate 		    object->attributes[i].attribute.pValue,
16467c478bd9Sstevel@tonic-gate 		    clone_template[c].ulValueLen);
16477c478bd9Sstevel@tonic-gate 		c++;
16487c478bd9Sstevel@tonic-gate 	}
16497c478bd9Sstevel@tonic-gate 
16507c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->attribute_lock);
16517c478bd9Sstevel@tonic-gate 
16527c478bd9Sstevel@tonic-gate 	object->clone_template = clone_template;
16537c478bd9Sstevel@tonic-gate 	object->clone_template_size = c;
16547c478bd9Sstevel@tonic-gate 
16557c478bd9Sstevel@tonic-gate finish:
16567c478bd9Sstevel@tonic-gate 	return (rv);
16577c478bd9Sstevel@tonic-gate }
16587c478bd9Sstevel@tonic-gate 
16597c478bd9Sstevel@tonic-gate 
16607c478bd9Sstevel@tonic-gate /*
16617c478bd9Sstevel@tonic-gate  * meta_object_find_by_handle
16627c478bd9Sstevel@tonic-gate  *
16637c478bd9Sstevel@tonic-gate  * Search for an existing metaobject, using the object handle of a clone
16647c478bd9Sstevel@tonic-gate  * on a particular slot.
16657c478bd9Sstevel@tonic-gate  *
16667c478bd9Sstevel@tonic-gate  * Returns a matching metaobject, or NULL if no match was found.
16677c478bd9Sstevel@tonic-gate  */
16687c478bd9Sstevel@tonic-gate meta_object_t *
16697c478bd9Sstevel@tonic-gate meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum,
16707c478bd9Sstevel@tonic-gate     boolean_t token_only)
16717c478bd9Sstevel@tonic-gate {
16727c478bd9Sstevel@tonic-gate 	meta_object_t *object = NULL, *tmp_obj;
16737c478bd9Sstevel@tonic-gate 	meta_session_t *session;
16747c478bd9Sstevel@tonic-gate 
16757c478bd9Sstevel@tonic-gate 	if (!token_only) {
16767c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&meta_sessionlist_lock);
16777c478bd9Sstevel@tonic-gate 		session = meta_sessionlist_head;
16787c478bd9Sstevel@tonic-gate 		while (session != NULL) {
16797c478bd9Sstevel@tonic-gate 			/* lock the objects list while we look at it */
16807c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_rdlock(
16817c478bd9Sstevel@tonic-gate 			    &(session->object_list_lock));
16827c478bd9Sstevel@tonic-gate 			tmp_obj = session->object_list_head;
16837c478bd9Sstevel@tonic-gate 			while (tmp_obj != NULL) {
16847c478bd9Sstevel@tonic-gate 				slot_object_t *slot_object;
16857c478bd9Sstevel@tonic-gate 
16867c478bd9Sstevel@tonic-gate 				(void) pthread_rwlock_rdlock(
16877c478bd9Sstevel@tonic-gate 				    &(tmp_obj->object_lock));
16887c478bd9Sstevel@tonic-gate 				slot_object = tmp_obj->clones[slotnum];
16897c478bd9Sstevel@tonic-gate 				if (slot_object != NULL) {
16907c478bd9Sstevel@tonic-gate 					if (slot_object->hObject == hObject) {
16917c478bd9Sstevel@tonic-gate 						object = tmp_obj;
16927c478bd9Sstevel@tonic-gate 					}
16937c478bd9Sstevel@tonic-gate 				}
16947c478bd9Sstevel@tonic-gate 				(void) pthread_rwlock_unlock(
16957c478bd9Sstevel@tonic-gate 				    &(tmp_obj->object_lock));
16967c478bd9Sstevel@tonic-gate 				if (object != NULL) {
16977c478bd9Sstevel@tonic-gate 					break;
16987c478bd9Sstevel@tonic-gate 				}
16997c478bd9Sstevel@tonic-gate 				tmp_obj = tmp_obj->next;
17007c478bd9Sstevel@tonic-gate 			}
17017c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(
17027c478bd9Sstevel@tonic-gate 			    &(session->object_list_lock));
17037c478bd9Sstevel@tonic-gate 			if (object != NULL) {
17047c478bd9Sstevel@tonic-gate 				break;
17057c478bd9Sstevel@tonic-gate 			}
17067c478bd9Sstevel@tonic-gate 			session = session->next;
17077c478bd9Sstevel@tonic-gate 		}
17087c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&meta_sessionlist_lock);
17097c478bd9Sstevel@tonic-gate 	}
17107c478bd9Sstevel@tonic-gate 
17117c478bd9Sstevel@tonic-gate 	if (object != NULL) {
17127c478bd9Sstevel@tonic-gate 		/* found the object, no need to look further */
17137c478bd9Sstevel@tonic-gate 		return (object);
17147c478bd9Sstevel@tonic-gate 	}
17157c478bd9Sstevel@tonic-gate 
17167c478bd9Sstevel@tonic-gate 	/*
17177c478bd9Sstevel@tonic-gate 	 * Look at list of token objects
17187c478bd9Sstevel@tonic-gate 	 */
17197c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&tokenobject_list_lock);
17207c478bd9Sstevel@tonic-gate 	tmp_obj = tokenobject_list_head;
17217c478bd9Sstevel@tonic-gate 
17227c478bd9Sstevel@tonic-gate 	while (tmp_obj != NULL) {
17237c478bd9Sstevel@tonic-gate 		slot_object_t *slot_object;
17247c478bd9Sstevel@tonic-gate 
17257c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&(tmp_obj->object_lock));
17267c478bd9Sstevel@tonic-gate 		slot_object = tmp_obj->clones[slotnum];
17277c478bd9Sstevel@tonic-gate 		if (slot_object != NULL) {
17287c478bd9Sstevel@tonic-gate 			if (slot_object->hObject == hObject)
17297c478bd9Sstevel@tonic-gate 				object = tmp_obj;
17307c478bd9Sstevel@tonic-gate 		}
17317c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&(tmp_obj->object_lock));
17327c478bd9Sstevel@tonic-gate 		if (object != NULL) {
17337c478bd9Sstevel@tonic-gate 			break;
17347c478bd9Sstevel@tonic-gate 		}
17357c478bd9Sstevel@tonic-gate 		tmp_obj = tmp_obj->next;
17367c478bd9Sstevel@tonic-gate 	}
17377c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&tokenobject_list_lock);
17387c478bd9Sstevel@tonic-gate 
17397c478bd9Sstevel@tonic-gate 	return (object);
17407c478bd9Sstevel@tonic-gate }
17417c478bd9Sstevel@tonic-gate 
17427c478bd9Sstevel@tonic-gate CK_RV
17437c478bd9Sstevel@tonic-gate meta_token_object_deactivate(token_obj_type_t token_type)
17447c478bd9Sstevel@tonic-gate {
17457c478bd9Sstevel@tonic-gate 	meta_object_t *object, *tmp_object;
17467c478bd9Sstevel@tonic-gate 	CK_RV save_rv = CKR_OK, rv;
17477c478bd9Sstevel@tonic-gate 
17487c478bd9Sstevel@tonic-gate 	/* get a write lock on the token object list */
17497c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&tokenobject_list_lock);
17507c478bd9Sstevel@tonic-gate 
17517c478bd9Sstevel@tonic-gate 	object = tokenobject_list_head;
17527c478bd9Sstevel@tonic-gate 
17537c478bd9Sstevel@tonic-gate 	/* go through each object and delete the one with matching type */
17547c478bd9Sstevel@tonic-gate 	while (object != NULL) {
17557c478bd9Sstevel@tonic-gate 		tmp_object = object->next;
17567c478bd9Sstevel@tonic-gate 
17577c478bd9Sstevel@tonic-gate 		if ((token_type == ALL_TOKEN) ||
17587c478bd9Sstevel@tonic-gate 		    ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) ||
17597c478bd9Sstevel@tonic-gate 		    ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) {
17607c478bd9Sstevel@tonic-gate 			rv = meta_object_deactivate(object, B_TRUE, B_FALSE);
17617c478bd9Sstevel@tonic-gate 			if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
17627c478bd9Sstevel@tonic-gate 				save_rv = rv;
17637c478bd9Sstevel@tonic-gate 				goto finish;
17647c478bd9Sstevel@tonic-gate 			}
17658cae6764SAnthony Scarpino 			rv = meta_object_dealloc(NULL, object, B_FALSE);
17667c478bd9Sstevel@tonic-gate 			if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
17677c478bd9Sstevel@tonic-gate 				save_rv = rv;
17687c478bd9Sstevel@tonic-gate 				goto finish;
17697c478bd9Sstevel@tonic-gate 			}
17707c478bd9Sstevel@tonic-gate 		}
17717c478bd9Sstevel@tonic-gate 		object = tmp_object;
17727c478bd9Sstevel@tonic-gate 	}
17737c478bd9Sstevel@tonic-gate finish:
17747c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&tokenobject_list_lock);
17757c478bd9Sstevel@tonic-gate 	return (save_rv);
17767c478bd9Sstevel@tonic-gate }
17777c478bd9Sstevel@tonic-gate 
17787c478bd9Sstevel@tonic-gate /*
17797c478bd9Sstevel@tonic-gate  * This function adds the to-be-freed meta object to a linked list.
17807c478bd9Sstevel@tonic-gate  * When the number of objects queued in the linked list reaches the
17817c478bd9Sstevel@tonic-gate  * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
17827c478bd9Sstevel@tonic-gate  * object (FIFO) in the list.
17837c478bd9Sstevel@tonic-gate  */
17847c478bd9Sstevel@tonic-gate void
17857c478bd9Sstevel@tonic-gate meta_object_delay_free(meta_object_t *objp)
17867c478bd9Sstevel@tonic-gate {
17877c478bd9Sstevel@tonic-gate 	meta_object_t *tmp;
17887c478bd9Sstevel@tonic-gate 
17897c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
17907c478bd9Sstevel@tonic-gate 
17917c478bd9Sstevel@tonic-gate 	/* Add the newly deleted object at the end of the list */
17927c478bd9Sstevel@tonic-gate 	objp->next = NULL;
17937c478bd9Sstevel@tonic-gate 	if (obj_delay_freed.first == NULL) {
17947c478bd9Sstevel@tonic-gate 		obj_delay_freed.last = objp;
17957c478bd9Sstevel@tonic-gate 		obj_delay_freed.first = objp;
17967c478bd9Sstevel@tonic-gate 	} else {
17977c478bd9Sstevel@tonic-gate 		obj_delay_freed.last->next = objp;
17987c478bd9Sstevel@tonic-gate 		obj_delay_freed.last = objp;
17997c478bd9Sstevel@tonic-gate 	}
18007c478bd9Sstevel@tonic-gate 
18017c478bd9Sstevel@tonic-gate 	if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
18027c478bd9Sstevel@tonic-gate 		/*
18037c478bd9Sstevel@tonic-gate 		 * Free the first object in the list only if
18047c478bd9Sstevel@tonic-gate 		 * the total count reaches maximum threshold.
18057c478bd9Sstevel@tonic-gate 		 */
18067c478bd9Sstevel@tonic-gate 		obj_delay_freed.count--;
18077c478bd9Sstevel@tonic-gate 		tmp = obj_delay_freed.first->next;
18087c478bd9Sstevel@tonic-gate 		free(obj_delay_freed.first);
18097c478bd9Sstevel@tonic-gate 		obj_delay_freed.first = tmp;
18107c478bd9Sstevel@tonic-gate 	}
18117c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
18127c478bd9Sstevel@tonic-gate }
1813034448feSmcpowers 
1814034448feSmcpowers 
1815034448feSmcpowers /*
1816034448feSmcpowers  * This function checks if the object passed can be a freeobject.
1817034448feSmcpowers  *
1818034448feSmcpowers  * If there is more than one provider that supports the supported freeobject
1819034448feSmcpowers  * mechanisms then allow freeobjects to be an option.
1820034448feSmcpowers  */
1821034448feSmcpowers 
1822034448feSmcpowers boolean_t
1823034448feSmcpowers meta_freeobject_check(meta_session_t *session, meta_object_t *object,
1824034448feSmcpowers     CK_MECHANISM *pMech, CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len,
1825034448feSmcpowers     CK_KEY_TYPE keytype)
1826034448feSmcpowers {
1827034448feSmcpowers 	mech_support_info_t *info = &(session->mech_support_info);
1828034448feSmcpowers 
1829034448feSmcpowers 	/*
1830034448feSmcpowers 	 * If key migration is turned off, or the object does not has any of
1831034448feSmcpowers 	 * the required flags and there is only one slot, then we don't need
1832034448feSmcpowers 	 * FreeObjects.
1833034448feSmcpowers 	 */
1834034448feSmcpowers 	if (!metaslot_auto_key_migrate ||
1835034448feSmcpowers 	    (!object->isToken && !object->isSensitive &&
1836034448feSmcpowers 	    meta_slotManager_get_slotcount() < 2))
1837034448feSmcpowers 		goto failure;
1838034448feSmcpowers 
1839034448feSmcpowers 	/*
1840034448feSmcpowers 	 * If this call is for key generation, check pMech for supported
1841034448feSmcpowers 	 * FreeObject mechs
1842034448feSmcpowers 	 */
1843034448feSmcpowers 	if (pMech != NULL) {
1844034448feSmcpowers 		if (pMech->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN ||
1845034448feSmcpowers 		    pMech->mechanism == CKM_EC_KEY_PAIR_GEN ||
1846034448feSmcpowers 		    pMech->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN ||
1847034448feSmcpowers 		    pMech->mechanism == CKM_DH_PKCS_DERIVE)
1848034448feSmcpowers 			info->mech = pMech->mechanism;
1849034448feSmcpowers 		else
1850034448feSmcpowers 			goto failure;
1851034448feSmcpowers 
1852034448feSmcpowers 	/*
1853034448feSmcpowers 	 * If this call is for an object creation, look inside the template
1854034448feSmcpowers 	 * for supported FreeObject mechs
1855034448feSmcpowers 	 */
1856034448feSmcpowers 	} else if (tmpl_len > 0) {
1857d3a28a55Sdinak 		if (!get_template_ulong(CKA_KEY_TYPE, tmpl, tmpl_len, &keytype))
1858034448feSmcpowers 			goto failure;
1859034448feSmcpowers 
1860034448feSmcpowers 		switch (keytype) {
1861034448feSmcpowers 		case CKK_RSA:
1862034448feSmcpowers 			info->mech = CKM_RSA_PKCS_KEY_PAIR_GEN;
1863034448feSmcpowers 			break;
1864034448feSmcpowers 		case CKK_EC:
1865034448feSmcpowers 			info->mech = CKM_EC_KEY_PAIR_GEN;
1866034448feSmcpowers 			break;
1867034448feSmcpowers 		case CKK_DH:
1868034448feSmcpowers 			info->mech = CKM_DH_PKCS_KEY_PAIR_GEN;
1869034448feSmcpowers 			break;
1870034448feSmcpowers 		default:
1871034448feSmcpowers 			goto failure;
1872034448feSmcpowers 		}
1873034448feSmcpowers 	} else
1874034448feSmcpowers 		goto failure;
1875034448feSmcpowers 
1876034448feSmcpowers 	/* Get the slot that support this mech... */
1877d3a28a55Sdinak 	if (meta_mechManager_get_slots(info, B_FALSE, NULL) != CKR_OK)
1878034448feSmcpowers 		goto failure;
1879034448feSmcpowers 
1880034448feSmcpowers 	/*
1881034448feSmcpowers 	 * If there is only one slot with the mech or the first slot in
1882034448feSmcpowers 	 * the list is the keystore slot, we should bail.
1883034448feSmcpowers 	 */
1884034448feSmcpowers 	if (info->num_supporting_slots < 2 &&
1885034448feSmcpowers 	    info->supporting_slots[0]->slotnum == get_keystore_slotnum())
1886034448feSmcpowers 		goto failure;
1887034448feSmcpowers 
1888034448feSmcpowers 	if (object->isToken)
1889034448feSmcpowers 		object->isFreeToken = FREE_ALLOWED_KEY;
1890034448feSmcpowers 	else
1891034448feSmcpowers 		object->isFreeToken = FREE_DISABLED;
1892034448feSmcpowers 
1893034448feSmcpowers 	object->isFreeObject = FREE_ALLOWED_KEY;
1894034448feSmcpowers 
1895034448feSmcpowers 	return (B_TRUE);
1896034448feSmcpowers 
1897034448feSmcpowers failure:
1898034448feSmcpowers 	object->isFreeToken = FREE_DISABLED;
1899034448feSmcpowers 	object->isFreeObject = FREE_DISABLED;
1900034448feSmcpowers 	return (B_FALSE);
1901034448feSmcpowers }
1902034448feSmcpowers 
1903034448feSmcpowers /*
1904034448feSmcpowers  * This function assumes meta_freeobject_check() has just been called and set
1905034448feSmcpowers  * the isFreeObject and/or isFreeToken vars to FREE_ALLOWED_KEY.
1906034448feSmcpowers  *
1907034448feSmcpowers  * If the template value for CKA_PRIVATE, CKA_SENSITIVE and/or CKA_TOKEN are
1908034448feSmcpowers  * true, then isFreeObject is fully enabled.  In addition isFreeToken is
1909034448feSmcpowers  * enabled if is CKA_TOKEN true.
1910034448feSmcpowers  *
1911034448feSmcpowers  * If create is true, we are doing a C_CreateObject operation and don't
1912034448feSmcpowers  * handle CKA_PRIVATE & CKA_SENSITIVE flags, we only care about CKA_TOKEN.
1913034448feSmcpowers  */
1914034448feSmcpowers 
1915034448feSmcpowers boolean_t
1916034448feSmcpowers meta_freeobject_set(meta_object_t *object, CK_ATTRIBUTE *tmpl,
1917034448feSmcpowers     CK_ULONG tmpl_len, boolean_t create)
1918034448feSmcpowers {
1919034448feSmcpowers 
1920034448feSmcpowers 	/* This check should never be true, if it is, it's a bug */
1921034448feSmcpowers 	if (object->isFreeObject < FREE_ALLOWED_KEY)
1922034448feSmcpowers 		return (B_FALSE);
1923034448feSmcpowers 
1924034448feSmcpowers 	if (!create) {
1925034448feSmcpowers 		/* Turn off the Sensitive flag */
1926034448feSmcpowers 		if (object->isSensitive) {
1927d3a28a55Sdinak 			if (set_template_boolean(CKA_SENSITIVE, tmpl, tmpl_len,
1928d3a28a55Sdinak 			    B_TRUE, &falsevalue) == -1)
1929034448feSmcpowers 				goto failure;
1930034448feSmcpowers 
1931034448feSmcpowers 			object->isFreeObject = FREE_ENABLED;
1932034448feSmcpowers 		}
1933034448feSmcpowers 
1934034448feSmcpowers 		/* Turn off the Private flag */
1935034448feSmcpowers 		if (object->isPrivate) {
1936d3a28a55Sdinak 			if (set_template_boolean(CKA_PRIVATE, tmpl, tmpl_len,
1937d3a28a55Sdinak 			    B_TRUE, &falsevalue) == -1)
1938034448feSmcpowers 				goto failure;
1939034448feSmcpowers 
1940034448feSmcpowers 			object->isFreeObject = FREE_ENABLED;
1941034448feSmcpowers 		}
1942034448feSmcpowers 	}
1943034448feSmcpowers 
1944034448feSmcpowers 	if (object->isToken) {
1945034448feSmcpowers 		object->isToken = B_FALSE;
1946034448feSmcpowers 		object->isFreeToken = FREE_ENABLED;
1947034448feSmcpowers 		object->isFreeObject = FREE_ENABLED;
1948034448feSmcpowers 	} else
1949034448feSmcpowers 		object->isFreeToken = FREE_DISABLED;
1950034448feSmcpowers 
1951034448feSmcpowers 	/*
1952034448feSmcpowers 	 *  If isFreeObject is not in the FREE_ENABLED state yet, it can be
1953034448feSmcpowers 	 *  turned off because the object doesn't not need to be a FreeObject.
1954034448feSmcpowers 	 */
1955034448feSmcpowers 	if (object->isFreeObject == FREE_ALLOWED_KEY)
1956034448feSmcpowers 		object->isFreeObject = FREE_DISABLED;
1957034448feSmcpowers 
1958034448feSmcpowers 	return (B_TRUE);
1959034448feSmcpowers 
1960034448feSmcpowers failure:
1961034448feSmcpowers 	object->isFreeToken = FREE_DISABLED;
1962034448feSmcpowers 	object->isFreeObject = FREE_DISABLED;
1963034448feSmcpowers 	return (B_FALSE);
1964034448feSmcpowers }
1965034448feSmcpowers 
1966034448feSmcpowers /*
1967034448feSmcpowers  * This function sets the CKA_TOKEN flag on a given object template depending
1968034448feSmcpowers  * if the slot being used is a keystore.
1969034448feSmcpowers  *
1970034448feSmcpowers  * If the object is a token, but the slot is not the system keystore or has
1971034448feSmcpowers  * no keystore, then set the template to token = false; otherwise it's true.
1972034448feSmcpowers  * In addition we know ahead of time what the value is, so if the value is
1973034448feSmcpowers  * already correct, bypass the setting function
1974034448feSmcpowers  */
1975034448feSmcpowers CK_RV
1976034448feSmcpowers meta_freetoken_set(CK_ULONG slot_num, CK_BBOOL *current_value,
1977034448feSmcpowers     CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len)
1978034448feSmcpowers {
1979034448feSmcpowers 
1980034448feSmcpowers 	if (slot_num == get_keystore_slotnum()) {
1981034448feSmcpowers 		if (*current_value == TRUE)
1982034448feSmcpowers 			return (CKR_OK);
1983034448feSmcpowers 
1984034448feSmcpowers 		if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
1985034448feSmcpowers 		    &truevalue) == -1)
1986034448feSmcpowers 			return (CKR_FUNCTION_FAILED);
1987034448feSmcpowers 
1988034448feSmcpowers 	} else {
1989034448feSmcpowers 
1990034448feSmcpowers 		if (*current_value == FALSE)
1991034448feSmcpowers 			return (CKR_OK);
1992034448feSmcpowers 
1993034448feSmcpowers 		if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
1994034448feSmcpowers 		    &falsevalue) == -1)
1995034448feSmcpowers 			return (CKR_FUNCTION_FAILED);
1996034448feSmcpowers 
1997034448feSmcpowers 		*current_value = FALSE;
1998034448feSmcpowers 	}
1999034448feSmcpowers 
2000034448feSmcpowers 	return (CKR_OK);
2001034448feSmcpowers }
2002034448feSmcpowers 
2003034448feSmcpowers /*
2004034448feSmcpowers  * Cloning function for meta_freeobject_clone() to use.  This function
2005034448feSmcpowers  * is streamlined because we know what the object is and this should
2006034448feSmcpowers  * not be called as a generic cloner.
2007034448feSmcpowers  */
2008034448feSmcpowers 
2009034448feSmcpowers static CK_RV
2010034448feSmcpowers meta_freeobject_clone_maker(meta_session_t *session, meta_object_t *object,
2011034448feSmcpowers     CK_ULONG slotnum)
2012034448feSmcpowers {
2013034448feSmcpowers 
2014034448feSmcpowers 	slot_object_t *slot_object = NULL;
2015034448feSmcpowers 	slot_session_t *slot_session = NULL;
2016034448feSmcpowers 	CK_RV rv;
2017034448feSmcpowers 
2018034448feSmcpowers 	rv = meta_slot_object_alloc(&slot_object);
2019034448feSmcpowers 	if (rv != CKR_OK)
2020034448feSmcpowers 		goto cleanup;
2021034448feSmcpowers 
2022034448feSmcpowers 	rv = meta_get_slot_session(slotnum, &slot_session,
2023034448feSmcpowers 	    session->session_flags);
2024034448feSmcpowers 	if (rv != CKR_OK)
2025034448feSmcpowers 		goto cleanup;
2026034448feSmcpowers 
2027034448feSmcpowers 	rv = clone_by_create(object, slot_object, slot_session);
2028034448feSmcpowers 	if (rv == CKR_OK) {
2029034448feSmcpowers 		object->clones[slotnum] = slot_object;
2030034448feSmcpowers 		meta_slot_object_activate(slot_object, slot_session, B_TRUE);
2031034448feSmcpowers 	}
2032034448feSmcpowers 
2033034448feSmcpowers cleanup:
2034034448feSmcpowers 	meta_release_slot_session(slot_session);
2035034448feSmcpowers 	return (rv);
2036034448feSmcpowers 
2037034448feSmcpowers }
2038034448feSmcpowers 
2039034448feSmcpowers /*
2040034448feSmcpowers  * This function is called when a object is a FreeObject.
2041034448feSmcpowers  *
2042034448feSmcpowers  * What we are given is an object that has been generated on a provider
2043034448feSmcpowers  * that is not its final usage place. That maybe because:
2044034448feSmcpowers  * 1) it's a token and needs to be stored in keystore.
2045034448feSmcpowers  * 2) it was to be a private/sensitive object that we modified so we could know
2046034448feSmcpowers  *    the important attributes for cloning before we make it private/sensitive.
2047034448feSmcpowers  */
2048034448feSmcpowers 
2049034448feSmcpowers boolean_t
2050034448feSmcpowers meta_freeobject_clone(meta_session_t *session, meta_object_t *object)
2051034448feSmcpowers {
2052034448feSmcpowers 	CK_RV rv;
2053034448feSmcpowers 	CK_ULONG keystore_slotnum;
2054034448feSmcpowers 	CK_ATTRIBUTE attr[2];
2055034448feSmcpowers 	boolean_t failover = B_FALSE;
2056034448feSmcpowers 
2057034448feSmcpowers 	if (object->attributes == NULL) {
2058034448feSmcpowers 		rv = meta_object_copyin(object);
2059034448feSmcpowers 		if (rv != CKR_OK)
2060034448feSmcpowers 			return (rv);
2061034448feSmcpowers 	}
2062034448feSmcpowers 
2063034448feSmcpowers 	if (object->isPrivate) {
2064034448feSmcpowers 		CK_OBJECT_HANDLE new_clone;
2065034448feSmcpowers 		CK_ULONG slotnum = object->master_clone_slotnum;
2066034448feSmcpowers 		slot_session_t *slot_session;
2067034448feSmcpowers 
2068034448feSmcpowers 		attr[0].type = CKA_PRIVATE;
2069034448feSmcpowers 		attr[0].pValue = &truevalue;
2070034448feSmcpowers 		attr[0].ulValueLen = sizeof (truevalue);
2071034448feSmcpowers 
2072034448feSmcpowers 		/* Set the master attribute list */
2073034448feSmcpowers 		rv = attribute_set_value(attr, object->attributes,
2074034448feSmcpowers 		    object->num_attributes);
2075034448feSmcpowers 		if (rv > 0)
2076034448feSmcpowers 			return (CKR_FUNCTION_FAILED);
2077034448feSmcpowers 
2078034448feSmcpowers 		/* Get a slot session */
2079034448feSmcpowers 		rv = meta_get_slot_session(slotnum, &slot_session,
2080034448feSmcpowers 		    session->session_flags);
2081034448feSmcpowers 		if (rv > 0)
2082034448feSmcpowers 			return (rv);
2083034448feSmcpowers 
2084034448feSmcpowers 		/* Create the new CKA_PRIVATE one */
2085034448feSmcpowers 		rv = FUNCLIST(slot_session->fw_st_id)->\
2086034448feSmcpowers 		    C_CopyObject(slot_session->hSession,
2087034448feSmcpowers 		    object->clones[slotnum]->hObject, attr, 1, &new_clone);
2088034448feSmcpowers 
2089034448feSmcpowers 		if (rv == CKR_USER_NOT_LOGGED_IN) {
2090034448feSmcpowers 			/*
2091034448feSmcpowers 			 * If the CopyObject fails, we may be using a provider
2092034448feSmcpowers 			 * that has a keystore that is not the default
2093034448feSmcpowers 			 * keystore set in metaslot or has object management
2094034448feSmcpowers 			 * abilities. In which case we should write this
2095034448feSmcpowers 			 * object to metaslot's keystore and let the failover.
2096034448feSmcpowers 			 * rest of the function know we've changed providers.
2097034448feSmcpowers 			 */
2098034448feSmcpowers 			failover = B_TRUE;
2099034448feSmcpowers 			keystore_slotnum = get_keystore_slotnum();
2100034448feSmcpowers 			if (object->clones[keystore_slotnum] == NULL) {
2101034448feSmcpowers 				rv = meta_freeobject_clone_maker(session,
2102034448feSmcpowers 				    object, keystore_slotnum);
2103034448feSmcpowers 				if (rv != CKR_OK) {
2104034448feSmcpowers 					goto failure;
2105034448feSmcpowers 				}
2106034448feSmcpowers 			}
2107034448feSmcpowers 			object->master_clone_slotnum = keystore_slotnum;
2108034448feSmcpowers 
2109034448feSmcpowers 		} else if (rv != CKR_OK) {
2110034448feSmcpowers 			meta_release_slot_session(slot_session);
2111034448feSmcpowers 			goto failure;
2112034448feSmcpowers 		}
2113034448feSmcpowers 		/* Remove the old object */
2114034448feSmcpowers 		rv = FUNCLIST(slot_session->fw_st_id)->	\
2115034448feSmcpowers 		    C_DestroyObject(slot_session->hSession,
2116034448feSmcpowers 		    object->clones[slotnum]->hObject);
2117034448feSmcpowers 		if (rv != CKR_OK) {
2118034448feSmcpowers 			meta_release_slot_session(slot_session);
2119034448feSmcpowers 			goto failure;
2120034448feSmcpowers 		}
2121034448feSmcpowers 
2122034448feSmcpowers 		if (!failover)
2123034448feSmcpowers 			object->clones[slotnum]->hObject = new_clone;
2124034448feSmcpowers 		else
2125034448feSmcpowers 			object->clones[slotnum] = NULL;
2126034448feSmcpowers 
2127034448feSmcpowers 		meta_release_slot_session(slot_session);
2128034448feSmcpowers 
2129034448feSmcpowers 	}
2130034448feSmcpowers 
2131034448feSmcpowers 	if (object->isSensitive) {
2132034448feSmcpowers 		slot_session_t *slot_session;
2133034448feSmcpowers 		CK_ULONG slotnum = object->master_clone_slotnum;
2134034448feSmcpowers 
2135034448feSmcpowers 		attr[0].type = CKA_SENSITIVE;
2136034448feSmcpowers 		attr[0].pValue = &truevalue;
2137034448feSmcpowers 		attr[0].ulValueLen = sizeof (truevalue);
2138034448feSmcpowers 		rv = attribute_set_value(attr, object->attributes,
2139034448feSmcpowers 		    object->num_attributes);
2140034448feSmcpowers 		if (rv != CKR_OK)
2141034448feSmcpowers 			goto failure;
2142034448feSmcpowers 
2143034448feSmcpowers 		rv = meta_get_slot_session(slotnum, &slot_session,
2144034448feSmcpowers 		    session->session_flags);
2145034448feSmcpowers 		if (rv == CKR_OK) {
2146034448feSmcpowers 			rv = FUNCLIST(slot_session->fw_st_id)->		\
2147034448feSmcpowers 			    C_SetAttributeValue(slot_session->hSession,
2148034448feSmcpowers 			    object->clones[slotnum]->hObject, attr, 1);
2149034448feSmcpowers 
2150034448feSmcpowers 			meta_release_slot_session(slot_session);
2151034448feSmcpowers 		}
2152034448feSmcpowers 	}
2153034448feSmcpowers 
2154034448feSmcpowers 	if (object->isFreeToken == FREE_ENABLED || failover) {
2155034448feSmcpowers 		keystore_slotnum = get_keystore_slotnum();
2156034448feSmcpowers 		if (object->clones[keystore_slotnum] == NULL) {
2157034448feSmcpowers 			rv = meta_freeobject_clone_maker(session, object,
2158034448feSmcpowers 			    keystore_slotnum);
2159034448feSmcpowers 			if (rv != CKR_OK)
2160034448feSmcpowers 				goto failure;
2161034448feSmcpowers 
2162034448feSmcpowers 			object->master_clone_slotnum = keystore_slotnum;
2163034448feSmcpowers 		}
2164034448feSmcpowers 		object->isFreeToken = FREE_ENABLED;
2165034448feSmcpowers 	}
2166034448feSmcpowers 
2167034448feSmcpowers 	object->isFreeObject = FREE_ENABLED;
2168034448feSmcpowers 	return (CKR_OK);
2169034448feSmcpowers 
2170034448feSmcpowers failure:
2171034448feSmcpowers 	object->isFreeToken = FREE_DISABLED;
2172034448feSmcpowers 	object->isFreeObject = FREE_DISABLED;
2173034448feSmcpowers 	return (rv);
2174034448feSmcpowers 
2175034448feSmcpowers }
2176