summaryrefslogtreecommitdiff
path: root/usr/src/lib/pkcs11/pkcs11_kms/common/kmsAESCrypt.c
diff options
context:
space:
mode:
authorJohn Sonnenschein <johns@joyent.com>2012-05-17 18:26:57 +0000
committerJohn Sonnenschein <johns@joyent.com>2012-05-17 18:26:57 +0000
commit04b244dd661c24b510ac22936decfc0972d202d3 (patch)
tree3ebfef98afc303fddf3415d6fba64e8682f495e8 /usr/src/lib/pkcs11/pkcs11_kms/common/kmsAESCrypt.c
parenteac250589e41f1b705e1b7427b02b3379aac9f9e (diff)
parenta69187741b83640a90dd8586195456dd50c016a8 (diff)
downloadillumos-joyent-20120517.tar.gz
Merge git.joyent.com:illumos-joyent20120517
Diffstat (limited to 'usr/src/lib/pkcs11/pkcs11_kms/common/kmsAESCrypt.c')
-rw-r--r--usr/src/lib/pkcs11/pkcs11_kms/common/kmsAESCrypt.c1046
1 files changed, 0 insertions, 1046 deletions
diff --git a/usr/src/lib/pkcs11/pkcs11_kms/common/kmsAESCrypt.c b/usr/src/lib/pkcs11/pkcs11_kms/common/kmsAESCrypt.c
deleted file mode 100644
index 0e384e0043..0000000000
--- a/usr/src/lib/pkcs11/pkcs11_kms/common/kmsAESCrypt.c
+++ /dev/null
@@ -1,1046 +0,0 @@
-/*
- * 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) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
- */
-
-#include <pthread.h>
-#include <stdlib.h>
-#include <string.h>
-#include <strings.h>
-#include <sys/types.h>
-#include <security/cryptoki.h>
-#include <aes_impl.h>
-
-#include "kmsSession.h"
-#include "kmsObject.h"
-#include "kmsCrypt.h"
-
-/*
- * Add padding bytes with the value of length of padding.
- */
-static void
-kms_add_pkcs7_padding(CK_BYTE *buf, int block_size, CK_ULONG data_len)
-{
-
- ulong_t i, pad_len;
- CK_BYTE pad_value;
-
- pad_len = block_size - (data_len % block_size);
- pad_value = (CK_BYTE)pad_len;
-
- for (i = 0; i < pad_len; i++)
- buf[i] = pad_value;
-}
-
-/*
- * Remove padding bytes.
- */
-static CK_RV
-kms_remove_pkcs7_padding(CK_BYTE *pData, CK_ULONG padded_len,
- CK_ULONG *pulDataLen, int block_size)
-{
-
- CK_BYTE pad_value;
- ulong_t i;
-
- pad_value = pData[padded_len - 1];
-
-
- /* Make sure there is a valid padding value. */
- if ((pad_value == 0) || (pad_value > block_size))
- return (CKR_ENCRYPTED_DATA_INVALID);
-
- for (i = padded_len - pad_value; i < padded_len; i++)
- if (pad_value != pData[i])
- return (CKR_ENCRYPTED_DATA_INVALID);
-
- *pulDataLen = padded_len - pad_value;
- return (CKR_OK);
-}
-
-/*
- * Allocate context for the active encryption or decryption operation, and
- * generate AES key schedule to speed up the operation.
- */
-CK_RV
-kms_aes_crypt_init_common(kms_session_t *session_p,
- CK_MECHANISM_PTR pMechanism, kms_object_t *key_p,
- boolean_t encrypt)
-{
- size_t size;
- kms_aes_ctx_t *kms_aes_ctx;
-
- kms_aes_ctx = calloc(1, sizeof (kms_aes_ctx_t));
- if (kms_aes_ctx == NULL) {
- return (CKR_HOST_MEMORY);
- }
-
- kms_aes_ctx->key_sched = aes_alloc_keysched(&size, 0);
-
- if (kms_aes_ctx->key_sched == NULL) {
- free(kms_aes_ctx);
- return (CKR_HOST_MEMORY);
- }
-
- kms_aes_ctx->keysched_len = size;
-
- (void) pthread_mutex_lock(&session_p->session_mutex);
- if (encrypt) {
- /* Called by C_EncryptInit. */
- session_p->encrypt.context = kms_aes_ctx;
- session_p->encrypt.mech.mechanism = pMechanism->mechanism;
- } else {
- /* Called by C_DecryptInit. */
- session_p->decrypt.context = kms_aes_ctx;
- session_p->decrypt.mech.mechanism = pMechanism->mechanism;
- }
- (void) pthread_mutex_unlock(&session_p->session_mutex);
-
- /*
- * If this is a non-sensitive key and it does NOT have
- * a key schedule yet, then allocate one and expand it.
- * Otherwise, if it's a non-sensitive key, and it DOES have
- * a key schedule already attached to it, just copy the
- * pre-expanded schedule to the context and avoid the
- * extra key schedule expansion operation.
- */
- if (!(key_p->bool_attr_mask & SENSITIVE_BOOL_ON)) {
- if (OBJ_KEY_SCHED(key_p) == NULL) {
- void *ks;
-
- (void) pthread_mutex_lock(&key_p->object_mutex);
- if (OBJ_KEY_SCHED(key_p) == NULL) {
- ks = aes_alloc_keysched(&size, 0);
- if (ks == NULL) {
- (void) pthread_mutex_unlock(
- &key_p->object_mutex);
- free(kms_aes_ctx);
- return (CKR_HOST_MEMORY);
- }
-#ifdef __sparcv9
- /* LINTED */
- aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
- (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
-#else /* !__sparcv9 */
- aes_init_keysched(OBJ_SEC_VALUE(key_p),
- (OBJ_SEC_VALUE_LEN(key_p) * 8), ks);
-#endif /* __sparcv9 */
- OBJ_KEY_SCHED_LEN(key_p) = size;
- OBJ_KEY_SCHED(key_p) = ks;
- }
- (void) pthread_mutex_unlock(&key_p->object_mutex);
- }
- (void) memcpy(kms_aes_ctx->key_sched, OBJ_KEY_SCHED(key_p),
- OBJ_KEY_SCHED_LEN(key_p));
- kms_aes_ctx->keysched_len = OBJ_KEY_SCHED_LEN(key_p);
- } else {
- /*
- * Initialize key schedule for AES. aes_init_keysched()
- * requires key length in bits.
- */
-#ifdef __sparcv9
- /* LINTED */
- aes_init_keysched(OBJ_SEC_VALUE(key_p), (uint_t)
- (OBJ_SEC_VALUE_LEN(key_p) * 8), kms_aes_ctx->key_sched);
-#else /* !__sparcv9 */
- aes_init_keysched(OBJ_SEC_VALUE(key_p),
- (OBJ_SEC_VALUE_LEN(key_p) * 8), kms_aes_ctx->key_sched);
-#endif /* __sparcv9 */
- }
- return (CKR_OK);
-}
-
-/*
- * kms_aes_encrypt_common()
- *
- * Arguments:
- * session_p: pointer to kms_session_t struct
- * pData: pointer to the input data to be encrypted
- * ulDataLen: length of the input data
- * pEncrypted: pointer to the output data after encryption
- * pulEncryptedLen: pointer to the length of the output data
- * update: boolean flag indicates caller is kms_encrypt
- * or kms_encrypt_update
- *
- * Description:
- * This function calls the corresponding encrypt routine based
- * on the mechanism.
- *
- * Returns:
- * CKR_OK: success
- * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
- * is too small
- * CKR_FUNCTION_FAILED: encrypt function failed
- * CKR_DATA_LEN_RANGE: the input data is not a multiple of blocksize
- */
-CK_RV
-kms_aes_encrypt_common(kms_session_t *session_p, CK_BYTE_PTR pData,
- CK_ULONG ulDataLen, CK_BYTE_PTR pEncrypted,
- CK_ULONG_PTR pulEncryptedLen, boolean_t update)
-{
-
- int rc = 0;
- CK_RV rv = CKR_OK;
- kms_aes_ctx_t *kms_aes_ctx =
- (kms_aes_ctx_t *)session_p->encrypt.context;
- aes_ctx_t *aes_ctx;
- CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
- CK_BYTE *in_buf = NULL;
- CK_BYTE *out_buf = NULL;
- CK_ULONG out_len;
- CK_ULONG total_len;
- CK_ULONG remain;
-
- if (mechanism == CKM_AES_CTR)
- goto do_encryption;
-
- /*
- * AES only takes input length that is a multiple of blocksize
- * for C_Encrypt function with the mechanism CKM_AES_ECB or
- * CKM_AES_CBC.
- *
- * AES allows any input length for C_Encrypt function with the
- * mechanism CKM_AES_CBC_PAD and for C_EncryptUpdate function.
- */
- if ((!update) && (mechanism != CKM_AES_CBC_PAD)) {
- if ((ulDataLen % AES_BLOCK_LEN) != 0) {
- rv = CKR_DATA_LEN_RANGE;
- goto cleanup;
- }
- }
-
- if (!update) {
- /*
- * Called by C_Encrypt
- */
- if (mechanism == CKM_AES_CBC_PAD) {
- /*
- * For CKM_AES_CBC_PAD, compute output length to
- * count for the padding. If the length of input
- * data is a multiple of blocksize, then make output
- * length to be the sum of the input length and
- * one blocksize. Otherwise, output length will
- * be rounded up to the next multiple of blocksize.
- */
- out_len = AES_BLOCK_LEN *
- (ulDataLen / AES_BLOCK_LEN + 1);
- } else {
- /*
- * For non-padding mode, the output length will
- * be same as the input length.
- */
- 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);
- }
-
- /* Encrypt pad bytes in a separate operation */
- if (mechanism == CKM_AES_CBC_PAD) {
- out_len -= AES_BLOCK_LEN;
- }
-
- in_buf = pData;
- out_buf = pEncrypted;
- } else {
- /*
- * Called by C_EncryptUpdate
- *
- * Add the lengths of last remaining data and current
- * plaintext together to get the total input length.
- */
- total_len = kms_aes_ctx->remain_len + ulDataLen;
-
- /*
- * If the total input length is less than one blocksize,
- * or if the total input length is just one blocksize and
- * the mechanism is CKM_AES_CBC_PAD, we will need to delay
- * encryption until when more data comes in next
- * C_EncryptUpdate or when C_EncryptFinal is called.
- */
- if ((total_len < AES_BLOCK_LEN) ||
- ((mechanism == CKM_AES_CBC_PAD) &&
- (total_len == AES_BLOCK_LEN))) {
- if (pEncrypted != NULL) {
- /*
- * Save input data and its length in
- * the remaining buffer of AES context.
- */
- (void) memcpy(kms_aes_ctx->data +
- kms_aes_ctx->remain_len, pData, ulDataLen);
- kms_aes_ctx->remain_len += ulDataLen;
- }
-
- /* Set encrypted data length to 0. */
- *pulEncryptedLen = 0;
- return (CKR_OK);
- }
-
- /* Compute the length of remaing data. */
- remain = total_len % AES_BLOCK_LEN;
-
- /*
- * 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 (kms_aes_ctx->remain_len != 0) {
- /*
- * Copy last remaining data and current input data
- * to the output buffer.
- */
- (void) memmove(pEncrypted + kms_aes_ctx->remain_len,
- pData, out_len - kms_aes_ctx->remain_len);
- (void) memcpy(pEncrypted, kms_aes_ctx->data,
- kms_aes_ctx->remain_len);
- bzero(kms_aes_ctx->data, kms_aes_ctx->remain_len);
-
- in_buf = pEncrypted;
- } else {
- in_buf = pData;
- }
- out_buf = pEncrypted;
- }
-
-do_encryption:
- /*
- * Begin Encryption now.
- */
- switch (mechanism) {
-
- case CKM_AES_CBC:
- case CKM_AES_CBC_PAD:
- {
- crypto_data_t out;
-
- 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. */
- rc = aes_encrypt_contiguous_blocks(
- (aes_ctx_t *)kms_aes_ctx->aes_cbc,
- (char *)in_buf, out_len, &out);
-
- if (rc != 0)
- goto encrypt_failed;
-
- if (update) {
- /*
- * For encrypt update, if there is remaining data,
- * save it and its length in the context.
- */
- if (remain != 0)
- (void) memcpy(kms_aes_ctx->data, pData +
- (ulDataLen - remain), remain);
- kms_aes_ctx->remain_len = remain;
- } else if (mechanism == CKM_AES_CBC_PAD) {
- /*
- * Save the remainder of the input
- * block in a temporary block because
- * we dont want to overrun the buffer
- * by tacking on pad bytes.
- */
- CK_BYTE tmpblock[AES_BLOCK_LEN];
- (void) memcpy(tmpblock, in_buf + out_len,
- ulDataLen - out_len);
- kms_add_pkcs7_padding(tmpblock +
- (ulDataLen - out_len),
- AES_BLOCK_LEN, ulDataLen - out_len);
-
- out.cd_offset = out_len;
- out.cd_length = AES_BLOCK_LEN;
- out.cd_raw.iov_base = (char *)out_buf;
- out.cd_raw.iov_len = out_len + AES_BLOCK_LEN;
-
- /* Encrypt last block containing pad bytes. */
- rc = aes_encrypt_contiguous_blocks(
- (aes_ctx_t *)kms_aes_ctx->aes_cbc,
- (char *)tmpblock, AES_BLOCK_LEN, &out);
-
- out_len += AES_BLOCK_LEN;
- }
-
- if (rc == 0) {
- *pulEncryptedLen = out_len;
- break;
- }
-encrypt_failed:
- *pulEncryptedLen = 0;
- rv = CKR_FUNCTION_FAILED;
- goto cleanup;
- }
- default:
- rv = CKR_MECHANISM_INVALID;
- goto cleanup;
- } /* end switch */
-
- if (update)
- return (CKR_OK);
-
- /*
- * The following code will be executed if the caller is
- * kms_encrypt() or an error occurred. The encryption
- * operation will be terminated so we need to do some cleanup.
- */
-cleanup:
- (void) pthread_mutex_lock(&session_p->session_mutex);
- aes_ctx = (aes_ctx_t *)kms_aes_ctx->aes_cbc;
- if (aes_ctx != NULL) {
- bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
- free(kms_aes_ctx->aes_cbc);
- }
-
- bzero(kms_aes_ctx->key_sched, kms_aes_ctx->keysched_len);
- free(kms_aes_ctx->key_sched);
- free(session_p->encrypt.context);
- session_p->encrypt.context = NULL;
- (void) pthread_mutex_unlock(&session_p->session_mutex);
-
- return (rv);
-}
-
-
-/*
- * kms_aes_decrypt_common()
- *
- * Arguments:
- * session_p: pointer to kms_session_t struct
- * pEncrypted: pointer to the input data to be decrypted
- * ulEncryptedLen: length of the input data
- * pData: pointer to the output data
- * pulDataLen: pointer to the length of the output data
- * Update: boolean flag indicates caller is kms_decrypt
- * or kms_decrypt_update
- *
- * Description:
- * This function calls the corresponding decrypt routine based
- * on the mechanism.
- *
- * Returns:
- * CKR_OK: success
- * CKR_BUFFER_TOO_SMALL: the output buffer provided by application
- * is too small
- * CKR_ENCRYPTED_DATA_LEN_RANGE: the input data is not a multiple
- * of blocksize
- * CKR_FUNCTION_FAILED: decrypt function failed
- */
-CK_RV
-kms_aes_decrypt_common(kms_session_t *session_p, CK_BYTE_PTR pEncrypted,
- CK_ULONG ulEncryptedLen, CK_BYTE_PTR pData,
- CK_ULONG_PTR pulDataLen, boolean_t update)
-{
-
- int rc = 0;
- CK_RV rv = CKR_OK;
- kms_aes_ctx_t *kms_aes_ctx =
- (kms_aes_ctx_t *)session_p->decrypt.context;
- aes_ctx_t *aes_ctx;
- CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
- CK_BYTE *in_buf = NULL;
- CK_BYTE *out_buf = NULL;
- CK_ULONG out_len;
- CK_ULONG total_len;
- CK_ULONG remain;
-
- if (mechanism == CKM_AES_CTR)
- goto do_decryption;
-
- /*
- * AES only takes input length that is a multiple of 16 bytes
- * for C_Decrypt function with the mechanism CKM_AES_ECB,
- * CKM_AES_CBC or CKM_AES_CBC_PAD.
- *
- * AES allows any input length for C_DecryptUpdate function.
- */
- if (!update) {
- /*
- * Called by C_Decrypt
- */
- if ((ulEncryptedLen % AES_BLOCK_LEN) != 0) {
- rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
- goto cleanup;
- }
-
- /*
- * If application asks for the length of the output buffer
- * to hold the plaintext?
- */
- if (pData == NULL) {
- *pulDataLen = ulEncryptedLen;
- return (CKR_OK);
- }
-
- /* Is the application-supplied buffer large enough? */
- if (mechanism != CKM_AES_CBC_PAD) {
- if (*pulDataLen < ulEncryptedLen) {
- *pulDataLen = ulEncryptedLen;
- return (CKR_BUFFER_TOO_SMALL);
- }
- out_len = ulEncryptedLen;
- } else {
- /*
- * For CKM_AES_CBC_PAD, we don't know how
- * many bytes for padding at this time, so
- * we'd assume one block was padded.
- */
- if (*pulDataLen < (ulEncryptedLen - AES_BLOCK_LEN)) {
- *pulDataLen = ulEncryptedLen - AES_BLOCK_LEN;
- return (CKR_BUFFER_TOO_SMALL);
- }
- out_len = ulEncryptedLen - AES_BLOCK_LEN;
- }
- in_buf = pEncrypted;
- out_buf = pData;
- } else {
- /*
- * Called by C_DecryptUpdate
- *
- * Add the lengths of last remaining data and current
- * input data together to get the total input length.
- */
- total_len = kms_aes_ctx->remain_len + ulEncryptedLen;
-
- /*
- * If the total input length is less than one blocksize,
- * or if the total input length is just one blocksize and
- * the mechanism is CKM_AES_CBC_PAD, we will need to delay
- * decryption until when more data comes in next
- * C_DecryptUpdate or when C_DecryptFinal is called.
- */
- if ((total_len < AES_BLOCK_LEN) ||
- ((mechanism == CKM_AES_CBC_PAD) &&
- (total_len == AES_BLOCK_LEN))) {
- if (pData != NULL) {
- /*
- * Save input data and its length in
- * the remaining buffer of AES context.
- */
- (void) memcpy(kms_aes_ctx->data +
- kms_aes_ctx->remain_len,
- pEncrypted, ulEncryptedLen);
- kms_aes_ctx->remain_len += ulEncryptedLen;
- }
-
- /* Set output data length to 0. */
- *pulDataLen = 0;
- return (CKR_OK);
- }
-
- /* Compute the length of remaing data. */
- remain = total_len % AES_BLOCK_LEN;
-
- /*
- * Make sure that the output length is a multiple of
- * blocksize.
- */
- out_len = total_len - remain;
-
- if (mechanism == CKM_AES_CBC_PAD) {
- /*
- * If the input data length is a multiple of
- * blocksize, then save the last block of input
- * data in the remaining buffer. C_DecryptFinal
- * will handle this last block of data.
- */
- if (remain == 0) {
- remain = AES_BLOCK_LEN;
- out_len -= AES_BLOCK_LEN;
- }
- }
-
- /*
- * 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 (kms_aes_ctx->remain_len != 0) {
- /*
- * Copy last remaining data and current input data
- * to the output buffer.
- */
- (void) memmove(pData + kms_aes_ctx->remain_len,
- pEncrypted, out_len - kms_aes_ctx->remain_len);
- (void) memcpy(pData, kms_aes_ctx->data,
- kms_aes_ctx->remain_len);
- bzero(kms_aes_ctx->data, kms_aes_ctx->remain_len);
-
- in_buf = pData;
- } else {
- in_buf = pEncrypted;
- }
- out_buf = pData;
- }
-
-do_decryption:
- /*
- * Begin Decryption.
- */
- switch (mechanism) {
- case CKM_AES_CBC:
- case CKM_AES_CBC_PAD:
- {
- crypto_data_t out;
- CK_ULONG rem_len;
- uint8_t last_block[AES_BLOCK_LEN];
-
- 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. */
- rc = aes_decrypt_contiguous_blocks(
- (aes_ctx_t *)kms_aes_ctx->aes_cbc,
- (char *)in_buf, out_len, &out);
-
- if (rc != 0)
- goto decrypt_failed;
-
- if ((mechanism == CKM_AES_CBC_PAD) && (!update)) {
- /* Decrypt last block containing pad bytes. */
- out.cd_offset = 0;
- out.cd_length = AES_BLOCK_LEN;
- out.cd_raw.iov_base = (char *)last_block;
- out.cd_raw.iov_len = AES_BLOCK_LEN;
-
- /* Decrypt last block containing pad bytes. */
- rc = aes_decrypt_contiguous_blocks(
- (aes_ctx_t *)kms_aes_ctx->aes_cbc,
- (char *)in_buf + out_len, AES_BLOCK_LEN, &out);
-
- if (rc != 0)
- goto decrypt_failed;
-
- /*
- * Remove padding bytes after decryption of
- * ciphertext block to produce the original
- * plaintext.
- */
- rv = kms_remove_pkcs7_padding(last_block,
- AES_BLOCK_LEN, &rem_len, AES_BLOCK_LEN);
- if (rv == CKR_OK) {
- if (rem_len != 0)
- (void) memcpy(out_buf + out_len,
- last_block, rem_len);
- *pulDataLen = out_len + rem_len;
- } else {
- *pulDataLen = 0;
- goto cleanup;
- }
- } else {
- *pulDataLen = out_len;
- }
-
- if (update) {
- /*
- * For decrypt update, if there is remaining data,
- * save it and its length in the context.
- */
- if (remain != 0)
- (void) memcpy(kms_aes_ctx->data, pEncrypted +
- (ulEncryptedLen - remain), remain);
- kms_aes_ctx->remain_len = remain;
- }
-
- if (rc == 0)
- break;
-decrypt_failed:
- *pulDataLen = 0;
- rv = CKR_FUNCTION_FAILED;
- goto cleanup;
- }
- default:
- rv = CKR_MECHANISM_INVALID;
- goto cleanup;
- } /* end switch */
-
- if (update)
- return (CKR_OK);
-
- /*
- * The following code will be executed if the caller is
- * kms_decrypt() or an error occurred. The decryption
- * operation will be terminated so we need to do some cleanup.
- */
-cleanup:
- (void) pthread_mutex_lock(&session_p->session_mutex);
- aes_ctx = (aes_ctx_t *)kms_aes_ctx->aes_cbc;
- if (aes_ctx != NULL) {
- bzero(aes_ctx->ac_keysched, aes_ctx->ac_keysched_len);
- free(kms_aes_ctx->aes_cbc);
- }
-
- bzero(kms_aes_ctx->key_sched, kms_aes_ctx->keysched_len);
- free(kms_aes_ctx->key_sched);
- free(session_p->decrypt.context);
- session_p->decrypt.context = NULL;
- (void) pthread_mutex_unlock(&session_p->session_mutex);
-
- return (rv);
-}
-
-
-/*
- * Allocate and initialize a context for AES CBC mode of operation.
- */
-void *
-aes_cbc_ctx_init(void *key_sched, size_t size, uint8_t *ivec)
-{
- aes_ctx_t *aes_ctx;
-
- if ((aes_ctx = calloc(1, sizeof (aes_ctx_t))) == NULL)
- return (NULL);
-
- aes_ctx->ac_keysched = key_sched;
-
- (void) memcpy(&aes_ctx->ac_iv[0], ivec, AES_BLOCK_LEN);
-
- aes_ctx->ac_lastp = (uint8_t *)aes_ctx->ac_iv;
- aes_ctx->ac_keysched_len = size;
- aes_ctx->ac_flags |= CBC_MODE;
-
- return ((void *)aes_ctx);
-}
-
-/*
- * kms_encrypt_final()
- *
- * Arguments:
- * session_p: pointer to kms_session_t struct
- * pLastEncryptedPart: pointer to the last encrypted data part
- * pulLastEncryptedPartLen: pointer to the length of the last
- * encrypted data part
- *
- * Description:
- * called by C_EncryptFinal().
- *
- * Returns:
- * CKR_OK: success
- * CKR_FUNCTION_FAILED: encrypt final function failed
- * CKR_DATA_LEN_RANGE: remaining buffer contains bad length
- */
-CK_RV
-kms_aes_encrypt_final(kms_session_t *session_p, CK_BYTE_PTR pLastEncryptedPart,
- CK_ULONG_PTR pulLastEncryptedPartLen)
-{
-
- CK_MECHANISM_TYPE mechanism = session_p->encrypt.mech.mechanism;
- CK_ULONG out_len;
- CK_RV rv = CKR_OK;
- int rc;
-
- (void) pthread_mutex_lock(&session_p->session_mutex);
-
- if (session_p->encrypt.context == NULL) {
- rv = CKR_OPERATION_NOT_INITIALIZED;
- *pulLastEncryptedPartLen = 0;
-
- }
- if (mechanism == CKM_AES_CBC_PAD) {
- kms_aes_ctx_t *aes_ctx;
-
- aes_ctx = (kms_aes_ctx_t *)session_p->encrypt.context;
- /*
- * For CKM_AES_CBC_PAD, compute output length with
- * padding. If the remaining buffer has one block
- * of data, then output length will be two blocksize of
- * ciphertext. If the remaining buffer has less than
- * one block of data, then output length will be
- * one blocksize.
- */
- if (aes_ctx->remain_len == AES_BLOCK_LEN)
- out_len = 2 * AES_BLOCK_LEN;
- else
- out_len = AES_BLOCK_LEN;
-
- if (pLastEncryptedPart == NULL) {
- /*
- * Application asks for the length of the output
- * buffer to hold the ciphertext.
- */
- *pulLastEncryptedPartLen = out_len;
- goto clean1;
- } else {
- crypto_data_t out;
-
- /* Copy remaining data to the output buffer. */
- (void) memcpy(pLastEncryptedPart, aes_ctx->data,
- aes_ctx->remain_len);
-
- /*
- * Add padding bytes prior to encrypt final.
- */
- kms_add_pkcs7_padding(pLastEncryptedPart +
- aes_ctx->remain_len, AES_BLOCK_LEN,
- aes_ctx->remain_len);
-
- out.cd_format = CRYPTO_DATA_RAW;
- out.cd_offset = 0;
- out.cd_length = out_len;
- out.cd_raw.iov_base = (char *)pLastEncryptedPart;
- out.cd_raw.iov_len = out_len;
-
- /* Encrypt multiple blocks of data. */
- rc = aes_encrypt_contiguous_blocks(
- (aes_ctx_t *)aes_ctx->aes_cbc,
- (char *)pLastEncryptedPart, out_len, &out);
-
- if (rc == 0) {
- *pulLastEncryptedPartLen = out_len;
- } else {
- *pulLastEncryptedPartLen = 0;
- rv = CKR_FUNCTION_FAILED;
- }
-
- /* Cleanup memory space. */
- free(aes_ctx->aes_cbc);
- bzero(aes_ctx->key_sched,
- aes_ctx->keysched_len);
- free(aes_ctx->key_sched);
- }
- } else if (mechanism == CKM_AES_CBC) {
- kms_aes_ctx_t *aes_ctx;
-
- aes_ctx = (kms_aes_ctx_t *)session_p->encrypt.context;
- /*
- * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
- * so when the final is called, the remaining buffer
- * should not contain any more data.
- */
- *pulLastEncryptedPartLen = 0;
- if (aes_ctx->remain_len != 0) {
- rv = CKR_DATA_LEN_RANGE;
- } else {
- if (pLastEncryptedPart == NULL)
- goto clean1;
- }
-
- /* Cleanup memory space. */
- free(aes_ctx->aes_cbc);
- bzero(aes_ctx->key_sched, aes_ctx->keysched_len);
- free(aes_ctx->key_sched);
- } else {
- rv = CKR_MECHANISM_INVALID;
- }
-
- free(session_p->encrypt.context);
- session_p->encrypt.context = NULL;
-clean1:
- (void) pthread_mutex_unlock(&session_p->session_mutex);
- return (rv);
-}
-
-/*
- * kms_decrypt_final()
- *
- * Arguments:
- * session_p: pointer to kms_session_t struct
- * pLastPart: pointer to the last recovered data part
- * pulLastPartLen: pointer to the length of the last recovered data part
- *
- * Description:
- * called by C_DecryptFinal().
- *
- * Returns:
- * CKR_OK: success
- * CKR_FUNCTION_FAILED: decrypt final function failed
- * CKR_ENCRYPTED_DATA_LEN_RANGE: remaining buffer contains bad length
- */
-CK_RV
-kms_aes_decrypt_final(kms_session_t *session_p, CK_BYTE_PTR pLastPart,
- CK_ULONG_PTR pulLastPartLen)
-{
-
- CK_MECHANISM_TYPE mechanism = session_p->decrypt.mech.mechanism;
- CK_ULONG out_len;
- CK_RV rv = CKR_OK;
- int rc;
-
- (void) pthread_mutex_lock(&session_p->session_mutex);
-
- if (session_p->decrypt.context == NULL) {
- rv = CKR_OPERATION_NOT_INITIALIZED;
- *pulLastPartLen = 0;
- goto clean2;
- }
- switch (mechanism) {
-
- case CKM_AES_CBC_PAD:
- {
- kms_aes_ctx_t *kms_aes_ctx;
- kms_aes_ctx = (kms_aes_ctx_t *)session_p->decrypt.context;
-
- /*
- * We should have only one block of data left in the
- * remaining buffer.
- */
- if (kms_aes_ctx->remain_len != AES_BLOCK_LEN) {
- *pulLastPartLen = 0;
- rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
- /* Cleanup memory space. */
- free(kms_aes_ctx->aes_cbc);
- bzero(kms_aes_ctx->key_sched,
- kms_aes_ctx->keysched_len);
- free(kms_aes_ctx->key_sched);
-
- goto clean1;
- }
-
- out_len = AES_BLOCK_LEN;
-
- /*
- * If application asks for the length of the output buffer
- * to hold the plaintext?
- */
- if (pLastPart == NULL) {
- *pulLastPartLen = out_len;
- rv = CKR_OK;
- goto clean2;
- } else {
- crypto_data_t out;
-
- /* Copy remaining data to the output buffer. */
- (void) memcpy(pLastPart, kms_aes_ctx->data,
- AES_BLOCK_LEN);
-
- out.cd_format = CRYPTO_DATA_RAW;
- out.cd_offset = 0;
- out.cd_length = AES_BLOCK_LEN;
- out.cd_raw.iov_base = (char *)pLastPart;
- out.cd_raw.iov_len = AES_BLOCK_LEN;
-
- /* Decrypt final block of data. */
- rc = aes_decrypt_contiguous_blocks(
- (aes_ctx_t *)kms_aes_ctx->aes_cbc,
- (char *)pLastPart, AES_BLOCK_LEN, &out);
-
- if (rc == 0) {
- /*
- * Remove padding bytes after decryption of
- * ciphertext block to produce the original
- * plaintext.
- */
- rv = kms_remove_pkcs7_padding(pLastPart,
- AES_BLOCK_LEN, &out_len, AES_BLOCK_LEN);
- if (rv != CKR_OK)
- *pulLastPartLen = 0;
- else
- *pulLastPartLen = out_len;
- } else {
- *pulLastPartLen = 0;
- rv = CKR_FUNCTION_FAILED;
- }
-
- /* Cleanup memory space. */
- free(kms_aes_ctx->aes_cbc);
- bzero(kms_aes_ctx->key_sched,
- kms_aes_ctx->keysched_len);
- free(kms_aes_ctx->key_sched);
-
- }
-
- break;
- }
-
- case CKM_AES_CBC:
- {
- kms_aes_ctx_t *kms_aes_ctx;
-
- kms_aes_ctx = (kms_aes_ctx_t *)session_p->decrypt.context;
- /*
- * CKM_AES_CBC and CKM_AES_ECB does not do any padding,
- * so when the final is called, the remaining buffer
- * should not contain any more data.
- */
- *pulLastPartLen = 0;
- if (kms_aes_ctx->remain_len != 0) {
- rv = CKR_ENCRYPTED_DATA_LEN_RANGE;
- } else {
- if (pLastPart == NULL)
- goto clean2;
- }
-
- /* Cleanup memory space. */
- free(kms_aes_ctx->aes_cbc);
- bzero(kms_aes_ctx->key_sched, kms_aes_ctx->keysched_len);
- free(kms_aes_ctx->key_sched);
-
- break;
- }
- default:
- /* PKCS11: The mechanism only supports single-part operation. */
- rv = CKR_MECHANISM_INVALID;
- break;
- }
-
-clean1:
- free(session_p->decrypt.context);
- session_p->decrypt.context = NULL;
-
-clean2:
- (void) pthread_mutex_unlock(&session_p->session_mutex);
-
- return (rv);
-
-}