xref: /titanic_44/usr/src/lib/pkcs11/pkcs11_kernel/common/kernelVerify.c (revision 990b4856d0eaada6f8140335733a1b1771ed2746)
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 2007 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 <stdlib.h>
30 #include <errno.h>
31 #include <sys/crypto/ioctl.h>
32 #include <security/cryptoki.h>
33 #include "kernelGlobal.h"
34 #include "kernelObject.h"
35 #include "kernelSession.h"
36 #include "kernelEmulate.h"
37 
38 CK_RV
39 C_VerifyInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
40     CK_OBJECT_HANDLE hKey)
41 {
42 	CK_RV rv;
43 	kernel_session_t *session_p;
44 	kernel_object_t	*key_p;
45 	boolean_t ses_lock_held = B_FALSE;
46 	crypto_verify_init_t verify_init;
47 	crypto_mech_type_t k_mech_type;
48 	int r;
49 
50 	if (!kernel_initialized)
51 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
52 
53 	if (pMechanism == NULL) {
54 		return (CKR_ARGUMENTS_BAD);
55 	}
56 
57 	/* Get the kernel's internal mechanism number. */
58 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
59 	if (rv != CKR_OK)
60 		return (rv);
61 
62 	/* Obtain the session pointer. */
63 	rv = handle2session(hSession, &session_p);
64 	if (rv != CKR_OK)
65 		return (rv);
66 
67 	/* Obtain the object pointer. */
68 	HANDLE2OBJECT(hKey, key_p, rv);
69 	if (rv != CKR_OK) {
70 		REFRELE(session_p, ses_lock_held);
71 		return (rv);
72 	}
73 
74 	/* Check to see if key object supports verification. */
75 	if (key_p->is_lib_obj && !(key_p->bool_attr_mask & VERIFY_BOOL_ON)) {
76 		rv = CKR_KEY_TYPE_INCONSISTENT;
77 		goto clean_exit;
78 	}
79 
80 	(void) pthread_mutex_lock(&session_p->session_mutex);
81 	ses_lock_held = B_TRUE;
82 
83 	/*
84 	 * This active flag will remain ON until application calls either
85 	 * C_Verify or C_VerifyFinal to verify a signature on data.
86 	 */
87 	session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
88 
89 	if (!key_p->is_lib_obj) {
90 		verify_init.vi_key.ck_format = CRYPTO_KEY_REFERENCE;
91 		verify_init.vi_key.ck_obj_id = key_p->k_handle;
92 	} else {
93 		if (key_p->class == CKO_SECRET_KEY) {
94 			verify_init.vi_key.ck_format = CRYPTO_KEY_RAW;
95 			verify_init.vi_key.ck_data =
96 			    get_symmetric_key_value(key_p);
97 			if (verify_init.vi_key.ck_data == NULL) {
98 				rv = CKR_HOST_MEMORY;
99 				goto clean_exit;
100 			}
101 			verify_init.vi_key.ck_length =
102 			    OBJ_SEC(key_p)->sk_value_len << 3;
103 
104 		} else if (key_p->key_type == CKK_RSA) {
105 			if (get_rsa_public_key(key_p, &verify_init.vi_key) !=
106 			    CKR_OK) {
107 				rv = CKR_HOST_MEMORY;
108 				goto clean_exit;
109 			}
110 		} else if (key_p->key_type == CKK_DSA) {
111 			if (get_dsa_public_key(key_p, &verify_init.vi_key) !=
112 			    CKR_OK) {
113 				rv = CKR_HOST_MEMORY;
114 				goto clean_exit;
115 			}
116 		} else if (key_p->key_type == CKK_EC) {
117 			if (get_ec_public_key(key_p, &verify_init.vi_key) !=
118 			    CKR_OK) {
119 				rv = CKR_HOST_MEMORY;
120 				goto clean_exit;
121 			}
122 		} else {
123 			rv = CKR_KEY_TYPE_INCONSISTENT;
124 			goto clean_exit;
125 		}
126 	}
127 
128 	verify_init.vi_session = session_p->k_session;
129 	(void) pthread_mutex_unlock(&session_p->session_mutex);
130 	ses_lock_held = B_FALSE;
131 	verify_init.vi_mech.cm_type = k_mech_type;
132 	verify_init.vi_mech.cm_param = pMechanism->pParameter;
133 	verify_init.vi_mech.cm_param_len = pMechanism->ulParameterLen;
134 
135 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_INIT, &verify_init)) < 0) {
136 		if (errno != EINTR)
137 			break;
138 	}
139 	if (r < 0) {
140 		rv = CKR_FUNCTION_FAILED;
141 	} else {
142 		rv = crypto2pkcs11_error_number(verify_init.vi_return_value);
143 	}
144 
145 	if (rv == CKR_OK && SLOT_HAS_LIMITED_HASH(session_p) &&
146 	    is_hmac(pMechanism->mechanism)) {
147 		if (key_p->is_lib_obj && key_p->class == CKO_SECRET_KEY) {
148 			(void) pthread_mutex_lock(&session_p->session_mutex);
149 			session_p->verify.flags |= CRYPTO_EMULATE;
150 			(void) pthread_mutex_unlock(&session_p->session_mutex);
151 			rv = emulate_init(session_p, pMechanism,
152 			    &(verify_init.vi_key), OP_VERIFY);
153 		} else {
154 			rv = CKR_FUNCTION_FAILED;
155 		}
156 	}
157 
158 	/* free the memory allocated for verify_init.vi_key */
159 	if (key_p->is_lib_obj) {
160 		if (key_p->class == CKO_SECRET_KEY) {
161 			free(verify_init.vi_key.ck_data);
162 		} else {
163 			free_key_attributes(&verify_init.vi_key);
164 		}
165 	}
166 
167 	if (rv != CKR_OK) {
168 		(void) pthread_mutex_lock(&session_p->session_mutex);
169 		session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
170 		ses_lock_held = B_TRUE;
171 	}
172 
173 clean_exit:
174 	OBJ_REFRELE(key_p);
175 	REFRELE(session_p, ses_lock_held);
176 	return (rv);
177 }
178 
179 
180 CK_RV
181 C_Verify(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
182     CK_BYTE_PTR pSignature, CK_ULONG ulSignatureLen)
183 {
184 
185 	CK_RV rv;
186 	kernel_session_t *session_p;
187 	boolean_t ses_lock_held = B_FALSE;
188 	crypto_verify_t verify;
189 	int r;
190 
191 	if (!kernel_initialized)
192 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
193 
194 	/* Obatin the session pointer */
195 	rv = handle2session(hSession, &session_p);
196 	if (rv != CKR_OK)
197 		return (rv);
198 
199 	(void) pthread_mutex_lock(&session_p->session_mutex);
200 	ses_lock_held = B_TRUE;
201 
202 	/* Application must call C_VerifyInit before calling C_Verify. */
203 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
204 		REFRELE(session_p, ses_lock_held);
205 		return (CKR_OPERATION_NOT_INITIALIZED);
206 	}
207 
208 	/*
209 	 * C_Verify must be called without intervening C_VerifyUpdate
210 	 * calls.
211 	 */
212 	if (session_p->verify.flags & CRYPTO_OPERATION_UPDATE) {
213 		/*
214 		 * C_Verify can not be used to terminate a multi-part
215 		 * operation, so we'll leave the active verify operation
216 		 * flag on and let the application continue with the
217 		 * verify update operation.
218 		 */
219 		REFRELE(session_p, ses_lock_held);
220 		return (CKR_FUNCTION_FAILED);
221 	}
222 
223 	if (session_p->verify.flags & CRYPTO_EMULATE) {
224 		if ((ulDataLen < SLOT_THRESHOLD(session_p)) ||
225 		    (ulDataLen > SLOT_MAX_INDATA_LEN(session_p))) {
226 			session_p->verify.flags |= CRYPTO_EMULATE_USING_SW;
227 			(void) pthread_mutex_unlock(&session_p->session_mutex);
228 
229 			rv = do_soft_hmac_verify(get_spp(&session_p->verify),
230 			    pData, ulDataLen,
231 			    pSignature, ulSignatureLen, OP_SINGLE);
232 			goto clean_exit;
233 		} else {
234 			free_soft_ctx(get_sp(&session_p->verify), OP_VERIFY);
235 		}
236 	}
237 
238 	verify.cv_session = session_p->k_session;
239 	(void) pthread_mutex_unlock(&session_p->session_mutex);
240 	ses_lock_held = B_FALSE;
241 	verify.cv_datalen = ulDataLen;
242 	verify.cv_databuf = (char *)pData;
243 	verify.cv_signlen = ulSignatureLen;
244 	verify.cv_signbuf = (char *)pSignature;
245 
246 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY, &verify)) < 0) {
247 		if (errno != EINTR)
248 			break;
249 	}
250 	if (r < 0) {
251 		rv = CKR_FUNCTION_FAILED;
252 	} else {
253 		rv = crypto2pkcs11_error_number(verify.cv_return_value);
254 	}
255 
256 clean_exit:
257 	/*
258 	 * Always terminate the active verify operation.
259 	 * Application needs to call C_VerifyInit again for next
260 	 * verify operation.
261 	 */
262 	(void) pthread_mutex_lock(&session_p->session_mutex);
263 
264 	REINIT_OPBUF(&session_p->verify);
265 	session_p->verify.flags = 0;
266 	ses_lock_held = B_TRUE;
267 	REFRELE(session_p, ses_lock_held);
268 
269 	return (rv);
270 }
271 
272 
273 CK_RV
274 C_VerifyUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
275     CK_ULONG ulPartLen)
276 {
277 
278 	CK_RV rv;
279 	kernel_session_t *session_p;
280 	boolean_t ses_lock_held = B_FALSE;
281 	crypto_verify_update_t verify_update;
282 	int r;
283 
284 	if (!kernel_initialized)
285 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
286 
287 	/* Obtain the session pointer */
288 	rv = handle2session(hSession, &session_p);
289 	if (rv != CKR_OK)
290 		return (rv);
291 
292 	if (pPart == NULL) {
293 		rv = CKR_ARGUMENTS_BAD;
294 		goto clean_exit;
295 	}
296 
297 	(void) pthread_mutex_lock(&session_p->session_mutex);
298 	ses_lock_held = B_TRUE;
299 
300 	/*
301 	 * Application must call C_VerifyInit before calling
302 	 * C_VerifyUpdate.
303 	 */
304 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
305 		REFRELE(session_p, ses_lock_held);
306 		return (CKR_OPERATION_NOT_INITIALIZED);
307 	}
308 
309 	session_p->verify.flags |= CRYPTO_OPERATION_UPDATE;
310 
311 	if (session_p->verify.flags & CRYPTO_EMULATE) {
312 		(void) pthread_mutex_unlock(&session_p->session_mutex);
313 		rv = emulate_update(session_p, pPart, ulPartLen, OP_VERIFY);
314 		goto done;
315 	}
316 
317 	verify_update.vu_session = session_p->k_session;
318 	(void) pthread_mutex_unlock(&session_p->session_mutex);
319 	ses_lock_held = B_FALSE;
320 
321 	verify_update.vu_datalen = ulPartLen;
322 	verify_update.vu_databuf = (char *)pPart;
323 
324 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_UPDATE,
325 	    &verify_update)) < 0) {
326 		if (errno != EINTR)
327 			break;
328 	}
329 	if (r < 0) {
330 		rv = CKR_FUNCTION_FAILED;
331 	} else {
332 		rv = crypto2pkcs11_error_number(verify_update.vu_return_value);
333 	}
334 
335 done:
336 	if (rv == CKR_OK) {
337 		REFRELE(session_p, ses_lock_held);
338 		return (rv);
339 	}
340 
341 clean_exit:
342 	/*
343 	 * After an error occurred, terminate the current verify
344 	 * operation by resetting the active and update flags.
345 	 */
346 	(void) pthread_mutex_lock(&session_p->session_mutex);
347 	REINIT_OPBUF(&session_p->verify);
348 	session_p->verify.flags = 0;
349 	ses_lock_held = B_TRUE;
350 	REFRELE(session_p, ses_lock_held);
351 
352 	return (rv);
353 }
354 
355 
356 CK_RV
357 C_VerifyFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
358     CK_ULONG ulSignatureLen)
359 {
360 
361 	CK_RV rv;
362 	kernel_session_t *session_p;
363 	boolean_t ses_lock_held = B_FALSE;
364 	crypto_verify_final_t verify_final;
365 	int r;
366 
367 	if (!kernel_initialized)
368 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
369 
370 	/* Obtain the session pointer */
371 	rv = handle2session(hSession, &session_p);
372 	if (rv != CKR_OK)
373 		return (rv);
374 
375 	(void) pthread_mutex_lock(&session_p->session_mutex);
376 	ses_lock_held = B_TRUE;
377 
378 	/*
379 	 * Application must call C_VerifyInit before calling
380 	 * C_VerifyFinal.
381 	 */
382 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
383 		REFRELE(session_p, ses_lock_held);
384 		return (CKR_OPERATION_NOT_INITIALIZED);
385 	}
386 
387 	/* The order of checks is important here */
388 	if (session_p->verify.flags & CRYPTO_EMULATE_USING_SW) {
389 		if (session_p->verify.flags & CRYPTO_EMULATE_UPDATE_DONE) {
390 			(void) pthread_mutex_unlock(&session_p->session_mutex);
391 			rv = do_soft_hmac_verify(get_spp(&session_p->verify),
392 			    NULL, 0, pSignature, ulSignatureLen,
393 			    OP_FINAL);
394 		} else {
395 			/*
396 			 * We should not end up here even if an earlier
397 			 * C_VerifyFinal() call took the C_Verify() path as
398 			 * it never returns CKR_BUFFER_TOO_SMALL.
399 			 */
400 			rv = CKR_ARGUMENTS_BAD;
401 		}
402 		goto clean_exit;
403 	} else if (session_p->verify.flags & CRYPTO_EMULATE) {
404 		digest_buf_t *bufp = session_p->verify.context;
405 
406 		/*
407 		 * We are emulating a single-part operation now.
408 		 * So, clear the flag.
409 		 */
410 		session_p->verify.flags &= ~CRYPTO_OPERATION_UPDATE;
411 		if (bufp == NULL || bufp->buf == NULL) {
412 			rv = CKR_ARGUMENTS_BAD;
413 			goto clean_exit;
414 		}
415 		REFRELE(session_p, ses_lock_held);
416 		rv = C_Verify(hSession, bufp->buf, bufp->indata_len,
417 		    pSignature, ulSignatureLen);
418 		return (rv);
419 	}
420 
421 	verify_final.vf_session = session_p->k_session;
422 	(void) pthread_mutex_unlock(&session_p->session_mutex);
423 	ses_lock_held = B_FALSE;
424 
425 	verify_final.vf_signlen = ulSignatureLen;
426 	verify_final.vf_signbuf = (char *)pSignature;
427 
428 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_FINAL, &verify_final)) < 0) {
429 		if (errno != EINTR)
430 			break;
431 	}
432 	if (r < 0) {
433 		rv = CKR_FUNCTION_FAILED;
434 	} else {
435 		rv = crypto2pkcs11_error_number(verify_final.vf_return_value);
436 	}
437 
438 clean_exit:
439 	/* Always terminate the active verify operation */
440 	(void) pthread_mutex_lock(&session_p->session_mutex);
441 	REINIT_OPBUF(&session_p->verify);
442 	session_p->verify.flags = 0;
443 	ses_lock_held = B_TRUE;
444 	REFRELE(session_p, ses_lock_held);
445 
446 	return (rv);
447 }
448 
449 
450 CK_RV
451 C_VerifyRecoverInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism,
452     CK_OBJECT_HANDLE hKey)
453 {
454 
455 	CK_RV rv;
456 	kernel_session_t *session_p;
457 	kernel_object_t	*key_p;
458 	boolean_t ses_lock_held = B_FALSE;
459 	crypto_verify_recover_init_t vr_init;
460 	crypto_mech_type_t k_mech_type;
461 	int r;
462 
463 	if (!kernel_initialized)
464 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
465 
466 	if (pMechanism == NULL) {
467 		return (CKR_ARGUMENTS_BAD);
468 	}
469 
470 	/* Get the kernel's internal mechanism number. */
471 	rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
472 	if (rv != CKR_OK)
473 		return (rv);
474 
475 	/* Obtain the session pointer. */
476 	rv = handle2session(hSession, &session_p);
477 	if (rv != CKR_OK)
478 		return (rv);
479 
480 	/* Obtain the object pointer. */
481 	HANDLE2OBJECT(hKey, key_p, rv);
482 	if (rv != CKR_OK) {
483 		REFRELE(session_p, ses_lock_held);
484 		return (rv);
485 	}
486 
487 	/*
488 	 * Check to see if key object is a RSA key and if it supports
489 	 * verify_recover.
490 	 */
491 	if (key_p->is_lib_obj && !((key_p->key_type == CKK_RSA) &&
492 	    (key_p->bool_attr_mask & VERIFY_RECOVER_BOOL_ON))) {
493 		rv = CKR_KEY_TYPE_INCONSISTENT;
494 		goto clean_exit;
495 	}
496 
497 	(void) pthread_mutex_lock(&session_p->session_mutex);
498 	ses_lock_held = B_TRUE;
499 
500 	/*
501 	 * This active flag will remain ON until application calls
502 	 * C_VerifyRecover to verify a signature on data.
503 	 */
504 	session_p->verify.flags = CRYPTO_OPERATION_ACTIVE;
505 
506 	/* Set up the key data */
507 	if (!key_p->is_lib_obj) {
508 		vr_init.ri_key.ck_format = CRYPTO_KEY_REFERENCE;
509 		vr_init.ri_key.ck_obj_id = key_p->k_handle;
510 	} else {
511 		if (key_p->key_type == CKK_RSA) {
512 			if (get_rsa_public_key(key_p, &vr_init.ri_key) !=
513 			    CKR_OK) {
514 				rv = CKR_HOST_MEMORY;
515 				goto clean_exit;
516 			}
517 		} else {
518 			rv = CKR_KEY_TYPE_INCONSISTENT;
519 			goto clean_exit;
520 		}
521 	}
522 
523 	vr_init.ri_session = session_p->k_session;
524 	(void) pthread_mutex_unlock(&session_p->session_mutex);
525 	ses_lock_held = B_FALSE;
526 	vr_init.ri_mech.cm_type = k_mech_type;
527 	vr_init.ri_mech.cm_param = pMechanism->pParameter;
528 	vr_init.ri_mech.cm_param_len = pMechanism->ulParameterLen;
529 
530 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER_INIT,
531 	    &vr_init)) < 0) {
532 		if (errno != EINTR)
533 			break;
534 	}
535 	if (r < 0) {
536 		rv = CKR_FUNCTION_FAILED;
537 	} else {
538 		rv = crypto2pkcs11_error_number(vr_init.ri_return_value);
539 	}
540 
541 	/* free the memory allocated for vr_init.ri_key */
542 	if (key_p->is_lib_obj) {
543 		free_key_attributes(&vr_init.ri_key);
544 	}
545 
546 	if (rv != CKR_OK) {
547 		(void) pthread_mutex_lock(&session_p->session_mutex);
548 		session_p->verify.flags &= ~CRYPTO_OPERATION_ACTIVE;
549 		ses_lock_held = B_TRUE;
550 	}
551 
552 clean_exit:
553 	OBJ_REFRELE(key_p);
554 	REFRELE(session_p, ses_lock_held);
555 	return (rv);
556 }
557 
558 
559 CK_RV
560 C_VerifyRecover(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pSignature,
561     CK_ULONG ulSignatureLen, CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen)
562 {
563 
564 	CK_RV rv;
565 	kernel_session_t *session_p;
566 	boolean_t ses_lock_held = B_FALSE;
567 	crypto_verify_recover_t verify_recover;
568 	int r;
569 
570 	if (!kernel_initialized)
571 		return (CKR_CRYPTOKI_NOT_INITIALIZED);
572 
573 	/* Obtain the session pointer */
574 	rv = handle2session(hSession, &session_p);
575 	if (rv != CKR_OK)
576 		return (rv);
577 
578 	if (pSignature == NULL || pulDataLen == NULL) {
579 		rv = CKR_ARGUMENTS_BAD;
580 		goto clean_exit;
581 	}
582 
583 	(void) pthread_mutex_lock(&session_p->session_mutex);
584 	ses_lock_held = B_TRUE;
585 
586 	/*
587 	 * Application must call C_VerifyRecoverInit before calling
588 	 * C_Verify.
589 	 */
590 	if (!(session_p->verify.flags & CRYPTO_OPERATION_ACTIVE)) {
591 		REFRELE(session_p, ses_lock_held);
592 		return (CKR_OPERATION_NOT_INITIALIZED);
593 	}
594 
595 	verify_recover.vr_session = session_p->k_session;
596 	(void) pthread_mutex_unlock(&session_p->session_mutex);
597 	ses_lock_held = B_FALSE;
598 	verify_recover.vr_signlen = ulSignatureLen;
599 	verify_recover.vr_signbuf = (char *)pSignature;
600 	verify_recover.vr_datalen = *pulDataLen;
601 	verify_recover.vr_databuf = (char *)pData;
602 
603 	while ((r = ioctl(kernel_fd, CRYPTO_VERIFY_RECOVER,
604 	    &verify_recover)) < 0) {
605 		if (errno != EINTR)
606 			break;
607 	}
608 	if (r < 0) {
609 		rv = CKR_FUNCTION_FAILED;
610 	} else {
611 		rv = crypto2pkcs11_error_number(
612 		    verify_recover.vr_return_value);
613 	}
614 
615 	if (rv == CKR_OK || rv == CKR_BUFFER_TOO_SMALL)
616 		*pulDataLen = verify_recover.vr_datalen;
617 
618 	if ((rv == CKR_BUFFER_TOO_SMALL) ||
619 	    (rv == CKR_OK && pData == NULL)) {
620 		/*
621 		 * We will not terminate the active verify operation flag,
622 		 * when the application-supplied buffer is too small, or
623 		 * the application asks for the length of buffer to hold
624 		 * the recovered data.
625 		 */
626 		REFRELE(session_p, ses_lock_held);
627 		return (rv);
628 	}
629 
630 clean_exit:
631 	/*
632 	 * Always terminate the active verify operation.
633 	 * Application needs to call C_VerifyInit again for next
634 	 * verify operation.
635 	 */
636 	(void) pthread_mutex_lock(&session_p->session_mutex);
637 	session_p->verify.flags = 0;
638 	ses_lock_held = B_TRUE;
639 	REFRELE(session_p, ses_lock_held);
640 
641 	return (rv);
642 }
643