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 * Copyright 2018, Joyent, Inc.
26 */
27
28 #include <pthread.h>
29 #include <errno.h>
30 #include <sys/crypto/ioctl.h>
31 #include <security/cryptoki.h>
32 #include "kernelGlobal.h"
33 #include "kernelSession.h"
34 #include "kernelEmulate.h"
35
36 static CK_RV
common_digest_init(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,boolean_t is_external_caller)37 common_digest_init(CK_SESSION_HANDLE hSession,
38 CK_MECHANISM_PTR pMechanism, boolean_t is_external_caller)
39 {
40 CK_RV rv;
41 kernel_session_t *session_p;
42 boolean_t ses_lock_held = B_FALSE;
43 crypto_digest_init_t digest_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 */
56 rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
57 if (rv != CKR_OK)
58 return (rv);
59
60 /*
61 * Obtain the session pointer. Also, increment the session
62 * reference count.
63 */
64 rv = handle2session(hSession, &session_p);
65 if (rv != CKR_OK)
66 return (rv);
67
68 /* Acquire the session lock */
69 (void) pthread_mutex_lock(&session_p->session_mutex);
70 ses_lock_held = B_TRUE;
71
72 /*
73 * This active flag will remain ON until application calls either
74 * C_Digest or C_DigestFinal to actually obtain the value of
75 * the message digest.
76 */
77 session_p->digest.flags |= CRYPTO_OPERATION_ACTIVE;
78
79 if (SLOT_HAS_LIMITED_HASH(session_p) && is_external_caller) {
80 session_p->digest.mech.mechanism = pMechanism->mechanism;
81 session_p->digest.mech.pParameter = NULL;
82 session_p->digest.mech.ulParameterLen = 0;
83 session_p->digest.flags |= CRYPTO_EMULATE;
84 rv = emulate_buf_init(session_p, EDIGEST_LENGTH, OP_DIGEST);
85 REFRELE(session_p, ses_lock_held);
86 return (rv);
87 }
88
89 digest_init.di_session = session_p->k_session;
90 (void) pthread_mutex_unlock(&session_p->session_mutex);
91 ses_lock_held = B_FALSE;
92 digest_init.di_mech.cm_type = k_mech_type;
93 digest_init.di_mech.cm_param = pMechanism->pParameter;
94
95 /*
96 * If pParameter is NULL, set cm_param_len to be 0, so that ioctl call
97 * will have a clean input data.
98 */
99 if (pMechanism->pParameter != NULL)
100 digest_init.di_mech.cm_param_len = pMechanism->ulParameterLen;
101 else
102 digest_init.di_mech.cm_param_len = 0;
103
104 while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_INIT, &digest_init)) < 0) {
105 if (errno != EINTR)
106 break;
107 }
108 if (r < 0) {
109 rv = CKR_FUNCTION_FAILED;
110 } else {
111 rv = crypto2pkcs11_error_number(digest_init.di_return_value);
112 }
113
114 if (rv != CKR_OK) {
115 (void) pthread_mutex_lock(&session_p->session_mutex);
116 ses_lock_held = B_TRUE;
117 session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE;
118 /*
119 * Decrement the session reference count.
120 * We hold the session lock, and REFRELE()
121 * will release the session lock for us.
122 */
123 REFRELE(session_p, ses_lock_held);
124 return (rv);
125 }
126
127 /*
128 * Decrement the session reference count.
129 * We do not hold the session lock.
130 */
131 REFRELE(session_p, ses_lock_held);
132 return (rv);
133 }
134
135 CK_RV
C_DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism)136 C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
137 {
138 return (common_digest_init(hSession, pMechanism, B_TRUE));
139 }
140
141 CK_RV
C_Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)142 C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
143 CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
144 {
145 CK_RV rv;
146 kernel_session_t *session_p;
147 boolean_t ses_lock_held = B_FALSE;
148 crypto_digest_t digest;
149 int r;
150
151 if (!kernel_initialized)
152 return (CKR_CRYPTOKI_NOT_INITIALIZED);
153
154 /*
155 * Obtain the session pointer. Also, increment the session
156 * reference count.
157 */
158 rv = handle2session(hSession, &session_p);
159 if (rv != CKR_OK)
160 return (rv);
161
162 if ((pData == NULL && ulDataLen != 0) || pulDigestLen == NULL) {
163 rv = CKR_ARGUMENTS_BAD;
164 goto clean_exit;
165 }
166
167 /* Acquire the session lock */
168 (void) pthread_mutex_lock(&session_p->session_mutex);
169 ses_lock_held = B_TRUE;
170
171 /* Application must call C_DigestInit before calling C_Digest */
172 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
173 /*
174 * Decrement the session reference count.
175 * We hold the session lock, and REFRELE()
176 * will release the session lock for us.
177 */
178 REFRELE(session_p, ses_lock_held);
179 return (CKR_OPERATION_NOT_INITIALIZED);
180 }
181
182 /*
183 * C_Digest must be called without intervening C_DigestUpdate
184 * calls.
185 */
186 if (session_p->digest.flags & CRYPTO_OPERATION_UPDATE) {
187 /*
188 * C_Digest can not be used to terminate a multi-part
189 * operation, so we'll leave the active digest operation
190 * flag on and let the application continue with the
191 * digest update operation.
192 *
193 * Decrement the session reference count.
194 * We hold the session lock, and REFRELE()
195 * will release the session lock for us.
196 */
197 REFRELE(session_p, ses_lock_held);
198 return (CKR_FUNCTION_FAILED);
199 }
200
201 if (session_p->digest.flags & CRYPTO_EMULATE) {
202 crypto_active_op_t *opp;
203 CK_MECHANISM_PTR pMechanism;
204
205 opp = &(session_p->digest);
206 if (opp->context == NULL) {
207 REFRELE(session_p, ses_lock_held);
208 return (CKR_ARGUMENTS_BAD);
209 }
210 pMechanism = &(opp->mech);
211
212 if ((ulDataLen < SLOT_THRESHOLD(session_p)) ||
213 (ulDataLen > SLOT_HASH_MAX_INDATA_LEN(session_p))) {
214 session_p->digest.flags |= CRYPTO_EMULATE_USING_SW;
215 (void) pthread_mutex_unlock(&session_p->session_mutex);
216 ses_lock_held = B_FALSE;
217
218 rv = do_soft_digest(get_spp(opp), pMechanism,
219 pData, ulDataLen, pDigest, pulDigestLen,
220 OP_INIT | OP_SINGLE);
221 goto done;
222 } else if (!(session_p->digest.flags &
223 CRYPTO_EMULATE_INIT_DONE)) {
224 session_p->digest.flags |= CRYPTO_EMULATE_INIT_DONE;
225 (void) pthread_mutex_unlock(&session_p->session_mutex);
226 ses_lock_held = B_FALSE;
227
228 rv = common_digest_init(hSession, pMechanism, B_FALSE);
229 if (rv != CKR_OK)
230 goto clean_exit;
231 (void) pthread_mutex_lock(&session_p->session_mutex);
232 ses_lock_held = B_TRUE;
233 }
234 }
235
236 digest.cd_session = session_p->k_session;
237 (void) pthread_mutex_unlock(&session_p->session_mutex);
238 ses_lock_held = B_FALSE;
239 digest.cd_datalen = ulDataLen;
240 digest.cd_databuf = (char *)pData;
241 digest.cd_digestbuf = (char *)pDigest;
242 digest.cd_digestlen = *pulDigestLen;
243
244 while ((r = ioctl(kernel_fd, CRYPTO_DIGEST, &digest)) < 0) {
245 if (errno != EINTR)
246 break;
247 }
248 if (r < 0) {
249 rv = CKR_FUNCTION_FAILED;
250 } else {
251 rv = crypto2pkcs11_error_number(digest.cd_return_value);
252 }
253
254 if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL))
255 *pulDigestLen = digest.cd_digestlen;
256
257 done:
258 if ((rv == CKR_BUFFER_TOO_SMALL) ||
259 (rv == CKR_OK && pDigest == NULL)) {
260 /*
261 * We will not terminate the active digest operation flag,
262 * when the application-supplied buffer is too small, or
263 * the application asks for the length of buffer to hold
264 * the message digest.
265 *
266 * Decrement the session reference count.
267 * We do not hold the session lock.
268 */
269 REFRELE(session_p, ses_lock_held);
270 return (rv);
271 }
272
273 clean_exit:
274 /*
275 * Terminates the active digest operation.
276 * Application needs to call C_DigestInit again for next
277 * digest operation.
278 */
279 (void) pthread_mutex_lock(&session_p->session_mutex);
280 ses_lock_held = B_TRUE;
281
282 REINIT_OPBUF(&session_p->digest);
283 session_p->digest.flags = 0;
284
285 /*
286 * Decrement the session reference count.
287 * We hold the session lock, and REFRELE()
288 * will release the session lock for us.
289 */
290 REFRELE(session_p, ses_lock_held);
291
292 return (rv);
293 }
294
295 CK_RV
C_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)296 C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
297 CK_ULONG ulPartLen)
298 {
299
300 CK_RV rv;
301 kernel_session_t *session_p;
302 boolean_t ses_lock_held = B_FALSE;
303 crypto_digest_update_t digest_update;
304 int r;
305
306 if (!kernel_initialized)
307 return (CKR_CRYPTOKI_NOT_INITIALIZED);
308
309 /*
310 * Obtain the session pointer. Also, increment the session
311 * reference count.
312 */
313 rv = handle2session(hSession, &session_p);
314 if (rv != CKR_OK)
315 return (rv);
316
317 if (pPart == NULL) {
318 rv = CKR_ARGUMENTS_BAD;
319 goto clean_exit;
320 }
321
322 /* Acquire the session lock */
323 (void) pthread_mutex_lock(&session_p->session_mutex);
324 ses_lock_held = B_TRUE;
325
326 /*
327 * Application must call C_DigestInit before calling
328 * C_DigestUpdate.
329 */
330 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
331 /*
332 * Decrement the session reference count.
333 * We hold the session lock, and REFRELE()
334 * will release the session lock for us.
335 */
336 REFRELE(session_p, ses_lock_held);
337 return (CKR_OPERATION_NOT_INITIALIZED);
338 }
339
340 /* Set update flag to protect C_Digest */
341 session_p->digest.flags |= CRYPTO_OPERATION_UPDATE;
342
343 if (session_p->digest.flags & CRYPTO_EMULATE) {
344 (void) pthread_mutex_unlock(&session_p->session_mutex);
345 ses_lock_held = B_FALSE;
346 rv = emulate_update(session_p, pPart, ulPartLen, OP_DIGEST);
347 goto done;
348 }
349
350 digest_update.du_session = session_p->k_session;
351 (void) pthread_mutex_unlock(&session_p->session_mutex);
352 ses_lock_held = B_FALSE;
353 digest_update.du_datalen = ulPartLen;
354 digest_update.du_databuf = (char *)pPart;
355
356 while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_UPDATE,
357 &digest_update)) < 0) {
358 if (errno != EINTR)
359 break;
360 }
361 if (r < 0) {
362 rv = CKR_FUNCTION_FAILED;
363 } else {
364 rv = crypto2pkcs11_error_number(digest_update.du_return_value);
365 }
366
367 done:
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 (CKR_OK);
375 }
376
377 clean_exit:
378 /*
379 * After an error occurred, terminate the current digest
380 * operation by resetting the active and update flags.
381 */
382 (void) pthread_mutex_lock(&session_p->session_mutex);
383 ses_lock_held = B_TRUE;
384 REINIT_OPBUF(&session_p->digest);
385 session_p->digest.flags = 0;
386
387 /*
388 * Decrement the session reference count.
389 * We hold the session lock, and REFRELE()
390 * will release the session lock for us.
391 */
392 REFRELE(session_p, ses_lock_held);
393
394 return (rv);
395 }
396
397
398 CK_RV
C_DigestKey(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hKey)399 C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
400 {
401
402 CK_RV rv;
403 kernel_session_t *session_p;
404 kernel_object_t *key_p;
405 boolean_t ses_lock_held = B_FALSE;
406 CK_BYTE_PTR pPart;
407 CK_ULONG ulPartLen;
408 crypto_digest_key_t digest_key;
409 crypto_digest_update_t digest_update;
410 int r;
411
412 if (!kernel_initialized)
413 return (CKR_CRYPTOKI_NOT_INITIALIZED);
414
415 /*
416 * Obtain the session pointer. Also, increment the session
417 * reference count.
418 */
419 rv = handle2session(hSession, &session_p);
420 if (rv != CKR_OK)
421 return (rv);
422
423 /* Obtain the object pointer. */
424 HANDLE2OBJECT(hKey, key_p, rv);
425 if (rv != CKR_OK) {
426 (void) pthread_mutex_lock(&session_p->session_mutex);
427 ses_lock_held = B_TRUE;
428 REINIT_OPBUF(&session_p->digest);
429 session_p->digest.flags = 0;
430 REFRELE(session_p, ses_lock_held);
431 return (rv);
432 }
433
434 /* Check the key type */
435 if (key_p->is_lib_obj && (key_p->class != CKO_SECRET_KEY)) {
436 rv = CKR_KEY_INDIGESTIBLE;
437 goto clean_exit;
438 }
439
440 /*
441 * Application must call C_DigestInit before calling
442 * C_DigestKey.
443 */
444 (void) pthread_mutex_lock(&session_p->session_mutex);
445 ses_lock_held = B_TRUE;
446
447 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
448 /*
449 * Decrement the session reference count.
450 * We hold the session lock, and REFRELE()
451 * will release the session lock for us.
452 */
453 OBJ_REFRELE(key_p);
454 REFRELE(session_p, ses_lock_held);
455 return (CKR_OPERATION_NOT_INITIALIZED);
456 }
457 session_p->digest.flags |= CRYPTO_OPERATION_UPDATE;
458
459 /*
460 * If the key object is from the HW provider, call CRYPTO_DIGEST_KEY
461 * ioctl. Otherwise, call CRYPTO_DIGEST_UPDATE ioctl and pass the key
462 * by value.
463 */
464 if (key_p->is_lib_obj) {
465 digest_update.du_session = session_p->k_session;
466 } else {
467 digest_key.dk_session = session_p->k_session;
468 }
469 (void) pthread_mutex_unlock(&session_p->session_mutex);
470 ses_lock_held = B_FALSE;
471
472 if (!key_p->is_lib_obj) {
473 if (session_p->digest.flags & CRYPTO_EMULATE) {
474 rv = CKR_FUNCTION_NOT_SUPPORTED;
475 goto clean_exit;
476 }
477 digest_key.dk_key.ck_format = CRYPTO_KEY_REFERENCE;
478 digest_key.dk_key.ck_obj_id = key_p->k_handle;
479 while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_KEY,
480 &digest_key)) < 0) {
481 if (errno != EINTR)
482 break;
483 }
484 if (r < 0) {
485 rv = CKR_FUNCTION_FAILED;
486 } else {
487 rv = crypto2pkcs11_error_number(
488 digest_key.dk_return_value);
489 }
490 } else {
491 ulPartLen = OBJ_SEC_VALUE_LEN(key_p);
492 if (ulPartLen == 0) {
493 rv = CKR_KEY_SIZE_RANGE;
494 goto clean_exit;
495 }
496
497 pPart = (CK_BYTE_PTR) OBJ_SEC_VALUE(key_p);
498 if (pPart == NULL) {
499 rv = CKR_KEY_HANDLE_INVALID;
500 goto clean_exit;
501 }
502
503 (void) pthread_mutex_lock(&session_p->session_mutex);
504 ses_lock_held = B_TRUE;
505 if (session_p->digest.flags & CRYPTO_EMULATE) {
506 (void) pthread_mutex_unlock(&session_p->session_mutex);
507 ses_lock_held = B_FALSE;
508 rv = emulate_update(session_p, pPart,
509 ulPartLen, OP_DIGEST);
510 goto done;
511 }
512 (void) pthread_mutex_unlock(&session_p->session_mutex);
513 ses_lock_held = B_FALSE;
514
515 digest_update.du_datalen = ulPartLen;
516 digest_update.du_databuf = (char *)pPart;
517
518 while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_UPDATE,
519 &digest_update)) < 0) {
520 if (errno != EINTR)
521 break;
522 }
523 if (r < 0) {
524 rv = CKR_FUNCTION_FAILED;
525 } else {
526 rv = crypto2pkcs11_error_number(
527 digest_update.du_return_value);
528 }
529 }
530
531 done:
532 if (rv == CKR_OK) {
533 /*
534 * Decrement the session reference count.
535 * We do not hold the session lock.
536 */
537 OBJ_REFRELE(key_p);
538 REFRELE(session_p, ses_lock_held);
539 return (CKR_OK);
540 }
541
542 clean_exit:
543 OBJ_REFRELE(key_p);
544 /*
545 * After an error occurred, terminate the current digest
546 * operation by resetting the active and update flags.
547 */
548 (void) pthread_mutex_lock(&session_p->session_mutex);
549 ses_lock_held = B_TRUE;
550 REINIT_OPBUF(&session_p->digest);
551 session_p->digest.flags = 0;
552
553 /*
554 * Decrement the session reference count.
555 * We hold the session lock, and REFRELE()
556 * will release the session lock for us.
557 */
558 REFRELE(session_p, ses_lock_held);
559 return (rv);
560 }
561
562
563 CK_RV
C_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)564 C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
565 CK_ULONG_PTR pulDigestLen)
566 {
567
568 CK_RV rv;
569 kernel_session_t *session_p;
570 boolean_t ses_lock_held = B_FALSE;
571 crypto_digest_final_t digest_final;
572 int r;
573
574 if (!kernel_initialized)
575 return (CKR_CRYPTOKI_NOT_INITIALIZED);
576
577 /*
578 * Obtain the session pointer. Also, increment the session
579 * reference count.
580 */
581 rv = handle2session(hSession, &session_p);
582 if (rv != CKR_OK)
583 return (rv);
584
585 if (pulDigestLen == NULL) {
586 rv = CKR_ARGUMENTS_BAD;
587 goto clean_exit;
588 }
589
590 /* Acquire the session lock */
591 (void) pthread_mutex_lock(&session_p->session_mutex);
592 ses_lock_held = B_TRUE;
593
594 /*
595 * Application must call C_DigestInit before calling
596 * C_DigestFinal.
597 */
598 if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
599 /*
600 * Decrement the session reference count.
601 * We hold the session lock, and REFRELE()
602 * will release the session lock for us.
603 */
604 REFRELE(session_p, ses_lock_held);
605 return (CKR_OPERATION_NOT_INITIALIZED);
606 }
607
608 /* The order of checks is important here */
609 if (session_p->digest.flags & CRYPTO_EMULATE_USING_SW) {
610 if (session_p->digest.flags & CRYPTO_EMULATE_UPDATE_DONE) {
611 (void) pthread_mutex_unlock(&session_p->session_mutex);
612 ses_lock_held = B_FALSE;
613 rv = do_soft_digest(get_spp(&session_p->digest),
614 NULL, NULL, 0, pDigest, pulDigestLen, OP_FINAL);
615 } else {
616 /*
617 * We end up here if an earlier C_DigestFinal() call
618 * took the C_Digest() path and it had returned
619 * CKR_BUFFER_TOO_SMALL.
620 */
621 digest_buf_t *bufp = session_p->digest.context;
622 (void) pthread_mutex_unlock(&session_p->session_mutex);
623 ses_lock_held = B_FALSE;
624 if (bufp == NULL || bufp->buf == NULL) {
625 rv = CKR_ARGUMENTS_BAD;
626 goto clean_exit;
627 }
628 rv = do_soft_digest(get_spp(&session_p->digest),
629 NULL, bufp->buf, bufp->indata_len,
630 pDigest, pulDigestLen, OP_SINGLE);
631 }
632 goto done;
633 } else if (session_p->digest.flags & CRYPTO_EMULATE) {
634 digest_buf_t *bufp = session_p->digest.context;
635
636 /*
637 * We are emulating a single-part operation now.
638 * So, clear the flag.
639 */
640 session_p->digest.flags &= ~CRYPTO_OPERATION_UPDATE;
641 if (bufp == NULL || bufp->buf == NULL) {
642 rv = CKR_ARGUMENTS_BAD;
643 goto clean_exit;
644 }
645 REFRELE(session_p, ses_lock_held);
646 rv = C_Digest(hSession, bufp->buf, bufp->indata_len,
647 pDigest, pulDigestLen);
648 return (rv);
649 }
650
651 digest_final.df_session = session_p->k_session;
652 (void) pthread_mutex_unlock(&session_p->session_mutex);
653 ses_lock_held = B_FALSE;
654 digest_final.df_digestlen = *pulDigestLen;
655 digest_final.df_digestbuf = (char *)pDigest;
656
657 while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_FINAL, &digest_final)) < 0) {
658 if (errno != EINTR)
659 break;
660 }
661 if (r < 0) {
662 rv = CKR_FUNCTION_FAILED;
663 } else {
664 rv = crypto2pkcs11_error_number(digest_final.df_return_value);
665 }
666
667 if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL))
668 *pulDigestLen = digest_final.df_digestlen;
669
670 done:
671 if ((rv == CKR_BUFFER_TOO_SMALL) ||
672 (rv == CKR_OK && pDigest == NULL)) {
673 /*
674 * We will not terminate the active digest operation flag,
675 * when the application-supplied buffer is too small, or
676 * the application asks for the length of buffer to hold
677 * the message digest.
678 *
679 * Decrement the session reference count.
680 * We do not hold the session lock.
681 */
682 REFRELE(session_p, ses_lock_held);
683 return (rv);
684 }
685
686 clean_exit:
687 /* Terminates the active digest operation */
688 (void) pthread_mutex_lock(&session_p->session_mutex);
689 ses_lock_held = B_TRUE;
690 REINIT_OPBUF(&session_p->digest);
691 session_p->digest.flags = 0;
692
693 /*
694 * Decrement the session reference count.
695 * We hold the session lock, and REFRELE()
696 * will release the session lock for us.
697 */
698 REFRELE(session_p, ses_lock_held);
699
700 return (rv);
701 }
702