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