xref: /illumos-gate/usr/src/lib/pkcs11/libpkcs11/common/metaObjectManager.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
1*7c478bd9Sstevel@tonic-gate /*
2*7c478bd9Sstevel@tonic-gate  * CDDL HEADER START
3*7c478bd9Sstevel@tonic-gate  *
4*7c478bd9Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7c478bd9Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
6*7c478bd9Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
7*7c478bd9Sstevel@tonic-gate  * with the License.
8*7c478bd9Sstevel@tonic-gate  *
9*7c478bd9Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10*7c478bd9Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
11*7c478bd9Sstevel@tonic-gate  * See the License for the specific language governing permissions
12*7c478bd9Sstevel@tonic-gate  * and limitations under the License.
13*7c478bd9Sstevel@tonic-gate  *
14*7c478bd9Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
15*7c478bd9Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16*7c478bd9Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
17*7c478bd9Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
18*7c478bd9Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
19*7c478bd9Sstevel@tonic-gate  *
20*7c478bd9Sstevel@tonic-gate  * CDDL HEADER END
21*7c478bd9Sstevel@tonic-gate  */
22*7c478bd9Sstevel@tonic-gate /*
23*7c478bd9Sstevel@tonic-gate  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24*7c478bd9Sstevel@tonic-gate  * Use is subject to license terms.
25*7c478bd9Sstevel@tonic-gate  */
26*7c478bd9Sstevel@tonic-gate 
27*7c478bd9Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
28*7c478bd9Sstevel@tonic-gate 
29*7c478bd9Sstevel@tonic-gate #include <stdlib.h>
30*7c478bd9Sstevel@tonic-gate #include <string.h>
31*7c478bd9Sstevel@tonic-gate #include <strings.h>
32*7c478bd9Sstevel@tonic-gate #include <errno.h>
33*7c478bd9Sstevel@tonic-gate #include <fcntl.h>
34*7c478bd9Sstevel@tonic-gate #include <sys/types.h>
35*7c478bd9Sstevel@tonic-gate #include <sys/stat.h>
36*7c478bd9Sstevel@tonic-gate #include "metaGlobal.h"
37*7c478bd9Sstevel@tonic-gate 
38*7c478bd9Sstevel@tonic-gate /* Size of the template for creating key used for wrap/unwrap */
39*7c478bd9Sstevel@tonic-gate #define	WRAP_KEY_TEMPLATE_SIZE	7
40*7c478bd9Sstevel@tonic-gate 
41*7c478bd9Sstevel@tonic-gate /*
42*7c478bd9Sstevel@tonic-gate  * Information necessary to create keys for C_WrapKey/C_UnwrapKey
43*7c478bd9Sstevel@tonic-gate  */
44*7c478bd9Sstevel@tonic-gate typedef struct _wrap_info {
45*7c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS		class; /* class of the key for wrap/unwrap */
46*7c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE		key_type; /* key type of key for wrap/unwrap */
47*7c478bd9Sstevel@tonic-gate 	CK_ULONG		key_length; /* length of key */
48*7c478bd9Sstevel@tonic-gate 	CK_MECHANISM_TYPE	mech_type; /* mech used for wrap/unwrap */
49*7c478bd9Sstevel@tonic-gate 	CK_ULONG		iv_length; /* length of iv for mech */
50*7c478bd9Sstevel@tonic-gate 
51*7c478bd9Sstevel@tonic-gate 	boolean_t		src_supports;
52*7c478bd9Sstevel@tonic-gate 	boolean_t		dst_supports;
53*7c478bd9Sstevel@tonic-gate } wrap_info_t;
54*7c478bd9Sstevel@tonic-gate 
55*7c478bd9Sstevel@tonic-gate extern pthread_rwlock_t meta_sessionlist_lock;
56*7c478bd9Sstevel@tonic-gate extern meta_session_t *meta_sessionlist_head;
57*7c478bd9Sstevel@tonic-gate 
58*7c478bd9Sstevel@tonic-gate static wrap_info_t common_wrap_info[] = {
59*7c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_AES, 16, CKM_AES_CBC_PAD, 16, B_FALSE, B_FALSE},
60*7c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_DES3, 24, CKM_DES3_CBC_PAD, 8, B_FALSE, B_FALSE},
61*7c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_DES, 8, CKM_DES_CBC_PAD, 8, B_FALSE, B_FALSE},
62*7c478bd9Sstevel@tonic-gate };
63*7c478bd9Sstevel@tonic-gate 
64*7c478bd9Sstevel@tonic-gate static unsigned int num_common_wrap_info =
65*7c478bd9Sstevel@tonic-gate     sizeof (common_wrap_info) / sizeof (wrap_info_t);
66*7c478bd9Sstevel@tonic-gate 
67*7c478bd9Sstevel@tonic-gate static wrap_info_t special_wrap_info[] = {
68*7c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_SKIPJACK, 12,  CKM_SKIPJACK_WRAP, 0,
69*7c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
70*7c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_BATON, 40, CKM_BATON_WRAP, 0,
71*7c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
72*7c478bd9Sstevel@tonic-gate 	{CKO_SECRET_KEY, CKK_JUNIPER, 40, CKM_JUNIPER_WRAP, 0,
73*7c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
74*7c478bd9Sstevel@tonic-gate };
75*7c478bd9Sstevel@tonic-gate static unsigned int num_special_wrap_info =
76*7c478bd9Sstevel@tonic-gate     sizeof (special_wrap_info) / sizeof (wrap_info_t);
77*7c478bd9Sstevel@tonic-gate 
78*7c478bd9Sstevel@tonic-gate static wrap_info_t rsa_wrap_info[] = {
79*7c478bd9Sstevel@tonic-gate 	{CKO_PUBLIC_KEY, CKK_RSA, 0,  CKM_RSA_PKCS, 0,
80*7c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
81*7c478bd9Sstevel@tonic-gate 	{CKO_PUBLIC_KEY, CKK_RSA, 0, CKM_RSA_X_509, 0,
82*7c478bd9Sstevel@tonic-gate 	    B_FALSE, B_FALSE},
83*7c478bd9Sstevel@tonic-gate };
84*7c478bd9Sstevel@tonic-gate static unsigned int num_rsa_wrap_info =
85*7c478bd9Sstevel@tonic-gate     sizeof (rsa_wrap_info) / sizeof (wrap_info_t);
86*7c478bd9Sstevel@tonic-gate 
87*7c478bd9Sstevel@tonic-gate 
88*7c478bd9Sstevel@tonic-gate static pthread_rwlock_t meta_objectclose_lock;
89*7c478bd9Sstevel@tonic-gate static pthread_rwlock_t tokenobject_list_lock;
90*7c478bd9Sstevel@tonic-gate static meta_object_t *tokenobject_list_head;
91*7c478bd9Sstevel@tonic-gate 
92*7c478bd9Sstevel@tonic-gate static CK_BBOOL falsevalue = FALSE;
93*7c478bd9Sstevel@tonic-gate static CK_BBOOL truevalue = TRUE;
94*7c478bd9Sstevel@tonic-gate 
95*7c478bd9Sstevel@tonic-gate /*
96*7c478bd9Sstevel@tonic-gate  * Public and private exponent, and Module value for
97*7c478bd9Sstevel@tonic-gate  * creating the RSA public/private key.
98*7c478bd9Sstevel@tonic-gate  *
99*7c478bd9Sstevel@tonic-gate  */
100*7c478bd9Sstevel@tonic-gate static CK_BYTE PubExpo[3] = {0x01, 0x00, 0x01};
101*7c478bd9Sstevel@tonic-gate CK_BYTE PriExpo[128] = {
102*7c478bd9Sstevel@tonic-gate 	0x8e, 0xc9, 0x70, 0x57, 0x6b, 0xcd, 0xfb, 0xa9,
103*7c478bd9Sstevel@tonic-gate 	0x19, 0xad, 0xcd, 0x91, 0x69, 0xd5, 0x52, 0xec,
104*7c478bd9Sstevel@tonic-gate 	0x72, 0x1e, 0x45, 0x15, 0x06, 0xdc, 0x65, 0x2d,
105*7c478bd9Sstevel@tonic-gate 	0x98, 0xc4, 0xce, 0x33, 0x54, 0x15, 0x70, 0x8d,
106*7c478bd9Sstevel@tonic-gate 	0xfa, 0x65, 0xea, 0x53, 0x44, 0xf3, 0x3e, 0x3f,
107*7c478bd9Sstevel@tonic-gate 	0xb4, 0x4c, 0x60, 0xd5, 0x01, 0x2d, 0xa4, 0x12,
108*7c478bd9Sstevel@tonic-gate 	0x99, 0xbf, 0x3f, 0x0b, 0xcd, 0xbb, 0x24, 0x10,
109*7c478bd9Sstevel@tonic-gate 	0x60, 0x30, 0x5e, 0x58, 0xf8, 0x59, 0xaa, 0xd1,
110*7c478bd9Sstevel@tonic-gate 	0x63, 0x3b, 0xbc, 0xcb, 0x94, 0x58, 0x38, 0x24,
111*7c478bd9Sstevel@tonic-gate 	0xfc, 0x65, 0x25, 0xc5, 0xa6, 0x51, 0xa2, 0x2e,
112*7c478bd9Sstevel@tonic-gate 	0xf1, 0x5e, 0xf5, 0xc1, 0xf5, 0x46, 0xf7, 0xbd,
113*7c478bd9Sstevel@tonic-gate 	0xc7, 0x62, 0xa8, 0xe2, 0x27, 0xd6, 0x94, 0x5b,
114*7c478bd9Sstevel@tonic-gate 	0xd3, 0xa2, 0xb5, 0x76, 0x42, 0x67, 0x6b, 0x86,
115*7c478bd9Sstevel@tonic-gate 	0x91, 0x97, 0x4d, 0x07, 0x92, 0x00, 0x4a, 0xdf,
116*7c478bd9Sstevel@tonic-gate 	0x0b, 0x65, 0x64, 0x05, 0x03, 0x48, 0x27, 0xeb,
117*7c478bd9Sstevel@tonic-gate 	0xce, 0x9a, 0x49, 0x7f, 0x3e, 0x10, 0xe0, 0x01};
118*7c478bd9Sstevel@tonic-gate 
119*7c478bd9Sstevel@tonic-gate static CK_BYTE Modulus[128] = {
120*7c478bd9Sstevel@tonic-gate 	0x94, 0x32, 0xb9, 0x12, 0x1d, 0x68, 0x2c, 0xda,
121*7c478bd9Sstevel@tonic-gate 	0x2b, 0xe0, 0xe4, 0x97, 0x1b, 0x4d, 0xdc, 0x43,
122*7c478bd9Sstevel@tonic-gate 	0xdf, 0x38, 0x6e, 0x7b, 0x9f, 0x07, 0x58, 0xae,
123*7c478bd9Sstevel@tonic-gate 	0x9d, 0x82, 0x1e, 0xc7, 0xbc, 0x92, 0xbf, 0xd3,
124*7c478bd9Sstevel@tonic-gate 	0xce, 0x00, 0xbb, 0x91, 0xc9, 0x79, 0x06, 0x03,
125*7c478bd9Sstevel@tonic-gate 	0x1f, 0xbc, 0x9f, 0x94, 0x75, 0x29, 0x5f, 0xd7,
126*7c478bd9Sstevel@tonic-gate 	0xc5, 0xf3, 0x73, 0x8a, 0xa4, 0x35, 0x43, 0x7a,
127*7c478bd9Sstevel@tonic-gate 	0x00, 0x32, 0x97, 0x3e, 0x86, 0xef, 0x70, 0x6f,
128*7c478bd9Sstevel@tonic-gate 	0x18, 0x56, 0x15, 0xaa, 0x6a, 0x87, 0xe7, 0x8d,
129*7c478bd9Sstevel@tonic-gate 	0x7d, 0xdd, 0x1f, 0xa4, 0xe4, 0x31, 0xd4, 0x7a,
130*7c478bd9Sstevel@tonic-gate 	0x8c, 0x0e, 0x20, 0xd2, 0x23, 0xf5, 0x57, 0x3c,
131*7c478bd9Sstevel@tonic-gate 	0x1b, 0xa8, 0x44, 0xa4, 0x57, 0x8f, 0x33, 0x52,
132*7c478bd9Sstevel@tonic-gate 	0xad, 0x83, 0xae, 0x4a, 0x97, 0xa6, 0x1e, 0xa6,
133*7c478bd9Sstevel@tonic-gate 	0x2b, 0xfa, 0xea, 0xeb, 0x6e, 0x71, 0xb8, 0xb6,
134*7c478bd9Sstevel@tonic-gate 	0x0a, 0x36, 0xed, 0x83, 0xce, 0xb0, 0xdf, 0xc1,
135*7c478bd9Sstevel@tonic-gate 	0xd4, 0x3a, 0xe9, 0x99, 0x6f, 0xf3, 0x96, 0xb7};
136*7c478bd9Sstevel@tonic-gate 
137*7c478bd9Sstevel@tonic-gate static CK_RV
138*7c478bd9Sstevel@tonic-gate meta_clone_template_setup(meta_object_t *object,
139*7c478bd9Sstevel@tonic-gate     const generic_attr_t *attributes, size_t num_attributes);
140*7c478bd9Sstevel@tonic-gate 
141*7c478bd9Sstevel@tonic-gate /*
142*7c478bd9Sstevel@tonic-gate  * meta_objectManager_initialize
143*7c478bd9Sstevel@tonic-gate  *
144*7c478bd9Sstevel@tonic-gate  * Called from meta_Initialize.  Initializes all the variables used
145*7c478bd9Sstevel@tonic-gate  * by the object manager.
146*7c478bd9Sstevel@tonic-gate  */
147*7c478bd9Sstevel@tonic-gate CK_RV
148*7c478bd9Sstevel@tonic-gate meta_objectManager_initialize()
149*7c478bd9Sstevel@tonic-gate {
150*7c478bd9Sstevel@tonic-gate 	if (pthread_rwlock_init(&meta_objectclose_lock, NULL) != 0) {
151*7c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
152*7c478bd9Sstevel@tonic-gate 	}
153*7c478bd9Sstevel@tonic-gate 
154*7c478bd9Sstevel@tonic-gate 	if (pthread_rwlock_init(&tokenobject_list_lock, NULL) != 0) {
155*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_destroy(&meta_objectclose_lock);
156*7c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
157*7c478bd9Sstevel@tonic-gate 	}
158*7c478bd9Sstevel@tonic-gate 
159*7c478bd9Sstevel@tonic-gate 	tokenobject_list_head = NULL;
160*7c478bd9Sstevel@tonic-gate 
161*7c478bd9Sstevel@tonic-gate 	return (CKR_OK);
162*7c478bd9Sstevel@tonic-gate }
163*7c478bd9Sstevel@tonic-gate 
164*7c478bd9Sstevel@tonic-gate void
165*7c478bd9Sstevel@tonic-gate meta_objectManager_finalize()
166*7c478bd9Sstevel@tonic-gate {
167*7c478bd9Sstevel@tonic-gate 	/*
168*7c478bd9Sstevel@tonic-gate 	 * If there are still any token object in the list, need to
169*7c478bd9Sstevel@tonic-gate 	 * deactivate all of them.
170*7c478bd9Sstevel@tonic-gate 	 */
171*7c478bd9Sstevel@tonic-gate 	(void) meta_token_object_deactivate(ALL_TOKEN);
172*7c478bd9Sstevel@tonic-gate 
173*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&meta_objectclose_lock);
174*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&tokenobject_list_lock);
175*7c478bd9Sstevel@tonic-gate }
176*7c478bd9Sstevel@tonic-gate 
177*7c478bd9Sstevel@tonic-gate 
178*7c478bd9Sstevel@tonic-gate 
179*7c478bd9Sstevel@tonic-gate /*
180*7c478bd9Sstevel@tonic-gate  * meta_handle2object
181*7c478bd9Sstevel@tonic-gate  *
182*7c478bd9Sstevel@tonic-gate  * Convert a CK_OBJECT_HANDLE to the corresponding metaobject. If
183*7c478bd9Sstevel@tonic-gate  * successful, a reader-lock on the object will be held to indicate
184*7c478bd9Sstevel@tonic-gate  * that it's in use. Call OBJRELEASE() when finished.
185*7c478bd9Sstevel@tonic-gate  *
186*7c478bd9Sstevel@tonic-gate  */
187*7c478bd9Sstevel@tonic-gate CK_RV
188*7c478bd9Sstevel@tonic-gate meta_handle2object(CK_OBJECT_HANDLE hObject, meta_object_t **object)
189*7c478bd9Sstevel@tonic-gate {
190*7c478bd9Sstevel@tonic-gate 	meta_object_t *tmp_object = (meta_object_t *)(hObject);
191*7c478bd9Sstevel@tonic-gate 
192*7c478bd9Sstevel@tonic-gate 	/* Check for bad args (eg CK_INVALID_HANDLE, which is 0/NULL). */
193*7c478bd9Sstevel@tonic-gate 	if (tmp_object == NULL) {
194*7c478bd9Sstevel@tonic-gate 		*object = NULL;
195*7c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
196*7c478bd9Sstevel@tonic-gate 	}
197*7c478bd9Sstevel@tonic-gate 
198*7c478bd9Sstevel@tonic-gate 
199*7c478bd9Sstevel@tonic-gate 	/* Lock to ensure the magic-check + read-lock is atomic. */
200*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&meta_objectclose_lock);
201*7c478bd9Sstevel@tonic-gate 
202*7c478bd9Sstevel@tonic-gate 	if (tmp_object->magic_marker != METASLOT_OBJECT_MAGIC) {
203*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&meta_objectclose_lock);
204*7c478bd9Sstevel@tonic-gate 		*object = NULL;
205*7c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
206*7c478bd9Sstevel@tonic-gate 	}
207*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&tmp_object->object_lock);
208*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&meta_objectclose_lock);
209*7c478bd9Sstevel@tonic-gate 
210*7c478bd9Sstevel@tonic-gate 	*object = tmp_object;
211*7c478bd9Sstevel@tonic-gate 	return (CKR_OK);
212*7c478bd9Sstevel@tonic-gate }
213*7c478bd9Sstevel@tonic-gate 
214*7c478bd9Sstevel@tonic-gate 
215*7c478bd9Sstevel@tonic-gate /*
216*7c478bd9Sstevel@tonic-gate  * meta_object_alloc
217*7c478bd9Sstevel@tonic-gate  *
218*7c478bd9Sstevel@tonic-gate  * Creates a new metaobject, but does not yet add it to the object list.
219*7c478bd9Sstevel@tonic-gate  * Once the caller has finished initializing the object (by setting
220*7c478bd9Sstevel@tonic-gate  * object attributes), meta_object_add should be called. This two-step
221*7c478bd9Sstevel@tonic-gate  * process prevents others from seeing the object until fully intitialized.
222*7c478bd9Sstevel@tonic-gate  *
223*7c478bd9Sstevel@tonic-gate  */
224*7c478bd9Sstevel@tonic-gate CK_RV
225*7c478bd9Sstevel@tonic-gate meta_object_alloc(meta_session_t *session, meta_object_t **object)
226*7c478bd9Sstevel@tonic-gate {
227*7c478bd9Sstevel@tonic-gate 	meta_object_t *new_object;
228*7c478bd9Sstevel@tonic-gate 	CK_ULONG num_slots;
229*7c478bd9Sstevel@tonic-gate 
230*7c478bd9Sstevel@tonic-gate 	/* Allocate memory for the object. */
231*7c478bd9Sstevel@tonic-gate 	new_object = calloc(1, sizeof (meta_object_t));
232*7c478bd9Sstevel@tonic-gate 	if (new_object == NULL)
233*7c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
234*7c478bd9Sstevel@tonic-gate 
235*7c478bd9Sstevel@tonic-gate 	num_slots = meta_slotManager_get_slotcount();
236*7c478bd9Sstevel@tonic-gate 
237*7c478bd9Sstevel@tonic-gate 	new_object->clones = calloc(num_slots, sizeof (slot_object_t *));
238*7c478bd9Sstevel@tonic-gate 	if (new_object->clones == NULL) {
239*7c478bd9Sstevel@tonic-gate 		free(new_object);
240*7c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
241*7c478bd9Sstevel@tonic-gate 	}
242*7c478bd9Sstevel@tonic-gate 
243*7c478bd9Sstevel@tonic-gate 	new_object->tried_create_clone = calloc(num_slots, sizeof (boolean_t));
244*7c478bd9Sstevel@tonic-gate 	if (new_object->tried_create_clone == NULL) {
245*7c478bd9Sstevel@tonic-gate 		free(new_object->clones);
246*7c478bd9Sstevel@tonic-gate 		free(new_object);
247*7c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
248*7c478bd9Sstevel@tonic-gate 	}
249*7c478bd9Sstevel@tonic-gate 
250*7c478bd9Sstevel@tonic-gate 	/* Initialize the object fields. */
251*7c478bd9Sstevel@tonic-gate 	new_object->magic_marker = METASLOT_OBJECT_MAGIC;
252*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_init(&new_object->object_lock, NULL);
253*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_init(&new_object->attribute_lock, NULL);
254*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_object->clone_create_lock, NULL);
255*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_init(&new_object->isClosingObject_lock, NULL);
256*7c478bd9Sstevel@tonic-gate 	new_object->creator_session = session;
257*7c478bd9Sstevel@tonic-gate 
258*7c478bd9Sstevel@tonic-gate 	*object = new_object;
259*7c478bd9Sstevel@tonic-gate 
260*7c478bd9Sstevel@tonic-gate 	return (CKR_OK);
261*7c478bd9Sstevel@tonic-gate }
262*7c478bd9Sstevel@tonic-gate 
263*7c478bd9Sstevel@tonic-gate 
264*7c478bd9Sstevel@tonic-gate /*
265*7c478bd9Sstevel@tonic-gate  * meta_object_get_attr
266*7c478bd9Sstevel@tonic-gate  *
267*7c478bd9Sstevel@tonic-gate  * Get attribute values to fill in attribute values
268*7c478bd9Sstevel@tonic-gate  * being kept in the metaslot object.  The following 4 attributes
269*7c478bd9Sstevel@tonic-gate  * in the meta_object_t structure will be filled in:
270*7c478bd9Sstevel@tonic-gate  * isToken, isPrivate, isSensitive, isExtractable
271*7c478bd9Sstevel@tonic-gate  *
272*7c478bd9Sstevel@tonic-gate  * It's basically an easy way to do a C_GetAttributeValue.
273*7c478bd9Sstevel@tonic-gate  * So, the hSession argument is assumed
274*7c478bd9Sstevel@tonic-gate  * to be valid, and the pointer to meta_object_t is also assumed
275*7c478bd9Sstevel@tonic-gate  * to be valid.
276*7c478bd9Sstevel@tonic-gate  */
277*7c478bd9Sstevel@tonic-gate CK_RV
278*7c478bd9Sstevel@tonic-gate meta_object_get_attr(slot_session_t *slot_session, CK_OBJECT_HANDLE hObject,
279*7c478bd9Sstevel@tonic-gate     meta_object_t *object)
280*7c478bd9Sstevel@tonic-gate {
281*7c478bd9Sstevel@tonic-gate 	CK_BBOOL is_sensitive, is_extractable, is_token, is_private;
282*7c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS class;
283*7c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE attrs[3];
284*7c478bd9Sstevel@tonic-gate 	CK_RV rv;
285*7c478bd9Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession = slot_session->hSession;
286*7c478bd9Sstevel@tonic-gate 	CK_SLOT_ID fw_st_id = slot_session->fw_st_id;
287*7c478bd9Sstevel@tonic-gate 
288*7c478bd9Sstevel@tonic-gate 	attrs[0].type = CKA_CLASS;
289*7c478bd9Sstevel@tonic-gate 	attrs[0].pValue = &class;
290*7c478bd9Sstevel@tonic-gate 	attrs[0].ulValueLen = sizeof (class);
291*7c478bd9Sstevel@tonic-gate 
292*7c478bd9Sstevel@tonic-gate 	attrs[1].type = CKA_TOKEN;
293*7c478bd9Sstevel@tonic-gate 	attrs[1].pValue = &is_token;
294*7c478bd9Sstevel@tonic-gate 	attrs[1].ulValueLen = sizeof (is_token);
295*7c478bd9Sstevel@tonic-gate 
296*7c478bd9Sstevel@tonic-gate 	attrs[2].type = CKA_PRIVATE;
297*7c478bd9Sstevel@tonic-gate 	attrs[2].pValue = &is_private;
298*7c478bd9Sstevel@tonic-gate 	attrs[2].ulValueLen = sizeof (is_private);
299*7c478bd9Sstevel@tonic-gate 
300*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession, hObject,
301*7c478bd9Sstevel@tonic-gate 	    attrs, 3);
302*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
303*7c478bd9Sstevel@tonic-gate 		return (rv);
304*7c478bd9Sstevel@tonic-gate 	}
305*7c478bd9Sstevel@tonic-gate 
306*7c478bd9Sstevel@tonic-gate 
307*7c478bd9Sstevel@tonic-gate 	if ((class == CKO_PRIVATE_KEY) || (class == CKO_SECRET_KEY)) {
308*7c478bd9Sstevel@tonic-gate 		/*
309*7c478bd9Sstevel@tonic-gate 		 * CKA_SENSITIVE and CKA_EXTRACTABLE only applies to private
310*7c478bd9Sstevel@tonic-gate 		 * and secret keys.
311*7c478bd9Sstevel@tonic-gate 		 */
312*7c478bd9Sstevel@tonic-gate 		attrs[0].type = CKA_SENSITIVE;
313*7c478bd9Sstevel@tonic-gate 		attrs[0].pValue = &is_sensitive;
314*7c478bd9Sstevel@tonic-gate 		attrs[0].ulValueLen = sizeof (is_sensitive);
315*7c478bd9Sstevel@tonic-gate 
316*7c478bd9Sstevel@tonic-gate 		attrs[1].type = CKA_EXTRACTABLE;
317*7c478bd9Sstevel@tonic-gate 		attrs[1].pValue = &is_extractable;
318*7c478bd9Sstevel@tonic-gate 		attrs[1].ulValueLen = sizeof (is_extractable);
319*7c478bd9Sstevel@tonic-gate 
320*7c478bd9Sstevel@tonic-gate 		rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
321*7c478bd9Sstevel@tonic-gate 		    hObject, attrs, 2);
322*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
323*7c478bd9Sstevel@tonic-gate 			return (rv);
324*7c478bd9Sstevel@tonic-gate 		}
325*7c478bd9Sstevel@tonic-gate 	} else {
326*7c478bd9Sstevel@tonic-gate 		is_sensitive = CK_FALSE;
327*7c478bd9Sstevel@tonic-gate 		is_extractable = CK_TRUE;
328*7c478bd9Sstevel@tonic-gate 	}
329*7c478bd9Sstevel@tonic-gate 
330*7c478bd9Sstevel@tonic-gate 	object->isToken = is_token;
331*7c478bd9Sstevel@tonic-gate 	object->isPrivate = is_private;
332*7c478bd9Sstevel@tonic-gate 	object->isSensitive = is_sensitive;
333*7c478bd9Sstevel@tonic-gate 	object->isExtractable = is_extractable;
334*7c478bd9Sstevel@tonic-gate 
335*7c478bd9Sstevel@tonic-gate 	return (CKR_OK);
336*7c478bd9Sstevel@tonic-gate }
337*7c478bd9Sstevel@tonic-gate 
338*7c478bd9Sstevel@tonic-gate 
339*7c478bd9Sstevel@tonic-gate /*
340*7c478bd9Sstevel@tonic-gate  * meta_object_activate
341*7c478bd9Sstevel@tonic-gate  *
342*7c478bd9Sstevel@tonic-gate  * Add a new metaobject to the list of objects. See also meta_object_create,
343*7c478bd9Sstevel@tonic-gate  * which would be called to create an object before it is added.
344*7c478bd9Sstevel@tonic-gate  */
345*7c478bd9Sstevel@tonic-gate void
346*7c478bd9Sstevel@tonic-gate meta_object_activate(meta_object_t *new_object)
347*7c478bd9Sstevel@tonic-gate {
348*7c478bd9Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
349*7c478bd9Sstevel@tonic-gate 	meta_object_t **list_head;
350*7c478bd9Sstevel@tonic-gate 
351*7c478bd9Sstevel@tonic-gate 	/*
352*7c478bd9Sstevel@tonic-gate 	 * For session objects, we keep the list in the session that created
353*7c478bd9Sstevel@tonic-gate 	 * this object, because this object will be destroyed when that session
354*7c478bd9Sstevel@tonic-gate 	 * is closed.
355*7c478bd9Sstevel@tonic-gate 	 *
356*7c478bd9Sstevel@tonic-gate 	 * For token objects, the list is global (ie, not associated with any
357*7c478bd9Sstevel@tonic-gate 	 * particular session).
358*7c478bd9Sstevel@tonic-gate 	 */
359*7c478bd9Sstevel@tonic-gate 	if (new_object->isToken) {
360*7c478bd9Sstevel@tonic-gate 		list_lock = &tokenobject_list_lock;
361*7c478bd9Sstevel@tonic-gate 		list_head = &tokenobject_list_head;
362*7c478bd9Sstevel@tonic-gate 	} else {
363*7c478bd9Sstevel@tonic-gate 		list_lock = &new_object->creator_session->object_list_lock;
364*7c478bd9Sstevel@tonic-gate 		list_head = &new_object->creator_session->object_list_head;
365*7c478bd9Sstevel@tonic-gate 	}
366*7c478bd9Sstevel@tonic-gate 
367*7c478bd9Sstevel@tonic-gate 	/* Add object to the list of objects. */
368*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(list_lock);
369*7c478bd9Sstevel@tonic-gate 	INSERT_INTO_LIST(*list_head, new_object);
370*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(list_lock);
371*7c478bd9Sstevel@tonic-gate }
372*7c478bd9Sstevel@tonic-gate 
373*7c478bd9Sstevel@tonic-gate 
374*7c478bd9Sstevel@tonic-gate /*
375*7c478bd9Sstevel@tonic-gate  * meta_object_deactivate
376*7c478bd9Sstevel@tonic-gate  *
377*7c478bd9Sstevel@tonic-gate  * Removes the object from the list of valid meta objects.  Note
378*7c478bd9Sstevel@tonic-gate  * that this function does not clean up any allocated
379*7c478bd9Sstevel@tonic-gate  * resources (memory, object clones, etc).   Cleaning up of
380*7c478bd9Sstevel@tonic-gate  * allocated resources is done by calling the meta_object_deallocate()
381*7c478bd9Sstevel@tonic-gate  *
382*7c478bd9Sstevel@tonic-gate  */
383*7c478bd9Sstevel@tonic-gate CK_RV
384*7c478bd9Sstevel@tonic-gate meta_object_deactivate(meta_object_t *object, boolean_t have_list_lock,
385*7c478bd9Sstevel@tonic-gate     boolean_t have_object_lock)
386*7c478bd9Sstevel@tonic-gate {
387*7c478bd9Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
388*7c478bd9Sstevel@tonic-gate 	meta_object_t **list_head;
389*7c478bd9Sstevel@tonic-gate 
390*7c478bd9Sstevel@tonic-gate 	if (!have_object_lock) {
391*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&object->object_lock);
392*7c478bd9Sstevel@tonic-gate 	}
393*7c478bd9Sstevel@tonic-gate 
394*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object->isClosingObject_lock);
395*7c478bd9Sstevel@tonic-gate 	if (object->isClosingObject) {
396*7c478bd9Sstevel@tonic-gate 		/* Lost a delete race. */
397*7c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&object->isClosingObject_lock);
398*7c478bd9Sstevel@tonic-gate 		OBJRELEASE(object);
399*7c478bd9Sstevel@tonic-gate 		return (CKR_OBJECT_HANDLE_INVALID);
400*7c478bd9Sstevel@tonic-gate 	}
401*7c478bd9Sstevel@tonic-gate 	object->isClosingObject = B_TRUE;
402*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object->isClosingObject_lock);
403*7c478bd9Sstevel@tonic-gate 
404*7c478bd9Sstevel@tonic-gate 	if (object->isToken) {
405*7c478bd9Sstevel@tonic-gate 		list_lock = &tokenobject_list_lock;
406*7c478bd9Sstevel@tonic-gate 		list_head = &tokenobject_list_head;
407*7c478bd9Sstevel@tonic-gate 	} else {
408*7c478bd9Sstevel@tonic-gate 		list_lock = &object->creator_session->object_list_lock;
409*7c478bd9Sstevel@tonic-gate 		list_head = &object->creator_session->object_list_head;
410*7c478bd9Sstevel@tonic-gate 	}
411*7c478bd9Sstevel@tonic-gate 
412*7c478bd9Sstevel@tonic-gate 	/*
413*7c478bd9Sstevel@tonic-gate 	 * Remove object from the object list. Once removed, it will not
414*7c478bd9Sstevel@tonic-gate 	 * be possible for another thread to begin using the object.
415*7c478bd9Sstevel@tonic-gate 	 */
416*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&meta_objectclose_lock);
417*7c478bd9Sstevel@tonic-gate 	if (!have_list_lock) {
418*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(list_lock);
419*7c478bd9Sstevel@tonic-gate 	}
420*7c478bd9Sstevel@tonic-gate 
421*7c478bd9Sstevel@tonic-gate 
422*7c478bd9Sstevel@tonic-gate 	object->magic_marker = METASLOT_OBJECT_BADMAGIC;
423*7c478bd9Sstevel@tonic-gate 	/*
424*7c478bd9Sstevel@tonic-gate 	 * Can't use the regular REMOVE_FROM_LIST() function because
425*7c478bd9Sstevel@tonic-gate 	 * that will miss the "error cleanup" situation where object is not yet
426*7c478bd9Sstevel@tonic-gate 	 * in the list (object->next == NULL && object->prev == NULL)
427*7c478bd9Sstevel@tonic-gate 	 */
428*7c478bd9Sstevel@tonic-gate 	if (*list_head == object) {
429*7c478bd9Sstevel@tonic-gate 		/* Object is the first one in the list */
430*7c478bd9Sstevel@tonic-gate 		if (object->next) {
431*7c478bd9Sstevel@tonic-gate 			*list_head = object->next;
432*7c478bd9Sstevel@tonic-gate 			object->next->prev = NULL;
433*7c478bd9Sstevel@tonic-gate 		} else {
434*7c478bd9Sstevel@tonic-gate 			/* Object is the only one in the list */
435*7c478bd9Sstevel@tonic-gate 			*list_head = NULL;
436*7c478bd9Sstevel@tonic-gate 		}
437*7c478bd9Sstevel@tonic-gate 	} else if (object->next != NULL || object->prev != NULL) {
438*7c478bd9Sstevel@tonic-gate 		if (object->next) {
439*7c478bd9Sstevel@tonic-gate 			object->prev->next = object->next;
440*7c478bd9Sstevel@tonic-gate 			object->next->prev = object->prev;
441*7c478bd9Sstevel@tonic-gate 		} else {
442*7c478bd9Sstevel@tonic-gate 			/* Object is the last one in the list */
443*7c478bd9Sstevel@tonic-gate 			object->prev->next = NULL;
444*7c478bd9Sstevel@tonic-gate 		}
445*7c478bd9Sstevel@tonic-gate 	}
446*7c478bd9Sstevel@tonic-gate 
447*7c478bd9Sstevel@tonic-gate 	if (!have_list_lock) {
448*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(list_lock);
449*7c478bd9Sstevel@tonic-gate 	}
450*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&meta_objectclose_lock);
451*7c478bd9Sstevel@tonic-gate 
452*7c478bd9Sstevel@tonic-gate 	/*
453*7c478bd9Sstevel@tonic-gate 	 * Wait for anyone already using object to finish, by obtaining
454*7c478bd9Sstevel@tonic-gate 	 * a writer-lock (need to release our reader-lock first). Once we
455*7c478bd9Sstevel@tonic-gate 	 * get the write lock, we can just release it and finish cleaning
456*7c478bd9Sstevel@tonic-gate 	 * up the object.
457*7c478bd9Sstevel@tonic-gate 	 */
458*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->object_lock); /* rdlock */
459*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&object->object_lock);
460*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->object_lock); /* wrlock */
461*7c478bd9Sstevel@tonic-gate 
462*7c478bd9Sstevel@tonic-gate 
463*7c478bd9Sstevel@tonic-gate 	return (CKR_OK);
464*7c478bd9Sstevel@tonic-gate }
465*7c478bd9Sstevel@tonic-gate 
466*7c478bd9Sstevel@tonic-gate 
467*7c478bd9Sstevel@tonic-gate /*
468*7c478bd9Sstevel@tonic-gate  * meta_object_dealloc
469*7c478bd9Sstevel@tonic-gate  *
470*7c478bd9Sstevel@tonic-gate  * Performs final object cleanup, releasing any allocated memory and
471*7c478bd9Sstevel@tonic-gate  * destroying any clones on other slots. Caller is assumed to have
472*7c478bd9Sstevel@tonic-gate  * called meta_object_deactivate() before this function.
473*7c478bd9Sstevel@tonic-gate  *
474*7c478bd9Sstevel@tonic-gate  * Caller is assumed to have only reference to object, but should have
475*7c478bd9Sstevel@tonic-gate  * released any lock.
476*7c478bd9Sstevel@tonic-gate  *
477*7c478bd9Sstevel@tonic-gate  * If "nukeSourceObj" argument is true, we will actually delete the
478*7c478bd9Sstevel@tonic-gate  * object from the underlying slot.
479*7c478bd9Sstevel@tonic-gate  */
480*7c478bd9Sstevel@tonic-gate CK_RV
481*7c478bd9Sstevel@tonic-gate meta_object_dealloc(meta_object_t *object, boolean_t nukeSourceObj)
482*7c478bd9Sstevel@tonic-gate {
483*7c478bd9Sstevel@tonic-gate 	CK_RV rv, save_rv = CKR_OK;
484*7c478bd9Sstevel@tonic-gate 	CK_ULONG slotnum, num_slots;
485*7c478bd9Sstevel@tonic-gate 	CK_ULONG i;
486*7c478bd9Sstevel@tonic-gate 
487*7c478bd9Sstevel@tonic-gate 	/* First, delete all the clones of this object on other slots. */
488*7c478bd9Sstevel@tonic-gate 	num_slots = meta_slotManager_get_slotcount();
489*7c478bd9Sstevel@tonic-gate 	for (slotnum = 0; slotnum < num_slots; slotnum++) {
490*7c478bd9Sstevel@tonic-gate 		slot_session_t *obj_session;
491*7c478bd9Sstevel@tonic-gate 		slot_object_t *clone;
492*7c478bd9Sstevel@tonic-gate 
493*7c478bd9Sstevel@tonic-gate 		clone = object->clones[slotnum];
494*7c478bd9Sstevel@tonic-gate 		if (clone == NULL)
495*7c478bd9Sstevel@tonic-gate 			continue;
496*7c478bd9Sstevel@tonic-gate 
497*7c478bd9Sstevel@tonic-gate 		if (nukeSourceObj || !object->isToken) {
498*7c478bd9Sstevel@tonic-gate 
499*7c478bd9Sstevel@tonic-gate 			rv = meta_get_slot_session(slotnum, &obj_session,
500*7c478bd9Sstevel@tonic-gate 			    object->creator_session->session_flags);
501*7c478bd9Sstevel@tonic-gate 
502*7c478bd9Sstevel@tonic-gate 			if (rv == CKR_OK) {
503*7c478bd9Sstevel@tonic-gate 				rv = FUNCLIST(obj_session->fw_st_id)->\
504*7c478bd9Sstevel@tonic-gate 				    C_DestroyObject(obj_session->hSession,
505*7c478bd9Sstevel@tonic-gate 				    clone->hObject);
506*7c478bd9Sstevel@tonic-gate 
507*7c478bd9Sstevel@tonic-gate 				meta_release_slot_session(obj_session);
508*7c478bd9Sstevel@tonic-gate 				if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
509*7c478bd9Sstevel@tonic-gate 					save_rv = rv;
510*7c478bd9Sstevel@tonic-gate 				}
511*7c478bd9Sstevel@tonic-gate 			}
512*7c478bd9Sstevel@tonic-gate 
513*7c478bd9Sstevel@tonic-gate 		}
514*7c478bd9Sstevel@tonic-gate 
515*7c478bd9Sstevel@tonic-gate 		meta_slot_object_deactivate(clone);
516*7c478bd9Sstevel@tonic-gate 		meta_slot_object_dealloc(clone);
517*7c478bd9Sstevel@tonic-gate 
518*7c478bd9Sstevel@tonic-gate 		object->clones[slotnum] = NULL;
519*7c478bd9Sstevel@tonic-gate 	}
520*7c478bd9Sstevel@tonic-gate 
521*7c478bd9Sstevel@tonic-gate 	/* Now erase and delete any attributes in the metaobject. */
522*7c478bd9Sstevel@tonic-gate 	dealloc_attributes(object->attributes, object->num_attributes);
523*7c478bd9Sstevel@tonic-gate 
524*7c478bd9Sstevel@tonic-gate 	free(object->clones);
525*7c478bd9Sstevel@tonic-gate 	free(object->tried_create_clone);
526*7c478bd9Sstevel@tonic-gate 
527*7c478bd9Sstevel@tonic-gate 	if (object->clone_template) {
528*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < object->clone_template_size; i++) {
529*7c478bd9Sstevel@tonic-gate 			free(((object->clone_template)[i]).pValue);
530*7c478bd9Sstevel@tonic-gate 		}
531*7c478bd9Sstevel@tonic-gate 		free(object->clone_template);
532*7c478bd9Sstevel@tonic-gate 	}
533*7c478bd9Sstevel@tonic-gate 
534*7c478bd9Sstevel@tonic-gate 	/* Cleanup remaining object fields. */
535*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&object->object_lock);
536*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_destroy(&object->attribute_lock);
537*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_destroy(&object->isClosingObject_lock);
538*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_destroy(&object->clone_create_lock);
539*7c478bd9Sstevel@tonic-gate 
540*7c478bd9Sstevel@tonic-gate 	meta_object_delay_free(object);
541*7c478bd9Sstevel@tonic-gate 
542*7c478bd9Sstevel@tonic-gate 	return (save_rv);
543*7c478bd9Sstevel@tonic-gate }
544*7c478bd9Sstevel@tonic-gate 
545*7c478bd9Sstevel@tonic-gate 
546*7c478bd9Sstevel@tonic-gate /*
547*7c478bd9Sstevel@tonic-gate  * meta_slot_object_alloc
548*7c478bd9Sstevel@tonic-gate  */
549*7c478bd9Sstevel@tonic-gate CK_RV
550*7c478bd9Sstevel@tonic-gate meta_slot_object_alloc(slot_object_t **object) {
551*7c478bd9Sstevel@tonic-gate 	slot_object_t *new_object;
552*7c478bd9Sstevel@tonic-gate 
553*7c478bd9Sstevel@tonic-gate 	new_object = calloc(1, sizeof (slot_object_t));
554*7c478bd9Sstevel@tonic-gate 	if (new_object == NULL)
555*7c478bd9Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
556*7c478bd9Sstevel@tonic-gate 
557*7c478bd9Sstevel@tonic-gate 	*object = new_object;
558*7c478bd9Sstevel@tonic-gate 	return (CKR_OK);
559*7c478bd9Sstevel@tonic-gate }
560*7c478bd9Sstevel@tonic-gate 
561*7c478bd9Sstevel@tonic-gate 
562*7c478bd9Sstevel@tonic-gate /*
563*7c478bd9Sstevel@tonic-gate  * meta_slot_object_activate
564*7c478bd9Sstevel@tonic-gate  */
565*7c478bd9Sstevel@tonic-gate void
566*7c478bd9Sstevel@tonic-gate meta_slot_object_activate(slot_object_t *object,
567*7c478bd9Sstevel@tonic-gate 	slot_session_t *creator_session, boolean_t isToken)
568*7c478bd9Sstevel@tonic-gate {
569*7c478bd9Sstevel@tonic-gate 	object->creator_session = creator_session;
570*7c478bd9Sstevel@tonic-gate 
571*7c478bd9Sstevel@tonic-gate 	if (isToken) {
572*7c478bd9Sstevel@tonic-gate 		extern slot_data_t *slots;
573*7c478bd9Sstevel@tonic-gate 		slot_data_t *slot;
574*7c478bd9Sstevel@tonic-gate 
575*7c478bd9Sstevel@tonic-gate 		slot = &(slots[object->creator_session->slotnum]);
576*7c478bd9Sstevel@tonic-gate 
577*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(&slot->tokenobject_list_lock);
578*7c478bd9Sstevel@tonic-gate 		INSERT_INTO_LIST(slot->tokenobject_list_head, object);
579*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&slot->tokenobject_list_lock);
580*7c478bd9Sstevel@tonic-gate 	} else {
581*7c478bd9Sstevel@tonic-gate 		slot_session_t *session = object->creator_session;
582*7c478bd9Sstevel@tonic-gate 
583*7c478bd9Sstevel@tonic-gate 		/* Add to session's list of session objects. */
584*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_wrlock(&session->object_list_lock);
585*7c478bd9Sstevel@tonic-gate 		INSERT_INTO_LIST(session->object_list_head, object);
586*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&session->object_list_lock);
587*7c478bd9Sstevel@tonic-gate 	}
588*7c478bd9Sstevel@tonic-gate 	object->isToken = isToken;
589*7c478bd9Sstevel@tonic-gate }
590*7c478bd9Sstevel@tonic-gate 
591*7c478bd9Sstevel@tonic-gate 
592*7c478bd9Sstevel@tonic-gate /*
593*7c478bd9Sstevel@tonic-gate  * meta_slot_object_deactivate
594*7c478bd9Sstevel@tonic-gate  *
595*7c478bd9Sstevel@tonic-gate  * Remove the specified slot object from the appropriate object list.
596*7c478bd9Sstevel@tonic-gate  */
597*7c478bd9Sstevel@tonic-gate void
598*7c478bd9Sstevel@tonic-gate meta_slot_object_deactivate(slot_object_t *object)
599*7c478bd9Sstevel@tonic-gate {
600*7c478bd9Sstevel@tonic-gate 	slot_object_t **list_head;
601*7c478bd9Sstevel@tonic-gate 	pthread_rwlock_t *list_lock;
602*7c478bd9Sstevel@tonic-gate 
603*7c478bd9Sstevel@tonic-gate 	if (object->isToken) {
604*7c478bd9Sstevel@tonic-gate 		extern slot_data_t *slots;
605*7c478bd9Sstevel@tonic-gate 		slot_data_t *slot;
606*7c478bd9Sstevel@tonic-gate 
607*7c478bd9Sstevel@tonic-gate 		slot = &(slots[object->creator_session->slotnum]);
608*7c478bd9Sstevel@tonic-gate 
609*7c478bd9Sstevel@tonic-gate 		list_head = &slot->tokenobject_list_head;
610*7c478bd9Sstevel@tonic-gate 		list_lock = &slot->tokenobject_list_lock;
611*7c478bd9Sstevel@tonic-gate 	} else {
612*7c478bd9Sstevel@tonic-gate 		list_head = &object->creator_session->object_list_head;
613*7c478bd9Sstevel@tonic-gate 		list_lock = &object->creator_session->object_list_lock;
614*7c478bd9Sstevel@tonic-gate 	}
615*7c478bd9Sstevel@tonic-gate 
616*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(list_lock);
617*7c478bd9Sstevel@tonic-gate 	REMOVE_FROM_LIST(*list_head, object);
618*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(list_lock);
619*7c478bd9Sstevel@tonic-gate }
620*7c478bd9Sstevel@tonic-gate 
621*7c478bd9Sstevel@tonic-gate 
622*7c478bd9Sstevel@tonic-gate /*
623*7c478bd9Sstevel@tonic-gate  * meta_slot_object_dealloc
624*7c478bd9Sstevel@tonic-gate  */
625*7c478bd9Sstevel@tonic-gate void
626*7c478bd9Sstevel@tonic-gate meta_slot_object_dealloc(slot_object_t *object)
627*7c478bd9Sstevel@tonic-gate {
628*7c478bd9Sstevel@tonic-gate 	/* Not much cleanup for slot objects, unlike meta objects... */
629*7c478bd9Sstevel@tonic-gate 	free(object);
630*7c478bd9Sstevel@tonic-gate }
631*7c478bd9Sstevel@tonic-gate 
632*7c478bd9Sstevel@tonic-gate 
633*7c478bd9Sstevel@tonic-gate /*
634*7c478bd9Sstevel@tonic-gate  * meta_object_copyin
635*7c478bd9Sstevel@tonic-gate  *
636*7c478bd9Sstevel@tonic-gate  * When a key is generated/derived/unwrapped, the attribute values
637*7c478bd9Sstevel@tonic-gate  * created by the token are not immediately read into our copy of the
638*7c478bd9Sstevel@tonic-gate  * attributes. We defer this work until we actually need to know.
639*7c478bd9Sstevel@tonic-gate  */
640*7c478bd9Sstevel@tonic-gate CK_RV
641*7c478bd9Sstevel@tonic-gate meta_object_copyin(meta_object_t *object)
642*7c478bd9Sstevel@tonic-gate {
643*7c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
644*7c478bd9Sstevel@tonic-gate 	slot_session_t *session = NULL;
645*7c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE *attrs = NULL, *attrs_with_val = NULL;
646*7c478bd9Sstevel@tonic-gate 	slot_object_t *slot_object = NULL;
647*7c478bd9Sstevel@tonic-gate 	CK_ULONG num_attrs = 0, i, num_attrs_with_val;
648*7c478bd9Sstevel@tonic-gate 	CK_SESSION_HANDLE hSession;
649*7c478bd9Sstevel@tonic-gate 	CK_SLOT_ID fw_st_id;
650*7c478bd9Sstevel@tonic-gate 
651*7c478bd9Sstevel@tonic-gate 	/* Make sure no one else is looking at attributes. */
652*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&object->attribute_lock);
653*7c478bd9Sstevel@tonic-gate 
654*7c478bd9Sstevel@tonic-gate 	/* Did we just lose a copyin race with another thread */
655*7c478bd9Sstevel@tonic-gate 	if (object->attributes != NULL) {
656*7c478bd9Sstevel@tonic-gate 		goto finish;
657*7c478bd9Sstevel@tonic-gate 	}
658*7c478bd9Sstevel@tonic-gate 
659*7c478bd9Sstevel@tonic-gate 	slot_object = object->clones[object->master_clone_slotnum];
660*7c478bd9Sstevel@tonic-gate 
661*7c478bd9Sstevel@tonic-gate 	rv = meta_get_slot_session(object->master_clone_slotnum, &session,
662*7c478bd9Sstevel@tonic-gate 	    object->creator_session->session_flags);
663*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
664*7c478bd9Sstevel@tonic-gate 		goto finish;
665*7c478bd9Sstevel@tonic-gate 	}
666*7c478bd9Sstevel@tonic-gate 
667*7c478bd9Sstevel@tonic-gate 	/*
668*7c478bd9Sstevel@tonic-gate 	 * first, get the master template of all the attributes
669*7c478bd9Sstevel@tonic-gate 	 * for this object
670*7c478bd9Sstevel@tonic-gate 	 */
671*7c478bd9Sstevel@tonic-gate 	rv = get_master_attributes_by_object(session, slot_object,
672*7c478bd9Sstevel@tonic-gate 	    &(object->attributes), &(object->num_attributes));
673*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
674*7c478bd9Sstevel@tonic-gate 		goto finish;
675*7c478bd9Sstevel@tonic-gate 	}
676*7c478bd9Sstevel@tonic-gate 
677*7c478bd9Sstevel@tonic-gate 	/*
678*7c478bd9Sstevel@tonic-gate 	 * Get value for each attribute items.
679*7c478bd9Sstevel@tonic-gate 	 *
680*7c478bd9Sstevel@tonic-gate 	 * Some attributes are required by the given object type.
681*7c478bd9Sstevel@tonic-gate 	 * Some are optional.  Get all the values first, and then
682*7c478bd9Sstevel@tonic-gate 	 * make sure we have value for all required values,
683*7c478bd9Sstevel@tonic-gate 	 */
684*7c478bd9Sstevel@tonic-gate 	attrs = calloc(object->num_attributes, sizeof (CK_ATTRIBUTE));
685*7c478bd9Sstevel@tonic-gate 	if (attrs == NULL) {
686*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
687*7c478bd9Sstevel@tonic-gate 		goto finish;
688*7c478bd9Sstevel@tonic-gate 	}
689*7c478bd9Sstevel@tonic-gate 
690*7c478bd9Sstevel@tonic-gate 
691*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < object->num_attributes; i++) {
692*7c478bd9Sstevel@tonic-gate 		attrs[i].type =
693*7c478bd9Sstevel@tonic-gate 		    ((object->attributes[i]).attribute).type;
694*7c478bd9Sstevel@tonic-gate 	}
695*7c478bd9Sstevel@tonic-gate 	num_attrs = object->num_attributes;
696*7c478bd9Sstevel@tonic-gate 
697*7c478bd9Sstevel@tonic-gate 	hSession = session->hSession;
698*7c478bd9Sstevel@tonic-gate 	fw_st_id = session->fw_st_id;
699*7c478bd9Sstevel@tonic-gate 
700*7c478bd9Sstevel@tonic-gate 	/* first, call C_GetAttributeValue() to get size for each attribute */
701*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
702*7c478bd9Sstevel@tonic-gate 	    slot_object->hObject, attrs, num_attrs);
703*7c478bd9Sstevel@tonic-gate 	/*
704*7c478bd9Sstevel@tonic-gate 	 * If the return value is not CKR_OK, allow it to be
705*7c478bd9Sstevel@tonic-gate 	 * CKR_ATTRIBUTE_TYPE_INVALID for now.
706*7c478bd9Sstevel@tonic-gate 	 * Some attributes defined in PKCS#11 version 2.11
707*7c478bd9Sstevel@tonic-gate 	 * might not be defined in earlier versions.  We will
708*7c478bd9Sstevel@tonic-gate 	 * TRY to work with those providers if the attribute
709*7c478bd9Sstevel@tonic-gate 	 * is optional.
710*7c478bd9Sstevel@tonic-gate 	 */
711*7c478bd9Sstevel@tonic-gate 	if ((rv != CKR_OK) && (rv != CKR_ATTRIBUTE_TYPE_INVALID)) {
712*7c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED; /* make sure rv is appropriate */
713*7c478bd9Sstevel@tonic-gate 		goto finish;
714*7c478bd9Sstevel@tonic-gate 	}
715*7c478bd9Sstevel@tonic-gate 
716*7c478bd9Sstevel@tonic-gate 	/*
717*7c478bd9Sstevel@tonic-gate 	 * allocate space.
718*7c478bd9Sstevel@tonic-gate 	 * Since we don't know how many attributes have
719*7c478bd9Sstevel@tonic-gate 	 * values at this time, just assume all of them
720*7c478bd9Sstevel@tonic-gate 	 * have values so we save one loop to count the number
721*7c478bd9Sstevel@tonic-gate 	 * of attributes that have value.
722*7c478bd9Sstevel@tonic-gate 	 */
723*7c478bd9Sstevel@tonic-gate 	attrs_with_val = calloc(num_attrs, sizeof (CK_ATTRIBUTE));
724*7c478bd9Sstevel@tonic-gate 	if (attrs_with_val == NULL) {
725*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
726*7c478bd9Sstevel@tonic-gate 		goto finish;
727*7c478bd9Sstevel@tonic-gate 	}
728*7c478bd9Sstevel@tonic-gate 
729*7c478bd9Sstevel@tonic-gate 
730*7c478bd9Sstevel@tonic-gate 	num_attrs_with_val = 0;
731*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attrs; i++) {
732*7c478bd9Sstevel@tonic-gate 		if (!(((CK_LONG)(attrs[i].ulValueLen)) > 0)) {
733*7c478bd9Sstevel@tonic-gate 			/* if it isn't an optional attr, len should be > 0 */
734*7c478bd9Sstevel@tonic-gate 			if (!object->attributes[i].canBeEmptyValue) {
735*7c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
736*7c478bd9Sstevel@tonic-gate 				goto finish;
737*7c478bd9Sstevel@tonic-gate 			}
738*7c478bd9Sstevel@tonic-gate 		} else {
739*7c478bd9Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].type = attrs[i].type;
740*7c478bd9Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].ulValueLen =
741*7c478bd9Sstevel@tonic-gate 			    attrs[i].ulValueLen;
742*7c478bd9Sstevel@tonic-gate 			attrs_with_val[num_attrs_with_val].pValue =
743*7c478bd9Sstevel@tonic-gate 			    malloc(attrs[i].ulValueLen);
744*7c478bd9Sstevel@tonic-gate 			if (attrs_with_val[num_attrs_with_val].pValue == NULL) {
745*7c478bd9Sstevel@tonic-gate 				rv = CKR_HOST_MEMORY;
746*7c478bd9Sstevel@tonic-gate 				goto finish;
747*7c478bd9Sstevel@tonic-gate 			}
748*7c478bd9Sstevel@tonic-gate 			num_attrs_with_val++;
749*7c478bd9Sstevel@tonic-gate 		}
750*7c478bd9Sstevel@tonic-gate 	}
751*7c478bd9Sstevel@tonic-gate 
752*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
753*7c478bd9Sstevel@tonic-gate 	    slot_object->hObject, attrs_with_val, num_attrs_with_val);
754*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
755*7c478bd9Sstevel@tonic-gate 		goto finish;
756*7c478bd9Sstevel@tonic-gate 	}
757*7c478bd9Sstevel@tonic-gate 
758*7c478bd9Sstevel@tonic-gate 	/* store these values into the meta object */
759*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attrs_with_val; i++) {
760*7c478bd9Sstevel@tonic-gate 		rv = attribute_set_value(&(attrs_with_val[i]),
761*7c478bd9Sstevel@tonic-gate 		    object->attributes, object->num_attributes);
762*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
763*7c478bd9Sstevel@tonic-gate 			goto finish;
764*7c478bd9Sstevel@tonic-gate 		}
765*7c478bd9Sstevel@tonic-gate 	}
766*7c478bd9Sstevel@tonic-gate 
767*7c478bd9Sstevel@tonic-gate finish:
768*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->attribute_lock);
769*7c478bd9Sstevel@tonic-gate 
770*7c478bd9Sstevel@tonic-gate 	if (session)
771*7c478bd9Sstevel@tonic-gate 		meta_release_slot_session(session);
772*7c478bd9Sstevel@tonic-gate 
773*7c478bd9Sstevel@tonic-gate 	if (attrs) {
774*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_attrs; i++) {
775*7c478bd9Sstevel@tonic-gate 			if (attrs[i].pValue != NULL) {
776*7c478bd9Sstevel@tonic-gate 				free(attrs[i].pValue);
777*7c478bd9Sstevel@tonic-gate 			}
778*7c478bd9Sstevel@tonic-gate 		}
779*7c478bd9Sstevel@tonic-gate 		free(attrs);
780*7c478bd9Sstevel@tonic-gate 	}
781*7c478bd9Sstevel@tonic-gate 
782*7c478bd9Sstevel@tonic-gate 	if (attrs_with_val) {
783*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_attrs; i++) {
784*7c478bd9Sstevel@tonic-gate 			if (attrs_with_val[i].pValue != NULL) {
785*7c478bd9Sstevel@tonic-gate 				free(attrs_with_val[i].pValue);
786*7c478bd9Sstevel@tonic-gate 			}
787*7c478bd9Sstevel@tonic-gate 		}
788*7c478bd9Sstevel@tonic-gate 		free(attrs_with_val);
789*7c478bd9Sstevel@tonic-gate 	}
790*7c478bd9Sstevel@tonic-gate 	return (rv);
791*7c478bd9Sstevel@tonic-gate }
792*7c478bd9Sstevel@tonic-gate 
793*7c478bd9Sstevel@tonic-gate /*
794*7c478bd9Sstevel@tonic-gate  * Create an object to be used for wrapping and unwrapping.
795*7c478bd9Sstevel@tonic-gate  * The same template will be used for all wrapping/unwrapping keys all
796*7c478bd9Sstevel@tonic-gate  * the time
797*7c478bd9Sstevel@tonic-gate  */
798*7c478bd9Sstevel@tonic-gate 
799*7c478bd9Sstevel@tonic-gate static CK_RV
800*7c478bd9Sstevel@tonic-gate create_wrap_unwrap_key(slot_session_t *slot_session, CK_OBJECT_HANDLE *hObject,
801*7c478bd9Sstevel@tonic-gate     wrap_info_t *wrap_info, char *key_data, CK_ULONG key_len)
802*7c478bd9Sstevel@tonic-gate {
803*7c478bd9Sstevel@tonic-gate 
804*7c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS objclass;
805*7c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE keytype;
806*7c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
807*7c478bd9Sstevel@tonic-gate 	int i;
808*7c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE template[WRAP_KEY_TEMPLATE_SIZE];
809*7c478bd9Sstevel@tonic-gate 
810*7c478bd9Sstevel@tonic-gate 	i = 0;
811*7c478bd9Sstevel@tonic-gate 	objclass = wrap_info->class;
812*7c478bd9Sstevel@tonic-gate 	template[i].type = CKA_CLASS;
813*7c478bd9Sstevel@tonic-gate 	template[i].pValue = &objclass;
814*7c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (objclass);
815*7c478bd9Sstevel@tonic-gate 
816*7c478bd9Sstevel@tonic-gate 	i++;
817*7c478bd9Sstevel@tonic-gate 	keytype = wrap_info->key_type;
818*7c478bd9Sstevel@tonic-gate 	template[i].type = CKA_KEY_TYPE;
819*7c478bd9Sstevel@tonic-gate 	template[i].pValue = &keytype;
820*7c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (keytype);
821*7c478bd9Sstevel@tonic-gate 
822*7c478bd9Sstevel@tonic-gate 	i++;
823*7c478bd9Sstevel@tonic-gate 	template[i].type = CKA_TOKEN;
824*7c478bd9Sstevel@tonic-gate 	template[i].pValue = &falsevalue;
825*7c478bd9Sstevel@tonic-gate 	template[i].ulValueLen = sizeof (falsevalue);
826*7c478bd9Sstevel@tonic-gate 
827*7c478bd9Sstevel@tonic-gate 
828*7c478bd9Sstevel@tonic-gate 	if (objclass == CKO_SECRET_KEY) {
829*7c478bd9Sstevel@tonic-gate 		i++;
830*7c478bd9Sstevel@tonic-gate 		template[i].type = CKA_VALUE;
831*7c478bd9Sstevel@tonic-gate 		template[i].pValue = key_data;
832*7c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = key_len;
833*7c478bd9Sstevel@tonic-gate 
834*7c478bd9Sstevel@tonic-gate 		i++;
835*7c478bd9Sstevel@tonic-gate 		template[i].type = CKA_WRAP;
836*7c478bd9Sstevel@tonic-gate 		template[i].pValue = &truevalue;
837*7c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (truevalue);
838*7c478bd9Sstevel@tonic-gate 
839*7c478bd9Sstevel@tonic-gate 		i++;
840*7c478bd9Sstevel@tonic-gate 		template[i].type = CKA_UNWRAP;
841*7c478bd9Sstevel@tonic-gate 		template[i].pValue = &truevalue;
842*7c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (truevalue);
843*7c478bd9Sstevel@tonic-gate 	} else {
844*7c478bd9Sstevel@tonic-gate 		/* Modulus is the same for rsa public and private key */
845*7c478bd9Sstevel@tonic-gate 		i++;
846*7c478bd9Sstevel@tonic-gate 		template[i].type = CKA_MODULUS;
847*7c478bd9Sstevel@tonic-gate 		template[i].pValue = Modulus;
848*7c478bd9Sstevel@tonic-gate 		template[i].ulValueLen = sizeof (Modulus);
849*7c478bd9Sstevel@tonic-gate 
850*7c478bd9Sstevel@tonic-gate 		if (objclass == CKO_PUBLIC_KEY) {
851*7c478bd9Sstevel@tonic-gate 			/* RSA public key */
852*7c478bd9Sstevel@tonic-gate 			i++;
853*7c478bd9Sstevel@tonic-gate 			template[i].type = CKA_PUBLIC_EXPONENT;
854*7c478bd9Sstevel@tonic-gate 			template[i].pValue = PubExpo;
855*7c478bd9Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (PubExpo);
856*7c478bd9Sstevel@tonic-gate 
857*7c478bd9Sstevel@tonic-gate 			i++;
858*7c478bd9Sstevel@tonic-gate 			template[i].type = CKA_WRAP;
859*7c478bd9Sstevel@tonic-gate 			template[i].pValue = &truevalue;
860*7c478bd9Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (truevalue);
861*7c478bd9Sstevel@tonic-gate 		} else {
862*7c478bd9Sstevel@tonic-gate 			/* RSA private key */
863*7c478bd9Sstevel@tonic-gate 			i++;
864*7c478bd9Sstevel@tonic-gate 			template[i].type = CKA_PRIVATE_EXPONENT;
865*7c478bd9Sstevel@tonic-gate 			template[i].pValue = PriExpo;
866*7c478bd9Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (PriExpo);
867*7c478bd9Sstevel@tonic-gate 
868*7c478bd9Sstevel@tonic-gate 			i++;
869*7c478bd9Sstevel@tonic-gate 			template[i].type = CKA_UNWRAP;
870*7c478bd9Sstevel@tonic-gate 			template[i].pValue = &truevalue;
871*7c478bd9Sstevel@tonic-gate 			template[i].ulValueLen = sizeof (truevalue);
872*7c478bd9Sstevel@tonic-gate 		}
873*7c478bd9Sstevel@tonic-gate 	}
874*7c478bd9Sstevel@tonic-gate 
875*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject(
876*7c478bd9Sstevel@tonic-gate 	    slot_session->hSession, template, i + 1, hObject);
877*7c478bd9Sstevel@tonic-gate 
878*7c478bd9Sstevel@tonic-gate 	return (rv);
879*7c478bd9Sstevel@tonic-gate }
880*7c478bd9Sstevel@tonic-gate 
881*7c478bd9Sstevel@tonic-gate 
882*7c478bd9Sstevel@tonic-gate /*
883*7c478bd9Sstevel@tonic-gate  * Create a clone of a non-sensitive and extractable object.
884*7c478bd9Sstevel@tonic-gate  * If the template required for creating the clone doesn't exist,
885*7c478bd9Sstevel@tonic-gate  * it will be retrieved from the master clone.
886*7c478bd9Sstevel@tonic-gate  */
887*7c478bd9Sstevel@tonic-gate static CK_RV
888*7c478bd9Sstevel@tonic-gate clone_by_create(meta_object_t *object, slot_object_t *new_clone,
889*7c478bd9Sstevel@tonic-gate     slot_session_t *dst_slot_session)
890*7c478bd9Sstevel@tonic-gate {
891*7c478bd9Sstevel@tonic-gate 
892*7c478bd9Sstevel@tonic-gate 	CK_RV rv;
893*7c478bd9Sstevel@tonic-gate 
894*7c478bd9Sstevel@tonic-gate 	if (object->attributes == NULL) {
895*7c478bd9Sstevel@tonic-gate 		rv = meta_object_copyin(object);
896*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
897*7c478bd9Sstevel@tonic-gate 			return (rv);
898*7c478bd9Sstevel@tonic-gate 		}
899*7c478bd9Sstevel@tonic-gate 	}
900*7c478bd9Sstevel@tonic-gate 
901*7c478bd9Sstevel@tonic-gate 	if (object->clone_template == NULL) {
902*7c478bd9Sstevel@tonic-gate 		rv = meta_clone_template_setup(object, object->attributes,
903*7c478bd9Sstevel@tonic-gate 		    object->num_attributes);
904*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
905*7c478bd9Sstevel@tonic-gate 			return (rv);
906*7c478bd9Sstevel@tonic-gate 		}
907*7c478bd9Sstevel@tonic-gate 	}
908*7c478bd9Sstevel@tonic-gate 
909*7c478bd9Sstevel@tonic-gate 	/* Create the clone... */
910*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(dst_slot_session->fw_st_id)->C_CreateObject(
911*7c478bd9Sstevel@tonic-gate 	    dst_slot_session->hSession, object->clone_template,
912*7c478bd9Sstevel@tonic-gate 	    object->clone_template_size, &(new_clone->hObject));
913*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
914*7c478bd9Sstevel@tonic-gate 		return (rv);
915*7c478bd9Sstevel@tonic-gate 	}
916*7c478bd9Sstevel@tonic-gate 
917*7c478bd9Sstevel@tonic-gate 	return (CKR_OK);
918*7c478bd9Sstevel@tonic-gate }
919*7c478bd9Sstevel@tonic-gate 
920*7c478bd9Sstevel@tonic-gate /*
921*7c478bd9Sstevel@tonic-gate  * Goes through the list of wraping mechanisms, and returns the first
922*7c478bd9Sstevel@tonic-gate  * one that is supported by both the source and the destination slot.
923*7c478bd9Sstevel@tonic-gate  * If none of the mechanisms are supported by both slot, return the
924*7c478bd9Sstevel@tonic-gate  * first mechanism that's supported by the source slot
925*7c478bd9Sstevel@tonic-gate  */
926*7c478bd9Sstevel@tonic-gate static CK_RV
927*7c478bd9Sstevel@tonic-gate find_best_match_wrap_mech(wrap_info_t *wrap_info, int num_info,
928*7c478bd9Sstevel@tonic-gate 	CK_ULONG src_slotnum, CK_ULONG dst_slotnum, int *first_both_mech,
929*7c478bd9Sstevel@tonic-gate 	int *first_src_mech)
930*7c478bd9Sstevel@tonic-gate {
931*7c478bd9Sstevel@tonic-gate 
932*7c478bd9Sstevel@tonic-gate 	int i;
933*7c478bd9Sstevel@tonic-gate 	boolean_t src_supports, dst_supports;
934*7c478bd9Sstevel@tonic-gate 	CK_RV rv;
935*7c478bd9Sstevel@tonic-gate 
936*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_info; i++) {
937*7c478bd9Sstevel@tonic-gate 		src_supports = B_FALSE;
938*7c478bd9Sstevel@tonic-gate 		dst_supports = B_FALSE;
939*7c478bd9Sstevel@tonic-gate 
940*7c478bd9Sstevel@tonic-gate 		rv = meta_mechManager_slot_supports_mech(
941*7c478bd9Sstevel@tonic-gate 		    (wrap_info[i]).mech_type, src_slotnum,
942*7c478bd9Sstevel@tonic-gate 		    &src_supports, NULL, B_FALSE);
943*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
944*7c478bd9Sstevel@tonic-gate 			return (rv);
945*7c478bd9Sstevel@tonic-gate 		}
946*7c478bd9Sstevel@tonic-gate 
947*7c478bd9Sstevel@tonic-gate 		rv = meta_mechManager_slot_supports_mech(
948*7c478bd9Sstevel@tonic-gate 		    (wrap_info[i]).mech_type, dst_slotnum,
949*7c478bd9Sstevel@tonic-gate 		    &dst_supports, NULL, B_FALSE);
950*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
951*7c478bd9Sstevel@tonic-gate 			return (rv);
952*7c478bd9Sstevel@tonic-gate 		}
953*7c478bd9Sstevel@tonic-gate 
954*7c478bd9Sstevel@tonic-gate 		/* both source and destination supports the mech */
955*7c478bd9Sstevel@tonic-gate 		if ((src_supports) && (dst_supports)) {
956*7c478bd9Sstevel@tonic-gate 			*first_both_mech = i;
957*7c478bd9Sstevel@tonic-gate 			return (CKR_OK);
958*7c478bd9Sstevel@tonic-gate 		}
959*7c478bd9Sstevel@tonic-gate 
960*7c478bd9Sstevel@tonic-gate 		if ((src_supports) && (*first_src_mech == -1)) {
961*7c478bd9Sstevel@tonic-gate 			*first_src_mech = i;
962*7c478bd9Sstevel@tonic-gate 		}
963*7c478bd9Sstevel@tonic-gate 	}
964*7c478bd9Sstevel@tonic-gate 	return (CKR_OK);
965*7c478bd9Sstevel@tonic-gate }
966*7c478bd9Sstevel@tonic-gate 
967*7c478bd9Sstevel@tonic-gate /*
968*7c478bd9Sstevel@tonic-gate  * Determine the wrapping/unwrapping mechanism to be used
969*7c478bd9Sstevel@tonic-gate  *
970*7c478bd9Sstevel@tonic-gate  * If possible, select a mechanism that's supported by both source
971*7c478bd9Sstevel@tonic-gate  * and destination slot.  If none of the mechanisms are supported
972*7c478bd9Sstevel@tonic-gate  * by both slot, then, select the first one supported by
973*7c478bd9Sstevel@tonic-gate  * the source slot.
974*7c478bd9Sstevel@tonic-gate  */
975*7c478bd9Sstevel@tonic-gate 
976*7c478bd9Sstevel@tonic-gate static CK_RV
977*7c478bd9Sstevel@tonic-gate get_wrap_mechanism(CK_OBJECT_CLASS obj_class, CK_KEY_TYPE key_type,
978*7c478bd9Sstevel@tonic-gate     CK_ULONG src_slotnum, CK_ULONG dst_slotnum, wrap_info_t *wrap_info)
979*7c478bd9Sstevel@tonic-gate {
980*7c478bd9Sstevel@tonic-gate 	wrap_info_t *wrap_info_to_search = NULL;
981*7c478bd9Sstevel@tonic-gate 	unsigned int num_wrap_info;
982*7c478bd9Sstevel@tonic-gate 	CK_RV rv;
983*7c478bd9Sstevel@tonic-gate 	int i;
984*7c478bd9Sstevel@tonic-gate 	boolean_t src_supports = B_FALSE, dst_supports = B_FALSE;
985*7c478bd9Sstevel@tonic-gate 	int first_src_mech, rsa_first_src_mech, first_both_mech;
986*7c478bd9Sstevel@tonic-gate 
987*7c478bd9Sstevel@tonic-gate 	if ((obj_class == CKO_PRIVATE_KEY) && (key_type == CKK_KEA)) {
988*7c478bd9Sstevel@tonic-gate 		/*
989*7c478bd9Sstevel@tonic-gate 		 * only SKIPJACK keys can be used for wrapping
990*7c478bd9Sstevel@tonic-gate 		 * KEA private keys
991*7c478bd9Sstevel@tonic-gate 		 */
992*7c478bd9Sstevel@tonic-gate 
993*7c478bd9Sstevel@tonic-gate 		for (i = 0; i < num_special_wrap_info; i++) {
994*7c478bd9Sstevel@tonic-gate 			if ((special_wrap_info[i]).mech_type
995*7c478bd9Sstevel@tonic-gate 			    != CKM_SKIPJACK_WRAP) {
996*7c478bd9Sstevel@tonic-gate 				continue;
997*7c478bd9Sstevel@tonic-gate 			}
998*7c478bd9Sstevel@tonic-gate 
999*7c478bd9Sstevel@tonic-gate 			src_supports = B_FALSE;
1000*7c478bd9Sstevel@tonic-gate 			dst_supports = B_FALSE;
1001*7c478bd9Sstevel@tonic-gate 
1002*7c478bd9Sstevel@tonic-gate 			rv = meta_mechManager_slot_supports_mech(
1003*7c478bd9Sstevel@tonic-gate 			    (special_wrap_info[i]).mech_type, src_slotnum,
1004*7c478bd9Sstevel@tonic-gate 			    &src_supports, NULL, B_FALSE);
1005*7c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
1006*7c478bd9Sstevel@tonic-gate 				goto finish;
1007*7c478bd9Sstevel@tonic-gate 			}
1008*7c478bd9Sstevel@tonic-gate 
1009*7c478bd9Sstevel@tonic-gate 			rv = meta_mechManager_slot_supports_mech(
1010*7c478bd9Sstevel@tonic-gate 			    (special_wrap_info[i]).mech_type, dst_slotnum,
1011*7c478bd9Sstevel@tonic-gate 			    &dst_supports, NULL, B_FALSE);
1012*7c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
1013*7c478bd9Sstevel@tonic-gate 				goto finish;
1014*7c478bd9Sstevel@tonic-gate 			}
1015*7c478bd9Sstevel@tonic-gate 
1016*7c478bd9Sstevel@tonic-gate 			if (src_supports) {
1017*7c478bd9Sstevel@tonic-gate 				/*
1018*7c478bd9Sstevel@tonic-gate 				 * both src and dst supports the mech or
1019*7c478bd9Sstevel@tonic-gate 				 * only the src supports the mech
1020*7c478bd9Sstevel@tonic-gate 				 */
1021*7c478bd9Sstevel@tonic-gate 				(void) memcpy(wrap_info,
1022*7c478bd9Sstevel@tonic-gate 				    &(special_wrap_info[i]),
1023*7c478bd9Sstevel@tonic-gate 				    sizeof (wrap_info_t));
1024*7c478bd9Sstevel@tonic-gate 
1025*7c478bd9Sstevel@tonic-gate 				wrap_info->src_supports = src_supports;
1026*7c478bd9Sstevel@tonic-gate 				wrap_info->dst_supports = dst_supports;
1027*7c478bd9Sstevel@tonic-gate 				rv = CKR_OK;
1028*7c478bd9Sstevel@tonic-gate 				goto finish;
1029*7c478bd9Sstevel@tonic-gate 			}
1030*7c478bd9Sstevel@tonic-gate 
1031*7c478bd9Sstevel@tonic-gate 		}
1032*7c478bd9Sstevel@tonic-gate 
1033*7c478bd9Sstevel@tonic-gate 		/*
1034*7c478bd9Sstevel@tonic-gate 		 * if we are here, that means neither the source slot
1035*7c478bd9Sstevel@tonic-gate 		 * nor the destination slots suppports CKM_SKIPJACK_WRAP
1036*7c478bd9Sstevel@tonic-gate 		 */
1037*7c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
1038*7c478bd9Sstevel@tonic-gate 		goto finish;
1039*7c478bd9Sstevel@tonic-gate 	}
1040*7c478bd9Sstevel@tonic-gate 
1041*7c478bd9Sstevel@tonic-gate 	if ((key_type == CKK_SKIPJACK) || (key_type == CKK_BATON) ||
1042*7c478bd9Sstevel@tonic-gate 	    (key_type == CKK_JUNIPER)) {
1043*7c478bd9Sstevel@tonic-gate 		/* special key types */
1044*7c478bd9Sstevel@tonic-gate 		wrap_info_to_search = special_wrap_info;
1045*7c478bd9Sstevel@tonic-gate 		num_wrap_info = num_special_wrap_info;
1046*7c478bd9Sstevel@tonic-gate 	} else {
1047*7c478bd9Sstevel@tonic-gate 		/* use the regular wrapping mechanisms */
1048*7c478bd9Sstevel@tonic-gate 		wrap_info_to_search = common_wrap_info;
1049*7c478bd9Sstevel@tonic-gate 		num_wrap_info = num_common_wrap_info;
1050*7c478bd9Sstevel@tonic-gate 	}
1051*7c478bd9Sstevel@tonic-gate 
1052*7c478bd9Sstevel@tonic-gate 	first_both_mech = -1;
1053*7c478bd9Sstevel@tonic-gate 	first_src_mech = -1;
1054*7c478bd9Sstevel@tonic-gate 
1055*7c478bd9Sstevel@tonic-gate 	rv = find_best_match_wrap_mech(wrap_info_to_search, num_wrap_info,
1056*7c478bd9Sstevel@tonic-gate 	    src_slotnum, dst_slotnum, &first_both_mech, &first_src_mech);
1057*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1058*7c478bd9Sstevel@tonic-gate 		goto finish;
1059*7c478bd9Sstevel@tonic-gate 	}
1060*7c478bd9Sstevel@tonic-gate 
1061*7c478bd9Sstevel@tonic-gate 	if (first_both_mech != -1) {
1062*7c478bd9Sstevel@tonic-gate 		(void) memcpy(wrap_info,
1063*7c478bd9Sstevel@tonic-gate 		    &(wrap_info_to_search[first_both_mech]),
1064*7c478bd9Sstevel@tonic-gate 		    sizeof (wrap_info_t));
1065*7c478bd9Sstevel@tonic-gate 
1066*7c478bd9Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
1067*7c478bd9Sstevel@tonic-gate 		wrap_info->dst_supports = B_TRUE;
1068*7c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
1069*7c478bd9Sstevel@tonic-gate 		goto finish;
1070*7c478bd9Sstevel@tonic-gate 	}
1071*7c478bd9Sstevel@tonic-gate 
1072*7c478bd9Sstevel@tonic-gate 	/*
1073*7c478bd9Sstevel@tonic-gate 	 * If we are here, we did not find a mechanism that's supported
1074*7c478bd9Sstevel@tonic-gate 	 * by both source and destination slot.
1075*7c478bd9Sstevel@tonic-gate 	 *
1076*7c478bd9Sstevel@tonic-gate 	 * If it is a secret key, can also try to wrap it with
1077*7c478bd9Sstevel@tonic-gate 	 * a RSA public key
1078*7c478bd9Sstevel@tonic-gate 	 */
1079*7c478bd9Sstevel@tonic-gate 	if (obj_class == CKO_SECRET_KEY) {
1080*7c478bd9Sstevel@tonic-gate 		first_both_mech = -1;
1081*7c478bd9Sstevel@tonic-gate 		rsa_first_src_mech = -1;
1082*7c478bd9Sstevel@tonic-gate 
1083*7c478bd9Sstevel@tonic-gate 		rv = find_best_match_wrap_mech(rsa_wrap_info,
1084*7c478bd9Sstevel@tonic-gate 		    num_rsa_wrap_info, src_slotnum, dst_slotnum,
1085*7c478bd9Sstevel@tonic-gate 		    &first_both_mech, &rsa_first_src_mech);
1086*7c478bd9Sstevel@tonic-gate 
1087*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1088*7c478bd9Sstevel@tonic-gate 			goto finish;
1089*7c478bd9Sstevel@tonic-gate 		}
1090*7c478bd9Sstevel@tonic-gate 
1091*7c478bd9Sstevel@tonic-gate 		if (first_both_mech > -1) {
1092*7c478bd9Sstevel@tonic-gate 			(void) memcpy(wrap_info,
1093*7c478bd9Sstevel@tonic-gate 			    &(rsa_wrap_info[first_both_mech]),
1094*7c478bd9Sstevel@tonic-gate 			    sizeof (wrap_info_t));
1095*7c478bd9Sstevel@tonic-gate 
1096*7c478bd9Sstevel@tonic-gate 			wrap_info->src_supports = B_TRUE;
1097*7c478bd9Sstevel@tonic-gate 			wrap_info->dst_supports = B_TRUE;
1098*7c478bd9Sstevel@tonic-gate 			rv = CKR_OK;
1099*7c478bd9Sstevel@tonic-gate 			goto finish;
1100*7c478bd9Sstevel@tonic-gate 		}
1101*7c478bd9Sstevel@tonic-gate 	}
1102*7c478bd9Sstevel@tonic-gate 
1103*7c478bd9Sstevel@tonic-gate 	/*
1104*7c478bd9Sstevel@tonic-gate 	 * if we are here, that means none of the mechanisms are supported
1105*7c478bd9Sstevel@tonic-gate 	 * by both the source and the destination
1106*7c478bd9Sstevel@tonic-gate 	 */
1107*7c478bd9Sstevel@tonic-gate 	if (first_src_mech > -1) {
1108*7c478bd9Sstevel@tonic-gate 		/* source slot support one of the secret key mechs */
1109*7c478bd9Sstevel@tonic-gate 		(void) memcpy(wrap_info,
1110*7c478bd9Sstevel@tonic-gate 		    &(wrap_info_to_search[first_src_mech]),
1111*7c478bd9Sstevel@tonic-gate 		    sizeof (wrap_info_t));
1112*7c478bd9Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
1113*7c478bd9Sstevel@tonic-gate 		wrap_info->dst_supports = B_FALSE;
1114*7c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
1115*7c478bd9Sstevel@tonic-gate 	} else if (rsa_first_src_mech > -1) {
1116*7c478bd9Sstevel@tonic-gate 		/* source slot support one of the RSA mechs */
1117*7c478bd9Sstevel@tonic-gate 		(void) memcpy(wrap_info, &(rsa_wrap_info[rsa_first_src_mech]),
1118*7c478bd9Sstevel@tonic-gate 		    sizeof (wrap_info_t));
1119*7c478bd9Sstevel@tonic-gate 
1120*7c478bd9Sstevel@tonic-gate 		wrap_info->src_supports = B_TRUE;
1121*7c478bd9Sstevel@tonic-gate 		wrap_info->dst_supports = B_FALSE;
1122*7c478bd9Sstevel@tonic-gate 		rv = CKR_OK;
1123*7c478bd9Sstevel@tonic-gate 	} else {
1124*7c478bd9Sstevel@tonic-gate 		/* neither source nor destination support any wrap mechs */
1125*7c478bd9Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
1126*7c478bd9Sstevel@tonic-gate 	}
1127*7c478bd9Sstevel@tonic-gate 
1128*7c478bd9Sstevel@tonic-gate finish:
1129*7c478bd9Sstevel@tonic-gate 	return (rv);
1130*7c478bd9Sstevel@tonic-gate }
1131*7c478bd9Sstevel@tonic-gate 
1132*7c478bd9Sstevel@tonic-gate 
1133*7c478bd9Sstevel@tonic-gate /*
1134*7c478bd9Sstevel@tonic-gate  * This is called if the object to be cloned is a sensitive object
1135*7c478bd9Sstevel@tonic-gate  */
1136*7c478bd9Sstevel@tonic-gate static CK_RV
1137*7c478bd9Sstevel@tonic-gate clone_by_wrap(meta_object_t *object, slot_object_t *new_clone,
1138*7c478bd9Sstevel@tonic-gate     slot_session_t *dst_slot_session)
1139*7c478bd9Sstevel@tonic-gate {
1140*7c478bd9Sstevel@tonic-gate 	slot_session_t *src_slot_session = NULL;
1141*7c478bd9Sstevel@tonic-gate 	CK_OBJECT_HANDLE wrappingKey = NULL, unwrappingKey = NULL;
1142*7c478bd9Sstevel@tonic-gate 	CK_MECHANISM wrappingMech;
1143*7c478bd9Sstevel@tonic-gate 	CK_BYTE *wrappedKey = NULL;
1144*7c478bd9Sstevel@tonic-gate 	CK_ULONG wrappedKeyLen = 0;
1145*7c478bd9Sstevel@tonic-gate 	slot_object_t *slot_object = NULL;
1146*7c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1147*7c478bd9Sstevel@tonic-gate 	CK_OBJECT_HANDLE unwrapped_obj;
1148*7c478bd9Sstevel@tonic-gate 	meta_object_t *tmp_meta_obj = NULL;
1149*7c478bd9Sstevel@tonic-gate 	slot_object_t *tmp_slot_obj = NULL;
1150*7c478bd9Sstevel@tonic-gate 	CK_OBJECT_CLASS obj_class;
1151*7c478bd9Sstevel@tonic-gate 	CK_KEY_TYPE key_type;
1152*7c478bd9Sstevel@tonic-gate 	meta_session_t *tmp_meta_session = NULL;
1153*7c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE unwrap_template[4];
1154*7c478bd9Sstevel@tonic-gate 	char key_data[1024]; /* should be big enough for any key size */
1155*7c478bd9Sstevel@tonic-gate 	char ivbuf[1024]; /* should be big enough for any mech */
1156*7c478bd9Sstevel@tonic-gate 	wrap_info_t wrap_info;
1157*7c478bd9Sstevel@tonic-gate 	CK_ULONG key_len, unwrap_template_size;
1158*7c478bd9Sstevel@tonic-gate 
1159*7c478bd9Sstevel@tonic-gate 	slot_object = object->clones[object->master_clone_slotnum];
1160*7c478bd9Sstevel@tonic-gate 
1161*7c478bd9Sstevel@tonic-gate 	rv = meta_get_slot_session(object->master_clone_slotnum,
1162*7c478bd9Sstevel@tonic-gate 	    &src_slot_session, object->creator_session->session_flags);
1163*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1164*7c478bd9Sstevel@tonic-gate 		return (rv);
1165*7c478bd9Sstevel@tonic-gate 	}
1166*7c478bd9Sstevel@tonic-gate 
1167*7c478bd9Sstevel@tonic-gate 	/*
1168*7c478bd9Sstevel@tonic-gate 	 * get the object class and key type for unwrap template
1169*7c478bd9Sstevel@tonic-gate 	 * This information will also be used for determining
1170*7c478bd9Sstevel@tonic-gate 	 * which wrap mechanism and which key to use for
1171*7c478bd9Sstevel@tonic-gate 	 * doing the wrapping
1172*7c478bd9Sstevel@tonic-gate 	 */
1173*7c478bd9Sstevel@tonic-gate 	unwrap_template[0].type = CKA_CLASS;
1174*7c478bd9Sstevel@tonic-gate 	unwrap_template[0].pValue = &obj_class;
1175*7c478bd9Sstevel@tonic-gate 	unwrap_template[0].ulValueLen = sizeof (obj_class);
1176*7c478bd9Sstevel@tonic-gate 
1177*7c478bd9Sstevel@tonic-gate 	unwrap_template[1].type = CKA_KEY_TYPE;
1178*7c478bd9Sstevel@tonic-gate 	unwrap_template[1].pValue = &key_type;
1179*7c478bd9Sstevel@tonic-gate 	unwrap_template[1].ulValueLen = sizeof (key_type);
1180*7c478bd9Sstevel@tonic-gate 
1181*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_GetAttributeValue(
1182*7c478bd9Sstevel@tonic-gate 	    src_slot_session->hSession, slot_object->hObject,
1183*7c478bd9Sstevel@tonic-gate 	    unwrap_template, 2);
1184*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1185*7c478bd9Sstevel@tonic-gate 		goto finish;
1186*7c478bd9Sstevel@tonic-gate 	}
1187*7c478bd9Sstevel@tonic-gate 
1188*7c478bd9Sstevel@tonic-gate 	rv = get_wrap_mechanism(obj_class, key_type, src_slot_session->slotnum,
1189*7c478bd9Sstevel@tonic-gate 	    dst_slot_session->slotnum, &wrap_info);
1190*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1191*7c478bd9Sstevel@tonic-gate 		goto finish;
1192*7c478bd9Sstevel@tonic-gate 	}
1193*7c478bd9Sstevel@tonic-gate 
1194*7c478bd9Sstevel@tonic-gate 	/*
1195*7c478bd9Sstevel@tonic-gate 	 * open the random device and read number of bytes required for
1196*7c478bd9Sstevel@tonic-gate 	 * creating a secret key for wrapping and unwrapping
1197*7c478bd9Sstevel@tonic-gate 	 */
1198*7c478bd9Sstevel@tonic-gate 	if (wrap_info.class == CKO_SECRET_KEY) {
1199*7c478bd9Sstevel@tonic-gate 
1200*7c478bd9Sstevel@tonic-gate 		/*
1201*7c478bd9Sstevel@tonic-gate 		 * /dev/urandom will be used for generating the key used
1202*7c478bd9Sstevel@tonic-gate 		 * for doing the wrap/unwrap.  It's should be ok to
1203*7c478bd9Sstevel@tonic-gate 		 * use /dev/urandom because this key is used for this
1204*7c478bd9Sstevel@tonic-gate 		 * one time operation only.  It doesn't need to be stored.
1205*7c478bd9Sstevel@tonic-gate 		 */
1206*7c478bd9Sstevel@tonic-gate 		int fd;
1207*7c478bd9Sstevel@tonic-gate 
1208*7c478bd9Sstevel@tonic-gate 		while ((fd = open(RANDOM_DEVICE, O_RDONLY)) < 0) {
1209*7c478bd9Sstevel@tonic-gate 			if (errno != EINTR)
1210*7c478bd9Sstevel@tonic-gate 				break;
1211*7c478bd9Sstevel@tonic-gate 		}
1212*7c478bd9Sstevel@tonic-gate 		if (fd == -1) {
1213*7c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
1214*7c478bd9Sstevel@tonic-gate 			goto finish;
1215*7c478bd9Sstevel@tonic-gate 		}
1216*7c478bd9Sstevel@tonic-gate 		key_len = wrap_info.key_length;
1217*7c478bd9Sstevel@tonic-gate 
1218*7c478bd9Sstevel@tonic-gate 		if (looping_read(fd, key_data, key_len) != key_len) {
1219*7c478bd9Sstevel@tonic-gate 			rv = CKR_FUNCTION_FAILED;
1220*7c478bd9Sstevel@tonic-gate 			goto finish;
1221*7c478bd9Sstevel@tonic-gate 		}
1222*7c478bd9Sstevel@tonic-gate 
1223*7c478bd9Sstevel@tonic-gate 		if (wrap_info.iv_length > 0) {
1224*7c478bd9Sstevel@tonic-gate 			if (looping_read(fd, ivbuf, wrap_info.iv_length)
1225*7c478bd9Sstevel@tonic-gate 			    != wrap_info.iv_length) {
1226*7c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
1227*7c478bd9Sstevel@tonic-gate 				goto finish;
1228*7c478bd9Sstevel@tonic-gate 			}
1229*7c478bd9Sstevel@tonic-gate 		}
1230*7c478bd9Sstevel@tonic-gate 
1231*7c478bd9Sstevel@tonic-gate 		(void) close(fd);
1232*7c478bd9Sstevel@tonic-gate 	}
1233*7c478bd9Sstevel@tonic-gate 
1234*7c478bd9Sstevel@tonic-gate 	/* create the wrapping key */
1235*7c478bd9Sstevel@tonic-gate 	rv = create_wrap_unwrap_key(src_slot_session, &wrappingKey,
1236*7c478bd9Sstevel@tonic-gate 	    &wrap_info, key_data, key_len);
1237*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1238*7c478bd9Sstevel@tonic-gate 		goto finish;
1239*7c478bd9Sstevel@tonic-gate 	}
1240*7c478bd9Sstevel@tonic-gate 
1241*7c478bd9Sstevel@tonic-gate 	wrappingMech.mechanism = wrap_info.mech_type;
1242*7c478bd9Sstevel@tonic-gate 	wrappingMech.pParameter = ((wrap_info.iv_length > 0) ? ivbuf : NULL);
1243*7c478bd9Sstevel@tonic-gate 	wrappingMech.ulParameterLen = wrap_info.iv_length;
1244*7c478bd9Sstevel@tonic-gate 
1245*7c478bd9Sstevel@tonic-gate 	/* get the size of the wrapped key */
1246*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
1247*7c478bd9Sstevel@tonic-gate 	    src_slot_session->hSession, &wrappingMech,
1248*7c478bd9Sstevel@tonic-gate 	    wrappingKey, slot_object->hObject, NULL, &wrappedKeyLen);
1249*7c478bd9Sstevel@tonic-gate 
1250*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1251*7c478bd9Sstevel@tonic-gate 		goto finish;
1252*7c478bd9Sstevel@tonic-gate 	}
1253*7c478bd9Sstevel@tonic-gate 
1254*7c478bd9Sstevel@tonic-gate 	wrappedKey = malloc(wrappedKeyLen * sizeof (CK_BYTE));
1255*7c478bd9Sstevel@tonic-gate 	if (wrappedKey == NULL) {
1256*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
1257*7c478bd9Sstevel@tonic-gate 		goto finish;
1258*7c478bd9Sstevel@tonic-gate 	}
1259*7c478bd9Sstevel@tonic-gate 
1260*7c478bd9Sstevel@tonic-gate 	/* do the actual key wrapping */
1261*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
1262*7c478bd9Sstevel@tonic-gate 	    src_slot_session->hSession, &wrappingMech,
1263*7c478bd9Sstevel@tonic-gate 	    wrappingKey, slot_object->hObject, wrappedKey, &wrappedKeyLen);
1264*7c478bd9Sstevel@tonic-gate 
1265*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1266*7c478bd9Sstevel@tonic-gate 		goto finish;
1267*7c478bd9Sstevel@tonic-gate 	}
1268*7c478bd9Sstevel@tonic-gate 
1269*7c478bd9Sstevel@tonic-gate 	/* explicitly force the unwrapped object to be not sensitive */
1270*7c478bd9Sstevel@tonic-gate 	unwrap_template[2].type = CKA_SENSITIVE;
1271*7c478bd9Sstevel@tonic-gate 	unwrap_template[2].pValue = &falsevalue;
1272*7c478bd9Sstevel@tonic-gate 	unwrap_template[2].ulValueLen = sizeof (falsevalue);
1273*7c478bd9Sstevel@tonic-gate 
1274*7c478bd9Sstevel@tonic-gate 	unwrap_template[3].type = CKA_TOKEN;
1275*7c478bd9Sstevel@tonic-gate 	unwrap_template[3].pValue = &falsevalue;
1276*7c478bd9Sstevel@tonic-gate 	unwrap_template[3].ulValueLen = sizeof (falsevalue);
1277*7c478bd9Sstevel@tonic-gate 
1278*7c478bd9Sstevel@tonic-gate 	unwrap_template_size =
1279*7c478bd9Sstevel@tonic-gate 	    sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE);
1280*7c478bd9Sstevel@tonic-gate 
1281*7c478bd9Sstevel@tonic-gate 	if (!wrap_info.dst_supports) {
1282*7c478bd9Sstevel@tonic-gate 		/*
1283*7c478bd9Sstevel@tonic-gate 		 * if we know for sure that the destination slot doesn't
1284*7c478bd9Sstevel@tonic-gate 		 * support the wrapping mechanism, no point in trying.
1285*7c478bd9Sstevel@tonic-gate 		 * go directly to unwrap in source slot, and create key
1286*7c478bd9Sstevel@tonic-gate 		 * in destination
1287*7c478bd9Sstevel@tonic-gate 		 */
1288*7c478bd9Sstevel@tonic-gate 		goto unwrap_in_source;
1289*7c478bd9Sstevel@tonic-gate 	}
1290*7c478bd9Sstevel@tonic-gate 
1291*7c478bd9Sstevel@tonic-gate 	/* create the unwrapping key in destination slot */
1292*7c478bd9Sstevel@tonic-gate 	if (wrap_info.key_type == CKK_RSA) {
1293*7c478bd9Sstevel@tonic-gate 		/* for RSA key, the unwrapping key need to be private key */
1294*7c478bd9Sstevel@tonic-gate 		wrap_info.class = CKO_PRIVATE_KEY;
1295*7c478bd9Sstevel@tonic-gate 	}
1296*7c478bd9Sstevel@tonic-gate 	rv = create_wrap_unwrap_key(dst_slot_session,
1297*7c478bd9Sstevel@tonic-gate 	    &unwrappingKey, &wrap_info, key_data, key_len);
1298*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1299*7c478bd9Sstevel@tonic-gate 		goto finish;
1300*7c478bd9Sstevel@tonic-gate 	}
1301*7c478bd9Sstevel@tonic-gate 
1302*7c478bd9Sstevel@tonic-gate 	rv = FUNCLIST(dst_slot_session->fw_st_id)->C_UnwrapKey(
1303*7c478bd9Sstevel@tonic-gate 	    dst_slot_session->hSession, &wrappingMech,
1304*7c478bd9Sstevel@tonic-gate 	    unwrappingKey, wrappedKey, wrappedKeyLen, unwrap_template,
1305*7c478bd9Sstevel@tonic-gate 	    unwrap_template_size, &(new_clone->hObject));
1306*7c478bd9Sstevel@tonic-gate 
1307*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1308*7c478bd9Sstevel@tonic-gate unwrap_in_source:
1309*7c478bd9Sstevel@tonic-gate 
1310*7c478bd9Sstevel@tonic-gate 		/*
1311*7c478bd9Sstevel@tonic-gate 		 * There seemed to be a problem with unwrapping in the
1312*7c478bd9Sstevel@tonic-gate 		 * destination slot.
1313*7c478bd9Sstevel@tonic-gate 		 * Try to do the unwrap in the src slot so it becomes
1314*7c478bd9Sstevel@tonic-gate 		 * a non-sensitive object, then, get all the attributes
1315*7c478bd9Sstevel@tonic-gate 		 * and create the object in the destination slot
1316*7c478bd9Sstevel@tonic-gate 		 */
1317*7c478bd9Sstevel@tonic-gate 
1318*7c478bd9Sstevel@tonic-gate 
1319*7c478bd9Sstevel@tonic-gate 		if (wrap_info.class == CKO_SECRET_KEY) {
1320*7c478bd9Sstevel@tonic-gate 			/* unwrap with same key used for wrapping */
1321*7c478bd9Sstevel@tonic-gate 			rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
1322*7c478bd9Sstevel@tonic-gate 			    src_slot_session->hSession,
1323*7c478bd9Sstevel@tonic-gate 			    &wrappingMech, wrappingKey, wrappedKey,
1324*7c478bd9Sstevel@tonic-gate 			    wrappedKeyLen, unwrap_template,
1325*7c478bd9Sstevel@tonic-gate 			    unwrap_template_size, &(unwrapped_obj));
1326*7c478bd9Sstevel@tonic-gate 		} else {
1327*7c478bd9Sstevel@tonic-gate 			/*
1328*7c478bd9Sstevel@tonic-gate 			 * If the object is wrapping with RSA public key, need
1329*7c478bd9Sstevel@tonic-gate 			 * need to create RSA private key for unwrapping
1330*7c478bd9Sstevel@tonic-gate 			 */
1331*7c478bd9Sstevel@tonic-gate 			wrap_info.class = CKO_PRIVATE_KEY;
1332*7c478bd9Sstevel@tonic-gate 			rv = create_wrap_unwrap_key(src_slot_session,
1333*7c478bd9Sstevel@tonic-gate 			    &unwrappingKey, &wrap_info, key_data, key_len);
1334*7c478bd9Sstevel@tonic-gate 			if (rv != CKR_OK) {
1335*7c478bd9Sstevel@tonic-gate 				goto finish;
1336*7c478bd9Sstevel@tonic-gate 			}
1337*7c478bd9Sstevel@tonic-gate 			rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
1338*7c478bd9Sstevel@tonic-gate 			    src_slot_session->hSession,
1339*7c478bd9Sstevel@tonic-gate 			    &wrappingMech, unwrappingKey, wrappedKey,
1340*7c478bd9Sstevel@tonic-gate 			    wrappedKeyLen, unwrap_template,
1341*7c478bd9Sstevel@tonic-gate 			    unwrap_template_size, &(unwrapped_obj));
1342*7c478bd9Sstevel@tonic-gate 		}
1343*7c478bd9Sstevel@tonic-gate 
1344*7c478bd9Sstevel@tonic-gate 
1345*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1346*7c478bd9Sstevel@tonic-gate 			goto finish;
1347*7c478bd9Sstevel@tonic-gate 		}
1348*7c478bd9Sstevel@tonic-gate 
1349*7c478bd9Sstevel@tonic-gate 		rv = meta_session_alloc(&tmp_meta_session);
1350*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1351*7c478bd9Sstevel@tonic-gate 			goto finish;
1352*7c478bd9Sstevel@tonic-gate 		}
1353*7c478bd9Sstevel@tonic-gate 
1354*7c478bd9Sstevel@tonic-gate 		tmp_meta_session->session_flags = CKF_SERIAL_SESSION;
1355*7c478bd9Sstevel@tonic-gate 
1356*7c478bd9Sstevel@tonic-gate 		rv = meta_object_alloc(tmp_meta_session, &tmp_meta_obj);
1357*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1358*7c478bd9Sstevel@tonic-gate 			goto finish;
1359*7c478bd9Sstevel@tonic-gate 		}
1360*7c478bd9Sstevel@tonic-gate 
1361*7c478bd9Sstevel@tonic-gate 		rv = meta_slot_object_alloc(&tmp_slot_obj);
1362*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1363*7c478bd9Sstevel@tonic-gate 			goto finish;
1364*7c478bd9Sstevel@tonic-gate 		}
1365*7c478bd9Sstevel@tonic-gate 
1366*7c478bd9Sstevel@tonic-gate 		tmp_meta_obj->master_clone_slotnum = src_slot_session->slotnum;
1367*7c478bd9Sstevel@tonic-gate 		tmp_slot_obj->hObject = unwrapped_obj;
1368*7c478bd9Sstevel@tonic-gate 		tmp_meta_obj->clones[tmp_meta_obj->master_clone_slotnum]
1369*7c478bd9Sstevel@tonic-gate 		    = tmp_slot_obj;
1370*7c478bd9Sstevel@tonic-gate 		meta_slot_object_activate(tmp_slot_obj, src_slot_session,
1371*7c478bd9Sstevel@tonic-gate 		    B_FALSE);
1372*7c478bd9Sstevel@tonic-gate 		tmp_slot_obj = NULL;
1373*7c478bd9Sstevel@tonic-gate 
1374*7c478bd9Sstevel@tonic-gate 		rv = clone_by_create(tmp_meta_obj, new_clone,
1375*7c478bd9Sstevel@tonic-gate 		    dst_slot_session);
1376*7c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK) {
1377*7c478bd9Sstevel@tonic-gate 			goto finish;
1378*7c478bd9Sstevel@tonic-gate 		}
1379*7c478bd9Sstevel@tonic-gate 	}
1380*7c478bd9Sstevel@tonic-gate 
1381*7c478bd9Sstevel@tonic-gate finish:
1382*7c478bd9Sstevel@tonic-gate 	if (unwrappingKey) {
1383*7c478bd9Sstevel@tonic-gate 		(void) FUNCLIST(dst_slot_session->fw_st_id)->C_DestroyObject(
1384*7c478bd9Sstevel@tonic-gate 		    dst_slot_session->hSession, unwrappingKey);
1385*7c478bd9Sstevel@tonic-gate 	}
1386*7c478bd9Sstevel@tonic-gate 
1387*7c478bd9Sstevel@tonic-gate 	if (wrappingKey) {
1388*7c478bd9Sstevel@tonic-gate 		(void) FUNCLIST(src_slot_session->fw_st_id)->C_DestroyObject(
1389*7c478bd9Sstevel@tonic-gate 		    src_slot_session->hSession, wrappingKey);
1390*7c478bd9Sstevel@tonic-gate 	}
1391*7c478bd9Sstevel@tonic-gate 
1392*7c478bd9Sstevel@tonic-gate 	if (tmp_slot_obj) {
1393*7c478bd9Sstevel@tonic-gate 		(void) meta_slot_object_dealloc(tmp_slot_obj);
1394*7c478bd9Sstevel@tonic-gate 	}
1395*7c478bd9Sstevel@tonic-gate 
1396*7c478bd9Sstevel@tonic-gate 	if (tmp_meta_obj) {
1397*7c478bd9Sstevel@tonic-gate 		(void) meta_object_dealloc(tmp_meta_obj, B_TRUE);
1398*7c478bd9Sstevel@tonic-gate 	}
1399*7c478bd9Sstevel@tonic-gate 
1400*7c478bd9Sstevel@tonic-gate 	if (tmp_meta_session) {
1401*7c478bd9Sstevel@tonic-gate 		(void) meta_session_dealloc(tmp_meta_session);
1402*7c478bd9Sstevel@tonic-gate 	}
1403*7c478bd9Sstevel@tonic-gate 
1404*7c478bd9Sstevel@tonic-gate 	if (wrappedKey) {
1405*7c478bd9Sstevel@tonic-gate 		free(wrappedKey);
1406*7c478bd9Sstevel@tonic-gate 	}
1407*7c478bd9Sstevel@tonic-gate 
1408*7c478bd9Sstevel@tonic-gate 	if (src_slot_session) {
1409*7c478bd9Sstevel@tonic-gate 		meta_release_slot_session(src_slot_session);
1410*7c478bd9Sstevel@tonic-gate 	}
1411*7c478bd9Sstevel@tonic-gate 
1412*7c478bd9Sstevel@tonic-gate 	return (rv);
1413*7c478bd9Sstevel@tonic-gate 
1414*7c478bd9Sstevel@tonic-gate }
1415*7c478bd9Sstevel@tonic-gate 
1416*7c478bd9Sstevel@tonic-gate 
1417*7c478bd9Sstevel@tonic-gate /*
1418*7c478bd9Sstevel@tonic-gate  * meta_object_get_clone
1419*7c478bd9Sstevel@tonic-gate  *
1420*7c478bd9Sstevel@tonic-gate  * Creates a "clone" of a metaobject on the specified slot. A clone is a
1421*7c478bd9Sstevel@tonic-gate  * copy of the object.
1422*7c478bd9Sstevel@tonic-gate  *
1423*7c478bd9Sstevel@tonic-gate  * Clones are cached, so that they can be reused with subsquent operations.
1424*7c478bd9Sstevel@tonic-gate  */
1425*7c478bd9Sstevel@tonic-gate CK_RV
1426*7c478bd9Sstevel@tonic-gate meta_object_get_clone(meta_object_t *object,
1427*7c478bd9Sstevel@tonic-gate 	CK_ULONG slot_num, slot_session_t *slot_session,
1428*7c478bd9Sstevel@tonic-gate 	slot_object_t **clone)
1429*7c478bd9Sstevel@tonic-gate {
1430*7c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1431*7c478bd9Sstevel@tonic-gate 	slot_object_t *newclone = NULL;
1432*7c478bd9Sstevel@tonic-gate 
1433*7c478bd9Sstevel@tonic-gate 	/* Does a clone already exist? */
1434*7c478bd9Sstevel@tonic-gate 	if (object->clones[slot_num] != NULL) {
1435*7c478bd9Sstevel@tonic-gate 		*clone = object->clones[slot_num];
1436*7c478bd9Sstevel@tonic-gate 		return (CKR_OK);
1437*7c478bd9Sstevel@tonic-gate 	}
1438*7c478bd9Sstevel@tonic-gate 
1439*7c478bd9Sstevel@tonic-gate 	if ((object->isSensitive) && (object->isToken) &&
1440*7c478bd9Sstevel@tonic-gate 	    (!metaslot_auto_key_migrate)) {
1441*7c478bd9Sstevel@tonic-gate 		/*
1442*7c478bd9Sstevel@tonic-gate 		 * if the object is a sensitive token object, and auto
1443*7c478bd9Sstevel@tonic-gate 		 * key migrate is not allowed, will not create the clone
1444*7c478bd9Sstevel@tonic-gate 		 * in another slot
1445*7c478bd9Sstevel@tonic-gate 		 */
1446*7c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
1447*7c478bd9Sstevel@tonic-gate 	}
1448*7c478bd9Sstevel@tonic-gate 
1449*7c478bd9Sstevel@tonic-gate 	/* object attributes can't be extracted and attributes are not known */
1450*7c478bd9Sstevel@tonic-gate 	if ((!object->isExtractable) && (object->attributes == NULL)) {
1451*7c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
1452*7c478bd9Sstevel@tonic-gate 	}
1453*7c478bd9Sstevel@tonic-gate 
1454*7c478bd9Sstevel@tonic-gate 	/*
1455*7c478bd9Sstevel@tonic-gate 	 * has an attempt already been made to create this object in
1456*7c478bd9Sstevel@tonic-gate 	 * slot?  If yes, and there's no clone, as indicated above,
1457*7c478bd9Sstevel@tonic-gate 	 * that means this object can't be created in this slot.
1458*7c478bd9Sstevel@tonic-gate 	 */
1459*7c478bd9Sstevel@tonic-gate 	if (object->tried_create_clone[slot_num]) {
1460*7c478bd9Sstevel@tonic-gate 		return (CKR_FUNCTION_FAILED);
1461*7c478bd9Sstevel@tonic-gate 	}
1462*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&object->clone_create_lock);
1463*7c478bd9Sstevel@tonic-gate 
1464*7c478bd9Sstevel@tonic-gate 	/* Maybe someone just created one? */
1465*7c478bd9Sstevel@tonic-gate 	if (object->clones[slot_num] != NULL) {
1466*7c478bd9Sstevel@tonic-gate 		*clone = object->clones[slot_num];
1467*7c478bd9Sstevel@tonic-gate 		goto finish;
1468*7c478bd9Sstevel@tonic-gate 	}
1469*7c478bd9Sstevel@tonic-gate 
1470*7c478bd9Sstevel@tonic-gate 
1471*7c478bd9Sstevel@tonic-gate 	rv = meta_slot_object_alloc(&newclone);
1472*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK)
1473*7c478bd9Sstevel@tonic-gate 		goto finish;
1474*7c478bd9Sstevel@tonic-gate 
1475*7c478bd9Sstevel@tonic-gate 	object->tried_create_clone[slot_num] = B_TRUE;
1476*7c478bd9Sstevel@tonic-gate 
1477*7c478bd9Sstevel@tonic-gate 	if (object->isSensitive) {
1478*7c478bd9Sstevel@tonic-gate 		rv = clone_by_wrap(object, newclone, slot_session);
1479*7c478bd9Sstevel@tonic-gate 	} else {
1480*7c478bd9Sstevel@tonic-gate 		rv = clone_by_create(object, newclone, slot_session);
1481*7c478bd9Sstevel@tonic-gate 	}
1482*7c478bd9Sstevel@tonic-gate 
1483*7c478bd9Sstevel@tonic-gate 	if (rv != CKR_OK) {
1484*7c478bd9Sstevel@tonic-gate 		goto finish;
1485*7c478bd9Sstevel@tonic-gate 	}
1486*7c478bd9Sstevel@tonic-gate 
1487*7c478bd9Sstevel@tonic-gate 	object->clones[slot_num] = newclone;
1488*7c478bd9Sstevel@tonic-gate 	meta_slot_object_activate(newclone, slot_session, object->isToken);
1489*7c478bd9Sstevel@tonic-gate 
1490*7c478bd9Sstevel@tonic-gate 	*clone = newclone;
1491*7c478bd9Sstevel@tonic-gate 	newclone = NULL;
1492*7c478bd9Sstevel@tonic-gate finish:
1493*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&object->clone_create_lock);
1494*7c478bd9Sstevel@tonic-gate 
1495*7c478bd9Sstevel@tonic-gate 	if (newclone)
1496*7c478bd9Sstevel@tonic-gate 		meta_slot_object_dealloc(newclone);
1497*7c478bd9Sstevel@tonic-gate 
1498*7c478bd9Sstevel@tonic-gate 	return (rv);
1499*7c478bd9Sstevel@tonic-gate }
1500*7c478bd9Sstevel@tonic-gate 
1501*7c478bd9Sstevel@tonic-gate 
1502*7c478bd9Sstevel@tonic-gate /*
1503*7c478bd9Sstevel@tonic-gate  * meta_setup_clone_template
1504*7c478bd9Sstevel@tonic-gate  *
1505*7c478bd9Sstevel@tonic-gate  * Create a clone template for the specified object.
1506*7c478bd9Sstevel@tonic-gate  */
1507*7c478bd9Sstevel@tonic-gate static CK_RV
1508*7c478bd9Sstevel@tonic-gate meta_clone_template_setup(meta_object_t *object,
1509*7c478bd9Sstevel@tonic-gate     const generic_attr_t *attributes, size_t num_attributes)
1510*7c478bd9Sstevel@tonic-gate {
1511*7c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1512*7c478bd9Sstevel@tonic-gate 	CK_ATTRIBUTE *clone_template;
1513*7c478bd9Sstevel@tonic-gate 	size_t i, c = 0;
1514*7c478bd9Sstevel@tonic-gate 
1515*7c478bd9Sstevel@tonic-gate 	clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE));
1516*7c478bd9Sstevel@tonic-gate 	if (clone_template == NULL) {
1517*7c478bd9Sstevel@tonic-gate 		rv = CKR_HOST_MEMORY;
1518*7c478bd9Sstevel@tonic-gate 		goto finish;
1519*7c478bd9Sstevel@tonic-gate 	}
1520*7c478bd9Sstevel@tonic-gate 
1521*7c478bd9Sstevel@tonic-gate 	/* Don't allow attributes to change while we look at them. */
1522*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&object->attribute_lock);
1523*7c478bd9Sstevel@tonic-gate 
1524*7c478bd9Sstevel@tonic-gate 	for (i = 0; i < num_attributes; i++) {
1525*7c478bd9Sstevel@tonic-gate 		if (!attributes[i].isCloneAttr) {
1526*7c478bd9Sstevel@tonic-gate 			continue;
1527*7c478bd9Sstevel@tonic-gate 		}
1528*7c478bd9Sstevel@tonic-gate 		if ((!(attributes[i].hasValueForClone)) &&
1529*7c478bd9Sstevel@tonic-gate 		    (attributes[i].canBeEmptyValue)) {
1530*7c478bd9Sstevel@tonic-gate 			continue;
1531*7c478bd9Sstevel@tonic-gate 		}
1532*7c478bd9Sstevel@tonic-gate 
1533*7c478bd9Sstevel@tonic-gate 		clone_template[c].type = attributes[i].attribute.type;
1534*7c478bd9Sstevel@tonic-gate 		clone_template[c].ulValueLen =
1535*7c478bd9Sstevel@tonic-gate 				attributes[i].attribute.ulValueLen;
1536*7c478bd9Sstevel@tonic-gate 		/* Allocate space to store the attribute value. */
1537*7c478bd9Sstevel@tonic-gate 		clone_template[c].pValue = malloc(clone_template[c].ulValueLen);
1538*7c478bd9Sstevel@tonic-gate 		if (clone_template[c].pValue == NULL) {
1539*7c478bd9Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
1540*7c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(&object->attribute_lock);
1541*7c478bd9Sstevel@tonic-gate 			goto finish;
1542*7c478bd9Sstevel@tonic-gate 		}
1543*7c478bd9Sstevel@tonic-gate 
1544*7c478bd9Sstevel@tonic-gate 		(void) memcpy(clone_template[c].pValue,
1545*7c478bd9Sstevel@tonic-gate 		    object->attributes[i].attribute.pValue,
1546*7c478bd9Sstevel@tonic-gate 		    clone_template[c].ulValueLen);
1547*7c478bd9Sstevel@tonic-gate 		c++;
1548*7c478bd9Sstevel@tonic-gate 	}
1549*7c478bd9Sstevel@tonic-gate 
1550*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&object->attribute_lock);
1551*7c478bd9Sstevel@tonic-gate 
1552*7c478bd9Sstevel@tonic-gate 	object->clone_template = clone_template;
1553*7c478bd9Sstevel@tonic-gate 	object->clone_template_size = c;
1554*7c478bd9Sstevel@tonic-gate 
1555*7c478bd9Sstevel@tonic-gate finish:
1556*7c478bd9Sstevel@tonic-gate 	return (rv);
1557*7c478bd9Sstevel@tonic-gate }
1558*7c478bd9Sstevel@tonic-gate 
1559*7c478bd9Sstevel@tonic-gate 
1560*7c478bd9Sstevel@tonic-gate /*
1561*7c478bd9Sstevel@tonic-gate  * meta_object_find_by_handle
1562*7c478bd9Sstevel@tonic-gate  *
1563*7c478bd9Sstevel@tonic-gate  * Search for an existing metaobject, using the object handle of a clone
1564*7c478bd9Sstevel@tonic-gate  * on a particular slot.
1565*7c478bd9Sstevel@tonic-gate  *
1566*7c478bd9Sstevel@tonic-gate  * Returns a matching metaobject, or NULL if no match was found.
1567*7c478bd9Sstevel@tonic-gate  */
1568*7c478bd9Sstevel@tonic-gate meta_object_t *
1569*7c478bd9Sstevel@tonic-gate meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum,
1570*7c478bd9Sstevel@tonic-gate     boolean_t token_only)
1571*7c478bd9Sstevel@tonic-gate {
1572*7c478bd9Sstevel@tonic-gate 	meta_object_t *object = NULL, *tmp_obj;
1573*7c478bd9Sstevel@tonic-gate 	meta_session_t *session;
1574*7c478bd9Sstevel@tonic-gate 
1575*7c478bd9Sstevel@tonic-gate 	if (!token_only) {
1576*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&meta_sessionlist_lock);
1577*7c478bd9Sstevel@tonic-gate 		session = meta_sessionlist_head;
1578*7c478bd9Sstevel@tonic-gate 		while (session != NULL) {
1579*7c478bd9Sstevel@tonic-gate 			/* lock the objects list while we look at it */
1580*7c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_rdlock(
1581*7c478bd9Sstevel@tonic-gate 			    &(session->object_list_lock));
1582*7c478bd9Sstevel@tonic-gate 			tmp_obj = session->object_list_head;
1583*7c478bd9Sstevel@tonic-gate 			while (tmp_obj != NULL) {
1584*7c478bd9Sstevel@tonic-gate 				slot_object_t *slot_object;
1585*7c478bd9Sstevel@tonic-gate 
1586*7c478bd9Sstevel@tonic-gate 				(void) pthread_rwlock_rdlock(
1587*7c478bd9Sstevel@tonic-gate 				    &(tmp_obj->object_lock));
1588*7c478bd9Sstevel@tonic-gate 				slot_object = tmp_obj->clones[slotnum];
1589*7c478bd9Sstevel@tonic-gate 				if (slot_object != NULL) {
1590*7c478bd9Sstevel@tonic-gate 					if (slot_object->hObject == hObject) {
1591*7c478bd9Sstevel@tonic-gate 						object = tmp_obj;
1592*7c478bd9Sstevel@tonic-gate 					}
1593*7c478bd9Sstevel@tonic-gate 				}
1594*7c478bd9Sstevel@tonic-gate 				(void) pthread_rwlock_unlock(
1595*7c478bd9Sstevel@tonic-gate 				    &(tmp_obj->object_lock));
1596*7c478bd9Sstevel@tonic-gate 				if (object != NULL) {
1597*7c478bd9Sstevel@tonic-gate 					break;
1598*7c478bd9Sstevel@tonic-gate 				}
1599*7c478bd9Sstevel@tonic-gate 				tmp_obj = tmp_obj->next;
1600*7c478bd9Sstevel@tonic-gate 			}
1601*7c478bd9Sstevel@tonic-gate 			(void) pthread_rwlock_unlock(
1602*7c478bd9Sstevel@tonic-gate 			    &(session->object_list_lock));
1603*7c478bd9Sstevel@tonic-gate 			if (object != NULL) {
1604*7c478bd9Sstevel@tonic-gate 				break;
1605*7c478bd9Sstevel@tonic-gate 			}
1606*7c478bd9Sstevel@tonic-gate 			session = session->next;
1607*7c478bd9Sstevel@tonic-gate 		}
1608*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&meta_sessionlist_lock);
1609*7c478bd9Sstevel@tonic-gate 	}
1610*7c478bd9Sstevel@tonic-gate 
1611*7c478bd9Sstevel@tonic-gate 	if (object != NULL) {
1612*7c478bd9Sstevel@tonic-gate 		/* found the object, no need to look further */
1613*7c478bd9Sstevel@tonic-gate 		return (object);
1614*7c478bd9Sstevel@tonic-gate 	}
1615*7c478bd9Sstevel@tonic-gate 
1616*7c478bd9Sstevel@tonic-gate 	/*
1617*7c478bd9Sstevel@tonic-gate 	 * Look at list of token objects
1618*7c478bd9Sstevel@tonic-gate 	 */
1619*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_rdlock(&tokenobject_list_lock);
1620*7c478bd9Sstevel@tonic-gate 	tmp_obj = tokenobject_list_head;
1621*7c478bd9Sstevel@tonic-gate 
1622*7c478bd9Sstevel@tonic-gate 	while (tmp_obj != NULL) {
1623*7c478bd9Sstevel@tonic-gate 		slot_object_t *slot_object;
1624*7c478bd9Sstevel@tonic-gate 
1625*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_rdlock(&(tmp_obj->object_lock));
1626*7c478bd9Sstevel@tonic-gate 		slot_object = tmp_obj->clones[slotnum];
1627*7c478bd9Sstevel@tonic-gate 		if (slot_object != NULL) {
1628*7c478bd9Sstevel@tonic-gate 			if (slot_object->hObject == hObject)
1629*7c478bd9Sstevel@tonic-gate 				object = tmp_obj;
1630*7c478bd9Sstevel@tonic-gate 		}
1631*7c478bd9Sstevel@tonic-gate 		(void) pthread_rwlock_unlock(&(tmp_obj->object_lock));
1632*7c478bd9Sstevel@tonic-gate 		if (object != NULL) {
1633*7c478bd9Sstevel@tonic-gate 			break;
1634*7c478bd9Sstevel@tonic-gate 		}
1635*7c478bd9Sstevel@tonic-gate 		tmp_obj = tmp_obj->next;
1636*7c478bd9Sstevel@tonic-gate 	}
1637*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&tokenobject_list_lock);
1638*7c478bd9Sstevel@tonic-gate 
1639*7c478bd9Sstevel@tonic-gate 	return (object);
1640*7c478bd9Sstevel@tonic-gate }
1641*7c478bd9Sstevel@tonic-gate 
1642*7c478bd9Sstevel@tonic-gate CK_RV
1643*7c478bd9Sstevel@tonic-gate meta_token_object_deactivate(token_obj_type_t token_type)
1644*7c478bd9Sstevel@tonic-gate {
1645*7c478bd9Sstevel@tonic-gate 	meta_object_t *object, *tmp_object;
1646*7c478bd9Sstevel@tonic-gate 	CK_RV save_rv = CKR_OK, rv;
1647*7c478bd9Sstevel@tonic-gate 
1648*7c478bd9Sstevel@tonic-gate 	/* get a write lock on the token object list */
1649*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_wrlock(&tokenobject_list_lock);
1650*7c478bd9Sstevel@tonic-gate 
1651*7c478bd9Sstevel@tonic-gate 	object = tokenobject_list_head;
1652*7c478bd9Sstevel@tonic-gate 
1653*7c478bd9Sstevel@tonic-gate 	/* go through each object and delete the one with matching type */
1654*7c478bd9Sstevel@tonic-gate 	while (object != NULL) {
1655*7c478bd9Sstevel@tonic-gate 		tmp_object = object->next;
1656*7c478bd9Sstevel@tonic-gate 
1657*7c478bd9Sstevel@tonic-gate 		if ((token_type == ALL_TOKEN) ||
1658*7c478bd9Sstevel@tonic-gate 		    ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) ||
1659*7c478bd9Sstevel@tonic-gate 		    ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) {
1660*7c478bd9Sstevel@tonic-gate 			rv = meta_object_deactivate(object, B_TRUE, B_FALSE);
1661*7c478bd9Sstevel@tonic-gate 			if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
1662*7c478bd9Sstevel@tonic-gate 				save_rv = rv;
1663*7c478bd9Sstevel@tonic-gate 				goto finish;
1664*7c478bd9Sstevel@tonic-gate 			}
1665*7c478bd9Sstevel@tonic-gate 			rv = meta_object_dealloc(object, B_FALSE);
1666*7c478bd9Sstevel@tonic-gate 			if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
1667*7c478bd9Sstevel@tonic-gate 				save_rv = rv;
1668*7c478bd9Sstevel@tonic-gate 				goto finish;
1669*7c478bd9Sstevel@tonic-gate 			}
1670*7c478bd9Sstevel@tonic-gate 		}
1671*7c478bd9Sstevel@tonic-gate 		object = tmp_object;
1672*7c478bd9Sstevel@tonic-gate 	}
1673*7c478bd9Sstevel@tonic-gate finish:
1674*7c478bd9Sstevel@tonic-gate 	(void) pthread_rwlock_unlock(&tokenobject_list_lock);
1675*7c478bd9Sstevel@tonic-gate 	return (save_rv);
1676*7c478bd9Sstevel@tonic-gate }
1677*7c478bd9Sstevel@tonic-gate 
1678*7c478bd9Sstevel@tonic-gate /*
1679*7c478bd9Sstevel@tonic-gate  * This function adds the to-be-freed meta object to a linked list.
1680*7c478bd9Sstevel@tonic-gate  * When the number of objects queued in the linked list reaches the
1681*7c478bd9Sstevel@tonic-gate  * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
1682*7c478bd9Sstevel@tonic-gate  * object (FIFO) in the list.
1683*7c478bd9Sstevel@tonic-gate  */
1684*7c478bd9Sstevel@tonic-gate void
1685*7c478bd9Sstevel@tonic-gate meta_object_delay_free(meta_object_t *objp)
1686*7c478bd9Sstevel@tonic-gate {
1687*7c478bd9Sstevel@tonic-gate 	meta_object_t *tmp;
1688*7c478bd9Sstevel@tonic-gate 
1689*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
1690*7c478bd9Sstevel@tonic-gate 
1691*7c478bd9Sstevel@tonic-gate 	/* Add the newly deleted object at the end of the list */
1692*7c478bd9Sstevel@tonic-gate 	objp->next = NULL;
1693*7c478bd9Sstevel@tonic-gate 	if (obj_delay_freed.first == NULL) {
1694*7c478bd9Sstevel@tonic-gate 		obj_delay_freed.last = objp;
1695*7c478bd9Sstevel@tonic-gate 		obj_delay_freed.first = objp;
1696*7c478bd9Sstevel@tonic-gate 	} else {
1697*7c478bd9Sstevel@tonic-gate 		obj_delay_freed.last->next = objp;
1698*7c478bd9Sstevel@tonic-gate 		obj_delay_freed.last = objp;
1699*7c478bd9Sstevel@tonic-gate 	}
1700*7c478bd9Sstevel@tonic-gate 
1701*7c478bd9Sstevel@tonic-gate 	if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
1702*7c478bd9Sstevel@tonic-gate 		/*
1703*7c478bd9Sstevel@tonic-gate 		 * Free the first object in the list only if
1704*7c478bd9Sstevel@tonic-gate 		 * the total count reaches maximum threshold.
1705*7c478bd9Sstevel@tonic-gate 		 */
1706*7c478bd9Sstevel@tonic-gate 		obj_delay_freed.count--;
1707*7c478bd9Sstevel@tonic-gate 		tmp = obj_delay_freed.first->next;
1708*7c478bd9Sstevel@tonic-gate 		free(obj_delay_freed.first);
1709*7c478bd9Sstevel@tonic-gate 		obj_delay_freed.first = tmp;
1710*7c478bd9Sstevel@tonic-gate 	}
1711*7c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
1712*7c478bd9Sstevel@tonic-gate }
1713