xref: /titanic_41/usr/src/lib/pkcs11/libpkcs11/common/metaObjectManager.c (revision c93c462eec9d46f84d567abf52eb29a27c2e134b)
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 2009 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
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 			free(((object->clone_template)[i]).pValue);
601 		}
602 		free(object->clone_template);
603 	}
604 
605 	/* Cleanup remaining object fields. */
606 	(void) pthread_rwlock_destroy(&object->object_lock);
607 	(void) pthread_rwlock_destroy(&object->attribute_lock);
608 	(void) pthread_mutex_destroy(&object->isClosingObject_lock);
609 	(void) pthread_mutex_destroy(&object->clone_create_lock);
610 
611 	meta_object_delay_free(object);
612 
613 	return (save_rv);
614 }
615 
616 
617 /*
618  * meta_slot_object_alloc
619  */
620 CK_RV
621 meta_slot_object_alloc(slot_object_t **object) {
622 	slot_object_t *new_object;
623 
624 	new_object = calloc(1, sizeof (slot_object_t));
625 	if (new_object == NULL)
626 		return (CKR_HOST_MEMORY);
627 
628 	*object = new_object;
629 	return (CKR_OK);
630 }
631 
632 
633 /*
634  * meta_slot_object_activate
635  */
636 void
637 meta_slot_object_activate(slot_object_t *object,
638 	slot_session_t *creator_session, boolean_t isToken)
639 {
640 	object->creator_session = creator_session;
641 
642 	if (isToken) {
643 		extern slot_data_t *slots;
644 		slot_data_t *slot;
645 
646 		slot = &(slots[object->creator_session->slotnum]);
647 
648 		(void) pthread_rwlock_wrlock(&slot->tokenobject_list_lock);
649 		INSERT_INTO_LIST(slot->tokenobject_list_head, object);
650 		(void) pthread_rwlock_unlock(&slot->tokenobject_list_lock);
651 	} else {
652 		slot_session_t *session = object->creator_session;
653 
654 		/* Add to session's list of session objects. */
655 		(void) pthread_rwlock_wrlock(&session->object_list_lock);
656 		INSERT_INTO_LIST(session->object_list_head, object);
657 		(void) pthread_rwlock_unlock(&session->object_list_lock);
658 	}
659 
660 	/*
661 	 * This set tells the slot object that we are in the token list,
662 	 * but does not cause harm with the metaobject knowing the object
663 	 * isn't a token, but a freetoken
664 	 */
665 
666 	object->isToken = isToken;
667 }
668 
669 
670 /*
671  * meta_slot_object_deactivate
672  *
673  * Remove the specified slot object from the appropriate object list.
674  */
675 void
676 meta_slot_object_deactivate(slot_object_t *object)
677 {
678 	slot_object_t **list_head;
679 	pthread_rwlock_t *list_lock;
680 
681 	if (object->isToken) {
682 		extern slot_data_t *slots;
683 		slot_data_t *slot;
684 
685 		slot = &(slots[object->creator_session->slotnum]);
686 
687 		list_head = &slot->tokenobject_list_head;
688 		list_lock = &slot->tokenobject_list_lock;
689 	} else {
690 		list_head = &object->creator_session->object_list_head;
691 		list_lock = &object->creator_session->object_list_lock;
692 	}
693 
694 	(void) pthread_rwlock_wrlock(list_lock);
695 	REMOVE_FROM_LIST(*list_head, object);
696 	(void) pthread_rwlock_unlock(list_lock);
697 }
698 
699 
700 /*
701  * meta_slot_object_dealloc
702  */
703 void
704 meta_slot_object_dealloc(slot_object_t *object)
705 {
706 	/* Not much cleanup for slot objects, unlike meta objects... */
707 	free(object);
708 }
709 
710 
711 /*
712  * meta_object_copyin
713  *
714  * When a key is generated/derived/unwrapped, the attribute values
715  * created by the token are not immediately read into our copy of the
716  * attributes. We defer this work until we actually need to know.
717  */
718 CK_RV
719 meta_object_copyin(meta_object_t *object)
720 {
721 	CK_RV rv = CKR_OK;
722 	slot_session_t *session = NULL;
723 	CK_ATTRIBUTE *attrs = NULL, *attrs_with_val = NULL;
724 	slot_object_t *slot_object = NULL;
725 	CK_ULONG num_attrs = 0, i, num_attrs_with_val;
726 	CK_SESSION_HANDLE hSession;
727 	CK_SLOT_ID fw_st_id;
728 
729 	/* Make sure no one else is looking at attributes. */
730 	(void) pthread_rwlock_wrlock(&object->attribute_lock);
731 
732 	/* Did we just lose a copyin race with another thread */
733 	if (object->attributes != NULL) {
734 		goto finish;
735 	}
736 
737 	slot_object = object->clones[object->master_clone_slotnum];
738 
739 	rv = meta_get_slot_session(object->master_clone_slotnum, &session,
740 	    object->creator_session->session_flags);
741 	if (rv != CKR_OK) {
742 		goto finish;
743 	}
744 
745 	/*
746 	 * first, get the master template of all the attributes
747 	 * for this object
748 	 */
749 	rv = get_master_attributes_by_object(session, slot_object,
750 	    &(object->attributes), &(object->num_attributes));
751 	if (rv != CKR_OK) {
752 		goto finish;
753 	}
754 
755 	/*
756 	 * Get value for each attribute items.
757 	 *
758 	 * Some attributes are required by the given object type.
759 	 * Some are optional.  Get all the values first, and then
760 	 * make sure we have value for all required values,
761 	 */
762 	attrs = calloc(object->num_attributes, sizeof (CK_ATTRIBUTE));
763 	if (attrs == NULL) {
764 		rv = CKR_HOST_MEMORY;
765 		goto finish;
766 	}
767 
768 
769 	for (i = 0; i < object->num_attributes; i++) {
770 		attrs[i].type =
771 		    ((object->attributes[i]).attribute).type;
772 	}
773 	num_attrs = object->num_attributes;
774 
775 	hSession = session->hSession;
776 	fw_st_id = session->fw_st_id;
777 
778 	/* first, call C_GetAttributeValue() to get size for each attribute */
779 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
780 	    slot_object->hObject, attrs, num_attrs);
781 	/*
782 	 * If the return value is not CKR_OK, allow it to be
783 	 * CKR_ATTRIBUTE_TYPE_INVALID for now.
784 	 * Some attributes defined in PKCS#11 version 2.11
785 	 * might not be defined in earlier versions.  We will
786 	 * TRY to work with those providers if the attribute
787 	 * is optional.
788 	 */
789 	if ((rv != CKR_OK) && (rv != CKR_ATTRIBUTE_TYPE_INVALID)) {
790 		rv = CKR_FUNCTION_FAILED; /* make sure rv is appropriate */
791 		goto finish;
792 	}
793 
794 	/*
795 	 * allocate space.
796 	 * Since we don't know how many attributes have
797 	 * values at this time, just assume all of them
798 	 * have values so we save one loop to count the number
799 	 * of attributes that have value.
800 	 */
801 	attrs_with_val = calloc(num_attrs, sizeof (CK_ATTRIBUTE));
802 	if (attrs_with_val == NULL) {
803 		rv = CKR_HOST_MEMORY;
804 		goto finish;
805 	}
806 
807 
808 	num_attrs_with_val = 0;
809 	for (i = 0; i < num_attrs; i++) {
810 		if (!(((CK_LONG)(attrs[i].ulValueLen)) > 0)) {
811 			/* if it isn't an optional attr, len should be > 0 */
812 			if (!object->attributes[i].canBeEmptyValue) {
813 				rv = CKR_FUNCTION_FAILED;
814 				goto finish;
815 			}
816 		} else {
817 			attrs_with_val[num_attrs_with_val].type = attrs[i].type;
818 			attrs_with_val[num_attrs_with_val].ulValueLen =
819 			    attrs[i].ulValueLen;
820 			attrs_with_val[num_attrs_with_val].pValue =
821 			    malloc(attrs[i].ulValueLen);
822 			if (attrs_with_val[num_attrs_with_val].pValue == NULL) {
823 				rv = CKR_HOST_MEMORY;
824 				goto finish;
825 			}
826 			num_attrs_with_val++;
827 		}
828 	}
829 
830 	rv = FUNCLIST(fw_st_id)->C_GetAttributeValue(hSession,
831 	    slot_object->hObject, attrs_with_val, num_attrs_with_val);
832 	if (rv != CKR_OK) {
833 		goto finish;
834 	}
835 
836 	/* store these values into the meta object */
837 	for (i = 0; i < num_attrs_with_val; i++) {
838 		rv = attribute_set_value(&(attrs_with_val[i]),
839 		    object->attributes, object->num_attributes);
840 		if (rv != CKR_OK) {
841 			goto finish;
842 		}
843 	}
844 
845 finish:
846 	(void) pthread_rwlock_unlock(&object->attribute_lock);
847 
848 	if (session)
849 		meta_release_slot_session(session);
850 
851 	if (attrs) {
852 		for (i = 0; i < num_attrs; i++) {
853 			if (attrs[i].pValue != NULL) {
854 				free(attrs[i].pValue);
855 			}
856 		}
857 		free(attrs);
858 	}
859 
860 	if (attrs_with_val) {
861 		for (i = 0; i < num_attrs; i++) {
862 			if (attrs_with_val[i].pValue != NULL) {
863 				free(attrs_with_val[i].pValue);
864 			}
865 		}
866 		free(attrs_with_val);
867 	}
868 	return (rv);
869 }
870 
871 /*
872  * Create an object to be used for wrapping and unwrapping.
873  * The same template will be used for all wrapping/unwrapping keys all
874  * the time
875  */
876 
877 static CK_RV
878 create_wrap_unwrap_key(slot_session_t *slot_session, CK_OBJECT_HANDLE *hObject,
879     wrap_info_t *wrap_info, char *key_data, CK_ULONG key_len)
880 {
881 
882 	CK_OBJECT_CLASS objclass;
883 	CK_KEY_TYPE keytype;
884 	CK_RV rv = CKR_OK;
885 	int i;
886 	CK_ATTRIBUTE template[WRAP_KEY_TEMPLATE_SIZE];
887 
888 	i = 0;
889 	objclass = wrap_info->class;
890 	template[i].type = CKA_CLASS;
891 	template[i].pValue = &objclass;
892 	template[i].ulValueLen = sizeof (objclass);
893 
894 	i++;
895 	keytype = wrap_info->key_type;
896 	template[i].type = CKA_KEY_TYPE;
897 	template[i].pValue = &keytype;
898 	template[i].ulValueLen = sizeof (keytype);
899 
900 	i++;
901 	template[i].type = CKA_TOKEN;
902 	template[i].pValue = &falsevalue;
903 	template[i].ulValueLen = sizeof (falsevalue);
904 
905 
906 	if (objclass == CKO_SECRET_KEY) {
907 		i++;
908 		template[i].type = CKA_VALUE;
909 		template[i].pValue = key_data;
910 		template[i].ulValueLen = key_len;
911 
912 		i++;
913 		template[i].type = CKA_WRAP;
914 		template[i].pValue = &truevalue;
915 		template[i].ulValueLen = sizeof (truevalue);
916 
917 		i++;
918 		template[i].type = CKA_UNWRAP;
919 		template[i].pValue = &truevalue;
920 		template[i].ulValueLen = sizeof (truevalue);
921 	} else {
922 		/* Modulus is the same for rsa public and private key */
923 		i++;
924 		template[i].type = CKA_MODULUS;
925 		template[i].pValue = Modulus;
926 		template[i].ulValueLen = sizeof (Modulus);
927 
928 		if (objclass == CKO_PUBLIC_KEY) {
929 			/* RSA public key */
930 			i++;
931 			template[i].type = CKA_PUBLIC_EXPONENT;
932 			template[i].pValue = PubExpo;
933 			template[i].ulValueLen = sizeof (PubExpo);
934 
935 			i++;
936 			template[i].type = CKA_WRAP;
937 			template[i].pValue = &truevalue;
938 			template[i].ulValueLen = sizeof (truevalue);
939 		} else {
940 			/* RSA private key */
941 			i++;
942 			template[i].type = CKA_PRIVATE_EXPONENT;
943 			template[i].pValue = PriExpo;
944 			template[i].ulValueLen = sizeof (PriExpo);
945 
946 			i++;
947 			template[i].type = CKA_UNWRAP;
948 			template[i].pValue = &truevalue;
949 			template[i].ulValueLen = sizeof (truevalue);
950 		}
951 	}
952 
953 	rv = FUNCLIST(slot_session->fw_st_id)->C_CreateObject(
954 	    slot_session->hSession, template, i + 1, hObject);
955 
956 	return (rv);
957 }
958 
959 
960 /*
961  * Create a clone of a non-sensitive and extractable object.
962  * If the template required for creating the clone doesn't exist,
963  * it will be retrieved from the master clone.
964  */
965 static CK_RV
966 clone_by_create(meta_object_t *object, slot_object_t *new_clone,
967     slot_session_t *dst_slot_session)
968 {
969 	CK_RV rv;
970 	int free_token_index = -1;
971 
972 	if (object->attributes == NULL) {
973 		rv = meta_object_copyin(object);
974 		if (rv != CKR_OK) {
975 			return (rv);
976 		}
977 	}
978 
979 	if (object->clone_template == NULL) {
980 		rv = meta_clone_template_setup(object, object->attributes,
981 		    object->num_attributes);
982 		if (rv != CKR_OK) {
983 			return (rv);
984 		}
985 	}
986 
987 	if (object->isFreeToken == FREE_ENABLED) {
988 		if (dst_slot_session->slotnum == get_keystore_slotnum())
989 			free_token_index = set_template_boolean(CKA_TOKEN,
990 			    object->clone_template,
991 			    object->clone_template_size, B_FALSE, &truevalue);
992 		else
993 			free_token_index = set_template_boolean(CKA_TOKEN,
994 			    object->clone_template,
995 			    object->clone_template_size, B_FALSE, &falsevalue);
996 	}
997 
998 	/* Create the clone... */
999 	rv = FUNCLIST(dst_slot_session->fw_st_id)->C_CreateObject(
1000 	    dst_slot_session->hSession, object->clone_template,
1001 	    object->clone_template_size, &(new_clone->hObject));
1002 
1003 	if (free_token_index != -1) {
1004 			free_token_index = set_template_boolean(CKA_TOKEN,
1005 			    object->clone_template, object->clone_template_size,
1006 			    B_FALSE, &falsevalue);
1007 	}
1008 
1009 	if (rv != CKR_OK) {
1010 		return (rv);
1011 	}
1012 
1013 	return (CKR_OK);
1014 }
1015 
1016 /*
1017  * Goes through the list of wraping mechanisms, and returns the first
1018  * one that is supported by both the source and the destination slot.
1019  * If none of the mechanisms are supported by both slot, return the
1020  * first mechanism that's supported by the source slot
1021  */
1022 static CK_RV
1023 find_best_match_wrap_mech(wrap_info_t *wrap_info, int num_info,
1024 	CK_ULONG src_slotnum, CK_ULONG dst_slotnum, int *first_both_mech,
1025 	int *first_src_mech)
1026 {
1027 
1028 	int i;
1029 	boolean_t src_supports, dst_supports;
1030 	CK_RV rv;
1031 	CK_MECHANISM_INFO mech_info;
1032 
1033 	mech_info.flags = CKF_WRAP;
1034 
1035 	for (i = 0; i < num_info; i++) {
1036 		src_supports = B_FALSE;
1037 		dst_supports = B_FALSE;
1038 
1039 		rv = meta_mechManager_slot_supports_mech(
1040 		    (wrap_info[i]).mech_type, src_slotnum,
1041 		    &src_supports, NULL, B_FALSE, &mech_info);
1042 		if (rv != CKR_OK) {
1043 			return (rv);
1044 		}
1045 
1046 		rv = meta_mechManager_slot_supports_mech(
1047 		    (wrap_info[i]).mech_type, dst_slotnum,
1048 		    &dst_supports, NULL, B_FALSE, &mech_info);
1049 		if (rv != CKR_OK) {
1050 			return (rv);
1051 		}
1052 
1053 		/* both source and destination supports the mech */
1054 		if ((src_supports) && (dst_supports)) {
1055 			*first_both_mech = i;
1056 			return (CKR_OK);
1057 		}
1058 
1059 		if ((src_supports) && (*first_src_mech == -1)) {
1060 			*first_src_mech = i;
1061 		}
1062 	}
1063 	return (CKR_OK);
1064 }
1065 
1066 /*
1067  * Determine the wrapping/unwrapping mechanism to be used
1068  *
1069  * If possible, select a mechanism that's supported by both source
1070  * and destination slot.  If none of the mechanisms are supported
1071  * by both slot, then, select the first one supported by
1072  * the source slot.
1073  */
1074 
1075 static CK_RV
1076 get_wrap_mechanism(CK_OBJECT_CLASS obj_class, CK_KEY_TYPE key_type,
1077     CK_ULONG src_slotnum, CK_ULONG dst_slotnum, wrap_info_t *wrap_info)
1078 {
1079 	wrap_info_t *wrap_info_to_search = NULL;
1080 	unsigned int num_wrap_info;
1081 	CK_RV rv;
1082 	int i;
1083 	boolean_t src_supports = B_FALSE, dst_supports = B_FALSE;
1084 	int first_src_mech, rsa_first_src_mech, first_both_mech;
1085 	CK_MECHANISM_INFO mech_info;
1086 
1087 	mech_info.flags = CKF_WRAP;
1088 
1089 	if ((obj_class == CKO_PRIVATE_KEY) && (key_type == CKK_KEA)) {
1090 		/*
1091 		 * only SKIPJACK keys can be used for wrapping
1092 		 * KEA private keys
1093 		 */
1094 
1095 		for (i = 0; i < num_special_wrap_info; i++) {
1096 			if ((special_wrap_info[i]).mech_type
1097 			    != CKM_SKIPJACK_WRAP) {
1098 				continue;
1099 			}
1100 
1101 			src_supports = B_FALSE;
1102 			dst_supports = B_FALSE;
1103 
1104 			rv = meta_mechManager_slot_supports_mech(
1105 			    (special_wrap_info[i]).mech_type, src_slotnum,
1106 			    &src_supports, NULL, B_FALSE, &mech_info);
1107 			if (rv != CKR_OK) {
1108 				goto finish;
1109 			}
1110 
1111 			rv = meta_mechManager_slot_supports_mech(
1112 			    (special_wrap_info[i]).mech_type, dst_slotnum,
1113 			    &dst_supports, NULL, B_FALSE, &mech_info);
1114 			if (rv != CKR_OK) {
1115 				goto finish;
1116 			}
1117 
1118 			if (src_supports) {
1119 				/*
1120 				 * both src and dst supports the mech or
1121 				 * only the src supports the mech
1122 				 */
1123 				(void) memcpy(wrap_info,
1124 				    &(special_wrap_info[i]),
1125 				    sizeof (wrap_info_t));
1126 
1127 				wrap_info->src_supports = src_supports;
1128 				wrap_info->dst_supports = dst_supports;
1129 				rv = CKR_OK;
1130 				goto finish;
1131 			}
1132 
1133 		}
1134 
1135 		/*
1136 		 * if we are here, that means neither the source slot
1137 		 * nor the destination slots suppports CKM_SKIPJACK_WRAP
1138 		 */
1139 		rv = CKR_FUNCTION_FAILED;
1140 		goto finish;
1141 	}
1142 
1143 	if ((key_type == CKK_SKIPJACK) || (key_type == CKK_BATON) ||
1144 	    (key_type == CKK_JUNIPER)) {
1145 		/* special key types */
1146 		wrap_info_to_search = special_wrap_info;
1147 		num_wrap_info = num_special_wrap_info;
1148 	} else {
1149 		/* use the regular wrapping mechanisms */
1150 		wrap_info_to_search = common_wrap_info;
1151 		num_wrap_info = num_common_wrap_info;
1152 	}
1153 
1154 	first_both_mech = -1;
1155 	first_src_mech = -1;
1156 
1157 	rv = find_best_match_wrap_mech(wrap_info_to_search, num_wrap_info,
1158 	    src_slotnum, dst_slotnum, &first_both_mech, &first_src_mech);
1159 	if (rv != CKR_OK) {
1160 		goto finish;
1161 	}
1162 
1163 	if (first_both_mech != -1) {
1164 		(void) memcpy(wrap_info,
1165 		    &(wrap_info_to_search[first_both_mech]),
1166 		    sizeof (wrap_info_t));
1167 
1168 		wrap_info->src_supports = B_TRUE;
1169 		wrap_info->dst_supports = B_TRUE;
1170 		rv = CKR_OK;
1171 		goto finish;
1172 	}
1173 
1174 	/*
1175 	 * If we are here, we did not find a mechanism that's supported
1176 	 * by both source and destination slot.
1177 	 *
1178 	 * If it is a secret key, can also try to wrap it with
1179 	 * a RSA public key
1180 	 */
1181 	if (obj_class == CKO_SECRET_KEY) {
1182 		first_both_mech = -1;
1183 		rsa_first_src_mech = -1;
1184 
1185 		rv = find_best_match_wrap_mech(rsa_wrap_info,
1186 		    num_rsa_wrap_info, src_slotnum, dst_slotnum,
1187 		    &first_both_mech, &rsa_first_src_mech);
1188 
1189 		if (rv != CKR_OK) {
1190 			goto finish;
1191 		}
1192 
1193 		if (first_both_mech > -1) {
1194 			(void) memcpy(wrap_info,
1195 			    &(rsa_wrap_info[first_both_mech]),
1196 			    sizeof (wrap_info_t));
1197 
1198 			wrap_info->src_supports = B_TRUE;
1199 			wrap_info->dst_supports = B_TRUE;
1200 			rv = CKR_OK;
1201 			goto finish;
1202 		}
1203 	}
1204 
1205 	/*
1206 	 * if we are here, that means none of the mechanisms are supported
1207 	 * by both the source and the destination
1208 	 */
1209 	if (first_src_mech > -1) {
1210 		/* source slot support one of the secret key mechs */
1211 		(void) memcpy(wrap_info,
1212 		    &(wrap_info_to_search[first_src_mech]),
1213 		    sizeof (wrap_info_t));
1214 		wrap_info->src_supports = B_TRUE;
1215 		wrap_info->dst_supports = B_FALSE;
1216 		rv = CKR_OK;
1217 	} else if (rsa_first_src_mech > -1) {
1218 		/* source slot support one of the RSA mechs */
1219 		(void) memcpy(wrap_info, &(rsa_wrap_info[rsa_first_src_mech]),
1220 		    sizeof (wrap_info_t));
1221 
1222 		wrap_info->src_supports = B_TRUE;
1223 		wrap_info->dst_supports = B_FALSE;
1224 		rv = CKR_OK;
1225 	} else {
1226 		/* neither source nor destination support any wrap mechs */
1227 		rv = CKR_FUNCTION_FAILED;
1228 	}
1229 
1230 finish:
1231 	return (rv);
1232 }
1233 
1234 
1235 /*
1236  * This is called if the object to be cloned is a sensitive object
1237  */
1238 static CK_RV
1239 clone_by_wrap(meta_object_t *object, slot_object_t *new_clone,
1240     slot_session_t *dst_slot_session)
1241 {
1242 	slot_session_t *src_slot_session = NULL;
1243 	CK_OBJECT_HANDLE wrappingKey = NULL, unwrappingKey = NULL;
1244 	CK_MECHANISM wrappingMech;
1245 	CK_BYTE *wrappedKey = NULL;
1246 	CK_ULONG wrappedKeyLen = 0;
1247 	slot_object_t *slot_object = NULL;
1248 	CK_RV rv = CKR_OK;
1249 	CK_OBJECT_HANDLE unwrapped_obj;
1250 	meta_object_t *tmp_meta_obj = NULL;
1251 	slot_object_t *tmp_slot_obj = NULL;
1252 	CK_OBJECT_CLASS obj_class;
1253 	CK_KEY_TYPE key_type;
1254 	meta_session_t *tmp_meta_session = NULL;
1255 	CK_ATTRIBUTE unwrap_template[4];
1256 	char key_data[1024]; /* should be big enough for any key size */
1257 	char ivbuf[1024]; /* should be big enough for any mech */
1258 	wrap_info_t wrap_info;
1259 	CK_ULONG key_len, unwrap_template_size;
1260 
1261 	slot_object = object->clones[object->master_clone_slotnum];
1262 
1263 	rv = meta_get_slot_session(object->master_clone_slotnum,
1264 	    &src_slot_session, object->creator_session->session_flags);
1265 	if (rv != CKR_OK) {
1266 		return (rv);
1267 	}
1268 
1269 	/*
1270 	 * get the object class and key type for unwrap template
1271 	 * This information will also be used for determining
1272 	 * which wrap mechanism and which key to use for
1273 	 * doing the wrapping
1274 	 */
1275 	unwrap_template[0].type = CKA_CLASS;
1276 	unwrap_template[0].pValue = &obj_class;
1277 	unwrap_template[0].ulValueLen = sizeof (obj_class);
1278 
1279 	unwrap_template[1].type = CKA_KEY_TYPE;
1280 	unwrap_template[1].pValue = &key_type;
1281 	unwrap_template[1].ulValueLen = sizeof (key_type);
1282 
1283 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_GetAttributeValue(
1284 	    src_slot_session->hSession, slot_object->hObject,
1285 	    unwrap_template, 2);
1286 	if (rv != CKR_OK) {
1287 		goto finish;
1288 	}
1289 
1290 	rv = get_wrap_mechanism(obj_class, key_type, src_slot_session->slotnum,
1291 	    dst_slot_session->slotnum, &wrap_info);
1292 	if (rv != CKR_OK) {
1293 		goto finish;
1294 	}
1295 
1296 	/*
1297 	 * open the random device and read number of bytes required for
1298 	 * creating a secret key for wrapping and unwrapping
1299 	 */
1300 	if (wrap_info.class == CKO_SECRET_KEY) {
1301 
1302 		/*
1303 		 * /dev/urandom will be used for generating the key used
1304 		 * for doing the wrap/unwrap.  It's should be ok to
1305 		 * use /dev/urandom because this key is used for this
1306 		 * one time operation only.  It doesn't need to be stored.
1307 		 */
1308 		int fd;
1309 
1310 		while ((fd = open(RANDOM_DEVICE, O_RDONLY)) < 0) {
1311 			if (errno != EINTR)
1312 				break;
1313 		}
1314 		if (fd == -1) {
1315 			rv = CKR_FUNCTION_FAILED;
1316 			goto finish;
1317 		}
1318 		key_len = wrap_info.key_length;
1319 
1320 		if (looping_read(fd, key_data, key_len) != key_len) {
1321 			rv = CKR_FUNCTION_FAILED;
1322 			goto finish;
1323 		}
1324 
1325 		if (wrap_info.iv_length > 0) {
1326 			if (looping_read(fd, ivbuf, wrap_info.iv_length)
1327 			    != wrap_info.iv_length) {
1328 				rv = CKR_FUNCTION_FAILED;
1329 				goto finish;
1330 			}
1331 		}
1332 
1333 		(void) close(fd);
1334 	}
1335 
1336 	/* create the wrapping key */
1337 	rv = create_wrap_unwrap_key(src_slot_session, &wrappingKey,
1338 	    &wrap_info, key_data, key_len);
1339 	if (rv != CKR_OK) {
1340 		goto finish;
1341 	}
1342 
1343 	wrappingMech.mechanism = wrap_info.mech_type;
1344 	wrappingMech.pParameter = ((wrap_info.iv_length > 0) ? ivbuf : NULL);
1345 	wrappingMech.ulParameterLen = wrap_info.iv_length;
1346 
1347 	/* get the size of the wrapped key */
1348 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
1349 	    src_slot_session->hSession, &wrappingMech,
1350 	    wrappingKey, slot_object->hObject, NULL, &wrappedKeyLen);
1351 
1352 	if (rv != CKR_OK) {
1353 		goto finish;
1354 	}
1355 
1356 	wrappedKey = malloc(wrappedKeyLen * sizeof (CK_BYTE));
1357 	if (wrappedKey == NULL) {
1358 		rv = CKR_HOST_MEMORY;
1359 		goto finish;
1360 	}
1361 
1362 	/* do the actual key wrapping */
1363 	rv = FUNCLIST(src_slot_session->fw_st_id)->C_WrapKey(
1364 	    src_slot_session->hSession, &wrappingMech,
1365 	    wrappingKey, slot_object->hObject, wrappedKey, &wrappedKeyLen);
1366 
1367 	if (rv != CKR_OK) {
1368 		goto finish;
1369 	}
1370 
1371 	/* explicitly force the unwrapped object to be not sensitive */
1372 	unwrap_template[2].type = CKA_SENSITIVE;
1373 	unwrap_template[2].pValue = &falsevalue;
1374 	unwrap_template[2].ulValueLen = sizeof (falsevalue);
1375 
1376 	unwrap_template[3].type = CKA_TOKEN;
1377 	unwrap_template[3].pValue = &falsevalue;
1378 	unwrap_template[3].ulValueLen = sizeof (falsevalue);
1379 
1380 	unwrap_template_size =
1381 	    sizeof (unwrap_template) / sizeof (CK_ATTRIBUTE);
1382 
1383 	if (!wrap_info.dst_supports) {
1384 		/*
1385 		 * if we know for sure that the destination slot doesn't
1386 		 * support the wrapping mechanism, no point in trying.
1387 		 * go directly to unwrap in source slot, and create key
1388 		 * in destination
1389 		 */
1390 		goto unwrap_in_source;
1391 	}
1392 
1393 	/* create the unwrapping key in destination slot */
1394 	if (wrap_info.key_type == CKK_RSA) {
1395 		/* for RSA key, the unwrapping key need to be private key */
1396 		wrap_info.class = CKO_PRIVATE_KEY;
1397 	}
1398 	rv = create_wrap_unwrap_key(dst_slot_session,
1399 	    &unwrappingKey, &wrap_info, key_data, key_len);
1400 	if (rv != CKR_OK) {
1401 		goto finish;
1402 	}
1403 
1404 	rv = FUNCLIST(dst_slot_session->fw_st_id)->C_UnwrapKey(
1405 	    dst_slot_session->hSession, &wrappingMech,
1406 	    unwrappingKey, wrappedKey, wrappedKeyLen, unwrap_template,
1407 	    unwrap_template_size, &(new_clone->hObject));
1408 
1409 	if (rv != CKR_OK) {
1410 unwrap_in_source:
1411 
1412 		/*
1413 		 * There seemed to be a problem with unwrapping in the
1414 		 * destination slot.
1415 		 * Try to do the unwrap in the src slot so it becomes
1416 		 * a non-sensitive object, then, get all the attributes
1417 		 * and create the object in the destination slot
1418 		 */
1419 
1420 
1421 		if (wrap_info.class == CKO_SECRET_KEY) {
1422 			/* unwrap with same key used for wrapping */
1423 			rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
1424 			    src_slot_session->hSession,
1425 			    &wrappingMech, wrappingKey, wrappedKey,
1426 			    wrappedKeyLen, unwrap_template,
1427 			    unwrap_template_size, &(unwrapped_obj));
1428 		} else {
1429 			/*
1430 			 * If the object is wrapping with RSA public key, need
1431 			 * need to create RSA private key for unwrapping
1432 			 */
1433 			wrap_info.class = CKO_PRIVATE_KEY;
1434 			rv = create_wrap_unwrap_key(src_slot_session,
1435 			    &unwrappingKey, &wrap_info, key_data, key_len);
1436 			if (rv != CKR_OK) {
1437 				goto finish;
1438 			}
1439 			rv = FUNCLIST(src_slot_session->fw_st_id)->C_UnwrapKey(
1440 			    src_slot_session->hSession,
1441 			    &wrappingMech, unwrappingKey, wrappedKey,
1442 			    wrappedKeyLen, unwrap_template,
1443 			    unwrap_template_size, &(unwrapped_obj));
1444 		}
1445 
1446 
1447 		if (rv != CKR_OK) {
1448 			goto finish;
1449 		}
1450 
1451 		rv = meta_session_alloc(&tmp_meta_session);
1452 		if (rv != CKR_OK) {
1453 			goto finish;
1454 		}
1455 
1456 		tmp_meta_session->session_flags = CKF_SERIAL_SESSION;
1457 
1458 		rv = meta_object_alloc(tmp_meta_session, &tmp_meta_obj);
1459 		if (rv != CKR_OK) {
1460 			goto finish;
1461 		}
1462 
1463 		rv = meta_slot_object_alloc(&tmp_slot_obj);
1464 		if (rv != CKR_OK) {
1465 			goto finish;
1466 		}
1467 
1468 		tmp_meta_obj->master_clone_slotnum = src_slot_session->slotnum;
1469 		tmp_slot_obj->hObject = unwrapped_obj;
1470 		tmp_meta_obj->clones[tmp_meta_obj->master_clone_slotnum]
1471 		    = tmp_slot_obj;
1472 		meta_slot_object_activate(tmp_slot_obj, src_slot_session,
1473 		    B_FALSE);
1474 		tmp_slot_obj = NULL;
1475 
1476 		rv = clone_by_create(tmp_meta_obj, new_clone,
1477 		    dst_slot_session);
1478 		if (rv != CKR_OK) {
1479 			goto finish;
1480 		}
1481 	}
1482 
1483 finish:
1484 	if (unwrappingKey) {
1485 		(void) FUNCLIST(dst_slot_session->fw_st_id)->C_DestroyObject(
1486 		    dst_slot_session->hSession, unwrappingKey);
1487 	}
1488 
1489 	if (wrappingKey) {
1490 		(void) FUNCLIST(src_slot_session->fw_st_id)->C_DestroyObject(
1491 		    src_slot_session->hSession, wrappingKey);
1492 	}
1493 
1494 	if (tmp_slot_obj) {
1495 		(void) meta_slot_object_dealloc(tmp_slot_obj);
1496 	}
1497 
1498 	if (tmp_meta_obj) {
1499 		(void) meta_object_dealloc(tmp_meta_session, tmp_meta_obj,
1500 		    B_TRUE);
1501 	}
1502 
1503 	if (tmp_meta_session) {
1504 		(void) meta_session_dealloc(tmp_meta_session);
1505 	}
1506 
1507 	if (wrappedKey) {
1508 		free(wrappedKey);
1509 	}
1510 
1511 	if (src_slot_session) {
1512 		meta_release_slot_session(src_slot_session);
1513 	}
1514 
1515 	return (rv);
1516 
1517 }
1518 
1519 
1520 /*
1521  * meta_object_get_clone
1522  *
1523  * Creates a "clone" of a metaobject on the specified slot. A clone is a
1524  * copy of the object.
1525  *
1526  * Clones are cached, so that they can be reused with subsquent operations.
1527  */
1528 CK_RV
1529 meta_object_get_clone(meta_object_t *object,
1530 	CK_ULONG slot_num, slot_session_t *slot_session,
1531 	slot_object_t **clone)
1532 {
1533 	CK_RV rv = CKR_OK;
1534 	slot_object_t *newclone = NULL;
1535 
1536 	/* Does a clone already exist? */
1537 	if (object->clones[slot_num] != NULL) {
1538 		*clone = object->clones[slot_num];
1539 		return (CKR_OK);
1540 	}
1541 
1542 	if ((object->isSensitive) && (object->isToken) &&
1543 	    (!metaslot_auto_key_migrate)) {
1544 		/*
1545 		 * if the object is a sensitive token object, and auto
1546 		 * key migrate is not allowed, will not create the clone
1547 		 * in another slot
1548 		 */
1549 		return (CKR_FUNCTION_FAILED);
1550 	}
1551 
1552 	/* object attributes can't be extracted and attributes are not known */
1553 	if ((!object->isExtractable) && (object->attributes == NULL)) {
1554 		return (CKR_FUNCTION_FAILED);
1555 	}
1556 
1557 	(void) pthread_mutex_lock(&object->clone_create_lock);
1558 
1559 	/* Maybe someone just created one? */
1560 	if (object->clones[slot_num] != NULL) {
1561 		*clone = object->clones[slot_num];
1562 		goto finish;
1563 	}
1564 
1565 	/*
1566 	 * has an attempt already been made to create this object in
1567 	 * slot?  If yes, and there's no clone, as indicated above,
1568 	 * that means this object can't be created in this slot.
1569 	 */
1570 	if (object->tried_create_clone[slot_num]) {
1571 		(void) pthread_mutex_unlock(&object->clone_create_lock);
1572 		return (CKR_FUNCTION_FAILED);
1573 	}
1574 
1575 	rv = meta_slot_object_alloc(&newclone);
1576 	if (rv != CKR_OK)
1577 		goto finish;
1578 
1579 	object->tried_create_clone[slot_num] = B_TRUE;
1580 
1581 	/*
1582 	 * If this object is sensitive and we do not have not copied in the
1583 	 * attributes via FreeObject functionality, then we need to wrap it off
1584 	 * the provider.  If we do have attributes, we can just create the
1585 	 * clone
1586 	 */
1587 
1588 	if (object->isSensitive && object->attributes == NULL) {
1589 		rv = clone_by_wrap(object, newclone, slot_session);
1590 	} else {
1591 		rv = clone_by_create(object, newclone, slot_session);
1592 	}
1593 
1594 	if (rv != CKR_OK) {
1595 		goto finish;
1596 	}
1597 
1598 	object->clones[slot_num] = newclone;
1599 	meta_slot_object_activate(newclone, slot_session, object->isToken);
1600 
1601 	*clone = newclone;
1602 	newclone = NULL;
1603 finish:
1604 	(void) pthread_mutex_unlock(&object->clone_create_lock);
1605 
1606 	if (newclone)
1607 		meta_slot_object_dealloc(newclone);
1608 
1609 	return (rv);
1610 }
1611 
1612 
1613 /*
1614  * meta_setup_clone_template
1615  *
1616  * Create a clone template for the specified object.
1617  */
1618 static CK_RV
1619 meta_clone_template_setup(meta_object_t *object,
1620     const generic_attr_t *attributes, size_t num_attributes)
1621 {
1622 	CK_RV rv = CKR_OK;
1623 	CK_ATTRIBUTE *clone_template;
1624 	size_t i, c = 0;
1625 
1626 	clone_template = malloc(num_attributes * sizeof (CK_ATTRIBUTE));
1627 	if (clone_template == NULL) {
1628 		rv = CKR_HOST_MEMORY;
1629 		goto finish;
1630 	}
1631 
1632 	/* Don't allow attributes to change while we look at them. */
1633 	(void) pthread_rwlock_rdlock(&object->attribute_lock);
1634 
1635 	for (i = 0; i < num_attributes; i++) {
1636 		if (!attributes[i].isCloneAttr ||
1637 		    (attributes[i].attribute.type == CKA_TOKEN &&
1638 		    object->isFreeToken == FREE_DISABLED)) {
1639 			continue;
1640 		}
1641 		if ((!(attributes[i].hasValueForClone)) &&
1642 		    (attributes[i].canBeEmptyValue)) {
1643 			continue;
1644 		}
1645 
1646 		clone_template[c].type = attributes[i].attribute.type;
1647 		clone_template[c].ulValueLen =
1648 		    attributes[i].attribute.ulValueLen;
1649 		/* Allocate space to store the attribute value. */
1650 		clone_template[c].pValue = malloc(clone_template[c].ulValueLen);
1651 		if (clone_template[c].pValue == NULL) {
1652 			rv = CKR_HOST_MEMORY;
1653 			(void) pthread_rwlock_unlock(&object->attribute_lock);
1654 			goto finish;
1655 		}
1656 
1657 		(void) memcpy(clone_template[c].pValue,
1658 		    object->attributes[i].attribute.pValue,
1659 		    clone_template[c].ulValueLen);
1660 		c++;
1661 	}
1662 
1663 	(void) pthread_rwlock_unlock(&object->attribute_lock);
1664 
1665 	object->clone_template = clone_template;
1666 	object->clone_template_size = c;
1667 
1668 finish:
1669 	return (rv);
1670 }
1671 
1672 
1673 /*
1674  * meta_object_find_by_handle
1675  *
1676  * Search for an existing metaobject, using the object handle of a clone
1677  * on a particular slot.
1678  *
1679  * Returns a matching metaobject, or NULL if no match was found.
1680  */
1681 meta_object_t *
1682 meta_object_find_by_handle(CK_OBJECT_HANDLE hObject, CK_ULONG slotnum,
1683     boolean_t token_only)
1684 {
1685 	meta_object_t *object = NULL, *tmp_obj;
1686 	meta_session_t *session;
1687 
1688 	if (!token_only) {
1689 		(void) pthread_rwlock_rdlock(&meta_sessionlist_lock);
1690 		session = meta_sessionlist_head;
1691 		while (session != NULL) {
1692 			/* lock the objects list while we look at it */
1693 			(void) pthread_rwlock_rdlock(
1694 			    &(session->object_list_lock));
1695 			tmp_obj = session->object_list_head;
1696 			while (tmp_obj != NULL) {
1697 				slot_object_t *slot_object;
1698 
1699 				(void) pthread_rwlock_rdlock(
1700 				    &(tmp_obj->object_lock));
1701 				slot_object = tmp_obj->clones[slotnum];
1702 				if (slot_object != NULL) {
1703 					if (slot_object->hObject == hObject) {
1704 						object = tmp_obj;
1705 					}
1706 				}
1707 				(void) pthread_rwlock_unlock(
1708 				    &(tmp_obj->object_lock));
1709 				if (object != NULL) {
1710 					break;
1711 				}
1712 				tmp_obj = tmp_obj->next;
1713 			}
1714 			(void) pthread_rwlock_unlock(
1715 			    &(session->object_list_lock));
1716 			if (object != NULL) {
1717 				break;
1718 			}
1719 			session = session->next;
1720 		}
1721 		(void) pthread_rwlock_unlock(&meta_sessionlist_lock);
1722 	}
1723 
1724 	if (object != NULL) {
1725 		/* found the object, no need to look further */
1726 		return (object);
1727 	}
1728 
1729 	/*
1730 	 * Look at list of token objects
1731 	 */
1732 	(void) pthread_rwlock_rdlock(&tokenobject_list_lock);
1733 	tmp_obj = tokenobject_list_head;
1734 
1735 	while (tmp_obj != NULL) {
1736 		slot_object_t *slot_object;
1737 
1738 		(void) pthread_rwlock_rdlock(&(tmp_obj->object_lock));
1739 		slot_object = tmp_obj->clones[slotnum];
1740 		if (slot_object != NULL) {
1741 			if (slot_object->hObject == hObject)
1742 				object = tmp_obj;
1743 		}
1744 		(void) pthread_rwlock_unlock(&(tmp_obj->object_lock));
1745 		if (object != NULL) {
1746 			break;
1747 		}
1748 		tmp_obj = tmp_obj->next;
1749 	}
1750 	(void) pthread_rwlock_unlock(&tokenobject_list_lock);
1751 
1752 	return (object);
1753 }
1754 
1755 CK_RV
1756 meta_token_object_deactivate(token_obj_type_t token_type)
1757 {
1758 	meta_object_t *object, *tmp_object;
1759 	CK_RV save_rv = CKR_OK, rv;
1760 
1761 	/* get a write lock on the token object list */
1762 	(void) pthread_rwlock_wrlock(&tokenobject_list_lock);
1763 
1764 	object = tokenobject_list_head;
1765 
1766 	/* go through each object and delete the one with matching type */
1767 	while (object != NULL) {
1768 		tmp_object = object->next;
1769 
1770 		if ((token_type == ALL_TOKEN) ||
1771 		    ((object->isPrivate) && (token_type == PRIVATE_TOKEN)) ||
1772 		    ((!object->isPrivate) && (token_type == PUBLIC_TOKEN))) {
1773 			rv = meta_object_deactivate(object, B_TRUE, B_FALSE);
1774 			if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
1775 				save_rv = rv;
1776 				goto finish;
1777 			}
1778 			rv = meta_object_dealloc(NULL, object, B_FALSE);
1779 			if ((rv != CKR_OK) && (save_rv == CKR_OK)) {
1780 				save_rv = rv;
1781 				goto finish;
1782 			}
1783 		}
1784 		object = tmp_object;
1785 	}
1786 finish:
1787 	(void) pthread_rwlock_unlock(&tokenobject_list_lock);
1788 	return (save_rv);
1789 }
1790 
1791 /*
1792  * This function adds the to-be-freed meta object to a linked list.
1793  * When the number of objects queued in the linked list reaches the
1794  * maximum threshold MAX_OBJ_TO_BE_FREED, it will free the first
1795  * object (FIFO) in the list.
1796  */
1797 void
1798 meta_object_delay_free(meta_object_t *objp)
1799 {
1800 	meta_object_t *tmp;
1801 
1802 	(void) pthread_mutex_lock(&obj_delay_freed.obj_to_be_free_mutex);
1803 
1804 	/* Add the newly deleted object at the end of the list */
1805 	objp->next = NULL;
1806 	if (obj_delay_freed.first == NULL) {
1807 		obj_delay_freed.last = objp;
1808 		obj_delay_freed.first = objp;
1809 	} else {
1810 		obj_delay_freed.last->next = objp;
1811 		obj_delay_freed.last = objp;
1812 	}
1813 
1814 	if (++obj_delay_freed.count >= MAX_OBJ_TO_BE_FREED) {
1815 		/*
1816 		 * Free the first object in the list only if
1817 		 * the total count reaches maximum threshold.
1818 		 */
1819 		obj_delay_freed.count--;
1820 		tmp = obj_delay_freed.first->next;
1821 		free(obj_delay_freed.first);
1822 		obj_delay_freed.first = tmp;
1823 	}
1824 	(void) pthread_mutex_unlock(&obj_delay_freed.obj_to_be_free_mutex);
1825 }
1826 
1827 
1828 /*
1829  * This function checks if the object passed can be a freeobject.
1830  *
1831  * If there is more than one provider that supports the supported freeobject
1832  * mechanisms then allow freeobjects to be an option.
1833  */
1834 
1835 boolean_t
1836 meta_freeobject_check(meta_session_t *session, meta_object_t *object,
1837     CK_MECHANISM *pMech, CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len,
1838     CK_KEY_TYPE keytype)
1839 {
1840 	mech_support_info_t *info = &(session->mech_support_info);
1841 
1842 	/*
1843 	 * If key migration is turned off, or the object does not has any of
1844 	 * the required flags and there is only one slot, then we don't need
1845 	 * FreeObjects.
1846 	 */
1847 	if (!metaslot_auto_key_migrate ||
1848 	    (!object->isToken && !object->isSensitive &&
1849 	    meta_slotManager_get_slotcount() < 2))
1850 		goto failure;
1851 
1852 	/*
1853 	 * If this call is for key generation, check pMech for supported
1854 	 * FreeObject mechs
1855 	 */
1856 	if (pMech != NULL) {
1857 		if (pMech->mechanism == CKM_RSA_PKCS_KEY_PAIR_GEN ||
1858 		    pMech->mechanism == CKM_EC_KEY_PAIR_GEN ||
1859 		    pMech->mechanism == CKM_DH_PKCS_KEY_PAIR_GEN ||
1860 		    pMech->mechanism == CKM_DH_PKCS_DERIVE)
1861 			info->mech = pMech->mechanism;
1862 		else
1863 			goto failure;
1864 
1865 	/*
1866 	 * If this call is for an object creation, look inside the template
1867 	 * for supported FreeObject mechs
1868 	 */
1869 	} else if (tmpl_len > 0) {
1870 		if (!get_template_ulong(CKA_KEY_TYPE, tmpl, tmpl_len, &keytype))
1871 			goto failure;
1872 
1873 		switch (keytype) {
1874 		case CKK_RSA:
1875 			info->mech = CKM_RSA_PKCS_KEY_PAIR_GEN;
1876 			break;
1877 		case CKK_EC:
1878 			info->mech = CKM_EC_KEY_PAIR_GEN;
1879 			break;
1880 		case CKK_DH:
1881 			info->mech = CKM_DH_PKCS_KEY_PAIR_GEN;
1882 			break;
1883 		default:
1884 			goto failure;
1885 		}
1886 	} else
1887 		goto failure;
1888 
1889 	/* Get the slot that support this mech... */
1890 	if (meta_mechManager_get_slots(info, B_FALSE, NULL) != CKR_OK)
1891 		goto failure;
1892 
1893 	/*
1894 	 * If there is only one slot with the mech or the first slot in
1895 	 * the list is the keystore slot, we should bail.
1896 	 */
1897 	if (info->num_supporting_slots < 2 &&
1898 	    info->supporting_slots[0]->slotnum == get_keystore_slotnum())
1899 		goto failure;
1900 
1901 	if (object->isToken)
1902 		object->isFreeToken = FREE_ALLOWED_KEY;
1903 	else
1904 		object->isFreeToken = FREE_DISABLED;
1905 
1906 	object->isFreeObject = FREE_ALLOWED_KEY;
1907 
1908 	return (B_TRUE);
1909 
1910 failure:
1911 	object->isFreeToken = FREE_DISABLED;
1912 	object->isFreeObject = FREE_DISABLED;
1913 	return (B_FALSE);
1914 }
1915 
1916 /*
1917  * This function assumes meta_freeobject_check() has just been called and set
1918  * the isFreeObject and/or isFreeToken vars to FREE_ALLOWED_KEY.
1919  *
1920  * If the template value for CKA_PRIVATE, CKA_SENSITIVE and/or CKA_TOKEN are
1921  * true, then isFreeObject is fully enabled.  In addition isFreeToken is
1922  * enabled if is CKA_TOKEN true.
1923  *
1924  * If create is true, we are doing a C_CreateObject operation and don't
1925  * handle CKA_PRIVATE & CKA_SENSITIVE flags, we only care about CKA_TOKEN.
1926  */
1927 
1928 boolean_t
1929 meta_freeobject_set(meta_object_t *object, CK_ATTRIBUTE *tmpl,
1930     CK_ULONG tmpl_len, boolean_t create)
1931 {
1932 
1933 	/* This check should never be true, if it is, it's a bug */
1934 	if (object->isFreeObject < FREE_ALLOWED_KEY)
1935 		return (B_FALSE);
1936 
1937 	if (!create) {
1938 		/* Turn off the Sensitive flag */
1939 		if (object->isSensitive) {
1940 			if (set_template_boolean(CKA_SENSITIVE, tmpl, tmpl_len,
1941 			    B_TRUE, &falsevalue) == -1)
1942 				goto failure;
1943 
1944 			object->isFreeObject = FREE_ENABLED;
1945 		}
1946 
1947 		/* Turn off the Private flag */
1948 		if (object->isPrivate) {
1949 			if (set_template_boolean(CKA_PRIVATE, tmpl, tmpl_len,
1950 			    B_TRUE, &falsevalue) == -1)
1951 				goto failure;
1952 
1953 			object->isFreeObject = FREE_ENABLED;
1954 		}
1955 	}
1956 
1957 	if (object->isToken) {
1958 		object->isToken = B_FALSE;
1959 		object->isFreeToken = FREE_ENABLED;
1960 		object->isFreeObject = FREE_ENABLED;
1961 	} else
1962 		object->isFreeToken = FREE_DISABLED;
1963 
1964 	/*
1965 	 *  If isFreeObject is not in the FREE_ENABLED state yet, it can be
1966 	 *  turned off because the object doesn't not need to be a FreeObject.
1967 	 */
1968 	if (object->isFreeObject == FREE_ALLOWED_KEY)
1969 		object->isFreeObject = FREE_DISABLED;
1970 
1971 	return (B_TRUE);
1972 
1973 failure:
1974 	object->isFreeToken = FREE_DISABLED;
1975 	object->isFreeObject = FREE_DISABLED;
1976 	return (B_FALSE);
1977 }
1978 
1979 /*
1980  * This function sets the CKA_TOKEN flag on a given object template depending
1981  * if the slot being used is a keystore.
1982  *
1983  * If the object is a token, but the slot is not the system keystore or has
1984  * no keystore, then set the template to token = false; otherwise it's true.
1985  * In addition we know ahead of time what the value is, so if the value is
1986  * already correct, bypass the setting function
1987  */
1988 CK_RV
1989 meta_freetoken_set(CK_ULONG slot_num, CK_BBOOL *current_value,
1990     CK_ATTRIBUTE *tmpl, CK_ULONG tmpl_len)
1991 {
1992 
1993 	if (slot_num == get_keystore_slotnum()) {
1994 		if (*current_value == TRUE)
1995 			return (CKR_OK);
1996 
1997 		if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
1998 		    &truevalue) == -1)
1999 			return (CKR_FUNCTION_FAILED);
2000 
2001 	} else {
2002 
2003 		if (*current_value == FALSE)
2004 			return (CKR_OK);
2005 
2006 		if (set_template_boolean(CKA_TOKEN, tmpl, tmpl_len, B_TRUE,
2007 		    &falsevalue) == -1)
2008 			return (CKR_FUNCTION_FAILED);
2009 
2010 		*current_value = FALSE;
2011 	}
2012 
2013 	return (CKR_OK);
2014 }
2015 
2016 /*
2017  * Cloning function for meta_freeobject_clone() to use.  This function
2018  * is streamlined because we know what the object is and this should
2019  * not be called as a generic cloner.
2020  */
2021 
2022 static CK_RV
2023 meta_freeobject_clone_maker(meta_session_t *session, meta_object_t *object,
2024     CK_ULONG slotnum)
2025 {
2026 
2027 	slot_object_t *slot_object = NULL;
2028 	slot_session_t *slot_session = NULL;
2029 	CK_RV rv;
2030 
2031 	rv = meta_slot_object_alloc(&slot_object);
2032 	if (rv != CKR_OK)
2033 		goto cleanup;
2034 
2035 	rv = meta_get_slot_session(slotnum, &slot_session,
2036 	    session->session_flags);
2037 	if (rv != CKR_OK)
2038 		goto cleanup;
2039 
2040 	rv = clone_by_create(object, slot_object, slot_session);
2041 	if (rv == CKR_OK) {
2042 		object->clones[slotnum] = slot_object;
2043 		meta_slot_object_activate(slot_object, slot_session, B_TRUE);
2044 	}
2045 
2046 cleanup:
2047 	meta_release_slot_session(slot_session);
2048 	return (rv);
2049 
2050 }
2051 
2052 /*
2053  * This function is called when a object is a FreeObject.
2054  *
2055  * What we are given is an object that has been generated on a provider
2056  * that is not its final usage place. That maybe because:
2057  * 1) it's a token and needs to be stored in keystore.
2058  * 2) it was to be a private/sensitive object that we modified so we could know
2059  *    the important attributes for cloning before we make it private/sensitive.
2060  */
2061 
2062 boolean_t
2063 meta_freeobject_clone(meta_session_t *session, meta_object_t *object)
2064 {
2065 	CK_RV rv;
2066 	CK_ULONG keystore_slotnum;
2067 	CK_ATTRIBUTE attr[2];
2068 	boolean_t failover = B_FALSE;
2069 
2070 	if (object->attributes == NULL) {
2071 		rv = meta_object_copyin(object);
2072 		if (rv != CKR_OK)
2073 			return (rv);
2074 	}
2075 
2076 	if (object->isPrivate) {
2077 		CK_OBJECT_HANDLE new_clone;
2078 		CK_ULONG slotnum = object->master_clone_slotnum;
2079 		slot_session_t *slot_session;
2080 
2081 		attr[0].type = CKA_PRIVATE;
2082 		attr[0].pValue = &truevalue;
2083 		attr[0].ulValueLen = sizeof (truevalue);
2084 
2085 		/* Set the master attribute list */
2086 		rv = attribute_set_value(attr, object->attributes,
2087 		    object->num_attributes);
2088 		if (rv > 0)
2089 			return (CKR_FUNCTION_FAILED);
2090 
2091 		/* Get a slot session */
2092 		rv = meta_get_slot_session(slotnum, &slot_session,
2093 		    session->session_flags);
2094 		if (rv > 0)
2095 			return (rv);
2096 
2097 		/* Create the new CKA_PRIVATE one */
2098 		rv = FUNCLIST(slot_session->fw_st_id)->\
2099 		    C_CopyObject(slot_session->hSession,
2100 		    object->clones[slotnum]->hObject, attr, 1, &new_clone);
2101 
2102 		if (rv == CKR_USER_NOT_LOGGED_IN) {
2103 			/*
2104 			 * If the CopyObject fails, we may be using a provider
2105 			 * that has a keystore that is not the default
2106 			 * keystore set in metaslot or has object management
2107 			 * abilities. In which case we should write this
2108 			 * object to metaslot's keystore and let the failover.
2109 			 * rest of the function know we've changed providers.
2110 			 */
2111 			failover = B_TRUE;
2112 			keystore_slotnum = get_keystore_slotnum();
2113 			if (object->clones[keystore_slotnum] == NULL) {
2114 				rv = meta_freeobject_clone_maker(session,
2115 				    object, keystore_slotnum);
2116 				if (rv != CKR_OK) {
2117 					goto failure;
2118 				}
2119 			}
2120 			object->master_clone_slotnum = keystore_slotnum;
2121 
2122 		} else if (rv != CKR_OK) {
2123 			meta_release_slot_session(slot_session);
2124 			goto failure;
2125 		}
2126 		/* Remove the old object */
2127 		rv = FUNCLIST(slot_session->fw_st_id)->	\
2128 		    C_DestroyObject(slot_session->hSession,
2129 		    object->clones[slotnum]->hObject);
2130 		if (rv != CKR_OK) {
2131 			meta_release_slot_session(slot_session);
2132 			goto failure;
2133 		}
2134 
2135 		if (!failover)
2136 			object->clones[slotnum]->hObject = new_clone;
2137 		else
2138 			object->clones[slotnum] = NULL;
2139 
2140 		meta_release_slot_session(slot_session);
2141 
2142 	}
2143 
2144 	if (object->isSensitive) {
2145 		slot_session_t *slot_session;
2146 		CK_ULONG slotnum = object->master_clone_slotnum;
2147 
2148 		attr[0].type = CKA_SENSITIVE;
2149 		attr[0].pValue = &truevalue;
2150 		attr[0].ulValueLen = sizeof (truevalue);
2151 		rv = attribute_set_value(attr, object->attributes,
2152 		    object->num_attributes);
2153 		if (rv != CKR_OK)
2154 			goto failure;
2155 
2156 		rv = meta_get_slot_session(slotnum, &slot_session,
2157 		    session->session_flags);
2158 		if (rv == CKR_OK) {
2159 			rv = FUNCLIST(slot_session->fw_st_id)->		\
2160 			    C_SetAttributeValue(slot_session->hSession,
2161 			    object->clones[slotnum]->hObject, attr, 1);
2162 
2163 			meta_release_slot_session(slot_session);
2164 		}
2165 	}
2166 
2167 	if (object->isFreeToken == FREE_ENABLED || failover) {
2168 		keystore_slotnum = get_keystore_slotnum();
2169 		if (object->clones[keystore_slotnum] == NULL) {
2170 			rv = meta_freeobject_clone_maker(session, object,
2171 			    keystore_slotnum);
2172 			if (rv != CKR_OK)
2173 				goto failure;
2174 
2175 			object->master_clone_slotnum = keystore_slotnum;
2176 		}
2177 		object->isFreeToken = FREE_ENABLED;
2178 	}
2179 
2180 	object->isFreeObject = FREE_ENABLED;
2181 	return (CKR_OK);
2182 
2183 failure:
2184 	object->isFreeToken = FREE_DISABLED;
2185 	object->isFreeObject = FREE_DISABLED;
2186 	return (rv);
2187 
2188 }
2189