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