xref: /titanic_41/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelObjectUtil.c (revision 7c478bd95313f5f23a4c958a745db2134aa03244)
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, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  */
22 /*
23  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
24  * Use is subject to license terms.
25  */
26 
27 #pragma ident	"%Z%%M%	%I%	%E% SMI"
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <strings.h>
32 #include <errno.h>
33 #include <security/cryptoki.h>
34 #include <cryptoutil.h>
35 #include "kernelGlobal.h"
36 #include "kernelObject.h"
37 #include "kernelSession.h"
38 #include "kernelSlot.h"
39 
40 /*
41  * Add an object to the session's object list.
42  *
43  * This function will acquire the lock on the session, and release
44  * that lock after adding the object to the session's object list.
45  */
46 void
47 kernel_add_object_to_session(kernel_object_t *objp, kernel_session_t *sp)
48 {
49 
50 	/* Acquire the session lock. */
51 	(void) pthread_mutex_lock(&sp->session_mutex);
52 
53 	/* Insert the new object in front of session's object list. */
54 	if (sp->object_list == NULL) {
55 		sp->object_list = objp;
56 		objp->next = NULL;
57 		objp->prev = NULL;
58 	} else {
59 		sp->object_list->prev = objp;
60 		objp->next = sp->object_list;
61 		objp->prev = NULL;
62 		sp->object_list = objp;
63 	}
64 
65 	/* Release the session lock. */
66 	(void) pthread_mutex_unlock(&sp->session_mutex);
67 }
68 
69 
70 /*
71  * Clean up and release the storage allocated to the object.
72  *
73  * The function is called either with the object lock being held
74  * (by caller kernel_delete_object()), or there is no object lock
75  * yet (by kernel_build_XXX_object() during creating an object).
76  */
77 void
78 kernel_cleanup_object(kernel_object_t *objp)
79 {
80 
81 	/*
82 	 * Free the storage allocated to a secret key object.
83 	 */
84 	if (OBJ_SEC(objp) != NULL) {
85 		if (OBJ_SEC_VALUE(objp) != NULL) {
86 			bzero(OBJ_SEC_VALUE(objp), OBJ_SEC_VALUE_LEN(objp));
87 			free(OBJ_SEC_VALUE(objp));
88 			OBJ_SEC_VALUE(objp) = NULL;
89 			OBJ_SEC_VALUE_LEN(objp) = 0;
90 		}
91 		free(OBJ_SEC(objp));
92 		OBJ_SEC(objp) = NULL;
93 	} else {
94 		kernel_cleanup_object_bigint_attrs(objp);
95 	}
96 
97 	/*
98 	 * Free the storage allocated to the extra attribute list.
99 	 */
100 	kernel_cleanup_extra_attr(objp);
101 }
102 
103 
104 /*
105  * Create a new object. Copy the attributes that can be modified
106  * (in the boolean attribute mask field and extra attribute list)
107  * from the old object to the new object.
108  *
109  * The caller of this function holds the lock on the old object.
110  */
111 CK_RV
112 kernel_copy_object(kernel_object_t *old_object, kernel_object_t **new_object,
113     boolean_t copy_everything, kernel_session_t *sp)
114 {
115 
116 	CK_RV rv = CKR_OK;
117 	kernel_object_t *new_objp = NULL;
118 	CK_ATTRIBUTE_INFO_PTR attrp;
119 
120 	/* Allocate new object. */
121 	new_objp = calloc(1, sizeof (kernel_object_t));
122 	if (new_objp == NULL)
123 		return (CKR_HOST_MEMORY);
124 
125 	new_objp->class = old_object->class;
126 	new_objp->bool_attr_mask = old_object->bool_attr_mask;
127 
128 	attrp = old_object->extra_attrlistp;
129 	while (attrp) {
130 		/*
131 		 * Copy the attribute_info struct from the old
132 		 * object to a new attribute_info struct, and add
133 		 * that new struct to the extra attribute list
134 		 * of the new object.
135 		 */
136 		rv = kernel_copy_extra_attr(attrp, new_objp);
137 		if (rv != CKR_OK) {
138 			kernel_cleanup_extra_attr(new_objp);
139 			free(new_objp);
140 			return (rv);
141 		}
142 		attrp = attrp->next;
143 	}
144 
145 	*new_object = new_objp;
146 
147 	if (!copy_everything) {
148 		/* done with copying all information that can be modified */
149 		return (CKR_OK);
150 	}
151 
152 	/*
153 	 * Copy the rest of the object.
154 	 * Certain fields that are not appropriate for coping will be
155 	 * initialized.
156 	 */
157 	new_objp->key_type = old_object->key_type;
158 	new_objp->magic_marker = old_object->magic_marker;
159 	new_objp->mechanism = old_object->mechanism;
160 	new_objp->session_handle = (CK_SESSION_HANDLE)sp;
161 	(void) pthread_mutex_init(&(new_objp->object_mutex), NULL);
162 	/* copy key related information */
163 	switch (new_objp->class) {
164 		case CKO_PUBLIC_KEY:
165 			rv = kernel_copy_public_key_attr(OBJ_PUB(old_object),
166 			    &(OBJ_PUB(new_objp)), new_objp->key_type);
167 			break;
168 		case CKO_PRIVATE_KEY:
169 			rv = kernel_copy_private_key_attr(OBJ_PRI(old_object),
170 			    &(OBJ_PRI(new_objp)), new_objp->key_type);
171 			break;
172 		case CKO_SECRET_KEY:
173 			rv = kernel_copy_secret_key_attr(OBJ_SEC(old_object),
174 			    &(OBJ_SEC(new_objp)));
175 			break;
176 		default:
177 			/* should never be this case */
178 			break;
179 	}
180 	if (rv != CKR_OK) {
181 		/*
182 		 * don't need to cleanup the memory from failure of copying
183 		 * any key related stuff.  Each individual function for
184 		 * copying key attr will free the memory if it fails
185 		 */
186 		kernel_cleanup_extra_attr(new_objp);
187 		free(new_objp);
188 	}
189 	return (rv);
190 }
191 
192 
193 /*
194  * Copy the attributes (in the boolean attribute mask field and
195  * extra attribute list) from the new object back to the original
196  * object. Also, clean up and release all the storage in the extra
197  * attribute list of the original object.
198  *
199  * The caller of this function holds the lock on the old object.
200  */
201 void
202 kernel_merge_object(kernel_object_t *old_object, kernel_object_t *new_object)
203 {
204 
205 	old_object->bool_attr_mask = new_object->bool_attr_mask;
206 	kernel_cleanup_extra_attr(old_object);
207 	old_object->extra_attrlistp = new_object->extra_attrlistp;
208 
209 }
210 
211 
212 /*
213  * Create a new object struct.  If it is a session object, add the object to
214  * the session's object list.  If it is a token object, add it to the slot's
215  * token object list.  The caller does not hold the slot lock.
216  */
217 CK_RV
218 kernel_add_object(CK_ATTRIBUTE_PTR pTemplate,  CK_ULONG ulCount,
219 	CK_ULONG *objecthandle_p, kernel_session_t *sp)
220 {
221 
222 	CK_RV rv = CKR_OK;
223 	kernel_object_t *new_objp = NULL;
224 	kernel_slot_t	*pslot;
225 	crypto_object_create_t	objc;
226 	CK_BBOOL is_pri_obj;
227 	CK_BBOOL is_token_obj = B_FALSE;
228 	int r;
229 
230 	new_objp = calloc(1, sizeof (kernel_object_t));
231 	if (new_objp == NULL) {
232 		rv = CKR_HOST_MEMORY;
233 		goto fail_cleanup;
234 	}
235 
236 	new_objp->extra_attrlistp = NULL;
237 	new_objp->is_lib_obj = B_TRUE;
238 
239 	/*
240 	 * If the HW provider supports object creation, create the object
241 	 * in the HW provider by calling the CRYPTO_OBJECT_CREATE ioctl.
242 	 * Otherwise, create the object in the library.
243 	 */
244 	pslot = slot_table[sp->ses_slotid];
245 	if (pslot->sl_func_list.fl_object_create) {
246 		new_objp->is_lib_obj = B_FALSE;
247 		objc.oc_session = sp->k_session;
248 		objc.oc_count = ulCount;
249 		rv = process_object_attributes(pTemplate, ulCount,
250 		    &objc.oc_attributes, &is_token_obj);
251 		if (rv != CKR_OK) {
252 			goto fail_cleanup;
253 		}
254 
255 		/* Cannot create a token object with a READ-ONLY session */
256 		if (is_token_obj && sp->ses_RO) {
257 			free_object_attributes(objc.oc_attributes, ulCount);
258 			rv = CKR_SESSION_READ_ONLY;
259 			goto fail_cleanup;
260 		}
261 
262 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_CREATE,
263 		    &objc)) < 0) {
264 			if (errno != EINTR)
265 				break;
266 		}
267 		if (r < 0) {
268 			rv = CKR_FUNCTION_FAILED;
269 		} else {
270 			rv = crypto2pkcs11_error_number(objc.oc_return_value);
271 		}
272 
273 		free_object_attributes(objc.oc_attributes, ulCount);
274 
275 		if (rv != CKR_OK) {
276 			goto fail_cleanup;
277 		}
278 
279 		/* Get the CKA_PRIVATE value of this object. */
280 		new_objp->k_handle = objc.oc_handle;
281 		rv = get_cka_private_value(sp, new_objp->k_handle,
282 		    &is_pri_obj);
283 		if (rv != CKR_OK) {
284 			goto fail_cleanup;
285 		}
286 
287 		/* Set the PRIVATE_BOOL_ON and TOKEN_BOOL_ON attributes */
288 		if (is_pri_obj)
289 			new_objp->bool_attr_mask |= PRIVATE_BOOL_ON;
290 		else
291 			new_objp->bool_attr_mask &= ~PRIVATE_BOOL_ON;
292 
293 		if (is_token_obj)
294 			new_objp->bool_attr_mask |= TOKEN_BOOL_ON;
295 		else
296 			new_objp->bool_attr_mask &= ~TOKEN_BOOL_ON;
297 
298 	} else {
299 		/*
300 		 * Create the object in the library.
301 		 * Validate attribute template and fill in the attributes
302 		 * in the kernel_object_t.
303 		 */
304 		rv = kernel_build_object(pTemplate, ulCount, new_objp, sp);
305 		if (rv != CKR_OK) {
306 			goto fail_cleanup;
307 		}
308 	}
309 
310 	/* Initialize the rest of stuffs in kernel_object_t. */
311 	(void) pthread_mutex_init(&new_objp->object_mutex, NULL);
312 	new_objp->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
313 	new_objp->session_handle = (CK_SESSION_HANDLE)sp;
314 
315 	if (is_token_obj) {
316 		/* Add the new object to the slot's token object list. */
317 		pslot = slot_table[sp->ses_slotid];
318 		kernel_add_token_object_to_slot(new_objp, pslot);
319 	} else {
320 		/* Add the new object to the session's object list. */
321 		kernel_add_object_to_session(new_objp, sp);
322 	}
323 
324 	/* Type casting the address of an object struct to an object handle. */
325 	*objecthandle_p =  (CK_ULONG)new_objp;
326 
327 	return (CKR_OK);
328 
329 fail_cleanup:
330 	if (new_objp) {
331 		/*
332 		 * If the object is created in the HW provider, the storage
333 		 * allocated for the ioctl call is always cleaned up after
334 		 * the call.  If the object is created in the library,
335 		 * the storage allocated inside of this object should
336 		 * have been cleaned up in the kernel_build_object()
337 		 * after an error occurred. Therefore, we can safely
338 		 * free the object.
339 		 */
340 		free(new_objp);
341 	}
342 
343 	return (rv);
344 }
345 
346 
347 /*
348  * Remove an object from the session's object list.
349  *
350  * The caller of this function holds the session lock.
351  */
352 void
353 kernel_remove_object_from_session(kernel_object_t *objp, kernel_session_t *sp)
354 {
355 
356 	/*
357 	 * Remove the object from the session's object list.
358 	 */
359 	if (sp->object_list == objp) {
360 		/* Object is the first one in the list. */
361 		if (objp->next) {
362 			sp->object_list = objp->next;
363 			objp->next->prev = NULL;
364 		} else {
365 			/* Object is the only one in the list. */
366 			sp->object_list = NULL;
367 		}
368 	} else {
369 		/* Object is not the first one in the list. */
370 		if (objp->next) {
371 			/* Object is in the middle of the list. */
372 			objp->prev->next = objp->next;
373 			objp->next->prev = objp->prev;
374 		} else {
375 			/* Object is the last one in the list. */
376 			objp->prev->next = NULL;
377 		}
378 	}
379 }
380 
381 
382 /*
383  * Delete a session object:
384  * - Remove the object from the session's object list.
385  * - Release the storage allocated to the object.
386  *
387  * The boolean argument ses_lock_held is used to indicate that whether
388  * the caller holds the session lock or not.
389  * - When called by kernel_delete_all_objects_in_session() or
390  *   kernel_delete_pri_objects_in_slot() -- ses_lock_held = TRUE.
391  *
392  * The boolean argument wrapper_only is used to indicate that whether
393  * the caller only wants to clean up the object wrapper from the library and
394  * needs not to make an ioctl call.
395  * - This argument only applies to the object created in the provider level.
396  * - When called by kernel_cleanup_pri_objects_in_slot(), wrapper_only is TRUE.
397  * - When called by C_DestroyObject(), wrapper_only is FALSE.
398  * - When called by kernel_delete_all_objects_in_session(), the value of
399  *   wrapper_only depends on its caller.
400  */
401 CK_RV
402 kernel_delete_session_object(kernel_session_t *sp, kernel_object_t *objp,
403     boolean_t ses_lock_held, boolean_t wrapper_only)
404 {
405 	CK_RV rv = CKR_OK;
406 	crypto_object_destroy_t	obj_destroy;
407 	int r;
408 
409 	/*
410 	 * Check to see if the caller holds the lock on the session.
411 	 * If not, we need to acquire that lock in order to proceed.
412 	 */
413 	if (!ses_lock_held) {
414 		/* Acquire the session lock. */
415 		(void) pthread_mutex_lock(&sp->session_mutex);
416 	}
417 
418 	/* Remove the object from the session's object list first. */
419 	kernel_remove_object_from_session(objp, sp);
420 
421 	if (!ses_lock_held) {
422 		/*
423 		 * If the session lock is obtained by this function,
424 		 * then release that lock after removing the object
425 		 * from session's object list.
426 		 * We want the releasing of the object storage to
427 		 * be done without holding the session lock.
428 		 */
429 		(void) pthread_mutex_unlock(&sp->session_mutex);
430 	}
431 
432 	/* Acquire the lock on the object. */
433 	(void) pthread_mutex_lock(&objp->object_mutex);
434 
435 	/*
436 	 * Make sure another thread hasn't freed the object.
437 	 */
438 	if (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC) {
439 		(void) pthread_mutex_unlock(&objp->object_mutex);
440 		return (CKR_OBJECT_HANDLE_INVALID);
441 	}
442 
443 	/* Mark object as no longer valid. */
444 	objp->magic_marker = 0;
445 
446 	/* Destroy the object. */
447 	if (objp->is_lib_obj) {
448 		/*
449 		 * If this object is created in the library, cleanup the
450 		 * contents of this object such as free all the storage
451 		 * allocated for this object.
452 		 */
453 		kernel_cleanup_object(objp);
454 	} else {
455 		/*
456 		 * This object is created in the HW provider. If wrapper_only
457 		 * is FALSE, make an ioctl call to destroy it in kernel.
458 		 */
459 		if (!wrapper_only) {
460 			obj_destroy.od_session = sp->k_session;
461 			obj_destroy.od_handle = objp->k_handle;
462 
463 			while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY,
464 			    &obj_destroy)) < 0) {
465 				if (errno != EINTR)
466 					break;
467 			}
468 			if (r < 0) {
469 				rv = CKR_FUNCTION_FAILED;
470 			} else {
471 				rv = crypto2pkcs11_error_number(
472 				    obj_destroy.od_return_value);
473 			}
474 
475 			/*
476 			 * Ignore ioctl return codes for a session object.
477 			 * If the kernel can not delete a session object, it
478 			 * is likely caused by the HW provider. There's not
479 			 * much that can be done.  The library will still
480 			 * cleanup the object wrapper in the library. The HW
481 			 * provider will destroy all session objects when
482 			 * the application exits.
483 			 */
484 			rv = CKR_OK;
485 		}
486 	}
487 
488 	if (rv == CKR_OK) {
489 		(void) pthread_mutex_unlock(&objp->object_mutex);
490 		/* Destroy the object lock */
491 		(void) pthread_mutex_destroy(&objp->object_mutex);
492 		/* Free the object itself */
493 		free(objp);
494 	}
495 
496 	return (rv);
497 }
498 
499 
500 /*
501  * Delete all the objects in a session. The caller holds the lock
502  * on the session.   If the wrapper_only argument is TRUE, the caller only
503  * want to clean up object wrappers in the library.
504  */
505 void
506 kernel_delete_all_objects_in_session(kernel_session_t *sp,
507     boolean_t wrapper_only)
508 {
509 
510 	kernel_object_t *objp = sp->object_list;
511 
512 	kernel_object_t *objp1;
513 
514 	/* Delete all the objects in the session. */
515 	while (objp) {
516 		objp1 = objp->next;
517 
518 		/*
519 		 * Delete an session object by calling
520 		 * kernel_delete_session_object():
521 		 * - The 3rd TRUE boolean argument indicates that the caller
522 		 *   holds the session lock.
523 		 * - The 4th boolean argument indicates whether we only want
524 		 *   clean up object wrappers in the library.
525 		 */
526 		(void) kernel_delete_session_object(sp, objp, B_TRUE,
527 		    wrapper_only);
528 
529 		objp = objp1;
530 	}
531 
532 }
533 
534 
535 static CK_RV
536 add_to_search_result(kernel_object_t *obj, find_context_t *fcontext,
537     CK_ULONG *num_result_alloc)
538 {
539 	/*
540 	 * allocate space for storing results if the currently
541 	 * allocated space is not enough
542 	 */
543 	if (*num_result_alloc <= fcontext->num_results) {
544 		fcontext->objs_found = realloc(fcontext->objs_found,
545 		    sizeof (kernel_object_t *) * (*num_result_alloc + BUFSIZ));
546 		if (fcontext->objs_found == NULL) {
547 			return (CKR_HOST_MEMORY);
548 		}
549 		*num_result_alloc += BUFSIZ;
550 	}
551 
552 	(fcontext->objs_found)[(fcontext->num_results)++] = obj;
553 	return (CKR_OK);
554 }
555 
556 static CK_RV
557 search_for_objects(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
558     CK_ULONG ulCount, find_context_t *fcontext)
559 {
560 	kernel_session_t *session_p;
561 	kernel_object_t *obj;
562 	CK_OBJECT_CLASS pclasses[6]; /* classes attrs possiblely exist */
563 	CK_ULONG num_pclasses;	/* number of possible classes */
564 	CK_ULONG num_result_alloc = 0; /* spaces allocated for results */
565 	CK_RV rv = CKR_OK;
566 	kernel_slot_t	*pslot;
567 
568 	if (ulCount > 0) {
569 		/* there are some search requirement */
570 		kernel_process_find_attr(pclasses, &num_pclasses,
571 		    pTemplate, ulCount);
572 	}
573 
574 	/* Acquire the slot lock */
575 	pslot = slot_table[sp->ses_slotid];
576 	(void) pthread_mutex_lock(&pslot->sl_mutex);
577 
578 
579 	/*
580 	 * Go through all objects in each session.
581 	 * Acquire individual session lock for the session
582 	 * we are searching.
583 	 */
584 	session_p = pslot->sl_sess_list;
585 	while (session_p) {
586 		(void) pthread_mutex_lock(&session_p->session_mutex);
587 		obj = session_p->object_list;
588 		while (obj) {
589 			(void) pthread_mutex_lock(&obj->object_mutex);
590 			if (ulCount > 0) {
591 				if (kernel_find_match_attrs(obj, pclasses,
592 				    num_pclasses, pTemplate, ulCount)) {
593 					rv = add_to_search_result(
594 					    obj, fcontext, &num_result_alloc);
595 				}
596 			} else {
597 				/* no search criteria, just record the object */
598 				rv = add_to_search_result(obj, fcontext,
599 				    &num_result_alloc);
600 			}
601 			(void) pthread_mutex_unlock(&obj->object_mutex);
602 			if (rv != CKR_OK) {
603 				(void) pthread_mutex_unlock(
604 				    &session_p->session_mutex);
605 				goto cleanup;
606 			}
607 			obj = obj->next;
608 		}
609 		(void) pthread_mutex_unlock(&session_p->session_mutex);
610 		session_p = session_p->next;
611 	}
612 
613 cleanup:
614 	/* Release the slot lock */
615 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
616 	return (rv);
617 }
618 
619 
620 /*
621  * Initialize the context for C_FindObjects() calls
622  */
623 CK_RV
624 kernel_find_objects_init(kernel_session_t *sp, CK_ATTRIBUTE_PTR pTemplate,
625     CK_ULONG ulCount)
626 {
627 
628 	CK_RV rv = CKR_OK;
629 	CK_OBJECT_CLASS class; /* for kernel_validate_attr(). Value unused */
630 	find_context_t *fcontext;
631 
632 	if (ulCount) {
633 		rv = kernel_validate_attr(pTemplate, ulCount, &class);
634 		/* Make sure all attributes in template are valid */
635 		if (rv != CKR_OK) {
636 			return (rv);
637 		}
638 	}
639 
640 	/* prepare the find context */
641 	fcontext = calloc(1, sizeof (find_context_t));
642 	if (fcontext == NULL) {
643 		return (CKR_HOST_MEMORY);
644 	}
645 
646 	rv = search_for_objects(sp, pTemplate, ulCount, fcontext);
647 	if (rv != CKR_OK) {
648 		free(fcontext);
649 		return (rv);
650 	}
651 
652 	/* store the find_context in the session */
653 	sp->find_objects.context = (CK_VOID_PTR)fcontext;
654 
655 	return (rv);
656 }
657 
658 void
659 kernel_find_objects_final(kernel_session_t *sp)
660 {
661 
662 	find_context_t *fcontext;
663 
664 	fcontext = sp->find_objects.context;
665 	sp->find_objects.context = NULL;
666 	sp->find_objects.flags = 0;
667 	if (fcontext->objs_found != NULL) {
668 		free(fcontext->objs_found);
669 	}
670 
671 	free(fcontext);
672 
673 }
674 
675 void
676 kernel_find_objects(kernel_session_t *sp, CK_OBJECT_HANDLE *obj_found,
677     CK_ULONG max_obj_requested, CK_ULONG *found_obj_count)
678 {
679 	find_context_t *fcontext;
680 	CK_ULONG num_obj_found = 0;
681 	CK_ULONG i;
682 	kernel_object_t *obj;
683 
684 	fcontext = sp->find_objects.context;
685 
686 	for (i = fcontext->next_result_index;
687 	    ((num_obj_found < max_obj_requested) &&
688 	    (i < fcontext->num_results));
689 	    i++) {
690 		obj = fcontext->objs_found[i];
691 		if (obj != NULL) {
692 			(void) pthread_mutex_lock(&obj->object_mutex);
693 			/* a sanity check to make sure the obj is still valid */
694 			if (obj->magic_marker == KERNELTOKEN_OBJECT_MAGIC) {
695 				obj_found[num_obj_found] =
696 				    (CK_OBJECT_HANDLE)obj;
697 				num_obj_found++;
698 			}
699 			(void) pthread_mutex_unlock(&obj->object_mutex);
700 		}
701 	}
702 	fcontext->next_result_index = i;
703 	*found_obj_count = num_obj_found;
704 }
705 
706 
707 /*
708  * Add an token object to the token object list in slot.
709  *
710  * This function will acquire the lock on the slot, and release
711  * that lock after adding the object to the slot's token object list.
712  */
713 void
714 kernel_add_token_object_to_slot(kernel_object_t *objp, kernel_slot_t *pslot)
715 {
716 
717 	/* Acquire the slot lock. */
718 	(void) pthread_mutex_lock(&pslot->sl_mutex);
719 
720 	/* Insert the new object in front of slot's token object list. */
721 	if (pslot->sl_tobj_list == NULL) {
722 		pslot->sl_tobj_list = objp;
723 		objp->next = NULL;
724 		objp->prev = NULL;
725 	} else {
726 		pslot->sl_tobj_list->prev = objp;
727 		objp->next = pslot->sl_tobj_list;
728 		objp->prev = NULL;
729 		pslot->sl_tobj_list = objp;
730 	}
731 
732 	/* Release the slot lock. */
733 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
734 }
735 
736 
737 /*
738  * Remove an token object from the slot's token object list.
739  * This routine is called by kernel_delete_token_object().
740  * The caller of this function hold the slot lock.
741  */
742 void
743 kernel_remove_token_object_from_slot(kernel_slot_t *pslot,
744     kernel_object_t *objp)
745 {
746 
747 	if (pslot->sl_tobj_list == objp) {
748 		/* Object is the first one in the list */
749 		if (objp->next) {
750 			pslot->sl_tobj_list = objp->next;
751 			objp->next->prev = NULL;
752 		} else {
753 			/* Object is the only one in the list. */
754 			pslot->sl_tobj_list = NULL;
755 		}
756 	} else {
757 		/* Object is not the first one in the list. */
758 		if (objp->next) {
759 			/* Object is in the middle of the list. */
760 			objp->prev->next = objp->next;
761 			objp->next->prev = objp->prev;
762 		} else {
763 			/* Object is the last one in the list. */
764 			objp->prev->next = NULL;
765 		}
766 	}
767 }
768 
769 
770 /*
771  * Delete a token object:
772  * - Remove the object from the slot's token object list.
773  * - Release the storage allocated to the object.
774  *
775  * The boolean argument slot_lock_held is used to indicate that whether
776  * the caller holds the slot lock or not. When the caller does not hold
777  * the slot lock, this function will acquire that lock in order to proceed,
778  * and also release that lock before returning to caller.
779  *
780  * The boolean argument wrapper_only is used to indicate that whether
781  * the caller only wants to the object wrapper from library.
782  */
783 CK_RV
784 kernel_delete_token_object(kernel_slot_t *pslot, kernel_session_t *sp,
785     kernel_object_t *objp, boolean_t slot_lock_held, boolean_t wrapper_only)
786 {
787 	CK_RV rv;
788 	crypto_object_destroy_t	obj_destroy;
789 	int r;
790 
791 	/*
792 	 * Check to see if the caller holds the lock on the slot.
793 	 * If not, we need to acquire that lock in order to proceed.
794 	 */
795 	if (!slot_lock_held) {
796 		(void) pthread_mutex_lock(&pslot->sl_mutex);
797 	}
798 
799 	/* Remove the object from the slot's token object list first. */
800 	kernel_remove_token_object_from_slot(pslot, objp);
801 
802 	/* Release the slot lock if the call doesn't hold the lock. */
803 	if (!slot_lock_held) {
804 		(void) pthread_mutex_unlock(&pslot->sl_mutex);
805 	}
806 
807 	/*
808 	 * Make sure another thread hasn't freed the object.
809 	 */
810 	if (objp->magic_marker != KERNELTOKEN_OBJECT_MAGIC) {
811 		(void) pthread_mutex_unlock(&objp->object_mutex);
812 		return (CKR_OBJECT_HANDLE_INVALID);
813 	}
814 
815 	/* Acquire the lock on the object. */
816 	(void) pthread_mutex_lock(&objp->object_mutex);
817 
818 	/* Mark object as no longer valid. */
819 	objp->magic_marker = 0;
820 
821 	if (!wrapper_only) {
822 		obj_destroy.od_session = sp->k_session;
823 		obj_destroy.od_handle = objp->k_handle;
824 
825 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_DESTROY,
826 		    &obj_destroy)) < 0) {
827 			if (errno != EINTR)
828 				break;
829 		}
830 		if (r < 0) {
831 			rv = CKR_FUNCTION_FAILED;
832 		} else {
833 			rv = crypto2pkcs11_error_number(
834 			    obj_destroy.od_return_value);
835 		}
836 
837 		/*
838 		 * Could not destroy an object from kernel. Write a warning
839 		 * in syslog, but we still clean up the object wrapper in
840 		 * the library.
841 		 */
842 		if (rv != CKR_OK) {
843 			cryptoerror(LOG_ERR, "pkcs11_kernel: Could not "
844 			    "destroy an object in kernel.");
845 			rv = CKR_OK;
846 		}
847 	}
848 
849 	if (rv == CKR_OK) {
850 		(void) pthread_mutex_unlock(&objp->object_mutex);
851 		/* Destroy the object lock */
852 		(void) pthread_mutex_destroy(&objp->object_mutex);
853 		/* Free the object itself */
854 		free(objp);
855 	}
856 
857 	return (rv);
858 }
859 
860 
861 /*
862  * Clean up private object wrappers in this slot. The caller holds the slot
863  * lock.
864  */
865 void
866 kernel_cleanup_pri_objects_in_slot(kernel_slot_t *pslot,
867     kernel_session_t *cur_sp)
868 {
869 	kernel_session_t *session_p;
870 	kernel_object_t *objp;
871 	kernel_object_t *objp1;
872 
873 	/*
874 	 * Delete every private token object from the slot' token object list
875 	 */
876 	objp = pslot->sl_tobj_list;
877 	while (objp) {
878 		objp1 = objp->next;
879 		/*
880 		 * The first TRUE boolean argument indicates that the caller
881 		 * hold the slot lock.  The second TRUE boolean argument
882 		 * indicates that the caller just wants to clean up the object
883 		 * wrapper from the library only.
884 		 */
885 		if (objp->bool_attr_mask & PRIVATE_BOOL_ON) {
886 			(void) kernel_delete_token_object(pslot, cur_sp, objp,
887 			    B_TRUE, B_TRUE);
888 		}
889 		objp = objp1;
890 	}
891 
892 	/*
893 	 * Walk through all the sessions in this slot and delete every
894 	 * private object.
895 	 */
896 	session_p = pslot->sl_sess_list;
897 	while (session_p) {
898 
899 		/* Delete all the objects in the session. */
900 		objp = session_p->object_list;
901 		while (objp) {
902 			objp1 = objp->next;
903 			/*
904 			 * The FALSE boolean argument indicates that the
905 			 * caller does not hold the session lock.  The TRUE
906 			 * boolean argument indicates that the caller just
907 			 * want to clean upt the object wrapper from the
908 			 * library only.
909 			 */
910 			if (objp->bool_attr_mask & PRIVATE_BOOL_ON) {
911 				(void) kernel_delete_session_object(session_p,
912 				    objp, B_FALSE, B_TRUE);
913 			}
914 
915 			objp = objp1;
916 		}
917 
918 		session_p = session_p->next;
919 	}
920 }
921 
922 /*
923  * Get the object size in bytes for the objects created in the library.
924  */
925 CK_RV
926 kernel_get_object_size(kernel_object_t *obj, CK_ULONG_PTR pulSize)
927 {
928 	CK_RV rv = CKR_OK;
929 	CK_ULONG obj_size;
930 	biginteger_t *big;
931 
932 	obj_size = sizeof (kernel_object_t);
933 
934 	switch (obj->class) {
935 	case CKO_PUBLIC_KEY:
936 		if (obj->key_type == CKK_RSA) {
937 			big = OBJ_PUB_RSA_PUBEXPO(obj);
938 			obj_size += big->big_value_len;
939 			big = OBJ_PUB_RSA_MOD(obj);
940 			obj_size += big->big_value_len;
941 
942 		} else if (obj->key_type == CKK_DSA) {
943 			big = OBJ_PUB_DSA_PRIME(obj);
944 			obj_size += big->big_value_len;
945 			big = OBJ_PUB_DSA_SUBPRIME(obj);
946 			obj_size += big->big_value_len;
947 			big = OBJ_PUB_DSA_BASE(obj);
948 			obj_size += big->big_value_len;
949 			big = OBJ_PUB_DSA_VALUE(obj);
950 			obj_size += big->big_value_len;
951 
952 		} else {
953 			rv = CKR_OBJECT_HANDLE_INVALID;
954 		}
955 		break;
956 
957 	case CKO_PRIVATE_KEY:
958 		if (obj->key_type == CKK_RSA) {
959 			big = OBJ_PRI_RSA_MOD(obj);
960 			obj_size += big->big_value_len;
961 
962 			big = OBJ_PRI_RSA_PUBEXPO(obj); /* optional */
963 			if (big != NULL) {
964 				obj_size += big->big_value_len;
965 			}
966 
967 			big = OBJ_PRI_RSA_PRIEXPO(obj);
968 			obj_size += big->big_value_len;
969 
970 			big = OBJ_PRI_RSA_PRIME1(obj); /* optional */
971 			if (big != NULL) {
972 				obj_size += big->big_value_len;
973 			}
974 
975 			big = OBJ_PRI_RSA_PRIME2(obj); /* optional */
976 			if (big != NULL) {
977 				obj_size += big->big_value_len;
978 			}
979 
980 			big = OBJ_PRI_RSA_EXPO1(obj); /* optional */
981 			if (big != NULL) {
982 				obj_size += big->big_value_len;
983 			}
984 
985 			big = OBJ_PRI_RSA_EXPO2(obj); /* optional */
986 			if (big != NULL) {
987 				obj_size += big->big_value_len;
988 			}
989 
990 			big = OBJ_PRI_RSA_COEF(obj); /* optional */
991 			if (big != NULL) {
992 				obj_size += big->big_value_len;
993 			}
994 
995 		} else if (obj->key_type == CKK_DSA) {
996 			big = OBJ_PRI_DSA_PRIME(obj);
997 			obj_size += big->big_value_len;
998 			big = OBJ_PRI_DSA_SUBPRIME(obj);
999 			obj_size += big->big_value_len;
1000 			big = OBJ_PRI_DSA_BASE(obj);
1001 			obj_size += big->big_value_len;
1002 			big = OBJ_PRI_DSA_VALUE(obj);
1003 			obj_size += big->big_value_len;
1004 
1005 		} else {
1006 			rv = CKR_OBJECT_HANDLE_INVALID;
1007 		}
1008 		break;
1009 
1010 	case CKO_SECRET_KEY:
1011 		obj_size += OBJ_SEC_VALUE_LEN(obj);
1012 		break;
1013 
1014 	default:
1015 		rv = CKR_OBJECT_HANDLE_INVALID;
1016 	}
1017 
1018 	if (rv == CKR_OK) {
1019 		*pulSize = obj_size;
1020 	}
1021 
1022 	return (rv);
1023 }
1024