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