mirror of https://github.com/ARMmbed/mbed-os.git
[Silicon Labs] cryptographic acceleration support
Initial commit of mbed TLS hardware acceleration drivers for Silicon Labs partspull/4825/head
parent
2305a8c7e4
commit
1e51dfa302
|
@ -0,0 +1,498 @@
|
|||
/*
|
||||
* Hardware-accelerated AES implementation for Silicon Labs devices
|
||||
* containing an AES peripheral.
|
||||
*
|
||||
* Copyright 2017, Silicon Laboratories, Inc.
|
||||
* 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_C)
|
||||
#if defined(MBEDTLS_AES_ALT)
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(AES_PRESENT) && (AES_COUNT == 1)
|
||||
#include "em_aes.h"
|
||||
#include "em_cmu.h"
|
||||
#include "em_bus.h"
|
||||
#include <string.h>
|
||||
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
#include "mbedtls/threading.h"
|
||||
#include "em_core.h"
|
||||
/* Mutex for protecting access to the AES instance */
|
||||
static mbedtls_threading_mutex_t aes_mutex;
|
||||
static volatile bool aes_mutex_inited = false;
|
||||
#endif
|
||||
|
||||
static void aes_lock( void )
|
||||
{
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
if ( !aes_mutex_inited ) {
|
||||
/* Turn off interrupts that can cause preemption */
|
||||
CORE_irqState_t critical_irq_state = CORE_EnterCritical();
|
||||
if ( !aes_mutex_inited ) {
|
||||
mbedtls_mutex_init(&aes_mutex);
|
||||
aes_mutex_inited = true;
|
||||
}
|
||||
CORE_ExitCritical(critical_irq_state);
|
||||
}
|
||||
mbedtls_mutex_lock(&aes_mutex);
|
||||
#endif
|
||||
BUS_RegBitWrite(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_AES_SHIFT, 1);
|
||||
return;
|
||||
}
|
||||
|
||||
static void aes_unlock( void )
|
||||
{
|
||||
#if defined(MBEDTLS_THREADING_C)
|
||||
if ( aes_mutex_inited ) {
|
||||
mbedtls_mutex_unlock(&aes_mutex);
|
||||
}
|
||||
#endif
|
||||
BUS_RegBitWrite(&(CMU->HFCORECLKEN0), _CMU_HFCORECLKEN0_AES_SHIFT, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize AES context
|
||||
*/
|
||||
void mbedtls_aes_init( mbedtls_aes_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear AES context
|
||||
*/
|
||||
void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
||||
{
|
||||
if( ctx == NULL )
|
||||
return;
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (encryption)
|
||||
*/
|
||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
if ( ( 128 != keybits ) && ( 256 != keybits ) )
|
||||
{
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
|
||||
ctx->keybits = keybits;
|
||||
memcpy( ctx->key, key, keybits/8 );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (decryption)
|
||||
*/
|
||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
if ( ( 128 != keybits ) && ( 256 != keybits ) )
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
|
||||
ctx->keybits = keybits;
|
||||
switch (keybits)
|
||||
{
|
||||
case 128:
|
||||
aes_lock();
|
||||
AES_DecryptKey128( ctx->key, key );
|
||||
aes_unlock();
|
||||
break;
|
||||
case 256:
|
||||
aes_lock();
|
||||
AES_DecryptKey256( ctx->key, key );
|
||||
aes_unlock();
|
||||
break;
|
||||
default:
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-ECB block encryption
|
||||
*/
|
||||
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
switch ( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
aes_lock();
|
||||
AES_ECB128( output, input, 16, ctx->key, true );
|
||||
aes_unlock();
|
||||
break;
|
||||
case 256:
|
||||
aes_lock();
|
||||
AES_ECB256( output, input, 16, ctx->key, true );
|
||||
aes_unlock();
|
||||
break;
|
||||
default:
|
||||
// Error
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-ECB block decryption
|
||||
*/
|
||||
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
switch ( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
aes_lock();
|
||||
AES_ECB128( output, input, 16, ctx->key, false );
|
||||
aes_unlock();
|
||||
break;
|
||||
case 256:
|
||||
aes_lock();
|
||||
AES_ECB256( output, input, 16, ctx->key, false );
|
||||
aes_unlock();
|
||||
break;
|
||||
default:
|
||||
// Error
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-ECB block encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
switch ( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
aes_lock();
|
||||
AES_ECB128( output,
|
||||
input,
|
||||
16,
|
||||
ctx->key,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
aes_unlock();
|
||||
break;
|
||||
case 256:
|
||||
aes_lock();
|
||||
AES_ECB256( output,
|
||||
input,
|
||||
16,
|
||||
ctx->key,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
aes_unlock();
|
||||
break;
|
||||
default:
|
||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
/*
|
||||
* AES-CBC buffer encryption/decryption
|
||||
*/
|
||||
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 )
|
||||
{
|
||||
uint8_t tmpIv[16];
|
||||
|
||||
if( length % 16 )
|
||||
{
|
||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
if ( mode == MBEDTLS_AES_DECRYPT )
|
||||
{
|
||||
if ( length >= 16 )
|
||||
memcpy( tmpIv, &input[length-16], 16 );
|
||||
}
|
||||
|
||||
switch ( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
aes_lock();
|
||||
AES_CBC128( output,
|
||||
input,
|
||||
length,
|
||||
ctx->key,
|
||||
iv,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
aes_unlock();
|
||||
break;
|
||||
case 256:
|
||||
aes_lock();
|
||||
AES_CBC256( output,
|
||||
input,
|
||||
length,
|
||||
ctx->key,
|
||||
iv,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
aes_unlock();
|
||||
break;
|
||||
default:
|
||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
if ( length >= 16 )
|
||||
{
|
||||
if ( mode == MBEDTLS_AES_ENCRYPT )
|
||||
memcpy( iv, &output[length-16], 16 );
|
||||
else
|
||||
memcpy( iv, tmpIv, 16 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||
|
||||
#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 )
|
||||
{
|
||||
size_t n = iv_off ? *iv_off : 0;
|
||||
|
||||
if ( n || ( length & 0xf ) )
|
||||
{
|
||||
// IV offset or length not aligned to block size
|
||||
int c;
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
{
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||
|
||||
c = *input++;
|
||||
*output++ = (unsigned char)( c ^ iv[n] );
|
||||
iv[n] = (unsigned char) c;
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||
|
||||
iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ );
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
}
|
||||
|
||||
if (iv_off)
|
||||
{
|
||||
*iv_off = n;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
aes_lock();
|
||||
AES_CFB128(output,
|
||||
input,
|
||||
length,
|
||||
ctx->key,
|
||||
iv,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
aes_unlock();
|
||||
break;
|
||||
|
||||
case 256:
|
||||
aes_lock();
|
||||
AES_CFB256(output,
|
||||
input,
|
||||
length,
|
||||
ctx->key,
|
||||
iv,
|
||||
mode == MBEDTLS_AES_ENCRYPT ? true : false );
|
||||
aes_unlock();
|
||||
break;
|
||||
|
||||
default:
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 )
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char ov[17];
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
memcpy( ov, iv, 16 );
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv );
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
ov[16] = *input;
|
||||
|
||||
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
|
||||
|
||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
||||
ov[16] = c;
|
||||
|
||||
memcpy( iv, ov + 1, 16 );
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/*
|
||||
* AES-CTR Nonce update function
|
||||
*/
|
||||
void aes_ctr_update_nonce( uint8_t *nonce_counter )
|
||||
{
|
||||
for( size_t i = 16; i > 0; i-- )
|
||||
if( ++nonce_counter[i - 1] != 0 )
|
||||
break;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES-CTR buffer encryption/decryption
|
||||
*/
|
||||
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 )
|
||||
{
|
||||
size_t n = nc_off ? *nc_off : 0;
|
||||
|
||||
if ( n || ( length & 0xf ) || ctx->keybits == 192 )
|
||||
{
|
||||
// IV offset or length not aligned to block size
|
||||
int c, i;
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
if( n == 0 )
|
||||
{
|
||||
mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block );
|
||||
|
||||
for( i = 16; i > 0; i-- )
|
||||
if( ++nonce_counter[i - 1] != 0 )
|
||||
break;
|
||||
}
|
||||
c = *input++;
|
||||
*output++ = (unsigned char)( c ^ stream_block[n] );
|
||||
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
}
|
||||
|
||||
if (nc_off)
|
||||
{
|
||||
*nc_off = n;
|
||||
}
|
||||
return( 0 );
|
||||
}
|
||||
else
|
||||
{
|
||||
switch( ctx->keybits )
|
||||
{
|
||||
case 128:
|
||||
aes_lock();
|
||||
AES_CTR128( output,
|
||||
input,
|
||||
length,
|
||||
ctx->key,
|
||||
nonce_counter,
|
||||
&aes_ctr_update_nonce );
|
||||
aes_unlock();
|
||||
break;
|
||||
|
||||
case 256:
|
||||
aes_lock();
|
||||
AES_CTR256( output,
|
||||
input,
|
||||
length,
|
||||
ctx->key,
|
||||
nonce_counter,
|
||||
&aes_ctr_update_nonce );
|
||||
aes_unlock();
|
||||
break;
|
||||
|
||||
default:
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
break;
|
||||
}
|
||||
|
||||
return( 0 );
|
||||
}
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
|
||||
#endif /* AES_PRESENT && (AES_COUNT == 1) */
|
||||
#endif /* MBEDTLS_AES_ALT */
|
||||
#endif /* MBEDTLS_AES_C */
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* AES block cipher
|
||||
*
|
||||
* Copyright (C) 2015-2017, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MBEDTLS_AES_ALT_H
|
||||
#define MBEDTLS_AES_ALT_H
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_aes AES block cipher
|
||||
* \brief Hardware accelerated AES block cipher.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(MBEDTLS_AES_ALT)
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief AES context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
unsigned int keybits; /*!< size of key */
|
||||
unsigned char key[32]; /*!< AES key 128 or 256 bits */
|
||||
}
|
||||
mbedtls_aes_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize AES context
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
*/
|
||||
void mbedtls_aes_init( mbedtls_aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clear AES context
|
||||
*
|
||||
* \param ctx AES context to be cleared
|
||||
*/
|
||||
void mbedtls_aes_free( mbedtls_aes_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (encryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key encryption key
|
||||
* \param keybits must be 128 or 256
|
||||
*
|
||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief AES key schedule (decryption)
|
||||
*
|
||||
* \param ctx AES context to be initialized
|
||||
* \param key decryption key
|
||||
* \param keybits must be 128 or 256
|
||||
*
|
||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_KEY_LENGTH
|
||||
*/
|
||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key,
|
||||
unsigned int keybits );
|
||||
|
||||
/**
|
||||
* \brief AES-ECB block encryption/decryption
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
|
||||
* \param input 16-byte input block
|
||||
* \param output 16-byte output block
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
/**
|
||||
* \brief AES-CBC buffer encryption/decryption
|
||||
* Length should be a multiple of the block
|
||||
* size (16 bytes)
|
||||
*
|
||||
* \note Upon exit, the content of the IV is updated so that you can
|
||||
* call the function same function again on the following
|
||||
* block(s) of data and get the same result as if it was
|
||||
* encrypted in one call. This allows a "streaming" usage.
|
||||
* If on the other hand you need to retain the contents of the
|
||||
* IV, you should either save it manually or use the cipher
|
||||
* module instead.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful, or MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH
|
||||
*/
|
||||
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 );
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CFB)
|
||||
/**
|
||||
* \brief AES-CFB128 buffer encryption/decryption.
|
||||
*
|
||||
* Note: Due to the nature of CFB you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
|
||||
*
|
||||
* \note Upon exit, the content of the IV is updated so that you can
|
||||
* call the function same function again on the following
|
||||
* block(s) of data and get the same result as if it was
|
||||
* encrypted in one call. This allows a "streaming" usage.
|
||||
* If on the other hand you need to retain the contents of the
|
||||
* IV, you should either save it manually or use the cipher
|
||||
* module instead.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv_off offset in IV (updated after use)
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
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 );
|
||||
|
||||
/**
|
||||
* \brief AES-CFB8 buffer encryption/decryption.
|
||||
*
|
||||
* Note: Due to the nature of CFB you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
|
||||
*
|
||||
* \note Upon exit, the content of the IV is updated so that you can
|
||||
* call the function same function again on the following
|
||||
* block(s) of data and get the same result as if it was
|
||||
* encrypted in one call. This allows a "streaming" usage.
|
||||
* If on the other hand you need to retain the contents of the
|
||||
* IV, you should either save it manually or use the cipher
|
||||
* module instead.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param mode MBEDTLS_AES_ENCRYPT or MBEDTLS_AES_DECRYPT
|
||||
* \param length length of the input data
|
||||
* \param iv initialization vector (updated after use)
|
||||
* \param input buffer holding the input data
|
||||
* \param output buffer holding the output data
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
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 );
|
||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/**
|
||||
* \brief AES-CTR buffer encryption/decryption
|
||||
*
|
||||
* Warning: You have to keep the maximum use of your counter in mind!
|
||||
*
|
||||
* Note: Due to the nature of CTR you should use the same key schedule for
|
||||
* both encryption and decryption. So a context initialized with
|
||||
* mbedtls_aes_setkey_enc() for both MBEDTLS_AES_ENCRYPT and MBEDTLS_AES_DECRYPT.
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param length The length of the data
|
||||
* \param nc_off The offset in the current stream_block (for resuming
|
||||
* within current cipher stream). The offset pointer to
|
||||
* should be 0 at the start of a stream.
|
||||
* \param nonce_counter The 128-bit nonce and counter.
|
||||
* \param stream_block The saved stream-block for resuming. Is overwritten
|
||||
* by the function.
|
||||
* \param input The input data stream
|
||||
* \param output The output data stream
|
||||
*
|
||||
* \return 0 if successful
|
||||
*/
|
||||
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 );
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
|
||||
/**
|
||||
* \brief Internal AES block encryption function
|
||||
* (Only exposed to allow overriding it,
|
||||
* see MBEDTLS_AES_ENCRYPT_ALT)
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param input Plaintext block
|
||||
* \param output Output (ciphertext) block
|
||||
*/
|
||||
void mbedtls_aes_encrypt( mbedtls_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
/**
|
||||
* \brief Internal AES block decryption function
|
||||
* (Only exposed to allow overriding it,
|
||||
* see MBEDTLS_AES_DECRYPT_ALT)
|
||||
*
|
||||
* \param ctx AES context
|
||||
* \param input Ciphertext block
|
||||
* \param output Output (plaintext) block
|
||||
*/
|
||||
void mbedtls_aes_decrypt( mbedtls_aes_context *ctx,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_AES_ALT */
|
||||
|
||||
/** \} (end addtogroup sl_crypto_aes) */
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
|
||||
#endif /* MBEDTLS_AES_ALT_H */
|
|
@ -0,0 +1,545 @@
|
|||
/*
|
||||
* FIPS-197 compliant AES implementation
|
||||
*
|
||||
* Copyright (C) 2017, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file includes alternative plugin implementations of various
|
||||
* functions in aes.c using the CRYPTO hardware accelerator incorporated
|
||||
* in MCU devices from Silicon Laboratories.
|
||||
*/
|
||||
|
||||
/*
|
||||
* The AES block cipher was designed by Vincent Rijmen and Joan Daemen.
|
||||
*
|
||||
* http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf
|
||||
* http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf
|
||||
*/
|
||||
|
||||
#include "mbedtls/aes.h"
|
||||
|
||||
#if defined(MBEDTLS_AES_C)
|
||||
#if defined(MBEDTLS_AES_ALT)
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_PRESENT)
|
||||
|
||||
#include "crypto_management.h"
|
||||
#include "em_crypto.h"
|
||||
#include "em_core.h"
|
||||
#include <string.h>
|
||||
|
||||
__STATIC_INLINE void CRYPTO_DataReadUnaligned(volatile uint32_t * reg,
|
||||
const uint8_t * val)
|
||||
{
|
||||
/* Check data is 32bit aligned, if not, read into temporary buffer and
|
||||
then move to user buffer. */
|
||||
if ((uint32_t)val & 0x3)
|
||||
{
|
||||
uint32_t temp[4];
|
||||
CRYPTO_DataRead(reg, temp);
|
||||
memcpy((void*)val, temp, 16);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_DataRead(reg, (uint32_t*)val);
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE void CRYPTO_DataWriteUnaligned(volatile uint32_t * reg,
|
||||
const uint8_t * val)
|
||||
{
|
||||
/* Check data is 32bit aligned, if not move to temporary buffer before
|
||||
writing.*/
|
||||
if ((uint32_t)val & 0x3)
|
||||
{
|
||||
uint32_t temp[4];
|
||||
memcpy(temp, val, 16);
|
||||
CRYPTO_DataWrite(reg, temp);
|
||||
}
|
||||
else
|
||||
{
|
||||
CRYPTO_DataWrite(reg, (uint32_t*)val);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Initialize AES context
|
||||
*/
|
||||
void mbedtls_aes_init( mbedtls_aes_context *ctx )
|
||||
{
|
||||
if( ctx == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* Clear AES context
|
||||
*/
|
||||
void mbedtls_aes_free( mbedtls_aes_context *ctx )
|
||||
{
|
||||
if( ctx == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (encryption)
|
||||
*/
|
||||
int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
if( ctx == NULL || key == NULL ) {
|
||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||
|
||||
if ( ( 128UL != keybits ) && ( 256UL != keybits ) ) {
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
|
||||
ctx->keybits = keybits;
|
||||
memcpy(ctx->key, key, keybits/8);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* AES key schedule (decryption)
|
||||
*/
|
||||
int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx,
|
||||
const unsigned char *key,
|
||||
unsigned int keybits )
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if( ctx == NULL || key == NULL ) {
|
||||
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_aes_context ) );
|
||||
|
||||
if ( ( 128UL != keybits ) && ( 256UL != keybits ) ) {
|
||||
/* Unsupported key size */
|
||||
return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH );
|
||||
}
|
||||
|
||||
ctx->keybits = keybits;
|
||||
|
||||
CRYPTO_TypeDef *device = crypto_management_acquire();
|
||||
device->WAC = 0;
|
||||
device->CTRL = 0;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_KeyBufWrite(device, (uint32_t*)key, (keybits == 128) ? cryptoKey128Bits : cryptoKey256Bits);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
/* Busy-wait here to allow context-switching to occur */
|
||||
device->CMD = CRYPTO_CMD_INSTR_AESENC;
|
||||
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_KeyRead(device, (uint32_t*)ctx->key, (keybits == 128) ? cryptoKey128Bits : cryptoKey256Bits);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
crypto_management_release(device);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* TODO: underneath these, we should swap out the em_crypto-provided library
|
||||
* functions with in-place implemented functions, to get much shorter
|
||||
* critical sections */
|
||||
|
||||
/*
|
||||
* AES-ECB block encryption/decryption
|
||||
*/
|
||||
int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx,
|
||||
int mode,
|
||||
const unsigned char input[16],
|
||||
unsigned char output[16] )
|
||||
{
|
||||
int ret = 0;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if( ctx == NULL || input == NULL || output == NULL ) {
|
||||
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
CRYPTO_TypeDef *device = crypto_management_acquire();
|
||||
device->WAC = 0;
|
||||
device->CTRL = 0;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_KeyBufWrite(device, (uint32_t*)ctx->key, (ctx->keybits == 128UL) ? cryptoKey128Bits : cryptoKey256Bits);
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA0, (uint8_t *)input);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
if ( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_AESENC;
|
||||
} else {
|
||||
device->CMD = CRYPTO_CMD_INSTR_AESDEC;
|
||||
}
|
||||
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)output);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
crypto_management_release(device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CBC)
|
||||
|
||||
/*
|
||||
* AES-CBC buffer encryption/decryption
|
||||
*/
|
||||
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 )
|
||||
{
|
||||
int ret = 0;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
size_t processed = 0;
|
||||
|
||||
if( ctx == NULL || input == NULL || output == NULL || iv == NULL ) {
|
||||
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
/* Input length must be a multiple of 16 bytes which is the AES block
|
||||
length. */
|
||||
if( length & 0xf ) {
|
||||
return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
CRYPTO_TypeDef *device = crypto_management_acquire();
|
||||
device->WAC = 0;
|
||||
device->CTRL = 0;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_KeyBufWrite(device, (uint32_t*)ctx->key, (ctx->keybits == 128UL) ? cryptoKey128Bits : cryptoKey256Bits);
|
||||
if ( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA0, (uint8_t *)iv);
|
||||
} else {
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA2, (uint8_t *)iv);
|
||||
}
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
while ( processed < length ) {
|
||||
if ( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA0XOR, (uint8_t *)(&input[processed]));
|
||||
device->CMD = CRYPTO_CMD_INSTR_AESENC;
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
|
||||
CORE_EXIT_CRITICAL();
|
||||
} else {
|
||||
/* Decrypt input block, XOR IV to decrypted text, set ciphertext as next IV */
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA0, (uint8_t *)(&input[processed]));
|
||||
CRYPTO_EXECUTE_4( device,
|
||||
CRYPTO_CMD_INSTR_DATA0TODATA1,
|
||||
CRYPTO_CMD_INSTR_AESDEC,
|
||||
CRYPTO_CMD_INSTR_DATA2TODATA0XOR,
|
||||
CRYPTO_CMD_INSTR_DATA1TODATA2);
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
|
||||
CORE_EXIT_CRITICAL();
|
||||
}
|
||||
processed += 16;
|
||||
}
|
||||
|
||||
if ( processed >= 16 ) {
|
||||
if ( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||
memcpy(iv, &output[processed-16], 16);
|
||||
} else {
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataReadUnaligned(&device->DATA2, (uint8_t *)(iv));
|
||||
CORE_EXIT_CRITICAL();
|
||||
}
|
||||
}
|
||||
|
||||
crypto_management_release(device);
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CBC */
|
||||
|
||||
#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 )
|
||||
{
|
||||
size_t n = iv_off ? *iv_off : 0;
|
||||
size_t processed = 0;
|
||||
int ret = 0;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if( ctx == NULL || input == NULL || output == NULL || iv == NULL ) {
|
||||
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
while ( processed < length ) {
|
||||
if ( n > 0 ) {
|
||||
/* start by filling up the IV */
|
||||
if( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||
iv[n] = output[processed] = (unsigned char)( iv[n] ^ input[processed] );
|
||||
} else {
|
||||
int c = input[processed];
|
||||
output[processed] = (unsigned char)( c ^ iv[n] );
|
||||
iv[n] = (unsigned char) c;
|
||||
}
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
processed++;
|
||||
continue;
|
||||
} else {
|
||||
/* process one ore more blocks of data */
|
||||
CRYPTO_TypeDef *device = crypto_management_acquire();
|
||||
device->WAC = 0;
|
||||
device->CTRL = 0;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_KeyBufWrite(device, (uint32_t*)ctx->key, (ctx->keybits == 128UL) ? cryptoKey128Bits : cryptoKey256Bits);
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA0, (uint8_t *)iv);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
/* Encryption: encrypt IV, encIV xor input -> output and IV */
|
||||
/* Decryption: encrypt IV, encIV xor input -> output, input -> IV */
|
||||
size_t iterations = (length - processed) / 16;
|
||||
for (size_t i = 0; i < iterations; i++ ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_AESENC;
|
||||
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
if ( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA0XOR, (uint8_t *)(&input[processed]));
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
|
||||
} else {
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA1, (uint8_t *)(&input[processed]));
|
||||
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0XOR;
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
|
||||
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0;
|
||||
}
|
||||
CORE_EXIT_CRITICAL();
|
||||
processed += 16;
|
||||
}
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)iv);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
while ( length - processed > 0 ) {
|
||||
if ( n == 0 ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_AESENC;
|
||||
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)iv);
|
||||
CORE_EXIT_CRITICAL();
|
||||
}
|
||||
/* Save remainder to iv */
|
||||
if( mode == MBEDTLS_AES_ENCRYPT ) {
|
||||
iv[n] = output[processed] = (unsigned char)( iv[n] ^ input[processed] );
|
||||
} else {
|
||||
int c = input[processed];
|
||||
output[processed] = (unsigned char)( c ^ iv[n] );
|
||||
iv[n] = (unsigned char) c;
|
||||
}
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
processed++;
|
||||
}
|
||||
|
||||
crypto_management_release(device);
|
||||
}
|
||||
}
|
||||
|
||||
if ( iv_off ) {
|
||||
*iv_off = n;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* 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 )
|
||||
{
|
||||
unsigned char c;
|
||||
unsigned char ov[17];
|
||||
int ret = 0;
|
||||
|
||||
if( ctx == NULL || input == NULL || output == NULL || iv == NULL ) {
|
||||
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
while( length-- )
|
||||
{
|
||||
memcpy( ov, iv, 16 );
|
||||
if ( (ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
if( mode == MBEDTLS_AES_DECRYPT )
|
||||
ov[16] = *input;
|
||||
|
||||
c = *output++ = (unsigned char)( iv[0] ^ *input++ );
|
||||
|
||||
if( mode == MBEDTLS_AES_ENCRYPT )
|
||||
ov[16] = c;
|
||||
|
||||
memcpy( iv, ov + 1, 16 );
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /*MBEDTLS_CIPHER_MODE_CFB */
|
||||
|
||||
#if defined(MBEDTLS_CIPHER_MODE_CTR)
|
||||
/*
|
||||
* AES-CTR buffer encryption/decryption
|
||||
*/
|
||||
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 )
|
||||
{
|
||||
size_t n = nc_off ? *nc_off : 0;
|
||||
size_t processed = 0;
|
||||
int ret = 0;
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if( ctx == NULL || input == NULL || output == NULL || nonce_counter == NULL || stream_block == NULL ) {
|
||||
return ( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH );
|
||||
}
|
||||
|
||||
if ( ctx->keybits != 128UL && ctx->keybits != 256UL) {
|
||||
return MBEDTLS_ERR_AES_INVALID_KEY_LENGTH;
|
||||
}
|
||||
|
||||
while ( processed < length ) {
|
||||
if ( n > 0 ) {
|
||||
/* start by filling up the IV */
|
||||
output[processed] = (unsigned char)( input[processed] ^ stream_block[n] );
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
processed++;
|
||||
continue;
|
||||
} else {
|
||||
/* process one ore more blocks of data */
|
||||
CRYPTO_TypeDef *device = crypto_management_acquire();
|
||||
device->WAC = 0;
|
||||
device->CTRL = CRYPTO_CTRL_INCWIDTH_INCWIDTH4;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_KeyBufWrite(device, (uint32_t*)ctx->key, (ctx->keybits == 128UL) ? cryptoKey128Bits : cryptoKey256Bits);
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA1, (uint8_t *)nonce_counter);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
/* strategy: encrypt nonce, encNonce xor input -> output, inc(nonce) */
|
||||
size_t iterations = (length - processed) / 16;
|
||||
for (size_t i = 0; i < iterations; i++ ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0;
|
||||
device->CMD = CRYPTO_CMD_INSTR_AESENC;
|
||||
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
|
||||
device->CMD = CRYPTO_CMD_INSTR_DATA1INC;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataWriteUnaligned(&device->DATA0XOR, (uint8_t *)(&input[processed]));
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)(&output[processed]));
|
||||
CORE_EXIT_CRITICAL();
|
||||
processed += 16;
|
||||
}
|
||||
|
||||
while ( length - processed > 0 ) {
|
||||
if ( n == 0 ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_DATA1TODATA0;
|
||||
device->CMD = CRYPTO_CMD_INSTR_AESENC;
|
||||
while ((device->STATUS & CRYPTO_STATUS_INSTRRUNNING) != 0);
|
||||
device->CMD = CRYPTO_CMD_INSTR_DATA1INC;
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataReadUnaligned(&device->DATA0, (uint8_t *)stream_block);
|
||||
CORE_EXIT_CRITICAL();
|
||||
}
|
||||
/* Save remainder to iv */
|
||||
output[processed] = (unsigned char)( input[processed] ^ stream_block[n] );
|
||||
n = ( n + 1 ) & 0x0F;
|
||||
processed++;
|
||||
}
|
||||
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DataReadUnaligned(&device->DATA1, (uint8_t *)nonce_counter);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
crypto_management_release(device);
|
||||
}
|
||||
}
|
||||
|
||||
if ( nc_off ) {
|
||||
*nc_off = n;
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
#endif /* MBEDTLS_CIPHER_MODE_CTR */
|
||||
|
||||
#endif /* CRYPTO_PRESENT */
|
||||
|
||||
#endif /* MBEDTLS_AES_ALT */
|
||||
|
||||
#endif /* MBEDTLS_AES_C */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,392 @@
|
|||
/*
|
||||
* Silicon Labs CRYPTO device management interface.
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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 "crypto_management.h"
|
||||
#include "em_core.h"
|
||||
#include "em_bus.h"
|
||||
|
||||
#if defined( CRYPTO_PRESENT )
|
||||
#if defined( MBEDTLS_THREADING_C )
|
||||
#include "mbedtls/threading.h"
|
||||
static mbedtls_threading_mutex_t crypto_locks[CRYPTO_COUNT];
|
||||
static volatile bool crypto_locks_initialized = false;
|
||||
static unsigned int acquire_count = 0U;
|
||||
#endif /* MBEDTLS_THREADING_C */
|
||||
|
||||
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
|
||||
/** Preemptable context of CRYPTO hardware module. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t CTRL; /*!< Control Register */
|
||||
uint32_t WAC; /*!< Wide Arithmetic Configuration */
|
||||
uint32_t SEQCTRL; /*!< Sequence Control */
|
||||
uint32_t SEQCTRLB; /*!< Sequence Control B */
|
||||
uint32_t IEN; /*!< Interrupt Enable Register */
|
||||
uint32_t SEQ[5]; /*!< Instruction Sequence registers */
|
||||
CRYPTO_Data260_TypeDef DDATA[5]; /*!< DDATA registers. Covers all data
|
||||
registers
|
||||
of CRYPTO, including DATA(128 bit),
|
||||
DDATA (256bit/260bit),
|
||||
QDATA (512bit) registers. */
|
||||
uint32_t regmask; /*!< Bitmask for which registers to save */
|
||||
uint32_t operands; /*!< Saving the currently selected operands */
|
||||
bool carry; /*!< Saving the status of the carry flag */
|
||||
} crypto_context_t;
|
||||
|
||||
static crypto_context_t preemption_context;
|
||||
static bool is_preempted = false;
|
||||
static CORE_DECLARE_IRQ_STATE;
|
||||
#endif /* MBEDTLS_CRYPTO_DEVICE_PREEMPTION */
|
||||
|
||||
typedef enum
|
||||
{
|
||||
#if defined( CRYPTO0 )
|
||||
CRYPTO0_ID = 0,
|
||||
#elif defined( CRYPTO )
|
||||
CRYPTO_ID = 0,
|
||||
#endif
|
||||
#if defined( CRYPTO1 )
|
||||
CRYPTO1_ID = 1,
|
||||
#endif
|
||||
} crypto_instance_number_t;
|
||||
|
||||
typedef struct {
|
||||
CRYPTO_TypeDef *device;
|
||||
uint32_t clockMask;
|
||||
} crypto_device_t;
|
||||
|
||||
static const crypto_device_t crypto_devices[CRYPTO_COUNT] =
|
||||
{
|
||||
#if defined( CRYPTO0 )
|
||||
{
|
||||
CRYPTO0,
|
||||
_CMU_HFBUSCLKEN0_CRYPTO0_SHIFT
|
||||
},
|
||||
#elif defined( CRYPTO )
|
||||
{
|
||||
CRYPTO,
|
||||
_CMU_HFBUSCLKEN0_CRYPTO_SHIFT
|
||||
},
|
||||
#endif
|
||||
#if defined( CRYPTO1 )
|
||||
{
|
||||
CRYPTO1,
|
||||
_CMU_HFBUSCLKEN0_CRYPTO1_SHIFT
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static inline int crypto_management_index_by_device( CRYPTO_TypeDef *device )
|
||||
{
|
||||
#if defined( CRYPTO0 )
|
||||
if ( device == CRYPTO0 ) return 0;
|
||||
#elif defined( CRYPTO )
|
||||
if ( device == CRYPTO ) return 0;
|
||||
#endif
|
||||
#if defined( CRYPTO1 )
|
||||
if ( device == CRYPTO1 ) return 1;
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Use bitband for clock enable/disable operations, such that they are atomic */
|
||||
#define CRYPTO_CLOCK_ENABLE(clk) BUS_RegBitWrite(&(CMU->HFBUSCLKEN0), clk, 1)
|
||||
#define CRYPTO_CLOCK_DISABLE(clk) BUS_RegBitWrite(&(CMU->HFBUSCLKEN0), clk, 0)
|
||||
#define CRYPTO_CLOCK_ENABLED(clk) BUS_RegBitRead(&(CMU->HFBUSCLKEN0), clk)
|
||||
|
||||
/* Get ownership of an available crypto device */
|
||||
CRYPTO_TypeDef *crypto_management_acquire( void )
|
||||
{
|
||||
CRYPTO_TypeDef *device = NULL;
|
||||
|
||||
#if defined( MBEDTLS_THREADING_C )
|
||||
/* Initialize mutexes if that hasn't happened yet */
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if ( !crypto_locks_initialized ) {
|
||||
CORE_ENTER_CRITICAL();
|
||||
if ( !crypto_locks_initialized ) {
|
||||
for ( int i = 0; i < CRYPTO_COUNT; i++ ) {
|
||||
mbedtls_mutex_init(&crypto_locks[i]);
|
||||
}
|
||||
crypto_locks_initialized = true;
|
||||
}
|
||||
CORE_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
/* Try to take an available crypto instance */
|
||||
unsigned int devno = 0;
|
||||
for ( ; devno < CRYPTO_COUNT; devno++ ) {
|
||||
if ( 0 == THREADING_TakeMutexNonBlocking(&crypto_locks[devno]) ) {
|
||||
device = crypto_devices[devno].device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If no device immediately available, do naieve round-robin */
|
||||
if ( device == NULL ) {
|
||||
devno = acquire_count % CRYPTO_COUNT;
|
||||
mbedtls_mutex_lock( &crypto_locks[devno] );
|
||||
device = crypto_devices[devno].device;
|
||||
}
|
||||
|
||||
/* Doing this outside of critical section is safe, since we own the lock
|
||||
* and are using bitband to poke the clock enable bit */
|
||||
CRYPTO_CLOCK_ENABLE( crypto_devices[devno].clockMask );
|
||||
|
||||
acquire_count++;
|
||||
#else // !MBEDTLS_THREADING_C
|
||||
device = crypto_devices[0].device;
|
||||
CRYPTO_CLOCK_ENABLE( crypto_devices[0].clockMask );
|
||||
#endif // MBEDTLS_THREADING_C
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
/* Get ownership of the default crypto device (CRYPTO0/CRYPTO) */
|
||||
CRYPTO_TypeDef *crypto_management_acquire_default( void )
|
||||
{
|
||||
CRYPTO_TypeDef *device = NULL;
|
||||
|
||||
#if defined( MBEDTLS_THREADING_C )
|
||||
/* Initialize mutexes if that hasn't happened yet */
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
|
||||
if ( !crypto_locks_initialized ) {
|
||||
CORE_ENTER_CRITICAL();
|
||||
if ( !crypto_locks_initialized ) {
|
||||
for ( int i = 0; i < CRYPTO_COUNT; i++ ) {
|
||||
mbedtls_mutex_init(&crypto_locks[i]);
|
||||
}
|
||||
crypto_locks_initialized = true;
|
||||
}
|
||||
CORE_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
mbedtls_mutex_lock( &crypto_locks[0] );
|
||||
device = crypto_devices[0].device;
|
||||
|
||||
/* Doing this outside of critical section is safe, since we own the lock
|
||||
* and are using bitband to poke the clock enable bit */
|
||||
CRYPTO_CLOCK_ENABLE( crypto_devices[0].clockMask );
|
||||
#else // !MBEDTLS_THREADING_C
|
||||
device = crypto_devices[0].device;
|
||||
CRYPTO_CLOCK_ENABLE( crypto_devices[0].clockMask );
|
||||
#endif // MBEDTLS_THREADING_C
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
/* Release ownership of an available crypto device */
|
||||
void crypto_management_release( CRYPTO_TypeDef *device )
|
||||
{
|
||||
int devno = crypto_management_index_by_device( device );
|
||||
if ( devno < 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Doing this outside of critical section is safe, since we still own the lock
|
||||
* and are using bitband to poke the clock enable bit */
|
||||
CRYPTO_CLOCK_DISABLE( crypto_devices[devno].clockMask );
|
||||
|
||||
#if defined ( MBEDTLS_THREADING_C )
|
||||
mbedtls_mutex_unlock( &crypto_locks[devno] );
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Acquire a device with preemption. NOT thread-safe! */
|
||||
CRYPTO_TypeDef *crypto_management_acquire_preemption( uint32_t regmask )
|
||||
{
|
||||
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
|
||||
CRYPTO_TypeDef *device = NULL;
|
||||
/* Turn off interrupts */
|
||||
CORE_ENTER_CRITICAL();
|
||||
|
||||
/* Check if there is an unused CRYPTO instance */
|
||||
for ( int i = 0; i < CRYPTO_COUNT; i++ ) {
|
||||
if ( !CRYPTO_CLOCK_ENABLED( crypto_devices[i].clockMask ) ) {
|
||||
/* Found an unused device */
|
||||
CRYPTO_CLOCK_ENABLE( crypto_devices[i].clockMask );
|
||||
device = crypto_devices[i].device;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is no unused instance, preempt the last one */
|
||||
if ( device == NULL ) {
|
||||
is_preempted = true;
|
||||
device = crypto_devices[CRYPTO_COUNT - 1].device;
|
||||
|
||||
/* In case this instance is still working on anything */
|
||||
CRYPTO_InstructionSequenceWait(device);
|
||||
|
||||
/* Store operational context */
|
||||
preemption_context.regmask = regmask;
|
||||
preemption_context.WAC = device->WAC;
|
||||
preemption_context.CTRL = device->CTRL;
|
||||
preemption_context.SEQCTRL = device->SEQCTRL;
|
||||
preemption_context.SEQCTRLB = device->SEQCTRLB;
|
||||
preemption_context.IEN = device->IEN;
|
||||
preemption_context.operands = device->CSTATUS;
|
||||
preemption_context.carry = (device->DSTATUS & CRYPTO_DSTATUS_CARRY) != 0;
|
||||
|
||||
if ( (preemption_context.WAC & _CRYPTO_WAC_RESULTWIDTH_MASK) == CRYPTO_WAC_RESULTWIDTH_260BIT)
|
||||
{
|
||||
CRYPTO_DData0Read260(device, preemption_context.DDATA[0]); /* Always save DDATA0 because it'll get clobbered in 260-bit mode*/
|
||||
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA1) != 0 ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_DDATA1TODDATA0; /* Move DDATA1 to DDATA0
|
||||
in order to read. */
|
||||
CRYPTO_DData0Read260(device, preemption_context.DDATA[1]);
|
||||
}
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA2) != 0 ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_DDATA2TODDATA0; /* Move DDATA2 to DDATA0
|
||||
in order to read. */
|
||||
CRYPTO_DData0Read260(device, preemption_context.DDATA[2]);
|
||||
}
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA3) != 0 ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_DDATA3TODDATA0; /* Move DDATA3 to DDATA0
|
||||
in order to read. */
|
||||
CRYPTO_DData0Read260(device, preemption_context.DDATA[3]);
|
||||
}
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA4) != 0 ) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_DDATA4TODDATA0; /* Move DDATA4 to DDATA0
|
||||
in order to read. */
|
||||
CRYPTO_DData0Read260(device, preemption_context.DDATA[4]);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA0) != 0 )
|
||||
CRYPTO_DDataRead(&device->DDATA0, preemption_context.DDATA[0]);
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA1) != 0 )
|
||||
CRYPTO_DDataRead(&device->DDATA1, preemption_context.DDATA[1]);
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA2) != 0 )
|
||||
CRYPTO_DDataRead(&device->DDATA2, preemption_context.DDATA[2]);
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA3) != 0 )
|
||||
CRYPTO_DDataRead(&device->DDATA3, preemption_context.DDATA[3]);
|
||||
if ( (regmask & CRYPTO_MANAGEMENT_SAVE_DDATA4) != 0 )
|
||||
CRYPTO_DDataRead(&device->DDATA4, preemption_context.DDATA[4]);
|
||||
}
|
||||
|
||||
/* Search for possible EXEC commands and replace with END. */
|
||||
for ( size_t j = 0; j < (regmask & 0x7U)*sizeof(uint32_t); j++ ) {
|
||||
if ( (j & 0x03) == 0 ) {
|
||||
preemption_context.SEQ[j / sizeof(uint32_t)] = *((&device->SEQ0) + (j / sizeof(uint32_t)));
|
||||
}
|
||||
if ( ((uint8_t*)preemption_context.SEQ)[j] == CRYPTO_CMD_INSTR_EXEC ) {
|
||||
((uint8_t*)preemption_context.SEQ)[j] = CRYPTO_CMD_INSTR_END;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return device;
|
||||
#else
|
||||
(void) regmask;
|
||||
return crypto_management_acquire();
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Release a device from preemption */
|
||||
void crypto_management_release_preemption( CRYPTO_TypeDef *device )
|
||||
{
|
||||
if ( crypto_management_index_by_device( device ) < 0 ) {
|
||||
return;
|
||||
}
|
||||
#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION )
|
||||
|
||||
if ( is_preempted ) {
|
||||
/* If we preempted something, put their context back */
|
||||
device->WAC = preemption_context.WAC;
|
||||
device->CTRL = preemption_context.CTRL;
|
||||
device->SEQCTRL = preemption_context.SEQCTRL;
|
||||
device->SEQCTRLB = preemption_context.SEQCTRLB;
|
||||
device->IEN = preemption_context.IEN;
|
||||
|
||||
if ( (preemption_context.WAC & _CRYPTO_WAC_RESULTWIDTH_MASK) == CRYPTO_WAC_RESULTWIDTH_260BIT)
|
||||
{
|
||||
/* Start by writing the DDATA1 value to DDATA0 and move to DDATA1. */
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA1) != 0 ) {
|
||||
CRYPTO_DData0Write260(device, preemption_context.DDATA[1]);
|
||||
device->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA1;
|
||||
}
|
||||
|
||||
/* Write the DDATA2 value to DDATA0 and move to DDATA2. */
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA2) != 0 ) {
|
||||
CRYPTO_DData0Write260(device, preemption_context.DDATA[2]);
|
||||
device->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA2;
|
||||
}
|
||||
|
||||
/* Write the DDATA3 value to DDATA0 and move to DDATA3. */
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA3) != 0 ) {
|
||||
CRYPTO_DData0Write260(device, preemption_context.DDATA[3]);
|
||||
device->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA3;
|
||||
}
|
||||
|
||||
/* Write the DDATA4 value to DDATA0 and move to DDATA4. */
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA4) != 0 ) {
|
||||
CRYPTO_DData0Write260(device, preemption_context.DDATA[4]);
|
||||
device->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA4;
|
||||
}
|
||||
|
||||
/* Finally write DDATA0 */
|
||||
CRYPTO_DData0Write260(device, preemption_context.DDATA[0]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA0) != 0 )
|
||||
CRYPTO_DDataWrite(&device->DDATA0, preemption_context.DDATA[0]);
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA1) != 0 )
|
||||
CRYPTO_DDataWrite(&device->DDATA1, preemption_context.DDATA[1]);
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA2) != 0 )
|
||||
CRYPTO_DDataWrite(&device->DDATA2, preemption_context.DDATA[2]);
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA3) != 0 )
|
||||
CRYPTO_DDataWrite(&device->DDATA3, preemption_context.DDATA[3]);
|
||||
if ( (preemption_context.regmask & CRYPTO_MANAGEMENT_SAVE_DDATA4) != 0 )
|
||||
CRYPTO_DDataWrite(&device->DDATA4, preemption_context.DDATA[4]);
|
||||
}
|
||||
|
||||
if (preemption_context.carry) {
|
||||
device->CMD = CRYPTO_CMD_INSTR_CSET;
|
||||
} else {
|
||||
device->CMD = CRYPTO_CMD_INSTR_CCLR;
|
||||
}
|
||||
|
||||
device->CMD = (preemption_context.operands & 0x7U) |
|
||||
(((preemption_context.operands >> 8) & 0x7U) << 3) |
|
||||
0xC0;
|
||||
|
||||
for (size_t i = 0; i < (preemption_context.regmask & 0x7U); i++ ) {
|
||||
*((&device->SEQ0) + i) = preemption_context.SEQ[i];
|
||||
}
|
||||
|
||||
is_preempted = false;
|
||||
} else {
|
||||
/* If we didn't preempt anything, turn crypto clock back off */
|
||||
CRYPTO_CLOCK_DISABLE( crypto_devices[crypto_management_index_by_device( device )].clockMask );
|
||||
}
|
||||
|
||||
/* Turn interrupts back on */
|
||||
CORE_EXIT_CRITICAL();
|
||||
#else
|
||||
crypto_management_release(device);
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif /* CRYPTO_PRESENT */
|
|
@ -0,0 +1,128 @@
|
|||
/*
|
||||
* Silicon Labs CRYPTO device management interface.
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#ifndef MBEDTLS_CRYPTO_MANAGEMENT_H
|
||||
#define MBEDTLS_CRYPTO_MANAGEMENT_H
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_management CRYPTO peripheral instance management
|
||||
* \brief Management functions for CRYPTO peripherals. These functions take care
|
||||
* of not having two 'owners' simultaneously for the same peripheral,
|
||||
* potentially messing up the internal state of said peripheral.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined( CRYPTO_PRESENT )
|
||||
#include "em_crypto.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Save DDATA0 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_DDATA0 (0x1U << 3)
|
||||
/** Save DDATA1 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_DDATA1 (0x1U << 4)
|
||||
/** Save DDATA2 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_DDATA2 (0x1U << 5)
|
||||
/** Save DDATA3 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_DDATA3 (0x1U << 6)
|
||||
/** Save DDATA4 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_DDATA4 (0x1U << 7)
|
||||
/** Save SEQ0 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ0 (0x1U)
|
||||
/** Save SEQ0 through SEQ1 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ1 (0x2U)
|
||||
/** Save SEQ0 through SEQ2 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ2 (0x3U)
|
||||
/** Save SEQ0 through SEQ3 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ3 (0x4U)
|
||||
/** Save SEQ0 through SEQ4 register when preempting */
|
||||
#define CRYPTO_MANAGEMENT_SAVE_UPTO_SEQ4 (0x5U)
|
||||
|
||||
/**
|
||||
* \brief Get ownership of a CRYPTO peripheral
|
||||
*
|
||||
* \return Handle of assigned CRYPTO peripheral
|
||||
*/
|
||||
CRYPTO_TypeDef *crypto_management_acquire( void );
|
||||
|
||||
/**
|
||||
* \brief Get ownership of the default CRYPTO peripheral
|
||||
*
|
||||
* \return Handle of default CRYPTO peripheral
|
||||
*/
|
||||
CRYPTO_TypeDef *crypto_management_acquire_default( void );
|
||||
|
||||
/**
|
||||
* \brief Release ownership of a CRYPTO peripheral
|
||||
*
|
||||
* \param device Handle of CRYPTO peripheral to be released
|
||||
*/
|
||||
void crypto_management_release( CRYPTO_TypeDef *device );
|
||||
|
||||
/**
|
||||
* \brief Acquire preempting ownership of a CRYPTO peripheral.
|
||||
* NOTE: this function is not meant for general use, it
|
||||
* is not thread-safe, and must be called form the
|
||||
* highest priority thread/interrupt allowed to use mbed TLS.
|
||||
*
|
||||
* \param regmask Bitmask of CRYPTO_MANAGEMENT_ defines instructing what
|
||||
* parts of the device state will be clobbered during
|
||||
* preemption.
|
||||
*
|
||||
* \return Handle of assigned CRYPTO peripheral
|
||||
*/
|
||||
CRYPTO_TypeDef *crypto_management_acquire_preemption( uint32_t regmask );
|
||||
|
||||
/**
|
||||
* \brief Releasing preempting ownership of a CRYPTO peripheral.
|
||||
* NOTE: this function is not meant for general use, it
|
||||
* is not thread-safe, and must be called form the
|
||||
* highest priority thread/interrupt allowed to use mbed TLS.
|
||||
*
|
||||
* \param device Handle of preempted CRYPTO peripheral to be released
|
||||
*/
|
||||
void crypto_management_release_preemption( CRYPTO_TypeDef *device );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* CRYPTO_PRESENT */
|
||||
|
||||
/** \} (end addtogroup sl_crypto_management) */
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
|
||||
#endif /* MBEDTLS_CRYPTO_MANAGEMENT_H */
|
|
@ -0,0 +1,449 @@
|
|||
/*
|
||||
* FIPS-180-2 compliant SHA-1 & SHA-256 implementation
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
/*
|
||||
* This file includes an alternative implementation of the standard
|
||||
* mbedtls/libary/sha[1][256].c using the CRYPTO hardware accelerator incorporated
|
||||
* in MCU devices from Silicon Laboratories.
|
||||
*/
|
||||
/*
|
||||
* The SHA-1 standard was published by NIST in 1993.
|
||||
*
|
||||
* http://www.itl.nist.gov/fipspubs/fip180-1.htm
|
||||
*
|
||||
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
|
||||
*
|
||||
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
||||
*/
|
||||
|
||||
#if !defined(MBEDTLS_CONFIG_FILE)
|
||||
#include "mbedtls/config.h"
|
||||
#else
|
||||
#include MBEDTLS_CONFIG_FILE
|
||||
#endif
|
||||
|
||||
#include "mbedtls/sha1.h"
|
||||
#include "mbedtls/sha256.h"
|
||||
|
||||
#if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA1_ALT)
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined(CRYPTO_PRESENT)
|
||||
#include "em_crypto.h"
|
||||
#include "em_core.h"
|
||||
#include "crypto_management.h"
|
||||
#include "em_assert.h"
|
||||
#include <string.h>
|
||||
|
||||
static const uint32_t init_state_sha1[8] =
|
||||
{
|
||||
0x67452301UL,
|
||||
0xEFCDAB89UL,
|
||||
0x98BADCFEUL,
|
||||
0x10325476UL,
|
||||
0xC3D2E1F0UL,
|
||||
0x0UL,
|
||||
0x0UL,
|
||||
0x0UL
|
||||
};
|
||||
|
||||
static const uint32_t init_state_sha256[8] =
|
||||
{
|
||||
0x6A09E667UL,
|
||||
0xBB67AE85UL,
|
||||
0x3C6EF372UL,
|
||||
0xA54FF53AUL,
|
||||
0x510E527FUL,
|
||||
0x9B05688CUL,
|
||||
0x1F83D9ABUL,
|
||||
0x5BE0CD19UL
|
||||
};
|
||||
|
||||
static const uint32_t init_state_sha224[8] =
|
||||
{
|
||||
0xC1059ED8UL,
|
||||
0x367CD507UL,
|
||||
0x3070DD17UL,
|
||||
0xF70E5939UL,
|
||||
0xFFC00B31UL,
|
||||
0x68581511UL,
|
||||
0x64F98FA7UL,
|
||||
0xBEFA4FA4UL
|
||||
};
|
||||
|
||||
static const unsigned char sha_padding[64] =
|
||||
{
|
||||
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
|
||||
};
|
||||
|
||||
typedef enum {
|
||||
CRYPTO_SHA1,
|
||||
CRYPTO_SHA2
|
||||
} crypto_sha_mode_t;
|
||||
|
||||
/*
|
||||
* 32-bit integer manipulation macros (big endian)
|
||||
*/
|
||||
#ifndef PUT_UINT32_BE
|
||||
#define PUT_UINT32_BE(n,b,i) \
|
||||
do { \
|
||||
(b)[(i) ] = (unsigned char) ( (n) >> 24 ); \
|
||||
(b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \
|
||||
(b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \
|
||||
(b)[(i) + 3] = (unsigned char) ( (n) ); \
|
||||
} while( 0 )
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief unified SHA acceleration function.
|
||||
*
|
||||
* @param[inout] state State context for SHA hashing
|
||||
* @param[in] data Input block(s). Must contain N blocks
|
||||
* of SHA1/SHA256 block size (64 bytes)
|
||||
* @param blocks Amount of blocks pointed to by data
|
||||
* @param mode SHA operation mode
|
||||
*/
|
||||
static void crypto_sha_update_state( uint32_t state[8],
|
||||
const unsigned char *data,
|
||||
size_t blocks,
|
||||
crypto_sha_mode_t mode )
|
||||
{
|
||||
CORE_DECLARE_IRQ_STATE;
|
||||
CRYPTO_TypeDef *crypto = crypto_management_acquire();
|
||||
|
||||
switch ( mode ) {
|
||||
case CRYPTO_SHA1:
|
||||
crypto->CTRL = CRYPTO_CTRL_SHA_SHA1;
|
||||
break;
|
||||
case CRYPTO_SHA2:
|
||||
crypto->CTRL = CRYPTO_CTRL_SHA_SHA2;
|
||||
break;
|
||||
}
|
||||
|
||||
crypto->WAC = 0;
|
||||
crypto->IEN = 0;
|
||||
|
||||
/* Set result width of MADD32 operation. */
|
||||
CRYPTO_ResultWidthSet(crypto, cryptoResult256Bits);
|
||||
|
||||
/* Clear sequence control registers */
|
||||
crypto->SEQCTRL = 0;
|
||||
crypto->SEQCTRLB = 0;
|
||||
|
||||
/* Put the state back */
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DDataWrite(&crypto->DDATA1, state);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
CRYPTO_EXECUTE_3( crypto,
|
||||
CRYPTO_CMD_INSTR_DDATA1TODDATA0,
|
||||
CRYPTO_CMD_INSTR_DDATA1TODDATA2,
|
||||
CRYPTO_CMD_INSTR_SELDDATA0DDATA1 );
|
||||
|
||||
/* Load the data block(s) */
|
||||
for ( size_t i = 0; i < blocks; i++ ) {
|
||||
if ((uint32_t)(&data[i*64]) & 0x3)
|
||||
{
|
||||
uint32_t temp[16];
|
||||
memcpy(temp, &data[i*64], 64);
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_QDataWrite(&crypto->QDATA1BIG, temp);
|
||||
CORE_EXIT_CRITICAL();
|
||||
}
|
||||
else
|
||||
{
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_QDataWrite(&crypto->QDATA1BIG, (uint32_t*) &data[i*64]);
|
||||
CORE_EXIT_CRITICAL();
|
||||
}
|
||||
|
||||
/* Process the data block */
|
||||
CRYPTO_EXECUTE_3( crypto,
|
||||
CRYPTO_CMD_INSTR_SHA,
|
||||
CRYPTO_CMD_INSTR_MADD32,
|
||||
CRYPTO_CMD_INSTR_DDATA0TODDATA1 );
|
||||
}
|
||||
CORE_ENTER_CRITICAL();
|
||||
CRYPTO_DDataRead(&crypto->DDATA0, state);
|
||||
CORE_EXIT_CRITICAL();
|
||||
|
||||
crypto_management_release( crypto );
|
||||
}
|
||||
|
||||
#if defined(MBEDTLS_SHA256_ALT) && defined(MBEDTLS_SHA256_C)
|
||||
void mbedtls_sha256_init( mbedtls_sha256_context *ctx )
|
||||
{
|
||||
if( ctx == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
|
||||
}
|
||||
|
||||
void mbedtls_sha256_free( mbedtls_sha256_context *ctx )
|
||||
{
|
||||
if( ctx == NULL ) {
|
||||
return;
|
||||
}
|
||||
|
||||
memset( ctx, 0, sizeof( mbedtls_sha256_context ) );
|
||||
}
|
||||
|
||||
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
|
||||
const mbedtls_sha256_context *src )
|
||||
{
|
||||
if ( dst != NULL && src != NULL ) {
|
||||
*dst = *src;
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 context setup
|
||||
*/
|
||||
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
|
||||
if ( is224 != 0 ) {
|
||||
ctx->is224 = true;
|
||||
memcpy(ctx->state, init_state_sha224, 32);
|
||||
} else {
|
||||
ctx->is224 = false;
|
||||
memcpy(ctx->state, init_state_sha256, 32);
|
||||
}
|
||||
}
|
||||
|
||||
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] )
|
||||
{
|
||||
crypto_sha_update_state( ctx->state, data, 1, CRYPTO_SHA2 );
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 process buffer
|
||||
*/
|
||||
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
|
||||
size_t ilen )
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if( ilen == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (uint32_t) ilen ) {
|
||||
ctx->total[1]++;
|
||||
}
|
||||
|
||||
if( left && ilen >= fill ) {
|
||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||
mbedtls_sha256_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 ) {
|
||||
size_t blocks = ilen / 64;
|
||||
crypto_sha_update_state( ctx->state, input, blocks, CRYPTO_SHA2 );
|
||||
input += blocks * 64;
|
||||
ilen -= blocks * 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 ) {
|
||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* SHA-256 final digest
|
||||
*/
|
||||
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] )
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
mbedtls_sha256_update( ctx, sha_padding, padn );
|
||||
mbedtls_sha256_update( ctx, msglen, 8 );
|
||||
|
||||
for ( size_t i = 0; i < (ctx->is224 ? 28 : 32); i+=4) {
|
||||
*((uint32_t*)(&output[i])) = __REV(ctx->state[i >> 2]);
|
||||
}
|
||||
}
|
||||
#endif /* #if defined(MBEDTLS_SHA256_ALT) && defined(MBEDTLS_SHA256_C) */
|
||||
|
||||
#if defined(MBEDTLS_SHA1_ALT) && defined(MBEDTLS_SHA1_C)
|
||||
|
||||
/**
|
||||
* \brief Initialize SHA-1 context
|
||||
*/
|
||||
void mbedtls_sha1_init( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
if( ctx == NULL ) {
|
||||
return;
|
||||
}
|
||||
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clear SHA-1 context
|
||||
*/
|
||||
void mbedtls_sha1_free( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
if( ctx == NULL ) {
|
||||
return;
|
||||
}
|
||||
memset( ctx, 0, sizeof( mbedtls_sha1_context ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Clone (the state of) a SHA-1 context
|
||||
*/
|
||||
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
|
||||
const mbedtls_sha1_context *src )
|
||||
{
|
||||
if ( dst != NULL && src != NULL ) {
|
||||
*dst = *src;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*/
|
||||
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx )
|
||||
{
|
||||
ctx->total[0] = 0;
|
||||
ctx->total[1] = 0;
|
||||
memcpy(ctx->state, init_state_sha1, 32);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief SHA-1 process buffer
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void mbedtls_sha1_update( mbedtls_sha1_context *ctx,
|
||||
const unsigned char *input,
|
||||
size_t ilen )
|
||||
{
|
||||
size_t fill;
|
||||
uint32_t left;
|
||||
|
||||
if( ilen == 0 ) {
|
||||
return;
|
||||
}
|
||||
|
||||
left = ctx->total[0] & 0x3F;
|
||||
fill = 64 - left;
|
||||
|
||||
ctx->total[0] += (uint32_t) ilen;
|
||||
ctx->total[0] &= 0xFFFFFFFF;
|
||||
|
||||
if( ctx->total[0] < (uint32_t) ilen ) {
|
||||
ctx->total[1]++;
|
||||
}
|
||||
|
||||
if( left && ilen >= fill ) {
|
||||
memcpy( (void *) (ctx->buffer + left), input, fill );
|
||||
mbedtls_sha1_process( ctx, ctx->buffer );
|
||||
input += fill;
|
||||
ilen -= fill;
|
||||
left = 0;
|
||||
}
|
||||
|
||||
while( ilen >= 64 ) {
|
||||
size_t blocks = ilen / 64;
|
||||
crypto_sha_update_state( ctx->state, input, blocks, CRYPTO_SHA1 );
|
||||
input += blocks * 64;
|
||||
ilen -= blocks * 64;
|
||||
}
|
||||
|
||||
if( ilen > 0 ) {
|
||||
memcpy( (void *) (ctx->buffer + left), input, ilen );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief SHA-1 final digest
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx,
|
||||
unsigned char output[20] )
|
||||
{
|
||||
uint32_t last, padn;
|
||||
uint32_t high, low;
|
||||
unsigned char msglen[8];
|
||||
|
||||
high = ( ctx->total[0] >> 29 )
|
||||
| ( ctx->total[1] << 3 );
|
||||
low = ( ctx->total[0] << 3 );
|
||||
|
||||
PUT_UINT32_BE( high, msglen, 0 );
|
||||
PUT_UINT32_BE( low, msglen, 4 );
|
||||
|
||||
last = ctx->total[0] & 0x3F;
|
||||
padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last );
|
||||
|
||||
mbedtls_sha1_update( ctx, sha_padding, padn );
|
||||
mbedtls_sha1_update( ctx, msglen, 8 );
|
||||
|
||||
for ( size_t i = 0; i < 20; i+=4) {
|
||||
*((uint32_t*)(&output[i])) = __REV(ctx->state[i >> 2]);
|
||||
}
|
||||
}
|
||||
|
||||
/* Internal use */
|
||||
void mbedtls_sha1_process( mbedtls_sha1_context *ctx,
|
||||
const unsigned char data[64] )
|
||||
{
|
||||
crypto_sha_update_state( ctx->state, data, 1, CRYPTO_SHA1 );
|
||||
}
|
||||
|
||||
#endif /* defined(MBEDTLS_SHA1_ALT) && defined(MBEDTLS_SHA1_C) */
|
||||
|
||||
#endif /* #if defined(CRYPTO_PRESENT) */
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA1_ALT) */
|
|
@ -0,0 +1,43 @@
|
|||
/*
|
||||
* mbed OS configuration header for mbed TLS HW acceleration
|
||||
*
|
||||
* Copyright (C) 2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MBEDTLS_DEVICE_H
|
||||
#define MBEDTLS_DEVICE_H
|
||||
|
||||
#include "em_device.h"
|
||||
|
||||
#if defined ( AES_PRESENT )
|
||||
#define MBEDTLS_AES_ALT
|
||||
#endif
|
||||
|
||||
#if defined ( CRYPTO_PRESENT )
|
||||
#define MBEDTLS_AES_ALT
|
||||
|
||||
#define MBEDTLS_ECP_INTERNAL_ALT
|
||||
#define ECP_SHORTWEIERSTRASS
|
||||
#define MBEDTLS_ECP_ADD_MIXED_ALT
|
||||
#define MBEDTLS_ECP_DOUBLE_JAC_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT
|
||||
#define MBEDTLS_ECP_NORMALIZE_JAC_ALT
|
||||
#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT
|
||||
|
||||
#define MBEDTLS_SHA1_ALT
|
||||
#define MBEDTLS_SHA256_ALT
|
||||
#endif
|
||||
|
||||
#endif /* MBEDTLS_DEVICE_H */
|
|
@ -0,0 +1,111 @@
|
|||
/**
|
||||
* \file sha1_alt.h
|
||||
*
|
||||
* \brief SHA-1 cryptographic hash function
|
||||
*
|
||||
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MBEDTLS_SHA1_ALT_H
|
||||
#define MBEDTLS_SHA1_ALT_H
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_sha1 SHA-1 cryptographic hash function
|
||||
* \brief CRYPTO hardware accelerated SHA-1 cryptographic hash function.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(MBEDTLS_SHA1_ALT)
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t state[8]; /*!< intermediate digest state */
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
}
|
||||
mbedtls_sha1_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize SHA-1 context
|
||||
*
|
||||
* \param ctx SHA-1 context to be initialized
|
||||
*/
|
||||
void mbedtls_sha1_init( mbedtls_sha1_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clear SHA-1 context
|
||||
*
|
||||
* \param ctx SHA-1 context to be cleared
|
||||
*/
|
||||
void mbedtls_sha1_free( mbedtls_sha1_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clone (the state of) a SHA-1 context
|
||||
*
|
||||
* \param dst The destination context
|
||||
* \param src The context to be cloned
|
||||
*/
|
||||
void mbedtls_sha1_clone( mbedtls_sha1_context *dst,
|
||||
const mbedtls_sha1_context *src );
|
||||
|
||||
/**
|
||||
* \brief SHA-1 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
*/
|
||||
void mbedtls_sha1_starts( mbedtls_sha1_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief SHA-1 process buffer
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void mbedtls_sha1_update( mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen );
|
||||
|
||||
/**
|
||||
* \brief SHA-1 final digest
|
||||
*
|
||||
* \param ctx SHA-1 context
|
||||
* \param output SHA-1 checksum result
|
||||
*/
|
||||
void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, unsigned char output[20] );
|
||||
|
||||
/* Internal use */
|
||||
void mbedtls_sha1_process( mbedtls_sha1_context *ctx, const unsigned char data[64] );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA1_ALT) */
|
||||
|
||||
/** \} (end addtogroup sl_crypto_sha1) */
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
|
||||
#endif /* #ifndef MBEDTLS_SHA1_ALT_H */
|
|
@ -0,0 +1,120 @@
|
|||
/**
|
||||
* \file sha256_alt.h
|
||||
*
|
||||
* \brief SHA-224 and SHA-256 cryptographic hash function
|
||||
*
|
||||
* Copyright (C) 2015-2016, Silicon Labs, http://www.silabs.com
|
||||
* 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.
|
||||
*/
|
||||
#ifndef MBEDTLS_SHA256_ALT_H
|
||||
#define MBEDTLS_SHA256_ALT_H
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
/***************************************************************************//**
|
||||
* \addtogroup sl_crypto_sha256 SHA-224 and SHA-256 cryptographic hash function
|
||||
* \brief CRYPTO hardware accelerated SHA-224 and SHA-256 cryptographic hash function.
|
||||
* \{
|
||||
******************************************************************************/
|
||||
|
||||
#if defined(MBEDTLS_SHA256_ALT)
|
||||
|
||||
/* SiliconLabs CRYPTO hardware acceleration implementation */
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* \brief SHA-256 context structure
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t state[8]; /*!< intermediate digest state */
|
||||
uint32_t total[2]; /*!< number of bytes processed */
|
||||
unsigned char buffer[64]; /*!< data block being processed */
|
||||
bool is224; /*!< false => SHA-256, else SHA-224 */
|
||||
}
|
||||
mbedtls_sha256_context;
|
||||
|
||||
/**
|
||||
* \brief Initialize SHA-256 context
|
||||
*
|
||||
* \param ctx SHA-256 context to be initialized
|
||||
*/
|
||||
void mbedtls_sha256_init( mbedtls_sha256_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clear SHA-256 context
|
||||
*
|
||||
* \param ctx SHA-256 context to be cleared
|
||||
*/
|
||||
void mbedtls_sha256_free( mbedtls_sha256_context *ctx );
|
||||
|
||||
/**
|
||||
* \brief Clone (the state of) a SHA-256 context
|
||||
*
|
||||
* \param dst The destination context
|
||||
* \param src The context to be cloned
|
||||
*/
|
||||
void mbedtls_sha256_clone( mbedtls_sha256_context *dst,
|
||||
const mbedtls_sha256_context *src );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 context setup
|
||||
*
|
||||
* \param ctx context to be initialized
|
||||
* \param is224 0 = use SHA256, 1 = use SHA224
|
||||
*/
|
||||
void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 process buffer
|
||||
*
|
||||
* \param ctx SHA-256 context
|
||||
* \param input buffer holding the data
|
||||
* \param ilen length of the input data
|
||||
*/
|
||||
void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input,
|
||||
size_t ilen );
|
||||
|
||||
/**
|
||||
* \brief SHA-256 final digest
|
||||
*
|
||||
* \param ctx SHA-256 context
|
||||
* \param output SHA-224/256 checksum result
|
||||
*/
|
||||
void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] );
|
||||
|
||||
/* Internal use */
|
||||
void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] );
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* #if defined(MBEDTLS_SHA256_ALT) */
|
||||
|
||||
/** \} (end addtogroup sl_crypto_sha256) */
|
||||
/** \} (end addtogroup sl_crypto) */
|
||||
|
||||
#endif /* #ifndef MBEDTLS_SHA256_ALT_H */
|
|
@ -2320,7 +2320,7 @@
|
|||
"inherits": ["EFM32"],
|
||||
"extra_labels_add": ["EFM32GG", "1024K", "SL_AES"],
|
||||
"core": "Cortex-M3",
|
||||
"macros": ["EFM32GG990F1024", "TRANSACTION_QUEUE_SIZE_SPI=4"],
|
||||
"macros": ["EFM32GG990F1024", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||
"release_versions": ["2", "5"],
|
||||
"device_name": "EFM32GG990F1024",
|
||||
|
@ -2374,7 +2374,7 @@
|
|||
"inherits": ["EFM32"],
|
||||
"extra_labels_add": ["EFM32LG", "256K", "SL_AES"],
|
||||
"core": "Cortex-M3",
|
||||
"macros": ["EFM32LG990F256", "TRANSACTION_QUEUE_SIZE_SPI=4"],
|
||||
"macros": ["EFM32LG990F256", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||
"release_versions": ["2", "5"],
|
||||
"device_name": "EFM32LG990F256",
|
||||
|
@ -2428,7 +2428,7 @@
|
|||
"inherits": ["EFM32"],
|
||||
"extra_labels_add": ["EFM32WG", "256K", "SL_AES"],
|
||||
"core": "Cortex-M4F",
|
||||
"macros": ["EFM32WG990F256", "TRANSACTION_QUEUE_SIZE_SPI=4"],
|
||||
"macros": ["EFM32WG990F256", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||
"release_versions": ["2", "5"],
|
||||
"device_name": "EFM32WG990F256",
|
||||
|
@ -2483,7 +2483,7 @@
|
|||
"extra_labels_add": ["EFM32ZG", "32K", "SL_AES"],
|
||||
"core": "Cortex-M0+",
|
||||
"default_toolchain": "uARM",
|
||||
"macros": ["EFM32ZG222F32", "TRANSACTION_QUEUE_SIZE_SPI=0"],
|
||||
"macros": ["EFM32ZG222F32", "TRANSACTION_QUEUE_SIZE_SPI=0", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "uARM", "IAR"],
|
||||
"default_lib": "small",
|
||||
"release_versions": ["2"],
|
||||
|
@ -2537,7 +2537,7 @@
|
|||
"extra_labels_add": ["EFM32HG", "64K", "SL_AES"],
|
||||
"core": "Cortex-M0+",
|
||||
"default_toolchain": "uARM",
|
||||
"macros": ["EFM32HG322F64", "TRANSACTION_QUEUE_SIZE_SPI=0"],
|
||||
"macros": ["EFM32HG322F64", "TRANSACTION_QUEUE_SIZE_SPI=0", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "uARM", "IAR"],
|
||||
"default_lib": "small",
|
||||
"release_versions": ["2"],
|
||||
|
@ -2590,7 +2590,7 @@
|
|||
"inherits": ["EFM32"],
|
||||
"extra_labels_add": ["EFM32PG", "256K", "SL_CRYPTO"],
|
||||
"core": "Cortex-M4F",
|
||||
"macros": ["EFM32PG1B100F256GM32", "TRANSACTION_QUEUE_SIZE_SPI=4"],
|
||||
"macros": ["EFM32PG1B100F256GM32", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||
"release_versions": ["2", "5"],
|
||||
"device_name": "EFM32PG1B100F256GM32",
|
||||
|
@ -2643,7 +2643,7 @@
|
|||
"inherits": ["EFM32"],
|
||||
"extra_labels_add": ["EFR32MG1", "256K", "SL_RAIL", "SL_CRYPTO"],
|
||||
"core": "Cortex-M4F",
|
||||
"macros": ["EFR32MG1P132F256GM48", "TRANSACTION_QUEUE_SIZE_SPI=4"],
|
||||
"macros": ["EFR32MG1P132F256GM48", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||
"release_versions": ["2", "5"],
|
||||
"device_name": "EFR32MG1P132F256GM48",
|
||||
|
@ -2654,7 +2654,7 @@
|
|||
"inherits": ["EFM32"],
|
||||
"extra_labels_add": ["EFR32MG1", "256K", "SL_RAIL", "SL_CRYPTO"],
|
||||
"core": "Cortex-M4F",
|
||||
"macros": ["EFR32MG1P233F256GM48", "TRANSACTION_QUEUE_SIZE_SPI=4"],
|
||||
"macros": ["EFR32MG1P233F256GM48", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||
"release_versions": ["2", "5"],
|
||||
"public": false,
|
||||
|
@ -2744,7 +2744,7 @@
|
|||
"inherits": ["EFM32"],
|
||||
"extra_labels_add": ["EFM32PG12", "1024K", "SL_CRYPTO"],
|
||||
"core": "Cortex-M4F",
|
||||
"macros": ["EFM32PG12B500F1024GL125", "TRANSACTION_QUEUE_SIZE_SPI=4"],
|
||||
"macros": ["EFM32PG12B500F1024GL125", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||
"release_versions": ["2", "5"],
|
||||
"public": false,
|
||||
|
@ -2794,7 +2794,7 @@
|
|||
},
|
||||
"EFR32MG12P332F1024GL125": {
|
||||
"inherits": ["EFM32"],
|
||||
"extra_labels_add": ["EFR32MG12", "1024K", "SL_RAIL", "SL_CRYPTO"],
|
||||
"extra_labels_add": ["EFR32MG12", "1024K", "SL_RAIL", "SL_CRYPTO", "MBEDTLS_CONFIG_HW_SUPPORT"],
|
||||
"core": "Cortex-M4F",
|
||||
"macros": ["EFR32MG12P332F1024GL125", "TRANSACTION_QUEUE_SIZE_SPI=4"],
|
||||
"supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"],
|
||||
|
|
Loading…
Reference in New Issue