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