Home | History | Annotate | Download | only in common
      1 /*
      2  * CDDL HEADER START
      3  *
      4  * The contents of this file are subject to the terms of the
      5  * Common Development and Distribution License (the "License").
      6  * You may not use this file except in compliance with the License.
      7  *
      8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
      9  * or http://www.opensolaris.org/os/licensing.
     10  * See the License for the specific language governing permissions
     11  * and limitations under the License.
     12  *
     13  * When distributing Covered Code, include this CDDL HEADER in each
     14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
     15  * If applicable, add the following below this CDDL HEADER, with the
     16  * fields enclosed by brackets "[]" replaced with your own identifying
     17  * information: Portions Copyright [yyyy] [name of copyright owner]
     18  *
     19  * CDDL HEADER END
     20  */
     21 /*
     22  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
     23  * Use is subject to license terms.
     24  */
     25 
     26 #include <pthread.h>
     27 #include <stdlib.h>
     28 #include <string.h>
     29 #include <strings.h>
     30 #include <sys/types.h>
     31 #include <security/cryptoki.h>
     32 #include "softSession.h"
     33 #include "softObject.h"
     34 #include "softCrypt.h"
     35 #include <aes_impl.h>
     36 
     37 /*
     38  * Allocate context for the active encryption or decryption operation, and
     39  * generate AES key schedule to speed up the operation.
     40  */
     41 CK_RV
     42 soft_aes_crypt_init_common(soft_session_t *session_p,
     43     CK_MECHANISM_PTR pMechanism, soft_object_t *key_p,
     44     boolean_t encrypt)
     45 {
     46 	size_t size;
     47 	soft_aes_ctx_t *soft_aes_ctx;
     48 
     49 	soft_aes_ctx = calloc(1, sizeof (soft_aes_ctx_t));
     50 	if (soft_aes_ctx == NULL) {
     51 		return (CKR_HOST_MEMORY);
     52 	}
     53 
     54 	soft_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
     55 
     56 	if (soft_aes_ctx->key_sched == NULL) {
     57 		free(soft_aes_ctx);
     58 		return (CKR_HOST_MEMORY);
     59 	}
     60 
     61 	soft_aes_ctx->keysched_len = size;
     62 
     63 	(void) pthread_mutex_lock(&session_p->session_mutex);
     64 	if (encrypt) {
     65 		/* Called by C_EncryptInit. */
     66 		session_p->encrypt.context = soft_aes_ctx;
     67 		session_p->encrypt.mech.mechanism = pMechanism->mechanism;
     68 	} else {
     69 		/* Called by C_DecryptInit. */
     70 		session_p->decrypt.context = soft_aes_ctx;
     71 		session_p->decrypt.mech.mechanism = pMechanism->mechanism;
     72 	}
     73 	(void) pthread_mutex_unlock(&session_p->session_mutex);
     74 
     75 	/*
     76 	 * If this is a non-sensitive key and it does NOT have
     77 	 * a key schedule yet, then allocate one and expand it.
     78 	 * Otherwise, if it's a non-sensitive key, and it DOES have
     79 	 * a key schedule already attached to it, just copy the
     80 	 * pre-expanded schedule to the context and avoid the
     81 	 * extra key schedule expansion operation.
     82 	 */
     83 	if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
     84 		if (OBJ_KEY_SCHED(key_p) == NULL) {
     85 			void *ks;
     86 
     87 			(void) pthread_mutex_lock(&key_p->object_mutex);
     88 			if (OBJ_KEY_SCHED(key_p) == NULL) {
     89 				ks = aes_alloc_keysched(&size, 0);
     90 				if (ks == NULL) {
     91 					(void) pthread_mutex_unlock(
     92 					    &key_p->object_mutex);
     93 					free(soft_aes_ctx);
     94 					return (CKR_HOST_MEMORY);
     95 				}
     96 #ifdef	__sparcv9
     97 				/* LINTED */
     98 				aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
     99 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
    100 #else	/* !__sparcv9 */
    101 				aes_init_keysched(OBJ_SEC_VALUE(key_p),
    102 				    (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
    103 #endif	/* __sparcv9 */
    104 				OBJ_KEY_SCHED_LEN(key_p) = size;
    105 				OBJ_KEY_SCHED(key_p) = ks;
    106 			}
    107 			(void) pthread_mutex_unlock(&key_p->object_mutex);
    108 		}
    109 		(void) memcpy(soft_aes_ctx->key_sched, OBJ_KEY_SCHED(key_p),
    110 		    OBJ_KEY_SCHED_LEN(key_p));
    111 		soft_aes_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
    112 	} else {
    113 		/*
    114 		 * Initialize key schedule for AES. aes_init_keysched()
    115 		 * requires key length in bits.
    116 		 */
    117 #ifdef	__sparcv9
    118 		/* LINTED */
    119 		aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
    120 		    (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
    121 #else	/* !__sparcv9 */
    122 		aes_init_keysched(OBJ_SEC_VALUE(key_p),
    123 		    (OBJ_SEC_VALUE_LEN(key_p) * 8), soft_aes_ctx->key_sched);
    124 #endif	/* __sparcv9 */
    125 	}
    126 	return (CKR_OK);
    127 }
    128 
    129 
    130 /*
    131  * soft_aes_encrypt_common()
    132  *
    133  * Arguments:
    134  *      session_p:	pointer to soft_session_t struct
    135  *	pData:		pointer to the input data to be encrypted
    136  *	ulDataLen:	length of the input data
    137  *	pEncrypted:	pointer to the output data after encryption
    138  *	pulEncryptedLen: pointer to the length of the output data
    139  *	update:		boolean flag indicates caller is soft_encrypt
    140  *			or soft_encrypt_update
    141  *
    142  * Description:
    143  *      This function calls the corresponding encrypt routine based
    144  *	on the mechanism.
    145  *
    146  * Returns:
    147  *      CKR_OK: success
    148  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
    149  *			      is too small
    150  *	CKR_FUNCTION_FAILED: encrypt function failed
    151  *	CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
    152  */
    153 CK_RV
    154 soft_aes_encrypt_common(soft_session_t *session_p, CK_BYTE_PTR pData,
    155     CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
    156     CK_ULONG_PTR pulEncryptedLen, boolean_t update)
    157 {
    158 
    159 	int rc = 0;
    160 	CK_RV rv = CKR_OK;
    161 	soft_aes_ctx_t *soft_aes_ctx =
    162 	    (soft_aes_ctx_t *)session_p->encrypt.context;
    163 	aes_ctx_t *aes_ctx;
    164 	CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
    165 	CK_BYTE *in_buf = NULL;
    166 	CK_BYTE *out_buf = NULL;
    167 	CK_ULONG out_len;
    168 	CK_ULONG total_len;
    169 	CK_ULONG remain;
    170 
    171 	if (mechanism == CKM_AES_CTR)
    172 		goto do_encryption;
    173 
    174 	/*
    175 	 * AES only takes input length that is a multiple of blocksize
    176 	 * for C_Encrypt function with the mechanism CKM_AES_ECB or
    177 	 * CKM_AES_CBC.
    178 	 *
    179 	 * AES allows any input length for C_Encrypt function with the
    180 	 * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function.
    181 	 */
    182 	if ((!update) && (mechanism != CKM_AES_CBC_PAD)) {
    183 		if ((ulDataLen % AES_BLOCK_LEN) != 0) {
    184 			rv = CKR_DATA_LEN_RANGE;
    185 			goto cleanup;
    186 		}
    187 	}
    188 
    189 	if (!update) {
    190 		/*
    191 		 * Called by C_Encrypt
    192 		 */
    193 		if (mechanism == CKM_AES_CBC_PAD) {
    194 			/*
    195 			 * For CKM_AES_CBC_PAD, compute output length to
    196 			 * count for the padding. If the length of input
    197 			 * data is a multiple of blocksize, then make output
    198 			 * length to be the sum of the input length and
    199 			 * one blocksize. Otherwise, output length will
    200 			 * be rounded up to the next multiple of blocksize.
    201 			 */
    202 			out_len = AES_BLOCK_LEN *
    203 			    (ulDataLen / AES_BLOCK_LEN + 1);
    204 		} else {
    205 			/*
    206 			 * For non-padding mode, the output length will
    207 			 * be same as the input length.
    208 			 */
    209 			out_len = ulDataLen;
    210 		}
    211 
    212 		/*
    213 		 * If application asks for the length of the output buffer
    214 		 * to hold the ciphertext?
    215 		 */
    216 		if (pEncrypted == NULL) {
    217 			*pulEncryptedLen = out_len;
    218 			return (CKR_OK);
    219 		}
    220 
    221 		/* Is the application-supplied buffer large enough? */
    222 		if (*pulEncryptedLen < out_len) {
    223 			*pulEncryptedLen = out_len;
    224 			return (CKR_BUFFER_TOO_SMALL);
    225 		}
    226 
    227 		/* Encrypt pad bytes in a separate operation */
    228 		if (mechanism == CKM_AES_CBC_PAD) {
    229 			out_len -= AES_BLOCK_LEN;
    230 		}
    231 
    232 		in_buf = pData;
    233 		out_buf = pEncrypted;
    234 	} else {
    235 		/*
    236 		 * Called by C_EncryptUpdate
    237 		 *
    238 		 * Add the lengths of last remaining data and current
    239 		 * plaintext together to get the total input length.
    240 		 */
    241 		total_len = soft_aes_ctx->remain_len + ulDataLen;
    242 
    243 		/*
    244 		 * If the total input length is less than one blocksize,
    245 		 * or if the total input length is just one blocksize and
    246 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
    247 		 * encryption until when more data comes in next
    248 		 * C_EncryptUpdate or when C_EncryptFinal is called.
    249 		 */
    250 		if ((total_len < AES_BLOCK_LEN) ||
    251 		    ((mechanism == CKM_AES_CBC_PAD) &&
    252 		    (total_len == AES_BLOCK_LEN))) {
    253 			if (pEncrypted != NULL) {
    254 				/*
    255 				 * Save input data and its length in
    256 				 * the remaining buffer of AES context.
    257 				 */
    258 				(void) memcpy(soft_aes_ctx->data +
    259 				    soft_aes_ctx->remain_len, pData, ulDataLen);
    260 				soft_aes_ctx->remain_len += ulDataLen;
    261 			}
    262 
    263 			/* Set encrypted data length to 0. */
    264 			*pulEncryptedLen = 0;
    265 			return (CKR_OK);
    266 		}
    267 
    268 		/* Compute the length of remaing data. */
    269 		remain = total_len % AES_BLOCK_LEN;
    270 
    271 		/*
    272 		 * Make sure that the output length is a multiple of
    273 		 * blocksize.
    274 		 */
    275 		out_len = total_len - remain;
    276 
    277 		/*
    278 		 * If application asks for the length of the output buffer
    279 		 * to hold the ciphertext?
    280 		 */
    281 		if (pEncrypted == NULL) {
    282 			*pulEncryptedLen = out_len;
    283 			return (CKR_OK);
    284 		}
    285 
    286 		/* Is the application-supplied buffer large enough? */
    287 		if (*pulEncryptedLen < out_len) {
    288 			*pulEncryptedLen = out_len;
    289 			return (CKR_BUFFER_TOO_SMALL);
    290 		}
    291 
    292 		if (soft_aes_ctx->remain_len != 0) {
    293 			/*
    294 			 * Copy last remaining data and current input data
    295 			 * to the output buffer.
    296 			 */
    297 			(void) memmove(pEncrypted + soft_aes_ctx->remain_len,
    298 			    pData, out_len - soft_aes_ctx->remain_len);
    299 			(void) memcpy(pEncrypted, soft_aes_ctx->data,
    300 			    soft_aes_ctx->remain_len);
    301 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
    302 
    303 			in_buf = pEncrypted;
    304 		} else {
    305 			in_buf = pData;
    306 		}
    307 		out_buf = pEncrypted;
    308 	}
    309 
    310 do_encryption:
    311 	/*
    312 	 * Begin Encryption now.
    313 	 */
    314 	switch (mechanism) {
    315 
    316 	case CKM_AES_ECB:
    317 	{
    318 
    319 		ulong_t i;
    320 		uint8_t *tmp_inbuf;
    321 		uint8_t *tmp_outbuf;
    322 
    323 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
    324 			tmp_inbuf = &in_buf[i];
    325 			tmp_outbuf = &out_buf[i];
    326 			/* Crunch one block of data for AES. */
    327 			(void) aes_encrypt_block(soft_aes_ctx->key_sched,
    328 			    tmp_inbuf, tmp_outbuf);
    329 		}
    330 
    331 		if (update) {
    332 			/*
    333 			 * For encrypt update, if there is a remaining
    334 			 * data, save it and its length in the context.
    335 			 */
    336 			if (remain != 0)
    337 				(void) memcpy(soft_aes_ctx->data, pData +
    338 				    (ulDataLen - remain), remain);
    339 			soft_aes_ctx->remain_len = remain;
    340 		}
    341 
    342 		*pulEncryptedLen = out_len;
    343 
    344 		break;
    345 	}
    346 
    347 	case CKM_AES_CBC:
    348 	case CKM_AES_CBC_PAD:
    349 	{
    350 		crypto_data_t out;
    351 
    352 		out.cd_format = CRYPTO_DATA_RAW;
    353 		out.cd_offset = 0;
    354 		out.cd_length = out_len;
    355 		out.cd_raw.iov_base = (char *)out_buf;
    356 		out.cd_raw.iov_len = out_len;
    357 
    358 		/* Encrypt multiple blocks of data. */
    359 		rc = aes_encrypt_contiguous_blocks(
    360 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
    361 		    (char *)in_buf, out_len, &out);
    362 
    363 		if (rc != 0)
    364 			goto encrypt_failed;
    365 
    366 		if (update) {
    367 			/*
    368 			 * For encrypt update, if there is remaining data,
    369 			 * save it and its length in the context.
    370 			 */
    371 			if (remain != 0)
    372 				(void) memcpy(soft_aes_ctx->data, pData +
    373 				    (ulDataLen - remain), remain);
    374 			soft_aes_ctx->remain_len = remain;
    375 		} else if (mechanism == CKM_AES_CBC_PAD) {
    376 			/*
    377 			 * Save the remainder of the input
    378 			 * block in a temporary block because
    379 			 * we dont want to overrun the buffer
    380 			 * by tacking on pad bytes.
    381 			 */
    382 			CK_BYTE tmpblock[AES_BLOCK_LEN];
    383 			(void) memcpy(tmpblock, in_buf + out_len,
    384 			    ulDataLen - out_len);
    385 			soft_add_pkcs7_padding(tmpblock +
    386 			    (ulDataLen - out_len),
    387 			    AES_BLOCK_LEN, ulDataLen - out_len);
    388 
    389 			out.cd_offset = out_len;
    390 			out.cd_length = AES_BLOCK_LEN;
    391 			out.cd_raw.iov_base = (char *)out_buf;
    392 			out.cd_raw.iov_len = out_len + AES_BLOCK_LEN;
    393 
    394 			/* Encrypt last block containing pad bytes. */
    395 			rc = aes_encrypt_contiguous_blocks(
    396 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
    397 			    (char *)tmpblock, AES_BLOCK_LEN, &out);
    398 
    399 			out_len += AES_BLOCK_LEN;
    400 		}
    401 
    402 		if (rc == 0) {
    403 			*pulEncryptedLen = out_len;
    404 			break;
    405 		}
    406 encrypt_failed:
    407 		*pulEncryptedLen = 0;
    408 		rv = CKR_FUNCTION_FAILED;
    409 		goto cleanup;
    410 	}
    411 	case CKM_AES_CTR:
    412 	{
    413 		crypto_data_t out;
    414 
    415 		out.cd_format = CRYPTO_DATA_RAW;
    416 		out.cd_offset = 0;
    417 		out.cd_length = *pulEncryptedLen;
    418 		out.cd_raw.iov_base = (char *)pEncrypted;
    419 		out.cd_raw.iov_len = *pulEncryptedLen;
    420 
    421 		rc = aes_encrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
    422 		    (char *)pData, ulDataLen, &out);
    423 
    424 		if (rc != 0) {
    425 			*pulEncryptedLen = 0;
    426 			rv = CKR_FUNCTION_FAILED;
    427 			goto cleanup;
    428 		}
    429 		/*
    430 		 * Since AES counter mode is a stream cipher, we call
    431 		 * aes_counter_final() to pick up any remaining bytes.
    432 		 * It is an internal function that does not destroy
    433 		 * the context like *normal* final routines.
    434 		 */
    435 		if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len > 0)
    436 			rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
    437 			    aes_encrypt_block);
    438 	}
    439 	} /* end switch */
    440 
    441 	if (update)
    442 		return (CKR_OK);
    443 
    444 	/*
    445 	 * The following code will be executed if the caller is
    446 	 * soft_encrypt() or an error occurred. The encryption
    447 	 * operation will be terminated so we need to do some cleanup.
    448 	 */
    449 cleanup:
    450 	(void) pthread_mutex_lock(&session_p->session_mutex);
    451 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
    452 	if (aes_ctx != NULL) {
    453 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
    454 		free(soft_aes_ctx->aes_cbc);
    455 	}
    456 
    457 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
    458 	free(soft_aes_ctx->key_sched);
    459 	free(session_p->encrypt.context);
    460 	session_p->encrypt.context = NULL;
    461 	(void) pthread_mutex_unlock(&session_p->session_mutex);
    462 
    463 	return (rv);
    464 }
    465 
    466 
    467 /*
    468  * soft_aes_decrypt_common()
    469  *
    470  * Arguments:
    471  *      session_p:	pointer to soft_session_t struct
    472  *	pEncrypted:	pointer to the input data to be decrypted
    473  *	ulEncryptedLen:	length of the input data
    474  *	pData:		pointer to the output data
    475  *	pulDataLen:	pointer to the length of the output data
    476  *	Update:		boolean flag indicates caller is soft_decrypt
    477  *			or soft_decrypt_update
    478  *
    479  * Description:
    480  *      This function calls the corresponding decrypt routine based
    481  *	on the mechanism.
    482  *
    483  * Returns:
    484  *      CKR_OK: success
    485  *      CKR_BUFFER_TOO_SMALL: the output buffer provided by application
    486  *			      is too small
    487  *	CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
    488  *				      of blocksize
    489  *	CKR_FUNCTION_FAILED: decrypt function failed
    490  */
    491 CK_RV
    492 soft_aes_decrypt_common(soft_session_t *session_p, CK_BYTE_PTR pEncrypted,
    493     CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
    494     CK_ULONG_PTR pulDataLen, boolean_t update)
    495 {
    496 
    497 	int rc = 0;
    498 	CK_RV rv = CKR_OK;
    499 	soft_aes_ctx_t *soft_aes_ctx =
    500 	    (soft_aes_ctx_t *)session_p->decrypt.context;
    501 	aes_ctx_t *aes_ctx;
    502 	CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
    503 	CK_BYTE *in_buf = NULL;
    504 	CK_BYTE *out_buf = NULL;
    505 	CK_ULONG out_len;
    506 	CK_ULONG total_len;
    507 	CK_ULONG remain;
    508 
    509 	if (mechanism == CKM_AES_CTR)
    510 		goto do_decryption;
    511 
    512 	/*
    513 	 * AES only takes input length that is a multiple of 16 bytes
    514 	 * for C_Decrypt function with the mechanism CKM_AES_ECB,
    515 	 * CKM_AES_CBC or CKM_AES_CBC_PAD.
    516 	 *
    517 	 * AES allows any input length for C_DecryptUpdate function.
    518 	 */
    519 	if (!update) {
    520 		/*
    521 		 * Called by C_Decrypt
    522 		 */
    523 		if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
    524 			rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
    525 			goto cleanup;
    526 		}
    527 
    528 		/*
    529 		 * If application asks for the length of the output buffer
    530 		 * to hold the plaintext?
    531 		 */
    532 		if (pData == NULL) {
    533 			*pulDataLen = ulEncryptedLen;
    534 			return (CKR_OK);
    535 		}
    536 
    537 		/* Is the application-supplied buffer large enough? */
    538 		if (mechanism != CKM_AES_CBC_PAD) {
    539 			if (*pulDataLen < ulEncryptedLen) {
    540 				*pulDataLen = ulEncryptedLen;
    541 				return (CKR_BUFFER_TOO_SMALL);
    542 			}
    543 			out_len = ulEncryptedLen;
    544 		} else {
    545 			/*
    546 			 * For CKM_AES_CBC_PAD, we don't know how
    547 			 * many bytes for padding at this time, so
    548 			 * we'd assume one block was padded.
    549 			 */
    550 			if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
    551 				*pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
    552 				return (CKR_BUFFER_TOO_SMALL);
    553 			}
    554 			out_len = ulEncryptedLen - AES_BLOCK_LEN;
    555 		}
    556 		in_buf = pEncrypted;
    557 		out_buf = pData;
    558 	} else {
    559 		/*
    560 		 *  Called by C_DecryptUpdate
    561 		 *
    562 		 * Add the lengths of last remaining data and current
    563 		 * input data together to get the total input length.
    564 		 */
    565 		total_len = soft_aes_ctx->remain_len + ulEncryptedLen;
    566 
    567 		/*
    568 		 * If the total input length is less than one blocksize,
    569 		 * or if the total input length is just one blocksize and
    570 		 * the mechanism is CKM_AES_CBC_PAD, we will need to delay
    571 		 * decryption until when more data comes in next
    572 		 * C_DecryptUpdate or when C_DecryptFinal is called.
    573 		 */
    574 		if ((total_len < AES_BLOCK_LEN) ||
    575 		    ((mechanism == CKM_AES_CBC_PAD) &&
    576 		    (total_len == AES_BLOCK_LEN))) {
    577 			if (pData != NULL) {
    578 				/*
    579 				 * Save input data and its length in
    580 				 * the remaining buffer of AES context.
    581 				 */
    582 				(void) memcpy(soft_aes_ctx->data +
    583 				    soft_aes_ctx->remain_len,
    584 				    pEncrypted, ulEncryptedLen);
    585 				soft_aes_ctx->remain_len += ulEncryptedLen;
    586 			}
    587 
    588 			/* Set output data length to 0. */
    589 			*pulDataLen = 0;
    590 			return (CKR_OK);
    591 		}
    592 
    593 		/* Compute the length of remaing data. */
    594 		remain = total_len % AES_BLOCK_LEN;
    595 
    596 		/*
    597 		 * Make sure that the output length is a multiple of
    598 		 * blocksize.
    599 		 */
    600 		out_len = total_len - remain;
    601 
    602 		if (mechanism == CKM_AES_CBC_PAD) {
    603 			/*
    604 			 * If the input data length is a multiple of
    605 			 * blocksize, then save the last block of input
    606 			 * data in the remaining buffer. C_DecryptFinal
    607 			 * will handle this last block of data.
    608 			 */
    609 			if (remain == 0) {
    610 				remain = AES_BLOCK_LEN;
    611 				out_len -= AES_BLOCK_LEN;
    612 			}
    613 		}
    614 
    615 		/*
    616 		 * If application asks for the length of the output buffer
    617 		 * to hold the plaintext?
    618 		 */
    619 		if (pData == NULL) {
    620 			*pulDataLen = out_len;
    621 			return (CKR_OK);
    622 		}
    623 
    624 		/*
    625 		 * Is the application-supplied buffer large enough?
    626 		 */
    627 		if (*pulDataLen < out_len) {
    628 			*pulDataLen = out_len;
    629 			return (CKR_BUFFER_TOO_SMALL);
    630 		}
    631 
    632 		if (soft_aes_ctx->remain_len != 0) {
    633 			/*
    634 			 * Copy last remaining data and current input data
    635 			 * to the output buffer.
    636 			 */
    637 			(void) memmove(pData + soft_aes_ctx->remain_len,
    638 			    pEncrypted, out_len - soft_aes_ctx->remain_len);
    639 			(void) memcpy(pData, soft_aes_ctx->data,
    640 			    soft_aes_ctx->remain_len);
    641 			bzero(soft_aes_ctx->data, soft_aes_ctx->remain_len);
    642 
    643 			in_buf = pData;
    644 		} else {
    645 			in_buf = pEncrypted;
    646 		}
    647 		out_buf = pData;
    648 	}
    649 
    650 do_decryption:
    651 	/*
    652 	 * Begin Decryption.
    653 	 */
    654 	switch (mechanism) {
    655 
    656 	case CKM_AES_ECB:
    657 	{
    658 
    659 		ulong_t i;
    660 		uint8_t *tmp_inbuf;
    661 		uint8_t *tmp_outbuf;
    662 
    663 		for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
    664 			tmp_inbuf = &in_buf[i];
    665 			tmp_outbuf = &out_buf[i];
    666 			/* Crunch one block of data for AES. */
    667 			(void) aes_decrypt_block(soft_aes_ctx->key_sched,
    668 			    tmp_inbuf, tmp_outbuf);
    669 		}
    670 
    671 		if (update) {
    672 			/*
    673 			 * For decrypt update, if there is a remaining
    674 			 * data, save it and its length in the context.
    675 			 */
    676 			if (remain != 0)
    677 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
    678 				    (ulEncryptedLen - remain), remain);
    679 			soft_aes_ctx->remain_len = remain;
    680 		}
    681 
    682 		*pulDataLen = out_len;
    683 
    684 		break;
    685 	}
    686 
    687 	case CKM_AES_CBC:
    688 	case CKM_AES_CBC_PAD:
    689 	{
    690 		crypto_data_t out;
    691 		CK_ULONG rem_len;
    692 		uint8_t last_block[AES_BLOCK_LEN];
    693 
    694 		out.cd_format = CRYPTO_DATA_RAW;
    695 		out.cd_offset = 0;
    696 		out.cd_length = out_len;
    697 		out.cd_raw.iov_base = (char *)out_buf;
    698 		out.cd_raw.iov_len = out_len;
    699 
    700 		/* Decrypt multiple blocks of data. */
    701 		rc = aes_decrypt_contiguous_blocks(
    702 		    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
    703 		    (char *)in_buf, out_len, &out);
    704 
    705 		if (rc != 0)
    706 			goto decrypt_failed;
    707 
    708 		if ((mechanism == CKM_AES_CBC_PAD) && (!update)) {
    709 			/* Decrypt last block containing pad bytes. */
    710 			out.cd_offset = 0;
    711 			out.cd_length = AES_BLOCK_LEN;
    712 			out.cd_raw.iov_base = (char *)last_block;
    713 			out.cd_raw.iov_len = AES_BLOCK_LEN;
    714 
    715 			/* Decrypt last block containing pad bytes. */
    716 			rc = aes_decrypt_contiguous_blocks(
    717 			    (aes_ctx_t *)soft_aes_ctx->aes_cbc,
    718 			    (char *)in_buf + out_len, AES_BLOCK_LEN, &out);
    719 
    720 			if (rc != 0)
    721 				goto decrypt_failed;
    722 
    723 			/*
    724 			 * Remove padding bytes after decryption of
    725 			 * ciphertext block to produce the original
    726 			 * plaintext.
    727 			 */
    728 			rv = soft_remove_pkcs7_padding(last_block,
    729 			    AES_BLOCK_LEN, &rem_len, AES_BLOCK_LEN);
    730 			if (rv == CKR_OK) {
    731 				if (rem_len != 0)
    732 					(void) memcpy(out_buf + out_len,
    733 					    last_block, rem_len);
    734 				*pulDataLen = out_len + rem_len;
    735 			} else {
    736 				*pulDataLen = 0;
    737 				goto cleanup;
    738 			}
    739 		} else {
    740 			*pulDataLen = out_len;
    741 		}
    742 
    743 		if (update) {
    744 			/*
    745 			 * For decrypt update, if there is remaining data,
    746 			 * save it and its length in the context.
    747 			 */
    748 			if (remain != 0)
    749 				(void) memcpy(soft_aes_ctx->data, pEncrypted +
    750 				    (ulEncryptedLen - remain), remain);
    751 			soft_aes_ctx->remain_len = remain;
    752 		}
    753 
    754 		if (rc == 0)
    755 			break;
    756 decrypt_failed:
    757 		*pulDataLen = 0;
    758 		rv = CKR_FUNCTION_FAILED;
    759 		goto cleanup;
    760 	}
    761 	case CKM_AES_CTR:
    762 	{
    763 		crypto_data_t out;
    764 
    765 		out.cd_format = CRYPTO_DATA_RAW;
    766 		out.cd_offset = 0;
    767 		out.cd_length = *pulDataLen;
    768 		out.cd_raw.iov_base = (char *)pData;
    769 		out.cd_raw.iov_len = *pulDataLen;
    770 
    771 		rc = aes_decrypt_contiguous_blocks(soft_aes_ctx->aes_cbc,
    772 		    (char *)pEncrypted, ulEncryptedLen, &out);
    773 
    774 		if (rc != 0) {
    775 			*pulDataLen = 0;
    776 			rv = CKR_FUNCTION_FAILED;
    777 			goto cleanup;
    778 		}
    779 
    780 		/*
    781 		 * Since AES counter mode is a stream cipher, we call
    782 		 * aes_counter_final() to pick up any remaining bytes.
    783 		 * It is an internal function that does not destroy
    784 		 * the context like *normal* final routines.
    785 		 */
    786 		if (((aes_ctx_t *)soft_aes_ctx->aes_cbc)->ac_remainder_len
    787 		    > 0) {
    788 			rc = ctr_mode_final(soft_aes_ctx->aes_cbc, &out,
    789 			    aes_encrypt_block);
    790 			if (rc == CRYPTO_DATA_LEN_RANGE)
    791 				rc = CRYPTO_ENCRYPTED_DATA_LEN_RANGE;
    792 		}
    793 	}
    794 	} /* end switch */
    795 
    796 	if (update)
    797 		return (CKR_OK);
    798 
    799 	/*
    800 	 * The following code will be executed if the caller is
    801 	 * soft_decrypt() or an error occurred. The decryption
    802 	 * operation will be terminated so we need to do some cleanup.
    803 	 */
    804 cleanup:
    805 	(void) pthread_mutex_lock(&session_p->session_mutex);
    806 	aes_ctx = (aes_ctx_t *)soft_aes_ctx->aes_cbc;
    807 	if (aes_ctx != NULL) {
    808 		bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
    809 		free(soft_aes_ctx->aes_cbc);
    810 	}
    811 
    812 	bzero(soft_aes_ctx->key_sched, soft_aes_ctx->keysched_len);
    813 	free(soft_aes_ctx->key_sched);
    814 	free(session_p->decrypt.context);
    815 	session_p->decrypt.context = NULL;
    816 	(void) pthread_mutex_unlock(&session_p->session_mutex);
    817 
    818 	return (rv);
    819 }
    820 
    821 
    822 /*
    823  * Allocate and initialize a context for AES CBC mode of operation.
    824  */
    825 void *
    826 aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
    827 {
    828 
    829 	cbc_ctx_t *cbc_ctx;
    830 
    831 	if ((cbc_ctx = calloc(1, sizeof (cbc_ctx_t))) == NULL)
    832 		return (NULL);
    833 
    834 	cbc_ctx->cbc_keysched = key_sched;
    835 	cbc_ctx->cbc_keysched_len = size;
    836 
    837 	(void) memcpy(&cbc_ctx->cbc_iv[0], ivec, AES_BLOCK_LEN);
    838 
    839 	cbc_ctx->cbc_lastp = (uint8_t *)cbc_ctx->cbc_iv;
    840 	cbc_ctx->cbc_flags |= CBC_MODE;
    841 
    842 	return (cbc_ctx);
    843 }
    844 
    845 /*
    846  * Allocate and initialize a context for AES CTR mode of operation.
    847  */
    848 void *
    849 aes_ctr_ctx_init(void *key_sched, size_t size, uint8_t *param)
    850 {
    851 
    852 	ctr_ctx_t *ctr_ctx;
    853 	CK_AES_CTR_PARAMS *pp;
    854 
    855 	/* LINTED: pointer alignment */
    856 	pp = (CK_AES_CTR_PARAMS *)param;
    857 
    858 	if ((ctr_ctx = calloc(1, sizeof (ctr_ctx_t))) == NULL)
    859 		return (NULL);
    860 
    861 	ctr_ctx->ctr_keysched = key_sched;
    862 	ctr_ctx->ctr_keysched_len = size;
    863 
    864 	if (ctr_init_ctx(ctr_ctx, pp->ulCounterBits, pp->cb, aes_copy_block)
    865 	    != CRYPTO_SUCCESS) {
    866 		free(ctr_ctx);
    867 		return (NULL);
    868 	}
    869 
    870 	return (ctr_ctx);
    871 }
    872