fips_aes_util.c revision 32e0ab73531b6e6e8957e9ecdbbd42603865f2d0
/*
* 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
* 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
*/
/*
*/
#define _AES_FIPS_POST
#include <fips/fips_test_vectors.h>
#ifndef _KERNEL
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <stdio.h>
#include <security/cryptoki.h>
#include <cryptoutil.h>
#include "softCrypt.h"
#else
#define _AES_IMPL
#include <aes/aes_impl.h>
#endif
#ifdef _KERNEL
void *
{
return (NULL);
return (cbc_ctx);
}
/*
* Allocate and initialize a context for AES CTR mode of operation.
*/
void *
{
/* LINTED: pointer alignment */
return (NULL);
aes_copy_block) != CRYPTO_SUCCESS) {
return (NULL);
}
return (ctr_ctx);
}
/*
* Allocate and initialize a context for AES CCM mode of operation.
*/
void *
{
return (NULL);
aes_xor_block) != CRYPTO_SUCCESS) {
return (NULL);
}
return (ccm_ctx);
}
/*
* Allocate and initialize a context for AES CCM mode of operation.
*/
void *
{
return (NULL);
aes_xor_block) != CRYPTO_SUCCESS) {
return (NULL);
}
return (gcm_ctx);
}
void *
{
return (NULL);
aes_xor_block) != CRYPTO_SUCCESS) {
return (NULL);
}
return (gcm_ctx);
}
#endif
/*
* Allocate context for the active encryption or decryption operation, and
* generate AES key schedule to speed up the operation.
*/
#ifdef _KERNEL
#else
#endif
{
#ifdef _KERNEL
#else
== NULL)
#endif
return (NULL);
#ifdef _KERNEL
#else
#endif
return (NULL);
}
#ifdef __sparcv9
#else /* !__sparcv9 */
#endif /* __sparcv9 */
switch (mechanism) {
case CKM_AES_CBC:
/* Save Initialization Vector (IV) in the context. */
/* Allocate a context for AES cipher-block chaining. */
soft_aes_ctx->ivec);
break;
case CKM_AES_CTR:
break;
#ifdef _KERNEL
case AES_CCM_MECH_INFO_TYPE:
break;
case AES_GCM_MECH_INFO_TYPE:
break;
case AES_GMAC_MECH_INFO_TYPE:
break;
#endif
default:
return (soft_aes_ctx);
}
#ifdef _KERNEL
#else
#endif
return (NULL);
}
return (soft_aes_ctx);
}
#ifdef _KERNEL
void
{
} else {
/* ECB MODE */
}
}
#else
void
{
} else {
/* ECB MODE */
}
}
#endif
/*
* fips_aes_encrypt()
*
* Arguments:
* soft_aes_ctx: pointer to AES context
* in_buf: pointer to the input data to be encrypted
* ulDataLen: length of the input data
* out_buf: pointer to the output data after encryption
* pulEncryptedLen: pointer to the length of the output data
* mechanism: CKM_AES_ECB or CKM_AES_CBC
*
* Description:
* This function calls the corresponding low-level encrypt
* routine based on the mechanism.
*
*/
#ifdef _KERNEL
int
#else
#endif
{
int rc = 0;
/*
* AES only takes input length that is a multiple of 16-byte
*/
if ((ulDataLen % AES_BLOCK_LEN) != 0)
return (CKR_DATA_LEN_RANGE);
/*
* For non-padding mode, the output length will
* be same as the input length.
*/
/*
* Begin Encryption now.
*/
switch (mechanism) {
case CKM_AES_ECB:
{
ulong_t i;
for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
tmp_outbuf = &out_buf[i];
/* Crunch one block of data for AES. */
}
break;
}
case CKM_AES_CBC:
{
/* Encrypt multiple blocks of data. */
if (rc != 0)
goto encrypt_failed;
if (rc == 0) {
break;
}
*pulEncryptedLen = 0;
return (CKR_DEVICE_ERROR);
}
case CKM_AES_CTR:
{
if (rc != 0) {
*pulEncryptedLen = 0;
return (CKR_DEVICE_ERROR);
}
/*
* Since AES counter mode is a stream cipher, we call
* aes_counter_final() to pick up any remaining bytes.
* It is an internal function that does not destroy
* the context like *normal* final routines.
*/
> 0) {
if (rc != 0) {
*pulEncryptedLen = 0;
return (CKR_DEVICE_ERROR);
}
}
break;
}
#ifdef _KERNEL
case AES_CCM_MECH_INFO_TYPE:
{
if (rc != 0) {
*pulEncryptedLen = 0;
return (rc);
}
/*
* ccm_encrypt_final() will compute the MAC and append
* it to existing ciphertext. So, need to adjust the left over
* length value accordingly
*/
/* order of following 2 lines MUST not be reversed */
if (rc != CRYPTO_SUCCESS) {
*pulEncryptedLen = 0;
return (rc);
}
break;
}
case AES_GCM_MECH_INFO_TYPE:
{
/*
* Output:
* A ciphertext, denoted C, whose bit length is the same as
* that of the plaintext.
* An authentication tag, or tag, for short, denoted T.
*/
if (rc != 0) {
*pulEncryptedLen = 0;
return (rc);
}
/*
* ccm_encrypt_final() will compute the MAC and append
* it to existing ciphertext. So, need to adjust the left over
* length value accordingly
*/
/* order of following 2 lines MUST not be reversed */
if (rc != CRYPTO_SUCCESS) {
*pulEncryptedLen = 0;
return (rc);
}
break;
}
case AES_GMAC_MECH_INFO_TYPE:
{
if (rc != CRYPTO_SUCCESS) {
*pulEncryptedLen = 0;
return (rc);
}
break;
}
#endif /* _KERNEL */
} /* end switch */
return (rv);
}
/*
* fips_aes_decrypt()
*
* Arguments:
* soft_aes_ctx: pointer to AES context
* in_buf: pointer to the input data to be decrypted
* ulEncryptedLen: length of the input data
* out_buf: pointer to the output data
* pulDataLen: pointer to the length of the output data
* mechanism: CKM_AES_ECB or CKM_AES_CBC
*
* Description:
* This function calls the corresponding low-level decrypt
* function based on the mechanism.
*
*/
#ifdef _KERNEL
int
#else
#endif
{
int rc = 0;
/*
* AES only takes input length that is a multiple of 16 bytes
*/
if ((ulEncryptedLen % AES_BLOCK_LEN) != 0)
return (CKR_ENCRYPTED_DATA_LEN_RANGE);
/*
* For non-padding mode, the output length will
* be same as the input length.
*/
/*
* Begin Decryption.
*/
switch (mechanism) {
case CKM_AES_ECB:
{
ulong_t i;
for (i = 0; i < out_len; i += AES_BLOCK_LEN) {
tmp_outbuf = &out_buf[i];
/* Crunch one block of data for AES. */
}
*pulDataLen = out_len;
break;
}
case CKM_AES_CBC:
{
/* Decrypt multiple blocks of data. */
if (rc != 0)
goto decrypt_failed;
*pulDataLen = out_len;
if (rc == 0)
break;
*pulDataLen = 0;
return (CKR_DEVICE_ERROR);
}
case CKM_AES_CTR:
{
if (rc != 0) {
*pulDataLen = 0;
return (CKR_DEVICE_ERROR);
}
/*
* Since AES counter mode is a stream cipher, we call
* aes_counter_final() to pick up any remaining bytes.
* It is an internal function that does not destroy
* the context like *normal* final routines.
*/
> 0) {
if (rc == CKR_DATA_LEN_RANGE)
return (CKR_ENCRYPTED_DATA_LEN_RANGE);
}
*pulDataLen = out_len;
break;
}
#ifdef _KERNEL
case AES_CCM_MECH_INFO_TYPE:
{
if (rc != 0) {
*pulDataLen = 0;
return (CRYPTO_FAILED);
}
/* order of following 2 lines MUST not be reversed */
if (rc != CRYPTO_SUCCESS) {
*pulDataLen = 0;
return (CRYPTO_FAILED);
}
break;
}
case AES_GCM_MECH_INFO_TYPE:
{
if (rc != 0) {
*pulDataLen = 0;
return (CRYPTO_FAILED);
}
/* order of following 2 lines MUST not be reversed */
if (rc != CRYPTO_SUCCESS) {
*pulDataLen = 0;
return (CRYPTO_FAILED);
}
break;
}
case AES_GMAC_MECH_INFO_TYPE:
{
if (rc != 0) {
*pulDataLen = 0;
return (CRYPTO_FAILED);
}
/* order of following 2 lines MUST not be reversed */
if (rc != CRYPTO_SUCCESS) {
*pulDataLen = 0;
return (CRYPTO_FAILED);
}
*pulDataLen = 0;
break;
}
#endif
} /* end switch */
return (rv);
}
/* AES self-test for 128-bit, 192-bit, or 256-bit key sizes */
int
{
#ifdef _KERNEL
/* AES variables. */
#endif
int rv;
/* check if aes_key_size is 128, 192, or 256 bits */
if ((aes_key_size != FIPS_AES_128_KEY_SIZE) &&
(aes_key_size != FIPS_AES_192_KEY_SIZE) &&
return (CKR_DEVICE_ERROR);
/*
* AES-ECB Known Answer Encryption Test
*/
#ifdef _KERNEL
#else
#endif
if (aes_context == NULL) {
return (CKR_HOST_MEMORY);
}
FIPS_AES_ENCRYPT_LENGTH) != 0))
return (CKR_DEVICE_ERROR);
/*
* AES-ECB Known Answer Decryption Test
*/
#ifdef _KERNEL
#else
#endif
if (aes_context == NULL) {
return (CKR_HOST_MEMORY);
}
FIPS_AES_DECRYPT_LENGTH) != 0))
return (CKR_DEVICE_ERROR);
/*
* AES-CBC Known Answer Encryption Test
*/
#ifdef _KERNEL
#else
#endif
if (aes_context == NULL) {
return (CKR_HOST_MEMORY);
}
FIPS_AES_ENCRYPT_LENGTH) != 0))
return (CKR_DEVICE_ERROR);
/*
* AES-CBC Known Answer Decryption Test
*/
#ifdef _KERNEL
#else
#endif
if (aes_context == NULL)
return (CRYPTO_HOST_MEMORY);
FIPS_AES_DECRYPT_LENGTH) != 0))
return (CKR_DEVICE_ERROR);
/*
* AES-CTR Known Answer Encryption Test
*/
#ifdef _KERNEL
#else
#endif
if (aes_context == NULL) {
return (CKR_HOST_MEMORY);
}
FIPS_AES_ENCRYPT_LENGTH) != 0))
return (CKR_DEVICE_ERROR);
/*
* AES-CTR Known Answer Decryption Test
*/
#ifdef _KERNEL
#else
#endif
if (aes_context == NULL) {
return (CKR_HOST_MEMORY);
}
FIPS_AES_DECRYPT_LENGTH) != 0))
return (CKR_DEVICE_ERROR);
/*
* The following POSTs are only available in Kernel
*
* CCM, GCM, and GMAC
*/
#ifdef _KERNEL
/*
* AES-CCM Known Answer Encryption Test
*/
if (aes_context == NULL) {
return (CRYPTO_HOST_MEMORY);
}
if ((rv != CRYPTO_SUCCESS) ||
3*FIPS_AES_ENCRYPT_LENGTH) != 0))
return (CRYPTO_DEVICE_ERROR);
/*
* AES-CCM Known Answer Decryption Test
*/
if (aes_context == NULL) {
return (CRYPTO_HOST_MEMORY);
}
if ((rv != CRYPTO_SUCCESS) ||
2*FIPS_AES_DECRYPT_LENGTH) != 0))
return (CRYPTO_DEVICE_ERROR);
/*
* AES-GCM Known Answer Encryption Test
*/
if (aes_context == NULL) {
return (CRYPTO_HOST_MEMORY);
}
if ((rv != CRYPTO_SUCCESS) ||
2*FIPS_AES_ENCRYPT_LENGTH) != 0))
return (CRYPTO_DEVICE_ERROR);
/*
* AES-GCM Known Answer Decryption Test
*/
if (aes_context == NULL) {
return (CRYPTO_HOST_MEMORY);
}
if ((rv != CRYPTO_SUCCESS) ||
FIPS_AES_DECRYPT_LENGTH) != 0))
return (CRYPTO_DEVICE_ERROR);
/*
* AES-GMAC Known Answer Encryption Test
*/
if (aes_context == NULL) {
return (CRYPTO_HOST_MEMORY);
}
if ((rv != CRYPTO_SUCCESS) ||
FIPS_AES_ENCRYPT_LENGTH) != 0))
return (CRYPTO_DEVICE_ERROR);
/*
* AES-GMAC Known Answer Decryption Test
*/
if (aes_context == NULL) {
return (CRYPTO_HOST_MEMORY);
}
if ((rv != CRYPTO_SUCCESS) ||
(aes_bytes_decrypted != 0))
return (CRYPTO_DEVICE_ERROR);
#endif /* _KERNEL */
return (CRYPTO_SUCCESS);
}