[Silicon Labs] cryptographic acceleration support

Initial commit of mbed TLS hardware acceleration drivers for Silicon Labs parts
pull/4825/head
Steven Cooreman 2017-07-28 19:00:45 +02:00
parent 2305a8c7e4
commit 1e51dfa302
11 changed files with 4295 additions and 10 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -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

View File

@ -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 */

View File

@ -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 */

View File

@ -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) */

View File

@ -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 */

View File

@ -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 */

View File

@ -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 */

View File

@ -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"],