xref: /titanic_41/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelObject.c (revision 26d8ba2242584067b65160d24193c37cdc83cd55)
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 <pthread.h>
30 #include <stdlib.h>
31 #include <errno.h>
32 #include <security/cryptoki.h>
33 #include "kernelGlobal.h"
34 #include "kernelObject.h"
35 #include "kernelSession.h"
36 #include <errno.h>
37 #include <string.h>
38 #include <cryptoutil.h>
39 
40 CK_RV
41 C_CreateObject(CK_SESSION_HANDLE hSession,
42     CK_ATTRIBUTE_PTR pTemplate,
43     CK_ULONG ulCount,
44     CK_OBJECT_HANDLE_PTR phObject)
45 {
46 
47 	CK_RV rv;
48 	kernel_session_t *session_p;
49 	boolean_t ses_lock_held = B_FALSE;
50 
51 	if (!kernel_initialized)
52 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
53 
54 	if ((pTemplate == NULL) || (ulCount == 0) ||
55 	    (phObject == NULL)) {
56 		return (CKR_ARGUMENTS_BAD);
57 	}
58 
59 	/*
60 	 * Obtain the session pointer. Also, increment the session
61 	 * reference count.
62 	 */
63 	rv = handle2session(hSession, &session_p);
64 	if (rv != CKR_OK)
65 		return (rv);
66 
67 	/* Create a new object. */
68 	rv = kernel_add_object(pTemplate, ulCount, phObject, session_p);
69 
70 	/*
71 	 * Decrement the session reference count.
72 	 * We do not hold the session lock.
73 	 */
74 	REFRELE(session_p, ses_lock_held);
75 
76 	return (rv);
77 }
78 
79 
80 CK_RV
81 C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
82     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
83     CK_OBJECT_HANDLE_PTR phNewObject)
84 {
85 
86 	CK_RV rv;
87 	kernel_session_t *session_p;
88 	boolean_t ses_lock_held = B_FALSE;
89 	kernel_object_t *old_object;
90 	kernel_object_t *new_object = NULL;
91 	crypto_object_copy_t  object_copy;
92 	CK_BBOOL is_pri_obj = FALSE;
93 	CK_BBOOL is_token_obj = FALSE;
94 	kernel_slot_t	*pslot;
95 	int i, r;
96 
97 	if (!kernel_initialized)
98 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
99 
100 	/* Check arguments */
101 	if (((ulCount > 0) && (pTemplate == NULL)) ||
102 	    (phNewObject == NULL)) {
103 		return (CKR_ARGUMENTS_BAD);
104 	}
105 
106 	/*
107 	 * Obtain the session pointer. Also, increment the session
108 	 * reference count.
109 	 */
110 	rv = handle2session(hSession, &session_p);
111 	if (rv != CKR_OK)
112 		return (rv);
113 
114 	/* Obtain the object pointer. */
115 	HANDLE2OBJECT(hObject, old_object, rv);
116 	if (rv != CKR_OK) {
117 		/*
118 		 * Decrement the session reference count.
119 		 * We do not hold the session lock.
120 		 */
121 		REFRELE(session_p, ses_lock_held);
122 		return (rv);
123 	}
124 
125 	(void) pthread_mutex_lock(&old_object->object_mutex);
126 
127 	if (old_object->is_lib_obj) {
128 		/*
129 		 * Copy the old object to a new object.
130 		 * The 3rd argument with TRUE value indicates that
131 		 * everything in the object will be duplicated.
132 		 */
133 		rv = kernel_copy_object(old_object, &new_object, B_TRUE,
134 		    session_p);
135 		(void) pthread_mutex_unlock(&old_object->object_mutex);
136 		if ((rv != CKR_OK) || (new_object == NULL)) {
137 			/*
138 			 * Most likely we ran out of space.
139 			 * Decrement the session reference count.
140 			 * We do not hold the session lock.
141 			 */
142 			OBJ_REFRELE(old_object);
143 			REFRELE(session_p, ses_lock_held);
144 			return (rv);
145 		}
146 
147 		new_object->is_lib_obj = B_TRUE;
148 
149 		/* Modify the object attribute if requested */
150 		for (i = 0; i < ulCount; i++) {
151 			/* Set the requested attribute into the new object. */
152 			rv = kernel_set_attribute(new_object, &pTemplate[i],
153 			    B_TRUE, session_p);
154 
155 			if (rv != CKR_OK) {
156 				kernel_cleanup_object(new_object);
157 
158 				/*
159 				 * Decrement the session reference count.
160 				 * We do not hold the session lock.
161 				 */
162 				OBJ_REFRELE(old_object);
163 				REFRELE(session_p, ses_lock_held);
164 				return (rv);
165 			}
166 		}
167 
168 		/* Insert the new object into this session's object list. */
169 		kernel_add_object_to_session(new_object, session_p);
170 
171 		/*
172 		 * Decrement the session reference count.
173 		 * We do not hold the session lock.
174 		 */
175 		OBJ_REFRELE(old_object);
176 		REFRELE(session_p, ses_lock_held);
177 
178 		/* set handle of the new object */
179 		*phNewObject = (CK_ULONG)new_object;
180 
181 	} else {
182 		/*
183 		 * The old object was created in the HW provider.
184 		 * First, create an object wrapper in library.
185 		 */
186 		new_object = calloc(1, sizeof (kernel_object_t));
187 		if (new_object == NULL) {
188 			(void) pthread_mutex_unlock(&old_object->object_mutex);
189 			OBJ_REFRELE(old_object);
190 			REFRELE(session_p, ses_lock_held);
191 			return (CKR_HOST_MEMORY);
192 		}
193 
194 		/* Call CRYPTO_OBJECT_COPY ioctl to get a new object. */
195 		object_copy.oc_session = session_p->k_session;
196 		object_copy.oc_handle = old_object->k_handle;
197 		(void) pthread_mutex_unlock(&old_object->object_mutex);
198 		object_copy.oc_count = ulCount;
199 		object_copy.oc_new_attributes = NULL;
200 		if (ulCount > 0) {
201 			rv = process_object_attributes(pTemplate, ulCount,
202 			    &object_copy.oc_new_attributes, &is_token_obj);
203 			if (rv != CKR_OK) {
204 				goto failed_cleanup;
205 			}
206 		}
207 
208 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_COPY,
209 		    &object_copy)) < 0) {
210 			if (errno != EINTR)
211 				break;
212 		}
213 		if (r < 0) {
214 			rv = CKR_FUNCTION_FAILED;
215 		} else {
216 			rv = crypto2pkcs11_error_number(
217 			    object_copy.oc_return_value);
218 		}
219 
220 		/* Free the attributes' space allocated for ioctl */
221 		free_object_attributes(object_copy.oc_new_attributes, ulCount);
222 
223 		if (rv != CKR_OK) {
224 			goto failed_cleanup;
225 		}
226 
227 		/*
228 		 * Store the kernel object handle in the object wrapper and
229 		 * get the CKA_PRIVATE value of the new object.
230 		 */
231 		new_object->k_handle = object_copy.oc_new_handle;
232 		rv = get_cka_private_value(session_p, new_object->k_handle,
233 		    &is_pri_obj);
234 		if (rv != CKR_OK) {
235 			goto failed_cleanup;
236 		}
237 
238 		/*
239 		 * Initialize other field of the object wrapper.
240 		 */
241 		new_object->is_lib_obj = B_FALSE;
242 		new_object->magic_marker = KERNELTOKEN_OBJECT_MAGIC;
243 		new_object->session_handle = (CK_SESSION_HANDLE)session_p;
244 		(void) pthread_mutex_init(&new_object->object_mutex, NULL);
245 
246 		if (is_pri_obj)
247 			new_object->bool_attr_mask |= PRIVATE_BOOL_ON;
248 		else
249 			new_object->bool_attr_mask &= ~PRIVATE_BOOL_ON;
250 
251 		if (is_token_obj)
252 			new_object->bool_attr_mask |= TOKEN_BOOL_ON;
253 		else
254 			new_object->bool_attr_mask &= ~TOKEN_BOOL_ON;
255 
256 		/*
257 		 * Add the new copied object into the slot's token list
258 		 * or the session list.  We don't hold the slot lock.
259 		 */
260 		if (is_token_obj) {
261 			pslot = slot_table[session_p->ses_slotid];
262 
263 			/*
264 			 * Decrement the session reference count.
265 			 * We do not hold the session lock.
266 			 */
267 			OBJ_REFRELE(old_object);
268 			REFRELE(session_p, ses_lock_held);
269 
270 			/* Add into the slot token object list. */
271 			kernel_add_token_object_to_slot(new_object, pslot);
272 		} else {
273 			kernel_add_object_to_session(new_object, session_p);
274 
275 			/*
276 			 * Decrement the session reference count.
277 			 * We do not hold the session lock.
278 			 */
279 			OBJ_REFRELE(old_object);
280 			REFRELE(session_p, ses_lock_held);
281 		}
282 
283 		/* set handle of the new object */
284 		*phNewObject = (CK_ULONG)new_object;
285 	}
286 
287 	return (rv);
288 
289 failed_cleanup:
290 	if (new_object != NULL) {
291 		(void) free(new_object);
292 	}
293 
294 	OBJ_REFRELE(old_object);
295 	REFRELE(session_p, ses_lock_held);
296 	return (rv);
297 }
298 
299 
300 CK_RV
301 C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
302 {
303 	CK_RV rv;
304 	kernel_object_t *object_p;
305 	kernel_session_t *session_p = (kernel_session_t *)(hSession);
306 	kernel_slot_t	*pslot;
307 	boolean_t ses_lock_held = B_FALSE;
308 	CK_SESSION_HANDLE creating_session;
309 
310 	if (!kernel_initialized)
311 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
312 
313 	/*
314 	 * The reason that we don't call handle2session is because
315 	 * the argument hSession may not be the creating_session of
316 	 * the object to be destroyed, and we want to avoid the lock
317 	 * contention. The handle2session will be called later for
318 	 * the creating_session.
319 	 */
320 	if ((session_p == NULL) ||
321 	    (session_p->magic_marker != KERNELTOKEN_SESSION_MAGIC)) {
322 		return (CKR_SESSION_HANDLE_INVALID);
323 	}
324 
325 	/* Obtain the object pointer without incrementing reference count. */
326 	HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
327 	if (rv != CKR_OK) {
328 		return (rv);
329 	}
330 
331 	/* Only session objects can be destroyed at a read-only session. */
332 	if ((session_p->ses_RO) &&
333 	    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
334 		return (CKR_SESSION_READ_ONLY);
335 	}
336 
337 	/*
338 	 * If the object is a session object, obtain the session handle
339 	 * which object belongs to.  For a token object, we will use the
340 	 * session handle from the caller, because the session used to
341 	 * create the token object may no longer exist.
342 	 */
343 	if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON))
344 		creating_session = object_p->session_handle;
345 	else
346 		creating_session = hSession;
347 
348 	rv = handle2session(creating_session, &session_p);
349 	if (rv != CKR_OK) {
350 		return (rv);
351 	}
352 
353 	/*
354 	 * Set OBJECT_IS_DELETING flag so any access to this
355 	 * object will be rejected.
356 	 */
357 	(void) pthread_mutex_lock(&object_p->object_mutex);
358 	if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
359 		(void) pthread_mutex_unlock(&object_p->object_mutex);
360 		REFRELE(session_p, ses_lock_held);
361 		return (CKR_OBJECT_HANDLE_INVALID);
362 	}
363 	object_p->obj_delete_sync |= OBJECT_IS_DELETING;
364 	(void) pthread_mutex_unlock(&object_p->object_mutex);
365 
366 	if (object_p->bool_attr_mask & TOKEN_BOOL_ON) {
367 		/*
368 		 * The first FALSE boolean argument indicates that the caller
369 		 * does not hold the slot lock.  The second FALSE boolean
370 		 * argument indicates that the caller wants to clean up the
371 		 * object in the HW provider also.
372 		 */
373 		pslot = slot_table[session_p->ses_slotid];
374 		rv = kernel_delete_token_object(pslot, session_p, object_p,
375 		    B_FALSE, B_FALSE);
376 	} else {
377 		/*
378 		 * The first FALSE boolean argument indicates that the caller
379 		 * does not hold the session lock.  The second FALSE boolean
380 		 * argument indicates that the caller wants to clean the object
381 		 * in the HW provider also.
382 		 */
383 		rv = kernel_delete_session_object(session_p, object_p, B_FALSE,
384 		    B_FALSE);
385 	}
386 	/*
387 	 * Decrement the session reference count.
388 	 * We do not hold the session lock.
389 	 */
390 	REFRELE(session_p, ses_lock_held);
391 	return (rv);
392 }
393 
394 
395 CK_RV
396 C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
397     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
398 {
399 
400 	CK_RV rv = CKR_OK, rv1 = CKR_OK;
401 	kernel_object_t *object_p;
402 	kernel_session_t *session_p;
403 	boolean_t ses_lock_held = B_FALSE;
404 	crypto_object_get_attribute_value_t obj_get_attr;
405 	int i, r;
406 
407 	if (!kernel_initialized)
408 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
409 
410 	if ((pTemplate == NULL) || (ulCount == 0))
411 		return (CKR_ARGUMENTS_BAD);
412 
413 	/*
414 	 * Obtain the session pointer. Also, increment the session
415 	 * reference count.
416 	 */
417 	rv = handle2session(hSession, &session_p);
418 	if (rv != CKR_OK)
419 		return (rv);
420 
421 	/* Obtain the object pointer. */
422 	HANDLE2OBJECT(hObject, object_p, rv);
423 	if (rv != CKR_OK) {
424 		/*
425 		 * Decrement the session reference count.
426 		 * We do not hold the session lock.
427 		 */
428 		REFRELE(session_p, ses_lock_held);
429 		return (rv);
430 	}
431 
432 	/* Acquire the lock on the object. */
433 	(void) pthread_mutex_lock(&object_p->object_mutex);
434 
435 	if (object_p->is_lib_obj) {
436 		/*
437 		 * The object was created in the library. The library
438 		 * contains the value information of each attribute.
439 		 */
440 		for (i = 0; i < ulCount; i++) {
441 			/*
442 			 * Get the value of each attribute in the template.
443 			 * (We must process EVERY attribute in the template.)
444 			 */
445 			rv = kernel_get_attribute(object_p, &pTemplate[i]);
446 			if (rv != CKR_OK)
447 				/* At least we catch some type of error. */
448 				rv1 = rv;
449 		}
450 		rv = rv1;
451 		(void) pthread_mutex_unlock(&object_p->object_mutex);
452 	} else {
453 		/*
454 		 * The object was created in HW provider, call ioctl to get
455 		 * the values of attributes.
456 		 */
457 		obj_get_attr.og_session = session_p->k_session;
458 		obj_get_attr.og_handle = object_p->k_handle;
459 		(void) pthread_mutex_unlock(&object_p->object_mutex);
460 		obj_get_attr.og_count = ulCount;
461 
462 		rv = process_object_attributes(pTemplate, ulCount,
463 		    &obj_get_attr.og_attributes, NULL);
464 		if (rv != CKR_OK) {
465 			goto clean_exit;
466 		}
467 
468 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_ATTRIBUTE_VALUE,
469 		    &obj_get_attr)) < 0) {
470 			if (errno != EINTR)
471 				break;
472 		}
473 		if (r < 0) {
474 			rv = CKR_FUNCTION_FAILED;
475 		} else {
476 			rv = crypto2pkcs11_error_number(
477 			    obj_get_attr.og_return_value);
478 		}
479 
480 		/*
481 		 * The error codes CKR_ATTRIBUTE_SENSITIVE,
482 		 * CKR_ATTRIBUTE_TYPE_INVALID, and CKR_BUFFER_TOO_SMALL
483 		 * do not denote true errors for this function. If a call
484 		 * returns any of these three values, then the call must
485 		 * nonetheless have processed every attribute in the
486 		 * template.  Every attribute in the template whose value
487 		 * can be returned will be returned.
488 		 */
489 		if ((rv == CKR_OK) ||
490 		    (rv == CKR_ATTRIBUTE_SENSITIVE) ||
491 		    (rv == CKR_ATTRIBUTE_TYPE_INVALID) ||
492 		    (rv == CKR_BUFFER_TOO_SMALL)) {
493 			rv1 = get_object_attributes(pTemplate, ulCount,
494 			    obj_get_attr.og_attributes);
495 			if (rv1 != CKR_OK) {
496 				rv = rv1;
497 			}
498 		}
499 
500 		/* Free the attributes' allocated for the ioctl call. */
501 		free_object_attributes(obj_get_attr.og_attributes, ulCount);
502 	}
503 
504 clean_exit:
505 	/*
506 	 * Decrement the session reference count.
507 	 * We do not hold the session lock.
508 	 */
509 	OBJ_REFRELE(object_p);
510 	REFRELE(session_p, ses_lock_held);
511 	return (rv);
512 }
513 
514 
515 CK_RV
516 C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
517     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
518 {
519 	CK_RV rv = CKR_OK;
520 	kernel_object_t *object_p;
521 	kernel_object_t *new_object = NULL;
522 	kernel_session_t *session_p;
523 	boolean_t ses_lock_held = B_FALSE;
524 	crypto_object_set_attribute_value_t obj_set_attr;
525 	int i, r;
526 
527 	if (!kernel_initialized)
528 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
529 
530 	if ((pTemplate == NULL) || (ulCount == 0))
531 		return (CKR_ARGUMENTS_BAD);
532 
533 	/*
534 	 * Obtain the session pointer. Also, increment the session
535 	 * reference count.
536 	 */
537 	rv = handle2session(hSession, &session_p);
538 	if (rv != CKR_OK)
539 		return (rv);
540 
541 	/* Obtain the object pointer. */
542 	HANDLE2OBJECT(hObject, object_p, rv);
543 	if (rv != CKR_OK) {
544 		/*
545 		 * Decrement the session reference count.
546 		 * We do not hold the session lock.
547 		 */
548 		REFRELE(session_p, ses_lock_held);
549 		return (rv);
550 	}
551 
552 	/* lock the object */
553 	(void) pthread_mutex_lock(&object_p->object_mutex);
554 
555 	/*
556 	 * If the object was created in the HW provider, changing its
557 	 * attributes' values need to be done in the provider too.
558 	 */
559 	if (!object_p->is_lib_obj) {
560 
561 		/* Cannot modify a token object with a READ-ONLY session */
562 		if (session_p->ses_RO &&
563 		    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
564 			(void) pthread_mutex_unlock(&object_p->object_mutex);
565 			rv = CKR_SESSION_READ_ONLY;
566 			goto clean_exit;
567 		}
568 
569 		obj_set_attr.sa_session = session_p->k_session;
570 		obj_set_attr.sa_handle = object_p->k_handle;
571 		(void) pthread_mutex_unlock(&object_p->object_mutex);
572 		obj_set_attr.sa_count = ulCount;
573 		rv = process_object_attributes(pTemplate, ulCount,
574 		    &obj_set_attr.sa_attributes, NULL);
575 		if (rv != CKR_OK) {
576 			goto clean_exit;
577 		}
578 
579 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_SET_ATTRIBUTE_VALUE,
580 		    &obj_set_attr)) < 0) {
581 			if (errno != EINTR)
582 				break;
583 		}
584 		if (r < 0) {
585 			rv = CKR_FUNCTION_FAILED;
586 		} else {
587 			rv = crypto2pkcs11_error_number(
588 			    obj_set_attr.sa_return_value);
589 		}
590 
591 		/* Free the attributes' space allocated for the ioctl call. */
592 		free_object_attributes(obj_set_attr.sa_attributes, ulCount);
593 		goto clean_exit;
594 	}
595 
596 	/*
597 	 * if we come here, the object must have been created in the
598 	 * library.  The work will be done completely in the library.
599 	 *
600 	 * Copy the old object to a new object. We work on the copied
601 	 * version because in case of error we still keep the old one
602 	 * intact.
603 	 */
604 	rv = kernel_copy_object(object_p, &new_object, B_FALSE, NULL);
605 	(void) pthread_mutex_unlock(&object_p->object_mutex);
606 	if ((rv != CKR_OK) || (new_object == NULL)) {
607 		/*
608 		 * Most likely we ran out of space.
609 		 * Decrement the session reference count.
610 		 * We do not hold the session lock.
611 		 */
612 		goto clean_exit;
613 	}
614 
615 	for (i = 0; i < ulCount; i++) {
616 		/* Set the requested attribute into the new object. */
617 		rv = kernel_set_attribute(new_object, &pTemplate[i], B_FALSE,
618 		    session_p);
619 
620 		if (rv != CKR_OK) {
621 			kernel_cleanup_object(new_object);
622 			goto clean_exit;
623 		}
624 	}
625 
626 	/*
627 	 * We've successfully set all the requested attributes.
628 	 * Merge the new object with the old object, then destory
629 	 * the new one. The reason to do the merging is because we
630 	 * have to keep the original object handle (address of object).
631 	 */
632 	(void) pthread_mutex_lock(&object_p->object_mutex);
633 	kernel_merge_object(object_p, new_object);
634 	(void) pthread_mutex_unlock(&object_p->object_mutex);
635 
636 clean_exit:
637 	if (new_object != NULL)
638 		(void) free(new_object);
639 
640 	/*
641 	 * Decrement the session reference count.
642 	 * We do not hold the session lock.
643 	 */
644 	OBJ_REFRELE(object_p);
645 	REFRELE(session_p, ses_lock_held);
646 
647 	return (rv);
648 }
649 
650 
651 CK_RV
652 C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
653     CK_ULONG_PTR pulSize)
654 {
655 
656 	CK_RV rv = CKR_OK;
657 	kernel_object_t *object_p;
658 	kernel_session_t *session_p;
659 	boolean_t ses_lock_held = B_FALSE;
660 	crypto_object_get_size_t obj_gs;
661 	int r;
662 
663 	if (!kernel_initialized)
664 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
665 
666 	/* Check if pulSize is valid */
667 	if (pulSize == NULL) {
668 		return (CKR_ARGUMENTS_BAD);
669 	}
670 
671 	/*
672 	 * Obtain the session pointer. Also, increment the session
673 	 * reference count.
674 	 */
675 	rv = handle2session(hSession, &session_p);
676 	if (rv != CKR_OK)
677 		return (rv);
678 
679 	/* Obtain the object pointer. */
680 	HANDLE2OBJECT(hObject, object_p, rv);
681 	if (rv != CKR_OK) {
682 		/*
683 		 * Decrement the session reference count.
684 		 * We do not hold the session lock.
685 		 */
686 		REFRELE(session_p, ses_lock_held);
687 		return (rv);
688 	}
689 
690 	/* Acquire the lock on the object. */
691 	(void) pthread_mutex_lock(&object_p->object_mutex);
692 
693 	if (!object_p->is_lib_obj) {
694 		/*
695 		 * The object was created in HW provider, call the
696 		 * CRYPTO_OBJECT_GET_SIZE ioctl.
697 		 */
698 		obj_gs.gs_session = session_p->k_session;
699 		obj_gs.gs_handle = object_p->k_handle;
700 		(void) pthread_mutex_unlock(&object_p->object_mutex);
701 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_GET_SIZE,
702 		    &obj_gs)) < 0) {
703 			if (errno != EINTR)
704 				break;
705 		}
706 		if (r < 0) {
707 			rv = CKR_FUNCTION_FAILED;
708 		} else {
709 			rv = crypto2pkcs11_error_number(
710 			    obj_gs.gs_return_value);
711 		}
712 
713 		if (rv == CKR_OK) {
714 			*pulSize = obj_gs.gs_size;
715 		}
716 
717 	} else {
718 		rv = kernel_get_object_size(object_p, pulSize);
719 		(void) pthread_mutex_unlock(&object_p->object_mutex);
720 	}
721 
722 	/*
723 	 * Decrement the session reference count.
724 	 * We do not hold the session lock.
725 	 */
726 	OBJ_REFRELE(object_p);
727 	REFRELE(session_p, ses_lock_held);
728 	return (rv);
729 }
730 
731 
732 CK_RV
733 C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
734     CK_ULONG ulCount)
735 {
736 	CK_RV		rv;
737 	kernel_session_t	*session_p;
738 	boolean_t ses_lock_held = B_FALSE;
739 	kernel_slot_t *pslot;
740 	crypto_object_find_init_t obj_fi;
741 	int r;
742 
743 	if (!kernel_initialized)
744 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
745 
746 	/* Check the arguments */
747 	if ((ulCount > 0) && (pTemplate == NULL)) {
748 		return (CKR_ARGUMENTS_BAD);
749 	}
750 
751 	/*
752 	 * Obtain the session pointer. Also, increment the session
753 	 * reference count.
754 	 */
755 	rv = handle2session(sh, &session_p);
756 	if (rv != CKR_OK)
757 		return (rv);
758 
759 	/* Acquire the session lock */
760 	(void) pthread_mutex_lock(&session_p->session_mutex);
761 	ses_lock_held = B_TRUE;
762 
763 	/* Check to see if find operation is already active */
764 	if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
765 		/* decrement the session count, and unlock the mutex */
766 		REFRELE(session_p, ses_lock_held);
767 		return (CKR_OPERATION_ACTIVE);
768 	} else {
769 		/*
770 		 * This active flag will remain ON until application calls
771 		 * C_FindObjectsFinal.
772 		 */
773 		session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
774 	}
775 
776 
777 	/*
778 	 * If the HW provider supports object creation, we call the
779 	 * CRYPTO_OBJECT_FIND_INIT ioctl to initialize object finding.
780 	 * Otherwise, all the objects are created in the library and we
781 	 * do the find objects solely in the library.
782 	 */
783 	pslot = slot_table[session_p->ses_slotid];
784 	if (pslot->sl_func_list.fl_object_create) {
785 		obj_fi.fi_session = session_p->k_session;
786 		(void) pthread_mutex_unlock(&session_p->session_mutex);
787 		ses_lock_held = B_FALSE;
788 		obj_fi.fi_count = ulCount;
789 		rv = process_object_attributes(pTemplate, ulCount,
790 		    &obj_fi.fi_attributes, NULL);
791 		if (rv == CKR_OK) {
792 			while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_INIT,
793 			    &obj_fi)) < 0) {
794 				if (errno != EINTR)
795 					break;
796 			}
797 			if (r < 0) {
798 				rv = CKR_FUNCTION_FAILED;
799 			} else {
800 				rv = crypto2pkcs11_error_number(
801 				    obj_fi.fi_return_value);
802 			}
803 		}
804 
805 		/* Free the attributes' space allocated for the ioctl call. */
806 		free_object_attributes(obj_fi.fi_attributes, ulCount);
807 
808 	} else {
809 		(void) pthread_mutex_unlock(&session_p->session_mutex);
810 		ses_lock_held = B_FALSE;
811 		rv = kernel_find_objects_init(session_p,  pTemplate, ulCount);
812 	}
813 
814 	if (rv != CKR_OK) {
815 		(void) pthread_mutex_lock(&session_p->session_mutex);
816 		session_p->find_objects.flags = 0;
817 		(void) pthread_mutex_unlock(&session_p->session_mutex);
818 	}
819 
820 	/* decrement the session count, and unlock the mutex */
821 	REFRELE(session_p, ses_lock_held);
822 	return (rv);
823 
824 }
825 
826 CK_RV
827 C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject,
828     CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
829 {
830 	CK_RV rv = CKR_OK;
831 	kernel_slot_t		*pslot;
832 	kernel_session_t	*session_p;
833 	boolean_t ses_lock_held = B_FALSE;
834 	crypto_object_find_update_t obj_fu;
835 	int r;
836 
837 	if (!kernel_initialized)
838 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
839 
840 	/* check for invalid arguments */
841 	if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
842 	    (pulObjectCount == NULL)) {
843 		return (CKR_ARGUMENTS_BAD);
844 	}
845 
846 	if (ulMaxObjectCount == 0) {
847 		/* don't need to do anything, just return */
848 		*pulObjectCount = 0;
849 		return (CKR_OK);
850 	}
851 
852 	/*
853 	 * Obtain the session pointer. Also, increment the session
854 	 * reference count.
855 	 */
856 	rv = handle2session(sh, &session_p);
857 	if (rv != CKR_OK)
858 		return (rv);
859 
860 	/* Acquire the slot lock */
861 	pslot = slot_table[session_p->ses_slotid];
862 	(void) pthread_mutex_lock(&pslot->sl_mutex);
863 
864 	/* Acquire the session lock */
865 	(void) pthread_mutex_lock(&session_p->session_mutex);
866 	ses_lock_held = B_TRUE;
867 
868 	/* Check to see if find operation is active */
869 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
870 		rv = CKR_OPERATION_NOT_INITIALIZED;
871 		goto clean_exit;
872 	}
873 
874 	/*
875 	 * Similar to C_FindObjectInit(), if the HW provider supports object
876 	 * creation, we call the respective ioctl to find objects.
877 	 * Otherwise, all the objects are created in the library and we do
878 	 * the find objects solely in the library.
879 	 */
880 	if (pslot->sl_func_list.fl_object_create) {
881 		obj_fu.fu_session = session_p->k_session;
882 		obj_fu.fu_max_count = ulMaxObjectCount;
883 		obj_fu.fu_handles = (char *)calloc(1,
884 		    ulMaxObjectCount * sizeof (crypto_object_id_t));
885 		if (obj_fu.fu_handles == NULL) {
886 			rv = CKR_HOST_MEMORY;
887 			goto clean_exit;
888 		}
889 
890 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_UPDATE,
891 		    &obj_fu)) < 0) {
892 			if (errno != EINTR)
893 				break;
894 		}
895 		if (r < 0) {
896 			rv = CKR_FUNCTION_FAILED;
897 		} else {
898 			rv = crypto2pkcs11_error_number(
899 			    obj_fu.fu_return_value);
900 		}
901 
902 		if (rv == CKR_OK) {
903 			rv = process_found_objects(session_p, phObject,
904 			    pulObjectCount, obj_fu);
905 		}
906 		free(obj_fu.fu_handles);
907 
908 	} else {
909 
910 		kernel_find_objects(session_p, phObject, ulMaxObjectCount,
911 		    pulObjectCount);
912 		rv = CKR_OK;
913 	}
914 
915 clean_exit:
916 	/* decrement the session count, and release the session lock */
917 	REFRELE(session_p, ses_lock_held);
918 
919 	/* release the slot lock */
920 	(void) pthread_mutex_unlock(&pslot->sl_mutex);
921 
922 	return (rv);
923 }
924 
925 
926 CK_RV
927 C_FindObjectsFinal(CK_SESSION_HANDLE sh)
928 {
929 
930 	kernel_session_t	*session_p;
931 	CK_RV rv;
932 	boolean_t ses_lock_held = B_FALSE;
933 	kernel_slot_t *pslot;
934 	crypto_object_find_final_t obj_ff;
935 	int r;
936 
937 	if (!kernel_initialized)
938 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
939 
940 	/*
941 	 * Obtain the session pointer. Also, increment the session
942 	 * reference count.
943 	 */
944 	rv = handle2session(sh, &session_p);
945 	if (rv != CKR_OK)
946 		return (rv);
947 
948 	/* Acquire the session lock */
949 	(void) pthread_mutex_lock(&session_p->session_mutex);
950 	ses_lock_held = B_TRUE;
951 
952 	/* Check to see if find operation is active */
953 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
954 		REFRELE(session_p, ses_lock_held);
955 		return (CKR_OPERATION_NOT_INITIALIZED);
956 	}
957 
958 	/*
959 	 * Similar to C_FindObjectInit(), if the HW provider supports object
960 	 * creation, we need to call the CRYPTO_OBJECT_FIND_FINAL ioctl.
961 	 */
962 	pslot = slot_table[session_p->ses_slotid];
963 	if (pslot->sl_func_list.fl_object_create) {
964 		obj_ff.ff_session = session_p->k_session;
965 		while ((r = ioctl(kernel_fd, CRYPTO_OBJECT_FIND_FINAL,
966 		    &obj_ff)) < 0) {
967 			if (errno != EINTR)
968 				break;
969 		}
970 		if (r < 0) {
971 			rv = CKR_FUNCTION_FAILED;
972 		} else {
973 			rv = crypto2pkcs11_error_number(
974 			    obj_ff.ff_return_value);
975 		}
976 
977 		/* only need to reset find_objects.flags */
978 		if (rv == CKR_OK) {
979 			session_p->find_objects.flags = 0;
980 		}
981 
982 	} else {
983 		/*
984 		 * The find object operations were done in the library, we
985 		 * need to cleanup find_objects context.
986 		 */
987 		kernel_find_objects_final(session_p);
988 		rv = CKR_OK;
989 	}
990 
991 	/* decrement the session count, and release the lock */
992 	REFRELE(session_p, ses_lock_held);
993 	return (rv);
994 }
995