Skip to content

Fix issues in Cryptocell 310 ccm_alt discovered by On Target Testing #8704

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 9 commits into from
Nov 27, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
148 changes: 112 additions & 36 deletions features/cryptocell/FEATURE_CRYPTOCELL310/ccm_alt.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,9 @@
#if defined(MBEDTLS_CCM_ALT)
#include <string.h>
#include "mbedtls/platform.h"
#include "mbedtls/platform_util.h"
#include "mbedtls/aes.h"

/* Implementation that should never be optimized out by the compiler */
static void mbedtls_zeroize( void *v, size_t n ) {
volatile unsigned char *p = (unsigned char*)v;
while( n-- ) *p++ = 0;
}
#include "crys_aesccm_error.h"

void mbedtls_ccm_init( mbedtls_ccm_context *ctx )
{
Expand All @@ -37,7 +33,7 @@ void mbedtls_ccm_init( mbedtls_ccm_context *ctx )

void mbedtls_ccm_free( mbedtls_ccm_context *ctx )
{
mbedtls_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ccm_context ) );
}

int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
Expand All @@ -46,18 +42,30 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
unsigned int keybits )
{
if( ctx == NULL )
return ( MBEDTLS_ERR_CCM_BAD_INPUT );
return( MBEDTLS_ERR_CCM_BAD_INPUT );

if( cipher != MBEDTLS_CIPHER_ID_AES )
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}

if( cipher != MBEDTLS_CIPHER_ID_AES ||
keybits != 128 )
switch( keybits )
{
return ( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
case 128:
{
memcpy( ctx->cipher_key , key, keybits / 8 );
ctx->key_size = CRYS_AES_Key128BitSize;
}
break;
case 192:
case 256:
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
default:
return( MBEDTLS_ERR_CCM_BAD_INPUT );
}

memcpy( ctx->cipher_key , key, keybits / 8 );
ctx->keySize_ID = CRYS_AES_Key128BitSize;

return ( 0 );
return( 0 );

}

Expand All @@ -66,36 +74,55 @@ int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
*/

int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len )
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input,
unsigned char *output,
unsigned char *tag, size_t tag_len )

{
CRYSError_t CrysRet = CRYS_OK;
CRYSError_t crys_ret = CRYS_OK;
CRYS_AESCCM_Mac_Res_t cc_mac_res = { 0 };
int ret = 0;
/*
* Check length requirements: SP800-38C A.1
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
* 'length' checked later (when writing it to the first block)
*/
if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
return ( MBEDTLS_ERR_CCM_BAD_INPUT );
return( MBEDTLS_ERR_CCM_BAD_INPUT );

if( tag_len > sizeof( cc_mac_res ) )
return( MBEDTLS_ERR_CCM_BAD_INPUT );

/* Also implies q is within bounds */
if( iv_len < 7 || iv_len > 13 )
return ( MBEDTLS_ERR_CCM_BAD_INPUT );
return( MBEDTLS_ERR_CCM_BAD_INPUT );

#if SIZE_MAX > UINT_MAX
if( length > 0xFFFFFFFF || add_len > 0xFFFFFFFF )
return ( MBEDTLS_ERR_CCM_BAD_INPUT );
return( MBEDTLS_ERR_CCM_BAD_INPUT );
#endif

CrysRet = CRYS_AESCCM( SASI_AES_ENCRYPT, ctx->cipher_key, ctx->keySize_ID,(uint8_t*)iv, iv_len,
(uint8_t*)add, add_len, (uint8_t*)input, length, output, tag_len, tag );
if( CrysRet != CRYS_OK )
return ( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
crys_ret = CRYS_AESCCM( SASI_AES_ENCRYPT, ctx->cipher_key, ctx->key_size,
(uint8_t*)iv, iv_len, (uint8_t*)add, add_len,
(uint8_t*)input, length, output, tag_len,
cc_mac_res );
if( crys_ret == CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR )
{
ret = MBEDTLS_ERR_CCM_BAD_INPUT;
goto exit;
}
else if( crys_ret != CRYS_OK )
{
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
goto exit;
}

memcpy( tag, cc_mac_res, tag_len );

return ( 0 );
exit:
return( ret );

}

Expand All @@ -109,31 +136,80 @@ int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *tag, size_t tag_len )

{
CRYSError_t CrysRet = CRYS_OK;
CRYSError_t crys_ret = CRYS_OK;
int ret = 0;
/*
* Check length requirements: SP800-38C A.1
* Additional requirement: a < 2^16 - 2^8 to simplify the code.
* 'length' checked later (when writing it to the first block)
*/
if( tag_len < 4 || tag_len > 16 || tag_len % 2 != 0 )
return ( MBEDTLS_ERR_CCM_BAD_INPUT );
return( MBEDTLS_ERR_CCM_BAD_INPUT );

/* Also implies q is within bounds */
if( iv_len < 7 || iv_len > 13 )
return ( MBEDTLS_ERR_CCM_BAD_INPUT );
return( MBEDTLS_ERR_CCM_BAD_INPUT );

#if SIZE_MAX > UINT_MAX
if( length > 0xFFFFFFFF || add_len > 0xFFFFFFFF )
return ( MBEDTLS_ERR_CCM_BAD_INPUT );
return( MBEDTLS_ERR_CCM_BAD_INPUT );
#endif

CrysRet = CRYS_AESCCM( SASI_AES_DECRYPT, ctx->cipher_key, ctx->keySize_ID,(uint8_t*)iv, iv_len,
(uint8_t*)add, add_len, (uint8_t*)input, length, output, tag_len, (uint8_t*)tag );
if ( CrysRet != CRYS_OK )
return ( MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED );
crys_ret = CRYS_AESCCM( SASI_AES_DECRYPT, ctx->cipher_key, ctx->key_size,
(uint8_t*)iv, iv_len, (uint8_t*)add, add_len,
(uint8_t*)input, length, output, tag_len,
(uint8_t*)tag );
if( crys_ret == CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR )
{
/*
* When CRYS_AESCCM_ILLEGAL_PARAMETER_SIZE_ERROR is returned,
* no operation has occured, and no need to zeroize output.
* In addition, it could be that the message length is too big,
* returning this error code, and we don't want to overflow
* the output buffer.
*/
return( MBEDTLS_ERR_CCM_BAD_INPUT );
}
else if( crys_ret == CRYS_FATAL_ERROR )
{
/*
* Unfortunately, Crys AESCCM returns CRYS_FATAL_ERROR when
* MAC isn't as expected.
*/
ret = MBEDTLS_ERR_CCM_AUTH_FAILED;
goto exit;
}
else if( crys_ret != CRYS_OK )
{
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
goto exit;
}

return ( 0 );
exit:
if( ret != 0 )
mbedtls_platform_zeroize( output, length );
return( ret );

}

int mbedtls_ccm_star_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input,
unsigned char *output,
unsigned char *tag, size_t tag_len )
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}

int mbedtls_ccm_star_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input,
unsigned char *output,
const unsigned char *tag, size_t tag_len )
{
return( MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED );
}

#endif
97 changes: 2 additions & 95 deletions features/cryptocell/FEATURE_CRYPTOCELL310/ccm_alt.h
Original file line number Diff line number Diff line change
Expand Up @@ -24,104 +24,11 @@
#if defined(MBEDTLS_CCM_ALT)
#include "crys_aesccm.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct {
CRYS_AESCCM_Key_t cipher_key; /*!< cipher key used */
CRYS_AESCCM_KeySize_t keySize_ID;
CRYS_AESCCM_Key_t cipher_key; /*!< cipher key used */
CRYS_AESCCM_KeySize_t key_size;
}
mbedtls_ccm_context;

/**
* \brief Initialize CCM context (just makes references valid)
* Makes the context ready for mbedtls_ccm_setkey() or
* mbedtls_ccm_free().
*
* \param ctx CCM context to initialize
*/
void mbedtls_ccm_init( mbedtls_ccm_context *ctx );

/**
* \brief CCM initialization (encryption and decryption)
*
* \param ctx CCM context to be initialized
* \param cipher cipher to use (a 128-bit block cipher)
* \param key encryption key
* \param keybits key size in bits (must be acceptable by the cipher)
*
* \return 0 if successful, or a cipher specific error code
*/
int mbedtls_ccm_setkey( mbedtls_ccm_context *ctx,
mbedtls_cipher_id_t cipher,
const unsigned char *key,
unsigned int keybits );

/**
* \brief Free a CCM context and underlying cipher sub-context
*
* \param ctx CCM context to free
*/
void mbedtls_ccm_free( mbedtls_ccm_context *ctx );

/**
* \brief CCM buffer encryption
*
* \param ctx CCM context
* \param length length of the input data in bytes
* \param iv nonce (initialization vector)
* \param iv_len length of IV in bytes
* must be 2, 3, 4, 5, 6, 7 or 8
* \param add additional data
* \param add_len length of additional data in bytes
* must be less than 2^16 - 2^8
* \param input buffer holding the input data
* \param output buffer for holding the output data
* must be at least 'length' bytes wide
* \param tag buffer for holding the tag
* \param tag_len length of the tag to generate in bytes
* must be 4, 6, 8, 10, 14 or 16
*
* \note The tag is written to a separate buffer. To get the tag
* concatenated with the output as in the CCM spec, use
* tag = output + length and make sure the output buffer is
* at least length + tag_len wide.
*
* \return 0 if successful
*/
int mbedtls_ccm_encrypt_and_tag( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
unsigned char *tag, size_t tag_len );

/**
* \brief CCM buffer authenticated decryption
*
* \param ctx CCM context
* \param length length of the input data
* \param iv initialization vector
* \param iv_len length of IV
* \param add additional data
* \param add_len length of additional data
* \param input buffer holding the input data
* \param output buffer for holding the output data
* \param tag buffer holding the tag
* \param tag_len length of the tag
*
* \return 0 if successful and authenticated,
* MBEDTLS_ERR_CCM_AUTH_FAILED if tag does not match
*/
int mbedtls_ccm_auth_decrypt( mbedtls_ccm_context *ctx, size_t length,
const unsigned char *iv, size_t iv_len,
const unsigned char *add, size_t add_len,
const unsigned char *input, unsigned char *output,
const unsigned char *tag, size_t tag_len );

#ifdef __cplusplus
}
#endif

#endif /* MBEDTLS_CCM_ALT */
#endif /* __CCM_ALT__ */