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