/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* or http://www.opensolaris.org/os/licensing.
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
*/
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>
#include <security/cryptoki.h>
#include "softSession.h"
#include "softObject.h"
#include "softCrypt.h"
#include <aes/aes_impl.h>
#ifdef _aes_amd64
#include <sys/auxv.h> /* getisax() */
#include <sys/auxv_386.h> /* AV_386_AES bit */
#endif
#ifdef _aes_amd64
#define AESNI_aes_ecb_SMALL_JOB \
if ((out_len < AESNI_MODES_THRESHOLD) || \
!soft_intel_aes_instructions_present()) { \
/* \
* AES-NI for small buffers - \
* call block-level AES encrypt function directly. \
*/ \
ulong_t i; \
uint8_t *tmp_inbuf; \
uint8_t *tmp_outbuf; \
\
for (i = 0; i < out_len; i += AES_BLOCK_LEN) { \
tmp_inbuf = &in_buf[i]; \
tmp_outbuf = &out_buf[i]; \
/* Crunch one block of data for AES. */ \
(void) aes_encrypt_block( \
soft_aes_ctx->key_sched, \
tmp_inbuf, tmp_outbuf); \
} \
goto end_small_job;
}
#else
#define AESNI_aes_ecb_SMALL_JOB
#endif
/* there is no small job shortcut for non-AES_ECB */
#define AESNI_aes_cbc_SMALL_JOB
#define AESNI_aes_ctr_SMALL_JOB
#define AESNI_des_common_SMALL_JOB
#define AESNI_des3_common_SMALL_JOB
/* datasz must be multiple of blocksz for block ciphers */
#define SOFT_cbc_DATASZ_CHECK(len, blocksz, is_encrypt) \
if (((len) % (blocksz)) != 0) { \
if ((is_encrypt)) { \
rv = CKR_DATA_LEN_RANGE; \
} else { \
rv = CKR_ENCRYPTED_DATA_LEN_RANGE; \
} \
goto cleanup; \
}
#define SOFT_ecb_DATASZ_CHECK(len, blocksz, is_encrypt) \
SOFT_cbc_DATASZ_CHECK((len), (blocksz), (is_encrypt))
#define SOFT_common_DATASZ_CHECK(len, blocksz, is_encrypt) \
SOFT_cbc_DATASZ_CHECK((len), (blocksz), (is_encrypt))
/* datasz can be of any length for stream cipher (CTR) */
#define SOFT_ctr_DATASZ_CHECK(len, blocksz, is_encrypt)
#define FREE_aes_CTX \
bzero(alg_ctx->ac_keysched, alg_ctx->ac_keysched_len); \
free(soft_alg_ctx->mode_ctx);
#define FREE_des_CTX \
bzero(alg_ctx->dc_keysched, alg_ctx->dc_keysched_len); \
free(soft_alg_ctx->mode_ctx);
#define FREE_des3_CTX FREE_des_CTX
#define GET_aes_keysched(op) \
ks = &(((aes_key_t *)cctx->cc_keysched)->encr_ks.ks64[0]);
#define GET_des_keysched(op) \
ks = &(((des_keysched_t *)cctx->cc_keysched)->ksch_##op[0]);
#define GET_des3_keysched(op) \
ks = &(((des3_keysched_t *)cctx->cc_keysched)->ksch_##op[0]);
#if defined(__sparc)
#define LOW_LEVEL_CRYPT(op, alg) \
common_ctx_t *cctx = (common_ctx_t *)soft_alg_ctx->mode_ctx; \
uint64_t *ks; \
yf_functions_t *funcs; \
funcs = session_p->low_level_functions; \
\
GET_##alg##_keysched(op) \
funcs->load_keys(ks); \
funcs->contig_blocks(ks, (uint64_t *)(void *)in_buf, \
(uint64_t *)(void *)out_buf, out_len, cctx->cc_iv);
#else
#define LOW_LEVEL_CRYPT(op, alg) \
rc = alg##_crypt_contiguous_blocks(( \
alg##_ctx_t *)soft_alg_ctx->mode_ctx, (char *)in_buf, \
out_len, &out, session_p->low_level_functions);
#endif
#define soft_des3_ctx_t soft_des_ctx_t
#define des3_ctx_t des_ctx_t
#define des3_crypt_contiguous_blocks des_crypt_contiguous_blocks
#define des3_encrypt_contiguous_blocks des_encrypt_contiguous_blocks
#define des3_decrypt_contiguous_blocks des_decrypt_contiguous_blocks
#define SOFT_RAWDATA_ENCRYPT(alg, mode, blocksz) \
CK_RV \
soft_##alg##_##mode##_encrypt(soft_session_t *session_p, CK_BYTE_PTR pData, \
CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, CK_ULONG_PTR pulEncryptedLen) \
{ \
int rc = 0; \
CK_RV rv = CKR_OK; \
soft_##alg##_ctx_t *soft_alg_ctx = \
(soft_##alg##_ctx_t *)session_p->encrypt.context; \
alg##_ctx_t *alg_ctx; \
CK_BYTE *in_buf = NULL; \
CK_BYTE *out_buf = NULL; \
CK_ULONG out_len; \
crypto_data_t out; \
\
if (ulDataLen == 0) { \
*pulEncryptedLen = 0; \
return (CKR_OK); \
} \
\
SOFT_##mode##_DATASZ_CHECK(ulDataLen, blocksz, B_TRUE) \
\
out_len = ulDataLen; \
\
/* \
* If application asks for the length of the output buffer \
* to hold the ciphertext? \
*/ \
if (pEncrypted == NULL) { \
*pulEncryptedLen = out_len; \
return (CKR_OK); \
} \
\
/* Is the application-supplied buffer large enough? */ \
if (*pulEncryptedLen < out_len) { \
*pulEncryptedLen = out_len; \
return (CKR_BUFFER_TOO_SMALL); \
} \
\
in_buf = pData; \
out_buf = pEncrypted; \
\
/* \
* Begin Encryption now. \
*/ \
\
/* \
* For intel, AES ECB small jobs are optimized by calling \
* block-level AES encrypt function directly. It goes to \
* 'end_small_job' when the job is done. \
* It is NOP for other algorithms and modes. \
*/ \
AESNI_##alg##_##mode##_SMALL_JOB \
\
out.cd_format = CRYPTO_DATA_RAW; \
out.cd_offset = 0; \
out.cd_length = out_len; \
out.cd_raw.iov_base = (char *)out_buf; \
out.cd_raw.iov_len = out_len; \
\
/* Encrypt multiple blocks of data. */ \
if (session_p->low_level_functions != NULL) { \
if ((soft_alg_ctx->remain_len == 0) && \
((((size_t)in_buf) & 7) == 0) && \
((((size_t)out_buf) & 7) == 0) && \
((out_len & ((blocksz) - 1)) == 0)) { \
LOW_LEVEL_CRYPT(encrypt, alg) \
} else { \
rc = alg##_crypt_contiguous_blocks( \
(alg##_ctx_t *)soft_alg_ctx->mode_ctx, \
(char *)in_buf, out_len, &out, \
session_p->low_level_functions); \
} \
} else { \
rc = alg##_encrypt_contiguous_blocks( \
(alg##_ctx_t *)soft_alg_ctx->mode_ctx, \
(char *)in_buf, out_len, &out); \
} \
\
if (rc != 0) { \
*pulEncryptedLen = 0; \
rv = CKR_FUNCTION_FAILED; \
goto cleanup; \
} \
\
end_small_job: \
\
*pulEncryptedLen = out_len; \
\
/* \
* The encryption operation will be terminated so we need \
* to do some cleanup. \
*/ \
cleanup: \
(void) pthread_mutex_lock(&session_p->session_mutex); \
alg_ctx = (alg##_ctx_t *)soft_alg_ctx->mode_ctx; \
if (alg_ctx != NULL) { \
FREE_##alg##_CTX \
} \
\
bzero(soft_alg_ctx->key_sched, soft_alg_ctx->keysched_len); \
free(soft_alg_ctx->key_sched); \
(void) pthread_mutex_unlock(&session_p->session_mutex); \
\
soft_clear_session_context(session_p, SOFT_ENCRYPT_OP, \
sizeof (soft_##alg##_ctx_t)); \
\
return (rv); \
}
/*
* Define:
* soft_aes_cbc_encrypt()
* soft_aes_ecb_encrypt()
* soft_aes_ctr_encrypt()
* soft_des_common_encrypt()
* soft_des3_common_encrypt()
*/
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT(aes, cbc, AES_BLOCK_LEN)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT(aes, ecb, AES_BLOCK_LEN)
SOFT_RAWDATA_ENCRYPT(aes, ctr, AES_BLOCK_LEN)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT(des, common, DES_BLOCK_LEN)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT(des3, common, DES_BLOCK_LEN)
#define SOFT_RAWDATA_ENCRYPT_UPDATE(alg, mode, blocksz, is_block_cipher) \
CK_RV \
soft_##alg##_##mode##_encrypt_update(soft_session_t *session_p, \
CK_BYTE_PTR pData, CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted, \
CK_ULONG_PTR pulEncryptedLen) \
{ \
int rc = 0; \
CK_RV rv = CKR_OK; \
soft_##alg##_ctx_t *soft_alg_ctx = \
(soft_##alg##_ctx_t *)session_p->encrypt.context; \
alg##_ctx_t *alg_ctx; \
CK_BYTE *in_buf = pData; \
CK_BYTE *out_buf = pEncrypted; \
CK_ULONG out_len = ulDataLen; \
CK_ULONG total_len; \
CK_ULONG remain = 0; \
crypto_data_t out; \
\
if (ulDataLen == 0) { \
*pulEncryptedLen = 0; \
return (CKR_OK); \
} \
\
if (is_block_cipher) { \
/* \
* Add the lengths of last remaining data and current \
* plaintext together to get the total input length. \
*/ \
total_len = soft_alg_ctx->remain_len + ulDataLen; \
\
/* \
* If the total input length is less than one \
* blocksize, we will need to delay encryption until \
* when more data comes in the next C_EncryptUpdate or \
* when C_EncryptFinal is called. \
*/ \
if (total_len < (blocksz)) { \
if (pEncrypted != NULL) { \
/* \
* Save input data and its length in \
* the remaining buffer of the context. \
*/ \
(void) memcpy(soft_alg_ctx->data + \
soft_alg_ctx->remain_len, pData, \
ulDataLen); \
soft_alg_ctx->remain_len += ulDataLen; \
} \
\
/* Set encrypted data length to 0. */ \
*pulEncryptedLen = 0; \
return (CKR_OK); \
} \
\
/* Compute the length of remaining data. */ \
remain = total_len % (blocksz); \
\
/* \
* Make sure that the output length is a multiple of \
* blocksize. \
*/ \
out_len = total_len - remain; \
} \
\
/* \
* If application asks for the length of the output buffer \
* to hold the ciphertext? \
*/ \
if (pEncrypted == NULL) { \
*pulEncryptedLen = out_len; \
return (CKR_OK); \
} \
\
/* Is the application-supplied buffer large enough? */ \
if (*pulEncryptedLen < out_len) { \
*pulEncryptedLen = out_len; \
return (CKR_BUFFER_TOO_SMALL); \
} \
\
if (is_block_cipher) { \
if (soft_alg_ctx->remain_len != 0) { \
/* \
* Copy last remaining data and current \
* input data to the output buffer. \
*/ \
(void) memmove(pEncrypted + \
soft_alg_ctx->remain_len, pData, \
out_len - soft_alg_ctx->remain_len); \
(void) memcpy(pEncrypted, soft_alg_ctx->data, \
soft_alg_ctx->remain_len); \
bzero(soft_alg_ctx->data, \
soft_alg_ctx->remain_len); \
\
in_buf = pEncrypted; \
} else { \
in_buf = pData; \
} \
out_buf = pEncrypted; \
} \
\
/* \
* Begin Encryption now. \
*/ \
out.cd_format = CRYPTO_DATA_RAW; \
out.cd_offset = 0; \
out.cd_length = out_len; \
out.cd_raw.iov_base = (char *)out_buf; \
out.cd_raw.iov_len = out_len; \
\
/* Encrypt multiple blocks of data. */ \
\
if (session_p->low_level_functions != NULL) { \
if ((soft_alg_ctx->remain_len == 0) && \
((((size_t)in_buf) & 7) == 0) && \
((((size_t)out_buf) & 7) == 0) && \
((out_len & ((blocksz) - 1)) == 0)) { \
LOW_LEVEL_CRYPT(encrypt, alg) \
} else { \
rc = alg##_crypt_contiguous_blocks( \
(alg##_ctx_t *)soft_alg_ctx->mode_ctx, \
(char *)in_buf, out_len, &out, \
session_p->low_level_functions); \
} \
} else { \
rc = alg##_encrypt_contiguous_blocks( \
(alg##_ctx_t *)soft_alg_ctx->mode_ctx, \
(char *)in_buf, out_len, &out); \
} \
\
if (rc != 0) { \
*pulEncryptedLen = 0; \
rv = CKR_FUNCTION_FAILED; \
goto cleanup; \
} \
*pulEncryptedLen = out_len; \
\
/* \
* For encrypt update, if there is remaining data, \
* save it and its length in the context. \
*/ \
if (remain != 0) \
(void) memcpy(soft_alg_ctx->data, pData + \
(ulDataLen - remain), remain); \
soft_alg_ctx->remain_len = remain; \
\
return (CKR_OK); \
\
/* \
* The encryption operation will be terminated so we need \
* to do some cleanup. \
*/ \
cleanup: \
(void) pthread_mutex_lock(&session_p->session_mutex); \
alg_ctx = (alg##_ctx_t *)soft_alg_ctx->mode_ctx; \
if (alg_ctx != NULL) { \
FREE_##alg##_CTX \
} \
\
bzero(soft_alg_ctx->key_sched, soft_alg_ctx->keysched_len); \
free(soft_alg_ctx->key_sched); \
(void) pthread_mutex_unlock(&session_p->session_mutex); \
\
soft_clear_session_context(session_p, SOFT_ENCRYPT_OP, \
sizeof (soft_##alg##_ctx_t)); \
\
return (rv); \
\
}
/*
* Define:
* soft_aes_cbc_encrypt_update()
* soft_aes_ecb_encrypt_update()
* soft_aes_ctr_encrypt_update()
* soft_des_common_encrypt_update()
* soft_des3_common_encrypt_update()
*/
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT_UPDATE(aes, cbc, AES_BLOCK_LEN, B_TRUE)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT_UPDATE(aes, ecb, AES_BLOCK_LEN, B_TRUE)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT_UPDATE(aes, ctr, AES_BLOCK_LEN, B_FALSE)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT_UPDATE(des, common, DES_BLOCK_LEN, B_TRUE)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_ENCRYPT_UPDATE(des3, common, DES_BLOCK_LEN, B_TRUE)
#define SOFT_RAWDATA_DECRYPT(alg, mode, blocksz) \
CK_RV \
soft_##alg##_##mode##_decrypt(soft_session_t *session_p, \
CK_BYTE_PTR pEncrypted, CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData, \
CK_ULONG_PTR pulDataLen) \
{ \
int rc = 0; \
CK_RV rv = CKR_OK; \
soft_##alg##_ctx_t *soft_alg_ctx = \
(soft_##alg##_ctx_t *)session_p->decrypt.context; \
alg##_ctx_t *alg_ctx; \
CK_BYTE *in_buf = NULL; \
CK_BYTE *out_buf = NULL; \
CK_ULONG out_len; \
crypto_data_t out; \
\
if (ulEncryptedLen == 0) { \
*pulDataLen = 0; \
return (CKR_OK); \
} \
\
SOFT_##mode##_DATASZ_CHECK(ulEncryptedLen, blocksz, B_FALSE) \
\
/* \
* If application asks for the length of the output buffer \
* to hold the plaintext? \
*/ \
if (pData == NULL) { \
*pulDataLen = ulEncryptedLen; \
return (CKR_OK); \
} \
\
if (*pulDataLen < ulEncryptedLen) { \
*pulDataLen = ulEncryptedLen; \
return (CKR_BUFFER_TOO_SMALL); \
} \
out_len = ulEncryptedLen; \
\
in_buf = pEncrypted; \
out_buf = pData; \
\
out.cd_format = CRYPTO_DATA_RAW; \
out.cd_offset = 0; \
out.cd_length = out_len; \
out.cd_raw.iov_base = (char *)out_buf; \
out.cd_raw.iov_len = out_len; \
\
/* Decrypt multiple blocks of data. */ \
if (session_p->low_level_functions != NULL) { \
if ((soft_alg_ctx->remain_len == 0) && \
((((size_t)in_buf) & 7) == 0) && \
((((size_t)out_buf) & 7) == 0) && \
((out_len & ((blocksz) - 1)) == 0)) { \
LOW_LEVEL_CRYPT(decrypt, alg) \
} else { \
rc = alg##_crypt_contiguous_blocks( \
(alg##_ctx_t *)soft_alg_ctx->mode_ctx, \
(char *)in_buf, out_len, &out, \
session_p->low_level_functions); \
} \
} else { \
rc = alg##_decrypt_contiguous_blocks( \
(alg##_ctx_t *)soft_alg_ctx->mode_ctx, \
(char *)in_buf, out_len, &out); \
} \
if (rc != 0) { \
*pulDataLen = 0; \
rv = CKR_FUNCTION_FAILED; \
goto cleanup; \
} \
*pulDataLen = out_len; \
\
/* Decryption is terminated. Cleanup */ \
cleanup: \
(void) pthread_mutex_lock(&session_p->session_mutex); \
alg_ctx = (alg##_ctx_t *)soft_alg_ctx->mode_ctx; \
if (alg_ctx != NULL) { \
FREE_##alg##_CTX \
} \
\
bzero(soft_alg_ctx->key_sched, soft_alg_ctx->keysched_len); \
free(soft_alg_ctx->key_sched); \
(void) pthread_mutex_unlock(&session_p->session_mutex); \
\
soft_clear_session_context(session_p, SOFT_DECRYPT_OP, \
sizeof (soft_##alg##_ctx_t)); \
\
return (rv); \
}
/*
* Define:
* soft_aes_cbc_decrypt()
* soft_aes_ecb_decrypt()
* soft_aes_ctr_decrypt()
* soft_des_common_decrypt()
* soft_des3_common_decrypt()
*/
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT(aes, cbc, AES_BLOCK_LEN)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT(aes, ecb, AES_BLOCK_LEN)
SOFT_RAWDATA_DECRYPT(aes, ctr, AES_BLOCK_LEN)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT(des, common, DES_BLOCK_LEN)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT(des3, common, DES_BLOCK_LEN)
#define SOFT_RAWDATA_DECRYPT_UPDATE(alg, mode, blocksz, is_block_cipher) \
CK_RV \
soft_##alg##_##mode##_decrypt_update(soft_session_t *session_p, \
CK_BYTE_PTR pEncrypted, CK_ULONG ulEncryptedLen, \
CK_BYTE_PTR pData, CK_ULONG_PTR pulDataLen) \
{ \
int rc = 0; \
CK_RV rv = CKR_OK; \
soft_##alg##_ctx_t *soft_alg_ctx = \
(soft_##alg##_ctx_t *)session_p->decrypt.context; \
alg##_ctx_t *alg_ctx; \
CK_BYTE *in_buf = pEncrypted; \
CK_BYTE *out_buf = pData; \
CK_ULONG out_len = ulEncryptedLen; \
CK_ULONG total_len; \
CK_ULONG remain = 0; \
crypto_data_t out; \
\
if (ulEncryptedLen == 0) { \
*pulDataLen = 0; \
return (CKR_OK); \
} \
\
if (is_block_cipher) { \
/* \
* Add the lengths of last remaining data and current \
* input data together to get the total input length. \
*/ \
total_len = soft_alg_ctx->remain_len + ulEncryptedLen; \
\
/* \
* If the total input length is less than one \
* blocksize, we will need to delay decryption until \
* when more data comes in next C_DecryptUpdate or when \
* C_DecryptFinal is called. \
*/ \
if (total_len < (blocksz)) { \
if (pData != NULL) { \
/* \
* Save input data and its length in \
* the remaining buffer of context. \
*/ \
(void) memcpy(soft_alg_ctx->data + \
soft_alg_ctx->remain_len, \
pEncrypted, ulEncryptedLen); \
soft_alg_ctx->remain_len += \
ulEncryptedLen; \
} \
\
/* Set output data length to 0. */ \
*pulDataLen = 0; \
return (CKR_OK); \
} \
\
/* Compute the length of remaining data. */ \
remain = total_len % (blocksz); \
\
/* \
* Make sure that the output length is a \
* multiple of blocksize. \
*/ \
out_len = total_len - remain; \
} \
\
/* \
* If application asks for the length of the output buffer \
* to hold the plaintext? \
*/ \
if (pData == NULL) { \
*pulDataLen = out_len; \
return (CKR_OK); \
} \
\
/* \
* Is the application-supplied buffer large enough? \
*/ \
if (*pulDataLen < out_len) { \
*pulDataLen = out_len; \
return (CKR_BUFFER_TOO_SMALL); \
} \
\
if (is_block_cipher) { \
if (soft_alg_ctx->remain_len != 0) { \
/* \
* Copy last remaining data and current input \
* data to the output buffer. \
*/ \
(void) memmove(pData + \
soft_alg_ctx->remain_len, pEncrypted, \
out_len - soft_alg_ctx->remain_len); \
(void) memcpy(pData, soft_alg_ctx->data, \
soft_alg_ctx->remain_len); \
bzero(soft_alg_ctx->data, \
soft_alg_ctx->remain_len); \
\
in_buf = pData; \
} else { \
in_buf = pEncrypted; \
} \
out_buf = pData; \
} \
\
out.cd_format = CRYPTO_DATA_RAW; \
out.cd_offset = 0; \
out.cd_length = out_len; \
out.cd_raw.iov_base = (char *)out_buf; \
out.cd_raw.iov_len = out_len; \
\
/* Decrypt multiple blocks of data. */ \
if (session_p->low_level_functions != NULL) { \
if ((soft_alg_ctx->remain_len == 0) && \
((((size_t)in_buf) & 7) == 0) && \
((((size_t)out_buf) & 7) == 0) && \
((out_len & ((blocksz) - 1)) == 0)) { \
LOW_LEVEL_CRYPT(decrypt, alg) \
} else { \
rc = alg##_crypt_contiguous_blocks( \
(alg##_ctx_t *)soft_alg_ctx->mode_ctx, \
(char *)in_buf, out_len, &out, \
session_p->low_level_functions); \
} \
} else { \
rc = alg##_decrypt_contiguous_blocks( \
(alg##_ctx_t *)soft_alg_ctx->mode_ctx, \
(char *)in_buf, out_len, &out); \
} \
\
if (rc != 0) { \
*pulDataLen = 0; \
rv = CKR_FUNCTION_FAILED; \
goto cleanup; \
} \
*pulDataLen = out_len; \
\
/* \
* For decrypt update, if there is remaining data \
* save it and its length in the context. \
*/ \
if (remain != 0) \
(void) memcpy(soft_alg_ctx->data, pEncrypted + \
(ulEncryptedLen - remain), remain); \
soft_alg_ctx->remain_len = remain; \
\
return (CKR_OK); \
\
cleanup: \
(void) pthread_mutex_lock(&session_p->session_mutex); \
alg_ctx = (alg##_ctx_t *)soft_alg_ctx->mode_ctx; \
if (alg_ctx != NULL) { \
FREE_##alg##_CTX \
} \
\
bzero(soft_alg_ctx->key_sched, soft_alg_ctx->keysched_len); \
free(soft_alg_ctx->key_sched); \
(void) pthread_mutex_unlock(&session_p->session_mutex); \
\
soft_clear_session_context(session_p, SOFT_DECRYPT_OP, \
sizeof (soft_##alg##_ctx_t)); \
\
return (rv); \
}
/*
* Define:
* soft_aes_cbc_decrypt_update()
* soft_aes_ecb_decrypt_update()
* soft_aes_ctr_decrypt_update()
* soft_des_common_decrypt_update()
* soft_des3_common_decrypt_update()
*/
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT_UPDATE(aes, cbc, AES_BLOCK_LEN, B_TRUE)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT_UPDATE(aes, ecb, AES_BLOCK_LEN, B_TRUE)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT_UPDATE(aes, ctr, AES_BLOCK_LEN, B_FALSE)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT_UPDATE(des, common, DES_BLOCK_LEN, B_TRUE)
/* LINTED E_CONSTANT_CONDITION */
SOFT_RAWDATA_DECRYPT_UPDATE(des3, common, DES_BLOCK_LEN, B_TRUE)
soft_crypt_functions_t pk11_aes_cbc_functions = {
soft_aes_cbc_encrypt,
soft_aes_cbc_encrypt_update,
soft_aes_cbc_decrypt,
soft_aes_cbc_decrypt_update
};
soft_crypt_functions_t pk11_aes_ecb_functions = {
soft_aes_ecb_encrypt,
soft_aes_ecb_encrypt_update,
soft_aes_ecb_decrypt,
soft_aes_ecb_decrypt_update
};
soft_crypt_functions_t pk11_aes_ctr_functions = {
soft_aes_ctr_encrypt,
soft_aes_ctr_encrypt_update,
soft_aes_ctr_decrypt,
soft_aes_ctr_decrypt_update
};
soft_crypt_functions_t pk11_des_common_functions = {
soft_des_common_encrypt,
soft_des_common_encrypt_update,
soft_des_common_decrypt,
soft_des_common_decrypt_update
};
soft_crypt_functions_t pk11_des3_common_functions = {
soft_des3_common_encrypt,
soft_des3_common_encrypt_update,
soft_des3_common_decrypt,
soft_des3_common_decrypt_update
};