10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
5*7690SAlexandr.Nedvedicky@Sun.COM  * Common Development and Distribution License (the "License").
6*7690SAlexandr.Nedvedicky@Sun.COM  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*7690SAlexandr.Nedvedicky@Sun.COM  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <strings.h>
270Sstevel@tonic-gate #include <md5.h>
280Sstevel@tonic-gate #include <pthread.h>
290Sstevel@tonic-gate #include <stdlib.h>
300Sstevel@tonic-gate #include <sys/sha1.h>
31676Sizick #include <sys/sha2.h>
320Sstevel@tonic-gate #include <sys/types.h>
330Sstevel@tonic-gate #include <security/cryptoki.h>
340Sstevel@tonic-gate #include "softGlobal.h"
350Sstevel@tonic-gate #include "softOps.h"
360Sstevel@tonic-gate #include "softSession.h"
370Sstevel@tonic-gate #include "softObject.h"
380Sstevel@tonic-gate 
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * soft_digest_init()
420Sstevel@tonic-gate  *
430Sstevel@tonic-gate  * Arguments:
440Sstevel@tonic-gate  *	session_p:	pointer to soft_session_t struct
450Sstevel@tonic-gate  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
460Sstevel@tonic-gate  *
470Sstevel@tonic-gate  * Description:
480Sstevel@tonic-gate  *	called by C_DigestInit(). This function allocates space for
490Sstevel@tonic-gate  *  	context, then calls the corresponding software provided digest
500Sstevel@tonic-gate  *	init routine based on the mechanism.
510Sstevel@tonic-gate  *
520Sstevel@tonic-gate  * Returns:
530Sstevel@tonic-gate  *	CKR_OK: success
540Sstevel@tonic-gate  *	CKR_HOST_MEMORY: run out of system memory
550Sstevel@tonic-gate  *	CKR_MECHANISM_INVALID: invalid mechanism type
560Sstevel@tonic-gate  */
570Sstevel@tonic-gate CK_RV
soft_digest_init(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism)580Sstevel@tonic-gate soft_digest_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism)
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	switch (pMechanism->mechanism) {
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	case CKM_MD5:
640Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
650Sstevel@tonic-gate 
660Sstevel@tonic-gate 		session_p->digest.context = malloc(sizeof (MD5_CTX));
670Sstevel@tonic-gate 
680Sstevel@tonic-gate 		if (session_p->digest.context == NULL) {
690Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&session_p->session_mutex);
700Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
710Sstevel@tonic-gate 		}
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 		session_p->digest.mech.mechanism = CKM_MD5;
740Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 		MD5Init((MD5_CTX *)session_p->digest.context);
770Sstevel@tonic-gate 
780Sstevel@tonic-gate 		break;
790Sstevel@tonic-gate 
800Sstevel@tonic-gate 	case CKM_SHA_1:
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
830Sstevel@tonic-gate 
840Sstevel@tonic-gate 		session_p->digest.context = malloc(sizeof (SHA1_CTX));
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 		if (session_p->digest.context == NULL) {
870Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&session_p->session_mutex);
880Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
890Sstevel@tonic-gate 		}
900Sstevel@tonic-gate 
910Sstevel@tonic-gate 		session_p->digest.mech.mechanism = CKM_SHA_1;
92872Sizick 		session_p->digest.mech.pParameter = pMechanism->pParameter;
93872Sizick 		session_p->digest.mech.ulParameterLen =
94872Sizick 		    pMechanism->ulParameterLen;
950Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
960Sstevel@tonic-gate 
970Sstevel@tonic-gate 		SHA1Init((SHA1_CTX *)session_p->digest.context);
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 		break;
1000Sstevel@tonic-gate 
101676Sizick 	case CKM_SHA256:
102676Sizick 	case CKM_SHA384:
103676Sizick 	case CKM_SHA512:
104676Sizick 
105676Sizick 		(void) pthread_mutex_lock(&session_p->session_mutex);
106676Sizick 
107676Sizick 		session_p->digest.context = malloc(sizeof (SHA2_CTX));
108676Sizick 
109676Sizick 		if (session_p->digest.context == NULL) {
110676Sizick 			(void) pthread_mutex_unlock(&session_p->session_mutex);
111676Sizick 			return (CKR_HOST_MEMORY);
112676Sizick 		}
113676Sizick 
114676Sizick 		switch (pMechanism->mechanism) {
115676Sizick 		case CKM_SHA256:
116676Sizick 			session_p->digest.mech.mechanism = CKM_SHA256;
117676Sizick 			(void) pthread_mutex_unlock(&session_p->session_mutex);
118676Sizick 			SHA2Init(SHA256,
119676Sizick 			    (SHA2_CTX *)session_p->digest.context);
120676Sizick 			break;
121676Sizick 
122676Sizick 		case CKM_SHA384:
123676Sizick 			session_p->digest.mech.mechanism = CKM_SHA384;
124676Sizick 			(void) pthread_mutex_unlock(&session_p->session_mutex);
125676Sizick 			SHA2Init(SHA384,
126676Sizick 			    (SHA2_CTX *)session_p->digest.context);
127676Sizick 			break;
128676Sizick 
129676Sizick 		case CKM_SHA512:
130676Sizick 			session_p->digest.mech.mechanism = CKM_SHA512;
131676Sizick 			(void) pthread_mutex_unlock(&session_p->session_mutex);
132676Sizick 			SHA2Init(SHA512,
133676Sizick 			    (SHA2_CTX *)session_p->digest.context);
134676Sizick 			break;
135676Sizick 		}
136676Sizick 		break;
137676Sizick 
1380Sstevel@tonic-gate 	default:
1390Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
1400Sstevel@tonic-gate 	}
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	return (CKR_OK);
1430Sstevel@tonic-gate }
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate /*
1470Sstevel@tonic-gate  * soft_digest_common()
1480Sstevel@tonic-gate  *
1490Sstevel@tonic-gate  * Arguments:
1500Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
1510Sstevel@tonic-gate  *	pData:		pointer to the input data to be digested
1520Sstevel@tonic-gate  *	ulDataLen:	length of the input data
1530Sstevel@tonic-gate  *	pDigest:	pointer to the output data after digesting
1540Sstevel@tonic-gate  *	pulDigestLen:	length of the output data
1550Sstevel@tonic-gate  *
1560Sstevel@tonic-gate  * Description:
1570Sstevel@tonic-gate  *      called by soft_digest() or soft_digest_final(). This function
1580Sstevel@tonic-gate  *      determines the length of output buffer and calls the corresponding
1590Sstevel@tonic-gate  *	software provided digest routine based on the mechanism.
1600Sstevel@tonic-gate  *
1610Sstevel@tonic-gate  * Returns:
1620Sstevel@tonic-gate  *      CKR_OK: success
1630Sstevel@tonic-gate  *      CKR_MECHANISM_INVALID: invalid mechanism type
1640Sstevel@tonic-gate  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
1650Sstevel@tonic-gate  *			      is too small
1660Sstevel@tonic-gate  */
1670Sstevel@tonic-gate CK_RV
soft_digest_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)1680Sstevel@tonic-gate soft_digest_common(soft_session_t *session_p, CK_BYTE_PTR pData,
1690Sstevel@tonic-gate 	CK_ULONG ulDataLen, CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
1700Sstevel@tonic-gate {
1710Sstevel@tonic-gate 
1720Sstevel@tonic-gate 	CK_ULONG digestLen = 0;
1730Sstevel@tonic-gate 	size_t len = 0;
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 	/*
1760Sstevel@tonic-gate 	 * Determine the output data length based on the mechanism
1770Sstevel@tonic-gate 	 */
1780Sstevel@tonic-gate 	switch (session_p->digest.mech.mechanism) {
1790Sstevel@tonic-gate 
1800Sstevel@tonic-gate 	case CKM_MD5:
1810Sstevel@tonic-gate 		digestLen = 16;
1820Sstevel@tonic-gate 		break;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	case CKM_SHA_1:
1850Sstevel@tonic-gate 		digestLen = 20;
1860Sstevel@tonic-gate 		break;
1870Sstevel@tonic-gate 
188676Sizick 	case CKM_SHA256:
189676Sizick 		digestLen = 32;
190676Sizick 		break;
191676Sizick 
192676Sizick 	case CKM_SHA384:
193676Sizick 		digestLen = 48;
194676Sizick 		break;
195676Sizick 
196676Sizick 	case CKM_SHA512:
197676Sizick 		digestLen = 64;
198676Sizick 		break;
199676Sizick 
2000Sstevel@tonic-gate 	default:
2010Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
2020Sstevel@tonic-gate 	}
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 	if (pDigest == NULL) {
2050Sstevel@tonic-gate 		/*
2060Sstevel@tonic-gate 		 * Application only wants to know the length of the
2070Sstevel@tonic-gate 		 * buffer needed to hold the message digest.
2080Sstevel@tonic-gate 		 */
2090Sstevel@tonic-gate 		*pulDigestLen = digestLen;
2100Sstevel@tonic-gate 		return (CKR_OK);
2110Sstevel@tonic-gate 	}
2120Sstevel@tonic-gate 
2130Sstevel@tonic-gate 	if (*pulDigestLen < digestLen) {
2140Sstevel@tonic-gate 		/*
2150Sstevel@tonic-gate 		 * Application provides buffer too small to hold the
2160Sstevel@tonic-gate 		 * digest message. Return the length of buffer needed
2170Sstevel@tonic-gate 		 * to the application.
2180Sstevel@tonic-gate 		 */
2190Sstevel@tonic-gate 		*pulDigestLen = digestLen;
2200Sstevel@tonic-gate 		return (CKR_BUFFER_TOO_SMALL);
2210Sstevel@tonic-gate 	}
2220Sstevel@tonic-gate 
2230Sstevel@tonic-gate 	/*
2240Sstevel@tonic-gate 	 * Call the corresponding system provided software digest routine.
2250Sstevel@tonic-gate 	 * If the soft_digest_common() is called by soft_digest_final()
2260Sstevel@tonic-gate 	 * the pData is NULL, and the ulDataLen is zero.
2270Sstevel@tonic-gate 	 */
2280Sstevel@tonic-gate 	switch (session_p->digest.mech.mechanism) {
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	case CKM_MD5:
2310Sstevel@tonic-gate 		if (pData != NULL) {
2320Sstevel@tonic-gate 			/*
2330Sstevel@tonic-gate 			 * this is called by soft_digest()
2340Sstevel@tonic-gate 			 */
2350Sstevel@tonic-gate #ifdef	__sparcv9
2360Sstevel@tonic-gate 			MD5Update((MD5_CTX *)session_p->digest.context,
2370Sstevel@tonic-gate 			    /* LINTED */
2380Sstevel@tonic-gate 			    pData, (uint_t)ulDataLen);
2390Sstevel@tonic-gate #else	/* !__sparcv9 */
2400Sstevel@tonic-gate 			MD5Update((MD5_CTX *)session_p->digest.context,
2410Sstevel@tonic-gate 			    pData, ulDataLen);
2420Sstevel@tonic-gate #endif	/* __sparcv9 */
2430Sstevel@tonic-gate 			MD5Final(pDigest, (MD5_CTX *)session_p->digest.context);
2440Sstevel@tonic-gate 		} else {
2450Sstevel@tonic-gate 			/*
2460Sstevel@tonic-gate 			 * this is called by soft_digest_final()
2470Sstevel@tonic-gate 			 */
2480Sstevel@tonic-gate 			MD5Final(pDigest, (MD5_CTX *)session_p->digest.context);
2490Sstevel@tonic-gate 			len = sizeof (MD5_CTX);
2500Sstevel@tonic-gate 		}
2510Sstevel@tonic-gate 		break;
2520Sstevel@tonic-gate 
2530Sstevel@tonic-gate 	case CKM_SHA_1:
2540Sstevel@tonic-gate 		if (pData != NULL) {
2550Sstevel@tonic-gate 			/*
2560Sstevel@tonic-gate 			 * this is called by soft_digest()
2570Sstevel@tonic-gate 			 */
2580Sstevel@tonic-gate 
2590Sstevel@tonic-gate #ifdef	__sparcv9
2600Sstevel@tonic-gate 			SHA1Update((SHA1_CTX *)session_p->digest.context,
2610Sstevel@tonic-gate 			    /* LINTED */
2620Sstevel@tonic-gate 			    pData, (uint32_t)ulDataLen);
2630Sstevel@tonic-gate #else	/* !__sparcv9 */
2640Sstevel@tonic-gate 			SHA1Update((SHA1_CTX *)session_p->digest.context,
2650Sstevel@tonic-gate 			    pData, ulDataLen);
2660Sstevel@tonic-gate #endif	/* __sparcv9 */
2670Sstevel@tonic-gate 			SHA1Final(pDigest,
2680Sstevel@tonic-gate 			    (SHA1_CTX *)session_p->digest.context);
2690Sstevel@tonic-gate 		} else {
2700Sstevel@tonic-gate 			/*
2710Sstevel@tonic-gate 			 * this is called by soft_digest_final()
2720Sstevel@tonic-gate 			 */
2730Sstevel@tonic-gate 			SHA1Final(pDigest,
2740Sstevel@tonic-gate 			    (SHA1_CTX *)session_p->digest.context);
2750Sstevel@tonic-gate 			len = sizeof (SHA1_CTX);
2760Sstevel@tonic-gate 		}
2770Sstevel@tonic-gate 		break;
278676Sizick 	case CKM_SHA256:
279676Sizick 	case CKM_SHA384:
280676Sizick 	case CKM_SHA512:
281676Sizick 		if (pData != NULL) {
282676Sizick 			/*
283676Sizick 			 * this is called by soft_digest()
284676Sizick 			 */
285676Sizick 
286676Sizick 			SHA2Update((SHA2_CTX *)session_p->digest.context,
287676Sizick 			    pData, ulDataLen);
288676Sizick 
289676Sizick 			SHA2Final(pDigest,
290676Sizick 			    (SHA2_CTX *)session_p->digest.context);
291676Sizick 		} else {
292676Sizick 			/*
293676Sizick 			 * this is called by soft_digest_final()
294676Sizick 			 */
295676Sizick 			SHA2Final(pDigest,
296676Sizick 			    (SHA2_CTX *)session_p->digest.context);
297676Sizick 			len = sizeof (SHA2_CTX);
298676Sizick 		}
299676Sizick 
300676Sizick 		break;
3010Sstevel@tonic-gate 	}
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 	/* Paranoia on behalf of C_DigestKey callers: bzero the context */
3040Sstevel@tonic-gate 	if (session_p->digest.flags & CRYPTO_KEY_DIGESTED) {
3050Sstevel@tonic-gate 		bzero(session_p->digest.context, len);
3060Sstevel@tonic-gate 		session_p->digest.flags &= ~CRYPTO_KEY_DIGESTED;
3070Sstevel@tonic-gate 	}
3080Sstevel@tonic-gate 	*pulDigestLen = digestLen;
3090Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
3100Sstevel@tonic-gate 	free(session_p->digest.context);
3110Sstevel@tonic-gate 	session_p->digest.context = NULL;
3120Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
3130Sstevel@tonic-gate 
3140Sstevel@tonic-gate 	return (CKR_OK);
3150Sstevel@tonic-gate }
3160Sstevel@tonic-gate 
3170Sstevel@tonic-gate 
3180Sstevel@tonic-gate /*
3190Sstevel@tonic-gate  * soft_digest()
3200Sstevel@tonic-gate  *
3210Sstevel@tonic-gate  * Arguments:
3220Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
3230Sstevel@tonic-gate  *      pData:		pointer to the input data to be digested
3240Sstevel@tonic-gate  *      ulDataLen:	length of the input data
3250Sstevel@tonic-gate  *      pDigest:	pointer to the output data after digesting
3260Sstevel@tonic-gate  *      pulDigestLen:	length of the output data
3270Sstevel@tonic-gate  *
3280Sstevel@tonic-gate  * Description:
3290Sstevel@tonic-gate  *      called by C_Digest(). This function calls soft_digest_common().
3300Sstevel@tonic-gate  *
3310Sstevel@tonic-gate  * Returns:
3320Sstevel@tonic-gate  *      see return values in soft_digest_common().
3330Sstevel@tonic-gate  */
3340Sstevel@tonic-gate CK_RV
soft_digest(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)3350Sstevel@tonic-gate soft_digest(soft_session_t *session_p, CK_BYTE_PTR pData, CK_ULONG ulDataLen,
3360Sstevel@tonic-gate 	CK_BYTE_PTR pDigest, CK_ULONG_PTR pulDigestLen)
3370Sstevel@tonic-gate {
3380Sstevel@tonic-gate 
3390Sstevel@tonic-gate 	return (soft_digest_common(session_p, pData, ulDataLen,
3400Sstevel@tonic-gate 	    pDigest, pulDigestLen));
3410Sstevel@tonic-gate }
3420Sstevel@tonic-gate 
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate /*
3450Sstevel@tonic-gate  * soft_digest_update()
3460Sstevel@tonic-gate  *
3470Sstevel@tonic-gate  * Arguments:
3480Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
3490Sstevel@tonic-gate  *      pPart:		pointer to the input data to be digested
3500Sstevel@tonic-gate  *      ulPartLen:	length of the input data
3510Sstevel@tonic-gate  *
3520Sstevel@tonic-gate  * Description:
3530Sstevel@tonic-gate  *      called by C_DigestUpdate(). This function calls the corresponding
3540Sstevel@tonic-gate  *	software provided digest update routine based on the mechanism.
3550Sstevel@tonic-gate  *
3560Sstevel@tonic-gate  * Returns:
3570Sstevel@tonic-gate  *      CKR_OK: success
3580Sstevel@tonic-gate  *      CKR_MECHANISM_INVALID: invalid MECHANISM type.
3590Sstevel@tonic-gate  */
3600Sstevel@tonic-gate CK_RV
soft_digest_update(soft_session_t * session_p,CK_BYTE_PTR pPart,CK_ULONG ulPartLen)3610Sstevel@tonic-gate soft_digest_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
3620Sstevel@tonic-gate 	CK_ULONG ulPartLen)
3630Sstevel@tonic-gate {
3640Sstevel@tonic-gate 
3650Sstevel@tonic-gate 	switch (session_p->digest.mech.mechanism) {
3660Sstevel@tonic-gate 
3670Sstevel@tonic-gate 	case CKM_MD5:
3680Sstevel@tonic-gate #ifdef	__sparcv9
3690Sstevel@tonic-gate 		MD5Update((MD5_CTX *)session_p->digest.context,
3700Sstevel@tonic-gate 		    /* LINTED */
3710Sstevel@tonic-gate 		    pPart, (uint_t)ulPartLen);
3720Sstevel@tonic-gate #else	/* !__sparcv9 */
3730Sstevel@tonic-gate 		MD5Update((MD5_CTX *)session_p->digest.context,
3740Sstevel@tonic-gate 		    pPart, ulPartLen);
3750Sstevel@tonic-gate #endif	/* __sparcv9 */
3760Sstevel@tonic-gate 		break;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	case CKM_SHA_1:
3790Sstevel@tonic-gate #ifdef	__sparcv9
3800Sstevel@tonic-gate 		SHA1Update((SHA1_CTX *)session_p->digest.context,
3810Sstevel@tonic-gate 		    /* LINTED */
3820Sstevel@tonic-gate 		    pPart, (uint32_t)ulPartLen);
3830Sstevel@tonic-gate #else	/* !__sparcv9 */
3840Sstevel@tonic-gate 		SHA1Update((SHA1_CTX *)session_p->digest.context,
3850Sstevel@tonic-gate 		    pPart, ulPartLen);
3860Sstevel@tonic-gate #endif	/* __sparcv9 */
3870Sstevel@tonic-gate 		break;
3880Sstevel@tonic-gate 
389676Sizick 	case CKM_SHA256:
390676Sizick 	case CKM_SHA384:
391676Sizick 	case CKM_SHA512:
392676Sizick 		SHA2Update((SHA2_CTX *)session_p->digest.context,
393676Sizick 		    pPart, ulPartLen);
394676Sizick 		break;
395676Sizick 
3960Sstevel@tonic-gate 	default:
3970Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
3980Sstevel@tonic-gate 	}
3990Sstevel@tonic-gate 
4000Sstevel@tonic-gate 	return (CKR_OK);
4010Sstevel@tonic-gate }
4020Sstevel@tonic-gate 
4030Sstevel@tonic-gate 
4040Sstevel@tonic-gate /*
4050Sstevel@tonic-gate  * soft_digest_final()
4060Sstevel@tonic-gate  *
4070Sstevel@tonic-gate  * Arguments:
4080Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
4090Sstevel@tonic-gate  *      pDigest:	pointer to the output data after digesting
4100Sstevel@tonic-gate  *      pulDigestLen:	length of the output data
4110Sstevel@tonic-gate  *
4120Sstevel@tonic-gate  * Description:
4130Sstevel@tonic-gate  *      called by C_DigestFinal(). This function calls soft_digest_common().
4140Sstevel@tonic-gate  *
4150Sstevel@tonic-gate  * Returns:
4160Sstevel@tonic-gate  *	see return values in soft_digest_common().
4170Sstevel@tonic-gate  */
4180Sstevel@tonic-gate CK_RV
soft_digest_final(soft_session_t * session_p,CK_BYTE_PTR pDigest,CK_ULONG_PTR pulDigestLen)4190Sstevel@tonic-gate soft_digest_final(soft_session_t *session_p, CK_BYTE_PTR pDigest,
4200Sstevel@tonic-gate 	CK_ULONG_PTR pulDigestLen)
4210Sstevel@tonic-gate {
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	return (soft_digest_common(session_p, NULL, 0,
4240Sstevel@tonic-gate 	    pDigest, pulDigestLen));
4250Sstevel@tonic-gate }
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate /*
4280Sstevel@tonic-gate  * Perform digest init operation internally for the support of
4290Sstevel@tonic-gate  * CKM_MD5_RSA_PKCS, CKM_SHA1_RSA_PKCS, CKM_SHA1_KEY_DERIVATION
4300Sstevel@tonic-gate  * and CKM_MD5_KEY_DERIVATION mechanisms.
4310Sstevel@tonic-gate  *
4320Sstevel@tonic-gate  * This function is called with the session being held, and without
4330Sstevel@tonic-gate  * its mutex taken.
4340Sstevel@tonic-gate  */
4350Sstevel@tonic-gate CK_RV
soft_digest_init_internal(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism)4360Sstevel@tonic-gate soft_digest_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR
4370Sstevel@tonic-gate 	pMechanism)
4380Sstevel@tonic-gate {
4390Sstevel@tonic-gate 
4400Sstevel@tonic-gate 	CK_RV rv;
4410Sstevel@tonic-gate 
4420Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	/* Check to see if digest operation is already active */
4450Sstevel@tonic-gate 	if (session_p->digest.flags & CRYPTO_OPERATION_ACTIVE) {
4460Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
4470Sstevel@tonic-gate 		return (CKR_OPERATION_ACTIVE);
4480Sstevel@tonic-gate 	}
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	session_p->digest.flags = CRYPTO_OPERATION_ACTIVE;
4510Sstevel@tonic-gate 
4520Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 	rv = soft_digest_init(session_p, pMechanism);
4550Sstevel@tonic-gate 
4560Sstevel@tonic-gate 	if (rv != CKR_OK) {
4570Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
4580Sstevel@tonic-gate 		session_p->digest.flags &= ~CRYPTO_OPERATION_ACTIVE;
4590Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
4600Sstevel@tonic-gate 	}
4610Sstevel@tonic-gate 
4620Sstevel@tonic-gate 	return (rv);
4630Sstevel@tonic-gate }
4640Sstevel@tonic-gate 
4650Sstevel@tonic-gate /*
4660Sstevel@tonic-gate  * Call soft_digest_update() function with the value of a secret key.
4670Sstevel@tonic-gate  */
4680Sstevel@tonic-gate CK_RV
soft_digest_key(soft_session_t * session_p,soft_object_t * key_p)4690Sstevel@tonic-gate soft_digest_key(soft_session_t *session_p, soft_object_t *key_p)
4700Sstevel@tonic-gate {
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate 	CK_RV rv;
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	/* Only secret key is allowed to be digested */
4750Sstevel@tonic-gate 	if (key_p->class != CKO_SECRET_KEY)
4760Sstevel@tonic-gate 		return (CKR_KEY_INDIGESTIBLE);
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate 	if ((OBJ_SEC_VALUE(key_p) == NULL) ||
4790Sstevel@tonic-gate 	    (OBJ_SEC_VALUE_LEN(key_p) == 0))
4800Sstevel@tonic-gate 		return (CKR_KEY_SIZE_RANGE);
4810Sstevel@tonic-gate 
4820Sstevel@tonic-gate 	rv = soft_digest_update(session_p, OBJ_SEC_VALUE(key_p),
4830Sstevel@tonic-gate 	    OBJ_SEC_VALUE_LEN(key_p));
4840Sstevel@tonic-gate 
4850Sstevel@tonic-gate 	return (rv);
4860Sstevel@tonic-gate 
4870Sstevel@tonic-gate }
488*7690SAlexandr.Nedvedicky@Sun.COM 
489*7690SAlexandr.Nedvedicky@Sun.COM /*
490*7690SAlexandr.Nedvedicky@Sun.COM  * This function releases allocated digest context. The caller
491*7690SAlexandr.Nedvedicky@Sun.COM  * may (lock_held == B_TRUE) or may not (lock_held == B_FALSE)
492*7690SAlexandr.Nedvedicky@Sun.COM  * hold a session mutex.
493*7690SAlexandr.Nedvedicky@Sun.COM  */
494*7690SAlexandr.Nedvedicky@Sun.COM void
soft_digest_cleanup(soft_session_t * session_p,boolean_t lock_held)495*7690SAlexandr.Nedvedicky@Sun.COM soft_digest_cleanup(soft_session_t *session_p, boolean_t lock_held)
496*7690SAlexandr.Nedvedicky@Sun.COM {
497*7690SAlexandr.Nedvedicky@Sun.COM 	boolean_t lock_true = B_TRUE;
498*7690SAlexandr.Nedvedicky@Sun.COM 
499*7690SAlexandr.Nedvedicky@Sun.COM 	if (!lock_held)
500*7690SAlexandr.Nedvedicky@Sun.COM 		(void) pthread_mutex_lock(&session_p->session_mutex);
501*7690SAlexandr.Nedvedicky@Sun.COM 
502*7690SAlexandr.Nedvedicky@Sun.COM 	if (session_p->digest.context != NULL) {
503*7690SAlexandr.Nedvedicky@Sun.COM 		free(session_p->digest.context);
504*7690SAlexandr.Nedvedicky@Sun.COM 		session_p->digest.context = NULL;
505*7690SAlexandr.Nedvedicky@Sun.COM 	}
506*7690SAlexandr.Nedvedicky@Sun.COM 
507*7690SAlexandr.Nedvedicky@Sun.COM 	session_p->digest.flags = 0;
508*7690SAlexandr.Nedvedicky@Sun.COM 
509*7690SAlexandr.Nedvedicky@Sun.COM 	if (!lock_held)
510*7690SAlexandr.Nedvedicky@Sun.COM 		SES_REFRELE(session_p, lock_true);
511*7690SAlexandr.Nedvedicky@Sun.COM 
512*7690SAlexandr.Nedvedicky@Sun.COM }
513