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