xref: /titanic_41/usr/src/lib/pkcs11/pkcs11_softtoken/common/softDecryptUtil.c (revision 726fad2a65f16c200a03969c29cb5c86c2d427db)
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
547c883c7Sdinak  * Common Development and Distribution License (the "License").
647c883c7Sdinak  * 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  */
217c478bd9Sstevel@tonic-gate 
22*726fad2aSDina K Nimeh /*
23*726fad2aSDina K Nimeh  * Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
24*726fad2aSDina K Nimeh  */
257c478bd9Sstevel@tonic-gate 
267c478bd9Sstevel@tonic-gate #include <pthread.h>
277c478bd9Sstevel@tonic-gate #include <stdlib.h>
287c478bd9Sstevel@tonic-gate #include <string.h>
297c478bd9Sstevel@tonic-gate #include <strings.h>
307c478bd9Sstevel@tonic-gate #include <sys/types.h>
317c478bd9Sstevel@tonic-gate #include <security/cryptoki.h>
3223c57df7Smcpowers #include <modes/modes.h>
337c478bd9Sstevel@tonic-gate #include <arcfour.h>
347c478bd9Sstevel@tonic-gate #include "softSession.h"
357c478bd9Sstevel@tonic-gate #include "softObject.h"
367c478bd9Sstevel@tonic-gate #include "softOps.h"
377c478bd9Sstevel@tonic-gate #include "softCrypt.h"
387c478bd9Sstevel@tonic-gate #include "softRSA.h"
397c478bd9Sstevel@tonic-gate 
407c478bd9Sstevel@tonic-gate /*
417c478bd9Sstevel@tonic-gate  * Remove padding bytes.
427c478bd9Sstevel@tonic-gate  */
437c478bd9Sstevel@tonic-gate CK_RV
soft_remove_pkcs7_padding(CK_BYTE * pData,CK_ULONG padded_len,CK_ULONG * pulDataLen)447c478bd9Sstevel@tonic-gate soft_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
45*726fad2aSDina K Nimeh     CK_ULONG *pulDataLen)
467c478bd9Sstevel@tonic-gate {
47*726fad2aSDina K Nimeh 	CK_RV	rv;
487c478bd9Sstevel@tonic-gate 
49*726fad2aSDina K Nimeh #ifdef	__sparcv9
50*726fad2aSDina K Nimeh 	if ((rv = pkcs7_decode(pData, (&padded_len))) != CKR_OK)
51*726fad2aSDina K Nimeh #else	/* !__sparcv9 */
52*726fad2aSDina K Nimeh 	if ((rv = pkcs7_decode(pData, (size_t *)(&padded_len))) != CKR_OK)
53*726fad2aSDina K Nimeh #endif	/* __sparcv9 */
54*726fad2aSDina K Nimeh 		return (rv);
557c478bd9Sstevel@tonic-gate 
56*726fad2aSDina K Nimeh 	*pulDataLen = padded_len;
577c478bd9Sstevel@tonic-gate 	return (CKR_OK);
587c478bd9Sstevel@tonic-gate }
597c478bd9Sstevel@tonic-gate 
607c478bd9Sstevel@tonic-gate 
617c478bd9Sstevel@tonic-gate /*
627c478bd9Sstevel@tonic-gate  * soft_decrypt_init()
637c478bd9Sstevel@tonic-gate  *
647c478bd9Sstevel@tonic-gate  * Arguments:
657c478bd9Sstevel@tonic-gate  *	session_p:	pointer to soft_session_t struct
667c478bd9Sstevel@tonic-gate  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
677c478bd9Sstevel@tonic-gate  *	key_p:		pointer to key soft_object_t struct
687c478bd9Sstevel@tonic-gate  *
697c478bd9Sstevel@tonic-gate  * Description:
707c478bd9Sstevel@tonic-gate  *	called by C_DecryptInit(). This function calls the corresponding
717c478bd9Sstevel@tonic-gate  *	decrypt init routine based on the mechanism.
727c478bd9Sstevel@tonic-gate  *
737c478bd9Sstevel@tonic-gate  * Returns:
747c478bd9Sstevel@tonic-gate  *	CKR_OK: success
757c478bd9Sstevel@tonic-gate  *	CKR_HOST_MEMORY: run out of system memory
767c478bd9Sstevel@tonic-gate  *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
777c478bd9Sstevel@tonic-gate  *	CKR_MECHANISM_INVALID: invalid mechanism type
787c478bd9Sstevel@tonic-gate  *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
797c478bd9Sstevel@tonic-gate  *				   with the specified mechanism
807c478bd9Sstevel@tonic-gate  */
817c478bd9Sstevel@tonic-gate CK_RV
soft_decrypt_init(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p)827c478bd9Sstevel@tonic-gate soft_decrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
837c478bd9Sstevel@tonic-gate     soft_object_t *key_p)
847c478bd9Sstevel@tonic-gate {
857c478bd9Sstevel@tonic-gate 
867c478bd9Sstevel@tonic-gate 	CK_RV rv;
877c478bd9Sstevel@tonic-gate 
887c478bd9Sstevel@tonic-gate 	switch (pMechanism->mechanism) {
897c478bd9Sstevel@tonic-gate 
907c478bd9Sstevel@tonic-gate 	case CKM_DES_ECB:
917c478bd9Sstevel@tonic-gate 
927c478bd9Sstevel@tonic-gate 		if (key_p->key_type != CKK_DES) {
937c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
947c478bd9Sstevel@tonic-gate 		}
957c478bd9Sstevel@tonic-gate 
967c478bd9Sstevel@tonic-gate 		goto ecb_common;
977c478bd9Sstevel@tonic-gate 
987c478bd9Sstevel@tonic-gate 	case CKM_DES3_ECB:
997c478bd9Sstevel@tonic-gate 
1007c478bd9Sstevel@tonic-gate 		if ((key_p->key_type != CKK_DES2) &&
1017c478bd9Sstevel@tonic-gate 		    (key_p->key_type != CKK_DES3)) {
1027c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1037c478bd9Sstevel@tonic-gate 		}
1047c478bd9Sstevel@tonic-gate 
1057c478bd9Sstevel@tonic-gate ecb_common:
1067c478bd9Sstevel@tonic-gate 
1077c478bd9Sstevel@tonic-gate 		return (soft_des_crypt_init_common(session_p, pMechanism,
1087c478bd9Sstevel@tonic-gate 		    key_p, B_FALSE));
1097c478bd9Sstevel@tonic-gate 
1107c478bd9Sstevel@tonic-gate 	case CKM_DES_CBC:
1117c478bd9Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
1127c478bd9Sstevel@tonic-gate 
1137c478bd9Sstevel@tonic-gate 		if (key_p->key_type != CKK_DES) {
1147c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1157c478bd9Sstevel@tonic-gate 		}
1167c478bd9Sstevel@tonic-gate 
1177c478bd9Sstevel@tonic-gate 		goto cbc_common;
1187c478bd9Sstevel@tonic-gate 
1197c478bd9Sstevel@tonic-gate 	case CKM_DES3_CBC:
1207c478bd9Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
1217c478bd9Sstevel@tonic-gate 	{
1227c478bd9Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
1237c478bd9Sstevel@tonic-gate 
1247c478bd9Sstevel@tonic-gate 		if ((key_p->key_type != CKK_DES2) &&
1257c478bd9Sstevel@tonic-gate 		    (key_p->key_type != CKK_DES3)) {
1267c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1277c478bd9Sstevel@tonic-gate 		}
1287c478bd9Sstevel@tonic-gate 
1297c478bd9Sstevel@tonic-gate cbc_common:
1307c478bd9Sstevel@tonic-gate 		if ((pMechanism->pParameter == NULL) ||
1317c478bd9Sstevel@tonic-gate 		    (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
1327c478bd9Sstevel@tonic-gate 			return (CKR_MECHANISM_PARAM_INVALID);
1337c478bd9Sstevel@tonic-gate 		}
1347c478bd9Sstevel@tonic-gate 
1357c478bd9Sstevel@tonic-gate 		rv = soft_des_crypt_init_common(session_p, pMechanism,
1367c478bd9Sstevel@tonic-gate 		    key_p, B_FALSE);
1377c478bd9Sstevel@tonic-gate 
1387c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
1397c478bd9Sstevel@tonic-gate 			return (rv);
1407c478bd9Sstevel@tonic-gate 
1417c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
1427c478bd9Sstevel@tonic-gate 
1437c478bd9Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
1447c478bd9Sstevel@tonic-gate 		/* Save Initialization Vector (IV) in the context. */
1457c478bd9Sstevel@tonic-gate 		(void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
1467c478bd9Sstevel@tonic-gate 		    DES_BLOCK_LEN);
1477c478bd9Sstevel@tonic-gate 
1487c478bd9Sstevel@tonic-gate 		/* Allocate a context for DES cipher-block chaining. */
1497c478bd9Sstevel@tonic-gate 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
1507c478bd9Sstevel@tonic-gate 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
1517c478bd9Sstevel@tonic-gate 		    soft_des_ctx->ivec, key_p->key_type);
1527c478bd9Sstevel@tonic-gate 
1537c478bd9Sstevel@tonic-gate 		if (soft_des_ctx->des_cbc == NULL) {
1547c478bd9Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
1557c478bd9Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
1567c478bd9Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
1577c478bd9Sstevel@tonic-gate 			free(session_p->decrypt.context);
1587c478bd9Sstevel@tonic-gate 			session_p->decrypt.context = NULL;
1597c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&session_p->session_mutex);
1607c478bd9Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
1617c478bd9Sstevel@tonic-gate 		}
1627c478bd9Sstevel@tonic-gate 
1637c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
1647c478bd9Sstevel@tonic-gate 
1657c478bd9Sstevel@tonic-gate 		return (rv);
1667c478bd9Sstevel@tonic-gate 	}
1677c478bd9Sstevel@tonic-gate 	case CKM_AES_ECB:
1687c478bd9Sstevel@tonic-gate 
1697c478bd9Sstevel@tonic-gate 		if (key_p->key_type != CKK_AES) {
1707c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1717c478bd9Sstevel@tonic-gate 		}
1727c478bd9Sstevel@tonic-gate 
1737c478bd9Sstevel@tonic-gate 		return (soft_aes_crypt_init_common(session_p, pMechanism,
1747c478bd9Sstevel@tonic-gate 		    key_p, B_FALSE));
1757c478bd9Sstevel@tonic-gate 
1767c478bd9Sstevel@tonic-gate 	case CKM_AES_CBC:
1777c478bd9Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
1787c478bd9Sstevel@tonic-gate 	{
1797c478bd9Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
1807c478bd9Sstevel@tonic-gate 
1817c478bd9Sstevel@tonic-gate 		if (key_p->key_type != CKK_AES) {
1827c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1837c478bd9Sstevel@tonic-gate 		}
1847c478bd9Sstevel@tonic-gate 
1857c478bd9Sstevel@tonic-gate 		if ((pMechanism->pParameter == NULL) ||
1867c478bd9Sstevel@tonic-gate 		    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
1877c478bd9Sstevel@tonic-gate 			return (CKR_MECHANISM_PARAM_INVALID);
1887c478bd9Sstevel@tonic-gate 		}
1897c478bd9Sstevel@tonic-gate 
1907c478bd9Sstevel@tonic-gate 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
1917c478bd9Sstevel@tonic-gate 		    key_p, B_FALSE);
1927c478bd9Sstevel@tonic-gate 
1937c478bd9Sstevel@tonic-gate 		if (rv != CKR_OK)
1947c478bd9Sstevel@tonic-gate 			return (rv);
1957c478bd9Sstevel@tonic-gate 
1967c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
1977c478bd9Sstevel@tonic-gate 
1987c478bd9Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
1997c478bd9Sstevel@tonic-gate 
2007c478bd9Sstevel@tonic-gate 		/* Save Initialization Vector (IV) in the context. */
2017c478bd9Sstevel@tonic-gate 		(void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
2027c478bd9Sstevel@tonic-gate 		    AES_BLOCK_LEN);
2037c478bd9Sstevel@tonic-gate 
2047c478bd9Sstevel@tonic-gate 		/* Allocate a context for AES cipher-block chaining. */
2057c478bd9Sstevel@tonic-gate 		soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
2067c478bd9Sstevel@tonic-gate 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
2077c478bd9Sstevel@tonic-gate 		    soft_aes_ctx->ivec);
2087c478bd9Sstevel@tonic-gate 
2097c478bd9Sstevel@tonic-gate 		if (soft_aes_ctx->aes_cbc == NULL) {
2107c478bd9Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
2117c478bd9Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
2127c478bd9Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
2137c478bd9Sstevel@tonic-gate 			free(session_p->decrypt.context);
2147c478bd9Sstevel@tonic-gate 			session_p->decrypt.context = NULL;
2157c478bd9Sstevel@tonic-gate 			(void) pthread_mutex_unlock(&session_p->session_mutex);
2167c478bd9Sstevel@tonic-gate 			return (CKR_HOST_MEMORY);
2177c478bd9Sstevel@tonic-gate 		}
2187c478bd9Sstevel@tonic-gate 
2197c478bd9Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
2207c478bd9Sstevel@tonic-gate 
2217c478bd9Sstevel@tonic-gate 		return (rv);
2227c478bd9Sstevel@tonic-gate 	}
22323c57df7Smcpowers 	case CKM_AES_CTR:
22423c57df7Smcpowers 	{
22523c57df7Smcpowers 		soft_aes_ctx_t *soft_aes_ctx;
2267c478bd9Sstevel@tonic-gate 
22723c57df7Smcpowers 		if (key_p->key_type != CKK_AES) {
22823c57df7Smcpowers 			return (CKR_KEY_TYPE_INCONSISTENT);
22923c57df7Smcpowers 		}
23023c57df7Smcpowers 
23123c57df7Smcpowers 		if (pMechanism->pParameter == NULL ||
23223c57df7Smcpowers 		    pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
23323c57df7Smcpowers 			return (CKR_MECHANISM_PARAM_INVALID);
23423c57df7Smcpowers 		}
23523c57df7Smcpowers 
23623c57df7Smcpowers 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
23723c57df7Smcpowers 		    key_p, B_FALSE);
23823c57df7Smcpowers 
23923c57df7Smcpowers 		if (rv != CKR_OK)
24023c57df7Smcpowers 			return (rv);
24123c57df7Smcpowers 
24223c57df7Smcpowers 		(void) pthread_mutex_lock(&session_p->session_mutex);
24323c57df7Smcpowers 
24423c57df7Smcpowers 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
24523c57df7Smcpowers 		soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
24623c57df7Smcpowers 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
24723c57df7Smcpowers 		    pMechanism->pParameter);
24823c57df7Smcpowers 
24923c57df7Smcpowers 		if (soft_aes_ctx->aes_cbc == NULL) {
25023c57df7Smcpowers 			bzero(soft_aes_ctx->key_sched,
25123c57df7Smcpowers 			    soft_aes_ctx->keysched_len);
25223c57df7Smcpowers 			free(soft_aes_ctx->key_sched);
25323c57df7Smcpowers 			free(session_p->decrypt.context);
25423c57df7Smcpowers 			session_p->decrypt.context = NULL;
25523c57df7Smcpowers 			rv = CKR_HOST_MEMORY;
25623c57df7Smcpowers 		}
25723c57df7Smcpowers 
25823c57df7Smcpowers 		(void) pthread_mutex_unlock(&session_p->session_mutex);
25923c57df7Smcpowers 
26023c57df7Smcpowers 		return (rv);
26123c57df7Smcpowers 	}
262f66d273dSizick 	case CKM_BLOWFISH_CBC:
263f66d273dSizick 	{
264f66d273dSizick 		soft_blowfish_ctx_t *soft_blowfish_ctx;
265f66d273dSizick 
266f66d273dSizick 		if (key_p->key_type != CKK_BLOWFISH)
267f66d273dSizick 			return (CKR_KEY_TYPE_INCONSISTENT);
268f66d273dSizick 
269f66d273dSizick 		if ((pMechanism->pParameter == NULL) ||
270f66d273dSizick 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
271f66d273dSizick 			return (CKR_MECHANISM_PARAM_INVALID);
272f66d273dSizick 
273f66d273dSizick 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
274f66d273dSizick 		    key_p, B_FALSE);
275f66d273dSizick 
276f66d273dSizick 		if (rv != CKR_OK)
277f66d273dSizick 			return (rv);
278f66d273dSizick 
279f66d273dSizick 		(void) pthread_mutex_lock(&session_p->session_mutex);
280f66d273dSizick 
281f66d273dSizick 		soft_blowfish_ctx =
282f66d273dSizick 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
283f66d273dSizick 
284f66d273dSizick 		/* Save Initialization Vector in the context. */
285f66d273dSizick 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
286f66d273dSizick 		    BLOWFISH_BLOCK_LEN);
287f66d273dSizick 
288f66d273dSizick 		/* Allocate a context for CBC */
289f66d273dSizick 		soft_blowfish_ctx->blowfish_cbc =
290f66d273dSizick 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
291f66d273dSizick 		    soft_blowfish_ctx->keysched_len,
292f66d273dSizick 		    soft_blowfish_ctx->ivec);
293f66d273dSizick 
294f66d273dSizick 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
295f66d273dSizick 			bzero(soft_blowfish_ctx->key_sched,
296f66d273dSizick 			    soft_blowfish_ctx->keysched_len);
297f66d273dSizick 			free(soft_blowfish_ctx->key_sched);
298f66d273dSizick 			free(session_p->decrypt.context = NULL);
299f66d273dSizick 			(void) pthread_mutex_unlock(&session_p->session_mutex);
300f66d273dSizick 			return (CKR_HOST_MEMORY);
301f66d273dSizick 		}
302f66d273dSizick 
303f66d273dSizick 		(void) pthread_mutex_unlock(&session_p->session_mutex);
304f66d273dSizick 		return (rv);
305f66d273dSizick 	}
306f66d273dSizick 
3077c478bd9Sstevel@tonic-gate 	case CKM_RC4:
3087c478bd9Sstevel@tonic-gate 
3097c478bd9Sstevel@tonic-gate 		if (key_p->key_type != CKK_RC4) {
3107c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
3117c478bd9Sstevel@tonic-gate 		}
3127c478bd9Sstevel@tonic-gate 
3137c478bd9Sstevel@tonic-gate 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
3147c478bd9Sstevel@tonic-gate 		    B_FALSE));
3157c478bd9Sstevel@tonic-gate 
3167c478bd9Sstevel@tonic-gate 	case CKM_RSA_X_509:
3177c478bd9Sstevel@tonic-gate 	case CKM_RSA_PKCS:
3187c478bd9Sstevel@tonic-gate 
3197c478bd9Sstevel@tonic-gate 		if (key_p->key_type != CKK_RSA) {
3207c478bd9Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
3217c478bd9Sstevel@tonic-gate 		}
3227c478bd9Sstevel@tonic-gate 
3237c478bd9Sstevel@tonic-gate 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
3247c478bd9Sstevel@tonic-gate 		    key_p, B_FALSE));
3257c478bd9Sstevel@tonic-gate 
3267c478bd9Sstevel@tonic-gate 	default:
3277c478bd9Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
3287c478bd9Sstevel@tonic-gate 	}
3297c478bd9Sstevel@tonic-gate }
3307c478bd9Sstevel@tonic-gate 
3317c478bd9Sstevel@tonic-gate 
3327c478bd9Sstevel@tonic-gate /*
3337c478bd9Sstevel@tonic-gate  * soft_decrypt_common()
3347c478bd9Sstevel@tonic-gate  *
3357c478bd9Sstevel@tonic-gate  * Arguments:
3367c478bd9Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
3377c478bd9Sstevel@tonic-gate  *	pEncrypted:	pointer to the encrypted data as input
3387c478bd9Sstevel@tonic-gate  *	ulEncryptedLen:	length of the input data
3397c478bd9Sstevel@tonic-gate  *	pData:		pointer to the output data contains plaintext
3407c478bd9Sstevel@tonic-gate  *	pulDataLen:	pointer to the length of the output data
3417c478bd9Sstevel@tonic-gate  *	Update:		boolean flag indicates caller is soft_decrypt
3427c478bd9Sstevel@tonic-gate  *			or soft_decrypt_update
3437c478bd9Sstevel@tonic-gate  *
3447c478bd9Sstevel@tonic-gate  * Description:
3457c478bd9Sstevel@tonic-gate  *      This function calls the corresponding decrypt routine based
3467c478bd9Sstevel@tonic-gate  *	on the mechanism.
3477c478bd9Sstevel@tonic-gate  *
3487c478bd9Sstevel@tonic-gate  * Returns:
3497c478bd9Sstevel@tonic-gate  *	see soft_decrypt_common().
3507c478bd9Sstevel@tonic-gate  */
3517c478bd9Sstevel@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)3527c478bd9Sstevel@tonic-gate soft_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
3537c478bd9Sstevel@tonic-gate     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
3547c478bd9Sstevel@tonic-gate     CK_ULONG_PTR pulDataLen, boolean_t Update)
3557c478bd9Sstevel@tonic-gate {
3567c478bd9Sstevel@tonic-gate 
3577c478bd9Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
3587c478bd9Sstevel@tonic-gate 
3597c478bd9Sstevel@tonic-gate 	switch (mechanism) {
3607c478bd9Sstevel@tonic-gate 
3617c478bd9Sstevel@tonic-gate 	case CKM_DES_ECB:
3627c478bd9Sstevel@tonic-gate 	case CKM_DES_CBC:
3637c478bd9Sstevel@tonic-gate 	case CKM_DES3_ECB:
3647c478bd9Sstevel@tonic-gate 	case CKM_DES3_CBC:
36547c883c7Sdinak 
36647c883c7Sdinak 		if (ulEncryptedLen == 0) {
36747c883c7Sdinak 			*pulDataLen = 0;
36847c883c7Sdinak 			return (CKR_OK);
36947c883c7Sdinak 		}
37047c883c7Sdinak 		/* FALLTHROUGH */
37147c883c7Sdinak 
37247c883c7Sdinak 	case CKM_DES_CBC_PAD:
3737c478bd9Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
3747c478bd9Sstevel@tonic-gate 
3757c478bd9Sstevel@tonic-gate 		return (soft_des_decrypt_common(session_p, pEncrypted,
3767c478bd9Sstevel@tonic-gate 		    ulEncryptedLen, pData, pulDataLen, Update));
3777c478bd9Sstevel@tonic-gate 
3787c478bd9Sstevel@tonic-gate 	case CKM_AES_ECB:
3797c478bd9Sstevel@tonic-gate 	case CKM_AES_CBC:
38023c57df7Smcpowers 	case CKM_AES_CTR:
38147c883c7Sdinak 
38247c883c7Sdinak 		if (ulEncryptedLen == 0) {
38347c883c7Sdinak 			*pulDataLen = 0;
38447c883c7Sdinak 			return (CKR_OK);
38547c883c7Sdinak 		}
38647c883c7Sdinak 		/* FALLTHROUGH */
38747c883c7Sdinak 
3887c478bd9Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
3897c478bd9Sstevel@tonic-gate 
3907c478bd9Sstevel@tonic-gate 		return (soft_aes_decrypt_common(session_p, pEncrypted,
3917c478bd9Sstevel@tonic-gate 		    ulEncryptedLen, pData, pulDataLen, Update));
3927c478bd9Sstevel@tonic-gate 
393f66d273dSizick 	case CKM_BLOWFISH_CBC:
394f66d273dSizick 
39547c883c7Sdinak 		if (ulEncryptedLen == 0) {
39647c883c7Sdinak 			*pulDataLen = 0;
39747c883c7Sdinak 			return (CKR_OK);
39847c883c7Sdinak 		}
39947c883c7Sdinak 
400f66d273dSizick 		return (soft_blowfish_decrypt_common(session_p, pEncrypted,
401f66d273dSizick 		    ulEncryptedLen, pData, pulDataLen, Update));
402f66d273dSizick 
4037c478bd9Sstevel@tonic-gate 	case CKM_RC4:
4047c478bd9Sstevel@tonic-gate 
40547c883c7Sdinak 		if (ulEncryptedLen == 0) {
40647c883c7Sdinak 			*pulDataLen = 0;
40747c883c7Sdinak 			return (CKR_OK);
40847c883c7Sdinak 		}
4097c478bd9Sstevel@tonic-gate 
41047c883c7Sdinak 
41147c883c7Sdinak 		return (soft_arcfour_crypt(&(session_p->decrypt), pEncrypted,
41247c883c7Sdinak 		    ulEncryptedLen, pData, pulDataLen));
4137c478bd9Sstevel@tonic-gate 
4147c478bd9Sstevel@tonic-gate 	case CKM_RSA_X_509:
4157c478bd9Sstevel@tonic-gate 	case CKM_RSA_PKCS:
4167c478bd9Sstevel@tonic-gate 
4177c478bd9Sstevel@tonic-gate 		return (soft_rsa_decrypt_common(session_p, pEncrypted,
4187c478bd9Sstevel@tonic-gate 		    ulEncryptedLen, pData, pulDataLen, mechanism));
4197c478bd9Sstevel@tonic-gate 
4207c478bd9Sstevel@tonic-gate 	default:
4217c478bd9Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
4227c478bd9Sstevel@tonic-gate 
4237c478bd9Sstevel@tonic-gate 	}
4247c478bd9Sstevel@tonic-gate }
4257c478bd9Sstevel@tonic-gate 
4267c478bd9Sstevel@tonic-gate 
4277c478bd9Sstevel@tonic-gate /*
4287c478bd9Sstevel@tonic-gate  * soft_decrypt()
4297c478bd9Sstevel@tonic-gate  *
4307c478bd9Sstevel@tonic-gate  * Arguments:
4317c478bd9Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
4327c478bd9Sstevel@tonic-gate  *	pEncryptedData: pointer to the encrypted data as input
4337c478bd9Sstevel@tonic-gate  *	ulEncryptedDataLen: length of the input data
4347c478bd9Sstevel@tonic-gate  *	pData:		pointer to the output data contains plaintext
4357c478bd9Sstevel@tonic-gate  *	pulDataLen:	pointer to the length of the output data
4367c478bd9Sstevel@tonic-gate  *
4377c478bd9Sstevel@tonic-gate  * Description:
4387c478bd9Sstevel@tonic-gate  *      called by C_Decrypt(). This function calls the soft_decrypt_common
4397c478bd9Sstevel@tonic-gate  *	routine.
4407c478bd9Sstevel@tonic-gate  *
4417c478bd9Sstevel@tonic-gate  * Returns:
4427c478bd9Sstevel@tonic-gate  *	see soft_decrypt_common().
4437c478bd9Sstevel@tonic-gate  */
4447c478bd9Sstevel@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)4457c478bd9Sstevel@tonic-gate soft_decrypt(soft_session_t *session_p, CK_BYTE_PTR pEncryptedData,
4467c478bd9Sstevel@tonic-gate     CK_ULONG ulEncryptedDataLen, CK_BYTE_PTR pData,
4477c478bd9Sstevel@tonic-gate     CK_ULONG_PTR pulDataLen)
4487c478bd9Sstevel@tonic-gate {
4497c478bd9Sstevel@tonic-gate 
4507c478bd9Sstevel@tonic-gate 	return (soft_decrypt_common(session_p, pEncryptedData,
4517c478bd9Sstevel@tonic-gate 	    ulEncryptedDataLen, pData, pulDataLen, B_FALSE));
4527c478bd9Sstevel@tonic-gate }
4537c478bd9Sstevel@tonic-gate 
4547c478bd9Sstevel@tonic-gate 
4557c478bd9Sstevel@tonic-gate /*
4567c478bd9Sstevel@tonic-gate  * soft_decrypt_update()
4577c478bd9Sstevel@tonic-gate  *
4587c478bd9Sstevel@tonic-gate  * Arguments:
4597c478bd9Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
4607c478bd9Sstevel@tonic-gate  *	pEncryptedPart: pointer to the encrypted data as input
4617c478bd9Sstevel@tonic-gate  *	ulEncryptedPartLen: length of the input data
4627c478bd9Sstevel@tonic-gate  *	pPart:          pointer to the output data contains plaintext
4637c478bd9Sstevel@tonic-gate  *	pulPartLen:     pointer to the length of the output data
4647c478bd9Sstevel@tonic-gate  *
4657c478bd9Sstevel@tonic-gate  * Description:
4667c478bd9Sstevel@tonic-gate  *      called by C_DecryptUpdate(). This function calls the
4677c478bd9Sstevel@tonic-gate  *	soft_decrypt_common routine (with update flag on).
4687c478bd9Sstevel@tonic-gate  *
4697c478bd9Sstevel@tonic-gate  * Returns:
4707c478bd9Sstevel@tonic-gate  *	see soft_decrypt_common().
4717c478bd9Sstevel@tonic-gate  */
4727c478bd9Sstevel@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)4737c478bd9Sstevel@tonic-gate soft_decrypt_update(soft_session_t *session_p, CK_BYTE_PTR pEncryptedPart,
4747c478bd9Sstevel@tonic-gate 	CK_ULONG ulEncryptedPartLen, CK_BYTE_PTR pPart,
4757c478bd9Sstevel@tonic-gate 	CK_ULONG_PTR pulPartLen)
4767c478bd9Sstevel@tonic-gate {
4777c478bd9Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
4787c478bd9Sstevel@tonic-gate 
4797c478bd9Sstevel@tonic-gate 	switch (mechanism) {
4807c478bd9Sstevel@tonic-gate 
4817c478bd9Sstevel@tonic-gate 	case CKM_DES_ECB:
4827c478bd9Sstevel@tonic-gate 	case CKM_DES_CBC:
4837c478bd9Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
4847c478bd9Sstevel@tonic-gate 	case CKM_DES3_ECB:
4857c478bd9Sstevel@tonic-gate 	case CKM_DES3_CBC:
4867c478bd9Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
4877c478bd9Sstevel@tonic-gate 	case CKM_AES_ECB:
4887c478bd9Sstevel@tonic-gate 	case CKM_AES_CBC:
4897c478bd9Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
49023c57df7Smcpowers 	case CKM_AES_CTR:
491f66d273dSizick 	case CKM_BLOWFISH_CBC:
49247c883c7Sdinak 	case CKM_RC4:
4937c478bd9Sstevel@tonic-gate 
4947c478bd9Sstevel@tonic-gate 		return (soft_decrypt_common(session_p, pEncryptedPart,
4957c478bd9Sstevel@tonic-gate 		    ulEncryptedPartLen, pPart, pulPartLen, B_TRUE));
4967c478bd9Sstevel@tonic-gate 
4977c478bd9Sstevel@tonic-gate 	default:
4987c478bd9Sstevel@tonic-gate 		/* PKCS11: The mechanism only supports single-part operation. */
4997c478bd9Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
5007c478bd9Sstevel@tonic-gate 	}
5017c478bd9Sstevel@tonic-gate 
5027c478bd9Sstevel@tonic-gate }
5037c478bd9Sstevel@tonic-gate 
5047c478bd9Sstevel@tonic-gate 
5057c478bd9Sstevel@tonic-gate /*
5067c478bd9Sstevel@tonic-gate  * soft_decrypt_final()
5077c478bd9Sstevel@tonic-gate  *
5087c478bd9Sstevel@tonic-gate  * Arguments:
5097c478bd9Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
5107c478bd9Sstevel@tonic-gate  *      pLastPart:	pointer to the last recovered data part
5117c478bd9Sstevel@tonic-gate  *      pulLastPartLen:	pointer to the length of the last recovered data part
5127c478bd9Sstevel@tonic-gate  *
5137c478bd9Sstevel@tonic-gate  * Description:
5147c478bd9Sstevel@tonic-gate  *      called by C_DecryptFinal().
5157c478bd9Sstevel@tonic-gate  *
5167c478bd9Sstevel@tonic-gate  * Returns:
5177c478bd9Sstevel@tonic-gate  *	CKR_OK: success
5187c478bd9Sstevel@tonic-gate  *	CKR_FUNCTION_FAILED: decrypt final function failed
5197c478bd9Sstevel@tonic-gate  *	CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
5207c478bd9Sstevel@tonic-gate  */
5217c478bd9Sstevel@tonic-gate CK_RV
soft_decrypt_final(soft_session_t * session_p,CK_BYTE_PTR pLastPart,CK_ULONG_PTR pulLastPartLen)5227c478bd9Sstevel@tonic-gate soft_decrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastPart,
5237c478bd9Sstevel@tonic-gate 	CK_ULONG_PTR pulLastPartLen)
5247c478bd9Sstevel@tonic-gate {
5257c478bd9Sstevel@tonic-gate 
5267c478bd9Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
5277c478bd9Sstevel@tonic-gate 	CK_ULONG out_len;
5287c478bd9Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
5297c478bd9Sstevel@tonic-gate 	int rc;
5307c478bd9Sstevel@tonic-gate 
5317c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
5327c478bd9Sstevel@tonic-gate 
5337c478bd9Sstevel@tonic-gate 	if (session_p->decrypt.context == NULL) {
5347c478bd9Sstevel@tonic-gate 		rv = CKR_OPERATION_NOT_INITIALIZED;
5357c478bd9Sstevel@tonic-gate 		*pulLastPartLen = 0;
5367c478bd9Sstevel@tonic-gate 		goto clean2;
5377c478bd9Sstevel@tonic-gate 	}
5387c478bd9Sstevel@tonic-gate 	switch (mechanism) {
5397c478bd9Sstevel@tonic-gate 
5407c478bd9Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
5417c478bd9Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
5427c478bd9Sstevel@tonic-gate 	{
5437c478bd9Sstevel@tonic-gate 
5447c478bd9Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
5457c478bd9Sstevel@tonic-gate 
5467c478bd9Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
5477c478bd9Sstevel@tonic-gate 
5487c478bd9Sstevel@tonic-gate 		/*
5497c478bd9Sstevel@tonic-gate 		 * We should have only one block of data left in the
5507c478bd9Sstevel@tonic-gate 		 * remaining buffer.
5517c478bd9Sstevel@tonic-gate 		 */
5527c478bd9Sstevel@tonic-gate 		if (soft_des_ctx->remain_len != DES_BLOCK_LEN) {
5537c478bd9Sstevel@tonic-gate 			*pulLastPartLen = 0;
5547c478bd9Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
5557c478bd9Sstevel@tonic-gate 			/* Cleanup memory space. */
5567c478bd9Sstevel@tonic-gate 			free(soft_des_ctx->des_cbc);
5577c478bd9Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
5587c478bd9Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
5597c478bd9Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
5607c478bd9Sstevel@tonic-gate 
5617c478bd9Sstevel@tonic-gate 			goto clean1;
5627c478bd9Sstevel@tonic-gate 		}
5637c478bd9Sstevel@tonic-gate 
5647c478bd9Sstevel@tonic-gate 		out_len = DES_BLOCK_LEN;
5657c478bd9Sstevel@tonic-gate 
5667c478bd9Sstevel@tonic-gate 		/*
5677c478bd9Sstevel@tonic-gate 		 * If application asks for the length of the output buffer
5687c478bd9Sstevel@tonic-gate 		 * to hold the plaintext?
5697c478bd9Sstevel@tonic-gate 		 */
5707c478bd9Sstevel@tonic-gate 		if (pLastPart == NULL) {
5717c478bd9Sstevel@tonic-gate 			*pulLastPartLen = out_len;
5727c478bd9Sstevel@tonic-gate 			rv = CKR_OK;
5737c478bd9Sstevel@tonic-gate 			goto clean2;
5747c478bd9Sstevel@tonic-gate 		} else {
5757c478bd9Sstevel@tonic-gate 			crypto_data_t out;
5767c478bd9Sstevel@tonic-gate 
5777c478bd9Sstevel@tonic-gate 			/* Copy remaining data to the output buffer. */
5787c478bd9Sstevel@tonic-gate 			(void) memcpy(pLastPart, soft_des_ctx->data,
5797c478bd9Sstevel@tonic-gate 			    DES_BLOCK_LEN);
5807c478bd9Sstevel@tonic-gate 
5817c478bd9Sstevel@tonic-gate 			out.cd_format = CRYPTO_DATA_RAW;
5827c478bd9Sstevel@tonic-gate 			out.cd_offset = 0;
5837c478bd9Sstevel@tonic-gate 			out.cd_length = DES_BLOCK_LEN;
5847c478bd9Sstevel@tonic-gate 			out.cd_raw.iov_base = (char *)pLastPart;
5857c478bd9Sstevel@tonic-gate 			out.cd_raw.iov_len = DES_BLOCK_LEN;
5867c478bd9Sstevel@tonic-gate 
5877c478bd9Sstevel@tonic-gate 			/* Decrypt final block of data. */
5887c478bd9Sstevel@tonic-gate 			rc = des_decrypt_contiguous_blocks(
5897c478bd9Sstevel@tonic-gate 			    (des_ctx_t *)soft_des_ctx->des_cbc,
5907c478bd9Sstevel@tonic-gate 			    (char *)pLastPart, DES_BLOCK_LEN, &out);
5917c478bd9Sstevel@tonic-gate 
5927c478bd9Sstevel@tonic-gate 			if (rc == 0) {
5937c478bd9Sstevel@tonic-gate 				/*
5947c478bd9Sstevel@tonic-gate 				 * Remove padding bytes after decryption of
5957c478bd9Sstevel@tonic-gate 				 * ciphertext block to produce the original
5967c478bd9Sstevel@tonic-gate 				 * plaintext.
5977c478bd9Sstevel@tonic-gate 				 */
5987c478bd9Sstevel@tonic-gate 				rv = soft_remove_pkcs7_padding(pLastPart,
599*726fad2aSDina K Nimeh 				    DES_BLOCK_LEN, &out_len);
6007c478bd9Sstevel@tonic-gate 				if (rv != CKR_OK)
6017c478bd9Sstevel@tonic-gate 					*pulLastPartLen = 0;
6027c478bd9Sstevel@tonic-gate 				else
6037c478bd9Sstevel@tonic-gate 					*pulLastPartLen = out_len;
6047c478bd9Sstevel@tonic-gate 			} else {
6057c478bd9Sstevel@tonic-gate 				*pulLastPartLen = 0;
6067c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
6077c478bd9Sstevel@tonic-gate 			}
6087c478bd9Sstevel@tonic-gate 
6097c478bd9Sstevel@tonic-gate 			/* Cleanup memory space. */
6107c478bd9Sstevel@tonic-gate 			free(soft_des_ctx->des_cbc);
6117c478bd9Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
6127c478bd9Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
6137c478bd9Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
6147c478bd9Sstevel@tonic-gate 
6157c478bd9Sstevel@tonic-gate 		}
6167c478bd9Sstevel@tonic-gate 
6177c478bd9Sstevel@tonic-gate 		break;
6187c478bd9Sstevel@tonic-gate 	}
6197c478bd9Sstevel@tonic-gate 
6207c478bd9Sstevel@tonic-gate 	case CKM_DES_CBC:
6217c478bd9Sstevel@tonic-gate 	case CKM_DES_ECB:
6227c478bd9Sstevel@tonic-gate 	case CKM_DES3_CBC:
6237c478bd9Sstevel@tonic-gate 	case CKM_DES3_ECB:
6247c478bd9Sstevel@tonic-gate 	{
6257c478bd9Sstevel@tonic-gate 
6267c478bd9Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
6277c478bd9Sstevel@tonic-gate 
6287c478bd9Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->decrypt.context;
6297c478bd9Sstevel@tonic-gate 		/*
6307c478bd9Sstevel@tonic-gate 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
6317c478bd9Sstevel@tonic-gate 		 * so when the final is called, the remaining buffer
6327c478bd9Sstevel@tonic-gate 		 * should not contain any more data.
6337c478bd9Sstevel@tonic-gate 		 */
6347c478bd9Sstevel@tonic-gate 		*pulLastPartLen = 0;
6357c478bd9Sstevel@tonic-gate 		if (soft_des_ctx->remain_len != 0) {
6367c478bd9Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
6377c478bd9Sstevel@tonic-gate 		} else {
6387c478bd9Sstevel@tonic-gate 			if (pLastPart == NULL)
6397c478bd9Sstevel@tonic-gate 				goto clean2;
6407c478bd9Sstevel@tonic-gate 		}
6417c478bd9Sstevel@tonic-gate 
6427c478bd9Sstevel@tonic-gate 		/* Cleanup memory space. */
6437c478bd9Sstevel@tonic-gate 		free(soft_des_ctx->des_cbc);
6447c478bd9Sstevel@tonic-gate 		bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
6457c478bd9Sstevel@tonic-gate 		free(soft_des_ctx->key_sched);
6467c478bd9Sstevel@tonic-gate 
6477c478bd9Sstevel@tonic-gate 		break;
6487c478bd9Sstevel@tonic-gate 	}
6497c478bd9Sstevel@tonic-gate 
6507c478bd9Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
6517c478bd9Sstevel@tonic-gate 	{
6527c478bd9Sstevel@tonic-gate 
6537c478bd9Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
6547c478bd9Sstevel@tonic-gate 
6557c478bd9Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
6567c478bd9Sstevel@tonic-gate 
6577c478bd9Sstevel@tonic-gate 		/*
6587c478bd9Sstevel@tonic-gate 		 * We should have only one block of data left in the
6597c478bd9Sstevel@tonic-gate 		 * remaining buffer.
6607c478bd9Sstevel@tonic-gate 		 */
6617c478bd9Sstevel@tonic-gate 		if (soft_aes_ctx->remain_len != AES_BLOCK_LEN) {
6627c478bd9Sstevel@tonic-gate 			*pulLastPartLen = 0;
6637c478bd9Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
6647c478bd9Sstevel@tonic-gate 			/* Cleanup memory space. */
6657c478bd9Sstevel@tonic-gate 			free(soft_aes_ctx->aes_cbc);
6667c478bd9Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
6677c478bd9Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
6687c478bd9Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
6697c478bd9Sstevel@tonic-gate 
6707c478bd9Sstevel@tonic-gate 			goto clean1;
6717c478bd9Sstevel@tonic-gate 		}
6727c478bd9Sstevel@tonic-gate 
6737c478bd9Sstevel@tonic-gate 		out_len = AES_BLOCK_LEN;
6747c478bd9Sstevel@tonic-gate 
6757c478bd9Sstevel@tonic-gate 		/*
6767c478bd9Sstevel@tonic-gate 		 * If application asks for the length of the output buffer
6777c478bd9Sstevel@tonic-gate 		 * to hold the plaintext?
6787c478bd9Sstevel@tonic-gate 		 */
6797c478bd9Sstevel@tonic-gate 		if (pLastPart == NULL) {
6807c478bd9Sstevel@tonic-gate 			*pulLastPartLen = out_len;
6817c478bd9Sstevel@tonic-gate 			rv = CKR_OK;
6827c478bd9Sstevel@tonic-gate 			goto clean2;
6837c478bd9Sstevel@tonic-gate 		} else {
6847c478bd9Sstevel@tonic-gate 			crypto_data_t out;
6857c478bd9Sstevel@tonic-gate 
6867c478bd9Sstevel@tonic-gate 			/* Copy remaining data to the output buffer. */
6877c478bd9Sstevel@tonic-gate 			(void) memcpy(pLastPart, soft_aes_ctx->data,
6887c478bd9Sstevel@tonic-gate 			    AES_BLOCK_LEN);
6897c478bd9Sstevel@tonic-gate 
6907c478bd9Sstevel@tonic-gate 			out.cd_format = CRYPTO_DATA_RAW;
6917c478bd9Sstevel@tonic-gate 			out.cd_offset = 0;
6927c478bd9Sstevel@tonic-gate 			out.cd_length = AES_BLOCK_LEN;
6937c478bd9Sstevel@tonic-gate 			out.cd_raw.iov_base = (char *)pLastPart;
6947c478bd9Sstevel@tonic-gate 			out.cd_raw.iov_len = AES_BLOCK_LEN;
6957c478bd9Sstevel@tonic-gate 
6967c478bd9Sstevel@tonic-gate 			/* Decrypt final block of data. */
6977c478bd9Sstevel@tonic-gate 			rc = aes_decrypt_contiguous_blocks(
6987c478bd9Sstevel@tonic-gate 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
6997c478bd9Sstevel@tonic-gate 			    (char *)pLastPart, AES_BLOCK_LEN, &out);
7007c478bd9Sstevel@tonic-gate 
7017c478bd9Sstevel@tonic-gate 			if (rc == 0) {
7027c478bd9Sstevel@tonic-gate 				/*
7037c478bd9Sstevel@tonic-gate 				 * Remove padding bytes after decryption of
7047c478bd9Sstevel@tonic-gate 				 * ciphertext block to produce the original
7057c478bd9Sstevel@tonic-gate 				 * plaintext.
7067c478bd9Sstevel@tonic-gate 				 */
7077c478bd9Sstevel@tonic-gate 				rv = soft_remove_pkcs7_padding(pLastPart,
708*726fad2aSDina K Nimeh 				    AES_BLOCK_LEN, &out_len);
7097c478bd9Sstevel@tonic-gate 				if (rv != CKR_OK)
7107c478bd9Sstevel@tonic-gate 					*pulLastPartLen = 0;
7117c478bd9Sstevel@tonic-gate 				else
7127c478bd9Sstevel@tonic-gate 					*pulLastPartLen = out_len;
7137c478bd9Sstevel@tonic-gate 			} else {
7147c478bd9Sstevel@tonic-gate 				*pulLastPartLen = 0;
7157c478bd9Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
7167c478bd9Sstevel@tonic-gate 			}
7177c478bd9Sstevel@tonic-gate 
7187c478bd9Sstevel@tonic-gate 			/* Cleanup memory space. */
7197c478bd9Sstevel@tonic-gate 			free(soft_aes_ctx->aes_cbc);
7207c478bd9Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
7217c478bd9Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
7227c478bd9Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
7237c478bd9Sstevel@tonic-gate 
7247c478bd9Sstevel@tonic-gate 		}
7257c478bd9Sstevel@tonic-gate 
7267c478bd9Sstevel@tonic-gate 		break;
7277c478bd9Sstevel@tonic-gate 	}
7287c478bd9Sstevel@tonic-gate 
7297c478bd9Sstevel@tonic-gate 	case CKM_AES_CBC:
7307c478bd9Sstevel@tonic-gate 	case CKM_AES_ECB:
7317c478bd9Sstevel@tonic-gate 	{
7327c478bd9Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
7337c478bd9Sstevel@tonic-gate 
7347c478bd9Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
7357c478bd9Sstevel@tonic-gate 		/*
7367c478bd9Sstevel@tonic-gate 		 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
7377c478bd9Sstevel@tonic-gate 		 * so when the final is called, the remaining buffer
7387c478bd9Sstevel@tonic-gate 		 * should not contain any more data.
7397c478bd9Sstevel@tonic-gate 		 */
7407c478bd9Sstevel@tonic-gate 		*pulLastPartLen = 0;
7417c478bd9Sstevel@tonic-gate 		if (soft_aes_ctx->remain_len != 0) {
7427c478bd9Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
7437c478bd9Sstevel@tonic-gate 		} else {
7447c478bd9Sstevel@tonic-gate 			if (pLastPart == NULL)
7457c478bd9Sstevel@tonic-gate 				goto clean2;
7467c478bd9Sstevel@tonic-gate 		}
7477c478bd9Sstevel@tonic-gate 
7487c478bd9Sstevel@tonic-gate 		/* Cleanup memory space. */
7497c478bd9Sstevel@tonic-gate 		free(soft_aes_ctx->aes_cbc);
7507c478bd9Sstevel@tonic-gate 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
7517c478bd9Sstevel@tonic-gate 		free(soft_aes_ctx->key_sched);
7527c478bd9Sstevel@tonic-gate 
7537c478bd9Sstevel@tonic-gate 		break;
7547c478bd9Sstevel@tonic-gate 	}
75523c57df7Smcpowers 	case CKM_AES_CTR:
75623c57df7Smcpowers 	{
75723c57df7Smcpowers 		crypto_data_t out;
75823c57df7Smcpowers 		soft_aes_ctx_t *soft_aes_ctx;
75923c57df7Smcpowers 		ctr_ctx_t *ctr_ctx;
76023c57df7Smcpowers 		size_t len;
7617c478bd9Sstevel@tonic-gate 
76223c57df7Smcpowers 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->decrypt.context;
76323c57df7Smcpowers 		ctr_ctx = soft_aes_ctx->aes_cbc;
76423c57df7Smcpowers 		len = ctr_ctx->ctr_remainder_len;
76523c57df7Smcpowers 		if (pLastPart == NULL) {
76623c57df7Smcpowers 			*pulLastPartLen = len;
76723c57df7Smcpowers 			goto clean1;
76823c57df7Smcpowers 		}
76923c57df7Smcpowers 		if (len > 0) {
77023c57df7Smcpowers 			out.cd_format = CRYPTO_DATA_RAW;
77123c57df7Smcpowers 			out.cd_offset = 0;
77223c57df7Smcpowers 			out.cd_length = len;
77323c57df7Smcpowers 			out.cd_raw.iov_base = (char *)pLastPart;
77423c57df7Smcpowers 			out.cd_raw.iov_len = len;
77523c57df7Smcpowers 
77623c57df7Smcpowers 			rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
77723c57df7Smcpowers 			if (rv == CRYPTO_DATA_LEN_RANGE)
77823c57df7Smcpowers 				rv = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
77923c57df7Smcpowers 		}
78023c57df7Smcpowers 		if (rv == CRYPTO_BUFFER_TOO_SMALL) {
78123c57df7Smcpowers 			*pulLastPartLen = len;
78223c57df7Smcpowers 			goto clean1;
78323c57df7Smcpowers 		}
78423c57df7Smcpowers 
78523c57df7Smcpowers 		/* Cleanup memory space. */
78623c57df7Smcpowers 		free(ctr_ctx);
78723c57df7Smcpowers 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
78823c57df7Smcpowers 		free(soft_aes_ctx->key_sched);
78923c57df7Smcpowers 
79023c57df7Smcpowers 		break;
79123c57df7Smcpowers 	}
792f66d273dSizick 	case CKM_BLOWFISH_CBC:
793f66d273dSizick 	{
794f66d273dSizick 		soft_blowfish_ctx_t *soft_blowfish_ctx;
795f66d273dSizick 
796f66d273dSizick 		soft_blowfish_ctx =
797f66d273dSizick 		    (soft_blowfish_ctx_t *)session_p->decrypt.context;
798f66d273dSizick 
799f66d273dSizick 		*pulLastPartLen = 0;
800f66d273dSizick 		if (soft_blowfish_ctx->remain_len != 0)
801f66d273dSizick 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
802f66d273dSizick 		else {
803f66d273dSizick 			if (pLastPart == NULL)
804f66d273dSizick 				goto clean2;
805f66d273dSizick 		}
806f66d273dSizick 
807f66d273dSizick 		free(soft_blowfish_ctx->blowfish_cbc);
808f66d273dSizick 		bzero(soft_blowfish_ctx->key_sched,
809f66d273dSizick 		    soft_blowfish_ctx->keysched_len);
810f66d273dSizick 		free(soft_blowfish_ctx->key_sched);
811f66d273dSizick 
812f66d273dSizick 		break;
813f66d273dSizick 	}
814f66d273dSizick 
8157c478bd9Sstevel@tonic-gate 	case CKM_RC4:
8167c478bd9Sstevel@tonic-gate 	{
8177c478bd9Sstevel@tonic-gate 		ARCFour_key *key = (ARCFour_key *)session_p->decrypt.context;
8187c478bd9Sstevel@tonic-gate 		bzero(key, sizeof (*key));
8197c478bd9Sstevel@tonic-gate 		*pulLastPartLen = 0;
8207c478bd9Sstevel@tonic-gate 		break;
8217c478bd9Sstevel@tonic-gate 	}
8227c478bd9Sstevel@tonic-gate 
8237c478bd9Sstevel@tonic-gate 	default:
8247c478bd9Sstevel@tonic-gate 		/* PKCS11: The mechanism only supports single-part operation. */
8257c478bd9Sstevel@tonic-gate 		rv = CKR_MECHANISM_INVALID;
8267c478bd9Sstevel@tonic-gate 		break;
8277c478bd9Sstevel@tonic-gate 	}
8287c478bd9Sstevel@tonic-gate 
8297c478bd9Sstevel@tonic-gate clean1:
8307c478bd9Sstevel@tonic-gate 	free(session_p->decrypt.context);
8317c478bd9Sstevel@tonic-gate 	session_p->decrypt.context = NULL;
8327c478bd9Sstevel@tonic-gate 
8337c478bd9Sstevel@tonic-gate clean2:
8347c478bd9Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
8357c478bd9Sstevel@tonic-gate 
8367c478bd9Sstevel@tonic-gate 	return (rv);
8377c478bd9Sstevel@tonic-gate 
8387c478bd9Sstevel@tonic-gate }
839