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
52786Sdinak  * Common Development and Distribution License (the "License").
62786Sdinak  * 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  */
21*12573SDina.Nimeh@Sun.COM 
220Sstevel@tonic-gate /*
23*12573SDina.Nimeh@Sun.COM  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #include <pthread.h>
270Sstevel@tonic-gate #include <stdlib.h>
280Sstevel@tonic-gate #include <string.h>
290Sstevel@tonic-gate #include <strings.h>
300Sstevel@tonic-gate #include <sys/types.h>
310Sstevel@tonic-gate #include <security/cryptoki.h>
327188Smcpowers #include <modes/modes.h>
330Sstevel@tonic-gate #include <arcfour.h>
340Sstevel@tonic-gate #include "softSession.h"
350Sstevel@tonic-gate #include "softObject.h"
360Sstevel@tonic-gate #include "softOps.h"
370Sstevel@tonic-gate #include "softCrypt.h"
380Sstevel@tonic-gate #include "softRSA.h"
390Sstevel@tonic-gate 
400Sstevel@tonic-gate /*
410Sstevel@tonic-gate  * Remove padding bytes.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate CK_RV
soft_remove_pkcs7_padding(CK_BYTE * pData,CK_ULONG padded_len,CK_ULONG * pulDataLen)440Sstevel@tonic-gate soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
45*12573SDina.Nimeh@Sun.COM     CK_ULONG *pulDataLen)
460Sstevel@tonic-gate {
47*12573SDina.Nimeh@Sun.COM 	CK_RV	rv;
480Sstevel@tonic-gate 
49*12573SDina.Nimeh@Sun.COM #ifdef	__sparcv9
50*12573SDina.Nimeh@Sun.COM 	if ((rv = pkcs7_decode(pData, (&padded_len))) != CKR_OK)
51*12573SDina.Nimeh@Sun.COM #else	/* !__sparcv9 */
52*12573SDina.Nimeh@Sun.COM 	if ((rv = pkcs7_decode(pData, (size_t *)(&padded_len))) != CKR_OK)
53*12573SDina.Nimeh@Sun.COM #endif	/* __sparcv9 */
54*12573SDina.Nimeh@Sun.COM 		return (rv);
550Sstevel@tonic-gate 
56*12573SDina.Nimeh@Sun.COM 	*pulDataLen = padded_len;
570Sstevel@tonic-gate 	return (CKR_OK);
580Sstevel@tonic-gate }
590Sstevel@tonic-gate 
600Sstevel@tonic-gate 
610Sstevel@tonic-gate /*
620Sstevel@tonic-gate  * soft_decrypt_init()
630Sstevel@tonic-gate  *
640Sstevel@tonic-gate  * Arguments:
650Sstevel@tonic-gate  *	session_p:	pointer to soft_session_t struct
660Sstevel@tonic-gate  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
670Sstevel@tonic-gate  *	key_p:		pointer to key soft_object_t struct
680Sstevel@tonic-gate  *
690Sstevel@tonic-gate  * Description:
700Sstevel@tonic-gate  *	called by C_DecryptInit(). This function calls the corresponding
710Sstevel@tonic-gate  *	decrypt init routine based on the mechanism.
720Sstevel@tonic-gate  *
730Sstevel@tonic-gate  * Returns:
740Sstevel@tonic-gate  *	CKR_OK: success
750Sstevel@tonic-gate  *	CKR_HOST_MEMORY: run out of system memory
760Sstevel@tonic-gate  *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
770Sstevel@tonic-gate  *	CKR_MECHANISM_INVALID: invalid mechanism type
780Sstevel@tonic-gate  *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
790Sstevel@tonic-gate  *				   with the specified mechanism
800Sstevel@tonic-gate  */
810Sstevel@tonic-gate CK_RV
soft_decrypt_init(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p)820Sstevel@tonic-gate soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
830Sstevel@tonic-gate     soft_object_t *key_p)
840Sstevel@tonic-gate {
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	CK_RV rv;
870Sstevel@tonic-gate 
880Sstevel@tonic-gate 	switch (pMechanism->mechanism) {
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	case CKM_DES_ECB:
910Sstevel@tonic-gate 
920Sstevel@tonic-gate 		if (key_p->key_type != CKK_DES) {
930Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
940Sstevel@tonic-gate 		}
950Sstevel@tonic-gate 
960Sstevel@tonic-gate 		goto ecb_common;
970Sstevel@tonic-gate 
980Sstevel@tonic-gate 	case CKM_DES3_ECB:
990Sstevel@tonic-gate 
1000Sstevel@tonic-gate 		if ((key_p->key_type != CKK_DES2) &&
1010Sstevel@tonic-gate 		    (key_p->key_type != CKK_DES3)) {
1020Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1030Sstevel@tonic-gate 		}
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate ecb_common:
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate 		return (soft_des_crypt_init_common(session_p, pMechanism,
1080Sstevel@tonic-gate 		    key_p, B_FALSE));
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	case CKM_DES_CBC:
1110Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
1120Sstevel@tonic-gate 
1130Sstevel@tonic-gate 		if (key_p->key_type != CKK_DES) {
1140Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1150Sstevel@tonic-gate 		}
1160Sstevel@tonic-gate 
1170Sstevel@tonic-gate 		goto cbc_common;
1180Sstevel@tonic-gate 
1190Sstevel@tonic-gate 	case CKM_DES3_CBC:
1200Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
1210Sstevel@tonic-gate 	{
1220Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
1230Sstevel@tonic-gate 
1240Sstevel@tonic-gate 		if ((key_p->key_type != CKK_DES2) &&
1250Sstevel@tonic-gate 		    (key_p->key_type != CKK_DES3)) {
1260Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1270Sstevel@tonic-gate 		}
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate cbc_common:
1300Sstevel@tonic-gate 		if ((pMechanism->pParameter == NULL) ||
1310Sstevel@tonic-gate 		    (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
1320Sstevel@tonic-gate 			return (CKR_MECHANISM_PARAM_INVALID);
1330Sstevel@tonic-gate 		}
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 		rv = soft_des_crypt_init_common(session_p, pMechanism,
1360Sstevel@tonic-gate 		    key_p, B_FALSE);
1370Sstevel@tonic-gate 
1380Sstevel@tonic-gate 		if (rv != CKR_OK)
1390Sstevel@tonic-gate 			return (rv);
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
1420Sstevel@tonic-gate 
1430Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
1440Sstevel@tonic-gate 		/* Save Initialization Vector (IV) in the context. */
1450Sstevel@tonic-gate 		(void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
1460Sstevel@tonic-gate 		    DES_BLOCK_LEN);
1470Sstevel@tonic-gate 
1480Sstevel@tonic-gate 		/* Allocate a context for DES cipher-block chaining. */
1490Sstevel@tonic-gate 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
1500Sstevel@tonic-gate 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
1510Sstevel@tonic-gate 		    soft_des_ctx->ivec, key_p->key_type);
1520Sstevel@tonic-gate 
1530Sstevel@tonic-gate 		if (soft_des_ctx->des_cbc == NULL) {
1540Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
1550Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
1560Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
1570Sstevel@tonic-gate 			free(session_p->decrypt.context);
1580Sstevel@tonic-gate 			session_p->decrypt.context = NULL;
1590Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&session_p->session_mutex);
1600Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
1610Sstevel@tonic-gate 		}
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
1640Sstevel@tonic-gate 
1650Sstevel@tonic-gate 		return (rv);
1660Sstevel@tonic-gate 	}
1670Sstevel@tonic-gate 	case CKM_AES_ECB:
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 		if (key_p->key_type != CKK_AES) {
1700Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1710Sstevel@tonic-gate 		}
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 		return (soft_aes_crypt_init_common(session_p, pMechanism,
1740Sstevel@tonic-gate 		    key_p, B_FALSE));
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 	case CKM_AES_CBC:
1770Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
1780Sstevel@tonic-gate 	{
1790Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 		if (key_p->key_type != CKK_AES) {
1820Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1830Sstevel@tonic-gate 		}
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 		if ((pMechanism->pParameter == NULL) ||
1860Sstevel@tonic-gate 		    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
1870Sstevel@tonic-gate 			return (CKR_MECHANISM_PARAM_INVALID);
1880Sstevel@tonic-gate 		}
1890Sstevel@tonic-gate 
1900Sstevel@tonic-gate 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
1910Sstevel@tonic-gate 		    key_p, B_FALSE);
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 		if (rv != CKR_OK)
1940Sstevel@tonic-gate 			return (rv);
1950Sstevel@tonic-gate 
1960Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 		/* Save Initialization Vector (IV) in the context. */
2010Sstevel@tonic-gate 		(void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
2020Sstevel@tonic-gate 		    AES_BLOCK_LEN);
2030Sstevel@tonic-gate 
2040Sstevel@tonic-gate 		/* Allocate a context for AES cipher-block chaining. */
2050Sstevel@tonic-gate 		soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
2060Sstevel@tonic-gate 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
2070Sstevel@tonic-gate 		    soft_aes_ctx->ivec);
2080Sstevel@tonic-gate 
2090Sstevel@tonic-gate 		if (soft_aes_ctx->aes_cbc == NULL) {
2100Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
2110Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
2120Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
2130Sstevel@tonic-gate 			free(session_p->decrypt.context);
2140Sstevel@tonic-gate 			session_p->decrypt.context = NULL;
2150Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&session_p->session_mutex);
2160Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
2170Sstevel@tonic-gate 		}
2180Sstevel@tonic-gate 
2190Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 		return (rv);
2220Sstevel@tonic-gate 	}
2237188Smcpowers 	case CKM_AES_CTR:
2247188Smcpowers 	{
2257188Smcpowers 		soft_aes_ctx_t *soft_aes_ctx;
2260Sstevel@tonic-gate 
2277188Smcpowers 		if (key_p->key_type != CKK_AES) {
2287188Smcpowers 			return (CKR_KEY_TYPE_INCONSISTENT);
2297188Smcpowers 		}
2307188Smcpowers 
2317188Smcpowers 		if (pMechanism->pParameter == NULL ||
2327188Smcpowers 		    pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
2337188Smcpowers 			return (CKR_MECHANISM_PARAM_INVALID);
2347188Smcpowers 		}
2357188Smcpowers 
2367188Smcpowers 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
2377188Smcpowers 		    key_p, B_FALSE);
2387188Smcpowers 
2397188Smcpowers 		if (rv != CKR_OK)
2407188Smcpowers 			return (rv);
2417188Smcpowers 
2427188Smcpowers 		(void) pthread_mutex_lock(&session_p->session_mutex);
2437188Smcpowers 
2447188Smcpowers 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
2457188Smcpowers 		soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
2467188Smcpowers 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
2477188Smcpowers 		    pMechanism->pParameter);
2487188Smcpowers 
2497188Smcpowers 		if (soft_aes_ctx->aes_cbc == NULL) {
2507188Smcpowers 			bzero(soft_aes_ctx->key_sched,
2517188Smcpowers 			    soft_aes_ctx->keysched_len);
2527188Smcpowers 			free(soft_aes_ctx->key_sched);
2537188Smcpowers 			free(session_p->decrypt.context);
2547188Smcpowers 			session_p->decrypt.context = NULL;
2557188Smcpowers 			rv = CKR_HOST_MEMORY;
2567188Smcpowers 		}
2577188Smcpowers 
2587188Smcpowers 		(void) pthread_mutex_unlock(&session_p->session_mutex);
2597188Smcpowers 
2607188Smcpowers 		return (rv);
2617188Smcpowers 	}
262676Sizick 	case CKM_BLOWFISH_CBC:
263676Sizick 	{
264676Sizick 		soft_blowfish_ctx_t *soft_blowfish_ctx;
265676Sizick 
266676Sizick 		if (key_p->key_type != CKK_BLOWFISH)
267676Sizick 			return (CKR_KEY_TYPE_INCONSISTENT);
268676Sizick 
269676Sizick 		if ((pMechanism->pParameter == NULL) ||
270676Sizick 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
271676Sizick 			return (CKR_MECHANISM_PARAM_INVALID);
272676Sizick 
273676Sizick 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
274676Sizick 		    key_p, B_FALSE);
275676Sizick 
276676Sizick 		if (rv != CKR_OK)
277676Sizick 			return (rv);
278676Sizick 
279676Sizick 		(void) pthread_mutex_lock(&session_p->session_mutex);
280676Sizick 
281676Sizick 		soft_blowfish_ctx =
282676Sizick 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
283676Sizick 
284676Sizick 		/* Save Initialization Vector in the context. */
285676Sizick 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
286676Sizick 		    BLOWFISH_BLOCK_LEN);
287676Sizick 
288676Sizick 		/* Allocate a context for CBC */
289676Sizick 		soft_blowfish_ctx->blowfish_cbc =
290676Sizick 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
2917188Smcpowers 		    soft_blowfish_ctx->keysched_len,
2927188Smcpowers 		    soft_blowfish_ctx->ivec);
293676Sizick 
294676Sizick 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
295676Sizick 			bzero(soft_blowfish_ctx->key_sched,
296676Sizick 			    soft_blowfish_ctx->keysched_len);
297676Sizick 			free(soft_blowfish_ctx->key_sched);
298676Sizick 			free(session_p->decrypt.context = NULL);
299676Sizick 			(void) pthread_mutex_unlock(&session_p->session_mutex);
300676Sizick 			return (CKR_HOST_MEMORY);
301676Sizick 		}
302676Sizick 
303676Sizick 		(void) pthread_mutex_unlock(&session_p->session_mutex);
304676Sizick 		return (rv);
305676Sizick 	}
306676Sizick 
3070Sstevel@tonic-gate 	case CKM_RC4:
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 		if (key_p->key_type != CKK_RC4) {
3100Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
3110Sstevel@tonic-gate 		}
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
3140Sstevel@tonic-gate 		    B_FALSE));
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	case CKM_RSA_X_509:
3170Sstevel@tonic-gate 	case CKM_RSA_PKCS:
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 		if (key_p->key_type != CKK_RSA) {
3200Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
3210Sstevel@tonic-gate 		}
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
3240Sstevel@tonic-gate 		    key_p, B_FALSE));
3250Sstevel@tonic-gate 
3260Sstevel@tonic-gate 	default:
3270Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
3280Sstevel@tonic-gate 	}
3290Sstevel@tonic-gate }
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 
3320Sstevel@tonic-gate /*
3330Sstevel@tonic-gate  * soft_decrypt_common()
3340Sstevel@tonic-gate  *
3350Sstevel@tonic-gate  * Arguments:
3360Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
3370Sstevel@tonic-gate  *	pEncrypted:	pointer to the encrypted data as input
3380Sstevel@tonic-gate  *	ulEncryptedLen:	length of the input data
3390Sstevel@tonic-gate  *	pData:		pointer to the output data contains plaintext
3400Sstevel@tonic-gate  *	pulDataLen:	pointer to the length of the output data
3410Sstevel@tonic-gate  *	Update:		boolean flag indicates caller is soft_decrypt
3420Sstevel@tonic-gate  *			or soft_decrypt_update
3430Sstevel@tonic-gate  *
3440Sstevel@tonic-gate  * Description:
3450Sstevel@tonic-gate  *      This function calls the corresponding decrypt routine based
3460Sstevel@tonic-gate  *	on the mechanism.
3470Sstevel@tonic-gate  *
3480Sstevel@tonic-gate  * Returns:
3490Sstevel@tonic-gate  *	see soft_decrypt_common().
3500Sstevel@tonic-gate  */
3510Sstevel@tonic-gate CK_RV
soft_decrypt_common(soft_session_t * session_p,CK_BYTE_PTR pEncrypted,CK_ULONG ulEncryptedLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen,boolean_t Update)3520Sstevel@tonic-gate soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
3530Sstevel@tonic-gate     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
3540Sstevel@tonic-gate     CK_ULONG_PTR pulDataLen, boolean_t Update)
3550Sstevel@tonic-gate {
3560Sstevel@tonic-gate 
3570Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
3580Sstevel@tonic-gate 
3590Sstevel@tonic-gate 	switch (mechanism) {
3600Sstevel@tonic-gate 
3610Sstevel@tonic-gate 	case CKM_DES_ECB:
3620Sstevel@tonic-gate 	case CKM_DES_CBC:
3630Sstevel@tonic-gate 	case CKM_DES3_ECB:
3640Sstevel@tonic-gate 	case CKM_DES3_CBC:
3652786Sdinak 
3662786Sdinak 		if (ulEncryptedLen == 0) {
3672786Sdinak 			*pulDataLen = 0;
3682786Sdinak 			return (CKR_OK);
3692786Sdinak 		}
3702786Sdinak 		/* FALLTHROUGH */
3712786Sdinak 
3722786Sdinak 	case CKM_DES_CBC_PAD:
3730Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 		return (soft_des_decrypt_common(session_p, pEncrypted,
3760Sstevel@tonic-gate 		    ulEncryptedLen, pData, pulDataLen, Update));
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	case CKM_AES_ECB:
3790Sstevel@tonic-gate 	case CKM_AES_CBC:
3807188Smcpowers 	case CKM_AES_CTR:
3812786Sdinak 
3822786Sdinak 		if (ulEncryptedLen == 0) {
3832786Sdinak 			*pulDataLen = 0;
3842786Sdinak 			return (CKR_OK);
3852786Sdinak 		}
3862786Sdinak 		/* FALLTHROUGH */
3872786Sdinak 
3880Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
3890Sstevel@tonic-gate 
3900Sstevel@tonic-gate 		return (soft_aes_decrypt_common(session_p, pEncrypted,
3910Sstevel@tonic-gate 		    ulEncryptedLen, pData, pulDataLen, Update));
3920Sstevel@tonic-gate 
393676Sizick 	case CKM_BLOWFISH_CBC:
394676Sizick 
3952786Sdinak 		if (ulEncryptedLen == 0) {
3962786Sdinak 			*pulDataLen = 0;
3972786Sdinak 			return (CKR_OK);
3982786Sdinak 		}
3992786Sdinak 
400676Sizick 		return (soft_blowfish_decrypt_common(session_p, pEncrypted,
401676Sizick 		    ulEncryptedLen, pData, pulDataLen, Update));
402676Sizick 
4030Sstevel@tonic-gate 	case CKM_RC4:
4040Sstevel@tonic-gate 
4052786Sdinak 		if (ulEncryptedLen == 0) {
4062786Sdinak 			*pulDataLen = 0;
4072786Sdinak 			return (CKR_OK);
4080Sstevel@tonic-gate 		}
4092786Sdinak 
4102786Sdinak 
4112786Sdinak 		return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
4122786Sdinak 		    ulEncryptedLen, pData, pulDataLen));
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 	case CKM_RSA_X_509:
4150Sstevel@tonic-gate 	case CKM_RSA_PKCS:
4160Sstevel@tonic-gate 
4170Sstevel@tonic-gate 		return (soft_rsa_decrypt_common(session_p, pEncrypted,
4180Sstevel@tonic-gate 		    ulEncryptedLen, pData, pulDataLen, mechanism));
4190Sstevel@tonic-gate 
4200Sstevel@tonic-gate 	default:
4210Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
4220Sstevel@tonic-gate 
4230Sstevel@tonic-gate 	}
4240Sstevel@tonic-gate }
4250Sstevel@tonic-gate 
4260Sstevel@tonic-gate 
4270Sstevel@tonic-gate /*
4280Sstevel@tonic-gate  * soft_decrypt()
4290Sstevel@tonic-gate  *
4300Sstevel@tonic-gate  * Arguments:
4310Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
4320Sstevel@tonic-gate  *	pEncryptedData: pointer to the encrypted data as input
4330Sstevel@tonic-gate  *	ulEncryptedDataLen: length of the input data
4340Sstevel@tonic-gate  *	pData:		pointer to the output data contains plaintext
4350Sstevel@tonic-gate  *	pulDataLen:	pointer to the length of the output data
4360Sstevel@tonic-gate  *
4370Sstevel@tonic-gate  * Description:
4380Sstevel@tonic-gate  *      called by C_Decrypt(). This function calls the soft_decrypt_common
4390Sstevel@tonic-gate  *	routine.
4400Sstevel@tonic-gate  *
4410Sstevel@tonic-gate  * Returns:
4420Sstevel@tonic-gate  *	see soft_decrypt_common().
4430Sstevel@tonic-gate  */
4440Sstevel@tonic-gate CK_RV
soft_decrypt(soft_session_t * session_p,CK_BYTE_PTR pEncryptedData,CK_ULONG ulEncryptedDataLen,CK_BYTE_PTR pData,CK_ULONG_PTR pulDataLen)4450Sstevel@tonic-gate soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
4460Sstevel@tonic-gate     CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
4470Sstevel@tonic-gate     CK_ULONG_PTR pulDataLen)
4480Sstevel@tonic-gate {
4490Sstevel@tonic-gate 
4500Sstevel@tonic-gate 	return (soft_decrypt_common(session_p, pEncryptedData,
4510Sstevel@tonic-gate 	    ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
4520Sstevel@tonic-gate }
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 
4550Sstevel@tonic-gate /*
4560Sstevel@tonic-gate  * soft_decrypt_update()
4570Sstevel@tonic-gate  *
4580Sstevel@tonic-gate  * Arguments:
4590Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
4600Sstevel@tonic-gate  *	pEncryptedPart: pointer to the encrypted data as input
4610Sstevel@tonic-gate  *	ulEncryptedPartLen: length of the input data
4620Sstevel@tonic-gate  *	pPart:          pointer to the output data contains plaintext
4630Sstevel@tonic-gate  *	pulPartLen:     pointer to the length of the output data
4640Sstevel@tonic-gate  *
4650Sstevel@tonic-gate  * Description:
4660Sstevel@tonic-gate  *      called by C_DecryptUpdate(). This function calls the
4670Sstevel@tonic-gate  *	soft_decrypt_common routine (with update flag on).
4680Sstevel@tonic-gate  *
4690Sstevel@tonic-gate  * Returns:
4700Sstevel@tonic-gate  *	see soft_decrypt_common().
4710Sstevel@tonic-gate  */
4720Sstevel@tonic-gate CK_RV
soft_decrypt_update(soft_session_t * session_p,CK_BYTE_PTR pEncryptedPart,CK_ULONG ulEncryptedPartLen,CK_BYTE_PTR pPart,CK_ULONG_PTR pulPartLen)4730Sstevel@tonic-gate soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
4740Sstevel@tonic-gate 	CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
4750Sstevel@tonic-gate 	CK_ULONG_PTR pulPartLen)
4760Sstevel@tonic-gate {
4770Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
4780Sstevel@tonic-gate 
4790Sstevel@tonic-gate 	switch (mechanism) {
4800Sstevel@tonic-gate 
4810Sstevel@tonic-gate 	case CKM_DES_ECB:
4820Sstevel@tonic-gate 	case CKM_DES_CBC:
4830Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
4840Sstevel@tonic-gate 	case CKM_DES3_ECB:
4850Sstevel@tonic-gate 	case CKM_DES3_CBC:
4860Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
4870Sstevel@tonic-gate 	case CKM_AES_ECB:
4880Sstevel@tonic-gate 	case CKM_AES_CBC:
4890Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
4907188Smcpowers 	case CKM_AES_CTR:
491676Sizick 	case CKM_BLOWFISH_CBC:
4922786Sdinak 	case CKM_RC4:
4930Sstevel@tonic-gate 
4940Sstevel@tonic-gate 		return (soft_decrypt_common(session_p, pEncryptedPart,
4950Sstevel@tonic-gate 		    ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	default:
4980Sstevel@tonic-gate 		/* PKCS11: The mechanism only supports single-part operation. */
4990Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
5000Sstevel@tonic-gate 	}
5010Sstevel@tonic-gate 
5020Sstevel@tonic-gate }
5030Sstevel@tonic-gate 
5040Sstevel@tonic-gate 
5050Sstevel@tonic-gate /*
5060Sstevel@tonic-gate  * soft_decrypt_final()
5070Sstevel@tonic-gate  *
5080Sstevel@tonic-gate  * Arguments:
5090Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
5100Sstevel@tonic-gate  *      pLastPart:	pointer to the last recovered data part
5110Sstevel@tonic-gate  *      pulLastPartLen:	pointer to the length of the last recovered data part
5120Sstevel@tonic-gate  *
5130Sstevel@tonic-gate  * Description:
5140Sstevel@tonic-gate  *      called by C_DecryptFinal().
5150Sstevel@tonic-gate  *
5160Sstevel@tonic-gate  * Returns:
5170Sstevel@tonic-gate  *	CKR_OK: success
5180Sstevel@tonic-gate  *	CKR_FUNCTION_FAILED: decrypt final function failed
5190Sstevel@tonic-gate  *	CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
5200Sstevel@tonic-gate  */
5210Sstevel@tonic-gate CK_RV
soft_decrypt_final(soft_session_t * session_p,CK_BYTE_PTR pLastPart,CK_ULONG_PTR pulLastPartLen)5220Sstevel@tonic-gate soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
5230Sstevel@tonic-gate 	CK_ULONG_PTR pulLastPartLen)
5240Sstevel@tonic-gate {
5250Sstevel@tonic-gate 
5260Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
5270Sstevel@tonic-gate 	CK_ULONG out_len;
5280Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
5290Sstevel@tonic-gate 	int rc;
5300Sstevel@tonic-gate 
5310Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 	if (session_p->decrypt.context == NULL) {
5340Sstevel@tonic-gate 		rv = CKR_OPERATION_NOT_INITIALIZED;
5350Sstevel@tonic-gate 		*pulLastPartLen = 0;
5360Sstevel@tonic-gate 		goto clean2;
5370Sstevel@tonic-gate 	}
5380Sstevel@tonic-gate 	switch (mechanism) {
5390Sstevel@tonic-gate 
5400Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
5410Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
5420Sstevel@tonic-gate 	{
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
5450Sstevel@tonic-gate 
5460Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
5470Sstevel@tonic-gate 
5480Sstevel@tonic-gate 		/*
5490Sstevel@tonic-gate 		 * We should have only one block of data left in the
5500Sstevel@tonic-gate 		 * remaining buffer.
5510Sstevel@tonic-gate 		 */
5520Sstevel@tonic-gate 		if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
5530Sstevel@tonic-gate 			*pulLastPartLen = 0;
5540Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
5550Sstevel@tonic-gate 			/* Cleanup memory space. */
5560Sstevel@tonic-gate 			free(soft_des_ctx->des_cbc);
5570Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
5580Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
5590Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
5600Sstevel@tonic-gate 
5610Sstevel@tonic-gate 			goto clean1;
5620Sstevel@tonic-gate 		}
5630Sstevel@tonic-gate 
5640Sstevel@tonic-gate 		out_len = DES_BLOCK_LEN;
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 		/*
5670Sstevel@tonic-gate 		 * If application asks for the length of the output buffer
5680Sstevel@tonic-gate 		 * to hold the plaintext?
5690Sstevel@tonic-gate 		 */
5700Sstevel@tonic-gate 		if (pLastPart == NULL) {
5710Sstevel@tonic-gate 			*pulLastPartLen = out_len;
5720Sstevel@tonic-gate 			rv = CKR_OK;
5730Sstevel@tonic-gate 			goto clean2;
5740Sstevel@tonic-gate 		} else {
5750Sstevel@tonic-gate 			crypto_data_t out;
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 			/* Copy remaining data to the output buffer. */
5780Sstevel@tonic-gate 			(void) memcpy(pLastPart, soft_des_ctx->data,
5790Sstevel@tonic-gate 			    DES_BLOCK_LEN);
5800Sstevel@tonic-gate 
5810Sstevel@tonic-gate 			out.cd_format = CRYPTO_DATA_RAW;
5820Sstevel@tonic-gate 			out.cd_offset = 0;
5830Sstevel@tonic-gate 			out.cd_length = DES_BLOCK_LEN;
5840Sstevel@tonic-gate 			out.cd_raw.iov_base = (char *)pLastPart;
5850Sstevel@tonic-gate 			out.cd_raw.iov_len = DES_BLOCK_LEN;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 			/* Decrypt final block of data. */
5880Sstevel@tonic-gate 			rc = des_decrypt_contiguous_blocks(
5890Sstevel@tonic-gate 			    (des_ctx_t *)soft_des_ctx->des_cbc,
5900Sstevel@tonic-gate 			    (char *)pLastPart, DES_BLOCK_LEN, &out);
5910Sstevel@tonic-gate 
5920Sstevel@tonic-gate 			if (rc == 0) {
5930Sstevel@tonic-gate 				/*
5940Sstevel@tonic-gate 				 * Remove padding bytes after decryption of
5950Sstevel@tonic-gate 				 * ciphertext block to produce the original
5960Sstevel@tonic-gate 				 * plaintext.
5970Sstevel@tonic-gate 				 */
5980Sstevel@tonic-gate 				rv = soft_remove_pkcs7_padding(pLastPart,
599*12573SDina.Nimeh@Sun.COM 				    DES_BLOCK_LEN, &out_len);
6000Sstevel@tonic-gate 				if (rv != CKR_OK)
6010Sstevel@tonic-gate 					*pulLastPartLen = 0;
6020Sstevel@tonic-gate 				else
6030Sstevel@tonic-gate 					*pulLastPartLen = out_len;
6040Sstevel@tonic-gate 			} else {
6050Sstevel@tonic-gate 				*pulLastPartLen = 0;
6060Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
6070Sstevel@tonic-gate 			}
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 			/* Cleanup memory space. */
6100Sstevel@tonic-gate 			free(soft_des_ctx->des_cbc);
6110Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
6120Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
6130Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 		}
6160Sstevel@tonic-gate 
6170Sstevel@tonic-gate 		break;
6180Sstevel@tonic-gate 	}
6190Sstevel@tonic-gate 
6200Sstevel@tonic-gate 	case CKM_DES_CBC:
6210Sstevel@tonic-gate 	case CKM_DES_ECB:
6220Sstevel@tonic-gate 	case CKM_DES3_CBC:
6230Sstevel@tonic-gate 	case CKM_DES3_ECB:
6240Sstevel@tonic-gate 	{
6250Sstevel@tonic-gate 
6260Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
6270Sstevel@tonic-gate 
6280Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
6290Sstevel@tonic-gate 		/*
6300Sstevel@tonic-gate 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
6310Sstevel@tonic-gate 		 * so when the final is called, the remaining buffer
6320Sstevel@tonic-gate 		 * should not contain any more data.
6330Sstevel@tonic-gate 		 */
6340Sstevel@tonic-gate 		*pulLastPartLen = 0;
6350Sstevel@tonic-gate 		if (soft_des_ctx->remain_len != 0) {
6360Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
6370Sstevel@tonic-gate 		} else {
6380Sstevel@tonic-gate 			if (pLastPart == NULL)
6390Sstevel@tonic-gate 				goto clean2;
6400Sstevel@tonic-gate 		}
6410Sstevel@tonic-gate 
6420Sstevel@tonic-gate 		/* Cleanup memory space. */
6430Sstevel@tonic-gate 		free(soft_des_ctx->des_cbc);
6440Sstevel@tonic-gate 		bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
6450Sstevel@tonic-gate 		free(soft_des_ctx->key_sched);
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		break;
6480Sstevel@tonic-gate 	}
6490Sstevel@tonic-gate 
6500Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
6510Sstevel@tonic-gate 	{
6520Sstevel@tonic-gate 
6530Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
6540Sstevel@tonic-gate 
6550Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
6560Sstevel@tonic-gate 
6570Sstevel@tonic-gate 		/*
6580Sstevel@tonic-gate 		 * We should have only one block of data left in the
6590Sstevel@tonic-gate 		 * remaining buffer.
6600Sstevel@tonic-gate 		 */
6610Sstevel@tonic-gate 		if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
6620Sstevel@tonic-gate 			*pulLastPartLen = 0;
6630Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
6640Sstevel@tonic-gate 			/* Cleanup memory space. */
6650Sstevel@tonic-gate 			free(soft_aes_ctx->aes_cbc);
6660Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
6670Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
6680Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
6690Sstevel@tonic-gate 
6700Sstevel@tonic-gate 			goto clean1;
6710Sstevel@tonic-gate 		}
6720Sstevel@tonic-gate 
6730Sstevel@tonic-gate 		out_len = AES_BLOCK_LEN;
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 		/*
6760Sstevel@tonic-gate 		 * If application asks for the length of the output buffer
6770Sstevel@tonic-gate 		 * to hold the plaintext?
6780Sstevel@tonic-gate 		 */
6790Sstevel@tonic-gate 		if (pLastPart == NULL) {
6800Sstevel@tonic-gate 			*pulLastPartLen = out_len;
6810Sstevel@tonic-gate 			rv = CKR_OK;
6820Sstevel@tonic-gate 			goto clean2;
6830Sstevel@tonic-gate 		} else {
6840Sstevel@tonic-gate 			crypto_data_t out;
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 			/* Copy remaining data to the output buffer. */
6870Sstevel@tonic-gate 			(void) memcpy(pLastPart, soft_aes_ctx->data,
6880Sstevel@tonic-gate 			    AES_BLOCK_LEN);
6890Sstevel@tonic-gate 
6900Sstevel@tonic-gate 			out.cd_format = CRYPTO_DATA_RAW;
6910Sstevel@tonic-gate 			out.cd_offset = 0;
6920Sstevel@tonic-gate 			out.cd_length = AES_BLOCK_LEN;
6930Sstevel@tonic-gate 			out.cd_raw.iov_base = (char *)pLastPart;
6940Sstevel@tonic-gate 			out.cd_raw.iov_len = AES_BLOCK_LEN;
6950Sstevel@tonic-gate 
6960Sstevel@tonic-gate 			/* Decrypt final block of data. */
6970Sstevel@tonic-gate 			rc = aes_decrypt_contiguous_blocks(
6980Sstevel@tonic-gate 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
6990Sstevel@tonic-gate 			    (char *)pLastPart, AES_BLOCK_LEN, &out);
7000Sstevel@tonic-gate 
7010Sstevel@tonic-gate 			if (rc == 0) {
7020Sstevel@tonic-gate 				/*
7030Sstevel@tonic-gate 				 * Remove padding bytes after decryption of
7040Sstevel@tonic-gate 				 * ciphertext block to produce the original
7050Sstevel@tonic-gate 				 * plaintext.
7060Sstevel@tonic-gate 				 */
7070Sstevel@tonic-gate 				rv = soft_remove_pkcs7_padding(pLastPart,
708*12573SDina.Nimeh@Sun.COM 				    AES_BLOCK_LEN, &out_len);
7090Sstevel@tonic-gate 				if (rv != CKR_OK)
7100Sstevel@tonic-gate 					*pulLastPartLen = 0;
7110Sstevel@tonic-gate 				else
7120Sstevel@tonic-gate 					*pulLastPartLen = out_len;
7130Sstevel@tonic-gate 			} else {
7140Sstevel@tonic-gate 				*pulLastPartLen = 0;
7150Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
7160Sstevel@tonic-gate 			}
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 			/* Cleanup memory space. */
7190Sstevel@tonic-gate 			free(soft_aes_ctx->aes_cbc);
7200Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
7210Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
7220Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
7230Sstevel@tonic-gate 
7240Sstevel@tonic-gate 		}
7250Sstevel@tonic-gate 
7260Sstevel@tonic-gate 		break;
7270Sstevel@tonic-gate 	}
7280Sstevel@tonic-gate 
7290Sstevel@tonic-gate 	case CKM_AES_CBC:
7300Sstevel@tonic-gate 	case CKM_AES_ECB:
7310Sstevel@tonic-gate 	{
7320Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
7330Sstevel@tonic-gate 
7340Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
7350Sstevel@tonic-gate 		/*
7360Sstevel@tonic-gate 		 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
7370Sstevel@tonic-gate 		 * so when the final is called, the remaining buffer
7380Sstevel@tonic-gate 		 * should not contain any more data.
7390Sstevel@tonic-gate 		 */
7400Sstevel@tonic-gate 		*pulLastPartLen = 0;
7410Sstevel@tonic-gate 		if (soft_aes_ctx->remain_len != 0) {
7420Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
7430Sstevel@tonic-gate 		} else {
7440Sstevel@tonic-gate 			if (pLastPart == NULL)
7450Sstevel@tonic-gate 				goto clean2;
7460Sstevel@tonic-gate 		}
7470Sstevel@tonic-gate 
7480Sstevel@tonic-gate 		/* Cleanup memory space. */
7490Sstevel@tonic-gate 		free(soft_aes_ctx->aes_cbc);
7500Sstevel@tonic-gate 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
7510Sstevel@tonic-gate 		free(soft_aes_ctx->key_sched);
7520Sstevel@tonic-gate 
7530Sstevel@tonic-gate 		break;
7540Sstevel@tonic-gate 	}
7557188Smcpowers 	case CKM_AES_CTR:
7567188Smcpowers 	{
7577188Smcpowers 		crypto_data_t out;
7587188Smcpowers 		soft_aes_ctx_t *soft_aes_ctx;
7597188Smcpowers 		ctr_ctx_t *ctr_ctx;
7607188Smcpowers 		size_t len;
7610Sstevel@tonic-gate 
7627188Smcpowers 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
7637188Smcpowers 		ctr_ctx = soft_aes_ctx->aes_cbc;
7647188Smcpowers 		len = ctr_ctx->ctr_remainder_len;
7657188Smcpowers 		if (pLastPart == NULL) {
7667188Smcpowers 			*pulLastPartLen = len;
7677188Smcpowers 			goto clean1;
7687188Smcpowers 		}
7697188Smcpowers 		if (len > 0) {
7707188Smcpowers 			out.cd_format = CRYPTO_DATA_RAW;
7717188Smcpowers 			out.cd_offset = 0;
7727188Smcpowers 			out.cd_length = len;
7737188Smcpowers 			out.cd_raw.iov_base = (char *)pLastPart;
7747188Smcpowers 			out.cd_raw.iov_len = len;
7757188Smcpowers 
7767188Smcpowers 			rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
7777188Smcpowers 			if (rv == CRYPTO_DATA_LEN_RANGE)
7787188Smcpowers 				rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
7797188Smcpowers 		}
7807188Smcpowers 		if (rv == CRYPTO_BUFFER_TOO_SMALL) {
7817188Smcpowers 			*pulLastPartLen = len;
7827188Smcpowers 			goto clean1;
7837188Smcpowers 		}
7847188Smcpowers 
7857188Smcpowers 		/* Cleanup memory space. */
7867188Smcpowers 		free(ctr_ctx);
7877188Smcpowers 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
7887188Smcpowers 		free(soft_aes_ctx->key_sched);
7897188Smcpowers 
7907188Smcpowers 		break;
7917188Smcpowers 	}
792676Sizick 	case CKM_BLOWFISH_CBC:
793676Sizick 	{
794676Sizick 		soft_blowfish_ctx_t *soft_blowfish_ctx;
795676Sizick 
796676Sizick 		soft_blowfish_ctx =
797676Sizick 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
798676Sizick 
799676Sizick 		*pulLastPartLen = 0;
800676Sizick 		if (soft_blowfish_ctx->remain_len != 0)
801676Sizick 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
802676Sizick 		else {
803676Sizick 			if (pLastPart == NULL)
804676Sizick 				goto clean2;
805676Sizick 		}
806676Sizick 
807676Sizick 		free(soft_blowfish_ctx->blowfish_cbc);
808676Sizick 		bzero(soft_blowfish_ctx->key_sched,
809676Sizick 		    soft_blowfish_ctx->keysched_len);
810676Sizick 		free(soft_blowfish_ctx->key_sched);
811676Sizick 
812676Sizick 		break;
813676Sizick 	}
814676Sizick 
8150Sstevel@tonic-gate 	case CKM_RC4:
8160Sstevel@tonic-gate 	{
8170Sstevel@tonic-gate 		ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
8180Sstevel@tonic-gate 		bzero(key, sizeof (*key));
8190Sstevel@tonic-gate 		*pulLastPartLen = 0;
8200Sstevel@tonic-gate 		break;
8210Sstevel@tonic-gate 	}
8220Sstevel@tonic-gate 
8230Sstevel@tonic-gate 	default:
8240Sstevel@tonic-gate 		/* PKCS11: The mechanism only supports single-part operation. */
8250Sstevel@tonic-gate 		rv = CKR_MECHANISM_INVALID;
8260Sstevel@tonic-gate 		break;
8270Sstevel@tonic-gate 	}
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate clean1:
8300Sstevel@tonic-gate 	free(session_p->decrypt.context);
8310Sstevel@tonic-gate 	session_p->decrypt.context = NULL;
8320Sstevel@tonic-gate 
8330Sstevel@tonic-gate clean2:
8340Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
8350Sstevel@tonic-gate 
8360Sstevel@tonic-gate 	return (rv);
8370Sstevel@tonic-gate 
8380Sstevel@tonic-gate }
839