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