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
55862Smcpowers  * Common Development and Distribution License (the "License").
65862Smcpowers  * 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>
320Sstevel@tonic-gate #include "softSession.h"
330Sstevel@tonic-gate #include "softObject.h"
340Sstevel@tonic-gate #include "softCrypt.h"
357188Smcpowers #include <aes_impl.h>
360Sstevel@tonic-gate 
370Sstevel@tonic-gate /*
380Sstevel@tonic-gate  * Allocate context for the active encryption or decryption operation, and
390Sstevel@tonic-gate  * generate AES key schedule to speed up the operation.
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate CK_RV
soft_aes_crypt_init_common(soft_session_t * session_p,CK_MECHANISM_PTR pMechanism,soft_object_t * key_p,boolean_t encrypt)420Sstevel@tonic-gate soft_aes_crypt_init_common(soft_session_t *session_p,
430Sstevel@tonic-gate     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
440Sstevel@tonic-gate     boolean_t encrypt)
450Sstevel@tonic-gate {
460Sstevel@tonic-gate 	size_t size;
470Sstevel@tonic-gate 	soft_aes_ctx_t *soft_aes_ctx;
480Sstevel@tonic-gate 
490Sstevel@tonic-gate 	soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t));
500Sstevel@tonic-gate 	if (soft_aes_ctx == NULL) {
510Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
520Sstevel@tonic-gate 	}
530Sstevel@tonic-gate 
540Sstevel@tonic-gate 	soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
550Sstevel@tonic-gate 
560Sstevel@tonic-gate 	if (soft_aes_ctx->key_sched == NULL) {
570Sstevel@tonic-gate 		free(soft_aes_ctx);
580Sstevel@tonic-gate 		return (CKR_HOST_MEMORY);
590Sstevel@tonic-gate 	}
600Sstevel@tonic-gate 
610Sstevel@tonic-gate 	soft_aes_ctx->keysched_len = size;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
640Sstevel@tonic-gate 	if (encrypt) {
650Sstevel@tonic-gate 		/* Called by C_EncryptInit. */
660Sstevel@tonic-gate 		session_p->encrypt.context = soft_aes_ctx;
670Sstevel@tonic-gate 		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
680Sstevel@tonic-gate 	} else {
690Sstevel@tonic-gate 		/* Called by C_DecryptInit. */
700Sstevel@tonic-gate 		session_p->decrypt.context = soft_aes_ctx;
710Sstevel@tonic-gate 		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
720Sstevel@tonic-gate 	}
730Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
740Sstevel@tonic-gate 
750Sstevel@tonic-gate 	/*
760Sstevel@tonic-gate 	 * If this is a non-sensitive key and it does NOT have
770Sstevel@tonic-gate 	 * a key schedule yet, then allocate one and expand it.
780Sstevel@tonic-gate 	 * Otherwise, if it's a non-sensitive key, and it DOES have
790Sstevel@tonic-gate 	 * a key schedule already attached to it, just copy the
800Sstevel@tonic-gate 	 * pre-expanded schedule to the context and avoid the
810Sstevel@tonic-gate 	 * extra key schedule expansion operation.
820Sstevel@tonic-gate 	 */
830Sstevel@tonic-gate 	if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
845862Smcpowers 		if (OBJ_KEY_SCHED(key_p) == NULL) {
850Sstevel@tonic-gate 			void *ks;
865862Smcpowers 
875862Smcpowers 			(void) pthread_mutex_lock(&key_p->object_mutex);
885862Smcpowers 			if (OBJ_KEY_SCHED(key_p) == NULL) {
895862Smcpowers 				ks = aes_alloc_keysched(&size, 0);
905862Smcpowers 				if (ks == NULL) {
915862Smcpowers 					(void) pthread_mutex_unlock(
925862Smcpowers 					    &key_p->object_mutex);
935862Smcpowers 					free(soft_aes_ctx);
945862Smcpowers 					return (CKR_HOST_MEMORY);
955862Smcpowers 				}
965862Smcpowers #ifdef	__sparcv9
975862Smcpowers 				/* LINTED */
985862Smcpowers 				aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
995862Smcpowers 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
1005862Smcpowers #else	/* !__sparcv9 */
1015862Smcpowers 				aes_init_keysched(OBJ_SEC_VALUE(key_p),
1025862Smcpowers 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
1035862Smcpowers #endif	/* __sparcv9 */
1045862Smcpowers 				OBJ_KEY_SCHED_LEN(key_p) = size;
1055862Smcpowers 				OBJ_KEY_SCHED(key_p) = ks;
1060Sstevel@tonic-gate 			}
1075862Smcpowers 			(void) pthread_mutex_unlock(&key_p->object_mutex);
1080Sstevel@tonic-gate 		}
1090Sstevel@tonic-gate 		(void) memcpy(soft_aes_ctx->key_sched, OBJ_KEY_SCHED(key_p),
1105862Smcpowers 		    OBJ_KEY_SCHED_LEN(key_p));
1110Sstevel@tonic-gate 		soft_aes_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
1120Sstevel@tonic-gate 	} else {
1130Sstevel@tonic-gate 		/*
1140Sstevel@tonic-gate 		 * Initialize key schedule for AES. aes_init_keysched()
1150Sstevel@tonic-gate 		 * requires key length in bits.
1160Sstevel@tonic-gate 		 */
1170Sstevel@tonic-gate #ifdef	__sparcv9
1180Sstevel@tonic-gate 		/* LINTED */
1190Sstevel@tonic-gate 		aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
1205862Smcpowers 		    (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
1210Sstevel@tonic-gate #else	/* !__sparcv9 */
1220Sstevel@tonic-gate 		aes_init_keysched(OBJ_SEC_VALUE(key_p),
1235862Smcpowers 		    (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
1240Sstevel@tonic-gate #endif	/* __sparcv9 */
1250Sstevel@tonic-gate 	}
1260Sstevel@tonic-gate 	return (CKR_OK);
1270Sstevel@tonic-gate }
1280Sstevel@tonic-gate 
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate /*
1310Sstevel@tonic-gate  * soft_aes_encrypt_common()
1320Sstevel@tonic-gate  *
1330Sstevel@tonic-gate  * Arguments:
1340Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
1350Sstevel@tonic-gate  *	pData:		pointer to the input data to be encrypted
1360Sstevel@tonic-gate  *	ulDataLen:	length of the input data
1370Sstevel@tonic-gate  *	pEncrypted:	pointer to the output data after encryption
1380Sstevel@tonic-gate  *	pulEncryptedLen: pointer to the length of the output data
1390Sstevel@tonic-gate  *	update:		boolean flag indicates caller is soft_encrypt
1400Sstevel@tonic-gate  *			or soft_encrypt_update
1410Sstevel@tonic-gate  *
1420Sstevel@tonic-gate  * Description:
1430Sstevel@tonic-gate  *      This function calls the corresponding encrypt routine based
1440Sstevel@tonic-gate  *	on the mechanism.
1450Sstevel@tonic-gate  *
1460Sstevel@tonic-gate  * Returns:
1470Sstevel@tonic-gate  *      CKR_OK: success
1480Sstevel@tonic-gate  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
1490Sstevel@tonic-gate  *			      is too small
1500Sstevel@tonic-gate  *	CKR_FUNCTION_FAILED: encrypt function failed
1510Sstevel@tonic-gate  *	CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
1520Sstevel@tonic-gate  */
1530Sstevel@tonic-gate CK_RV
soft_aes_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)1540Sstevel@tonic-gate soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
1550Sstevel@tonic-gate     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
1560Sstevel@tonic-gate     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
1570Sstevel@tonic-gate {
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	int rc = 0;
1600Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
1610Sstevel@tonic-gate 	soft_aes_ctx_t *soft_aes_ctx =
1620Sstevel@tonic-gate 	    (soft_aes_ctx_t *)session_p->encrypt.context;
1630Sstevel@tonic-gate 	aes_ctx_t *aes_ctx;
1640Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
1650Sstevel@tonic-gate 	CK_BYTE *in_buf = NULL;
1660Sstevel@tonic-gate 	CK_BYTE *out_buf = NULL;
1670Sstevel@tonic-gate 	CK_ULONG out_len;
1680Sstevel@tonic-gate 	CK_ULONG total_len;
1690Sstevel@tonic-gate 	CK_ULONG remain;
1700Sstevel@tonic-gate 
1717188Smcpowers 	if (mechanism == CKM_AES_CTR)
1727188Smcpowers 		goto do_encryption;
1737188Smcpowers 
1740Sstevel@tonic-gate 	/*
1750Sstevel@tonic-gate 	 * AES only takes input length that is a multiple of blocksize
1760Sstevel@tonic-gate 	 * for C_Encrypt function with the mechanism CKM_AES_ECB or
1770Sstevel@tonic-gate 	 * CKM_AES_CBC.
1780Sstevel@tonic-gate 	 *
1790Sstevel@tonic-gate 	 * AES allows any input length for C_Encrypt function with the
1800Sstevel@tonic-gate 	 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function.
1810Sstevel@tonic-gate 	 */
1820Sstevel@tonic-gate 	if ((!update) && (mechanism != CKM_AES_CBC_PAD)) {
1830Sstevel@tonic-gate 		if ((ulDataLen % AES_BLOCK_LEN) != 0) {
1840Sstevel@tonic-gate 			rv = CKR_DATA_LEN_RANGE;
1850Sstevel@tonic-gate 			goto cleanup;
1860Sstevel@tonic-gate 		}
1870Sstevel@tonic-gate 	}
1880Sstevel@tonic-gate 
1890Sstevel@tonic-gate 	if (!update) {
1900Sstevel@tonic-gate 		/*
1910Sstevel@tonic-gate 		 * Called by C_Encrypt
1920Sstevel@tonic-gate 		 */
1930Sstevel@tonic-gate 		if (mechanism == CKM_AES_CBC_PAD) {
1940Sstevel@tonic-gate 			/*
1950Sstevel@tonic-gate 			 * For CKM_AES_CBC_PAD, compute output length to
1960Sstevel@tonic-gate 			 * count for the padding. If the length of input
1970Sstevel@tonic-gate 			 * data is a multiple of blocksize, then make output
1980Sstevel@tonic-gate 			 * length to be the sum of the input length and
1990Sstevel@tonic-gate 			 * one blocksize. Otherwise, output length will
2000Sstevel@tonic-gate 			 * be rounded up to the next multiple of blocksize.
2010Sstevel@tonic-gate 			 */
2020Sstevel@tonic-gate 			out_len = AES_BLOCK_LEN *
2030Sstevel@tonic-gate 			    (ulDataLen / AES_BLOCK_LEN + 1);
2040Sstevel@tonic-gate 		} else {
2050Sstevel@tonic-gate 			/*
2060Sstevel@tonic-gate 			 * For non-padding mode, the output length will
2070Sstevel@tonic-gate 			 * be same as the input length.
2080Sstevel@tonic-gate 			 */
2090Sstevel@tonic-gate 			out_len = ulDataLen;
2100Sstevel@tonic-gate 		}
2110Sstevel@tonic-gate 
2120Sstevel@tonic-gate 		/*
2130Sstevel@tonic-gate 		 * If application asks for the length of the output buffer
2140Sstevel@tonic-gate 		 * to hold the ciphertext?
2150Sstevel@tonic-gate 		 */
2160Sstevel@tonic-gate 		if (pEncrypted == NULL) {
2170Sstevel@tonic-gate 			*pulEncryptedLen = out_len;
2180Sstevel@tonic-gate 			return (CKR_OK);
2190Sstevel@tonic-gate 		}
2200Sstevel@tonic-gate 
2210Sstevel@tonic-gate 		/* Is the application-supplied buffer large enough? */
2220Sstevel@tonic-gate 		if (*pulEncryptedLen < out_len) {
2230Sstevel@tonic-gate 			*pulEncryptedLen = out_len;
2240Sstevel@tonic-gate 			return (CKR_BUFFER_TOO_SMALL);
2250Sstevel@tonic-gate 		}
2260Sstevel@tonic-gate 
2270Sstevel@tonic-gate 		/* Encrypt pad bytes in a separate operation */
2280Sstevel@tonic-gate 		if (mechanism == CKM_AES_CBC_PAD) {
2290Sstevel@tonic-gate 			out_len -= AES_BLOCK_LEN;
2300Sstevel@tonic-gate 		}
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 		in_buf = pData;
2330Sstevel@tonic-gate 		out_buf = pEncrypted;
2340Sstevel@tonic-gate 	} else {
2350Sstevel@tonic-gate 		/*
2360Sstevel@tonic-gate 		 * Called by C_EncryptUpdate
2370Sstevel@tonic-gate 		 *
2380Sstevel@tonic-gate 		 * Add the lengths of last remaining data and current
2390Sstevel@tonic-gate 		 * plaintext together to get the total input length.
2400Sstevel@tonic-gate 		 */
2410Sstevel@tonic-gate 		total_len = soft_aes_ctx->remain_len + ulDataLen;
2420Sstevel@tonic-gate 
2430Sstevel@tonic-gate 		/*
2440Sstevel@tonic-gate 		 * If the total input length is less than one blocksize,
2450Sstevel@tonic-gate 		 * or if the total input length is just one blocksize and
2460Sstevel@tonic-gate 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
2470Sstevel@tonic-gate 		 * encryption until when more data comes in next
2480Sstevel@tonic-gate 		 * C_EncryptUpdate or when C_EncryptFinal is called.
2490Sstevel@tonic-gate 		 */
2500Sstevel@tonic-gate 		if ((total_len < AES_BLOCK_LEN) ||
2510Sstevel@tonic-gate 		    ((mechanism == CKM_AES_CBC_PAD) &&
2520Sstevel@tonic-gate 		    (total_len == AES_BLOCK_LEN))) {
2530Sstevel@tonic-gate 			if (pEncrypted != NULL) {
2540Sstevel@tonic-gate 				/*
2550Sstevel@tonic-gate 				 * Save input data and its length in
2560Sstevel@tonic-gate 				 * the remaining buffer of AES context.
2570Sstevel@tonic-gate 				 */
2580Sstevel@tonic-gate 				(void) memcpy(soft_aes_ctx->data +
2590Sstevel@tonic-gate 				    soft_aes_ctx->remain_len, pData, ulDataLen);
2600Sstevel@tonic-gate 				soft_aes_ctx->remain_len += ulDataLen;
2610Sstevel@tonic-gate 			}
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 			/* Set encrypted data length to 0. */
2640Sstevel@tonic-gate 			*pulEncryptedLen = 0;
2650Sstevel@tonic-gate 			return (CKR_OK);
2660Sstevel@tonic-gate 		}
2670Sstevel@tonic-gate 
2680Sstevel@tonic-gate 		/* Compute the length of remaing data. */
2690Sstevel@tonic-gate 		remain = total_len % AES_BLOCK_LEN;
2700Sstevel@tonic-gate 
2710Sstevel@tonic-gate 		/*
2720Sstevel@tonic-gate 		 * Make sure that the output length is a multiple of
2730Sstevel@tonic-gate 		 * blocksize.
2740Sstevel@tonic-gate 		 */
2750Sstevel@tonic-gate 		out_len = total_len - remain;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 		/*
2780Sstevel@tonic-gate 		 * If application asks for the length of the output buffer
2790Sstevel@tonic-gate 		 * to hold the ciphertext?
2800Sstevel@tonic-gate 		 */
2810Sstevel@tonic-gate 		if (pEncrypted == NULL) {
2820Sstevel@tonic-gate 			*pulEncryptedLen = out_len;
2830Sstevel@tonic-gate 			return (CKR_OK);
2840Sstevel@tonic-gate 		}
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 		/* Is the application-supplied buffer large enough? */
2870Sstevel@tonic-gate 		if (*pulEncryptedLen < out_len) {
2880Sstevel@tonic-gate 			*pulEncryptedLen = out_len;
2890Sstevel@tonic-gate 			return (CKR_BUFFER_TOO_SMALL);
2900Sstevel@tonic-gate 		}
2910Sstevel@tonic-gate 
2920Sstevel@tonic-gate 		if (soft_aes_ctx->remain_len != 0) {
2930Sstevel@tonic-gate 			/*
2940Sstevel@tonic-gate 			 * Copy last remaining data and current input data
2950Sstevel@tonic-gate 			 * to the output buffer.
2960Sstevel@tonic-gate 			 */
2970Sstevel@tonic-gate 			(void) memmove(pEncrypted + soft_aes_ctx->remain_len,
2980Sstevel@tonic-gate 			    pData, out_len - soft_aes_ctx->remain_len);
2990Sstevel@tonic-gate 			(void) memcpy(pEncrypted, soft_aes_ctx->data,
3000Sstevel@tonic-gate 			    soft_aes_ctx->remain_len);
3010Sstevel@tonic-gate 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
3020Sstevel@tonic-gate 
3030Sstevel@tonic-gate 			in_buf = pEncrypted;
3040Sstevel@tonic-gate 		} else {
3050Sstevel@tonic-gate 			in_buf = pData;
3060Sstevel@tonic-gate 		}
3070Sstevel@tonic-gate 		out_buf = pEncrypted;
3080Sstevel@tonic-gate 	}
3090Sstevel@tonic-gate 
3107188Smcpowers do_encryption:
3110Sstevel@tonic-gate 	/*
3120Sstevel@tonic-gate 	 * Begin Encryption now.
3130Sstevel@tonic-gate 	 */
3140Sstevel@tonic-gate 	switch (mechanism) {
3150Sstevel@tonic-gate 
3160Sstevel@tonic-gate 	case CKM_AES_ECB:
3170Sstevel@tonic-gate 	{
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 		ulong_t i;
3200Sstevel@tonic-gate 		uint8_t *tmp_inbuf;
3210Sstevel@tonic-gate 		uint8_t *tmp_outbuf;
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
3240Sstevel@tonic-gate 			tmp_inbuf = &in_buf[i];
3250Sstevel@tonic-gate 			tmp_outbuf = &out_buf[i];
3260Sstevel@tonic-gate 			/* Crunch one block of data for AES. */
3277188Smcpowers 			(void) aes_encrypt_block(soft_aes_ctx->key_sched,
3280Sstevel@tonic-gate 			    tmp_inbuf, tmp_outbuf);
3290Sstevel@tonic-gate 		}
3300Sstevel@tonic-gate 
3310Sstevel@tonic-gate 		if (update) {
3320Sstevel@tonic-gate 			/*
3330Sstevel@tonic-gate 			 * For encrypt update, if there is a remaining
3340Sstevel@tonic-gate 			 * data, save it and its length in the context.
3350Sstevel@tonic-gate 			 */
3360Sstevel@tonic-gate 			if (remain != 0)
3370Sstevel@tonic-gate 				(void) memcpy(soft_aes_ctx->data, pData +
3380Sstevel@tonic-gate 				    (ulDataLen - remain), remain);
3390Sstevel@tonic-gate 			soft_aes_ctx->remain_len = remain;
3400Sstevel@tonic-gate 		}
3410Sstevel@tonic-gate 
3420Sstevel@tonic-gate 		*pulEncryptedLen = out_len;
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 		break;
3450Sstevel@tonic-gate 	}
3460Sstevel@tonic-gate 
3470Sstevel@tonic-gate 	case CKM_AES_CBC:
3480Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
3490Sstevel@tonic-gate 	{
3500Sstevel@tonic-gate 		crypto_data_t out;
3510Sstevel@tonic-gate 
3520Sstevel@tonic-gate 		out.cd_format = CRYPTO_DATA_RAW;
3530Sstevel@tonic-gate 		out.cd_offset = 0;
3540Sstevel@tonic-gate 		out.cd_length = out_len;
3550Sstevel@tonic-gate 		out.cd_raw.iov_base = (char *)out_buf;
3560Sstevel@tonic-gate 		out.cd_raw.iov_len = out_len;
3570Sstevel@tonic-gate 
3580Sstevel@tonic-gate 		/* Encrypt multiple blocks of data. */
3590Sstevel@tonic-gate 		rc = aes_encrypt_contiguous_blocks(
3600Sstevel@tonic-gate 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
3610Sstevel@tonic-gate 		    (char *)in_buf, out_len, &out);
3620Sstevel@tonic-gate 
3630Sstevel@tonic-gate 		if (rc != 0)
3640Sstevel@tonic-gate 			goto encrypt_failed;
3650Sstevel@tonic-gate 
3660Sstevel@tonic-gate 		if (update) {
3670Sstevel@tonic-gate 			/*
3680Sstevel@tonic-gate 			 * For encrypt update, if there is remaining data,
3690Sstevel@tonic-gate 			 * save it and its length in the context.
3700Sstevel@tonic-gate 			 */
3710Sstevel@tonic-gate 			if (remain != 0)
3720Sstevel@tonic-gate 				(void) memcpy(soft_aes_ctx->data, pData +
3730Sstevel@tonic-gate 				    (ulDataLen - remain), remain);
3740Sstevel@tonic-gate 			soft_aes_ctx->remain_len = remain;
3750Sstevel@tonic-gate 		} else if (mechanism == CKM_AES_CBC_PAD) {
3760Sstevel@tonic-gate 			/*
3770Sstevel@tonic-gate 			 * Save the remainder of the input
3780Sstevel@tonic-gate 			 * block in a temporary block because
3790Sstevel@tonic-gate 			 * we dont want to overrun the buffer
3800Sstevel@tonic-gate 			 * by tacking on pad bytes.
3810Sstevel@tonic-gate 			 */
3820Sstevel@tonic-gate 			CK_BYTE tmpblock[AES_BLOCK_LEN];
3830Sstevel@tonic-gate 			(void) memcpy(tmpblock, in_buf + out_len,
3845862Smcpowers 			    ulDataLen - out_len);
3850Sstevel@tonic-gate 			soft_add_pkcs7_padding(tmpblock +
3865862Smcpowers 			    (ulDataLen - out_len),
3875862Smcpowers 			    AES_BLOCK_LEN, ulDataLen - out_len);
3880Sstevel@tonic-gate 
3890Sstevel@tonic-gate 			out.cd_offset = out_len;
3900Sstevel@tonic-gate 			out.cd_length = AES_BLOCK_LEN;
3910Sstevel@tonic-gate 			out.cd_raw.iov_base = (char *)out_buf;
3920Sstevel@tonic-gate 			out.cd_raw.iov_len = out_len + AES_BLOCK_LEN;
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 			/* Encrypt last block containing pad bytes. */
3950Sstevel@tonic-gate 			rc = aes_encrypt_contiguous_blocks(
3960Sstevel@tonic-gate 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
3970Sstevel@tonic-gate 			    (char *)tmpblock, AES_BLOCK_LEN, &out);
3980Sstevel@tonic-gate 
3990Sstevel@tonic-gate 			out_len += AES_BLOCK_LEN;
4000Sstevel@tonic-gate 		}
4010Sstevel@tonic-gate 
4020Sstevel@tonic-gate 		if (rc == 0) {
4030Sstevel@tonic-gate 			*pulEncryptedLen = out_len;
4040Sstevel@tonic-gate 			break;
4050Sstevel@tonic-gate 		}
4060Sstevel@tonic-gate encrypt_failed:
4070Sstevel@tonic-gate 		*pulEncryptedLen = 0;
4080Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
4090Sstevel@tonic-gate 		goto cleanup;
4100Sstevel@tonic-gate 	}
4117188Smcpowers 	case CKM_AES_CTR:
4127188Smcpowers 	{
4137188Smcpowers 		crypto_data_t out;
4147188Smcpowers 
4157188Smcpowers 		out.cd_format = CRYPTO_DATA_RAW;
4167188Smcpowers 		out.cd_offset = 0;
4177188Smcpowers 		out.cd_length = *pulEncryptedLen;
4187188Smcpowers 		out.cd_raw.iov_base = (char *)pEncrypted;
4197188Smcpowers 		out.cd_raw.iov_len = *pulEncryptedLen;
4207188Smcpowers 
4217188Smcpowers 		rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
4227188Smcpowers 		    (char *)pData, ulDataLen, &out);
4237188Smcpowers 
4247188Smcpowers 		if (rc != 0) {
4257188Smcpowers 			*pulEncryptedLen = 0;
4267188Smcpowers 			rv = CKR_FUNCTION_FAILED;
4277188Smcpowers 			goto cleanup;
4287188Smcpowers 		}
4297188Smcpowers 		/*
4307188Smcpowers 		 * Since AES counter mode is a stream cipher, we call
4317188Smcpowers 		 * aes_counter_final() to pick up any remaining bytes.
4327188Smcpowers 		 * It is an internal function that does not destroy
4337188Smcpowers 		 * the context like *normal* final routines.
4347188Smcpowers 		 */
4357188Smcpowers 		if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0)
4367188Smcpowers 			rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
4377188Smcpowers 			    aes_encrypt_block);
4387188Smcpowers 	}
4390Sstevel@tonic-gate 	} /* end switch */
4400Sstevel@tonic-gate 
4410Sstevel@tonic-gate 	if (update)
4420Sstevel@tonic-gate 		return (CKR_OK);
4430Sstevel@tonic-gate 
4440Sstevel@tonic-gate 	/*
4450Sstevel@tonic-gate 	 * The following code will be executed if the caller is
4460Sstevel@tonic-gate 	 * soft_encrypt() or an error occurred. The encryption
4470Sstevel@tonic-gate 	 * operation will be terminated so we need to do some cleanup.
4480Sstevel@tonic-gate 	 */
4490Sstevel@tonic-gate cleanup:
4500Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
4510Sstevel@tonic-gate 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
4520Sstevel@tonic-gate 	if (aes_ctx != NULL) {
4530Sstevel@tonic-gate 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
4540Sstevel@tonic-gate 		free(soft_aes_ctx->aes_cbc);
4550Sstevel@tonic-gate 	}
4560Sstevel@tonic-gate 
4570Sstevel@tonic-gate 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
4580Sstevel@tonic-gate 	free(soft_aes_ctx->key_sched);
4590Sstevel@tonic-gate 	free(session_p->encrypt.context);
4600Sstevel@tonic-gate 	session_p->encrypt.context = NULL;
4610Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
4620Sstevel@tonic-gate 
4630Sstevel@tonic-gate 	return (rv);
4640Sstevel@tonic-gate }
4650Sstevel@tonic-gate 
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate /*
4680Sstevel@tonic-gate  * soft_aes_decrypt_common()
4690Sstevel@tonic-gate  *
4700Sstevel@tonic-gate  * Arguments:
4710Sstevel@tonic-gate  *      session_p:	pointer to soft_session_t struct
4720Sstevel@tonic-gate  *	pEncrypted:	pointer to the input data to be decrypted
4730Sstevel@tonic-gate  *	ulEncryptedLen:	length of the input data
4740Sstevel@tonic-gate  *	pData:		pointer to the output data
4750Sstevel@tonic-gate  *	pulDataLen:	pointer to the length of the output data
4760Sstevel@tonic-gate  *	Update:		boolean flag indicates caller is soft_decrypt
4770Sstevel@tonic-gate  *			or soft_decrypt_update
4780Sstevel@tonic-gate  *
4790Sstevel@tonic-gate  * Description:
4800Sstevel@tonic-gate  *      This function calls the corresponding decrypt routine based
4810Sstevel@tonic-gate  *	on the mechanism.
4820Sstevel@tonic-gate  *
4830Sstevel@tonic-gate  * Returns:
4840Sstevel@tonic-gate  *      CKR_OK: success
4850Sstevel@tonic-gate  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
4860Sstevel@tonic-gate  *			      is too small
4870Sstevel@tonic-gate  *	CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
4880Sstevel@tonic-gate  *				      of blocksize
4890Sstevel@tonic-gate  *	CKR_FUNCTION_FAILED: decrypt function failed
4900Sstevel@tonic-gate  */
4910Sstevel@tonic-gate CK_RV
soft_aes_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)4920Sstevel@tonic-gate soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
4930Sstevel@tonic-gate     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
4940Sstevel@tonic-gate     CK_ULONG_PTR pulDataLen, boolean_t update)
4950Sstevel@tonic-gate {
4960Sstevel@tonic-gate 
4970Sstevel@tonic-gate 	int rc = 0;
4980Sstevel@tonic-gate 	CK_RV rv = CKR_OK;
4990Sstevel@tonic-gate 	soft_aes_ctx_t *soft_aes_ctx =
5000Sstevel@tonic-gate 	    (soft_aes_ctx_t *)session_p->decrypt.context;
5010Sstevel@tonic-gate 	aes_ctx_t *aes_ctx;
5020Sstevel@tonic-gate 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
5030Sstevel@tonic-gate 	CK_BYTE *in_buf = NULL;
5040Sstevel@tonic-gate 	CK_BYTE *out_buf = NULL;
5050Sstevel@tonic-gate 	CK_ULONG out_len;
5060Sstevel@tonic-gate 	CK_ULONG total_len;
5070Sstevel@tonic-gate 	CK_ULONG remain;
5080Sstevel@tonic-gate 
5097188Smcpowers 	if (mechanism == CKM_AES_CTR)
5107188Smcpowers 		goto do_decryption;
5117188Smcpowers 
5120Sstevel@tonic-gate 	/*
5130Sstevel@tonic-gate 	 * AES only takes input length that is a multiple of 16 bytes
5140Sstevel@tonic-gate 	 * for C_Decrypt function with the mechanism CKM_AES_ECB,
5150Sstevel@tonic-gate 	 * CKM_AES_CBC or CKM_AES_CBC_PAD.
5160Sstevel@tonic-gate 	 *
5170Sstevel@tonic-gate 	 * AES allows any input length for C_DecryptUpdate function.
5180Sstevel@tonic-gate 	 */
5190Sstevel@tonic-gate 	if (!update) {
5200Sstevel@tonic-gate 		/*
5210Sstevel@tonic-gate 		 * Called by C_Decrypt
5220Sstevel@tonic-gate 		 */
5230Sstevel@tonic-gate 		if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
5240Sstevel@tonic-gate 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
5250Sstevel@tonic-gate 			goto cleanup;
5260Sstevel@tonic-gate 		}
5270Sstevel@tonic-gate 
5280Sstevel@tonic-gate 		/*
5290Sstevel@tonic-gate 		 * If application asks for the length of the output buffer
5300Sstevel@tonic-gate 		 * to hold the plaintext?
5310Sstevel@tonic-gate 		 */
5320Sstevel@tonic-gate 		if (pData == NULL) {
5330Sstevel@tonic-gate 			*pulDataLen = ulEncryptedLen;
5340Sstevel@tonic-gate 			return (CKR_OK);
5350Sstevel@tonic-gate 		}
5360Sstevel@tonic-gate 
5370Sstevel@tonic-gate 		/* Is the application-supplied buffer large enough? */
5380Sstevel@tonic-gate 		if (mechanism != CKM_AES_CBC_PAD) {
5390Sstevel@tonic-gate 			if (*pulDataLen < ulEncryptedLen) {
5400Sstevel@tonic-gate 				*pulDataLen = ulEncryptedLen;
5410Sstevel@tonic-gate 				return (CKR_BUFFER_TOO_SMALL);
5420Sstevel@tonic-gate 			}
5430Sstevel@tonic-gate 			out_len = ulEncryptedLen;
5440Sstevel@tonic-gate 		} else {
5450Sstevel@tonic-gate 			/*
5460Sstevel@tonic-gate 			 * For CKM_AES_CBC_PAD, we don't know how
5470Sstevel@tonic-gate 			 * many bytes for padding at this time, so
5480Sstevel@tonic-gate 			 * we'd assume one block was padded.
5490Sstevel@tonic-gate 			 */
5500Sstevel@tonic-gate 			if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
5510Sstevel@tonic-gate 				*pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
5520Sstevel@tonic-gate 				return (CKR_BUFFER_TOO_SMALL);
5530Sstevel@tonic-gate 			}
5540Sstevel@tonic-gate 			out_len = ulEncryptedLen - AES_BLOCK_LEN;
5550Sstevel@tonic-gate 		}
5560Sstevel@tonic-gate 		in_buf = pEncrypted;
5570Sstevel@tonic-gate 		out_buf = pData;
5580Sstevel@tonic-gate 	} else {
5590Sstevel@tonic-gate 		/*
5600Sstevel@tonic-gate 		 *  Called by C_DecryptUpdate
5610Sstevel@tonic-gate 		 *
5620Sstevel@tonic-gate 		 * Add the lengths of last remaining data and current
5630Sstevel@tonic-gate 		 * input data together to get the total input length.
5640Sstevel@tonic-gate 		 */
5650Sstevel@tonic-gate 		total_len = soft_aes_ctx->remain_len + ulEncryptedLen;
5660Sstevel@tonic-gate 
5670Sstevel@tonic-gate 		/*
5680Sstevel@tonic-gate 		 * If the total input length is less than one blocksize,
5690Sstevel@tonic-gate 		 * or if the total input length is just one blocksize and
5700Sstevel@tonic-gate 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
5710Sstevel@tonic-gate 		 * decryption until when more data comes in next
5720Sstevel@tonic-gate 		 * C_DecryptUpdate or when C_DecryptFinal is called.
5730Sstevel@tonic-gate 		 */
5740Sstevel@tonic-gate 		if ((total_len < AES_BLOCK_LEN) ||
5750Sstevel@tonic-gate 		    ((mechanism == CKM_AES_CBC_PAD) &&
5760Sstevel@tonic-gate 		    (total_len == AES_BLOCK_LEN))) {
5770Sstevel@tonic-gate 			if (pData != NULL) {
5780Sstevel@tonic-gate 				/*
5790Sstevel@tonic-gate 				 * Save input data and its length in
5800Sstevel@tonic-gate 				 * the remaining buffer of AES context.
5810Sstevel@tonic-gate 				 */
5820Sstevel@tonic-gate 				(void) memcpy(soft_aes_ctx->data +
5830Sstevel@tonic-gate 				    soft_aes_ctx->remain_len,
5840Sstevel@tonic-gate 				    pEncrypted, ulEncryptedLen);
5850Sstevel@tonic-gate 				soft_aes_ctx->remain_len += ulEncryptedLen;
5860Sstevel@tonic-gate 			}
5870Sstevel@tonic-gate 
5880Sstevel@tonic-gate 			/* Set output data length to 0. */
5890Sstevel@tonic-gate 			*pulDataLen = 0;
5900Sstevel@tonic-gate 			return (CKR_OK);
5910Sstevel@tonic-gate 		}
5920Sstevel@tonic-gate 
5930Sstevel@tonic-gate 		/* Compute the length of remaing data. */
5940Sstevel@tonic-gate 		remain = total_len % AES_BLOCK_LEN;
5950Sstevel@tonic-gate 
5960Sstevel@tonic-gate 		/*
5970Sstevel@tonic-gate 		 * Make sure that the output length is a multiple of
5980Sstevel@tonic-gate 		 * blocksize.
5990Sstevel@tonic-gate 		 */
6000Sstevel@tonic-gate 		out_len = total_len - remain;
6010Sstevel@tonic-gate 
6020Sstevel@tonic-gate 		if (mechanism == CKM_AES_CBC_PAD) {
6030Sstevel@tonic-gate 			/*
6040Sstevel@tonic-gate 			 * If the input data length is a multiple of
6050Sstevel@tonic-gate 			 * blocksize, then save the last block of input
6060Sstevel@tonic-gate 			 * data in the remaining buffer. C_DecryptFinal
6070Sstevel@tonic-gate 			 * will handle this last block of data.
6080Sstevel@tonic-gate 			 */
6090Sstevel@tonic-gate 			if (remain == 0) {
6100Sstevel@tonic-gate 				remain = AES_BLOCK_LEN;
6110Sstevel@tonic-gate 				out_len -= AES_BLOCK_LEN;
6120Sstevel@tonic-gate 			}
6130Sstevel@tonic-gate 		}
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 		/*
6160Sstevel@tonic-gate 		 * If application asks for the length of the output buffer
6170Sstevel@tonic-gate 		 * to hold the plaintext?
6180Sstevel@tonic-gate 		 */
6190Sstevel@tonic-gate 		if (pData == NULL) {
6200Sstevel@tonic-gate 			*pulDataLen = out_len;
6210Sstevel@tonic-gate 			return (CKR_OK);
6220Sstevel@tonic-gate 		}
6230Sstevel@tonic-gate 
6240Sstevel@tonic-gate 		/*
6250Sstevel@tonic-gate 		 * Is the application-supplied buffer large enough?
6260Sstevel@tonic-gate 		 */
6270Sstevel@tonic-gate 		if (*pulDataLen < out_len) {
6280Sstevel@tonic-gate 			*pulDataLen = out_len;
6290Sstevel@tonic-gate 			return (CKR_BUFFER_TOO_SMALL);
6300Sstevel@tonic-gate 		}
6310Sstevel@tonic-gate 
6320Sstevel@tonic-gate 		if (soft_aes_ctx->remain_len != 0) {
6330Sstevel@tonic-gate 			/*
6340Sstevel@tonic-gate 			 * Copy last remaining data and current input data
6350Sstevel@tonic-gate 			 * to the output buffer.
6360Sstevel@tonic-gate 			 */
6370Sstevel@tonic-gate 			(void) memmove(pData + soft_aes_ctx->remain_len,
6380Sstevel@tonic-gate 			    pEncrypted, out_len - soft_aes_ctx->remain_len);
6390Sstevel@tonic-gate 			(void) memcpy(pData, soft_aes_ctx->data,
6400Sstevel@tonic-gate 			    soft_aes_ctx->remain_len);
6410Sstevel@tonic-gate 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
6420Sstevel@tonic-gate 
6430Sstevel@tonic-gate 			in_buf = pData;
6440Sstevel@tonic-gate 		} else {
6450Sstevel@tonic-gate 			in_buf = pEncrypted;
6460Sstevel@tonic-gate 		}
6470Sstevel@tonic-gate 		out_buf = pData;
6480Sstevel@tonic-gate 	}
6490Sstevel@tonic-gate 
6507188Smcpowers do_decryption:
6510Sstevel@tonic-gate 	/*
6520Sstevel@tonic-gate 	 * Begin Decryption.
6530Sstevel@tonic-gate 	 */
6540Sstevel@tonic-gate 	switch (mechanism) {
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 	case CKM_AES_ECB:
6570Sstevel@tonic-gate 	{
6580Sstevel@tonic-gate 
6590Sstevel@tonic-gate 		ulong_t i;
6600Sstevel@tonic-gate 		uint8_t *tmp_inbuf;
6610Sstevel@tonic-gate 		uint8_t *tmp_outbuf;
6620Sstevel@tonic-gate 
6630Sstevel@tonic-gate 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
6640Sstevel@tonic-gate 			tmp_inbuf = &in_buf[i];
6650Sstevel@tonic-gate 			tmp_outbuf = &out_buf[i];
6660Sstevel@tonic-gate 			/* Crunch one block of data for AES. */
6677188Smcpowers 			(void) aes_decrypt_block(soft_aes_ctx->key_sched,
6680Sstevel@tonic-gate 			    tmp_inbuf, tmp_outbuf);
6690Sstevel@tonic-gate 		}
6700Sstevel@tonic-gate 
6710Sstevel@tonic-gate 		if (update) {
6720Sstevel@tonic-gate 			/*
6730Sstevel@tonic-gate 			 * For decrypt update, if there is a remaining
6740Sstevel@tonic-gate 			 * data, save it and its length in the context.
6750Sstevel@tonic-gate 			 */
6760Sstevel@tonic-gate 			if (remain != 0)
6770Sstevel@tonic-gate 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
6780Sstevel@tonic-gate 				    (ulEncryptedLen - remain), remain);
6790Sstevel@tonic-gate 			soft_aes_ctx->remain_len = remain;
6800Sstevel@tonic-gate 		}
6810Sstevel@tonic-gate 
6820Sstevel@tonic-gate 		*pulDataLen = out_len;
6830Sstevel@tonic-gate 
6840Sstevel@tonic-gate 		break;
6850Sstevel@tonic-gate 	}
6860Sstevel@tonic-gate 
6870Sstevel@tonic-gate 	case CKM_AES_CBC:
6880Sstevel@tonic-gate 	case CKM_AES_CBC_PAD:
6890Sstevel@tonic-gate 	{
6900Sstevel@tonic-gate 		crypto_data_t out;
6910Sstevel@tonic-gate 		CK_ULONG rem_len;
6920Sstevel@tonic-gate 		uint8_t last_block[AES_BLOCK_LEN];
6930Sstevel@tonic-gate 
6940Sstevel@tonic-gate 		out.cd_format = CRYPTO_DATA_RAW;
6950Sstevel@tonic-gate 		out.cd_offset = 0;
6960Sstevel@tonic-gate 		out.cd_length = out_len;
6970Sstevel@tonic-gate 		out.cd_raw.iov_base = (char *)out_buf;
6980Sstevel@tonic-gate 		out.cd_raw.iov_len = out_len;
6990Sstevel@tonic-gate 
7000Sstevel@tonic-gate 		/* Decrypt multiple blocks of data. */
7010Sstevel@tonic-gate 		rc = aes_decrypt_contiguous_blocks(
7020Sstevel@tonic-gate 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
7030Sstevel@tonic-gate 		    (char *)in_buf, out_len, &out);
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 		if (rc != 0)
7060Sstevel@tonic-gate 			goto decrypt_failed;
7070Sstevel@tonic-gate 
7080Sstevel@tonic-gate 		if ((mechanism == CKM_AES_CBC_PAD) && (!update)) {
7090Sstevel@tonic-gate 			/* Decrypt last block containing pad bytes. */
7100Sstevel@tonic-gate 			out.cd_offset = 0;
7110Sstevel@tonic-gate 			out.cd_length = AES_BLOCK_LEN;
7120Sstevel@tonic-gate 			out.cd_raw.iov_base = (char *)last_block;
7130Sstevel@tonic-gate 			out.cd_raw.iov_len = AES_BLOCK_LEN;
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 			/* Decrypt last block containing pad bytes. */
7160Sstevel@tonic-gate 			rc = aes_decrypt_contiguous_blocks(
7170Sstevel@tonic-gate 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
7180Sstevel@tonic-gate 			    (char *)in_buf + out_len, AES_BLOCK_LEN, &out);
7190Sstevel@tonic-gate 
7200Sstevel@tonic-gate 			if (rc != 0)
7210Sstevel@tonic-gate 				goto decrypt_failed;
7220Sstevel@tonic-gate 
7230Sstevel@tonic-gate 			/*
7240Sstevel@tonic-gate 			 * Remove padding bytes after decryption of
7250Sstevel@tonic-gate 			 * ciphertext block to produce the original
7260Sstevel@tonic-gate 			 * plaintext.
7270Sstevel@tonic-gate 			 */
7280Sstevel@tonic-gate 			rv = soft_remove_pkcs7_padding(last_block,
729*12573SDina.Nimeh@Sun.COM 			    AES_BLOCK_LEN, &rem_len);
7300Sstevel@tonic-gate 			if (rv == CKR_OK) {
7310Sstevel@tonic-gate 				if (rem_len != 0)
7320Sstevel@tonic-gate 					(void) memcpy(out_buf + out_len,
7330Sstevel@tonic-gate 					    last_block, rem_len);
7340Sstevel@tonic-gate 				*pulDataLen = out_len + rem_len;
7350Sstevel@tonic-gate 			} else {
7360Sstevel@tonic-gate 				*pulDataLen = 0;
7370Sstevel@tonic-gate 				goto cleanup;
7380Sstevel@tonic-gate 			}
7390Sstevel@tonic-gate 		} else {
7400Sstevel@tonic-gate 			*pulDataLen = out_len;
7410Sstevel@tonic-gate 		}
7420Sstevel@tonic-gate 
7430Sstevel@tonic-gate 		if (update) {
7440Sstevel@tonic-gate 			/*
7450Sstevel@tonic-gate 			 * For decrypt update, if there is remaining data,
7460Sstevel@tonic-gate 			 * save it and its length in the context.
7470Sstevel@tonic-gate 			 */
7480Sstevel@tonic-gate 			if (remain != 0)
7490Sstevel@tonic-gate 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
7500Sstevel@tonic-gate 				    (ulEncryptedLen - remain), remain);
7510Sstevel@tonic-gate 			soft_aes_ctx->remain_len = remain;
7520Sstevel@tonic-gate 		}
7530Sstevel@tonic-gate 
7540Sstevel@tonic-gate 		if (rc == 0)
7550Sstevel@tonic-gate 			break;
7560Sstevel@tonic-gate decrypt_failed:
7570Sstevel@tonic-gate 		*pulDataLen = 0;
7580Sstevel@tonic-gate 		rv = CKR_FUNCTION_FAILED;
7590Sstevel@tonic-gate 		goto cleanup;
7600Sstevel@tonic-gate 	}
7617188Smcpowers 	case CKM_AES_CTR:
7627188Smcpowers 	{
7637188Smcpowers 		crypto_data_t out;
7647188Smcpowers 
7657188Smcpowers 		out.cd_format = CRYPTO_DATA_RAW;
7667188Smcpowers 		out.cd_offset = 0;
7677188Smcpowers 		out.cd_length = *pulDataLen;
7687188Smcpowers 		out.cd_raw.iov_base = (char *)pData;
7697188Smcpowers 		out.cd_raw.iov_len = *pulDataLen;
7707188Smcpowers 
7717188Smcpowers 		rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
7727188Smcpowers 		    (char *)pEncrypted, ulEncryptedLen, &out);
7737188Smcpowers 
7747188Smcpowers 		if (rc != 0) {
7757188Smcpowers 			*pulDataLen = 0;
7767188Smcpowers 			rv = CKR_FUNCTION_FAILED;
7777188Smcpowers 			goto cleanup;
7787188Smcpowers 		}
7797188Smcpowers 
7807188Smcpowers 		/*
7817188Smcpowers 		 * Since AES counter mode is a stream cipher, we call
7827188Smcpowers 		 * aes_counter_final() to pick up any remaining bytes.
7837188Smcpowers 		 * It is an internal function that does not destroy
7847188Smcpowers 		 * the context like *normal* final routines.
7857188Smcpowers 		 */
7867188Smcpowers 		if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
7877188Smcpowers 		    > 0) {
7887188Smcpowers 			rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
7897188Smcpowers 			    aes_encrypt_block);
7907188Smcpowers 			if (rc == CRYPTO_DATA_LEN_RANGE)
7917188Smcpowers 				rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
7927188Smcpowers 		}
7937188Smcpowers 	}
7940Sstevel@tonic-gate 	} /* end switch */
7950Sstevel@tonic-gate 
7960Sstevel@tonic-gate 	if (update)
7970Sstevel@tonic-gate 		return (CKR_OK);
7980Sstevel@tonic-gate 
7990Sstevel@tonic-gate 	/*
8000Sstevel@tonic-gate 	 * The following code will be executed if the caller is
8010Sstevel@tonic-gate 	 * soft_decrypt() or an error occurred. The decryption
8020Sstevel@tonic-gate 	 * operation will be terminated so we need to do some cleanup.
8030Sstevel@tonic-gate 	 */
8040Sstevel@tonic-gate cleanup:
8050Sstevel@tonic-gate 	(void) pthread_mutex_lock(&session_p->session_mutex);
8060Sstevel@tonic-gate 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
8070Sstevel@tonic-gate 	if (aes_ctx != NULL) {
8080Sstevel@tonic-gate 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
8090Sstevel@tonic-gate 		free(soft_aes_ctx->aes_cbc);
8100Sstevel@tonic-gate 	}
8110Sstevel@tonic-gate 
8120Sstevel@tonic-gate 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
8130Sstevel@tonic-gate 	free(soft_aes_ctx->key_sched);
8140Sstevel@tonic-gate 	free(session_p->decrypt.context);
8150Sstevel@tonic-gate 	session_p->decrypt.context = NULL;
8160Sstevel@tonic-gate 	(void) pthread_mutex_unlock(&session_p->session_mutex);
8170Sstevel@tonic-gate 
8180Sstevel@tonic-gate 	return (rv);
8190Sstevel@tonic-gate }
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate 
8220Sstevel@tonic-gate /*
8230Sstevel@tonic-gate  * Allocate and initialize a context for AES CBC mode of operation.
8240Sstevel@tonic-gate  */
8250Sstevel@tonic-gate void *
aes_cbc_ctx_init(void * key_sched,size_t size,uint8_t * ivec)8260Sstevel@tonic-gate aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
8270Sstevel@tonic-gate {
8280Sstevel@tonic-gate 
8297188Smcpowers 	cbc_ctx_t *cbc_ctx;
8300Sstevel@tonic-gate 
8317188Smcpowers 	if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
8320Sstevel@tonic-gate 		return (NULL);
8330Sstevel@tonic-gate 
8347581SMark.Powers@Sun.COM 	cbc_ctx->cbc_keysched = key_sched;
8357581SMark.Powers@Sun.COM 	cbc_ctx->cbc_keysched_len = size;
8367188Smcpowers 
8377581SMark.Powers@Sun.COM 	(void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
8387188Smcpowers 
8397581SMark.Powers@Sun.COM 	cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
8407581SMark.Powers@Sun.COM 	cbc_ctx->cbc_flags |= CBC_MODE;
8410Sstevel@tonic-gate 
8427188Smcpowers 	return (cbc_ctx);
8437188Smcpowers }
8447188Smcpowers 
8457188Smcpowers /*
8467188Smcpowers  * Allocate and initialize a context for AES CTR mode of operation.
8477188Smcpowers  */
8487188Smcpowers void *
aes_ctr_ctx_init(void * key_sched,size_t size,uint8_t * param)8497188Smcpowers aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
8507188Smcpowers {
8510Sstevel@tonic-gate 
8527188Smcpowers 	ctr_ctx_t *ctr_ctx;
8537188Smcpowers 	CK_AES_CTR_PARAMS *pp;
8547188Smcpowers 
8557188Smcpowers 	/* LINTED: pointer alignment */
8567188Smcpowers 	pp = (CK_AES_CTR_PARAMS *)param;
8577188Smcpowers 
8587188Smcpowers 	if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
8597188Smcpowers 		return (NULL);
8600Sstevel@tonic-gate 
8617188Smcpowers 	ctr_ctx->ctr_keysched = key_sched;
8627188Smcpowers 	ctr_ctx->ctr_keysched_len = size;
8630Sstevel@tonic-gate 
8647188Smcpowers 	if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block)
8657188Smcpowers 	    != CRYPTO_SUCCESS) {
8667188Smcpowers 		free(ctr_ctx);
8677188Smcpowers 		return (NULL);
8687188Smcpowers 	}
8697188Smcpowers 
8707188Smcpowers 	return (ctr_ctx);
8710Sstevel@tonic-gate }
872