17c478bd9Sstevel@tonic-gate /*
27c478bd9Sstevel@tonic-gate * CDDL HEADER START
37c478bd9Sstevel@tonic-gate *
47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the
5ba5f469cSkrishna * Common Development and Distribution License (the "License").
6ba5f469cSkrishna * You may not use this file except in compliance with the License.
77c478bd9Sstevel@tonic-gate *
87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions
117c478bd9Sstevel@tonic-gate * and limitations under the License.
127c478bd9Sstevel@tonic-gate *
137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bd9Sstevel@tonic-gate *
197c478bd9Sstevel@tonic-gate * CDDL HEADER END
207c478bd9Sstevel@tonic-gate */
21ba5f469cSkrishna
227c478bd9Sstevel@tonic-gate /*
23b232b5fcSZdenek Kotala * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
247c478bd9Sstevel@tonic-gate * Use is subject to license terms.
257c478bd9Sstevel@tonic-gate */
267c478bd9Sstevel@tonic-gate
277c478bd9Sstevel@tonic-gate #include <pthread.h>
287c478bd9Sstevel@tonic-gate #include <errno.h>
297c478bd9Sstevel@tonic-gate #include <sys/crypto/ioctl.h>
307c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
317c478bd9Sstevel@tonic-gate #include "kernelGlobal.h"
327c478bd9Sstevel@tonic-gate #include "kernelSession.h"
33ba5f469cSkrishna #include "kernelEmulate.h"
347c478bd9Sstevel@tonic-gate
35b2a96221Skrishna static CK_RV
common_digest_init(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism,boolean_t is_external_caller)36b2a96221Skrishna common_digest_init(CK_SESSION_HANDLE hSession,
37b2a96221Skrishna CK_MECHANISM_PTR pMechanism, boolean_t is_external_caller)
387c478bd9Sstevel@tonic-gate {
397c478bd9Sstevel@tonic-gate CK_RV rv;
407c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
41b232b5fcSZdenek Kotala boolean_t ses_lock_held = B_FALSE;
427c478bd9Sstevel@tonic-gate crypto_digest_init_t digest_init;
437c478bd9Sstevel@tonic-gate crypto_mech_type_t k_mech_type;
447c478bd9Sstevel@tonic-gate int r;
457c478bd9Sstevel@tonic-gate
467c478bd9Sstevel@tonic-gate if (!kernel_initialized)
477c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
487c478bd9Sstevel@tonic-gate
497c478bd9Sstevel@tonic-gate if (pMechanism == NULL)
507c478bd9Sstevel@tonic-gate return (CKR_ARGUMENTS_BAD);
517c478bd9Sstevel@tonic-gate
527c478bd9Sstevel@tonic-gate /*
537c478bd9Sstevel@tonic-gate * Get the kernel's internal mechanism number.
547c478bd9Sstevel@tonic-gate */
557c478bd9Sstevel@tonic-gate rv = kernel_mech(pMechanism->mechanism, &k_mech_type);
567c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
577c478bd9Sstevel@tonic-gate return (rv);
587c478bd9Sstevel@tonic-gate
597c478bd9Sstevel@tonic-gate /*
607c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session
617c478bd9Sstevel@tonic-gate * reference count.
627c478bd9Sstevel@tonic-gate */
637c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
647c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
657c478bd9Sstevel@tonic-gate return (rv);
667c478bd9Sstevel@tonic-gate
677c478bd9Sstevel@tonic-gate /* Acquire the session lock */
687c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
69b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
707c478bd9Sstevel@tonic-gate
717c478bd9Sstevel@tonic-gate /*
727c478bd9Sstevel@tonic-gate * This active flag will remain ON until application calls either
737c478bd9Sstevel@tonic-gate * C_Digest or C_DigestFinal to actually obtain the value of
747c478bd9Sstevel@tonic-gate * the message digest.
757c478bd9Sstevel@tonic-gate */
76b2a96221Skrishna session_p->digest.flags |= CRYPTO_OPERATION_ACTIVE;
77b2a96221Skrishna
78b2a96221Skrishna if (SLOT_HAS_LIMITED_HASH(session_p) && is_external_caller) {
79b2a96221Skrishna session_p->digest.mech.mechanism = pMechanism->mechanism;
80b2a96221Skrishna session_p->digest.mech.pParameter = NULL;
81b2a96221Skrishna session_p->digest.mech.ulParameterLen = 0;
82b2a96221Skrishna session_p->digest.flags |= CRYPTO_EMULATE;
83b2a96221Skrishna rv = emulate_buf_init(session_p, EDIGEST_LENGTH, OP_DIGEST);
84b2a96221Skrishna REFRELE(session_p, ses_lock_held);
85b2a96221Skrishna return (rv);
86b2a96221Skrishna }
87b2a96221Skrishna
887c478bd9Sstevel@tonic-gate digest_init.di_session = session_p->k_session;
897c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
90b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
917c478bd9Sstevel@tonic-gate digest_init.di_mech.cm_type = k_mech_type;
927c478bd9Sstevel@tonic-gate digest_init.di_mech.cm_param = pMechanism->pParameter;
937c478bd9Sstevel@tonic-gate
947c478bd9Sstevel@tonic-gate /*
957c478bd9Sstevel@tonic-gate * If pParameter is NULL, set cm_param_len to be 0, so that ioctl call
967c478bd9Sstevel@tonic-gate * will have a clean input data.
977c478bd9Sstevel@tonic-gate */
987c478bd9Sstevel@tonic-gate if (pMechanism->pParameter != NULL)
997c478bd9Sstevel@tonic-gate digest_init.di_mech.cm_param_len = pMechanism->ulParameterLen;
1007c478bd9Sstevel@tonic-gate else
1017c478bd9Sstevel@tonic-gate digest_init.di_mech.cm_param_len = 0;
1027c478bd9Sstevel@tonic-gate
1037c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_INIT, &digest_init)) < 0) {
1047c478bd9Sstevel@tonic-gate if (errno != EINTR)
1057c478bd9Sstevel@tonic-gate break;
1067c478bd9Sstevel@tonic-gate }
1077c478bd9Sstevel@tonic-gate if (r < 0) {
1087c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
1097c478bd9Sstevel@tonic-gate } else {
1107c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(digest_init.di_return_value);
1117c478bd9Sstevel@tonic-gate }
1127c478bd9Sstevel@tonic-gate
1137c478bd9Sstevel@tonic-gate if (rv != CKR_OK) {
1147c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
115b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
1167c478bd9Sstevel@tonic-gate session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE;
1177c478bd9Sstevel@tonic-gate /*
1187c478bd9Sstevel@tonic-gate * Decrement the session reference count.
1197c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
1207c478bd9Sstevel@tonic-gate * will release the session lock for us.
1217c478bd9Sstevel@tonic-gate */
1227c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
1237c478bd9Sstevel@tonic-gate return (rv);
1247c478bd9Sstevel@tonic-gate }
1257c478bd9Sstevel@tonic-gate
1267c478bd9Sstevel@tonic-gate /*
1277c478bd9Sstevel@tonic-gate * Decrement the session reference count.
1287c478bd9Sstevel@tonic-gate * We do not hold the session lock.
1297c478bd9Sstevel@tonic-gate */
1307c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
1317c478bd9Sstevel@tonic-gate return (rv);
1327c478bd9Sstevel@tonic-gate }
1337c478bd9Sstevel@tonic-gate
1347c478bd9Sstevel@tonic-gate CK_RV
C_DigestInit(CK_SESSION_HANDLE hSession,CK_MECHANISM_PTR pMechanism)135b2a96221Skrishna C_DigestInit(CK_SESSION_HANDLE hSession, CK_MECHANISM_PTR pMechanism)
136b2a96221Skrishna {
137b2a96221Skrishna return (common_digest_init(hSession, pMechanism, B_TRUE));
138b2a96221Skrishna }
139b2a96221Skrishna
140b2a96221Skrishna CK_RV
C_Digest(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)1417c478bd9Sstevel@tonic-gate C_Digest(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
1427c478bd9Sstevel@tonic-gate CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
1437c478bd9Sstevel@tonic-gate {
1447c478bd9Sstevel@tonic-gate CK_RV rv;
1457c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
146b232b5fcSZdenek Kotala boolean_t ses_lock_held = B_FALSE;
1477c478bd9Sstevel@tonic-gate crypto_digest_t digest;
1487c478bd9Sstevel@tonic-gate int r;
1497c478bd9Sstevel@tonic-gate
1507c478bd9Sstevel@tonic-gate if (!kernel_initialized)
1517c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
1527c478bd9Sstevel@tonic-gate
1537c478bd9Sstevel@tonic-gate /*
1547c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session
1557c478bd9Sstevel@tonic-gate * reference count.
1567c478bd9Sstevel@tonic-gate */
1577c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
1587c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
1597c478bd9Sstevel@tonic-gate return (rv);
1607c478bd9Sstevel@tonic-gate
1617c478bd9Sstevel@tonic-gate if (pData == NULL || pulDigestLen == NULL) {
1627c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
1637c478bd9Sstevel@tonic-gate goto clean_exit;
1647c478bd9Sstevel@tonic-gate }
1657c478bd9Sstevel@tonic-gate
1667c478bd9Sstevel@tonic-gate /* Acquire the session lock */
1677c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
168b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
1697c478bd9Sstevel@tonic-gate
1707c478bd9Sstevel@tonic-gate /* Application must call C_DigestInit before calling C_Digest */
1717c478bd9Sstevel@tonic-gate if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
1727c478bd9Sstevel@tonic-gate /*
1737c478bd9Sstevel@tonic-gate * Decrement the session reference count.
1747c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
1757c478bd9Sstevel@tonic-gate * will release the session lock for us.
1767c478bd9Sstevel@tonic-gate */
1777c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
1787c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED);
1797c478bd9Sstevel@tonic-gate }
1807c478bd9Sstevel@tonic-gate
1817c478bd9Sstevel@tonic-gate /*
1827c478bd9Sstevel@tonic-gate * C_Digest must be called without intervening C_DigestUpdate
1837c478bd9Sstevel@tonic-gate * calls.
1847c478bd9Sstevel@tonic-gate */
1857c478bd9Sstevel@tonic-gate if (session_p->digest.flags & CRYPTO_OPERATION_UPDATE) {
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate * C_Digest can not be used to terminate a multi-part
1887c478bd9Sstevel@tonic-gate * operation, so we'll leave the active digest operation
1897c478bd9Sstevel@tonic-gate * flag on and let the application continue with the
1907c478bd9Sstevel@tonic-gate * digest update operation.
1917c478bd9Sstevel@tonic-gate *
1927c478bd9Sstevel@tonic-gate * Decrement the session reference count.
1937c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
1947c478bd9Sstevel@tonic-gate * will release the session lock for us.
1957c478bd9Sstevel@tonic-gate */
1967c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
1977c478bd9Sstevel@tonic-gate return (CKR_FUNCTION_FAILED);
1987c478bd9Sstevel@tonic-gate }
1997c478bd9Sstevel@tonic-gate
200ba5f469cSkrishna if (session_p->digest.flags & CRYPTO_EMULATE) {
201b2a96221Skrishna crypto_active_op_t *opp;
202b2a96221Skrishna CK_MECHANISM_PTR pMechanism;
203b2a96221Skrishna
204b2a96221Skrishna opp = &(session_p->digest);
205b232b5fcSZdenek Kotala if (opp->context == NULL) {
206b232b5fcSZdenek Kotala REFRELE(session_p, ses_lock_held);
207b2a96221Skrishna return (CKR_ARGUMENTS_BAD);
208b232b5fcSZdenek Kotala }
209b2a96221Skrishna pMechanism = &(opp->mech);
210b2a96221Skrishna
211ba5f469cSkrishna if ((ulDataLen < SLOT_THRESHOLD(session_p)) ||
212*4df55fdeSJanie Lu (ulDataLen > SLOT_HASH_MAX_INDATA_LEN(session_p))) {
213ba5f469cSkrishna session_p->digest.flags |= CRYPTO_EMULATE_USING_SW;
214ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex);
215b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
216ba5f469cSkrishna
217b2a96221Skrishna rv = do_soft_digest(get_spp(opp), pMechanism,
218b2a96221Skrishna pData, ulDataLen, pDigest, pulDigestLen,
219b2a96221Skrishna OP_INIT | OP_SINGLE);
220ba5f469cSkrishna goto done;
221b2a96221Skrishna } else if (!(session_p->digest.flags &
222b2a96221Skrishna CRYPTO_EMULATE_INIT_DONE)) {
223b2a96221Skrishna session_p->digest.flags |= CRYPTO_EMULATE_INIT_DONE;
224b2a96221Skrishna (void) pthread_mutex_unlock(&session_p->session_mutex);
225b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
226b232b5fcSZdenek Kotala
227b2a96221Skrishna rv = common_digest_init(hSession, pMechanism, B_FALSE);
228b2a96221Skrishna if (rv != CKR_OK)
229b2a96221Skrishna goto clean_exit;
230b2a96221Skrishna (void) pthread_mutex_lock(&session_p->session_mutex);
231b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
232ba5f469cSkrishna }
233ba5f469cSkrishna }
234ba5f469cSkrishna
2357c478bd9Sstevel@tonic-gate digest.cd_session = session_p->k_session;
2367c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
237b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
2387c478bd9Sstevel@tonic-gate digest.cd_datalen = ulDataLen;
2397c478bd9Sstevel@tonic-gate digest.cd_databuf = (char *)pData;
2407c478bd9Sstevel@tonic-gate digest.cd_digestbuf = (char *)pDigest;
2417c478bd9Sstevel@tonic-gate digest.cd_digestlen = *pulDigestLen;
2427c478bd9Sstevel@tonic-gate
2437c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DIGEST, &digest)) < 0) {
2447c478bd9Sstevel@tonic-gate if (errno != EINTR)
2457c478bd9Sstevel@tonic-gate break;
2467c478bd9Sstevel@tonic-gate }
2477c478bd9Sstevel@tonic-gate if (r < 0) {
2487c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
2497c478bd9Sstevel@tonic-gate } else {
2507c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(digest.cd_return_value);
2517c478bd9Sstevel@tonic-gate }
2527c478bd9Sstevel@tonic-gate
2537c478bd9Sstevel@tonic-gate if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL))
2547c478bd9Sstevel@tonic-gate *pulDigestLen = digest.cd_digestlen;
2557c478bd9Sstevel@tonic-gate
256ba5f469cSkrishna done:
2577c478bd9Sstevel@tonic-gate if ((rv == CKR_BUFFER_TOO_SMALL) ||
2587c478bd9Sstevel@tonic-gate (rv == CKR_OK && pDigest == NULL)) {
2597c478bd9Sstevel@tonic-gate /*
2607c478bd9Sstevel@tonic-gate * We will not terminate the active digest operation flag,
2617c478bd9Sstevel@tonic-gate * when the application-supplied buffer is too small, or
2627c478bd9Sstevel@tonic-gate * the application asks for the length of buffer to hold
2637c478bd9Sstevel@tonic-gate * the message digest.
2647c478bd9Sstevel@tonic-gate *
2657c478bd9Sstevel@tonic-gate * Decrement the session reference count.
2667c478bd9Sstevel@tonic-gate * We do not hold the session lock.
2677c478bd9Sstevel@tonic-gate */
2687c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
2697c478bd9Sstevel@tonic-gate return (rv);
2707c478bd9Sstevel@tonic-gate }
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate clean_exit:
2737c478bd9Sstevel@tonic-gate /*
2747c478bd9Sstevel@tonic-gate * Terminates the active digest operation.
2757c478bd9Sstevel@tonic-gate * Application needs to call C_DigestInit again for next
2767c478bd9Sstevel@tonic-gate * digest operation.
2777c478bd9Sstevel@tonic-gate */
2787c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
279b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
280ba5f469cSkrishna
281ba5f469cSkrishna REINIT_OPBUF(&session_p->digest);
2827c478bd9Sstevel@tonic-gate session_p->digest.flags = 0;
2837c478bd9Sstevel@tonic-gate
2847c478bd9Sstevel@tonic-gate /*
2857c478bd9Sstevel@tonic-gate * Decrement the session reference count.
2867c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
2877c478bd9Sstevel@tonic-gate * will release the session lock for us.
2887c478bd9Sstevel@tonic-gate */
2897c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
2907c478bd9Sstevel@tonic-gate
2917c478bd9Sstevel@tonic-gate return (rv);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate
2947c478bd9Sstevel@tonic-gate CK_RV
C_DigestUpdate(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)2957c478bd9Sstevel@tonic-gate C_DigestUpdate(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pPart,
2967c478bd9Sstevel@tonic-gate CK_ULONG ulPartLen)
2977c478bd9Sstevel@tonic-gate {
2987c478bd9Sstevel@tonic-gate
2997c478bd9Sstevel@tonic-gate CK_RV rv;
3007c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
301b232b5fcSZdenek Kotala boolean_t ses_lock_held = B_FALSE;
3027c478bd9Sstevel@tonic-gate crypto_digest_update_t digest_update;
3037c478bd9Sstevel@tonic-gate int r;
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate if (!kernel_initialized)
3067c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
3077c478bd9Sstevel@tonic-gate
3087c478bd9Sstevel@tonic-gate /*
3097c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session
3107c478bd9Sstevel@tonic-gate * reference count.
3117c478bd9Sstevel@tonic-gate */
3127c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
3137c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
3147c478bd9Sstevel@tonic-gate return (rv);
3157c478bd9Sstevel@tonic-gate
3167c478bd9Sstevel@tonic-gate if (pPart == NULL) {
3177c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
3187c478bd9Sstevel@tonic-gate goto clean_exit;
3197c478bd9Sstevel@tonic-gate }
3207c478bd9Sstevel@tonic-gate
3217c478bd9Sstevel@tonic-gate /* Acquire the session lock */
3227c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
323b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
3247c478bd9Sstevel@tonic-gate
3257c478bd9Sstevel@tonic-gate /*
3267c478bd9Sstevel@tonic-gate * Application must call C_DigestInit before calling
3277c478bd9Sstevel@tonic-gate * C_DigestUpdate.
3287c478bd9Sstevel@tonic-gate */
3297c478bd9Sstevel@tonic-gate if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
3307c478bd9Sstevel@tonic-gate /*
3317c478bd9Sstevel@tonic-gate * Decrement the session reference count.
3327c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
3337c478bd9Sstevel@tonic-gate * will release the session lock for us.
3347c478bd9Sstevel@tonic-gate */
3357c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
3367c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED);
3377c478bd9Sstevel@tonic-gate }
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate /* Set update flag to protect C_Digest */
3407c478bd9Sstevel@tonic-gate session_p->digest.flags |= CRYPTO_OPERATION_UPDATE;
3417c478bd9Sstevel@tonic-gate
342ba5f469cSkrishna if (session_p->digest.flags & CRYPTO_EMULATE) {
343ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex);
344b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
345ba5f469cSkrishna rv = emulate_update(session_p, pPart, ulPartLen, OP_DIGEST);
346ba5f469cSkrishna goto done;
347ba5f469cSkrishna }
348ba5f469cSkrishna
3497c478bd9Sstevel@tonic-gate digest_update.du_session = session_p->k_session;
3507c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
351b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
3527c478bd9Sstevel@tonic-gate digest_update.du_datalen = ulPartLen;
3537c478bd9Sstevel@tonic-gate digest_update.du_databuf = (char *)pPart;
3547c478bd9Sstevel@tonic-gate
3557c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_UPDATE,
3567c478bd9Sstevel@tonic-gate &digest_update)) < 0) {
3577c478bd9Sstevel@tonic-gate if (errno != EINTR)
3587c478bd9Sstevel@tonic-gate break;
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate if (r < 0) {
3617c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
3627c478bd9Sstevel@tonic-gate } else {
3637c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(digest_update.du_return_value);
3647c478bd9Sstevel@tonic-gate }
3657c478bd9Sstevel@tonic-gate
366ba5f469cSkrishna done:
3677c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
3687c478bd9Sstevel@tonic-gate /*
3697c478bd9Sstevel@tonic-gate * Decrement the session reference count.
3707c478bd9Sstevel@tonic-gate * We do not hold the session lock.
3717c478bd9Sstevel@tonic-gate */
3727c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
3737c478bd9Sstevel@tonic-gate return (CKR_OK);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate clean_exit:
3777c478bd9Sstevel@tonic-gate /*
3787c478bd9Sstevel@tonic-gate * After an error occurred, terminate the current digest
3797c478bd9Sstevel@tonic-gate * operation by resetting the active and update flags.
3807c478bd9Sstevel@tonic-gate */
3817c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
382b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
383ba5f469cSkrishna REINIT_OPBUF(&session_p->digest);
3847c478bd9Sstevel@tonic-gate session_p->digest.flags = 0;
3857c478bd9Sstevel@tonic-gate
3867c478bd9Sstevel@tonic-gate /*
3877c478bd9Sstevel@tonic-gate * Decrement the session reference count.
3887c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
3897c478bd9Sstevel@tonic-gate * will release the session lock for us.
3907c478bd9Sstevel@tonic-gate */
3917c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
3927c478bd9Sstevel@tonic-gate
3937c478bd9Sstevel@tonic-gate return (rv);
3947c478bd9Sstevel@tonic-gate }
3957c478bd9Sstevel@tonic-gate
3967c478bd9Sstevel@tonic-gate
3977c478bd9Sstevel@tonic-gate CK_RV
C_DigestKey(CK_SESSION_HANDLE hSession,CK_OBJECT_HANDLE hKey)3987c478bd9Sstevel@tonic-gate C_DigestKey(CK_SESSION_HANDLE hSession, CK_OBJECT_HANDLE hKey)
3997c478bd9Sstevel@tonic-gate {
4007c478bd9Sstevel@tonic-gate
4017c478bd9Sstevel@tonic-gate CK_RV rv;
4027c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
4037c478bd9Sstevel@tonic-gate kernel_object_t *key_p;
404b232b5fcSZdenek Kotala boolean_t ses_lock_held = B_FALSE;
4057c478bd9Sstevel@tonic-gate CK_BYTE_PTR pPart;
4067c478bd9Sstevel@tonic-gate CK_ULONG ulPartLen;
4077c478bd9Sstevel@tonic-gate crypto_digest_key_t digest_key;
4087c478bd9Sstevel@tonic-gate crypto_digest_update_t digest_update;
4097c478bd9Sstevel@tonic-gate int r;
4107c478bd9Sstevel@tonic-gate
4117c478bd9Sstevel@tonic-gate if (!kernel_initialized)
4127c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
4137c478bd9Sstevel@tonic-gate
4147c478bd9Sstevel@tonic-gate /*
4157c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session
4167c478bd9Sstevel@tonic-gate * reference count.
4177c478bd9Sstevel@tonic-gate */
4187c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
4197c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
4207c478bd9Sstevel@tonic-gate return (rv);
4217c478bd9Sstevel@tonic-gate
4227c478bd9Sstevel@tonic-gate /* Obtain the object pointer. */
4237c478bd9Sstevel@tonic-gate HANDLE2OBJECT(hKey, key_p, rv);
42401223cbaSmcpowers if (rv != CKR_OK) {
42501223cbaSmcpowers (void) pthread_mutex_lock(&session_p->session_mutex);
426b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
427ba5f469cSkrishna REINIT_OPBUF(&session_p->digest);
42801223cbaSmcpowers session_p->digest.flags = 0;
42901223cbaSmcpowers REFRELE(session_p, ses_lock_held);
43001223cbaSmcpowers return (rv);
43101223cbaSmcpowers }
4327c478bd9Sstevel@tonic-gate
4337c478bd9Sstevel@tonic-gate /* Check the key type */
4347c478bd9Sstevel@tonic-gate if (key_p->is_lib_obj && (key_p->class != CKO_SECRET_KEY)) {
4357c478bd9Sstevel@tonic-gate rv = CKR_KEY_INDIGESTIBLE;
4367c478bd9Sstevel@tonic-gate goto clean_exit;
4377c478bd9Sstevel@tonic-gate }
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate /*
4407c478bd9Sstevel@tonic-gate * Application must call C_DigestInit before calling
4417c478bd9Sstevel@tonic-gate * C_DigestKey.
4427c478bd9Sstevel@tonic-gate */
4437c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
444b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
445b232b5fcSZdenek Kotala
4467c478bd9Sstevel@tonic-gate if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
4477c478bd9Sstevel@tonic-gate /*
4487c478bd9Sstevel@tonic-gate * Decrement the session reference count.
4497c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
4507c478bd9Sstevel@tonic-gate * will release the session lock for us.
4517c478bd9Sstevel@tonic-gate */
45201223cbaSmcpowers OBJ_REFRELE(key_p);
4537c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
4547c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED);
4557c478bd9Sstevel@tonic-gate }
4567c478bd9Sstevel@tonic-gate session_p->digest.flags |= CRYPTO_OPERATION_UPDATE;
4577c478bd9Sstevel@tonic-gate
4587c478bd9Sstevel@tonic-gate /*
4597c478bd9Sstevel@tonic-gate * If the key object is from the HW provider, call CRYPTO_DIGEST_KEY
4607c478bd9Sstevel@tonic-gate * ioctl. Otherwise, call CRYPTO_DIGEST_UPDATE ioctl and pass the key
4617c478bd9Sstevel@tonic-gate * by value.
4627c478bd9Sstevel@tonic-gate */
4637c478bd9Sstevel@tonic-gate if (key_p->is_lib_obj) {
4647c478bd9Sstevel@tonic-gate digest_update.du_session = session_p->k_session;
4657c478bd9Sstevel@tonic-gate } else {
4667c478bd9Sstevel@tonic-gate digest_key.dk_session = session_p->k_session;
4677c478bd9Sstevel@tonic-gate }
4687c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
469b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
4707c478bd9Sstevel@tonic-gate
4717c478bd9Sstevel@tonic-gate if (!key_p->is_lib_obj) {
472ba5f469cSkrishna if (session_p->digest.flags & CRYPTO_EMULATE) {
473ba5f469cSkrishna rv = CKR_FUNCTION_NOT_SUPPORTED;
474ba5f469cSkrishna goto clean_exit;
475ba5f469cSkrishna }
4767c478bd9Sstevel@tonic-gate digest_key.dk_key.ck_format = CRYPTO_KEY_REFERENCE;
4777c478bd9Sstevel@tonic-gate digest_key.dk_key.ck_obj_id = key_p->k_handle;
4787c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_KEY,
4797c478bd9Sstevel@tonic-gate &digest_key)) < 0) {
4807c478bd9Sstevel@tonic-gate if (errno != EINTR)
4817c478bd9Sstevel@tonic-gate break;
4827c478bd9Sstevel@tonic-gate }
4837c478bd9Sstevel@tonic-gate if (r < 0) {
4847c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
4857c478bd9Sstevel@tonic-gate } else {
4867c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(
4877c478bd9Sstevel@tonic-gate digest_key.dk_return_value);
4887c478bd9Sstevel@tonic-gate }
4897c478bd9Sstevel@tonic-gate } else {
4907c478bd9Sstevel@tonic-gate ulPartLen = OBJ_SEC_VALUE_LEN(key_p);
4917c478bd9Sstevel@tonic-gate if (ulPartLen == 0) {
4927c478bd9Sstevel@tonic-gate rv = CKR_KEY_SIZE_RANGE;
4937c478bd9Sstevel@tonic-gate goto clean_exit;
4947c478bd9Sstevel@tonic-gate }
4957c478bd9Sstevel@tonic-gate
4967c478bd9Sstevel@tonic-gate pPart = (CK_BYTE_PTR) OBJ_SEC_VALUE(key_p);
4977c478bd9Sstevel@tonic-gate if (pPart == NULL) {
4987c478bd9Sstevel@tonic-gate rv = CKR_KEY_HANDLE_INVALID;
4997c478bd9Sstevel@tonic-gate goto clean_exit;
5007c478bd9Sstevel@tonic-gate }
5017c478bd9Sstevel@tonic-gate
502ba5f469cSkrishna (void) pthread_mutex_lock(&session_p->session_mutex);
503b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
504ba5f469cSkrishna if (session_p->digest.flags & CRYPTO_EMULATE) {
505ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex);
506b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
507ba5f469cSkrishna rv = emulate_update(session_p, pPart,
508ba5f469cSkrishna ulPartLen, OP_DIGEST);
509ba5f469cSkrishna goto done;
510ba5f469cSkrishna }
511ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex);
512b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
513ba5f469cSkrishna
5147c478bd9Sstevel@tonic-gate digest_update.du_datalen = ulPartLen;
5157c478bd9Sstevel@tonic-gate digest_update.du_databuf = (char *)pPart;
5167c478bd9Sstevel@tonic-gate
5177c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_UPDATE,
5187c478bd9Sstevel@tonic-gate &digest_update)) < 0) {
5197c478bd9Sstevel@tonic-gate if (errno != EINTR)
5207c478bd9Sstevel@tonic-gate break;
5217c478bd9Sstevel@tonic-gate }
5227c478bd9Sstevel@tonic-gate if (r < 0) {
5237c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
5247c478bd9Sstevel@tonic-gate } else {
5257c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(
5267c478bd9Sstevel@tonic-gate digest_update.du_return_value);
5277c478bd9Sstevel@tonic-gate }
5287c478bd9Sstevel@tonic-gate }
5297c478bd9Sstevel@tonic-gate
530ba5f469cSkrishna done:
5317c478bd9Sstevel@tonic-gate if (rv == CKR_OK) {
5327c478bd9Sstevel@tonic-gate /*
5337c478bd9Sstevel@tonic-gate * Decrement the session reference count.
5347c478bd9Sstevel@tonic-gate * We do not hold the session lock.
5357c478bd9Sstevel@tonic-gate */
53601223cbaSmcpowers OBJ_REFRELE(key_p);
53701223cbaSmcpowers REFRELE(session_p, ses_lock_held);
5387c478bd9Sstevel@tonic-gate return (CKR_OK);
5397c478bd9Sstevel@tonic-gate }
5407c478bd9Sstevel@tonic-gate
5417c478bd9Sstevel@tonic-gate clean_exit:
54201223cbaSmcpowers OBJ_REFRELE(key_p);
5437c478bd9Sstevel@tonic-gate /*
5447c478bd9Sstevel@tonic-gate * After an error occurred, terminate the current digest
5457c478bd9Sstevel@tonic-gate * operation by resetting the active and update flags.
5467c478bd9Sstevel@tonic-gate */
5477c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
548b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
549ba5f469cSkrishna REINIT_OPBUF(&session_p->digest);
5507c478bd9Sstevel@tonic-gate session_p->digest.flags = 0;
5517c478bd9Sstevel@tonic-gate
5527c478bd9Sstevel@tonic-gate /*
5537c478bd9Sstevel@tonic-gate * Decrement the session reference count.
5547c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
5557c478bd9Sstevel@tonic-gate * will release the session lock for us.
5567c478bd9Sstevel@tonic-gate */
5577c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
5587c478bd9Sstevel@tonic-gate return (rv);
5597c478bd9Sstevel@tonic-gate }
5607c478bd9Sstevel@tonic-gate
5617c478bd9Sstevel@tonic-gate
5627c478bd9Sstevel@tonic-gate CK_RV
C_DigestFinal(CK_SESSION_HANDLE hSession,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)5637c478bd9Sstevel@tonic-gate C_DigestFinal(CK_SESSION_HANDLE hSession, CK_BYTE_PTR pDigest,
5647c478bd9Sstevel@tonic-gate CK_ULONG_PTR pulDigestLen)
5657c478bd9Sstevel@tonic-gate {
5667c478bd9Sstevel@tonic-gate
5677c478bd9Sstevel@tonic-gate CK_RV rv;
5687c478bd9Sstevel@tonic-gate kernel_session_t *session_p;
569b232b5fcSZdenek Kotala boolean_t ses_lock_held = B_FALSE;
5707c478bd9Sstevel@tonic-gate crypto_digest_final_t digest_final;
5717c478bd9Sstevel@tonic-gate int r;
5727c478bd9Sstevel@tonic-gate
5737c478bd9Sstevel@tonic-gate if (!kernel_initialized)
5747c478bd9Sstevel@tonic-gate return (CKR_CRYPTOKI_NOT_INITIALIZED);
5757c478bd9Sstevel@tonic-gate
5767c478bd9Sstevel@tonic-gate /*
5777c478bd9Sstevel@tonic-gate * Obtain the session pointer. Also, increment the session
5787c478bd9Sstevel@tonic-gate * reference count.
5797c478bd9Sstevel@tonic-gate */
5807c478bd9Sstevel@tonic-gate rv = handle2session(hSession, &session_p);
5817c478bd9Sstevel@tonic-gate if (rv != CKR_OK)
5827c478bd9Sstevel@tonic-gate return (rv);
5837c478bd9Sstevel@tonic-gate
5847c478bd9Sstevel@tonic-gate if (pulDigestLen == NULL) {
5857c478bd9Sstevel@tonic-gate rv = CKR_ARGUMENTS_BAD;
5867c478bd9Sstevel@tonic-gate goto clean_exit;
5877c478bd9Sstevel@tonic-gate }
5887c478bd9Sstevel@tonic-gate
5897c478bd9Sstevel@tonic-gate /* Acquire the session lock */
5907c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
591b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
5927c478bd9Sstevel@tonic-gate
5937c478bd9Sstevel@tonic-gate /*
5947c478bd9Sstevel@tonic-gate * Application must call C_DigestInit before calling
5957c478bd9Sstevel@tonic-gate * C_DigestFinal.
5967c478bd9Sstevel@tonic-gate */
5977c478bd9Sstevel@tonic-gate if (!(session_p->digest.flags & CRYPTO_OPERATION_ACTIVE)) {
5987c478bd9Sstevel@tonic-gate /*
5997c478bd9Sstevel@tonic-gate * Decrement the session reference count.
6007c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
6017c478bd9Sstevel@tonic-gate * will release the session lock for us.
6027c478bd9Sstevel@tonic-gate */
6037c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
6047c478bd9Sstevel@tonic-gate return (CKR_OPERATION_NOT_INITIALIZED);
6057c478bd9Sstevel@tonic-gate }
6067c478bd9Sstevel@tonic-gate
607ba5f469cSkrishna /* The order of checks is important here */
608ba5f469cSkrishna if (session_p->digest.flags & CRYPTO_EMULATE_USING_SW) {
609ba5f469cSkrishna if (session_p->digest.flags & CRYPTO_EMULATE_UPDATE_DONE) {
610ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex);
611b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
612ba5f469cSkrishna rv = do_soft_digest(get_spp(&session_p->digest),
613ba5f469cSkrishna NULL, NULL, NULL, pDigest, pulDigestLen, OP_FINAL);
614ba5f469cSkrishna } else {
615ba5f469cSkrishna /*
616ba5f469cSkrishna * We end up here if an earlier C_DigestFinal() call
617ba5f469cSkrishna * took the C_Digest() path and it had returned
618ba5f469cSkrishna * CKR_BUFFER_TOO_SMALL.
619ba5f469cSkrishna */
620ba5f469cSkrishna digest_buf_t *bufp = session_p->digest.context;
621ba5f469cSkrishna (void) pthread_mutex_unlock(&session_p->session_mutex);
622b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
623ba5f469cSkrishna if (bufp == NULL || bufp->buf == NULL) {
624ba5f469cSkrishna rv = CKR_ARGUMENTS_BAD;
625ba5f469cSkrishna goto clean_exit;
626ba5f469cSkrishna }
627ba5f469cSkrishna rv = do_soft_digest(get_spp(&session_p->digest),
628ba5f469cSkrishna NULL, bufp->buf, bufp->indata_len,
629ba5f469cSkrishna pDigest, pulDigestLen, OP_SINGLE);
630ba5f469cSkrishna }
631ba5f469cSkrishna goto done;
632ba5f469cSkrishna } else if (session_p->digest.flags & CRYPTO_EMULATE) {
633ba5f469cSkrishna digest_buf_t *bufp = session_p->digest.context;
634ba5f469cSkrishna
635ba5f469cSkrishna /*
636ba5f469cSkrishna * We are emulating a single-part operation now.
637ba5f469cSkrishna * So, clear the flag.
638ba5f469cSkrishna */
639ba5f469cSkrishna session_p->digest.flags &= ~CRYPTO_OPERATION_UPDATE;
640ba5f469cSkrishna if (bufp == NULL || bufp->buf == NULL) {
641ba5f469cSkrishna rv = CKR_ARGUMENTS_BAD;
642ba5f469cSkrishna goto clean_exit;
643ba5f469cSkrishna }
644ba5f469cSkrishna REFRELE(session_p, ses_lock_held);
645ba5f469cSkrishna rv = C_Digest(hSession, bufp->buf, bufp->indata_len,
646ba5f469cSkrishna pDigest, pulDigestLen);
647ba5f469cSkrishna return (rv);
648ba5f469cSkrishna }
649ba5f469cSkrishna
6507c478bd9Sstevel@tonic-gate digest_final.df_session = session_p->k_session;
6517c478bd9Sstevel@tonic-gate (void) pthread_mutex_unlock(&session_p->session_mutex);
652b232b5fcSZdenek Kotala ses_lock_held = B_FALSE;
6537c478bd9Sstevel@tonic-gate digest_final.df_digestlen = *pulDigestLen;
6547c478bd9Sstevel@tonic-gate digest_final.df_digestbuf = (char *)pDigest;
6557c478bd9Sstevel@tonic-gate
6567c478bd9Sstevel@tonic-gate while ((r = ioctl(kernel_fd, CRYPTO_DIGEST_FINAL, &digest_final)) < 0) {
6577c478bd9Sstevel@tonic-gate if (errno != EINTR)
6587c478bd9Sstevel@tonic-gate break;
6597c478bd9Sstevel@tonic-gate }
6607c478bd9Sstevel@tonic-gate if (r < 0) {
6617c478bd9Sstevel@tonic-gate rv = CKR_FUNCTION_FAILED;
6627c478bd9Sstevel@tonic-gate } else {
6637c478bd9Sstevel@tonic-gate rv = crypto2pkcs11_error_number(digest_final.df_return_value);
6647c478bd9Sstevel@tonic-gate }
6657c478bd9Sstevel@tonic-gate
6667c478bd9Sstevel@tonic-gate if ((rv == CKR_OK) || (rv == CKR_BUFFER_TOO_SMALL))
6677c478bd9Sstevel@tonic-gate *pulDigestLen = digest_final.df_digestlen;
6687c478bd9Sstevel@tonic-gate
669ba5f469cSkrishna done:
6707c478bd9Sstevel@tonic-gate if ((rv == CKR_BUFFER_TOO_SMALL) ||
6717c478bd9Sstevel@tonic-gate (rv == CKR_OK && pDigest == NULL)) {
6727c478bd9Sstevel@tonic-gate /*
6737c478bd9Sstevel@tonic-gate * We will not terminate the active digest operation flag,
6747c478bd9Sstevel@tonic-gate * when the application-supplied buffer is too small, or
6757c478bd9Sstevel@tonic-gate * the application asks for the length of buffer to hold
6767c478bd9Sstevel@tonic-gate * the message digest.
6777c478bd9Sstevel@tonic-gate *
6787c478bd9Sstevel@tonic-gate * Decrement the session reference count.
6797c478bd9Sstevel@tonic-gate * We do not hold the session lock.
6807c478bd9Sstevel@tonic-gate */
6817c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
6827c478bd9Sstevel@tonic-gate return (rv);
6837c478bd9Sstevel@tonic-gate }
6847c478bd9Sstevel@tonic-gate
6857c478bd9Sstevel@tonic-gate clean_exit:
6867c478bd9Sstevel@tonic-gate /* Terminates the active digest operation */
6877c478bd9Sstevel@tonic-gate (void) pthread_mutex_lock(&session_p->session_mutex);
688b232b5fcSZdenek Kotala ses_lock_held = B_TRUE;
689ba5f469cSkrishna REINIT_OPBUF(&session_p->digest);
6907c478bd9Sstevel@tonic-gate session_p->digest.flags = 0;
6917c478bd9Sstevel@tonic-gate
6927c478bd9Sstevel@tonic-gate /*
6937c478bd9Sstevel@tonic-gate * Decrement the session reference count.
6947c478bd9Sstevel@tonic-gate * We hold the session lock, and REFRELE()
6957c478bd9Sstevel@tonic-gate * will release the session lock for us.
6967c478bd9Sstevel@tonic-gate */
6977c478bd9Sstevel@tonic-gate REFRELE(session_p, ses_lock_held);
6987c478bd9Sstevel@tonic-gate
6997c478bd9Sstevel@tonic-gate return (rv);
7007c478bd9Sstevel@tonic-gate }
701