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