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  * Add padding bytes with the value of length of padding.
420Sstevel@tonic-gate  */
430Sstevel@tonic-gate void
soft_add_pkcs7_padding(CK_BYTE * buf,int block_size,CK_ULONG data_len)440Sstevel@tonic-gate soft_add_pkcs7_padding(CK_BYTE *buf, int block_size, CK_ULONG data_len)
450Sstevel@tonic-gate {
46*12573SDina.Nimeh@Sun.COM 	(void) pkcs7_encode(NULL, data_len, buf, block_size, block_size);
470Sstevel@tonic-gate }
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * Perform encrypt init operation internally for the support of
510Sstevel@tonic-gate  * CKM_DES_MAC and CKM_DES_MAC_GENERAL
520Sstevel@tonic-gate  *
530Sstevel@tonic-gate  * This function is called with the session being held, and without
540Sstevel@tonic-gate  * its mutex taken.
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate CK_RV
soft_encrypt_init_internal(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p)570Sstevel@tonic-gate soft_encrypt_init_internal(soft_session_t *session_p, CK_MECHANISM_PTR
580Sstevel@tonic-gate 	pMechanism, soft_object_t *key_p)
590Sstevel@tonic-gate {
600Sstevel@tonic-gate 	CK_RV rv;
610Sstevel@tonic-gate 
620Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	/* Check to see if encrypt operation is already active */
650Sstevel@tonic-gate 	if (session_p->encrypt.flags & CRYPTO_OPERATION_ACTIVE) {
660Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
670Sstevel@tonic-gate 		return (CKR_OPERATION_ACTIVE);
680Sstevel@tonic-gate 	}
690Sstevel@tonic-gate 
700Sstevel@tonic-gate 	session_p->encrypt.flags = CRYPTO_OPERATION_ACTIVE;
710Sstevel@tonic-gate 
720Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	rv = soft_encrypt_init(session_p, pMechanism, key_p);
750Sstevel@tonic-gate 
760Sstevel@tonic-gate 	if (rv != CKR_OK) {
770Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
780Sstevel@tonic-gate 		session_p->encrypt.flags &= ~CRYPTO_OPERATION_ACTIVE;
790Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
800Sstevel@tonic-gate 	}
810Sstevel@tonic-gate 
820Sstevel@tonic-gate 	return (rv);
830Sstevel@tonic-gate }
840Sstevel@tonic-gate 
850Sstevel@tonic-gate /*
860Sstevel@tonic-gate  * soft_encrypt_init()
870Sstevel@tonic-gate  *
880Sstevel@tonic-gate  * Arguments:
890Sstevel@tonic-gate  *	session_p:	pointer to soft_session_t struct
900Sstevel@tonic-gate  *	pMechanism:	pointer to CK_MECHANISM struct provided by application
910Sstevel@tonic-gate  *	key_p:		pointer to key soft_object_t struct
920Sstevel@tonic-gate  *
930Sstevel@tonic-gate  * Description:
940Sstevel@tonic-gate  *	called by C_EncryptInit(). This function calls the corresponding
950Sstevel@tonic-gate  *	encrypt init routine based on the mechanism.
960Sstevel@tonic-gate  *
970Sstevel@tonic-gate  * Returns:
980Sstevel@tonic-gate  *	CKR_OK: success
990Sstevel@tonic-gate  *	CKR_HOST_MEMORY: run out of system memory
1000Sstevel@tonic-gate  *	CKR_MECHANISM_PARAM_INVALID: invalid parameters in mechanism
1010Sstevel@tonic-gate  *	CKR_MECHANISM_INVALID: invalid mechanism type
1020Sstevel@tonic-gate  *	CKR_KEY_TYPE_INCONSISTENT: incorrect type of key to use
1030Sstevel@tonic-gate  *		with the specified mechanism
1040Sstevel@tonic-gate  */
1050Sstevel@tonic-gate CK_RV
soft_encrypt_init(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p)1060Sstevel@tonic-gate soft_encrypt_init(soft_session_t *session_p, CK_MECHANISM_PTR pMechanism,
1070Sstevel@tonic-gate     soft_object_t *key_p)
1080Sstevel@tonic-gate {
1090Sstevel@tonic-gate 
1100Sstevel@tonic-gate 	CK_RV rv;
1110Sstevel@tonic-gate 
1120Sstevel@tonic-gate 	switch (pMechanism->mechanism) {
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate 	case CKM_DES_ECB:
1150Sstevel@tonic-gate 
1160Sstevel@tonic-gate 		if (key_p->key_type != CKK_DES) {
1170Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1180Sstevel@tonic-gate 		}
1190Sstevel@tonic-gate 		goto ecb_common;
1200Sstevel@tonic-gate 
1210Sstevel@tonic-gate 	case CKM_DES3_ECB:
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 		if ((key_p->key_type != CKK_DES2) &&
1240Sstevel@tonic-gate 		    (key_p->key_type != CKK_DES3)) {
1250Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1260Sstevel@tonic-gate 		}
1270Sstevel@tonic-gate 
1280Sstevel@tonic-gate ecb_common:
1290Sstevel@tonic-gate 		return (soft_des_crypt_init_common(session_p, pMechanism,
1300Sstevel@tonic-gate 		    key_p, B_TRUE));
1310Sstevel@tonic-gate 
1320Sstevel@tonic-gate 	case CKM_DES_CBC:
1330Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate 		if (key_p->key_type != CKK_DES) {
1360Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1370Sstevel@tonic-gate 		}
1380Sstevel@tonic-gate 
1390Sstevel@tonic-gate 		goto cbc_common;
1400Sstevel@tonic-gate 
1410Sstevel@tonic-gate 	case CKM_DES3_CBC:
1420Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
1430Sstevel@tonic-gate 	{
1440Sstevel@tonic-gate 
1450Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
1460Sstevel@tonic-gate 
1470Sstevel@tonic-gate 		if ((key_p->key_type != CKK_DES2) &&
1480Sstevel@tonic-gate 		    (key_p->key_type != CKK_DES3)) {
1490Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1500Sstevel@tonic-gate 		}
1510Sstevel@tonic-gate 
1520Sstevel@tonic-gate cbc_common:
1530Sstevel@tonic-gate 		if ((pMechanism->pParameter == NULL) ||
1540Sstevel@tonic-gate 		    (pMechanism->ulParameterLen != DES_BLOCK_LEN)) {
1550Sstevel@tonic-gate 			return (CKR_MECHANISM_PARAM_INVALID);
1560Sstevel@tonic-gate 		}
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 		rv = soft_des_crypt_init_common(session_p, pMechanism,
1590Sstevel@tonic-gate 		    key_p, B_TRUE);
1600Sstevel@tonic-gate 
1610Sstevel@tonic-gate 		if (rv != CKR_OK)
1620Sstevel@tonic-gate 			return (rv);
1630Sstevel@tonic-gate 
1640Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
1650Sstevel@tonic-gate 
1660Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
1670Sstevel@tonic-gate 		/* Copy Initialization Vector (IV) into the context. */
1680Sstevel@tonic-gate 		(void) memcpy(soft_des_ctx->ivec, pMechanism->pParameter,
1690Sstevel@tonic-gate 		    DES_BLOCK_LEN);
1700Sstevel@tonic-gate 
1710Sstevel@tonic-gate 		/* Allocate a context for DES cipher-block chaining. */
1720Sstevel@tonic-gate 		soft_des_ctx->des_cbc = (void *)des_cbc_ctx_init(
1730Sstevel@tonic-gate 		    soft_des_ctx->key_sched, soft_des_ctx->keysched_len,
1740Sstevel@tonic-gate 		    soft_des_ctx->ivec, key_p->key_type);
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate 		if (soft_des_ctx->des_cbc == NULL) {
1770Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
1780Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
1790Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
1800Sstevel@tonic-gate 			free(session_p->encrypt.context);
1810Sstevel@tonic-gate 			session_p->encrypt.context = NULL;
1820Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
1830Sstevel@tonic-gate 		}
1840Sstevel@tonic-gate 
1850Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate 		return (rv);
1880Sstevel@tonic-gate 	}
1890Sstevel@tonic-gate 	case CKM_AES_ECB:
1900Sstevel@tonic-gate 
1910Sstevel@tonic-gate 		if (key_p->key_type != CKK_AES) {
1920Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
1930Sstevel@tonic-gate 		}
1940Sstevel@tonic-gate 
1950Sstevel@tonic-gate 		return (soft_aes_crypt_init_common(session_p, pMechanism,
1960Sstevel@tonic-gate 		    key_p, B_TRUE));
1970Sstevel@tonic-gate 
1980Sstevel@tonic-gate 	case CKM_AES_CBC:
1990Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
2000Sstevel@tonic-gate 	{
2010Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
2020Sstevel@tonic-gate 
2030Sstevel@tonic-gate 		if (key_p->key_type != CKK_AES) {
2040Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
2050Sstevel@tonic-gate 		}
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 		if ((pMechanism->pParameter == NULL) ||
2080Sstevel@tonic-gate 		    (pMechanism->ulParameterLen != AES_BLOCK_LEN)) {
2090Sstevel@tonic-gate 			return (CKR_MECHANISM_PARAM_INVALID);
2100Sstevel@tonic-gate 		}
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
2130Sstevel@tonic-gate 		    key_p, B_TRUE);
2140Sstevel@tonic-gate 
2150Sstevel@tonic-gate 		if (rv != CKR_OK)
2160Sstevel@tonic-gate 			return (rv);
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
2210Sstevel@tonic-gate 		/* Copy Initialization Vector (IV) into the context. */
2220Sstevel@tonic-gate 		(void) memcpy(soft_aes_ctx->ivec, pMechanism->pParameter,
2230Sstevel@tonic-gate 		    AES_BLOCK_LEN);
2240Sstevel@tonic-gate 
2250Sstevel@tonic-gate 		/* Allocate a context for AES cipher-block chaining. */
2260Sstevel@tonic-gate 		soft_aes_ctx->aes_cbc = (void *)aes_cbc_ctx_init(
2270Sstevel@tonic-gate 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
2280Sstevel@tonic-gate 		    soft_aes_ctx->ivec);
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 		if (soft_aes_ctx->aes_cbc == NULL) {
2310Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
2320Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
2330Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
2340Sstevel@tonic-gate 			free(session_p->encrypt.context);
2350Sstevel@tonic-gate 			session_p->encrypt.context = NULL;
2360Sstevel@tonic-gate 			rv = CKR_HOST_MEMORY;
2370Sstevel@tonic-gate 		}
2380Sstevel@tonic-gate 
2390Sstevel@tonic-gate 		(void) pthread_mutex_unlock(&session_p->session_mutex);
2400Sstevel@tonic-gate 
2410Sstevel@tonic-gate 		return (rv);
2420Sstevel@tonic-gate 	}
2437188Smcpowers 	case CKM_AES_CTR:
2447188Smcpowers 	{
2457188Smcpowers 		soft_aes_ctx_t *soft_aes_ctx;
2467188Smcpowers 
2477188Smcpowers 		if (key_p->key_type != CKK_AES) {
2487188Smcpowers 			return (CKR_KEY_TYPE_INCONSISTENT);
2497188Smcpowers 		}
2507188Smcpowers 
2517188Smcpowers 		if (pMechanism->pParameter == NULL ||
2527188Smcpowers 		    pMechanism->ulParameterLen != sizeof (CK_AES_CTR_PARAMS)) {
2537188Smcpowers 			return (CKR_MECHANISM_PARAM_INVALID);
2547188Smcpowers 		}
2557188Smcpowers 
2567188Smcpowers 		rv = soft_aes_crypt_init_common(session_p, pMechanism,
2577188Smcpowers 		    key_p, B_TRUE);
2587188Smcpowers 
2597188Smcpowers 		if (rv != CKR_OK)
2607188Smcpowers 			return (rv);
2617188Smcpowers 
2627188Smcpowers 		(void) pthread_mutex_lock(&session_p->session_mutex);
2637188Smcpowers 
2647188Smcpowers 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
2657188Smcpowers 		soft_aes_ctx->aes_cbc = aes_ctr_ctx_init(
2667188Smcpowers 		    soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len,
2677188Smcpowers 		    pMechanism->pParameter);
2687188Smcpowers 
2697188Smcpowers 		if (soft_aes_ctx->aes_cbc == NULL) {
2707188Smcpowers 			bzero(soft_aes_ctx->key_sched,
2717188Smcpowers 			    soft_aes_ctx->keysched_len);
2727188Smcpowers 			free(soft_aes_ctx->key_sched);
2737188Smcpowers 			free(session_p->encrypt.context);
2747188Smcpowers 			session_p->encrypt.context = NULL;
2757188Smcpowers 			rv = CKR_HOST_MEMORY;
2767188Smcpowers 		}
2777188Smcpowers 
2787188Smcpowers 		(void) pthread_mutex_unlock(&session_p->session_mutex);
2797188Smcpowers 
2807188Smcpowers 		return (rv);
2817188Smcpowers 	}
2820Sstevel@tonic-gate 	case CKM_RC4:
2830Sstevel@tonic-gate 
2840Sstevel@tonic-gate 		if (key_p->key_type != CKK_RC4) {
2850Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
2860Sstevel@tonic-gate 		}
2870Sstevel@tonic-gate 
2880Sstevel@tonic-gate 		return (soft_arcfour_crypt_init(session_p, pMechanism, key_p,
2890Sstevel@tonic-gate 		    B_TRUE));
2900Sstevel@tonic-gate 
2910Sstevel@tonic-gate 	case CKM_RSA_X_509:
2920Sstevel@tonic-gate 	case CKM_RSA_PKCS:
2930Sstevel@tonic-gate 
2940Sstevel@tonic-gate 		if (key_p->key_type != CKK_RSA) {
2950Sstevel@tonic-gate 			return (CKR_KEY_TYPE_INCONSISTENT);
2960Sstevel@tonic-gate 		}
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 		return (soft_rsa_crypt_init_common(session_p, pMechanism,
2990Sstevel@tonic-gate 		    key_p, B_TRUE));
3000Sstevel@tonic-gate 
301676Sizick 	case CKM_BLOWFISH_CBC:
302676Sizick 	{
303676Sizick 		soft_blowfish_ctx_t *soft_blowfish_ctx;
304676Sizick 
305676Sizick 		if (key_p->key_type != CKK_BLOWFISH)
306676Sizick 			return (CKR_KEY_TYPE_INCONSISTENT);
307676Sizick 
308676Sizick 		if ((pMechanism->pParameter == NULL) ||
309676Sizick 		    (pMechanism->ulParameterLen != BLOWFISH_BLOCK_LEN))
310676Sizick 			return (CKR_MECHANISM_PARAM_INVALID);
311676Sizick 
312676Sizick 		rv = soft_blowfish_crypt_init_common(session_p, pMechanism,
313676Sizick 		    key_p, B_TRUE);
314676Sizick 
315676Sizick 		if (rv != CKR_OK)
316676Sizick 			return (rv);
317676Sizick 
318676Sizick 		(void) pthread_mutex_lock(&session_p->session_mutex);
319676Sizick 
320676Sizick 		soft_blowfish_ctx =
321676Sizick 		    (soft_blowfish_ctx_t *)session_p->encrypt.context;
322676Sizick 		/* Copy Initialization Vector (IV) into the context. */
323676Sizick 		(void) memcpy(soft_blowfish_ctx->ivec, pMechanism->pParameter,
324676Sizick 		    BLOWFISH_BLOCK_LEN);
325676Sizick 
326676Sizick 		/* Allocate a context for Blowfish cipher-block chaining */
327676Sizick 		soft_blowfish_ctx->blowfish_cbc =
328676Sizick 		    (void *)blowfish_cbc_ctx_init(soft_blowfish_ctx->key_sched,
3297188Smcpowers 		    soft_blowfish_ctx->keysched_len,
3307188Smcpowers 		    soft_blowfish_ctx->ivec);
331676Sizick 
332676Sizick 		if (soft_blowfish_ctx->blowfish_cbc == NULL) {
333676Sizick 			bzero(soft_blowfish_ctx->key_sched,
334676Sizick 			    soft_blowfish_ctx->keysched_len);
335676Sizick 			free(soft_blowfish_ctx->key_sched);
336676Sizick 			free(session_p->encrypt.context);
337676Sizick 			session_p->encrypt.context = NULL;
338676Sizick 			rv = CKR_HOST_MEMORY;
339676Sizick 		}
340676Sizick 
341676Sizick 		(void) pthread_mutex_unlock(&session_p->session_mutex);
342676Sizick 
343676Sizick 		return (rv);
344676Sizick 	}
3450Sstevel@tonic-gate 	default:
3460Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
3470Sstevel@tonic-gate 	}
3480Sstevel@tonic-gate }
3490Sstevel@tonic-gate 
3500Sstevel@tonic-gate 
3510Sstevel@tonic-gate /*
3520Sstevel@tonic-gate  * soft_encrypt_common()
3530Sstevel@tonic-gate  *
3540Sstevel@tonic-gate  * Arguments:
3550Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
3560Sstevel@tonic-gate  *	pData:		pointer to the input data to be encrypted
3570Sstevel@tonic-gate  *	ulDataLen:	length of the input data
3580Sstevel@tonic-gate  *	pEncrypted:	pointer to the output data after encryption
3590Sstevel@tonic-gate  *	pulEncryptedLen: pointer to the length of the output data
3600Sstevel@tonic-gate  *	update:		boolean flag indicates caller is soft_encrypt
3610Sstevel@tonic-gate  *			or soft_encrypt_update
3620Sstevel@tonic-gate  *
3630Sstevel@tonic-gate  * Description:
3640Sstevel@tonic-gate  *      This function calls the corresponding encrypt routine based
3650Sstevel@tonic-gate  *	on the mechanism.
3660Sstevel@tonic-gate  *
3670Sstevel@tonic-gate  * Returns:
3680Sstevel@tonic-gate  *	see corresponding encrypt routine.
3690Sstevel@tonic-gate  */
3700Sstevel@tonic-gate CK_RV
soft_encrypt_common(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncrypted,CK_ULONG_PTR pulEncryptedLen,boolean_t update)3710Sstevel@tonic-gate soft_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
3720Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
3730Sstevel@tonic-gate     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
3740Sstevel@tonic-gate {
3750Sstevel@tonic-gate 
3760Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
3770Sstevel@tonic-gate 
3780Sstevel@tonic-gate 	switch (mechanism) {
3790Sstevel@tonic-gate 
3800Sstevel@tonic-gate 	case CKM_DES_ECB:
3810Sstevel@tonic-gate 	case CKM_DES_CBC:
3820Sstevel@tonic-gate 	case CKM_DES3_ECB:
3830Sstevel@tonic-gate 	case CKM_DES3_CBC:
3842786Sdinak 
3852786Sdinak 		if (ulDataLen == 0) {
3862786Sdinak 			*pulEncryptedLen = 0;
3872786Sdinak 			return (CKR_OK);
3882786Sdinak 		}
3892786Sdinak 		/* FALLTHROUGH */
3902786Sdinak 
3912786Sdinak 	case CKM_DES_CBC_PAD:
3920Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 		return (soft_des_encrypt_common(session_p, pData,
3950Sstevel@tonic-gate 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
3960Sstevel@tonic-gate 
3970Sstevel@tonic-gate 	case CKM_AES_ECB:
3980Sstevel@tonic-gate 	case CKM_AES_CBC:
3997188Smcpowers 	case CKM_AES_CTR:
4002786Sdinak 
4012786Sdinak 		if (ulDataLen == 0) {
4022786Sdinak 			*pulEncryptedLen = 0;
4032786Sdinak 			return (CKR_OK);
4042786Sdinak 		}
4052786Sdinak 		/* FALLTHROUGH */
4062786Sdinak 
4070Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
4080Sstevel@tonic-gate 
4090Sstevel@tonic-gate 		return (soft_aes_encrypt_common(session_p, pData,
4100Sstevel@tonic-gate 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
4110Sstevel@tonic-gate 
412676Sizick 	case CKM_BLOWFISH_CBC:
413676Sizick 
4142786Sdinak 		if (ulDataLen == 0) {
4152786Sdinak 			*pulEncryptedLen = 0;
4162786Sdinak 			return (CKR_OK);
4172786Sdinak 		}
4182786Sdinak 
419676Sizick 		return (soft_blowfish_encrypt_common(session_p, pData,
420676Sizick 		    ulDataLen, pEncrypted, pulEncryptedLen, update));
421676Sizick 
4220Sstevel@tonic-gate 	case CKM_RC4:
4230Sstevel@tonic-gate 
4242786Sdinak 		if (ulDataLen == 0) {
4252786Sdinak 			*pulEncryptedLen = 0;
4262786Sdinak 			return (CKR_OK);
4270Sstevel@tonic-gate 		}
4282786Sdinak 
4292786Sdinak 		return (soft_arcfour_crypt(&(session_p->encrypt), pData,
4302786Sdinak 		    ulDataLen, pEncrypted, pulEncryptedLen));
4310Sstevel@tonic-gate 
4320Sstevel@tonic-gate 	case CKM_RSA_X_509:
4330Sstevel@tonic-gate 	case CKM_RSA_PKCS:
4340Sstevel@tonic-gate 
4350Sstevel@tonic-gate 		return (soft_rsa_encrypt_common(session_p, pData,
4360Sstevel@tonic-gate 		    ulDataLen, pEncrypted, pulEncryptedLen, mechanism));
4370Sstevel@tonic-gate 
4380Sstevel@tonic-gate 	default:
4390Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
4400Sstevel@tonic-gate 	}
4410Sstevel@tonic-gate }
4420Sstevel@tonic-gate 
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate /*
4450Sstevel@tonic-gate  * soft_encrypt()
4460Sstevel@tonic-gate  *
4470Sstevel@tonic-gate  * Arguments:
4480Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
4490Sstevel@tonic-gate  *	pData:		pointer to the input data to be encrypted
4500Sstevel@tonic-gate  *	ulDataLen:	length of the input data
4510Sstevel@tonic-gate  *	pEncryptedData:	pointer to the output data after encryption
4520Sstevel@tonic-gate  *	pulEncryptedDataLen: pointer to the length of the output data
4530Sstevel@tonic-gate  *
4540Sstevel@tonic-gate  * Description:
4550Sstevel@tonic-gate  *      called by C_Encrypt(). This function calls the soft_encrypt_common
4560Sstevel@tonic-gate  *	routine.
4570Sstevel@tonic-gate  *
4580Sstevel@tonic-gate  * Returns:
4590Sstevel@tonic-gate  *	see soft_encrypt_common().
4600Sstevel@tonic-gate  */
4610Sstevel@tonic-gate CK_RV
soft_encrypt(soft_session_t * session_p,CK_BYTE_PTR pData,CK_ULONG ulDataLen,CK_BYTE_PTR pEncryptedData,CK_ULONG_PTR pulEncryptedDataLen)4620Sstevel@tonic-gate soft_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData,
4630Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pEncryptedData,
4640Sstevel@tonic-gate     CK_ULONG_PTR pulEncryptedDataLen)
4650Sstevel@tonic-gate {
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	return (soft_encrypt_common(session_p, pData, ulDataLen,
4680Sstevel@tonic-gate 	    pEncryptedData, pulEncryptedDataLen, B_FALSE));
4690Sstevel@tonic-gate }
4700Sstevel@tonic-gate 
4710Sstevel@tonic-gate 
4720Sstevel@tonic-gate /*
4730Sstevel@tonic-gate  * soft_encrypt_update()
4740Sstevel@tonic-gate  *
4750Sstevel@tonic-gate  * Arguments:
4760Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
4770Sstevel@tonic-gate  *      pPart:		pointer to the input data to be digested
4780Sstevel@tonic-gate  *      ulPartLen:	length of the input data
4790Sstevel@tonic-gate  *	pEncryptedPart:	pointer to the ciphertext
4800Sstevel@tonic-gate  *	pulEncryptedPartLen: pointer to the length of the ciphertext
4810Sstevel@tonic-gate  *
4820Sstevel@tonic-gate  * Description:
4830Sstevel@tonic-gate  *      called by C_EncryptUpdate(). This function calls the
4840Sstevel@tonic-gate  *	soft_encrypt_common routine (with update flag on).
4850Sstevel@tonic-gate  *
4860Sstevel@tonic-gate  * Returns:
4870Sstevel@tonic-gate  *	see soft_encrypt_common().
4880Sstevel@tonic-gate  */
4890Sstevel@tonic-gate CK_RV
soft_encrypt_update(soft_session_t * session_p,CK_BYTE_PTR pPart,CK_ULONG ulPartLen,CK_BYTE_PTR pEncryptedPart,CK_ULONG_PTR pulEncryptedPartLen)4900Sstevel@tonic-gate soft_encrypt_update(soft_session_t *session_p, CK_BYTE_PTR pPart,
4910Sstevel@tonic-gate 	CK_ULONG ulPartLen, CK_BYTE_PTR pEncryptedPart,
4920Sstevel@tonic-gate 	CK_ULONG_PTR pulEncryptedPartLen)
4930Sstevel@tonic-gate {
4940Sstevel@tonic-gate 
4950Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	switch (mechanism) {
4980Sstevel@tonic-gate 
4990Sstevel@tonic-gate 	case CKM_DES_ECB:
5000Sstevel@tonic-gate 	case CKM_DES_CBC:
5010Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
5020Sstevel@tonic-gate 	case CKM_DES3_ECB:
5030Sstevel@tonic-gate 	case CKM_DES3_CBC:
5040Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
5050Sstevel@tonic-gate 	case CKM_AES_ECB:
5060Sstevel@tonic-gate 	case CKM_AES_CBC:
5070Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
5087188Smcpowers 	case CKM_AES_CTR:
509676Sizick 	case CKM_BLOWFISH_CBC:
5102786Sdinak 	case CKM_RC4:
5110Sstevel@tonic-gate 
5120Sstevel@tonic-gate 		return (soft_encrypt_common(session_p, pPart, ulPartLen,
5130Sstevel@tonic-gate 		    pEncryptedPart, pulEncryptedPartLen, B_TRUE));
5140Sstevel@tonic-gate 
5150Sstevel@tonic-gate 	default:
5160Sstevel@tonic-gate 		/* PKCS11: The mechanism only supports single-part operation. */
5170Sstevel@tonic-gate 		return (CKR_MECHANISM_INVALID);
5180Sstevel@tonic-gate 	}
5190Sstevel@tonic-gate }
5200Sstevel@tonic-gate 
5210Sstevel@tonic-gate 
5220Sstevel@tonic-gate /*
5230Sstevel@tonic-gate  * soft_encrypt_final()
5240Sstevel@tonic-gate  *
5250Sstevel@tonic-gate  * Arguments:
5260Sstevel@tonic-gate  *      session_p:		pointer to soft_session_t struct
5270Sstevel@tonic-gate  *      pLastEncryptedPart:	pointer to the last encrypted data part
5280Sstevel@tonic-gate  *      pulLastEncryptedPartLen: pointer to the length of the last
5290Sstevel@tonic-gate  *				encrypted data part
5300Sstevel@tonic-gate  *
5310Sstevel@tonic-gate  * Description:
5320Sstevel@tonic-gate  *      called by C_EncryptFinal().
5330Sstevel@tonic-gate  *
5340Sstevel@tonic-gate  * Returns:
5350Sstevel@tonic-gate  *	CKR_OK: success
5360Sstevel@tonic-gate  *	CKR_FUNCTION_FAILED: encrypt final function failed
5370Sstevel@tonic-gate  *	CKR_DATA_LEN_RANGE: remaining buffer contains bad length
5380Sstevel@tonic-gate  */
5390Sstevel@tonic-gate CK_RV
soft_encrypt_final(soft_session_t * session_p,CK_BYTE_PTR pLastEncryptedPart,CK_ULONG_PTR pulLastEncryptedPartLen)5400Sstevel@tonic-gate soft_encrypt_final(soft_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
5410Sstevel@tonic-gate 	CK_ULONG_PTR pulLastEncryptedPartLen)
5420Sstevel@tonic-gate {
5430Sstevel@tonic-gate 
5440Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
5450Sstevel@tonic-gate 	CK_ULONG out_len;
5460Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
5470Sstevel@tonic-gate 	int rc;
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
5500Sstevel@tonic-gate 
5510Sstevel@tonic-gate 	if (session_p->encrypt.context == NULL) {
5520Sstevel@tonic-gate 		rv = CKR_OPERATION_NOT_INITIALIZED;
5530Sstevel@tonic-gate 		*pulLastEncryptedPartLen = 0;
5540Sstevel@tonic-gate 		goto clean1;
5550Sstevel@tonic-gate 	}
5560Sstevel@tonic-gate 	switch (mechanism) {
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
5590Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
5600Sstevel@tonic-gate 	{
5610Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
5620Sstevel@tonic-gate 
5630Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
5640Sstevel@tonic-gate 		/*
5650Sstevel@tonic-gate 		 * For CKM_DES_CBC_PAD, compute output length with
5660Sstevel@tonic-gate 		 * padding. If the remaining buffer has one block
5670Sstevel@tonic-gate 		 * of data, then output length will be two blocksize of
5680Sstevel@tonic-gate 		 * ciphertext. If the remaining buffer has less than
5690Sstevel@tonic-gate 		 * one block of data, then output length will be
5700Sstevel@tonic-gate 		 * one blocksize.
5710Sstevel@tonic-gate 		 */
5720Sstevel@tonic-gate 		if (soft_des_ctx->remain_len == DES_BLOCK_LEN)
5730Sstevel@tonic-gate 			out_len = 2 * DES_BLOCK_LEN;
5740Sstevel@tonic-gate 		else
5750Sstevel@tonic-gate 			out_len = DES_BLOCK_LEN;
5760Sstevel@tonic-gate 
5770Sstevel@tonic-gate 		if (pLastEncryptedPart == NULL) {
5780Sstevel@tonic-gate 			/*
5790Sstevel@tonic-gate 			 * Application asks for the length of the output
5800Sstevel@tonic-gate 			 * buffer to hold the ciphertext.
5810Sstevel@tonic-gate 			 */
5820Sstevel@tonic-gate 			*pulLastEncryptedPartLen = out_len;
5830Sstevel@tonic-gate 			goto clean1;
5840Sstevel@tonic-gate 		} else {
5850Sstevel@tonic-gate 			crypto_data_t out;
5860Sstevel@tonic-gate 
5870Sstevel@tonic-gate 			/* Copy remaining data to the output buffer. */
5880Sstevel@tonic-gate 			(void) memcpy(pLastEncryptedPart, soft_des_ctx->data,
5890Sstevel@tonic-gate 			    soft_des_ctx->remain_len);
5900Sstevel@tonic-gate 
5910Sstevel@tonic-gate 			/*
5920Sstevel@tonic-gate 			 * Add padding bytes prior to encrypt final.
5930Sstevel@tonic-gate 			 */
5940Sstevel@tonic-gate 			soft_add_pkcs7_padding(pLastEncryptedPart +
5950Sstevel@tonic-gate 			    soft_des_ctx->remain_len, DES_BLOCK_LEN,
5960Sstevel@tonic-gate 			    soft_des_ctx->remain_len);
5970Sstevel@tonic-gate 
5980Sstevel@tonic-gate 			out.cd_format = CRYPTO_DATA_RAW;
5990Sstevel@tonic-gate 			out.cd_offset = 0;
6000Sstevel@tonic-gate 			out.cd_length = out_len;
6010Sstevel@tonic-gate 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
6020Sstevel@tonic-gate 			out.cd_raw.iov_len = out_len;
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 			/* Encrypt multiple blocks of data. */
6050Sstevel@tonic-gate 			rc = des_encrypt_contiguous_blocks(
6060Sstevel@tonic-gate 			    (des_ctx_t *)soft_des_ctx->des_cbc,
6070Sstevel@tonic-gate 			    (char *)pLastEncryptedPart, out_len, &out);
6080Sstevel@tonic-gate 
6090Sstevel@tonic-gate 			if (rc == 0) {
6100Sstevel@tonic-gate 				*pulLastEncryptedPartLen = out_len;
6110Sstevel@tonic-gate 			} else {
6120Sstevel@tonic-gate 				*pulLastEncryptedPartLen = 0;
6130Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
6140Sstevel@tonic-gate 			}
6150Sstevel@tonic-gate 
6160Sstevel@tonic-gate 			/* Cleanup memory space. */
6170Sstevel@tonic-gate 			free(soft_des_ctx->des_cbc);
6180Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
6190Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
6200Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
6210Sstevel@tonic-gate 		}
6220Sstevel@tonic-gate 
6230Sstevel@tonic-gate 		break;
6240Sstevel@tonic-gate 	}
6250Sstevel@tonic-gate 	case CKM_DES_CBC:
6260Sstevel@tonic-gate 	case CKM_DES_ECB:
6270Sstevel@tonic-gate 	case CKM_DES3_CBC:
6280Sstevel@tonic-gate 	case CKM_DES3_ECB:
6290Sstevel@tonic-gate 	{
6300Sstevel@tonic-gate 
6310Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx;
6320Sstevel@tonic-gate 
6330Sstevel@tonic-gate 		soft_des_ctx = (soft_des_ctx_t *)session_p->encrypt.context;
6340Sstevel@tonic-gate 		/*
6350Sstevel@tonic-gate 		 * CKM_DES_CBC and CKM_DES_ECB does not do any padding,
6360Sstevel@tonic-gate 		 * so when the final is called, the remaining buffer
6370Sstevel@tonic-gate 		 * should not contain any more data.
6380Sstevel@tonic-gate 		 */
6390Sstevel@tonic-gate 		*pulLastEncryptedPartLen = 0;
6400Sstevel@tonic-gate 		if (soft_des_ctx->remain_len != 0) {
6410Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
6420Sstevel@tonic-gate 		} else {
6430Sstevel@tonic-gate 			if (pLastEncryptedPart == NULL)
6440Sstevel@tonic-gate 				goto clean1;
6450Sstevel@tonic-gate 		}
6460Sstevel@tonic-gate 
6470Sstevel@tonic-gate 		/* Cleanup memory space. */
6480Sstevel@tonic-gate 		free(soft_des_ctx->des_cbc);
6490Sstevel@tonic-gate 		bzero(soft_des_ctx->key_sched, soft_des_ctx->keysched_len);
6500Sstevel@tonic-gate 		free(soft_des_ctx->key_sched);
6510Sstevel@tonic-gate 
6520Sstevel@tonic-gate 		break;
6530Sstevel@tonic-gate 	}
6540Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
6550Sstevel@tonic-gate 	{
6560Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
6570Sstevel@tonic-gate 
6580Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
6590Sstevel@tonic-gate 		/*
6600Sstevel@tonic-gate 		 * For CKM_AES_CBC_PAD, compute output length with
6610Sstevel@tonic-gate 		 * padding. If the remaining buffer has one block
6620Sstevel@tonic-gate 		 * of data, then output length will be two blocksize of
6630Sstevel@tonic-gate 		 * ciphertext. If the remaining buffer has less than
6640Sstevel@tonic-gate 		 * one block of data, then output length will be
6650Sstevel@tonic-gate 		 * one blocksize.
6660Sstevel@tonic-gate 		 */
6670Sstevel@tonic-gate 		if (soft_aes_ctx->remain_len == AES_BLOCK_LEN)
6680Sstevel@tonic-gate 			out_len = 2 * AES_BLOCK_LEN;
6690Sstevel@tonic-gate 		else
6700Sstevel@tonic-gate 			out_len = AES_BLOCK_LEN;
6710Sstevel@tonic-gate 
6720Sstevel@tonic-gate 		if (pLastEncryptedPart == NULL) {
6730Sstevel@tonic-gate 			/*
6740Sstevel@tonic-gate 			 * Application asks for the length of the output
6750Sstevel@tonic-gate 			 * buffer to hold the ciphertext.
6760Sstevel@tonic-gate 			 */
6770Sstevel@tonic-gate 			*pulLastEncryptedPartLen = out_len;
6780Sstevel@tonic-gate 			goto clean1;
6790Sstevel@tonic-gate 		} else {
6800Sstevel@tonic-gate 			crypto_data_t out;
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 			/* Copy remaining data to the output buffer. */
6830Sstevel@tonic-gate 			(void) memcpy(pLastEncryptedPart, soft_aes_ctx->data,
6840Sstevel@tonic-gate 			    soft_aes_ctx->remain_len);
6850Sstevel@tonic-gate 
6860Sstevel@tonic-gate 			/*
6870Sstevel@tonic-gate 			 * Add padding bytes prior to encrypt final.
6880Sstevel@tonic-gate 			 */
6890Sstevel@tonic-gate 			soft_add_pkcs7_padding(pLastEncryptedPart +
6900Sstevel@tonic-gate 			    soft_aes_ctx->remain_len, AES_BLOCK_LEN,
6910Sstevel@tonic-gate 			    soft_aes_ctx->remain_len);
6920Sstevel@tonic-gate 
6930Sstevel@tonic-gate 			out.cd_format = CRYPTO_DATA_RAW;
6940Sstevel@tonic-gate 			out.cd_offset = 0;
6950Sstevel@tonic-gate 			out.cd_length = out_len;
6960Sstevel@tonic-gate 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
6970Sstevel@tonic-gate 			out.cd_raw.iov_len = out_len;
6980Sstevel@tonic-gate 
6990Sstevel@tonic-gate 			/* Encrypt multiple blocks of data. */
7000Sstevel@tonic-gate 			rc = aes_encrypt_contiguous_blocks(
7010Sstevel@tonic-gate 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
7020Sstevel@tonic-gate 			    (char *)pLastEncryptedPart, out_len, &out);
7030Sstevel@tonic-gate 
7040Sstevel@tonic-gate 			if (rc == 0) {
7050Sstevel@tonic-gate 				*pulLastEncryptedPartLen = out_len;
7060Sstevel@tonic-gate 			} else {
7070Sstevel@tonic-gate 				*pulLastEncryptedPartLen = 0;
7080Sstevel@tonic-gate 				rv = CKR_FUNCTION_FAILED;
7090Sstevel@tonic-gate 			}
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 			/* Cleanup memory space. */
7120Sstevel@tonic-gate 			free(soft_aes_ctx->aes_cbc);
7130Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
7140Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
7150Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
7160Sstevel@tonic-gate 		}
7170Sstevel@tonic-gate 
7180Sstevel@tonic-gate 		break;
7190Sstevel@tonic-gate 	}
7200Sstevel@tonic-gate 	case CKM_AES_CBC:
7210Sstevel@tonic-gate 	case CKM_AES_ECB:
7220Sstevel@tonic-gate 	{
7230Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx;
7240Sstevel@tonic-gate 
7250Sstevel@tonic-gate 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
7260Sstevel@tonic-gate 		/*
7270Sstevel@tonic-gate 		 * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
7280Sstevel@tonic-gate 		 * so when the final is called, the remaining buffer
7290Sstevel@tonic-gate 		 * should not contain any more data.
7300Sstevel@tonic-gate 		 */
7310Sstevel@tonic-gate 		*pulLastEncryptedPartLen = 0;
7320Sstevel@tonic-gate 		if (soft_aes_ctx->remain_len != 0) {
7330Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
7340Sstevel@tonic-gate 		} else {
7350Sstevel@tonic-gate 			if (pLastEncryptedPart == NULL)
7360Sstevel@tonic-gate 				goto clean1;
7370Sstevel@tonic-gate 		}
7380Sstevel@tonic-gate 
7390Sstevel@tonic-gate 		/* Cleanup memory space. */
7400Sstevel@tonic-gate 		free(soft_aes_ctx->aes_cbc);
7410Sstevel@tonic-gate 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
7420Sstevel@tonic-gate 		free(soft_aes_ctx->key_sched);
7430Sstevel@tonic-gate 
7440Sstevel@tonic-gate 		break;
7450Sstevel@tonic-gate 	}
7467188Smcpowers 	case CKM_AES_CTR:
7477188Smcpowers 	{
7487188Smcpowers 		crypto_data_t out;
7497188Smcpowers 		soft_aes_ctx_t *soft_aes_ctx;
7507188Smcpowers 		ctr_ctx_t *ctr_ctx;
7517188Smcpowers 		size_t len;
7520Sstevel@tonic-gate 
7537188Smcpowers 		soft_aes_ctx = (soft_aes_ctx_t *)session_p->encrypt.context;
7547188Smcpowers 		ctr_ctx = soft_aes_ctx->aes_cbc;
7557188Smcpowers 		len = ctr_ctx->ctr_remainder_len;
7567188Smcpowers 
7577188Smcpowers 		if (pLastEncryptedPart == NULL) {
7587188Smcpowers 			*pulLastEncryptedPartLen = len;
7597188Smcpowers 			goto clean1;
7607188Smcpowers 		}
7617188Smcpowers 		if (len > 0) {
7627188Smcpowers 			out.cd_format = CRYPTO_DATA_RAW;
7637188Smcpowers 			out.cd_offset = 0;
7647188Smcpowers 			out.cd_length = len;
7657188Smcpowers 			out.cd_raw.iov_base = (char *)pLastEncryptedPart;
7667188Smcpowers 			out.cd_raw.iov_len = len;
7677188Smcpowers 
7687188Smcpowers 			rv = ctr_mode_final(ctr_ctx, &out, aes_encrypt_block);
7697188Smcpowers 		}
7707188Smcpowers 		if (rv == CRYPTO_BUFFER_TOO_SMALL) {
7717188Smcpowers 			*pulLastEncryptedPartLen = len;
7727188Smcpowers 			goto clean1;
7737188Smcpowers 		}
7747188Smcpowers 
7757188Smcpowers 		/* Cleanup memory space. */
7767188Smcpowers 		free(ctr_ctx);
7777188Smcpowers 		bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
7787188Smcpowers 		free(soft_aes_ctx->key_sched);
7797188Smcpowers 
7807188Smcpowers 		break;
7817188Smcpowers 	}
782676Sizick 	case CKM_BLOWFISH_CBC:
783676Sizick 	{
784676Sizick 		soft_blowfish_ctx_t *soft_blowfish_ctx;
785676Sizick 
786676Sizick 		soft_blowfish_ctx =
787676Sizick 		    (soft_blowfish_ctx_t *)session_p->encrypt.context;
788676Sizick 		/*
789676Sizick 		 * CKM_BLOWFISH_CBC does not do any padding, so when the
790676Sizick 		 * final is called, the remaining buffer should not contain
791676Sizick 		 * any more data
792676Sizick 		 */
793676Sizick 		*pulLastEncryptedPartLen = 0;
794676Sizick 		if (soft_blowfish_ctx->remain_len != 0)
795676Sizick 			rv = CKR_DATA_LEN_RANGE;
796676Sizick 		else {
797676Sizick 			if (pLastEncryptedPart == NULL)
798676Sizick 				goto clean1;
799676Sizick 		}
800676Sizick 
801676Sizick 		free(soft_blowfish_ctx->blowfish_cbc);
802676Sizick 		bzero(soft_blowfish_ctx->key_sched,
803676Sizick 		    soft_blowfish_ctx->keysched_len);
804676Sizick 		free(soft_blowfish_ctx->key_sched);
805676Sizick 		break;
806676Sizick 	}
807676Sizick 
8080Sstevel@tonic-gate 	case CKM_RC4:
8090Sstevel@tonic-gate 	{
8100Sstevel@tonic-gate 		ARCFour_key *key = (ARCFour_key *)session_p->encrypt.context;
81110287SZdenek.Kotala@Sun.COM 		/* Remaining data size is always zero for RC4. */
81210287SZdenek.Kotala@Sun.COM 		*pulLastEncryptedPartLen = 0;
81310287SZdenek.Kotala@Sun.COM 		if (pLastEncryptedPart == NULL)
81410287SZdenek.Kotala@Sun.COM 			goto clean1;
8150Sstevel@tonic-gate 		bzero(key, sizeof (*key));
8160Sstevel@tonic-gate 		break;
8170Sstevel@tonic-gate 	}
8180Sstevel@tonic-gate 	default:
8190Sstevel@tonic-gate 		/* PKCS11: The mechanism only supports single-part operation. */
8200Sstevel@tonic-gate 		rv = CKR_MECHANISM_INVALID;
8210Sstevel@tonic-gate 		break;
8220Sstevel@tonic-gate 	}
8230Sstevel@tonic-gate 
8240Sstevel@tonic-gate 	free(session_p->encrypt.context);
8250Sstevel@tonic-gate 	session_p->encrypt.context = NULL;
8260Sstevel@tonic-gate clean1:
8270Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
8280Sstevel@tonic-gate 
8290Sstevel@tonic-gate 	return (rv);
8300Sstevel@tonic-gate }
8310Sstevel@tonic-gate 
8320Sstevel@tonic-gate /*
8330Sstevel@tonic-gate  * This function frees the allocated active crypto context and the
8340Sstevel@tonic-gate  * lower level of allocated struct as needed.
8350Sstevel@tonic-gate  * This function is called by the 1st tier of encrypt/decrypt routines
8360Sstevel@tonic-gate  * or by the 2nd tier of session close routine. Since the 1st tier
8370Sstevel@tonic-gate  * caller will always call this function without locking the session
8380Sstevel@tonic-gate  * mutex and the 2nd tier caller will call with the lock, we add the
839*12573SDina.Nimeh@Sun.COM  * third parameter "lock_held" to distinguish this case.
8400Sstevel@tonic-gate  */
8410Sstevel@tonic-gate void
soft_crypt_cleanup(soft_session_t * session_p,boolean_t encrypt,boolean_t lock_held)8420Sstevel@tonic-gate soft_crypt_cleanup(soft_session_t *session_p, boolean_t encrypt,
8430Sstevel@tonic-gate 	boolean_t lock_held)
8440Sstevel@tonic-gate {
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 	crypto_active_op_t *active_op;
8470Sstevel@tonic-gate 	boolean_t lock_true = B_TRUE;
8480Sstevel@tonic-gate 
8490Sstevel@tonic-gate 	if (!lock_held)
8500Sstevel@tonic-gate 		(void) pthread_mutex_lock(&session_p->session_mutex);
8510Sstevel@tonic-gate 
8520Sstevel@tonic-gate 	active_op = (encrypt) ? &(session_p->encrypt) : &(session_p->decrypt);
8530Sstevel@tonic-gate 
8540Sstevel@tonic-gate 	switch (active_op->mech.mechanism) {
8550Sstevel@tonic-gate 
8560Sstevel@tonic-gate 	case CKM_DES_CBC_PAD:
8570Sstevel@tonic-gate 	case CKM_DES3_CBC_PAD:
8580Sstevel@tonic-gate 	case CKM_DES_CBC:
8590Sstevel@tonic-gate 	case CKM_DES_ECB:
8600Sstevel@tonic-gate 	case CKM_DES3_CBC:
8610Sstevel@tonic-gate 	case CKM_DES3_ECB:
8620Sstevel@tonic-gate 	{
8630Sstevel@tonic-gate 
8640Sstevel@tonic-gate 		soft_des_ctx_t *soft_des_ctx =
8650Sstevel@tonic-gate 		    (soft_des_ctx_t *)active_op->context;
8660Sstevel@tonic-gate 		des_ctx_t *des_ctx;
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 		if (soft_des_ctx != NULL) {
8690Sstevel@tonic-gate 			des_ctx = (des_ctx_t *)soft_des_ctx->des_cbc;
8700Sstevel@tonic-gate 			if (des_ctx != NULL) {
8710Sstevel@tonic-gate 				bzero(des_ctx->dc_keysched,
8720Sstevel@tonic-gate 				    des_ctx->dc_keysched_len);
8730Sstevel@tonic-gate 				free(soft_des_ctx->des_cbc);
8740Sstevel@tonic-gate 			}
8750Sstevel@tonic-gate 			bzero(soft_des_ctx->key_sched,
8760Sstevel@tonic-gate 			    soft_des_ctx->keysched_len);
8770Sstevel@tonic-gate 			free(soft_des_ctx->key_sched);
8780Sstevel@tonic-gate 		}
8790Sstevel@tonic-gate 		break;
8800Sstevel@tonic-gate 	}
8810Sstevel@tonic-gate 
8820Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
8830Sstevel@tonic-gate 	case CKM_AES_CBC:
8840Sstevel@tonic-gate 	case CKM_AES_ECB:
8850Sstevel@tonic-gate 	{
8860Sstevel@tonic-gate 		soft_aes_ctx_t *soft_aes_ctx =
8870Sstevel@tonic-gate 		    (soft_aes_ctx_t *)active_op->context;
8880Sstevel@tonic-gate 		aes_ctx_t *aes_ctx;
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 		if (soft_aes_ctx != NULL) {
8910Sstevel@tonic-gate 			aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
8920Sstevel@tonic-gate 			if (aes_ctx != NULL) {
8930Sstevel@tonic-gate 				bzero(aes_ctx->ac_keysched,
8940Sstevel@tonic-gate 				    aes_ctx->ac_keysched_len);
8950Sstevel@tonic-gate 				free(soft_aes_ctx->aes_cbc);
8960Sstevel@tonic-gate 			}
8970Sstevel@tonic-gate 			bzero(soft_aes_ctx->key_sched,
8980Sstevel@tonic-gate 			    soft_aes_ctx->keysched_len);
8990Sstevel@tonic-gate 			free(soft_aes_ctx->key_sched);
9000Sstevel@tonic-gate 		}
9010Sstevel@tonic-gate 		break;
9020Sstevel@tonic-gate 	}
9030Sstevel@tonic-gate 
904676Sizick 	case CKM_BLOWFISH_CBC:
905676Sizick 	{
906676Sizick 		soft_blowfish_ctx_t *soft_blowfish_ctx =
907676Sizick 		    (soft_blowfish_ctx_t *)active_op->context;
908676Sizick 		blowfish_ctx_t *blowfish_ctx;
909676Sizick 
910676Sizick 		if (soft_blowfish_ctx != NULL) {
911676Sizick 			blowfish_ctx =
912676Sizick 			    (blowfish_ctx_t *)soft_blowfish_ctx->blowfish_cbc;
913676Sizick 			if (blowfish_ctx != NULL) {
914676Sizick 				bzero(blowfish_ctx->bc_keysched,
915676Sizick 				    blowfish_ctx->bc_keysched_len);
916676Sizick 				free(soft_blowfish_ctx->blowfish_cbc);
917676Sizick 			}
918676Sizick 
919676Sizick 			bzero(soft_blowfish_ctx->key_sched,
920676Sizick 			    soft_blowfish_ctx->keysched_len);
921676Sizick 			free(soft_blowfish_ctx->key_sched);
922676Sizick 		}
923676Sizick 		break;
924676Sizick 	}
925676Sizick 
9260Sstevel@tonic-gate 	case CKM_RC4:
9270Sstevel@tonic-gate 	{
9280Sstevel@tonic-gate 		ARCFour_key *key = (ARCFour_key *)active_op->context;
9290Sstevel@tonic-gate 
9300Sstevel@tonic-gate 		if (key != NULL)
9310Sstevel@tonic-gate 			bzero(key, sizeof (*key));
9320Sstevel@tonic-gate 		break;
9330Sstevel@tonic-gate 	}
9340Sstevel@tonic-gate 
9350Sstevel@tonic-gate 	case CKM_RSA_X_509:
9360Sstevel@tonic-gate 	case CKM_RSA_PKCS:
9372940Sizick 	{
9382940Sizick 		soft_rsa_ctx_t *rsa_ctx =
9392940Sizick 		    (soft_rsa_ctx_t *)active_op->context;
9402940Sizick 
9412940Sizick 		if (rsa_ctx != NULL)
9422940Sizick 			if (rsa_ctx->key != NULL) {
9432940Sizick 				soft_cleanup_object(rsa_ctx->key);
9442940Sizick 				free(rsa_ctx->key);
9452940Sizick 			}
9462940Sizick 
9470Sstevel@tonic-gate 		break;
9482940Sizick 	}
9490Sstevel@tonic-gate 
9500Sstevel@tonic-gate 	} /* switch */
9510Sstevel@tonic-gate 
9520Sstevel@tonic-gate 	if (active_op->context != NULL) {
9530Sstevel@tonic-gate 		free(active_op->context);
9540Sstevel@tonic-gate 		active_op->context = NULL;
9550Sstevel@tonic-gate 	}
9560Sstevel@tonic-gate 
9570Sstevel@tonic-gate 	active_op->flags = 0;
9580Sstevel@tonic-gate 
9590Sstevel@tonic-gate 	if (!lock_held)
9600Sstevel@tonic-gate 		SES_REFRELE(session_p, lock_true);
9610Sstevel@tonic-gate }
962