xref: /onnv-gate/usr/src/lib/pkcs11/libpkcs11/common/metaObjectManager.c (revision 12558:9c40eb91511d)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
54219Smcpowers  * Common Development and Distribution License (the "License").
64219Smcpowers  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*12558Sdan.opensolaris.anderson@drydog.com  * Copyright (c) 2004, 2010, Oracle and/or its affiliates. All rights reserved.
230Sstevel@tonic-gate  */
240Sstevel@tonic-gate 
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <stdlib.h>
270Sstevel@tonic-gate #include <string.h>
280Sstevel@tonic-gate #include <strings.h>
290Sstevel@tonic-gate #include <errno.h>
300Sstevel@tonic-gate #include <fcntl.h>
310Sstevel@tonic-gate #include <sys/types.h>
320Sstevel@tonic-gate #include <sys/stat.h>
330Sstevel@tonic-gate #include "metaGlobal.h"
340Sstevel@tonic-gate 
350Sstevel@tonic-gate /* Size of the template for creating key used for wrap/unwrap */
360Sstevel@tonic-gate #define	WRAP_KEY_TEMPLATE_SIZE	7
370Sstevel@tonic-gate 
380Sstevel@tonic-gate /*
390Sstevel@tonic-gate  * Information necessary to create keys for C_WrapKey/C_UnwrapKey
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate typedef struct _wrap_info {
420Sstevel@tonic-gate 	CK_OBJECT_CLASS		class; /* class of the key for wrap/unwrap */
430Sstevel@tonic-gate 	CK_KEY_TYPE		key_type; /* key type of key for wrap/unwrap */
440Sstevel@tonic-gate 	CK_ULONG		key_length; /* length of key */
450Sstevel@tonic-gate 	CK_MECHANISM_TYPE	mech_type; /* mech used for wrap/unwrap */
460Sstevel@tonic-gate 	CK_ULONG		iv_length; /* length of iv for mech */
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 	boolean_t		src_supports;
490Sstevel@tonic-gate 	boolean_t		dst_supports;
500Sstevel@tonic-gate } wrap_info_t;
510Sstevel@tonic-gate 
520Sstevel@tonic-gate extern pthread_rwlock_t meta_sessionlist_lock;
530Sstevel@tonic-gate extern meta_session_t *meta_sessionlist_head;
540Sstevel@tonic-gate 
550Sstevel@tonic-gate static wrap_info_t common_wrap_info[] = {
560Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_AES, 16, CKM_AES_CBC_PAD, 16, B_FALSE, B_FALSE},
570Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_DES3, 24, CKM_DES3_CBC_PAD, 8, B_FALSE, B_FALSE},
580Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_DES, 8, CKM_DES_CBC_PAD, 8, B_FALSE, B_FALSE},
590Sstevel@tonic-gate };
600Sstevel@tonic-gate 
610Sstevel@tonic-gate static unsigned int num_common_wrap_info =
620Sstevel@tonic-gate     sizeof (common_wrap_info) / sizeof (wrap_info_t);
630Sstevel@tonic-gate 
640Sstevel@tonic-gate static wrap_info_t special_wrap_info[] = {
650Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_SKIPJACK, 12,  CKM_SKIPJACK_WRAP, 0,
660Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
670Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_BATON, 40, CKM_BATON_WRAP, 0,
680Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
690Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_JUNIPER, 40, CKM_JUNIPER_WRAP, 0,
700Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
710Sstevel@tonic-gate };
720Sstevel@tonic-gate static unsigned int num_special_wrap_info =
730Sstevel@tonic-gate     sizeof (special_wrap_info) / sizeof (wrap_info_t);
740Sstevel@tonic-gate 
750Sstevel@tonic-gate static wrap_info_t rsa_wrap_info[] = {
760Sstevel@tonic-gate 	{CKO_PUBLIC_KEY, CKK_RSA, 0,  CKM_RSA_PKCS, 0,
770Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
780Sstevel@tonic-gate 	{CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_X_509, 0,
790Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
800Sstevel@tonic-gate };
810Sstevel@tonic-gate static unsigned int num_rsa_wrap_info =
820Sstevel@tonic-gate     sizeof (rsa_wrap_info) / sizeof (wrap_info_t);
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 
850Sstevel@tonic-gate static pthread_rwlock_t meta_objectclose_lock;
860Sstevel@tonic-gate static pthread_rwlock_t tokenobject_list_lock;
870Sstevel@tonic-gate static meta_object_t *tokenobject_list_head;
880Sstevel@tonic-gate 
894219Smcpowers CK_BBOOL falsevalue = FALSE;
904219Smcpowers CK_BBOOL truevalue = TRUE;
910Sstevel@tonic-gate 
920Sstevel@tonic-gate /*
930Sstevel@tonic-gate  * Public and private exponent, and Module value for
940Sstevel@tonic-gate  * creating the RSA public/private key.
950Sstevel@tonic-gate  *
960Sstevel@tonic-gate  */
970Sstevel@tonic-gate static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01};
980Sstevel@tonic-gate CK_BYTE PriExpo[128] = {
990Sstevel@tonic-gate 	0x8e, 0xc9, 0x70, 0x57, 0x6b, 0xcd, 0xfb, 0xa9,
1000Sstevel@tonic-gate 	0x19, 0xad, 0xcd, 0x91, 0x69, 0xd5, 0x52, 0xec,
1010Sstevel@tonic-gate 	0x72, 0x1e, 0x45, 0x15, 0x06, 0xdc, 0x65, 0x2d,
1020Sstevel@tonic-gate 	0x98, 0xc4, 0xce, 0x33, 0x54, 0x15, 0x70, 0x8d,
1030Sstevel@tonic-gate 	0xfa, 0x65, 0xea, 0x53, 0x44, 0xf3, 0x3e, 0x3f,
1040Sstevel@tonic-gate 	0xb4, 0x4c, 0x60, 0xd5, 0x01, 0x2d, 0xa4, 0x12,
1050Sstevel@tonic-gate 	0x99, 0xbf, 0x3f, 0x0b, 0xcd, 0xbb, 0x24, 0x10,
1060Sstevel@tonic-gate 	0x60, 0x30, 0x5e, 0x58, 0xf8, 0x59, 0xaa, 0xd1,
1070Sstevel@tonic-gate 	0x63, 0x3b, 0xbc, 0xcb, 0x94, 0x58, 0x38, 0x24,
1080Sstevel@tonic-gate 	0xfc, 0x65, 0x25, 0xc5, 0xa6, 0x51, 0xa2, 0x2e,
1090Sstevel@tonic-gate 	0xf1, 0x5e, 0xf5, 0xc1, 0xf5, 0x46, 0xf7, 0xbd,
1100Sstevel@tonic-gate 	0xc7, 0x62, 0xa8, 0xe2, 0x27, 0xd6, 0x94, 0x5b,
1110Sstevel@tonic-gate 	0xd3, 0xa2, 0xb5, 0x76, 0x42, 0x67, 0x6b, 0x86,
1120Sstevel@tonic-gate 	0x91, 0x97, 0x4d, 0x07, 0x92, 0x00, 0x4a, 0xdf,
1130Sstevel@tonic-gate 	0x0b, 0x65, 0x64, 0x05, 0x03, 0x48, 0x27, 0xeb,
1140Sstevel@tonic-gate 	0xce, 0x9a, 0x49, 0x7f, 0x3e, 0x10, 0xe0, 0x01};
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate static CK_BYTE Modulus[128] = {
1170Sstevel@tonic-gate 	0x94, 0x32, 0xb9, 0x12, 0x1d, 0x68, 0x2c, 0xda,
1180Sstevel@tonic-gate 	0x2b, 0xe0, 0xe4, 0x97, 0x1b, 0x4d, 0xdc, 0x43,
1190Sstevel@tonic-gate 	0xdf, 0x38, 0x6e, 0x7b, 0x9f, 0x07, 0x58, 0xae,
1200Sstevel@tonic-gate 	0x9d, 0x82, 0x1e, 0xc7, 0xbc, 0x92, 0xbf, 0xd3,
1210Sstevel@tonic-gate 	0xce, 0x00, 0xbb, 0x91, 0xc9, 0x79, 0x06, 0x03,
1220Sstevel@tonic-gate 	0x1f, 0xbc, 0x9f, 0x94, 0x75, 0x29, 0x5f, 0xd7,
1230Sstevel@tonic-gate 	0xc5, 0xf3, 0x73, 0x8a, 0xa4, 0x35, 0x43, 0x7a,
1240Sstevel@tonic-gate 	0x00, 0x32, 0x97, 0x3e, 0x86, 0xef, 0x70, 0x6f,
1250Sstevel@tonic-gate 	0x18, 0x56, 0x15, 0xaa, 0x6a, 0x87, 0xe7, 0x8d,
1260Sstevel@tonic-gate 	0x7d, 0xdd, 0x1f, 0xa4, 0xe4, 0x31, 0xd4, 0x7a,
1270Sstevel@tonic-gate 	0x8c, 0x0e, 0x20, 0xd2, 0x23, 0xf5, 0x57, 0x3c,
1280Sstevel@tonic-gate 	0x1b, 0xa8, 0x44, 0xa4, 0x57, 0x8f, 0x33, 0x52,
1290Sstevel@tonic-gate 	0xad, 0x83, 0xae, 0x4a, 0x97, 0xa6, 0x1e, 0xa6,
1300Sstevel@tonic-gate 	0x2b, 0xfa, 0xea, 0xeb, 0x6e, 0x71, 0xb8, 0xb6,
1310Sstevel@tonic-gate 	0x0a, 0x36, 0xed, 0x83, 0xce, 0xb0, 0xdf, 0xc1,
1320Sstevel@tonic-gate 	0xd4, 0x3a, 0xe9, 0x99, 0x6f, 0xf3, 0x96, 0xb7};
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate static CK_RV
1350Sstevel@tonic-gate meta_clone_template_setup(meta_object_t *object,
1360Sstevel@tonic-gate     const generic_attr_t *attributes, size_t num_attributes);
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate /*
1390Sstevel@tonic-gate  * meta_objectManager_initialize
1400Sstevel@tonic-gate  *
1410Sstevel@tonic-gate  * Called from meta_Initialize.  Initializes all the variables used
1420Sstevel@tonic-gate  * by the object manager.
1430Sstevel@tonic-gate  */
1440Sstevel@tonic-gate CK_RV
meta_objectManager_initialize()1450Sstevel@tonic-gate meta_objectManager_initialize()
1460Sstevel@tonic-gate {
1470Sstevel@tonic-gate 	if (pthread_rwlock_init(&meta_objectclose_lock, NULL) != 0) {
1480Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
1490Sstevel@tonic-gate 	}
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	if (pthread_rwlock_init(&tokenobject_list_lock, NULL) != 0) {
1520Sstevel@tonic-gate 		(void) pthread_rwlock_destroy(&meta_objectclose_lock);
1530Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
1540Sstevel@tonic-gate 	}
1550Sstevel@tonic-gate 
1560Sstevel@tonic-gate 	tokenobject_list_head = NULL;
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 	return (CKR_OK);
1590Sstevel@tonic-gate }
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate void
meta_objectManager_finalize()1620Sstevel@tonic-gate meta_objectManager_finalize()
1630Sstevel@tonic-gate {
1640Sstevel@tonic-gate 	/*
1650Sstevel@tonic-gate 	 * If there are still any token object in the list, need to
1660Sstevel@tonic-gate 	 * deactivate all of them.
1670Sstevel@tonic-gate 	 */
1680Sstevel@tonic-gate 	(void) meta_token_object_deactivate(ALL_TOKEN);
1690Sstevel@tonic-gate 
1700Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&meta_objectclose_lock);
1710Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&tokenobject_list_lock);
1720Sstevel@tonic-gate }
1730Sstevel@tonic-gate 
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate /*
1770Sstevel@tonic-gate  * meta_handle2object
1780Sstevel@tonic-gate  *
1790Sstevel@tonic-gate  * Convert a CK_OBJECT_HANDLE to the corresponding metaobject. If
1800Sstevel@tonic-gate  * successful, a reader-lock on the object will be held to indicate
1810Sstevel@tonic-gate  * that it's in use. Call OBJRELEASE() when finished.
1820Sstevel@tonic-gate  *
1830Sstevel@tonic-gate  */
1840Sstevel@tonic-gate CK_RV
meta_handle2object(CK_OBJECT_HANDLE hObject,meta_object_t ** object)1850Sstevel@tonic-gate meta_handle2object(CK_OBJECT_HANDLE hObject, meta_object_t **object)
1860Sstevel@tonic-gate {
1870Sstevel@tonic-gate 	meta_object_t *tmp_object = (meta_object_t *)(hObject);
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	/* Check for bad args (eg CK_INVALID_HANDLE, which is 0/NULL). */
1900Sstevel@tonic-gate 	if (tmp_object == NULL) {
1910Sstevel@tonic-gate 		*object = NULL;
1920Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
1930Sstevel@tonic-gate 	}
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 	/* Lock to ensure the magic-check + read-lock is atomic. */
1970Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&meta_objectclose_lock);
1980Sstevel@tonic-gate 
1990Sstevel@tonic-gate 	if (tmp_object->magic_marker != METASLOT_OBJECT_MAGIC) {
2000Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&meta_objectclose_lock);
2010Sstevel@tonic-gate 		*object = NULL;
2020Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
2030Sstevel@tonic-gate 	}
2040Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&tmp_object->object_lock);
2050Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&meta_objectclose_lock);
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	*object = tmp_object;
2080Sstevel@tonic-gate 	return (CKR_OK);
2090Sstevel@tonic-gate }
2100Sstevel@tonic-gate 
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate /*
2130Sstevel@tonic-gate  * meta_object_alloc
2140Sstevel@tonic-gate  *
2150Sstevel@tonic-gate  * Creates a new metaobject, but does not yet add it to the object list.
2160Sstevel@tonic-gate  * Once the caller has finished initializing the object (by setting
2170Sstevel@tonic-gate  * object attributes), meta_object_add should be called. This two-step
2180Sstevel@tonic-gate  * process prevents others from seeing the object until fully intitialized.
2190Sstevel@tonic-gate  *
2200Sstevel@tonic-gate  */
2210Sstevel@tonic-gate CK_RV
meta_object_alloc(meta_session_t * session,meta_object_t ** object)2220Sstevel@tonic-gate meta_object_alloc(meta_session_t *session, meta_object_t **object)
2230Sstevel@tonic-gate {
2240Sstevel@tonic-gate 	meta_object_t *new_object;
2250Sstevel@tonic-gate 	CK_ULONG num_slots;
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 	/* Allocate memory for the object. */
2280Sstevel@tonic-gate 	new_object = calloc(1, sizeof (meta_object_t));
2290Sstevel@tonic-gate 	if (new_object == NULL)
2300Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	num_slots = meta_slotManager_get_slotcount();
2330Sstevel@tonic-gate 
2340Sstevel@tonic-gate 	new_object->clones = calloc(num_slots, sizeof (slot_object_t *));
2350Sstevel@tonic-gate 	if (new_object->clones == NULL) {
2360Sstevel@tonic-gate 		free(new_object);
2370Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2380Sstevel@tonic-gate 	}
2390Sstevel@tonic-gate 
2400Sstevel@tonic-gate 	new_object->tried_create_clone = calloc(num_slots, sizeof (boolean_t));
2410Sstevel@tonic-gate 	if (new_object->tried_create_clone == NULL) {
2420Sstevel@tonic-gate 		free(new_object->clones);
2430Sstevel@tonic-gate 		free(new_object);
2440Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
2450Sstevel@tonic-gate 	}
2460Sstevel@tonic-gate 
2470Sstevel@tonic-gate 	/* Initialize the object fields. */
2480Sstevel@tonic-gate 	new_object->magic_marker = METASLOT_OBJECT_MAGIC;
2490Sstevel@tonic-gate 	(void) pthread_rwlock_init(&new_object->object_lock, NULL);
2500Sstevel@tonic-gate 	(void) pthread_rwlock_init(&new_object->attribute_lock, NULL);
2510Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_object->clone_create_lock, NULL);
2520Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_object->isClosingObject_lock, NULL);
2530Sstevel@tonic-gate 	new_object->creator_session = session;
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	*object = new_object;
2560Sstevel@tonic-gate 
2570Sstevel@tonic-gate 	return (CKR_OK);
2580Sstevel@tonic-gate }
2590Sstevel@tonic-gate 
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate /*
2620Sstevel@tonic-gate  * meta_object_get_attr
2630Sstevel@tonic-gate  *
2640Sstevel@tonic-gate  * Get attribute values to fill in attribute values
2650Sstevel@tonic-gate  * being kept in the metaslot object.  The following 4 attributes
2660Sstevel@tonic-gate  * in the meta_object_t structure will be filled in:
2670Sstevel@tonic-gate  * isToken, isPrivate, isSensitive, isExtractable
2680Sstevel@tonic-gate  *
2690Sstevel@tonic-gate  * It's basically an easy way to do a C_GetAttributeValue.
2700Sstevel@tonic-gate  * So, the hSession argument is assumed
2710Sstevel@tonic-gate  * to be valid, and the pointer to meta_object_t is also assumed
2720Sstevel@tonic-gate  * to be valid.
2730Sstevel@tonic-gate  */
2740Sstevel@tonic-gate CK_RV
meta_object_get_attr(slot_session_t * slot_session,CK_OBJECT_HANDLE hObject,meta_object_t * object)2750Sstevel@tonic-gate meta_object_get_attr(slot_session_t *slot_session, CK_OBJECT_HANDLE hObject,
2760Sstevel@tonic-gate     meta_object_t *object)
2770Sstevel@tonic-gate {
2784219Smcpowers 	CK_BBOOL is_sensitive = object->isSensitive;
2794219Smcpowers 	CK_BBOOL is_extractable = object->isExtractable;
2804219Smcpowers 	CK_BBOOL is_token = B_FALSE, is_private = B_FALSE;
2814219Smcpowers 	CK_KEY_TYPE keytype;
2820Sstevel@tonic-gate 	CK_OBJECT_CLASS class;
2830Sstevel@tonic-gate 	CK_ATTRIBUTE attrs[3];
2840Sstevel@tonic-gate 	CK_RV rv;
2850Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession = slot_session->hSession;
2860Sstevel@tonic-gate 	CK_SLOT_ID fw_st_id = slot_session->fw_st_id;
2874219Smcpowers 	int count = 1;
2880Sstevel@tonic-gate 
2890Sstevel@tonic-gate 	attrs[0].type = CKA_CLASS;
2900Sstevel@tonic-gate 	attrs[0].pValue = &class;
2910Sstevel@tonic-gate 	attrs[0].ulValueLen = sizeof (class);
2920Sstevel@tonic-gate 
2934219Smcpowers 	if (object->isFreeObject != FREE_ENABLED) {
2944219Smcpowers 		attrs[1].type = CKA_TOKEN;
2954219Smcpowers 		attrs[1].pValue = &is_token;
2964219Smcpowers 		attrs[1].ulValueLen = sizeof (is_token);
2974219Smcpowers 		count++;
2984219Smcpowers 	}
2990Sstevel@tonic-gate 
3004219Smcpowers 	/*
3014219Smcpowers 	 * If this is a freeobject, we already know the Private value
3024219Smcpowers 	 * and we don't want to overwrite it with the wrong value
3034219Smcpowers 	 */
3044219Smcpowers 	if (object->isFreeObject <= FREE_DISABLED) {
3054219Smcpowers 		attrs[count].type = CKA_PRIVATE;
3064219Smcpowers 		attrs[count].pValue = &is_private;
3074219Smcpowers 		attrs[count].ulValueLen = sizeof (is_private);
3084219Smcpowers 		count++;
3094219Smcpowers 	} else
3104219Smcpowers 		is_private = object->isPrivate;
3110Sstevel@tonic-gate 
3120Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
3134219Smcpowers 	    attrs, count);
3140Sstevel@tonic-gate 	if (rv != CKR_OK) {
3150Sstevel@tonic-gate 		return (rv);
3160Sstevel@tonic-gate 	}
3170Sstevel@tonic-gate 
3184219Smcpowers 	count = 0;
3194219Smcpowers 	switch (class) {
3204219Smcpowers 	case CKO_PRIVATE_KEY:
3214219Smcpowers 	case CKO_SECRET_KEY:
3224219Smcpowers 		/* Only need to check these for private & secret keys */
3234219Smcpowers 		attrs[0].type = CKA_EXTRACTABLE;
3244219Smcpowers 		attrs[0].pValue = &is_extractable;
3254219Smcpowers 		attrs[0].ulValueLen = sizeof (is_extractable);
3264219Smcpowers 		count = 1;
3270Sstevel@tonic-gate 
3280Sstevel@tonic-gate 		/*
3294219Smcpowers 		 * If this is a freeobject, we already know the Sensitive
3304219Smcpowers 		 * value and we don't want to overwrite it with the wrong
3314219Smcpowers 		 * value.
3320Sstevel@tonic-gate 		 */
3334219Smcpowers 
3344219Smcpowers 		if (object->isFreeObject <= FREE_DISABLED) {
3354219Smcpowers 			attrs[1].type = CKA_SENSITIVE;
3364219Smcpowers 			attrs[1].pValue = &is_sensitive;
3374219Smcpowers 			attrs[1].ulValueLen = sizeof (is_sensitive);
3384219Smcpowers 			count = 2;
3394219Smcpowers 
3404219Smcpowers 			/*
3414219Smcpowers 			 * We only need the key type if this is the first
3424219Smcpowers 			 * time we've looked at the object
3434219Smcpowers 			 */
3444219Smcpowers 			if (object->isFreeObject == FREE_UNCHECKED) {
3454219Smcpowers 				attrs[2].type = CKA_KEY_TYPE;
3464219Smcpowers 				attrs[2].pValue = &keytype;
3474219Smcpowers 				attrs[2].ulValueLen = sizeof (keytype);
3484219Smcpowers 				count = 3;
3494219Smcpowers 			}
3504219Smcpowers 		}
3514219Smcpowers 
3524219Smcpowers 		break;
3530Sstevel@tonic-gate 
3544219Smcpowers 	case CKO_PUBLIC_KEY:
3554219Smcpowers 		if (object->isFreeObject == FREE_UNCHECKED) {
3564219Smcpowers 			attrs[count].type = CKA_KEY_TYPE;
3574219Smcpowers 			attrs[count].pValue = &keytype;
3584219Smcpowers 			attrs[count].ulValueLen = sizeof (keytype);
3594219Smcpowers 			count++;
3604219Smcpowers 		}
3614219Smcpowers 		is_sensitive = CK_FALSE;
3624219Smcpowers 		is_extractable = CK_TRUE;
3634219Smcpowers 		break;
3640Sstevel@tonic-gate 
3654219Smcpowers 	default:
3664219Smcpowers 		object->isFreeObject = FREE_DISABLED;
3674219Smcpowers 		is_sensitive = CK_FALSE;
3684219Smcpowers 		is_extractable = CK_TRUE;
3694219Smcpowers 	};
3704219Smcpowers 
3714219Smcpowers 	if (count > 0) {
3724219Smcpowers 		rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
3734219Smcpowers 		    attrs, count);
3740Sstevel@tonic-gate 		if (rv != CKR_OK) {
3750Sstevel@tonic-gate 			return (rv);
3760Sstevel@tonic-gate 		}
3774219Smcpowers 
3784219Smcpowers 		if (object->isFreeObject == FREE_UNCHECKED) {
3794219Smcpowers 			if (keytype == CKK_EC || keytype == CKK_RSA ||
3804219Smcpowers 			    keytype == CKK_DH) {
3814219Smcpowers 				if (metaslot_config.auto_key_migrate) {
3824219Smcpowers 					object->isFreeObject = FREE_DISABLED;
3834219Smcpowers 					object->isFreeToken = FREE_DISABLED;
3844219Smcpowers 				}
3854219Smcpowers 
3864219Smcpowers 				object->isFreeObject = FREE_ENABLED;
3874219Smcpowers 				if (is_token)
3884219Smcpowers 					object->isFreeToken = FREE_ENABLED;
3894219Smcpowers 			} else
3904219Smcpowers 				object->isFreeObject = FREE_DISABLED;
3914219Smcpowers 
3924219Smcpowers 		}
3934219Smcpowers 
3940Sstevel@tonic-gate 	}
3950Sstevel@tonic-gate 
3960Sstevel@tonic-gate 	object->isToken = is_token;
3970Sstevel@tonic-gate 	object->isPrivate = is_private;
3980Sstevel@tonic-gate 	object->isSensitive = is_sensitive;
3990Sstevel@tonic-gate 	object->isExtractable = is_extractable;
4000Sstevel@tonic-gate 
4010Sstevel@tonic-gate 	return (CKR_OK);
4020Sstevel@tonic-gate }
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate 
4050Sstevel@tonic-gate /*
4060Sstevel@tonic-gate  * meta_object_activate
4070Sstevel@tonic-gate  *
4080Sstevel@tonic-gate  * Add a new metaobject to the list of objects. See also meta_object_create,
4090Sstevel@tonic-gate  * which would be called to create an object before it is added.
4100Sstevel@tonic-gate  */
4110Sstevel@tonic-gate void
meta_object_activate(meta_object_t * new_object)4120Sstevel@tonic-gate meta_object_activate(meta_object_t *new_object)
4130Sstevel@tonic-gate {
4140Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
4150Sstevel@tonic-gate 	meta_object_t **list_head;
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 	/*
4180Sstevel@tonic-gate 	 * For session objects, we keep the list in the session that created
4190Sstevel@tonic-gate 	 * this object, because this object will be destroyed when that session
4200Sstevel@tonic-gate 	 * is closed.
4210Sstevel@tonic-gate 	 *
4220Sstevel@tonic-gate 	 * For token objects, the list is global (ie, not associated with any
4230Sstevel@tonic-gate 	 * particular session).
4240Sstevel@tonic-gate 	 */
4250Sstevel@tonic-gate 	if (new_object->isToken) {
4260Sstevel@tonic-gate 		list_lock = &tokenobject_list_lock;
4270Sstevel@tonic-gate 		list_head = &tokenobject_list_head;
4280Sstevel@tonic-gate 	} else {
4290Sstevel@tonic-gate 		list_lock = &new_object->creator_session->object_list_lock;
4300Sstevel@tonic-gate 		list_head = &new_object->creator_session->object_list_head;
4310Sstevel@tonic-gate 	}
4320Sstevel@tonic-gate 
4330Sstevel@tonic-gate 	/* Add object to the list of objects. */
4340Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(list_lock);
4350Sstevel@tonic-gate 	INSERT_INTO_LIST(*list_head, new_object);
4360Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(list_lock);
4370Sstevel@tonic-gate }
4380Sstevel@tonic-gate 
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate /*
4410Sstevel@tonic-gate  * meta_object_deactivate
4420Sstevel@tonic-gate  *
4430Sstevel@tonic-gate  * Removes the object from the list of valid meta objects.  Note
4440Sstevel@tonic-gate  * that this function does not clean up any allocated
4450Sstevel@tonic-gate  * resources (memory, object clones, etc).   Cleaning up of
4468732SAnthony.Scarpino@Sun.COM  * allocated resources is done by calling the meta_object_dealloc()
4470Sstevel@tonic-gate  *
4480Sstevel@tonic-gate  */
4490Sstevel@tonic-gate CK_RV
meta_object_deactivate(meta_object_t * object,boolean_t have_list_lock,boolean_t have_object_lock)4500Sstevel@tonic-gate meta_object_deactivate(meta_object_t *object, boolean_t have_list_lock,
4510Sstevel@tonic-gate     boolean_t have_object_lock)
4520Sstevel@tonic-gate {
4530Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
4540Sstevel@tonic-gate 	meta_object_t **list_head;
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	if (!have_object_lock) {
4570Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&object->object_lock);
4580Sstevel@tonic-gate 	}
4590Sstevel@tonic-gate 
4600Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object->isClosingObject_lock);
4610Sstevel@tonic-gate 	if (object->isClosingObject) {
4620Sstevel@tonic-gate 		/* Lost a delete race. */
4630Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object->isClosingObject_lock);
4640Sstevel@tonic-gate 		OBJRELEASE(object);
4650Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
4660Sstevel@tonic-gate 	}
4670Sstevel@tonic-gate 	object->isClosingObject = B_TRUE;
4680Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object->isClosingObject_lock);
4690Sstevel@tonic-gate 
4708732SAnthony.Scarpino@Sun.COM 	if (object->isToken || (object->isFreeToken == FREE_ENABLED)) {
4710Sstevel@tonic-gate 		list_lock = &tokenobject_list_lock;
4720Sstevel@tonic-gate 		list_head = &tokenobject_list_head;
4730Sstevel@tonic-gate 	} else {
4740Sstevel@tonic-gate 		list_lock = &object->creator_session->object_list_lock;
4750Sstevel@tonic-gate 		list_head = &object->creator_session->object_list_head;
4760Sstevel@tonic-gate 	}
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	/*
4790Sstevel@tonic-gate 	 * Remove object from the object list. Once removed, it will not
4800Sstevel@tonic-gate 	 * be possible for another thread to begin using the object.
4810Sstevel@tonic-gate 	 */
4820Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&meta_objectclose_lock);
4830Sstevel@tonic-gate 	if (!have_list_lock) {
4840Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(list_lock);
4850Sstevel@tonic-gate 	}
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate 
4880Sstevel@tonic-gate 	object->magic_marker = METASLOT_OBJECT_BADMAGIC;
4890Sstevel@tonic-gate 	/*
4900Sstevel@tonic-gate 	 * Can't use the regular REMOVE_FROM_LIST() function because
4910Sstevel@tonic-gate 	 * that will miss the "error cleanup" situation where object is not yet
4920Sstevel@tonic-gate 	 * in the list (object->next == NULL && object->prev == NULL)
4930Sstevel@tonic-gate 	 */
4940Sstevel@tonic-gate 	if (*list_head == object) {
4950Sstevel@tonic-gate 		/* Object is the first one in the list */
4960Sstevel@tonic-gate 		if (object->next) {
4970Sstevel@tonic-gate 			*list_head = object->next;
4980Sstevel@tonic-gate 			object->next->prev = NULL;
4990Sstevel@tonic-gate 		} else {
5000Sstevel@tonic-gate 			/* Object is the only one in the list */
5010Sstevel@tonic-gate 			*list_head = NULL;
5020Sstevel@tonic-gate 		}
5030Sstevel@tonic-gate 	} else if (object->next != NULL || object->prev != NULL) {
5040Sstevel@tonic-gate 		if (object->next) {
5050Sstevel@tonic-gate 			object->prev->next = object->next;
5060Sstevel@tonic-gate 			object->next->prev = object->prev;
5070Sstevel@tonic-gate 		} else {
5080Sstevel@tonic-gate 			/* Object is the last one in the list */
5090Sstevel@tonic-gate 			object->prev->next = NULL;
5100Sstevel@tonic-gate 		}
5110Sstevel@tonic-gate 	}
5120Sstevel@tonic-gate 
5130Sstevel@tonic-gate 	if (!have_list_lock) {
5140Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(list_lock);
5150Sstevel@tonic-gate 	}
5160Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&meta_objectclose_lock);
5170Sstevel@tonic-gate 
5180Sstevel@tonic-gate 	/*
5190Sstevel@tonic-gate 	 * Wait for anyone already using object to finish, by obtaining
5200Sstevel@tonic-gate 	 * a writer-lock (need to release our reader-lock first). Once we
5210Sstevel@tonic-gate 	 * get the write lock, we can just release it and finish cleaning
5220Sstevel@tonic-gate 	 * up the object.
5230Sstevel@tonic-gate 	 */
5240Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->object_lock); /* rdlock */
5250Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&object->object_lock);
5260Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->object_lock); /* wrlock */
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 
5290Sstevel@tonic-gate 	return (CKR_OK);
5300Sstevel@tonic-gate }
5310Sstevel@tonic-gate 
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate /*
5340Sstevel@tonic-gate  * meta_object_dealloc
5350Sstevel@tonic-gate  *
5360Sstevel@tonic-gate  * Performs final object cleanup, releasing any allocated memory and
5370Sstevel@tonic-gate  * destroying any clones on other slots. Caller is assumed to have
5380Sstevel@tonic-gate  * called meta_object_deactivate() before this function.
5390Sstevel@tonic-gate  *
5400Sstevel@tonic-gate  * Caller is assumed to have only reference to object, but should have
5410Sstevel@tonic-gate  * released any lock.
5420Sstevel@tonic-gate  *
5430Sstevel@tonic-gate  * If "nukeSourceObj" argument is true, we will actually delete the
5440Sstevel@tonic-gate  * object from the underlying slot.
5450Sstevel@tonic-gate  */
5460Sstevel@tonic-gate CK_RV
meta_object_dealloc(meta_session_t * session,meta_object_t * object,boolean_t nukeSourceObj)5478732SAnthony.Scarpino@Sun.COM meta_object_dealloc(meta_session_t *session, meta_object_t *object,
5488732SAnthony.Scarpino@Sun.COM     boolean_t nukeSourceObj)
5490Sstevel@tonic-gate {
5500Sstevel@tonic-gate 	CK_RV rv, save_rv = CKR_OK;
5510Sstevel@tonic-gate 	CK_ULONG slotnum, num_slots;
5520Sstevel@tonic-gate 	CK_ULONG i;
5530Sstevel@tonic-gate 
5540Sstevel@tonic-gate 	/* First, delete all the clones of this object on other slots. */
5550Sstevel@tonic-gate 	num_slots = meta_slotManager_get_slotcount();
5560Sstevel@tonic-gate 	for (slotnum = 0; slotnum < num_slots; slotnum++) {
5570Sstevel@tonic-gate 		slot_session_t *obj_session;
5580Sstevel@tonic-gate 		slot_object_t *clone;
5590Sstevel@tonic-gate 
5600Sstevel@tonic-gate 		clone = object->clones[slotnum];
5610Sstevel@tonic-gate 		if (clone == NULL)
5620Sstevel@tonic-gate 			continue;
5634219Smcpowers 		if (nukeSourceObj || (!object->isToken &&
5644338Sdinak 		    !(object->isFreeToken == FREE_ENABLED &&
5654338Sdinak 		    get_keystore_slotnum() == slotnum))) {
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 			rv = meta_get_slot_session(slotnum, &obj_session,
5688732SAnthony.Scarpino@Sun.COM 			    (session == NULL) ?
5698732SAnthony.Scarpino@Sun.COM 			    object->creator_session->session_flags :
5708732SAnthony.Scarpino@Sun.COM 			    session->session_flags);
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 			if (rv == CKR_OK) {
5730Sstevel@tonic-gate 				rv = FUNCLIST(obj_session->fw_st_id)->\
5740Sstevel@tonic-gate 				    C_DestroyObject(obj_session->hSession,
5750Sstevel@tonic-gate 				    clone->hObject);
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 				meta_release_slot_session(obj_session);
5780Sstevel@tonic-gate 				if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
5790Sstevel@tonic-gate 					save_rv = rv;
5800Sstevel@tonic-gate 				}
5810Sstevel@tonic-gate 			}
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate 		}
5840Sstevel@tonic-gate 
5850Sstevel@tonic-gate 		meta_slot_object_deactivate(clone);
5860Sstevel@tonic-gate 		meta_slot_object_dealloc(clone);
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 		object->clones[slotnum] = NULL;
5890Sstevel@tonic-gate 	}
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 	/* Now erase and delete any attributes in the metaobject. */
5920Sstevel@tonic-gate 	dealloc_attributes(object->attributes, object->num_attributes);
5930Sstevel@tonic-gate 
5940Sstevel@tonic-gate 	free(object->clones);
5950Sstevel@tonic-gate 	free(object->tried_create_clone);
5960Sstevel@tonic-gate 
5970Sstevel@tonic-gate 	if (object->clone_template) {
5980Sstevel@tonic-gate 		for (i = 0; i < object->clone_template_size; i++) {
5990Sstevel@tonic-gate 			free(((object->clone_template)[i]).pValue);
6000Sstevel@tonic-gate 		}
6010Sstevel@tonic-gate 		free(object->clone_template);
6020Sstevel@tonic-gate 	}
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 	/* Cleanup remaining object fields. */
6050Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&object->object_lock);
6060Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&object->attribute_lock);
6070Sstevel@tonic-gate 	(void) pthread_mutex_destroy(&object->isClosingObject_lock);
6080Sstevel@tonic-gate 	(void) pthread_mutex_destroy(&object->clone_create_lock);
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 	meta_object_delay_free(object);
6110Sstevel@tonic-gate 
6120Sstevel@tonic-gate 	return (save_rv);
6130Sstevel@tonic-gate }
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate /*
6170Sstevel@tonic-gate  * meta_slot_object_alloc
6180Sstevel@tonic-gate  */
6190Sstevel@tonic-gate CK_RV
meta_slot_object_alloc(slot_object_t ** object)6200Sstevel@tonic-gate meta_slot_object_alloc(slot_object_t **object) {
6210Sstevel@tonic-gate 	slot_object_t *new_object;
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 	new_object = calloc(1, sizeof (slot_object_t));
6240Sstevel@tonic-gate 	if (new_object == NULL)
6250Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
6260Sstevel@tonic-gate 
6270Sstevel@tonic-gate 	*object = new_object;
6280Sstevel@tonic-gate 	return (CKR_OK);
6290Sstevel@tonic-gate }
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate /*
6330Sstevel@tonic-gate  * meta_slot_object_activate
6340Sstevel@tonic-gate  */
6350Sstevel@tonic-gate void
meta_slot_object_activate(slot_object_t * object,slot_session_t * creator_session,boolean_t isToken)6360Sstevel@tonic-gate meta_slot_object_activate(slot_object_t *object,
6370Sstevel@tonic-gate 	slot_session_t *creator_session, boolean_t isToken)
6380Sstevel@tonic-gate {
6390Sstevel@tonic-gate 	object->creator_session = creator_session;
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 	if (isToken) {
6420Sstevel@tonic-gate 		extern slot_data_t *slots;
6430Sstevel@tonic-gate 		slot_data_t *slot;
6440Sstevel@tonic-gate 
6450Sstevel@tonic-gate 		slot = &(slots[object->creator_session->slotnum]);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(&slot->tokenobject_list_lock);
6480Sstevel@tonic-gate 		INSERT_INTO_LIST(slot->tokenobject_list_head, object);
6490Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&slot->tokenobject_list_lock);
6500Sstevel@tonic-gate 	} else {
6510Sstevel@tonic-gate 		slot_session_t *session = object->creator_session;
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 		/* Add to session's list of session objects. */
6540Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(&session->object_list_lock);
6550Sstevel@tonic-gate 		INSERT_INTO_LIST(session->object_list_head, object);
6560Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&session->object_list_lock);
6570Sstevel@tonic-gate 	}
6584219Smcpowers 
6594219Smcpowers 	/*
6604219Smcpowers 	 * This set tells the slot object that we are in the token list,
6614219Smcpowers 	 * but does not cause harm with the metaobject knowing the object
6624219Smcpowers 	 * isn't a token, but a freetoken
6634219Smcpowers 	 */
6644219Smcpowers 
6650Sstevel@tonic-gate 	object->isToken = isToken;
6660Sstevel@tonic-gate }
6670Sstevel@tonic-gate 
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate /*
6700Sstevel@tonic-gate  * meta_slot_object_deactivate
6710Sstevel@tonic-gate  *
6720Sstevel@tonic-gate  * Remove the specified slot object from the appropriate object list.
6730Sstevel@tonic-gate  */
6740Sstevel@tonic-gate void
meta_slot_object_deactivate(slot_object_t * object)6750Sstevel@tonic-gate meta_slot_object_deactivate(slot_object_t *object)
6760Sstevel@tonic-gate {
6770Sstevel@tonic-gate 	slot_object_t **list_head;
6780Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
6790Sstevel@tonic-gate 
6800Sstevel@tonic-gate 	if (object->isToken) {
6810Sstevel@tonic-gate 		extern slot_data_t *slots;
6820Sstevel@tonic-gate 		slot_data_t *slot;
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 		slot = &(slots[object->creator_session->slotnum]);
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 		list_head = &slot->tokenobject_list_head;
6870Sstevel@tonic-gate 		list_lock = &slot->tokenobject_list_lock;
6880Sstevel@tonic-gate 	} else {
6890Sstevel@tonic-gate 		list_head = &object->creator_session->object_list_head;
6900Sstevel@tonic-gate 		list_lock = &object->creator_session->object_list_lock;
6910Sstevel@tonic-gate 	}
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(list_lock);
6940Sstevel@tonic-gate 	REMOVE_FROM_LIST(*list_head, object);
6950Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(list_lock);
6960Sstevel@tonic-gate }
6970Sstevel@tonic-gate 
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate /*
7000Sstevel@tonic-gate  * meta_slot_object_dealloc
7010Sstevel@tonic-gate  */
7020Sstevel@tonic-gate void
meta_slot_object_dealloc(slot_object_t * object)7030Sstevel@tonic-gate meta_slot_object_dealloc(slot_object_t *object)
7040Sstevel@tonic-gate {
7050Sstevel@tonic-gate 	/* Not much cleanup for slot objects, unlike meta objects... */
7060Sstevel@tonic-gate 	free(object);
7070Sstevel@tonic-gate }
7080Sstevel@tonic-gate 
7090Sstevel@tonic-gate 
7100Sstevel@tonic-gate /*
7110Sstevel@tonic-gate  * meta_object_copyin
7120Sstevel@tonic-gate  *
7130Sstevel@tonic-gate  * When a key is generated/derived/unwrapped, the attribute values
7140Sstevel@tonic-gate  * created by the token are not immediately read into our copy of the
7150Sstevel@tonic-gate  * attributes. We defer this work until we actually need to know.
7160Sstevel@tonic-gate  */
7170Sstevel@tonic-gate CK_RV
meta_object_copyin(meta_object_t * object)7180Sstevel@tonic-gate meta_object_copyin(meta_object_t *object)
7190Sstevel@tonic-gate {
7200Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
7210Sstevel@tonic-gate 	slot_session_t *session = NULL;
7220Sstevel@tonic-gate 	CK_ATTRIBUTE *attrs = NULL, *attrs_with_val = NULL;
7230Sstevel@tonic-gate 	slot_object_t *slot_object = NULL;
7240Sstevel@tonic-gate 	CK_ULONG num_attrs = 0, i, num_attrs_with_val;
7250Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession;
7260Sstevel@tonic-gate 	CK_SLOT_ID fw_st_id;
7270Sstevel@tonic-gate 
7280Sstevel@tonic-gate 	/* Make sure no one else is looking at attributes. */
7290Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&object->attribute_lock);
7300Sstevel@tonic-gate 
7310Sstevel@tonic-gate 	/* Did we just lose a copyin race with another thread */
7320Sstevel@tonic-gate 	if (object->attributes != NULL) {
7330Sstevel@tonic-gate 		goto finish;
7340Sstevel@tonic-gate 	}
7350Sstevel@tonic-gate 
7360Sstevel@tonic-gate 	slot_object = object->clones[object->master_clone_slotnum];
7370Sstevel@tonic-gate 
7380Sstevel@tonic-gate 	rv = meta_get_slot_session(object->master_clone_slotnum, &session,
7390Sstevel@tonic-gate 	    object->creator_session->session_flags);
7400Sstevel@tonic-gate 	if (rv != CKR_OK) {
7410Sstevel@tonic-gate 		goto finish;
7420Sstevel@tonic-gate 	}
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 	/*
7450Sstevel@tonic-gate 	 * first, get the master template of all the attributes
7460Sstevel@tonic-gate 	 * for this object
7470Sstevel@tonic-gate 	 */
7480Sstevel@tonic-gate 	rv = get_master_attributes_by_object(session, slot_object,
7490Sstevel@tonic-gate 	    &(object->attributes), &(object->num_attributes));
7500Sstevel@tonic-gate 	if (rv != CKR_OK) {
7510Sstevel@tonic-gate 		goto finish;
7520Sstevel@tonic-gate 	}
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 	/*
7550Sstevel@tonic-gate 	 * Get value for each attribute items.
7560Sstevel@tonic-gate 	 *
7570Sstevel@tonic-gate 	 * Some attributes are required by the given object type.
7580Sstevel@tonic-gate 	 * Some are optional.  Get all the values first, and then
7590Sstevel@tonic-gate 	 * make sure we have value for all required values,
7600Sstevel@tonic-gate 	 */
7610Sstevel@tonic-gate 	attrs = calloc(object->num_attributes, sizeof (CK_ATTRIBUTE));
7620Sstevel@tonic-gate 	if (attrs == NULL) {
7630Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
7640Sstevel@tonic-gate 		goto finish;
7650Sstevel@tonic-gate 	}
7660Sstevel@tonic-gate 
7670Sstevel@tonic-gate 
7680Sstevel@tonic-gate 	for (i = 0; i < object->num_attributes; i++) {
7690Sstevel@tonic-gate 		attrs[i].type =
7700Sstevel@tonic-gate 		    ((object->attributes[i]).attribute).type;
7710Sstevel@tonic-gate 	}
7720Sstevel@tonic-gate 	num_attrs = object->num_attributes;
7730Sstevel@tonic-gate 
7740Sstevel@tonic-gate 	hSession = session->hSession;
7750Sstevel@tonic-gate 	fw_st_id = session->fw_st_id;
7760Sstevel@tonic-gate 
7770Sstevel@tonic-gate 	/* first, call C_GetAttributeValue() to get size for each attribute */
7780Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
7790Sstevel@tonic-gate 	    slot_object->hObject, attrs, num_attrs);
7800Sstevel@tonic-gate 	/*
7810Sstevel@tonic-gate 	 * If the return value is not CKR_OK, allow it to be
7820Sstevel@tonic-gate 	 * CKR_ATTRIBUTE_TYPE_INVALID for now.
7830Sstevel@tonic-gate 	 * Some attributes defined in PKCS#11 version 2.11
7840Sstevel@tonic-gate 	 * might not be defined in earlier versions.  We will
7850Sstevel@tonic-gate 	 * TRY to work with those providers if the attribute
7860Sstevel@tonic-gate 	 * is optional.
7870Sstevel@tonic-gate 	 */
7880Sstevel@tonic-gate 	if ((rv != CKR_OK) && (rv != CKR_ATTRIBUTE_TYPE_INVALID)) {
7890Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED; /* make sure rv is appropriate */
7900Sstevel@tonic-gate 		goto finish;
7910Sstevel@tonic-gate 	}
7920Sstevel@tonic-gate 
7930Sstevel@tonic-gate 	/*
7940Sstevel@tonic-gate 	 * allocate space.
7950Sstevel@tonic-gate 	 * Since we don't know how many attributes have
7960Sstevel@tonic-gate 	 * values at this time, just assume all of them
7970Sstevel@tonic-gate 	 * have values so we save one loop to count the number
7980Sstevel@tonic-gate 	 * of attributes that have value.
7990Sstevel@tonic-gate 	 */
8000Sstevel@tonic-gate 	attrs_with_val = calloc(num_attrs, sizeof (CK_ATTRIBUTE));
8010Sstevel@tonic-gate 	if (attrs_with_val == NULL) {
8020Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
8030Sstevel@tonic-gate 		goto finish;
8040Sstevel@tonic-gate 	}
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 
8070Sstevel@tonic-gate 	num_attrs_with_val = 0;
8080Sstevel@tonic-gate 	for (i = 0; i < num_attrs; i++) {
8090Sstevel@tonic-gate 		if (!(((CK_LONG)(attrs[i].ulValueLen)) > 0)) {
8100Sstevel@tonic-gate 			/* if it isn't an optional attr, len should be > 0 */
8110Sstevel@tonic-gate 			if (!object->attributes[i].canBeEmptyValue) {
8120Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
8130Sstevel@tonic-gate 				goto finish;
8140Sstevel@tonic-gate 			}
8150Sstevel@tonic-gate 		} else {
8160Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].type = attrs[i].type;
8170Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].ulValueLen =
8180Sstevel@tonic-gate 			    attrs[i].ulValueLen;
8190Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].pValue =
8200Sstevel@tonic-gate 			    malloc(attrs[i].ulValueLen);
8210Sstevel@tonic-gate 			if (attrs_with_val[num_attrs_with_val].pValue == NULL) {
8220Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
8230Sstevel@tonic-gate 				goto finish;
8240Sstevel@tonic-gate 			}
8250Sstevel@tonic-gate 			num_attrs_with_val++;
8260Sstevel@tonic-gate 		}
8270Sstevel@tonic-gate 	}
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
8300Sstevel@tonic-gate 	    slot_object->hObject, attrs_with_val, num_attrs_with_val);
8310Sstevel@tonic-gate 	if (rv != CKR_OK) {
8320Sstevel@tonic-gate 		goto finish;
8330Sstevel@tonic-gate 	}
8340Sstevel@tonic-gate 
8350Sstevel@tonic-gate 	/* store these values into the meta object */
8360Sstevel@tonic-gate 	for (i = 0; i < num_attrs_with_val; i++) {
8370Sstevel@tonic-gate 		rv = attribute_set_value(&(attrs_with_val[i]),
8380Sstevel@tonic-gate 		    object->attributes, object->num_attributes);
8390Sstevel@tonic-gate 		if (rv != CKR_OK) {
8400Sstevel@tonic-gate 			goto finish;
8410Sstevel@tonic-gate 		}
8420Sstevel@tonic-gate 	}
8430Sstevel@tonic-gate 
8440Sstevel@tonic-gate finish:
8450Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->attribute_lock);
8460Sstevel@tonic-gate 
8470Sstevel@tonic-gate 	if (session)
8480Sstevel@tonic-gate 		meta_release_slot_session(session);
8490Sstevel@tonic-gate 
8500Sstevel@tonic-gate 	if (attrs) {
8510Sstevel@tonic-gate 		for (i = 0; i < num_attrs; i++) {
8520Sstevel@tonic-gate 			if (attrs[i].pValue != NULL) {
8530Sstevel@tonic-gate 				free(attrs[i].pValue);
8540Sstevel@tonic-gate 			}
8550Sstevel@tonic-gate 		}
8560Sstevel@tonic-gate 		free(attrs);
8570Sstevel@tonic-gate 	}
8580Sstevel@tonic-gate 
8590Sstevel@tonic-gate 	if (attrs_with_val) {
8600Sstevel@tonic-gate 		for (i = 0; i < num_attrs; i++) {
8610Sstevel@tonic-gate 			if (attrs_with_val[i].pValue != NULL) {
8620Sstevel@tonic-gate 				free(attrs_with_val[i].pValue);
8630Sstevel@tonic-gate 			}
8640Sstevel@tonic-gate 		}
8650Sstevel@tonic-gate 		free(attrs_with_val);
8660Sstevel@tonic-gate 	}
8670Sstevel@tonic-gate 	return (rv);
8680Sstevel@tonic-gate }
8690Sstevel@tonic-gate 
8700Sstevel@tonic-gate /*
8710Sstevel@tonic-gate  * Create an object to be used for wrapping and unwrapping.
8720Sstevel@tonic-gate  * The same template will be used for all wrapping/unwrapping keys all
8730Sstevel@tonic-gate  * the time
8740Sstevel@tonic-gate  */
8750Sstevel@tonic-gate 
8760Sstevel@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)8770Sstevel@tonic-gate create_wrap_unwrap_key(slot_session_t *slot_session, CK_OBJECT_HANDLE *hObject,
8780Sstevel@tonic-gate     wrap_info_t *wrap_info, char *key_data, CK_ULONG key_len)
8790Sstevel@tonic-gate {
8800Sstevel@tonic-gate 
8810Sstevel@tonic-gate 	CK_OBJECT_CLASS objclass;
8820Sstevel@tonic-gate 	CK_KEY_TYPE keytype;
8830Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
8840Sstevel@tonic-gate 	int i;
8850Sstevel@tonic-gate 	CK_ATTRIBUTE template[WRAP_KEY_TEMPLATE_SIZE];
8860Sstevel@tonic-gate 
8870Sstevel@tonic-gate 	i = 0;
8880Sstevel@tonic-gate 	objclass = wrap_info->class;
8890Sstevel@tonic-gate 	template[i].type = CKA_CLASS;
8900Sstevel@tonic-gate 	template[i].pValue = &objclass;
8910Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (objclass);
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 	i++;
8940Sstevel@tonic-gate 	keytype = wrap_info->key_type;
8950Sstevel@tonic-gate 	template[i].type = CKA_KEY_TYPE;
8960Sstevel@tonic-gate 	template[i].pValue = &keytype;
8970Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (keytype);
8980Sstevel@tonic-gate 
8990Sstevel@tonic-gate 	i++;
9000Sstevel@tonic-gate 	template[i].type = CKA_TOKEN;
9010Sstevel@tonic-gate 	template[i].pValue = &falsevalue;
9020Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (falsevalue);
9030Sstevel@tonic-gate 
9040Sstevel@tonic-gate 
9050Sstevel@tonic-gate 	if (objclass == CKO_SECRET_KEY) {
9060Sstevel@tonic-gate 		i++;
9070Sstevel@tonic-gate 		template[i].type = CKA_VALUE;
9080Sstevel@tonic-gate 		template[i].pValue = key_data;
9090Sstevel@tonic-gate 		template[i].ulValueLen = key_len;
9100Sstevel@tonic-gate 
9110Sstevel@tonic-gate 		i++;
9120Sstevel@tonic-gate 		template[i].type = CKA_WRAP;
9130Sstevel@tonic-gate 		template[i].pValue = &truevalue;
9140Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (truevalue);
9150Sstevel@tonic-gate 
9160Sstevel@tonic-gate 		i++;
9170Sstevel@tonic-gate 		template[i].type = CKA_UNWRAP;
9180Sstevel@tonic-gate 		template[i].pValue = &truevalue;
9190Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (truevalue);
9200Sstevel@tonic-gate 	} else {
9210Sstevel@tonic-gate 		/* Modulus is the same for rsa public and private key */
9220Sstevel@tonic-gate 		i++;
9230Sstevel@tonic-gate 		template[i].type = CKA_MODULUS;
9240Sstevel@tonic-gate 		template[i].pValue = Modulus;
9250Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (Modulus);
9260Sstevel@tonic-gate 
9270Sstevel@tonic-gate 		if (objclass == CKO_PUBLIC_KEY) {
9280Sstevel@tonic-gate 			/* RSA public key */
9290Sstevel@tonic-gate 			i++;
9300Sstevel@tonic-gate 			template[i].type = CKA_PUBLIC_EXPONENT;
9310Sstevel@tonic-gate 			template[i].pValue = PubExpo;
9320Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (PubExpo);
9330Sstevel@tonic-gate 
9340Sstevel@tonic-gate 			i++;
9350Sstevel@tonic-gate 			template[i].type = CKA_WRAP;
9360Sstevel@tonic-gate 			template[i].pValue = &truevalue;
9370Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (truevalue);
9380Sstevel@tonic-gate 		} else {
9390Sstevel@tonic-gate 			/* RSA private key */
9400Sstevel@tonic-gate 			i++;
9410Sstevel@tonic-gate 			template[i].type = CKA_PRIVATE_EXPONENT;
9420Sstevel@tonic-gate 			template[i].pValue = PriExpo;
9430Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (PriExpo);
9440Sstevel@tonic-gate 
9450Sstevel@tonic-gate 			i++;
9460Sstevel@tonic-gate 			template[i].type = CKA_UNWRAP;
9470Sstevel@tonic-gate 			template[i].pValue = &truevalue;
9480Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (truevalue);
9490Sstevel@tonic-gate 		}
9500Sstevel@tonic-gate 	}
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject(
9530Sstevel@tonic-gate 	    slot_session->hSession, template, i + 1, hObject);
9540Sstevel@tonic-gate 
9550Sstevel@tonic-gate 	return (rv);
9560Sstevel@tonic-gate }
9570Sstevel@tonic-gate 
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate /*
9600Sstevel@tonic-gate  * Create a clone of a non-sensitive and extractable object.
9610Sstevel@tonic-gate  * If the template required for creating the clone doesn't exist,
9620Sstevel@tonic-gate  * it will be retrieved from the master clone.
9630Sstevel@tonic-gate  */
9640Sstevel@tonic-gate static CK_RV
clone_by_create(meta_object_t * object,slot_object_t * new_clone,slot_session_t * dst_slot_session)9650Sstevel@tonic-gate clone_by_create(meta_object_t *object, slot_object_t *new_clone,
9660Sstevel@tonic-gate     slot_session_t *dst_slot_session)
9670Sstevel@tonic-gate {
9680Sstevel@tonic-gate 	CK_RV rv;
9694219Smcpowers 	int free_token_index = -1;
9700Sstevel@tonic-gate 
9710Sstevel@tonic-gate 	if (object->attributes == NULL) {
9720Sstevel@tonic-gate 		rv = meta_object_copyin(object);
9730Sstevel@tonic-gate 		if (rv != CKR_OK) {
9740Sstevel@tonic-gate 			return (rv);
9750Sstevel@tonic-gate 		}
9760Sstevel@tonic-gate 	}
9770Sstevel@tonic-gate 
9780Sstevel@tonic-gate 	if (object->clone_template == NULL) {
9790Sstevel@tonic-gate 		rv = meta_clone_template_setup(object, object->attributes,
9800Sstevel@tonic-gate 		    object->num_attributes);
9810Sstevel@tonic-gate 		if (rv != CKR_OK) {
9820Sstevel@tonic-gate 			return (rv);
9830Sstevel@tonic-gate 		}
9840Sstevel@tonic-gate 	}
9850Sstevel@tonic-gate 
9864219Smcpowers 	if (object->isFreeToken == FREE_ENABLED) {
9874219Smcpowers 		if (dst_slot_session->slotnum == get_keystore_slotnum())
9884219Smcpowers 			free_token_index = set_template_boolean(CKA_TOKEN,
9894219Smcpowers 			    object->clone_template,
9904219Smcpowers 			    object->clone_template_size, B_FALSE, &truevalue);
9914219Smcpowers 		else
9924219Smcpowers 			free_token_index = set_template_boolean(CKA_TOKEN,
9934219Smcpowers 			    object->clone_template,
9944219Smcpowers 			    object->clone_template_size, B_FALSE, &falsevalue);
9954219Smcpowers 	}
9964219Smcpowers 
9970Sstevel@tonic-gate 	/* Create the clone... */
9980Sstevel@tonic-gate 	rv = FUNCLIST(dst_slot_session->fw_st_id)->C_CreateObject(
9990Sstevel@tonic-gate 	    dst_slot_session->hSession, object->clone_template,
10000Sstevel@tonic-gate 	    object->clone_template_size, &(new_clone->hObject));
10014219Smcpowers 
10024219Smcpowers 	if (free_token_index != -1) {
10034338Sdinak 			free_token_index = set_template_boolean(CKA_TOKEN,
10044338Sdinak 			    object->clone_template, object->clone_template_size,
10054338Sdinak 			    B_FALSE, &falsevalue);
10064219Smcpowers 	}
10074219Smcpowers 
10080Sstevel@tonic-gate 	if (rv != CKR_OK) {
10090Sstevel@tonic-gate 		return (rv);
10100Sstevel@tonic-gate 	}
10110Sstevel@tonic-gate 
10120Sstevel@tonic-gate 	return (CKR_OK);
10130Sstevel@tonic-gate }
10140Sstevel@tonic-gate 
10150Sstevel@tonic-gate /*
10160Sstevel@tonic-gate  * Goes through the list of wraping mechanisms, and returns the first
10170Sstevel@tonic-gate  * one that is supported by both the source and the destination slot.
10180Sstevel@tonic-gate  * If none of the mechanisms are supported by both slot, return the
10190Sstevel@tonic-gate  * first mechanism that's supported by the source slot
10200Sstevel@tonic-gate  */
10210Sstevel@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)10220Sstevel@tonic-gate find_best_match_wrap_mech(wrap_info_t *wrap_info, int num_info,
10230Sstevel@tonic-gate 	CK_ULONG src_slotnum, CK_ULONG dst_slotnum, int *first_both_mech,
10240Sstevel@tonic-gate 	int *first_src_mech)
10250Sstevel@tonic-gate {
10260Sstevel@tonic-gate 
10270Sstevel@tonic-gate 	int i;
10280Sstevel@tonic-gate 	boolean_t src_supports, dst_supports;
10290Sstevel@tonic-gate 	CK_RV rv;
10304338Sdinak 	CK_MECHANISM_INFO mech_info;
10314338Sdinak 
10324338Sdinak 	mech_info.flags = CKF_WRAP;
10330Sstevel@tonic-gate 
10340Sstevel@tonic-gate 	for (i = 0; i < num_info; i++) {
10350Sstevel@tonic-gate 		src_supports = B_FALSE;
10360Sstevel@tonic-gate 		dst_supports = B_FALSE;
10370Sstevel@tonic-gate 
10380Sstevel@tonic-gate 		rv = meta_mechManager_slot_supports_mech(
10390Sstevel@tonic-gate 		    (wrap_info[i]).mech_type, src_slotnum,
10404338Sdinak 		    &src_supports, NULL, B_FALSE, &mech_info);
10410Sstevel@tonic-gate 		if (rv != CKR_OK) {
10420Sstevel@tonic-gate 			return (rv);
10430Sstevel@tonic-gate 		}
10440Sstevel@tonic-gate 
10450Sstevel@tonic-gate 		rv = meta_mechManager_slot_supports_mech(
10460Sstevel@tonic-gate 		    (wrap_info[i]).mech_type, dst_slotnum,
10474338Sdinak 		    &dst_supports, NULL, B_FALSE, &mech_info);
10480Sstevel@tonic-gate 		if (rv != CKR_OK) {
10490Sstevel@tonic-gate 			return (rv);
10500Sstevel@tonic-gate 		}
10510Sstevel@tonic-gate 
10520Sstevel@tonic-gate 		/* both source and destination supports the mech */
10530Sstevel@tonic-gate 		if ((src_supports) && (dst_supports)) {
10540Sstevel@tonic-gate 			*first_both_mech = i;
10550Sstevel@tonic-gate 			return (CKR_OK);
10560Sstevel@tonic-gate 		}
10570Sstevel@tonic-gate 
10580Sstevel@tonic-gate 		if ((src_supports) && (*first_src_mech == -1)) {
10590Sstevel@tonic-gate 			*first_src_mech = i;
10600Sstevel@tonic-gate 		}
10610Sstevel@tonic-gate 	}
10620Sstevel@tonic-gate 	return (CKR_OK);
10630Sstevel@tonic-gate }
10640Sstevel@tonic-gate 
10650Sstevel@tonic-gate /*
10660Sstevel@tonic-gate  * Determine the wrapping/unwrapping mechanism to be used
10670Sstevel@tonic-gate  *
10680Sstevel@tonic-gate  * If possible, select a mechanism that's supported by both source
10690Sstevel@tonic-gate  * and destination slot.  If none of the mechanisms are supported
10700Sstevel@tonic-gate  * by both slot, then, select the first one supported by
10710Sstevel@tonic-gate  * the source slot.
10720Sstevel@tonic-gate  */
10730Sstevel@tonic-gate 
10740Sstevel@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)10750Sstevel@tonic-gate get_wrap_mechanism(CK_OBJECT_CLASS obj_class, CK_KEY_TYPE key_type,
10760Sstevel@tonic-gate     CK_ULONG src_slotnum, CK_ULONG dst_slotnum, wrap_info_t *wrap_info)
10770Sstevel@tonic-gate {
10780Sstevel@tonic-gate 	wrap_info_t *wrap_info_to_search = NULL;
10790Sstevel@tonic-gate 	unsigned int num_wrap_info;
10800Sstevel@tonic-gate 	CK_RV rv;
10810Sstevel@tonic-gate 	int i;
10820Sstevel@tonic-gate 	boolean_t src_supports = B_FALSE, dst_supports = B_FALSE;
10830Sstevel@tonic-gate 	int first_src_mech, rsa_first_src_mech, first_both_mech;
10844338Sdinak 	CK_MECHANISM_INFO mech_info;
10854338Sdinak 
10864338Sdinak 	mech_info.flags = CKF_WRAP;
10870Sstevel@tonic-gate 
10880Sstevel@tonic-gate 	if ((obj_class == CKO_PRIVATE_KEY) && (key_type == CKK_KEA)) {
10890Sstevel@tonic-gate 		/*
10900Sstevel@tonic-gate 		 * only SKIPJACK keys can be used for wrapping
10910Sstevel@tonic-gate 		 * KEA private keys
10920Sstevel@tonic-gate 		 */
10930Sstevel@tonic-gate 
10940Sstevel@tonic-gate 		for (i = 0; i < num_special_wrap_info; i++) {
10950Sstevel@tonic-gate 			if ((special_wrap_info[i]).mech_type
10960Sstevel@tonic-gate 			    != CKM_SKIPJACK_WRAP) {
10970Sstevel@tonic-gate 				continue;
10980Sstevel@tonic-gate 			}
10990Sstevel@tonic-gate 
11000Sstevel@tonic-gate 			src_supports = B_FALSE;
11010Sstevel@tonic-gate 			dst_supports = B_FALSE;
11020Sstevel@tonic-gate 
11030Sstevel@tonic-gate 			rv = meta_mechManager_slot_supports_mech(
11040Sstevel@tonic-gate 			    (special_wrap_info[i]).mech_type, src_slotnum,
11054338Sdinak 			    &src_supports, NULL, B_FALSE, &mech_info);
11060Sstevel@tonic-gate 			if (rv != CKR_OK) {
11070Sstevel@tonic-gate 				goto finish;
11080Sstevel@tonic-gate 			}
11090Sstevel@tonic-gate 
11100Sstevel@tonic-gate 			rv = meta_mechManager_slot_supports_mech(
11110Sstevel@tonic-gate 			    (special_wrap_info[i]).mech_type, dst_slotnum,
11124338Sdinak 			    &dst_supports, NULL, B_FALSE, &mech_info);
11130Sstevel@tonic-gate 			if (rv != CKR_OK) {
11140Sstevel@tonic-gate 				goto finish;
11150Sstevel@tonic-gate 			}
11160Sstevel@tonic-gate 
11170Sstevel@tonic-gate 			if (src_supports) {
11180Sstevel@tonic-gate 				/*
11190Sstevel@tonic-gate 				 * both src and dst supports the mech or
11200Sstevel@tonic-gate 				 * only the src supports the mech
11210Sstevel@tonic-gate 				 */
11220Sstevel@tonic-gate 				(void) memcpy(wrap_info,
11230Sstevel@tonic-gate 				    &(special_wrap_info[i]),
11240Sstevel@tonic-gate 				    sizeof (wrap_info_t));
11250Sstevel@tonic-gate 
11260Sstevel@tonic-gate 				wrap_info->src_supports = src_supports;
11270Sstevel@tonic-gate 				wrap_info->dst_supports = dst_supports;
11280Sstevel@tonic-gate 				rv = CKR_OK;
11290Sstevel@tonic-gate 				goto finish;
11300Sstevel@tonic-gate 			}
11310Sstevel@tonic-gate 
11320Sstevel@tonic-gate 		}
11330Sstevel@tonic-gate 
11340Sstevel@tonic-gate 		/*
11350Sstevel@tonic-gate 		 * if we are here, that means neither the source slot
1136*12558Sdan.opensolaris.anderson@drydog.com 		 * nor the destination slots supports CKM_SKIPJACK_WRAP.
11370Sstevel@tonic-gate 		 */
11380Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
11390Sstevel@tonic-gate 		goto finish;
11400Sstevel@tonic-gate 	}
11410Sstevel@tonic-gate 
11420Sstevel@tonic-gate 	if ((key_type == CKK_SKIPJACK) || (key_type == CKK_BATON) ||
11430Sstevel@tonic-gate 	    (key_type == CKK_JUNIPER)) {
11440Sstevel@tonic-gate 		/* special key types */
11450Sstevel@tonic-gate 		wrap_info_to_search = special_wrap_info;
11460Sstevel@tonic-gate 		num_wrap_info = num_special_wrap_info;
11470Sstevel@tonic-gate 	} else {
11480Sstevel@tonic-gate 		/* use the regular wrapping mechanisms */
11490Sstevel@tonic-gate 		wrap_info_to_search = common_wrap_info;
11500Sstevel@tonic-gate 		num_wrap_info = num_common_wrap_info;
11510Sstevel@tonic-gate 	}
11520Sstevel@tonic-gate 
11530Sstevel@tonic-gate 	first_both_mech = -1;
11540Sstevel@tonic-gate 	first_src_mech = -1;
11550Sstevel@tonic-gate 
11560Sstevel@tonic-gate 	rv = find_best_match_wrap_mech(wrap_info_to_search, num_wrap_info,
11570Sstevel@tonic-gate 	    src_slotnum, dst_slotnum, &first_both_mech, &first_src_mech);
11580Sstevel@tonic-gate 	if (rv != CKR_OK) {
11590Sstevel@tonic-gate 		goto finish;
11600Sstevel@tonic-gate 	}
11610Sstevel@tonic-gate 
11620Sstevel@tonic-gate 	if (first_both_mech != -1) {
11630Sstevel@tonic-gate 		(void) memcpy(wrap_info,
11640Sstevel@tonic-gate 		    &(wrap_info_to_search[first_both_mech]),
11650Sstevel@tonic-gate 		    sizeof (wrap_info_t));
11660Sstevel@tonic-gate 
11670Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
11680Sstevel@tonic-gate 		wrap_info->dst_supports = B_TRUE;
11690Sstevel@tonic-gate 		rv = CKR_OK;
11700Sstevel@tonic-gate 		goto finish;
11710Sstevel@tonic-gate 	}
11720Sstevel@tonic-gate 
11730Sstevel@tonic-gate 	/*
11740Sstevel@tonic-gate 	 * If we are here, we did not find a mechanism that's supported
11750Sstevel@tonic-gate 	 * by both source and destination slot.
11760Sstevel@tonic-gate 	 *
11770Sstevel@tonic-gate 	 * If it is a secret key, can also try to wrap it with
11780Sstevel@tonic-gate 	 * a RSA public key
11790Sstevel@tonic-gate 	 */
11800Sstevel@tonic-gate 	if (obj_class == CKO_SECRET_KEY) {
11810Sstevel@tonic-gate 		first_both_mech = -1;
11820Sstevel@tonic-gate 		rsa_first_src_mech = -1;
11830Sstevel@tonic-gate 
11840Sstevel@tonic-gate 		rv = find_best_match_wrap_mech(rsa_wrap_info,
11850Sstevel@tonic-gate 		    num_rsa_wrap_info, src_slotnum, dst_slotnum,
11860Sstevel@tonic-gate 		    &first_both_mech, &rsa_first_src_mech);
11870Sstevel@tonic-gate 
11880Sstevel@tonic-gate 		if (rv != CKR_OK) {
11890Sstevel@tonic-gate 			goto finish;
11900Sstevel@tonic-gate 		}
11910Sstevel@tonic-gate 
11920Sstevel@tonic-gate 		if (first_both_mech > -1) {
11930Sstevel@tonic-gate 			(void) memcpy(wrap_info,
11940Sstevel@tonic-gate 			    &(rsa_wrap_info[first_both_mech]),
11950Sstevel@tonic-gate 			    sizeof (wrap_info_t));
11960Sstevel@tonic-gate 
11970Sstevel@tonic-gate 			wrap_info->src_supports = B_TRUE;
11980Sstevel@tonic-gate 			wrap_info->dst_supports = B_TRUE;
11990Sstevel@tonic-gate 			rv = CKR_OK;
12000Sstevel@tonic-gate 			goto finish;
12010Sstevel@tonic-gate 		}
12020Sstevel@tonic-gate 	}
12030Sstevel@tonic-gate 
12040Sstevel@tonic-gate 	/*
12050Sstevel@tonic-gate 	 * if we are here, that means none of the mechanisms are supported
12060Sstevel@tonic-gate 	 * by both the source and the destination
12070Sstevel@tonic-gate 	 */
12080Sstevel@tonic-gate 	if (first_src_mech > -1) {
12090Sstevel@tonic-gate 		/* source slot support one of the secret key mechs */
12100Sstevel@tonic-gate 		(void) memcpy(wrap_info,
12110Sstevel@tonic-gate 		    &(wrap_info_to_search[first_src_mech]),
12120Sstevel@tonic-gate 		    sizeof (wrap_info_t));
12130Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
12140Sstevel@tonic-gate 		wrap_info->dst_supports = B_FALSE;
12150Sstevel@tonic-gate 		rv = CKR_OK;
12160Sstevel@tonic-gate 	} else if (rsa_first_src_mech > -1) {
12170Sstevel@tonic-gate 		/* source slot support one of the RSA mechs */
12180Sstevel@tonic-gate 		(void) memcpy(wrap_info, &(rsa_wrap_info[rsa_first_src_mech]),
12190Sstevel@tonic-gate 		    sizeof (wrap_info_t));
12200Sstevel@tonic-gate 
12210Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
12220Sstevel@tonic-gate 		wrap_info->dst_supports = B_FALSE;
12230Sstevel@tonic-gate 		rv = CKR_OK;
12240Sstevel@tonic-gate 	} else {
12250Sstevel@tonic-gate 		/* neither source nor destination support any wrap mechs */
12260Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
12270Sstevel@tonic-gate 	}
12280Sstevel@tonic-gate 
12290Sstevel@tonic-gate finish:
12300Sstevel@tonic-gate 	return (rv);
12310Sstevel@tonic-gate }
12320Sstevel@tonic-gate 
12330Sstevel@tonic-gate 
12340Sstevel@tonic-gate /*
12350Sstevel@tonic-gate  * This is called if the object to be cloned is a sensitive object
12360Sstevel@tonic-gate  */
12370Sstevel@tonic-gate static CK_RV
clone_by_wrap(meta_object_t * object,slot_object_t * new_clone,slot_session_t * dst_slot_session)12380Sstevel@tonic-gate clone_by_wrap(meta_object_t *object, slot_object_t *new_clone,
12390Sstevel@tonic-gate     slot_session_t *dst_slot_session)
12400Sstevel@tonic-gate {
12410Sstevel@tonic-gate 	slot_session_t *src_slot_session = NULL;
12420Sstevel@tonic-gate 	CK_OBJECT_HANDLE wrappingKey = NULL, unwrappingKey = NULL;
12430Sstevel@tonic-gate 	CK_MECHANISM wrappingMech;
12440Sstevel@tonic-gate 	CK_BYTE *wrappedKey = NULL;
12450Sstevel@tonic-gate 	CK_ULONG wrappedKeyLen = 0;
12460Sstevel@tonic-gate 	slot_object_t *slot_object = NULL;
12470Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
12480Sstevel@tonic-gate 	CK_OBJECT_HANDLE unwrapped_obj;
12490Sstevel@tonic-gate 	meta_object_t *tmp_meta_obj = NULL;
12500Sstevel@tonic-gate 	slot_object_t *tmp_slot_obj = NULL;
12510Sstevel@tonic-gate 	CK_OBJECT_CLASS obj_class;
12520Sstevel@tonic-gate 	CK_KEY_TYPE key_type;
12530Sstevel@tonic-gate 	meta_session_t *tmp_meta_session = NULL;
12540Sstevel@tonic-gate 	CK_ATTRIBUTE unwrap_template[4];
12550Sstevel@tonic-gate 	char key_data[1024]; /* should be big enough for any key size */
12560Sstevel@tonic-gate 	char ivbuf[1024]; /* should be big enough for any mech */
12570Sstevel@tonic-gate 	wrap_info_t wrap_info;
12580Sstevel@tonic-gate 	CK_ULONG key_len, unwrap_template_size;
12590Sstevel@tonic-gate 
12600Sstevel@tonic-gate 	slot_object = object->clones[object->master_clone_slotnum];
12610Sstevel@tonic-gate 
12620Sstevel@tonic-gate 	rv = meta_get_slot_session(object->master_clone_slotnum,
12630Sstevel@tonic-gate 	    &src_slot_session, object->creator_session->session_flags);
12640Sstevel@tonic-gate 	if (rv != CKR_OK) {
12650Sstevel@tonic-gate 		return (rv);
12660Sstevel@tonic-gate 	}
12670Sstevel@tonic-gate 
12680Sstevel@tonic-gate 	/*
12690Sstevel@tonic-gate 	 * get the object class and key type for unwrap template
12700Sstevel@tonic-gate 	 * This information will also be used for determining
12710Sstevel@tonic-gate 	 * which wrap mechanism and which key to use for
12720Sstevel@tonic-gate 	 * doing the wrapping
12730Sstevel@tonic-gate 	 */
12740Sstevel@tonic-gate 	unwrap_template[0].type = CKA_CLASS;
12750Sstevel@tonic-gate 	unwrap_template[0].pValue = &obj_class;
12760Sstevel@tonic-gate 	unwrap_template[0].ulValueLen = sizeof (obj_class);
12770Sstevel@tonic-gate 
12780Sstevel@tonic-gate 	unwrap_template[1].type = CKA_KEY_TYPE;
12790Sstevel@tonic-gate 	unwrap_template[1].pValue = &key_type;
12800Sstevel@tonic-gate 	unwrap_template[1].ulValueLen = sizeof (key_type);
12810Sstevel@tonic-gate 
12820Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_GetAttributeValue(
12830Sstevel@tonic-gate 	    src_slot_session->hSession, slot_object->hObject,
12840Sstevel@tonic-gate 	    unwrap_template, 2);
12850Sstevel@tonic-gate 	if (rv != CKR_OK) {
12860Sstevel@tonic-gate 		goto finish;
12870Sstevel@tonic-gate 	}
12880Sstevel@tonic-gate 
12890Sstevel@tonic-gate 	rv = get_wrap_mechanism(obj_class, key_type, src_slot_session->slotnum,
12900Sstevel@tonic-gate 	    dst_slot_session->slotnum, &wrap_info);
12910Sstevel@tonic-gate 	if (rv != CKR_OK) {
12920Sstevel@tonic-gate 		goto finish;
12930Sstevel@tonic-gate 	}
12940Sstevel@tonic-gate 
12950Sstevel@tonic-gate 	/*
12969127SDina.Nimeh@Sun.COM 	 * read number of bytes required from random device for
12970Sstevel@tonic-gate 	 * creating a secret key for wrapping and unwrapping
12980Sstevel@tonic-gate 	 */
12990Sstevel@tonic-gate 	if (wrap_info.class == CKO_SECRET_KEY) {
13000Sstevel@tonic-gate 
13010Sstevel@tonic-gate 		/*
13020Sstevel@tonic-gate 		 * /dev/urandom will be used for generating the key used
13030Sstevel@tonic-gate 		 * for doing the wrap/unwrap.  It's should be ok to
13040Sstevel@tonic-gate 		 * use /dev/urandom because this key is used for this
13050Sstevel@tonic-gate 		 * one time operation only.  It doesn't need to be stored.
13060Sstevel@tonic-gate 		 */
13070Sstevel@tonic-gate 		key_len = wrap_info.key_length;
13089127SDina.Nimeh@Sun.COM 		if (pkcs11_get_urandom(key_data, key_len) < 0) {
13090Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
13100Sstevel@tonic-gate 			goto finish;
13110Sstevel@tonic-gate 		}
13120Sstevel@tonic-gate 
13130Sstevel@tonic-gate 		if (wrap_info.iv_length > 0) {
13149127SDina.Nimeh@Sun.COM 			if (pkcs11_get_urandom(
13159127SDina.Nimeh@Sun.COM 			    ivbuf, wrap_info.iv_length) < 0) {
13160Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
13170Sstevel@tonic-gate 				goto finish;
13180Sstevel@tonic-gate 			}
13190Sstevel@tonic-gate 		}
13200Sstevel@tonic-gate 	}
13210Sstevel@tonic-gate 
13220Sstevel@tonic-gate 	/* create the wrapping key */
13230Sstevel@tonic-gate 	rv = create_wrap_unwrap_key(src_slot_session, &wrappingKey,
13240Sstevel@tonic-gate 	    &wrap_info, key_data, key_len);
13250Sstevel@tonic-gate 	if (rv != CKR_OK) {
13260Sstevel@tonic-gate 		goto finish;
13270Sstevel@tonic-gate 	}
13280Sstevel@tonic-gate 
13290Sstevel@tonic-gate 	wrappingMech.mechanism = wrap_info.mech_type;
13300Sstevel@tonic-gate 	wrappingMech.pParameter = ((wrap_info.iv_length > 0) ? ivbuf : NULL);
13310Sstevel@tonic-gate 	wrappingMech.ulParameterLen = wrap_info.iv_length;
13320Sstevel@tonic-gate 
13330Sstevel@tonic-gate 	/* get the size of the wrapped key */
13340Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
13350Sstevel@tonic-gate 	    src_slot_session->hSession, &wrappingMech,
13360Sstevel@tonic-gate 	    wrappingKey, slot_object->hObject, NULL, &wrappedKeyLen);
13370Sstevel@tonic-gate 
13380Sstevel@tonic-gate 	if (rv != CKR_OK) {
13390Sstevel@tonic-gate 		goto finish;
13400Sstevel@tonic-gate 	}
13410Sstevel@tonic-gate 
13420Sstevel@tonic-gate 	wrappedKey = malloc(wrappedKeyLen * sizeof (CK_BYTE));
13430Sstevel@tonic-gate 	if (wrappedKey == NULL) {
13440Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
13450Sstevel@tonic-gate 		goto finish;
13460Sstevel@tonic-gate 	}
13470Sstevel@tonic-gate 
13480Sstevel@tonic-gate 	/* do the actual key wrapping */
13490Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
13500Sstevel@tonic-gate 	    src_slot_session->hSession, &wrappingMech,
13510Sstevel@tonic-gate 	    wrappingKey, slot_object->hObject, wrappedKey, &wrappedKeyLen);
13520Sstevel@tonic-gate 
13530Sstevel@tonic-gate 	if (rv != CKR_OK) {
13540Sstevel@tonic-gate 		goto finish;
13550Sstevel@tonic-gate 	}
13560Sstevel@tonic-gate 
13570Sstevel@tonic-gate 	/* explicitly force the unwrapped object to be not sensitive */
13580Sstevel@tonic-gate 	unwrap_template[2].type = CKA_SENSITIVE;
13590Sstevel@tonic-gate 	unwrap_template[2].pValue = &falsevalue;
13600Sstevel@tonic-gate 	unwrap_template[2].ulValueLen = sizeof (falsevalue);
13610Sstevel@tonic-gate 
13620Sstevel@tonic-gate 	unwrap_template[3].type = CKA_TOKEN;
13630Sstevel@tonic-gate 	unwrap_template[3].pValue = &falsevalue;
13640Sstevel@tonic-gate 	unwrap_template[3].ulValueLen = sizeof (falsevalue);
13650Sstevel@tonic-gate 
13660Sstevel@tonic-gate 	unwrap_template_size =
13670Sstevel@tonic-gate 	    sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE);
13680Sstevel@tonic-gate 
13690Sstevel@tonic-gate 	if (!wrap_info.dst_supports) {
13700Sstevel@tonic-gate 		/*
13710Sstevel@tonic-gate 		 * if we know for sure that the destination slot doesn't
13720Sstevel@tonic-gate 		 * support the wrapping mechanism, no point in trying.
13730Sstevel@tonic-gate 		 * go directly to unwrap in source slot, and create key
13740Sstevel@tonic-gate 		 * in destination
13750Sstevel@tonic-gate 		 */
13760Sstevel@tonic-gate 		goto unwrap_in_source;
13770Sstevel@tonic-gate 	}
13780Sstevel@tonic-gate 
13790Sstevel@tonic-gate 	/* create the unwrapping key in destination slot */
13800Sstevel@tonic-gate 	if (wrap_info.key_type == CKK_RSA) {
13810Sstevel@tonic-gate 		/* for RSA key, the unwrapping key need to be private key */
13820Sstevel@tonic-gate 		wrap_info.class = CKO_PRIVATE_KEY;
13830Sstevel@tonic-gate 	}
13840Sstevel@tonic-gate 	rv = create_wrap_unwrap_key(dst_slot_session,
13850Sstevel@tonic-gate 	    &unwrappingKey, &wrap_info, key_data, key_len);
13860Sstevel@tonic-gate 	if (rv != CKR_OK) {
13870Sstevel@tonic-gate 		goto finish;
13880Sstevel@tonic-gate 	}
13890Sstevel@tonic-gate 
13900Sstevel@tonic-gate 	rv = FUNCLIST(dst_slot_session->fw_st_id)->C_UnwrapKey(
13910Sstevel@tonic-gate 	    dst_slot_session->hSession, &wrappingMech,
13920Sstevel@tonic-gate 	    unwrappingKey, wrappedKey, wrappedKeyLen, unwrap_template,
13930Sstevel@tonic-gate 	    unwrap_template_size, &(new_clone->hObject));
13940Sstevel@tonic-gate 
13950Sstevel@tonic-gate 	if (rv != CKR_OK) {
13960Sstevel@tonic-gate unwrap_in_source:
13970Sstevel@tonic-gate 
13980Sstevel@tonic-gate 		/*
13990Sstevel@tonic-gate 		 * There seemed to be a problem with unwrapping in the
14000Sstevel@tonic-gate 		 * destination slot.
14010Sstevel@tonic-gate 		 * Try to do the unwrap in the src slot so it becomes
14020Sstevel@tonic-gate 		 * a non-sensitive object, then, get all the attributes
14030Sstevel@tonic-gate 		 * and create the object in the destination slot
14040Sstevel@tonic-gate 		 */
14050Sstevel@tonic-gate 
14060Sstevel@tonic-gate 
14070Sstevel@tonic-gate 		if (wrap_info.class == CKO_SECRET_KEY) {
14080Sstevel@tonic-gate 			/* unwrap with same key used for wrapping */
14090Sstevel@tonic-gate 			rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
14100Sstevel@tonic-gate 			    src_slot_session->hSession,
14110Sstevel@tonic-gate 			    &wrappingMech, wrappingKey, wrappedKey,
14120Sstevel@tonic-gate 			    wrappedKeyLen, unwrap_template,
14130Sstevel@tonic-gate 			    unwrap_template_size, &(unwrapped_obj));
14140Sstevel@tonic-gate 		} else {
14150Sstevel@tonic-gate 			/*
14160Sstevel@tonic-gate 			 * If the object is wrapping with RSA public key, need
14170Sstevel@tonic-gate 			 * need to create RSA private key for unwrapping
14180Sstevel@tonic-gate 			 */
14190Sstevel@tonic-gate 			wrap_info.class = CKO_PRIVATE_KEY;
14200Sstevel@tonic-gate 			rv = create_wrap_unwrap_key(src_slot_session,
14210Sstevel@tonic-gate 			    &unwrappingKey, &wrap_info, key_data, key_len);
14220Sstevel@tonic-gate 			if (rv != CKR_OK) {
14230Sstevel@tonic-gate 				goto finish;
14240Sstevel@tonic-gate 			}
14250Sstevel@tonic-gate 			rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
14260Sstevel@tonic-gate 			    src_slot_session->hSession,
14270Sstevel@tonic-gate 			    &wrappingMech, unwrappingKey, wrappedKey,
14280Sstevel@tonic-gate 			    wrappedKeyLen, unwrap_template,
14290Sstevel@tonic-gate 			    unwrap_template_size, &(unwrapped_obj));
14300Sstevel@tonic-gate 		}
14310Sstevel@tonic-gate 
14320Sstevel@tonic-gate 
14330Sstevel@tonic-gate 		if (rv != CKR_OK) {
14340Sstevel@tonic-gate 			goto finish;
14350Sstevel@tonic-gate 		}
14360Sstevel@tonic-gate 
14370Sstevel@tonic-gate 		rv = meta_session_alloc(&tmp_meta_session);
14380Sstevel@tonic-gate 		if (rv != CKR_OK) {
14390Sstevel@tonic-gate 			goto finish;
14400Sstevel@tonic-gate 		}
14410Sstevel@tonic-gate 
14420Sstevel@tonic-gate 		tmp_meta_session->session_flags = CKF_SERIAL_SESSION;
14430Sstevel@tonic-gate 
14440Sstevel@tonic-gate 		rv = meta_object_alloc(tmp_meta_session, &tmp_meta_obj);
14450Sstevel@tonic-gate 		if (rv != CKR_OK) {
14460Sstevel@tonic-gate 			goto finish;
14470Sstevel@tonic-gate 		}
14480Sstevel@tonic-gate 
14490Sstevel@tonic-gate 		rv = meta_slot_object_alloc(&tmp_slot_obj);
14500Sstevel@tonic-gate 		if (rv != CKR_OK) {
14510Sstevel@tonic-gate 			goto finish;
14520Sstevel@tonic-gate 		}
14530Sstevel@tonic-gate 
14540Sstevel@tonic-gate 		tmp_meta_obj->master_clone_slotnum = src_slot_session->slotnum;
14550Sstevel@tonic-gate 		tmp_slot_obj->hObject = unwrapped_obj;
14560Sstevel@tonic-gate 		tmp_meta_obj->clones[tmp_meta_obj->master_clone_slotnum]
14570Sstevel@tonic-gate 		    = tmp_slot_obj;
14580Sstevel@tonic-gate 		meta_slot_object_activate(tmp_slot_obj, src_slot_session,
14590Sstevel@tonic-gate 		    B_FALSE);
14600Sstevel@tonic-gate 		tmp_slot_obj = NULL;
14610Sstevel@tonic-gate 
14620Sstevel@tonic-gate 		rv = clone_by_create(tmp_meta_obj, new_clone,
14630Sstevel@tonic-gate 		    dst_slot_session);
14640Sstevel@tonic-gate 		if (rv != CKR_OK) {
14650Sstevel@tonic-gate 			goto finish;
14660Sstevel@tonic-gate 		}
14670Sstevel@tonic-gate 	}
14680Sstevel@tonic-gate 
14690Sstevel@tonic-gate finish:
14700Sstevel@tonic-gate 	if (unwrappingKey) {
14710Sstevel@tonic-gate 		(void) FUNCLIST(dst_slot_session->fw_st_id)->C_DestroyObject(
14720Sstevel@tonic-gate 		    dst_slot_session->hSession, unwrappingKey);
14730Sstevel@tonic-gate 	}
14740Sstevel@tonic-gate 
14750Sstevel@tonic-gate 	if (wrappingKey) {
14760Sstevel@tonic-gate 		(void) FUNCLIST(src_slot_session->fw_st_id)->C_DestroyObject(
14770Sstevel@tonic-gate 		    src_slot_session->hSession, wrappingKey);
14780Sstevel@tonic-gate 	}
14790Sstevel@tonic-gate 
14800Sstevel@tonic-gate 	if (tmp_slot_obj) {
14810Sstevel@tonic-gate 		(void) meta_slot_object_dealloc(tmp_slot_obj);
14820Sstevel@tonic-gate 	}
14830Sstevel@tonic-gate 
14840Sstevel@tonic-gate 	if (tmp_meta_obj) {
14858732SAnthony.Scarpino@Sun.COM 		(void) meta_object_dealloc(tmp_meta_session, tmp_meta_obj,
14868732SAnthony.Scarpino@Sun.COM 		    B_TRUE);
14870Sstevel@tonic-gate 	}
14880Sstevel@tonic-gate 
14890Sstevel@tonic-gate 	if (tmp_meta_session) {
14900Sstevel@tonic-gate 		(void) meta_session_dealloc(tmp_meta_session);
14910Sstevel@tonic-gate 	}
14920Sstevel@tonic-gate 
14930Sstevel@tonic-gate 	if (wrappedKey) {
14940Sstevel@tonic-gate 		free(wrappedKey);
14950Sstevel@tonic-gate 	}
14960Sstevel@tonic-gate 
14970Sstevel@tonic-gate 	if (src_slot_session) {
14980Sstevel@tonic-gate 		meta_release_slot_session(src_slot_session);
14990Sstevel@tonic-gate 	}
15000Sstevel@tonic-gate 
15010Sstevel@tonic-gate 	return (rv);
15020Sstevel@tonic-gate 
15030Sstevel@tonic-gate }
15040Sstevel@tonic-gate 
15050Sstevel@tonic-gate 
15060Sstevel@tonic-gate /*
15070Sstevel@tonic-gate  * meta_object_get_clone
15080Sstevel@tonic-gate  *
15090Sstevel@tonic-gate  * Creates a "clone" of a metaobject on the specified slot. A clone is a
15100Sstevel@tonic-gate  * copy of the object.
15110Sstevel@tonic-gate  *
1512*12558Sdan.opensolaris.anderson@drydog.com  * Clones are cached, so that they can be reused with subsequent operations.
15130Sstevel@tonic-gate  */
15140Sstevel@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)15150Sstevel@tonic-gate meta_object_get_clone(meta_object_t *object,
15160Sstevel@tonic-gate 	CK_ULONG slot_num, slot_session_t *slot_session,
15170Sstevel@tonic-gate 	slot_object_t **clone)
15180Sstevel@tonic-gate {
15190Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
15200Sstevel@tonic-gate 	slot_object_t *newclone = NULL;
15210Sstevel@tonic-gate 
15220Sstevel@tonic-gate 	/* Does a clone already exist? */
15230Sstevel@tonic-gate 	if (object->clones[slot_num] != NULL) {
15240Sstevel@tonic-gate 		*clone = object->clones[slot_num];
15250Sstevel@tonic-gate 		return (CKR_OK);
15260Sstevel@tonic-gate 	}
15270Sstevel@tonic-gate 
15280Sstevel@tonic-gate 	if ((object->isSensitive) && (object->isToken) &&
15290Sstevel@tonic-gate 	    (!metaslot_auto_key_migrate)) {
15300Sstevel@tonic-gate 		/*
15310Sstevel@tonic-gate 		 * if the object is a sensitive token object, and auto
15320Sstevel@tonic-gate 		 * key migrate is not allowed, will not create the clone
15330Sstevel@tonic-gate 		 * in another slot
15340Sstevel@tonic-gate 		 */
15350Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
15360Sstevel@tonic-gate 	}
15370Sstevel@tonic-gate 
15380Sstevel@tonic-gate 	/* object attributes can't be extracted and attributes are not known */
15390Sstevel@tonic-gate 	if ((!object->isExtractable) && (object->attributes == NULL)) {
15400Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
15410Sstevel@tonic-gate 	}
15420Sstevel@tonic-gate 
15435715Skrishna 	(void) pthread_mutex_lock(&object->clone_create_lock);
15445715Skrishna 
15455715Skrishna 	/* Maybe someone just created one? */
15465715Skrishna 	if (object->clones[slot_num] != NULL) {
15475715Skrishna 		*clone = object->clones[slot_num];
15485715Skrishna 		goto finish;
15495715Skrishna 	}
15505715Skrishna 
15510Sstevel@tonic-gate 	/*
15520Sstevel@tonic-gate 	 * has an attempt already been made to create this object in
15530Sstevel@tonic-gate 	 * slot?  If yes, and there's no clone, as indicated above,
15540Sstevel@tonic-gate 	 * that means this object can't be created in this slot.
15550Sstevel@tonic-gate 	 */
15560Sstevel@tonic-gate 	if (object->tried_create_clone[slot_num]) {
15575715Skrishna 		(void) pthread_mutex_unlock(&object->clone_create_lock);
15580Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
15590Sstevel@tonic-gate 	}
15600Sstevel@tonic-gate 
15610Sstevel@tonic-gate 	rv = meta_slot_object_alloc(&newclone);
15620Sstevel@tonic-gate 	if (rv != CKR_OK)
15630Sstevel@tonic-gate 		goto finish;
15640Sstevel@tonic-gate 
15650Sstevel@tonic-gate 	object->tried_create_clone[slot_num] = B_TRUE;
15660Sstevel@tonic-gate 
15674219Smcpowers 	/*
15684219Smcpowers 	 * If this object is sensitive and we do not have not copied in the
15694219Smcpowers 	 * attributes via FreeObject functionality, then we need to wrap it off
15704219Smcpowers 	 * the provider.  If we do have attributes, we can just create the
15714219Smcpowers 	 * clone
15724219Smcpowers 	 */
15734219Smcpowers 
15744219Smcpowers 	if (object->isSensitive && object->attributes == NULL) {
15750Sstevel@tonic-gate 		rv = clone_by_wrap(object, newclone, slot_session);
15760Sstevel@tonic-gate 	} else {
15770Sstevel@tonic-gate 		rv = clone_by_create(object, newclone, slot_session);
15780Sstevel@tonic-gate 	}
15790Sstevel@tonic-gate 
15800Sstevel@tonic-gate 	if (rv != CKR_OK) {
15810Sstevel@tonic-gate 		goto finish;
15820Sstevel@tonic-gate 	}
15830Sstevel@tonic-gate 
15840Sstevel@tonic-gate 	object->clones[slot_num] = newclone;
15850Sstevel@tonic-gate 	meta_slot_object_activate(newclone, slot_session, object->isToken);
15860Sstevel@tonic-gate 
15870Sstevel@tonic-gate 	*clone = newclone;
15880Sstevel@tonic-gate 	newclone = NULL;
15890Sstevel@tonic-gate finish:
15900Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object->clone_create_lock);
15910Sstevel@tonic-gate 
15920Sstevel@tonic-gate 	if (newclone)
15930Sstevel@tonic-gate 		meta_slot_object_dealloc(newclone);
15940Sstevel@tonic-gate 
15950Sstevel@tonic-gate 	return (rv);
15960Sstevel@tonic-gate }
15970Sstevel@tonic-gate 
15980Sstevel@tonic-gate 
15990Sstevel@tonic-gate /*
16000Sstevel@tonic-gate  * meta_setup_clone_template
16010Sstevel@tonic-gate  *
16020Sstevel@tonic-gate  * Create a clone template for the specified object.
16030Sstevel@tonic-gate  */
16040Sstevel@tonic-gate static CK_RV
meta_clone_template_setup(meta_object_t * object,const generic_attr_t * attributes,size_t num_attributes)16050Sstevel@tonic-gate meta_clone_template_setup(meta_object_t *object,
16060Sstevel@tonic-gate     const generic_attr_t *attributes, size_t num_attributes)
16070Sstevel@tonic-gate {
16080Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
16090Sstevel@tonic-gate 	CK_ATTRIBUTE *clone_template;
16100Sstevel@tonic-gate 	size_t i, c = 0;
16110Sstevel@tonic-gate 
16120Sstevel@tonic-gate 	clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE));
16130Sstevel@tonic-gate 	if (clone_template == NULL) {
16140Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
16150Sstevel@tonic-gate 		goto finish;
16160Sstevel@tonic-gate 	}
16170Sstevel@tonic-gate 
16180Sstevel@tonic-gate 	/* Don't allow attributes to change while we look at them. */
16190Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&object->attribute_lock);
16200Sstevel@tonic-gate 
16210Sstevel@tonic-gate 	for (i = 0; i < num_attributes; i++) {
16224219Smcpowers 		if (!attributes[i].isCloneAttr ||
16234219Smcpowers 		    (attributes[i].attribute.type == CKA_TOKEN &&
16244338Sdinak 		    object->isFreeToken == FREE_DISABLED)) {
16250Sstevel@tonic-gate 			continue;
16260Sstevel@tonic-gate 		}
16270Sstevel@tonic-gate 		if ((!(attributes[i].hasValueForClone)) &&
16280Sstevel@tonic-gate 		    (attributes[i].canBeEmptyValue)) {
16290Sstevel@tonic-gate 			continue;
16300Sstevel@tonic-gate 		}
16310Sstevel@tonic-gate 
16320Sstevel@tonic-gate 		clone_template[c].type = attributes[i].attribute.type;
16330Sstevel@tonic-gate 		clone_template[c].ulValueLen =
16344338Sdinak 		    attributes[i].attribute.ulValueLen;
16350Sstevel@tonic-gate 		/* Allocate space to store the attribute value. */
16360Sstevel@tonic-gate 		clone_template[c].pValue = malloc(clone_template[c].ulValueLen);
16370Sstevel@tonic-gate 		if (clone_template[c].pValue == NULL) {
1638*12558Sdan.opensolaris.anderson@drydog.com 			free(clone_template);
16390Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
16400Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(&object->attribute_lock);
16410Sstevel@tonic-gate 			goto finish;
16420Sstevel@tonic-gate 		}
16430Sstevel@tonic-gate 
16440Sstevel@tonic-gate 		(void) memcpy(clone_template[c].pValue,
16450Sstevel@tonic-gate 		    object->attributes[i].attribute.pValue,
16460Sstevel@tonic-gate 		    clone_template[c].ulValueLen);
16470Sstevel@tonic-gate 		c++;
16480Sstevel@tonic-gate 	}
16490Sstevel@tonic-gate 
16500Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->attribute_lock);
16510Sstevel@tonic-gate 
16520Sstevel@tonic-gate 	object->clone_template = clone_template;
16530Sstevel@tonic-gate 	object->clone_template_size = c;
16540Sstevel@tonic-gate 
16550Sstevel@tonic-gate finish:
16560Sstevel@tonic-gate 	return (rv);
16570Sstevel@tonic-gate }
16580Sstevel@tonic-gate 
16590Sstevel@tonic-gate 
16600Sstevel@tonic-gate /*
16610Sstevel@tonic-gate  * meta_object_find_by_handle
16620Sstevel@tonic-gate  *
16630Sstevel@tonic-gate  * Search for an existing metaobject, using the object handle of a clone
16640Sstevel@tonic-gate  * on a particular slot.
16650Sstevel@tonic-gate  *
16660Sstevel@tonic-gate  * Returns a matching metaobject, or NULL if no match was found.
16670Sstevel@tonic-gate  */
16680Sstevel@tonic-gate meta_object_t *
meta_object_find_by_handle(CK_OBJECT_HANDLE hObject,CK_ULONG slotnum,boolean_t token_only)16690Sstevel@tonic-gate meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum,
16700Sstevel@tonic-gate     boolean_t token_only)
16710Sstevel@tonic-gate {
16720Sstevel@tonic-gate 	meta_object_t *object = NULL, *tmp_obj;
16730Sstevel@tonic-gate 	meta_session_t *session;
16740Sstevel@tonic-gate 
16750Sstevel@tonic-gate 	if (!token_only) {
16760Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&meta_sessionlist_lock);
16770Sstevel@tonic-gate 		session = meta_sessionlist_head;
16780Sstevel@tonic-gate 		while (session != NULL) {
16790Sstevel@tonic-gate 			/* lock the objects list while we look at it */
16800Sstevel@tonic-gate 			(void) pthread_rwlock_rdlock(
16810Sstevel@tonic-gate 			    &(session->object_list_lock));
16820Sstevel@tonic-gate 			tmp_obj = session->object_list_head;
16830Sstevel@tonic-gate 			while (tmp_obj != NULL) {
16840Sstevel@tonic-gate 				slot_object_t *slot_object;
16850Sstevel@tonic-gate 
16860Sstevel@tonic-gate 				(void) pthread_rwlock_rdlock(
16870Sstevel@tonic-gate 				    &(tmp_obj->object_lock));
16880Sstevel@tonic-gate 				slot_object = tmp_obj->clones[slotnum];
16890Sstevel@tonic-gate 				if (slot_object != NULL) {
16900Sstevel@tonic-gate 					if (slot_object->hObject == hObject) {
16910Sstevel@tonic-gate 						object = tmp_obj;
16920Sstevel@tonic-gate 					}
16930Sstevel@tonic-gate 				}
16940Sstevel@tonic-gate 				(void) pthread_rwlock_unlock(
16950Sstevel@tonic-gate 				    &(tmp_obj->object_lock));
16960Sstevel@tonic-gate 				if (object != NULL) {
16970Sstevel@tonic-gate 					break;
16980Sstevel@tonic-gate 				}
16990Sstevel@tonic-gate 				tmp_obj = tmp_obj->next;
17000Sstevel@tonic-gate 			}
17010Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(
17020Sstevel@tonic-gate 			    &(session->object_list_lock));
17030Sstevel@tonic-gate 			if (object != NULL) {
17040Sstevel@tonic-gate 				break;
17050Sstevel@tonic-gate 			}
17060Sstevel@tonic-gate 			session = session->next;
17070Sstevel@tonic-gate 		}
17080Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&meta_sessionlist_lock);
17090Sstevel@tonic-gate 	}
17100Sstevel@tonic-gate 
17110Sstevel@tonic-gate 	if (object != NULL) {
17120Sstevel@tonic-gate 		/* found the object, no need to look further */
17130Sstevel@tonic-gate 		return (object);
17140Sstevel@tonic-gate 	}
17150Sstevel@tonic-gate 
17160Sstevel@tonic-gate 	/*
17170Sstevel@tonic-gate 	 * Look at list of token objects
17180Sstevel@tonic-gate 	 */
17190Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&tokenobject_list_lock);
17200Sstevel@tonic-gate 	tmp_obj = tokenobject_list_head;
17210Sstevel@tonic-gate 
17220Sstevel@tonic-gate 	while (tmp_obj != NULL) {
17230Sstevel@tonic-gate 		slot_object_t *slot_object;
17240Sstevel@tonic-gate 
17250Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&(tmp_obj->object_lock));
17260Sstevel@tonic-gate 		slot_object = tmp_obj->clones[slotnum];
17270Sstevel@tonic-gate 		if (slot_object != NULL) {
17280Sstevel@tonic-gate 			if (slot_object->hObject == hObject)
17290Sstevel@tonic-gate 				object = tmp_obj;
17300Sstevel@tonic-gate 		}
17310Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&(tmp_obj->object_lock));
17320Sstevel@tonic-gate 		if (object != NULL) {
17330Sstevel@tonic-gate 			break;
17340Sstevel@tonic-gate 		}
17350Sstevel@tonic-gate 		tmp_obj = tmp_obj->next;
17360Sstevel@tonic-gate 	}
17370Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&tokenobject_list_lock);
17380Sstevel@tonic-gate 
17390Sstevel@tonic-gate 	return (object);
17400Sstevel@tonic-gate }
17410Sstevel@tonic-gate 
17420Sstevel@tonic-gate CK_RV
meta_token_object_deactivate(token_obj_type_t token_type)17430Sstevel@tonic-gate meta_token_object_deactivate(token_obj_type_t token_type)
17440Sstevel@tonic-gate {
17450Sstevel@tonic-gate 	meta_object_t *object, *tmp_object;
17460Sstevel@tonic-gate 	CK_RV save_rv = CKR_OK, rv;
17470Sstevel@tonic-gate 
17480Sstevel@tonic-gate 	/* get a write lock on the token object list */
17490Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&tokenobject_list_lock);
17500Sstevel@tonic-gate 
17510Sstevel@tonic-gate 	object = tokenobject_list_head;
17520Sstevel@tonic-gate 
17530Sstevel@tonic-gate 	/* go through each object and delete the one with matching type */
17540Sstevel@tonic-gate 	while (object != NULL) {
17550Sstevel@tonic-gate 		tmp_object = object->next;
17560Sstevel@tonic-gate 
17570Sstevel@tonic-gate 		if ((token_type == ALL_TOKEN) ||
17580Sstevel@tonic-gate 		    ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) ||
17590Sstevel@tonic-gate 		    ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) {
17600Sstevel@tonic-gate 			rv = meta_object_deactivate(object, B_TRUE, B_FALSE);
17610Sstevel@tonic-gate 			if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
17620Sstevel@tonic-gate 				save_rv = rv;
17630Sstevel@tonic-gate 				goto finish;
17640Sstevel@tonic-gate 			}
17658732SAnthony.Scarpino@Sun.COM 			rv = meta_object_dealloc(NULL, object, B_FALSE);
17660Sstevel@tonic-gate 			if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
17670Sstevel@tonic-gate 				save_rv = rv;
17680Sstevel@tonic-gate 				goto finish;
17690Sstevel@tonic-gate 			}
17700Sstevel@tonic-gate 		}
17710Sstevel@tonic-gate 		object = tmp_object;
17720Sstevel@tonic-gate 	}
17730Sstevel@tonic-gate finish:
17740Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&tokenobject_list_lock);
17750Sstevel@tonic-gate 	return (save_rv);
17760Sstevel@tonic-gate }
17770Sstevel@tonic-gate 
17780Sstevel@tonic-gate /*
17790Sstevel@tonic-gate  * This function adds the to-be-freed meta object to a linked list.
17800Sstevel@tonic-gate  * When the number of objects queued in the linked list reaches the
17810Sstevel@tonic-gate  * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
17820Sstevel@tonic-gate  * object (FIFO) in the list.
17830Sstevel@tonic-gate  */
17840Sstevel@tonic-gate void
meta_object_delay_free(meta_object_t * objp)17850Sstevel@tonic-gate meta_object_delay_free(meta_object_t *objp)
17860Sstevel@tonic-gate {
17870Sstevel@tonic-gate 	meta_object_t *tmp;
17880Sstevel@tonic-gate 
17890Sstevel@tonic-gate 	(void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
17900Sstevel@tonic-gate 
17910Sstevel@tonic-gate 	/* Add the newly deleted object at the end of the list */
17920Sstevel@tonic-gate 	objp->next = NULL;
17930Sstevel@tonic-gate 	if (obj_delay_freed.first == NULL) {
17940Sstevel@tonic-gate 		obj_delay_freed.last = objp;
17950Sstevel@tonic-gate 		obj_delay_freed.first = objp;
17960Sstevel@tonic-gate 	} else {
17970Sstevel@tonic-gate 		obj_delay_freed.last->next = objp;
17980Sstevel@tonic-gate 		obj_delay_freed.last = objp;
17990Sstevel@tonic-gate 	}
18000Sstevel@tonic-gate 
18010Sstevel@tonic-gate 	if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
18020Sstevel@tonic-gate 		/*
18030Sstevel@tonic-gate 		 * Free the first object in the list only if
18040Sstevel@tonic-gate 		 * the total count reaches maximum threshold.
18050Sstevel@tonic-gate 		 */
18060Sstevel@tonic-gate 		obj_delay_freed.count--;
18070Sstevel@tonic-gate 		tmp = obj_delay_freed.first->next;
18080Sstevel@tonic-gate 		free(obj_delay_freed.first);
18090Sstevel@tonic-gate 		obj_delay_freed.first = tmp;
18100Sstevel@tonic-gate 	}
18110Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
18120Sstevel@tonic-gate }
18134219Smcpowers 
18144219Smcpowers 
18154219Smcpowers /*
18164219Smcpowers  * This function checks if the object passed can be a freeobject.
18174219Smcpowers  *
18184219Smcpowers  * If there is more than one provider that supports the supported freeobject
18194219Smcpowers  * mechanisms then allow freeobjects to be an option.
18204219Smcpowers  */
18214219Smcpowers 
18224219Smcpowers 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)18234219Smcpowers meta_freeobject_check(meta_session_t *session, meta_object_t *object,
18244219Smcpowers     CK_MECHANISM *pMech, CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len,
18254219Smcpowers     CK_KEY_TYPE keytype)
18264219Smcpowers {
18274219Smcpowers 	mech_support_info_t *info = &(session->mech_support_info);
18284219Smcpowers 
18294219Smcpowers 	/*
18304219Smcpowers 	 * If key migration is turned off, or the object does not has any of
18314219Smcpowers 	 * the required flags and there is only one slot, then we don't need
18324219Smcpowers 	 * FreeObjects.
18334219Smcpowers 	 */
18344219Smcpowers 	if (!metaslot_auto_key_migrate ||
18354219Smcpowers 	    (!object->isToken && !object->isSensitive &&
18364338Sdinak 	    meta_slotManager_get_slotcount() < 2))
18374219Smcpowers 		goto failure;
18384219Smcpowers 
18394219Smcpowers 	/*
18404219Smcpowers 	 * If this call is for key generation, check pMech for supported
18414219Smcpowers 	 * FreeObject mechs
18424219Smcpowers 	 */
18434219Smcpowers 	if (pMech != NULL) {
18444219Smcpowers 		if (pMech->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN ||
18454219Smcpowers 		    pMech->mechanism == CKM_EC_KEY_PAIR_GEN ||
18464219Smcpowers 		    pMech->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN ||
18474219Smcpowers 		    pMech->mechanism == CKM_DH_PKCS_DERIVE)
18484219Smcpowers 			info->mech = pMech->mechanism;
18494219Smcpowers 		else
18504219Smcpowers 			goto failure;
18514219Smcpowers 
18524219Smcpowers 	/*
18534219Smcpowers 	 * If this call is for an object creation, look inside the template
18544219Smcpowers 	 * for supported FreeObject mechs
18554219Smcpowers 	 */
18564219Smcpowers 	} else if (tmpl_len > 0) {
18574338Sdinak 		if (!get_template_ulong(CKA_KEY_TYPE, tmpl, tmpl_len, &keytype))
18584219Smcpowers 			goto failure;
18594219Smcpowers 
18604219Smcpowers 		switch (keytype) {
18614219Smcpowers 		case CKK_RSA:
18624219Smcpowers 			info->mech = CKM_RSA_PKCS_KEY_PAIR_GEN;
18634219Smcpowers 			break;
18644219Smcpowers 		case CKK_EC:
18654219Smcpowers 			info->mech = CKM_EC_KEY_PAIR_GEN;
18664219Smcpowers 			break;
18674219Smcpowers 		case CKK_DH:
18684219Smcpowers 			info->mech = CKM_DH_PKCS_KEY_PAIR_GEN;
18694219Smcpowers 			break;
18704219Smcpowers 		default:
18714219Smcpowers 			goto failure;
18724219Smcpowers 		}
18734219Smcpowers 	} else
18744219Smcpowers 		goto failure;
18754219Smcpowers 
18764219Smcpowers 	/* Get the slot that support this mech... */
18774338Sdinak 	if (meta_mechManager_get_slots(info, B_FALSE, NULL) != CKR_OK)
18784219Smcpowers 		goto failure;
18794219Smcpowers 
18804219Smcpowers 	/*
18814219Smcpowers 	 * If there is only one slot with the mech or the first slot in
18824219Smcpowers 	 * the list is the keystore slot, we should bail.
18834219Smcpowers 	 */
18844219Smcpowers 	if (info->num_supporting_slots < 2 &&
18854219Smcpowers 	    info->supporting_slots[0]->slotnum == get_keystore_slotnum())
18864219Smcpowers 		goto failure;
18874219Smcpowers 
18884219Smcpowers 	if (object->isToken)
18894219Smcpowers 		object->isFreeToken = FREE_ALLOWED_KEY;
18904219Smcpowers 	else
18914219Smcpowers 		object->isFreeToken = FREE_DISABLED;
18924219Smcpowers 
18934219Smcpowers 	object->isFreeObject = FREE_ALLOWED_KEY;
18944219Smcpowers 
18954219Smcpowers 	return (B_TRUE);
18964219Smcpowers 
18974219Smcpowers failure:
18984219Smcpowers 	object->isFreeToken = FREE_DISABLED;
18994219Smcpowers 	object->isFreeObject = FREE_DISABLED;
19004219Smcpowers 	return (B_FALSE);
19014219Smcpowers }
19024219Smcpowers 
19034219Smcpowers /*
19044219Smcpowers  * This function assumes meta_freeobject_check() has just been called and set
19054219Smcpowers  * the isFreeObject and/or isFreeToken vars to FREE_ALLOWED_KEY.
19064219Smcpowers  *
19074219Smcpowers  * If the template value for CKA_PRIVATE, CKA_SENSITIVE and/or CKA_TOKEN are
19084219Smcpowers  * true, then isFreeObject is fully enabled.  In addition isFreeToken is
19094219Smcpowers  * enabled if is CKA_TOKEN true.
19104219Smcpowers  *
19114219Smcpowers  * If create is true, we are doing a C_CreateObject operation and don't
19124219Smcpowers  * handle CKA_PRIVATE & CKA_SENSITIVE flags, we only care about CKA_TOKEN.
19134219Smcpowers  */
19144219Smcpowers 
19154219Smcpowers boolean_t
meta_freeobject_set(meta_object_t * object,CK_ATTRIBUTE * tmpl,CK_ULONG tmpl_len,boolean_t create)19164219Smcpowers meta_freeobject_set(meta_object_t *object, CK_ATTRIBUTE *tmpl,
19174219Smcpowers     CK_ULONG tmpl_len, boolean_t create)
19184219Smcpowers {
19194219Smcpowers 
19204219Smcpowers 	/* This check should never be true, if it is, it's a bug */
19214219Smcpowers 	if (object->isFreeObject < FREE_ALLOWED_KEY)
19224219Smcpowers 		return (B_FALSE);
19234219Smcpowers 
19244219Smcpowers 	if (!create) {
19254219Smcpowers 		/* Turn off the Sensitive flag */
19264219Smcpowers 		if (object->isSensitive) {
19274338Sdinak 			if (set_template_boolean(CKA_SENSITIVE, tmpl, tmpl_len,
19284338Sdinak 			    B_TRUE, &falsevalue) == -1)
19294219Smcpowers 				goto failure;
19304219Smcpowers 
19314219Smcpowers 			object->isFreeObject = FREE_ENABLED;
19324219Smcpowers 		}
19334219Smcpowers 
19344219Smcpowers 		/* Turn off the Private flag */
19354219Smcpowers 		if (object->isPrivate) {
19364338Sdinak 			if (set_template_boolean(CKA_PRIVATE, tmpl, tmpl_len,
19374338Sdinak 			    B_TRUE, &falsevalue) == -1)
19384219Smcpowers 				goto failure;
19394219Smcpowers 
19404219Smcpowers 			object->isFreeObject = FREE_ENABLED;
19414219Smcpowers 		}
19424219Smcpowers 	}
19434219Smcpowers 
19444219Smcpowers 	if (object->isToken) {
19454219Smcpowers 		object->isToken = B_FALSE;
19464219Smcpowers 		object->isFreeToken = FREE_ENABLED;
19474219Smcpowers 		object->isFreeObject = FREE_ENABLED;
19484219Smcpowers 	} else
19494219Smcpowers 		object->isFreeToken = FREE_DISABLED;
19504219Smcpowers 
19514219Smcpowers 	/*
19524219Smcpowers 	 *  If isFreeObject is not in the FREE_ENABLED state yet, it can be
19534219Smcpowers 	 *  turned off because the object doesn't not need to be a FreeObject.
19544219Smcpowers 	 */
19554219Smcpowers 	if (object->isFreeObject == FREE_ALLOWED_KEY)
19564219Smcpowers 		object->isFreeObject = FREE_DISABLED;
19574219Smcpowers 
19584219Smcpowers 	return (B_TRUE);
19594219Smcpowers 
19604219Smcpowers failure:
19614219Smcpowers 	object->isFreeToken = FREE_DISABLED;
19624219Smcpowers 	object->isFreeObject = FREE_DISABLED;
19634219Smcpowers 	return (B_FALSE);
19644219Smcpowers }
19654219Smcpowers 
19664219Smcpowers /*
19674219Smcpowers  * This function sets the CKA_TOKEN flag on a given object template depending
19684219Smcpowers  * if the slot being used is a keystore.
19694219Smcpowers  *
19704219Smcpowers  * If the object is a token, but the slot is not the system keystore or has
19714219Smcpowers  * no keystore, then set the template to token = false; otherwise it's true.
19724219Smcpowers  * In addition we know ahead of time what the value is, so if the value is
19734219Smcpowers  * already correct, bypass the setting function
19744219Smcpowers  */
19754219Smcpowers CK_RV
meta_freetoken_set(CK_ULONG slot_num,CK_BBOOL * current_value,CK_ATTRIBUTE * tmpl,CK_ULONG tmpl_len)19764219Smcpowers meta_freetoken_set(CK_ULONG slot_num, CK_BBOOL *current_value,
19774219Smcpowers     CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len)
19784219Smcpowers {
19794219Smcpowers 
19804219Smcpowers 	if (slot_num == get_keystore_slotnum()) {
19814219Smcpowers 		if (*current_value == TRUE)
19824219Smcpowers 			return (CKR_OK);
19834219Smcpowers 
19844219Smcpowers 		if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
19854338Sdinak 		    &truevalue) == -1)
19864219Smcpowers 			return (CKR_FUNCTION_FAILED);
19874219Smcpowers 
19884219Smcpowers 	} else {
19894219Smcpowers 
19904219Smcpowers 		if (*current_value == FALSE)
19914219Smcpowers 			return (CKR_OK);
19924219Smcpowers 
19934219Smcpowers 		if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
19944338Sdinak 		    &falsevalue) == -1)
19954219Smcpowers 			return (CKR_FUNCTION_FAILED);
19964219Smcpowers 
19974219Smcpowers 		*current_value = FALSE;
19984219Smcpowers 	}
19994219Smcpowers 
20004219Smcpowers 	return (CKR_OK);
20014219Smcpowers }
20024219Smcpowers 
20034219Smcpowers /*
20044219Smcpowers  * Cloning function for meta_freeobject_clone() to use.  This function
20054219Smcpowers  * is streamlined because we know what the object is and this should
20064219Smcpowers  * not be called as a generic cloner.
20074219Smcpowers  */
20084219Smcpowers 
20094219Smcpowers static CK_RV
meta_freeobject_clone_maker(meta_session_t * session,meta_object_t * object,CK_ULONG slotnum)20104219Smcpowers meta_freeobject_clone_maker(meta_session_t *session, meta_object_t *object,
20114219Smcpowers     CK_ULONG slotnum)
20124219Smcpowers {
20134219Smcpowers 
20144219Smcpowers 	slot_object_t *slot_object = NULL;
20154219Smcpowers 	slot_session_t *slot_session = NULL;
20164219Smcpowers 	CK_RV rv;
20174219Smcpowers 
20184219Smcpowers 	rv = meta_slot_object_alloc(&slot_object);
20194219Smcpowers 	if (rv != CKR_OK)
20204219Smcpowers 		goto cleanup;
20214219Smcpowers 
20224219Smcpowers 	rv = meta_get_slot_session(slotnum, &slot_session,
20234219Smcpowers 	    session->session_flags);
20244219Smcpowers 	if (rv != CKR_OK)
20254219Smcpowers 		goto cleanup;
20264219Smcpowers 
20274219Smcpowers 	rv = clone_by_create(object, slot_object, slot_session);
20284219Smcpowers 	if (rv == CKR_OK) {
20294219Smcpowers 		object->clones[slotnum] = slot_object;
20304219Smcpowers 		meta_slot_object_activate(slot_object, slot_session, B_TRUE);
20314219Smcpowers 	}
20324219Smcpowers 
20334219Smcpowers cleanup:
20344219Smcpowers 	meta_release_slot_session(slot_session);
20354219Smcpowers 	return (rv);
20364219Smcpowers 
20374219Smcpowers }
20384219Smcpowers 
20394219Smcpowers /*
20404219Smcpowers  * This function is called when a object is a FreeObject.
20414219Smcpowers  *
20424219Smcpowers  * What we are given is an object that has been generated on a provider
20434219Smcpowers  * that is not its final usage place. That maybe because:
20444219Smcpowers  * 1) it's a token and needs to be stored in keystore.
20454219Smcpowers  * 2) it was to be a private/sensitive object that we modified so we could know
20464219Smcpowers  *    the important attributes for cloning before we make it private/sensitive.
20474219Smcpowers  */
20484219Smcpowers 
20494219Smcpowers boolean_t
meta_freeobject_clone(meta_session_t * session,meta_object_t * object)20504219Smcpowers meta_freeobject_clone(meta_session_t *session, meta_object_t *object)
20514219Smcpowers {
20524219Smcpowers 	CK_RV rv;
20534219Smcpowers 	CK_ULONG keystore_slotnum;
20544219Smcpowers 	CK_ATTRIBUTE attr[2];
20554219Smcpowers 	boolean_t failover = B_FALSE;
20564219Smcpowers 
20574219Smcpowers 	if (object->attributes == NULL) {
20584219Smcpowers 		rv = meta_object_copyin(object);
20594219Smcpowers 		if (rv != CKR_OK)
20604219Smcpowers 			return (rv);
20614219Smcpowers 	}
20624219Smcpowers 
20634219Smcpowers 	if (object->isPrivate) {
20644219Smcpowers 		CK_OBJECT_HANDLE new_clone;
20654219Smcpowers 		CK_ULONG slotnum = object->master_clone_slotnum;
20664219Smcpowers 		slot_session_t *slot_session;
20674219Smcpowers 
20684219Smcpowers 		attr[0].type = CKA_PRIVATE;
20694219Smcpowers 		attr[0].pValue = &truevalue;
20704219Smcpowers 		attr[0].ulValueLen = sizeof (truevalue);
20714219Smcpowers 
20724219Smcpowers 		/* Set the master attribute list */
20734219Smcpowers 		rv = attribute_set_value(attr, object->attributes,
20744219Smcpowers 		    object->num_attributes);
20754219Smcpowers 		if (rv > 0)
20764219Smcpowers 			return (CKR_FUNCTION_FAILED);
20774219Smcpowers 
20784219Smcpowers 		/* Get a slot session */
20794219Smcpowers 		rv = meta_get_slot_session(slotnum, &slot_session,
20804219Smcpowers 		    session->session_flags);
20814219Smcpowers 		if (rv > 0)
20824219Smcpowers 			return (rv);
20834219Smcpowers 
20844219Smcpowers 		/* Create the new CKA_PRIVATE one */
20854219Smcpowers 		rv = FUNCLIST(slot_session->fw_st_id)->\
20864219Smcpowers 		    C_CopyObject(slot_session->hSession,
20874338Sdinak 		    object->clones[slotnum]->hObject, attr, 1, &new_clone);
20884219Smcpowers 
20894219Smcpowers 		if (rv == CKR_USER_NOT_LOGGED_IN) {
20904219Smcpowers 			/*
20914219Smcpowers 			 * If the CopyObject fails, we may be using a provider
20924219Smcpowers 			 * that has a keystore that is not the default
20934219Smcpowers 			 * keystore set in metaslot or has object management
20944219Smcpowers 			 * abilities. In which case we should write this
20954219Smcpowers 			 * object to metaslot's keystore and let the failover.
20964219Smcpowers 			 * rest of the function know we've changed providers.
20974219Smcpowers 			 */
20984219Smcpowers 			failover = B_TRUE;
20994219Smcpowers 			keystore_slotnum = get_keystore_slotnum();
21004219Smcpowers 			if (object->clones[keystore_slotnum] == NULL) {
21014219Smcpowers 				rv = meta_freeobject_clone_maker(session,
21024219Smcpowers 				    object, keystore_slotnum);
21034219Smcpowers 				if (rv != CKR_OK) {
21044219Smcpowers 					goto failure;
21054219Smcpowers 				}
21064219Smcpowers 			}
21074219Smcpowers 			object->master_clone_slotnum = keystore_slotnum;
21084219Smcpowers 
21094219Smcpowers 		} else if (rv != CKR_OK) {
21104219Smcpowers 			meta_release_slot_session(slot_session);
21114219Smcpowers 			goto failure;
21124219Smcpowers 		}
21134219Smcpowers 		/* Remove the old object */
21144219Smcpowers 		rv = FUNCLIST(slot_session->fw_st_id)->	\
21154219Smcpowers 		    C_DestroyObject(slot_session->hSession,
21164338Sdinak 		    object->clones[slotnum]->hObject);
21174219Smcpowers 		if (rv != CKR_OK) {
21184219Smcpowers 			meta_release_slot_session(slot_session);
21194219Smcpowers 			goto failure;
21204219Smcpowers 		}
21214219Smcpowers 
21224219Smcpowers 		if (!failover)
21234219Smcpowers 			object->clones[slotnum]->hObject = new_clone;
21244219Smcpowers 		else
21254219Smcpowers 			object->clones[slotnum] = NULL;
21264219Smcpowers 
21274219Smcpowers 		meta_release_slot_session(slot_session);
21284219Smcpowers 
21294219Smcpowers 	}
21304219Smcpowers 
21314219Smcpowers 	if (object->isSensitive) {
21324219Smcpowers 		slot_session_t *slot_session;
21334219Smcpowers 		CK_ULONG slotnum = object->master_clone_slotnum;
21344219Smcpowers 
21354219Smcpowers 		attr[0].type = CKA_SENSITIVE;
21364219Smcpowers 		attr[0].pValue = &truevalue;
21374219Smcpowers 		attr[0].ulValueLen = sizeof (truevalue);
21384219Smcpowers 		rv = attribute_set_value(attr, object->attributes,
21394219Smcpowers 		    object->num_attributes);
21404219Smcpowers 		if (rv != CKR_OK)
21414219Smcpowers 			goto failure;
21424219Smcpowers 
21434219Smcpowers 		rv = meta_get_slot_session(slotnum, &slot_session,
21444219Smcpowers 		    session->session_flags);
21454219Smcpowers 		if (rv == CKR_OK) {
21464219Smcpowers 			rv = FUNCLIST(slot_session->fw_st_id)->		\
21474219Smcpowers 			    C_SetAttributeValue(slot_session->hSession,
21484338Sdinak 			    object->clones[slotnum]->hObject, attr, 1);
21494219Smcpowers 
21504219Smcpowers 			meta_release_slot_session(slot_session);
21514219Smcpowers 		}
21524219Smcpowers 	}
21534219Smcpowers 
21544219Smcpowers 	if (object->isFreeToken == FREE_ENABLED || failover) {
21554219Smcpowers 		keystore_slotnum = get_keystore_slotnum();
21564219Smcpowers 		if (object->clones[keystore_slotnum] == NULL) {
21574219Smcpowers 			rv = meta_freeobject_clone_maker(session, object,
21584219Smcpowers 			    keystore_slotnum);
21594219Smcpowers 			if (rv != CKR_OK)
21604219Smcpowers 				goto failure;
21614219Smcpowers 
21624219Smcpowers 			object->master_clone_slotnum = keystore_slotnum;
21634219Smcpowers 		}
21644219Smcpowers 		object->isFreeToken = FREE_ENABLED;
21654219Smcpowers 	}
21664219Smcpowers 
21674219Smcpowers 	object->isFreeObject = FREE_ENABLED;
21684219Smcpowers 	return (CKR_OK);
21694219Smcpowers 
21704219Smcpowers failure:
21714219Smcpowers 	object->isFreeToken = FREE_DISABLED;
21724219Smcpowers 	object->isFreeObject = FREE_DISABLED;
21734219Smcpowers 	return (rv);
21744219Smcpowers 
21754219Smcpowers }
2176