xref: /onnv-gate/usr/src/lib/pkcs11/pkcs11_kms/common/kmsObject.c (revision 12720:3db6e0082404)
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 /*
23  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24  */
25 
26 
27 #include <pthread.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <errno.h>
31 #include <string.h>
32 #include <security/cryptoki.h>
33 #include "kmsGlobal.h"
34 #include "kmsObject.h"
35 #include "kmsSession.h"
36 
37 CK_RV
C_CreateObject(CK_SESSION_HANDLE hSession,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phObject)38 C_CreateObject(CK_SESSION_HANDLE hSession,
39     CK_ATTRIBUTE_PTR pTemplate,
40     CK_ULONG ulCount,
41     CK_OBJECT_HANDLE_PTR phObject)
42 {
43 
44 	CK_RV rv;
45 	kms_session_t *session_p;
46 	boolean_t ses_lock_held = B_FALSE;
47 
48 	if (!kms_initialized)
49 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
50 
51 	if ((pTemplate == NULL) || (ulCount == 0) ||
52 	    (phObject == NULL)) {
53 		return (CKR_ARGUMENTS_BAD);
54 	}
55 
56 	/*
57 	 * Obtain the session pointer. Also, increment the session
58 	 * reference count.
59 	 */
60 	rv = handle2session(hSession, &session_p);
61 	if (rv != CKR_OK)
62 		return (rv);
63 
64 	/* Create a new object. */
65 	rv = kms_add_object(pTemplate, ulCount, phObject, session_p);
66 
67 	/*
68 	 * Decrement the session reference count.
69 	 * We do not hold the session lock.
70 	 */
71 	REFRELE(session_p, ses_lock_held);
72 
73 	return (rv);
74 }
75 
76 CK_RV
C_CopyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount,CK_OBJECT_HANDLE_PTR phNewObject)77 C_CopyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
78     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount,
79     CK_OBJECT_HANDLE_PTR phNewObject)
80 {
81 
82 	CK_RV rv;
83 	kms_session_t *session_p;
84 	boolean_t ses_lock_held = B_FALSE;
85 	kms_object_t *old_object;
86 	kms_object_t *new_object = NULL;
87 	int i;
88 
89 	if (!kms_initialized)
90 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
91 
92 	/* Check arguments */
93 	if (((ulCount > 0) && (pTemplate == NULL)) ||
94 	    (phNewObject == NULL)) {
95 		return (CKR_ARGUMENTS_BAD);
96 	}
97 
98 	/*
99 	 * Obtain the session pointer. Also, increment the session
100 	 * reference count.
101 	 */
102 	rv = handle2session(hSession, &session_p);
103 	if (rv != CKR_OK)
104 		return (rv);
105 
106 	/* Obtain the object pointer. */
107 	HANDLE2OBJECT(hObject, old_object, rv);
108 	if (rv != CKR_OK) {
109 		/*
110 		 * Decrement the session reference count.
111 		 * We do not hold the session lock.
112 		 */
113 		REFRELE(session_p, ses_lock_held);
114 		return (rv);
115 	}
116 
117 	(void) pthread_mutex_lock(&old_object->object_mutex);
118 
119 	if (old_object->is_lib_obj) {
120 		/*
121 		 * Copy the old object to a new object.
122 		 * The 3rd argument with TRUE value indicates that
123 		 * everything in the object will be duplicated.
124 		 */
125 		rv = kms_copy_object(old_object, &new_object, B_TRUE,
126 		    session_p);
127 		(void) pthread_mutex_unlock(&old_object->object_mutex);
128 		if ((rv != CKR_OK) || (new_object == NULL)) {
129 			/*
130 			 * Most likely we ran out of space.
131 			 * Decrement the session reference count.
132 			 * We do not hold the session lock.
133 			 */
134 			OBJ_REFRELE(old_object);
135 			REFRELE(session_p, ses_lock_held);
136 			return (rv);
137 		}
138 
139 		new_object->is_lib_obj = B_TRUE;
140 
141 		/* Modify the object attribute if requested */
142 		for (i = 0; i < ulCount; i++) {
143 			/* Set the requested attribute into the new object. */
144 			rv = kms_set_attribute(new_object, &pTemplate[i],
145 			    B_TRUE);
146 
147 			if (rv != CKR_OK) {
148 				kms_cleanup_object(new_object);
149 				OBJ_REFRELE(old_object);
150 				REFRELE(session_p, ses_lock_held);
151 				return (rv);
152 			}
153 		}
154 
155 		/* Insert the new object into this session's object list. */
156 		kms_add_object_to_session(new_object, session_p);
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 
165 		/* set handle of the new object */
166 		*phNewObject = (CK_ULONG)new_object;
167 
168 	}
169 
170 	return (rv);
171 
172 failed_cleanup:
173 	if (new_object != NULL) {
174 		(void) kms_free_object(new_object);
175 	}
176 
177 	OBJ_REFRELE(old_object);
178 	REFRELE(session_p, ses_lock_held);
179 	return (rv);
180 }
181 
182 CK_RV
C_DestroyObject(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject)183 C_DestroyObject(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject)
184 {
185 	CK_RV rv;
186 	kms_object_t *object_p;
187 	kms_session_t *session_p = (kms_session_t *)(hSession);
188 	kms_slot_t	*pslot;
189 	boolean_t ses_lock_held = B_FALSE;
190 	CK_SESSION_HANDLE creating_session;
191 
192 	if (!kms_initialized)
193 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
194 
195 	/*
196 	 * The reason that we don't call handle2session is because
197 	 * the argument hSession may not be the creating_session of
198 	 * the object to be destroyed, and we want to avoid the lock
199 	 * contention. The handle2session will be called later for
200 	 * the creating_session.
201 	 */
202 	if ((session_p == NULL) ||
203 	    (session_p->magic_marker != KMSTOKEN_SESSION_MAGIC)) {
204 		return (CKR_SESSION_HANDLE_INVALID);
205 	}
206 	/* Obtain the object pointer without incrementing reference count. */
207 	HANDLE2OBJECT_DESTROY(hObject, object_p, rv);
208 	if (rv != CKR_OK) {
209 		return (rv);
210 	}
211 
212 	/* Only session objects can be destroyed at a read-only session. */
213 	if ((session_p->ses_RO) &&
214 	    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
215 		return (CKR_SESSION_READ_ONLY);
216 	}
217 
218 
219 	/*
220 	 * If the object is a session object, obtain the session handle
221 	 * which object belongs to.  For a token object, we will use the
222 	 * session handle from the caller, because the session used to
223 	 * create the token object may no longer exist.
224 	 */
225 	if (!(object_p->bool_attr_mask & TOKEN_BOOL_ON))
226 		creating_session = object_p->session_handle;
227 	else
228 		creating_session = hSession;
229 
230 	rv = handle2session(creating_session, &session_p);
231 	if (rv != CKR_OK) {
232 		return (rv);
233 	}
234 
235 	/*
236 	 * Set OBJECT_IS_DELETING flag so any access to this
237 	 * object will be rejected.
238 	 */
239 	(void) pthread_mutex_lock(&object_p->object_mutex);
240 	if (object_p->obj_delete_sync & OBJECT_IS_DELETING) {
241 		(void) pthread_mutex_unlock(&object_p->object_mutex);
242 		REFRELE(session_p, ses_lock_held);
243 		return (CKR_OBJECT_HANDLE_INVALID);
244 	}
245 	object_p->obj_delete_sync |= OBJECT_IS_DELETING;
246 	(void) pthread_mutex_unlock(&object_p->object_mutex);
247 
248 	if (object_p->bool_attr_mask & TOKEN_BOOL_ON) {
249 		/*
250 		 * The first FALSE boolean argument indicates that the caller
251 		 * does not hold the slot lock.  The second FALSE boolean
252 		 * argument indicates that the caller wants to clean up the
253 		 * object in the HW provider also.
254 		 */
255 		pslot = get_slotinfo();
256 		rv = kms_delete_token_object(pslot, session_p, object_p,
257 		    B_FALSE, B_FALSE);
258 	} else {
259 		/*
260 		 * The first FALSE boolean argument indicates that the caller
261 		 * does not hold the session lock.  The second FALSE boolean
262 		 * argument indicates that the caller wants to clean the object
263 		 * in the HW provider also.
264 		 */
265 		rv = kms_delete_object(session_p, object_p, B_FALSE,
266 		    B_FALSE);
267 	}
268 	/*
269 	 * Decrement the session reference count.
270 	 * We do not hold the session lock.
271 	 */
272 	REFRELE(session_p, ses_lock_held);
273 	return (rv);
274 }
275 
276 CK_RV
C_GetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)277 C_GetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
278     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
279 {
280 
281 	CK_RV rv = CKR_OK, rv1 = CKR_OK;
282 	kms_object_t *object_p;
283 	kms_session_t *session_p;
284 	boolean_t ses_lock_held = B_FALSE;
285 	int i;
286 
287 	if (!kms_initialized)
288 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
289 
290 	if ((pTemplate == NULL) || (ulCount == 0))
291 		return (CKR_ARGUMENTS_BAD);
292 
293 	/*
294 	 * Obtain the session pointer. Also, increment the session
295 	 * reference count.
296 	 */
297 	rv = handle2session(hSession, &session_p);
298 	if (rv != CKR_OK)
299 		return (rv);
300 
301 	/* Obtain the object pointer. */
302 	HANDLE2OBJECT(hObject, object_p, rv);
303 	if (rv != CKR_OK) {
304 		/*
305 		 * Decrement the session reference count.
306 		 * We do not hold the session lock.
307 		 */
308 		REFRELE(session_p, ses_lock_held);
309 		return (rv);
310 	}
311 
312 	/* Acquire the lock on the object. */
313 	(void) pthread_mutex_lock(&object_p->object_mutex);
314 
315 	/*
316 	 * The object was created in the library. The library
317 	 * contains the value information of each attribute.
318 	 */
319 	for (i = 0; i < ulCount; i++) {
320 		/*
321 		 * Get the value of each attribute in the template.
322 		 * (We must process EVERY attribute in the template.)
323 		 */
324 		rv = kms_get_attribute(object_p, &pTemplate[i]);
325 		if (rv != CKR_OK)
326 			rv1 = rv;
327 	}
328 	(void) pthread_mutex_unlock(&object_p->object_mutex);
329 
330 clean_exit:
331 	/*
332 	 * Decrement the session reference count.
333 	 * We do not hold the session lock.
334 	 */
335 	OBJ_REFRELE(object_p);
336 	REFRELE(session_p, ses_lock_held);
337 	rv = rv1;
338 	return (rv);
339 }
340 
341 CK_RV
C_SetAttributeValue(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)342 C_SetAttributeValue(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
343     CK_ATTRIBUTE_PTR pTemplate, CK_ULONG ulCount)
344 {
345 	CK_RV rv = CKR_OK;
346 	kms_object_t *object_p;
347 	kms_object_t *new_object = NULL;
348 	kms_session_t *session_p;
349 	boolean_t ses_lock_held = B_FALSE;
350 	int i;
351 
352 	if (!kms_initialized)
353 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
354 
355 	if ((pTemplate == NULL) || (ulCount == 0))
356 		return (CKR_ARGUMENTS_BAD);
357 
358 	/*
359 	 * Obtain the session pointer. Also, increment the session
360 	 * reference count.
361 	 */
362 	rv = handle2session(hSession, &session_p);
363 	if (rv != CKR_OK)
364 		return (rv);
365 
366 	/* Obtain the object pointer. */
367 	HANDLE2OBJECT(hObject, object_p, rv);
368 	if (rv != CKR_OK) {
369 		/*
370 		 * Decrement the session reference count.
371 		 * We do not hold the session lock.
372 		 */
373 		REFRELE(session_p, ses_lock_held);
374 		return (rv);
375 	}
376 
377 	/* lock the object */
378 	(void) pthread_mutex_lock(&object_p->object_mutex);
379 
380 	/*
381 	 * If the object was created in the HW provider, changing its
382 	 * attributes' values need to be done in the provider too.
383 	 */
384 	if (!object_p->is_lib_obj) {
385 
386 		/* Cannot modify a token object with a READ-ONLY session */
387 		if (session_p->ses_RO &&
388 		    (object_p->bool_attr_mask & TOKEN_BOOL_ON)) {
389 			(void) pthread_mutex_unlock(&object_p->object_mutex);
390 			rv = CKR_SESSION_READ_ONLY;
391 			goto clean_exit;
392 		}
393 	}
394 
395 	/*
396 	 * if we come here, the object must have been created in the
397 	 * library.  The work will be done completely in the library.
398 	 *
399 	 * Copy the old object to a new object. We work on the copied
400 	 * version because in case of error we still keep the old one
401 	 * intact.
402 	 */
403 	rv = kms_copy_object(object_p, &new_object, B_FALSE, NULL);
404 	(void) pthread_mutex_unlock(&object_p->object_mutex);
405 	if ((rv != CKR_OK) || (new_object == NULL)) {
406 		/*
407 		 * Most likely we ran out of space.
408 		 * Decrement the session reference count.
409 		 * We do not hold the session lock.
410 		 */
411 		goto clean_exit;
412 	}
413 
414 	for (i = 0; i < ulCount; i++) {
415 		/* Set the requested attribute into the new object. */
416 		rv = kms_set_attribute(new_object, &pTemplate[i], B_FALSE);
417 
418 		if (rv != CKR_OK) {
419 			kms_cleanup_object(new_object);
420 			goto clean_exit;
421 		}
422 	}
423 
424 	/*
425 	 * We've successfully set all the requested attributes.
426 	 * Merge the new object with the old object, then destory
427 	 * the new one. The reason to do the merging is because we
428 	 * have to keep the original object handle (address of object).
429 	 */
430 	(void) pthread_mutex_lock(&object_p->object_mutex);
431 	kms_merge_object(object_p, new_object);
432 	(void) pthread_mutex_unlock(&object_p->object_mutex);
433 
434 clean_exit:
435 	if (new_object != NULL)
436 		(void) kms_free_object(new_object);
437 
438 	/*
439 	 * Decrement the session reference count.
440 	 * We do not hold the session lock.
441 	 */
442 	OBJ_REFRELE(object_p);
443 	REFRELE(session_p, ses_lock_held);
444 
445 	return (rv);
446 }
447 
448 CK_RV
C_GetObjectSize(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hObject,CK_ULONG_PTR pulSize)449 C_GetObjectSize(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hObject,
450     CK_ULONG_PTR pulSize)
451 {
452 
453 	CK_RV rv = CKR_OK;
454 	kms_object_t *object_p;
455 	kms_session_t *session_p;
456 	boolean_t ses_lock_held = B_FALSE;
457 
458 	if (!kms_initialized)
459 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
460 
461 	/* Check if pulSize is valid */
462 	if (pulSize == NULL) {
463 		return (CKR_ARGUMENTS_BAD);
464 	}
465 
466 	/*
467 	 * Obtain the session pointer. Also, increment the session
468 	 * reference count.
469 	 */
470 	rv = handle2session(hSession, &session_p);
471 	if (rv != CKR_OK)
472 		return (rv);
473 
474 	/* Obtain the object pointer. */
475 	HANDLE2OBJECT(hObject, object_p, rv);
476 	if (rv != CKR_OK) {
477 		/*
478 		 * Decrement the session reference count.
479 		 * We do not hold the session lock.
480 		 */
481 		REFRELE(session_p, ses_lock_held);
482 		return (rv);
483 	}
484 
485 	/* Acquire the lock on the object. */
486 	(void) pthread_mutex_lock(&object_p->object_mutex);
487 
488 	rv = kms_get_object_size(object_p, pulSize);
489 
490 	(void) pthread_mutex_unlock(&object_p->object_mutex);
491 
492 	/*
493 	 * Decrement the session reference count.
494 	 * We do not hold the session lock.
495 	 */
496 	OBJ_REFRELE(object_p);
497 	REFRELE(session_p, ses_lock_held);
498 	return (rv);
499 }
500 
501 CK_RV
C_FindObjectsInit(CK_SESSION_HANDLE sh,CK_ATTRIBUTE_PTR pTemplate,CK_ULONG ulCount)502 C_FindObjectsInit(CK_SESSION_HANDLE sh, CK_ATTRIBUTE_PTR pTemplate,
503     CK_ULONG ulCount)
504 {
505 	CK_RV		rv;
506 	kms_session_t	*session_p;
507 	boolean_t ses_lock_held = B_FALSE;
508 
509 	if (!kms_initialized)
510 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
511 
512 	/* Check the arguments */
513 	if ((ulCount > 0) && (pTemplate == NULL)) {
514 		return (CKR_ARGUMENTS_BAD);
515 	}
516 
517 	/*
518 	 * Obtain the session pointer. Also, increment the session
519 	 * reference count.
520 	 */
521 	rv = handle2session(sh, &session_p);
522 	if (rv != CKR_OK)
523 		return (rv);
524 
525 	/* Acquire the session lock */
526 	(void) pthread_mutex_lock(&session_p->session_mutex);
527 	ses_lock_held = B_TRUE;
528 
529 	/* Check to see if find operation is already active */
530 	if (session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE) {
531 		/* decrement the session count, and unlock the mutex */
532 		REFRELE(session_p, ses_lock_held);
533 		return (CKR_OPERATION_ACTIVE);
534 	} else {
535 		/*
536 		 * This active flag will remain ON until application calls
537 		 * C_FindObjectsFinal.
538 		 */
539 		session_p->find_objects.flags = CRYPTO_OPERATION_ACTIVE;
540 	}
541 	(void) pthread_mutex_unlock(&session_p->session_mutex);
542 
543 	/*
544 	 * If the KMS provider supports object creation, we call the
545 	 * CRYPTO_OBJECT_FIND_INIT to initialize object finding.
546 	 * Otherwise, all the objects are created in the library and we
547 	 * do the find objects solely in the library.
548 	 */
549 	rv = kms_find_objects_init(session_p, pTemplate, ulCount);
550 	if (rv != CKR_OK) {
551 		(void) pthread_mutex_lock(&session_p->session_mutex);
552 		session_p->find_objects.flags = 0;
553 		(void) pthread_mutex_unlock(&session_p->session_mutex);
554 	}
555 	/* decrement the session count, and unlock the mutex */
556 	REFRELE(session_p, ses_lock_held);
557 	return (rv);
558 }
559 
560 CK_RV
C_FindObjects(CK_SESSION_HANDLE sh,CK_OBJECT_HANDLE_PTR phObject,CK_ULONG ulMaxObjectCount,CK_ULONG_PTR pulObjectCount)561 C_FindObjects(CK_SESSION_HANDLE sh, CK_OBJECT_HANDLE_PTR phObject,
562     CK_ULONG ulMaxObjectCount, CK_ULONG_PTR pulObjectCount)
563 {
564 	CK_RV rv = CKR_OK;
565 	kms_slot_t		*pslot = NULL;
566 	kms_session_t	*session_p;
567 	boolean_t ses_lock_held = B_FALSE;
568 
569 	if (!kms_initialized)
570 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
571 
572 	/* check for invalid arguments */
573 	if (((phObject == NULL) && (ulMaxObjectCount != 0)) ||
574 	    (pulObjectCount == NULL)) {
575 		return (CKR_ARGUMENTS_BAD);
576 	}
577 
578 	if (ulMaxObjectCount == 0) {
579 		/* don't need to do anything, just return */
580 		*pulObjectCount = 0;
581 		return (CKR_OK);
582 	}
583 
584 	/*
585 	 * Obtain the session pointer. Also, increment the session
586 	 * reference count.
587 	 */
588 	rv = handle2session(sh, &session_p);
589 	if (rv != CKR_OK)
590 		return (rv);
591 
592 	/* Acquire the slot lock */
593 	pslot = get_slotinfo();
594 	(void) pthread_mutex_lock(&pslot->sl_mutex);
595 
596 	/* Acquire the session lock */
597 	(void) pthread_mutex_lock(&session_p->session_mutex);
598 	ses_lock_held = B_TRUE;
599 
600 	/* Check to see if find operation is active */
601 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
602 		rv = CKR_OPERATION_NOT_INITIALIZED;
603 		goto clean_exit;
604 	}
605 
606 	/*
607 	 * Similar to C_FindObjectInit(), if the KMS provider supports object
608 	 * creation, we need to find objects.
609 	 * Otherwise, all the objects are created in the library and we do
610 	 * the find objects solely in the library.
611 	 */
612 
613 	rv = kms_find_objects(session_p, phObject,
614 	    ulMaxObjectCount, pulObjectCount);
615 
616 clean_exit:
617 	/* decrement the session count, and release the session lock */
618 	REFRELE(session_p, ses_lock_held);
619 
620 	/* release the slot lock */
621 	if (pslot)
622 		(void) pthread_mutex_unlock(&pslot->sl_mutex);
623 
624 	return (rv);
625 }
626 
627 CK_RV
C_FindObjectsFinal(CK_SESSION_HANDLE sh)628 C_FindObjectsFinal(CK_SESSION_HANDLE sh)
629 {
630 	kms_session_t	*session_p;
631 	CK_RV rv;
632 	boolean_t ses_lock_held = B_FALSE;
633 
634 	if (!kms_initialized)
635 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
636 
637 	/*
638 	 * Obtain the session pointer. Also, increment the session
639 	 * reference count.
640 	 */
641 	rv = handle2session(sh, &session_p);
642 	if (rv != CKR_OK)
643 		return (rv);
644 
645 	/* Acquire the session lock */
646 	(void) pthread_mutex_lock(&session_p->session_mutex);
647 	ses_lock_held = B_TRUE;
648 
649 	/* Check to see if find operation is active */
650 	if (!(session_p->find_objects.flags & CRYPTO_OPERATION_ACTIVE)) {
651 		REFRELE(session_p, ses_lock_held);
652 		return (CKR_OPERATION_NOT_INITIALIZED);
653 	}
654 
655 	/*
656 	 * Similar to C_FindObjectInit(), if the KMS provider supports object
657 	 * creation, we need to finalize the search on the KMS side.
658 	 */
659 	kms_find_objects_final(session_p);
660 
661 	/* decrement the session count, and release the lock */
662 	REFRELE(session_p, ses_lock_held);
663 	return (rv);
664 }
665