mbed-os/features/cryptocell/FEATURE_CRYPTOCELL310/aes_alt.c

309 lines
10 KiB
C

/*
* aes_alt.c
*
* Copyright (C) 2019, Arm Limited, All Rights Reserved
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
*/
#include "mbedtls/aes.h"
#if defined(MBEDTLS_AES_ALT)
#include <string.h>
#include "ssi_aes_defs.h"
#include "mbedtls/platform.h"
#if defined(MBEDTLS_CIPHER_MODE_CFB)
/*
* AES-CFB128 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx,
int mode,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}
/*
* AES-CFB8 buffer encryption/decryption
*/
int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}
#endif /*MBEDTLS_CIPHER_MODE_CFB */
#if defined(MBEDTLS_CIPHER_MODE_XTS)
int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits )
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}
int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx,
const unsigned char *key,
unsigned int keybits )
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}
int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx,
int mode,
size_t length,
const unsigned char data_unit[16],
const unsigned char *input,
unsigned char *output )
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
#if defined(MBEDTLS_CIPHER_MODE_OFB)
int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx,
size_t length,
size_t *iv_off,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output );
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}
#endif /* MBEDTLS_CIPHER_MODE_OFB */
void mbedtls_aes_init( mbedtls_aes_context *ctx )
{
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
}
void mbedtls_aes_free( mbedtls_aes_context *ctx )
{
if( ctx == NULL )
return;
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) );
}
#if defined(MBEDTLS_CIPHER_MODE_XTS)
void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ){}
void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ){}
#endif /* MBEDTLS_CIPHER_MODE_XTS */
static int CC_aes_setkey( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits, SaSiAesEncryptMode_t cipher_flag )
{
int ret = 0;
if( ctx == NULL )
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
switch( keybits )
{
case 128:
{
ctx->CC_cipherFlag = cipher_flag;
ctx->CC_keySizeInBytes = ( keybits / 8 );
memcpy( ctx->CC_Key, key, ctx->CC_keySizeInBytes );
}
break;
case 192:
case 256:
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
default:
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
}
return( 0 );
}
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
return( CC_aes_setkey( ctx, key, keybits, SASI_AES_ENCRYPT ) );
}
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
unsigned int keybits )
{
return( CC_aes_setkey( ctx, key, keybits, SASI_AES_DECRYPT ) );
}
static int CC_aes_cipher( mbedtls_aes_context *ctx,
int mode,
SaSiAesOperationMode_t aes_mode,
size_t length,
unsigned char* iv,
size_t iv_len,
const unsigned char *input,
unsigned char *output )
{
int ret = 0;
SaSiAesUserKeyData_t CC_KeyData = { ctx->CC_Key,
ctx->CC_keySizeInBytes };
ret = SaSi_AesInit( &ctx->CC_Context,
ctx->CC_cipherFlag,
aes_mode, SASI_AES_PADDING_NONE );
if( ret != 0 )
return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
ret = SaSi_AesSetKey( &ctx->CC_Context, SASI_AES_USER_KEY,
&CC_KeyData, sizeof( CC_KeyData ) );
if( ret != 0 )
return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
if( iv )
{
if( iv_len != SASI_AES_IV_SIZE_IN_BYTES )
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
ret = SaSi_AesSetIv( &ctx->CC_Context, iv );
if( ret != 0 )
return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
}
ret = SaSi_AesFinish( &ctx->CC_Context, length,
( unsigned char* )input, length, output, &length );
if( ret != 0 )
return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
/* update the IV for next block
* For CTR mode, update the nonce only if the current length is a full AES block length
*/
if( ( ( aes_mode == SASI_AES_MODE_CBC ) ||
( (aes_mode == SASI_AES_MODE_CTR) && ( ( length % SASI_AES_BLOCK_SIZE_IN_BYTES) == 0) ) )
&& iv )
{
ret = SaSi_AesGetIv( &ctx->CC_Context, iv );
if( ret != 0 )
return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
}
ret = SaSi_AesFree( &ctx->CC_Context );
if( ret != 0 )
return( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
return( 0 );
}
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
int mode,
const unsigned char input[16],
unsigned char output[16] )
{
if( ctx == NULL )
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
if( ( mode == MBEDTLS_AES_ENCRYPT && ctx->CC_cipherFlag != SASI_AES_ENCRYPT ) ||
( mode == MBEDTLS_AES_DECRYPT && ctx->CC_cipherFlag != SASI_AES_DECRYPT ) )
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
return( CC_aes_cipher( ctx, mode, SASI_AES_MODE_ECB, 16, NULL, 0, input, output ) );
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx,
int mode,
size_t length,
unsigned char iv[16],
const unsigned char *input,
unsigned char *output )
{
if( ctx == NULL )
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
if( length % SASI_AES_BLOCK_SIZE_IN_BYTES )
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
if( ( mode != MBEDTLS_AES_ENCRYPT || ctx->CC_cipherFlag != SASI_AES_ENCRYPT ) &&
( mode != MBEDTLS_AES_DECRYPT || ctx->CC_cipherFlag != SASI_AES_DECRYPT ) )
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
return( CC_aes_cipher( ctx, mode, SASI_AES_MODE_CBC, length, iv, 16, input, output ) );
}
#endif /* MBEDTLS_CIPHER_MODE_CBC */
#if defined(MBEDTLS_CIPHER_MODE_CTR)
int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx,
size_t length,
size_t *nc_off,
unsigned char nonce_counter[16],
unsigned char stream_block[16],
const unsigned char *input,
unsigned char *output )
{
int ret = 0;
int n = *nc_off, c, i;
size_t j;
if( ctx == NULL )
return( MBEDTLS_ERR_AES_BAD_INPUT_DATA );
if( *nc_off )
{
/* handle corner case where we are resuming a previous encryption,
* and we are resuming within current cipher stream(stream_block) */
while( n != 0 )
{
c = *input++;
*output++ = (unsigned char)( c ^ stream_block[n] );
n = ( n + 1) & 0x0F;
if( length > 0)
--length;
}
/*
* Increase the nonce_counter by 1 since we now passed one block
*/
for( i = 16; i > 0; i-- )
if( ++nonce_counter[i - 1] != 0 )
break;
}
if( CC_aes_cipher( ctx, MBEDTLS_AES_ENCRYPT, SASI_AES_MODE_CTR,
length, nonce_counter, SASI_AES_IV_SIZE_IN_BYTES, input, output ) != 0 )
{
ret = -1;
}
if( ( ( length % SASI_AES_BLOCK_SIZE_IN_BYTES ) != 0 ) && ret == 0 )
{
/* in case the length is not aligned, generate stream block for resuming
* increase nonce_block to the correct value*/
for( j = 0; j < ( length/SASI_AES_BLOCK_SIZE_IN_BYTES ); j++)
for( i = 16; i > 0; i-- )
if( ++nonce_counter[i - 1] != 0 )
break;
if( ( ret = CC_aes_cipher( ctx, MBEDTLS_AES_ENCRYPT, SASI_AES_MODE_ECB,
SASI_AES_BLOCK_SIZE_IN_BYTES, NULL, 0,
nonce_counter, stream_block ) ) != 0 )
{
goto exit;
}
}
*nc_off = ( length % SASI_AES_BLOCK_SIZE_IN_BYTES );
exit:
return( ret );
}
#endif /* MBEDTLS_CIPHER_MODE_CTR */
#endif/* MBEDTLS_AES_ALT */