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