From 1e51dfa3022a8e08dc38b9544ccf8b5818cc6551 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Fri, 28 Jul 2017 19:00:45 +0200 Subject: [PATCH 1/5] [Silicon Labs] cryptographic acceleration support Initial commit of mbed TLS hardware acceleration drivers for Silicon Labs parts --- .../targets/TARGET_Silicon_Labs/aes_aes.c | 498 +++++ .../targets/TARGET_Silicon_Labs/aes_alt.h | 267 +++ .../targets/TARGET_Silicon_Labs/crypto_aes.c | 545 ++++++ .../targets/TARGET_Silicon_Labs/crypto_ecp.c | 1732 +++++++++++++++++ .../TARGET_Silicon_Labs/crypto_management.c | 392 ++++ .../TARGET_Silicon_Labs/crypto_management.h | 128 ++ .../targets/TARGET_Silicon_Labs/crypto_sha.c | 449 +++++ .../TARGET_Silicon_Labs/mbedtls_device.h | 43 + .../targets/TARGET_Silicon_Labs/sha1_alt.h | 111 ++ .../targets/TARGET_Silicon_Labs/sha256_alt.h | 120 ++ targets/targets.json | 20 +- 11 files changed, 4295 insertions(+), 10 deletions(-) create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/aes_aes.c create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/crypto_aes.c create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.c create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.h create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/mbedtls_device.h create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/sha1_alt.h create mode 100644 features/mbedtls/targets/TARGET_Silicon_Labs/sha256_alt.h diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/aes_aes.c b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_aes.c new file mode 100644 index 0000000000..0cf54c25ad --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_aes.c @@ -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 + +#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 */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h new file mode 100644 index 0000000000..099b7f097b --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h @@ -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 */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_aes.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_aes.c new file mode 100644 index 0000000000..cfe87ef04b --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_aes.c @@ -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 + +__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 */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c new file mode 100644 index 0000000000..4ce61df01a --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c @@ -0,0 +1,1732 @@ +/* + * Elliptic curves over GF(p): CRYPTO hw acceleration functions + * + * 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 alternative plugin implementations of various + * functions in ecp.c using the CRYPTO hardware accelerator incorporated + * in MCU devices from Silicon Laboratories. + */ +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * + * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined( MBEDTLS_ECP_C ) +#if defined( MBEDTLS_ECP_INTERNAL_ALT ) +#include "em_device.h" + +#if defined( CRYPTO_PRESENT ) + +#include "mbedtls/ecp.h" +#include "mbedtls/ecp_internal.h" +#include "em_crypto.h" +#include "em_core.h" +#include "crypto_management.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/** ECC big integer type. */ +#define ECC_BIGINT_SIZE_IN_BITS (256) +#define ECC_BIGINT_SIZE_IN_BYTES (ECC_BIGINT_SIZE_IN_BITS/8) +#define ECC_BIGINT_SIZE_IN_32BIT_WORDS (ECC_BIGINT_SIZE_IN_BYTES/sizeof(uint32_t)) +#define EC_BIGINT_COPY(X, Y) memcpy(X, Y, sizeof(ecc_bigint_t)); +typedef uint32_t ecc_bigint_t[ECC_BIGINT_SIZE_IN_32BIT_WORDS]; + +#define SLCL_ECP_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) || defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +#define MPI_TO_BIGINT(bigint, mpi) mpitobigint(bigint, mpi); + +/***************************************************************************//** + * @brief + * Convert an mpi number representation to a 32bit word array used by crypto. + ******************************************************************************/ +__STATIC_INLINE void mpitobigint( ecc_bigint_t bigint, const mbedtls_mpi* mpi ) +{ + uint32_t* bi = bigint; + + if ( mpi->n < 8 ) + { + memcpy(bigint, mpi->p, mpi->n * sizeof(uint32_t)); + memset(&bi[mpi->n], 0, sizeof(ecc_bigint_t) - mpi->n * sizeof(uint32_t)); + } + else + { + memcpy(bigint, mpi->p, 8 * sizeof(uint32_t)); + } +} + +/***************************************************************************//** + * @brief + * Returns true if the value of the DDATA0 register is equal to zero. + ******************************************************************************/ +__STATIC_INLINE bool crypto_ddata0_is_zero(CRYPTO_TypeDef* crypto, + uint32_t* status_reg) +{ + CORE_DECLARE_IRQ_STATE; + CORE_ENTER_CRITICAL(); + CRYPTO_EXECUTE_3(crypto, + CRYPTO_CMD_INSTR_CCLR, + CRYPTO_CMD_INSTR_DEC, /* Decrement by one which will set + carry bit if DDATA0 is zero. */ + CRYPTO_CMD_INSTR_INC /* Increment in order to restore + original value. */ + ); + + *status_reg = crypto->DSTATUS; + CORE_EXIT_CRITICAL(); + + return (*status_reg & CRYPTO_DSTATUS_CARRY) == CRYPTO_DSTATUS_CARRY; +} + +/***************************************************************************//** + * @brief + * Modular division using CRYPTO hardware acceleration. + * + * @details + * This function computes R = X/Y mod(N) using CRYPTO hardware acceleration. + * The implementation is not a direct replacement plugin, i.e. alternative + * implementation, of an existing mbedtls function. This function is used + * internally in other CRYPTO plugin functions indirectly replacing + * mbedtls_mpi_inv_mod. + * + * @param[in] X Dividend of modular division operation + * @param[in] Y Divisor of modular division operation + * @param[in] N Modulus + * @param[out] R The destination of the result + * + * @return N/A + ******************************************************************************/ +static void mbedtls_mpi_div_mod(CRYPTO_TypeDef *crypto, + ecc_bigint_t X, + ecc_bigint_t Y, + ecc_bigint_t N, + ecc_bigint_t R) +{ + uint32_t D[9]; + uint32_t status_reg; + uint8_t rdata; + uint8_t lsb_C; + uint8_t lsb_D; + uint8_t lsb_U; + int t; + int k; + CORE_DECLARE_IRQ_STATE; + + /************** Initialize and organize data in crypto module **************/ + + /* + ** Register usage: + ** + ** DDATA0 - holds temporary results and loads 260 bit variables in/out + ** DDATA1 - variable referred to as 'C' in the following algorithm + ** DDATA2 - variable referred to as 'U' in the following algorithm + ** DDATA3 - variable referred to as 'D' in the following algorithm + ** DDATA4 - variable referred to as 'W' in the following algorithm + */ + + EC_BIGINT_COPY(D, N); /* D will hold the modulus (n) initially */ + D[8]=0; /* Set MSWord of D to 0. */ + + CORE_ENTER_CRITICAL(); + CRYPTO_DDataWrite(&crypto->DDATA1, Y); /* Set C to Y (divisor) initially */ + CRYPTO_DDataWrite(&crypto->DDATA2, X); /* Set U to X (dividend)initially */ + CRYPTO_DDataWrite(&crypto->DDATA3, N); /* Set D to modulus p initially */ + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_3(crypto, + CRYPTO_CMD_INSTR_CLR, /* DDATA0 = 0 */ + CRYPTO_CMD_INSTR_DDATA0TODDATA4, /* Set W to zero initially*/ + CRYPTO_CMD_INSTR_DDATA1TODDATA0);/* DDATA0 = C initially */ + + t = 0; + k = 1; + + /******************* Run main loop while 'C' is non-zero ********************/ + + /* while (C != 1024'd0) */ + while ( !crypto_ddata0_is_zero(crypto, &status_reg) ) + { + + lsb_C = (status_reg & _CRYPTO_DSTATUS_DDATA0LSBS_MASK) >> _CRYPTO_DSTATUS_DDATA0LSBS_SHIFT; + if ((lsb_C & 0x1) == 0) + { + CRYPTO_EXECUTE_3(crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA1, + CRYPTO_CMD_INSTR_SHRA, + CRYPTO_CMD_INSTR_DDATA0TODDATA1 + ); + t = t-1; + } + else + { + if (t<0) + { + CRYPTO_EXECUTE_6(crypto, + CRYPTO_CMD_INSTR_DDATA2TODDATA0, + CRYPTO_CMD_INSTR_DDATA4TODDATA2, + CRYPTO_CMD_INSTR_DDATA0TODDATA4, + CRYPTO_CMD_INSTR_DDATA1TODDATA0, + CRYPTO_CMD_INSTR_DDATA3TODDATA1, + CRYPTO_CMD_INSTR_DDATA0TODDATA3); + CORE_ENTER_CRITICAL(); + CRYPTO_DDATA0_260_BITS_READ(crypto, D); + CORE_EXIT_CRITICAL(); + t = -t; + } + + k = 1; + + CRYPTO_EXECUTE_2(crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_ADD); + + rdata = CRYPTO_DData0_4LSBitsRead(crypto); + + if((rdata & 0x3) != 0x0) + k = -1; + else + t = t-1; + + /* R1 = C >> 1 */ + crypto->CMD = CRYPTO_CMD_INSTR_DDATA1TODDATA0; /* to get the lsb of C */ + + lsb_C = CRYPTO_DData0_4LSBitsRead(crypto); + CRYPTO_EXECUTE_4(crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA1, + CRYPTO_CMD_INSTR_SHRA, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_DDATA3TODDATA0); /* to get the lsb of D(R3) */ + + /* R3 = D >> 1 */ + lsb_D = CRYPTO_DData0_4LSBitsRead(crypto); + + CRYPTO_EXECUTE_2(crypto, + CRYPTO_CMD_INSTR_SELDDATA3DDATA3, + CRYPTO_CMD_INSTR_SHRA); + + if(k == 1) + { + if (((lsb_C & 0x1)==0x1) && ((lsb_D & 0x1)==0x1)) + { + CRYPTO_EXECUTE_7(crypto, + /* C = R1+R3+1 */ + CRYPTO_CMD_INSTR_SELDDATA0DDATA1, + CRYPTO_CMD_INSTR_CSET, + CRYPTO_CMD_INSTR_ADDC, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + /* U = mod(R2+R4,n) */ + CRYPTO_CMD_INSTR_SELDDATA2DDATA4, + CRYPTO_CMD_INSTR_MADD, + CRYPTO_CMD_INSTR_DDATA0TODDATA2 + ); + } + else + { + CRYPTO_EXECUTE_6(crypto, + /* C = R1+R3 */ + CRYPTO_CMD_INSTR_SELDDATA0DDATA1, + CRYPTO_CMD_INSTR_ADD, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + /* U = mod(R2+R4,n) */ + CRYPTO_CMD_INSTR_SELDDATA2DDATA4, + CRYPTO_CMD_INSTR_MADD, + CRYPTO_CMD_INSTR_DDATA0TODDATA2 + ); + } + } + else + { + if (k == -1) + { + if (((lsb_C & 0x1)==0x0) && ((lsb_D & 0x1)==0x1)) + { + CRYPTO_EXECUTE_8(crypto, + /* C = R1-R3-1 */ + CRYPTO_CMD_INSTR_DDATA0TODDATA3, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_CSET, + CRYPTO_CMD_INSTR_SUBC, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + /* U = mod(R2-R4,p) */ + CRYPTO_CMD_INSTR_SELDDATA2DDATA4, + CRYPTO_CMD_INSTR_MSUB, + CRYPTO_CMD_INSTR_DDATA0TODDATA2 + ); + } + else + { + CRYPTO_EXECUTE_7(crypto, + /* C = R1+R3 */ + CRYPTO_CMD_INSTR_DDATA0TODDATA3, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_SUB, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + /* U = mod(R2-R4,p) */ + CRYPTO_CMD_INSTR_SELDDATA2DDATA4, + CRYPTO_CMD_INSTR_MSUB, + CRYPTO_CMD_INSTR_DDATA0TODDATA2 + ); + } + + CRYPTO_DDATA0_260_BITS_WRITE(crypto, D); + crypto->CMD = CRYPTO_CMD_INSTR_DDATA0TODDATA3; + + } /* if (k == -1) */ + } + } /* else: !if((C[31:0] & 0x1) == 0x0) */ + + crypto->CMD = CRYPTO_CMD_INSTR_DDATA2TODDATA0; + + lsb_U = CRYPTO_DData0_4LSBitsRead(crypto); + + /* if ((U[31:0] & 0x1) == 0x1) */ + if((lsb_U & 0x1) == 0x1) + { + CRYPTO_EXECUTE_3( crypto, + CRYPTO_CMD_INSTR_SELDDATA2DDATA2, + CRYPTO_CMD_INSTR_SHRA, + CRYPTO_CMD_INSTR_DDATA0TODDATA2); + + CORE_ENTER_CRITICAL(); + CRYPTO_DDataWrite(&crypto->DDATA0, N); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_6( crypto, + CRYPTO_CMD_INSTR_SELDDATA0DDATA0, + CRYPTO_CMD_INSTR_SHR, + CRYPTO_CMD_INSTR_SELDDATA0DDATA2, + CRYPTO_CMD_INSTR_CSET, + CRYPTO_CMD_INSTR_ADDC, + CRYPTO_CMD_INSTR_DDATA0TODDATA2); + } + else + { + CRYPTO_EXECUTE_3(crypto, + CRYPTO_CMD_INSTR_SELDDATA2DDATA2, + CRYPTO_CMD_INSTR_SHRA, + CRYPTO_CMD_INSTR_DDATA0TODDATA2); + } + + /* DDATA0 = C */ + crypto->CMD = CRYPTO_CMD_INSTR_DDATA1TODDATA0; + + } /* End of main loop: while (C != 0) */ + + /* if (D == 1): */ + /* Decrement D by 1 and test if zero. */ + CRYPTO_EXECUTE_2(crypto, + CRYPTO_CMD_INSTR_DDATA3TODDATA0, + CRYPTO_CMD_INSTR_DEC); + + if (crypto_ddata0_is_zero(crypto, &status_reg)) + { + CORE_ENTER_CRITICAL(); + CRYPTO_DDataRead(&crypto->DDATA4, R); + CORE_EXIT_CRITICAL(); + } + else + { + CORE_ENTER_CRITICAL(); + CRYPTO_DDataWrite(&crypto->DDATA0, N); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_2(crypto, + CRYPTO_CMD_INSTR_SELDDATA0DDATA4, + CRYPTO_CMD_INSTR_SUB + ); + + CORE_ENTER_CRITICAL(); + CRYPTO_DDataRead(&crypto->DDATA0, R); + CORE_EXIT_CRITICAL(); + } + return; +} /* mbedtls_mpi_div_mod */ +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT || MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + +/***************************************************************************//** + * @brief + * Enable CRYPTO by setting up control registers for given ecc curve. + ******************************************************************************/ +int mbedtls_ecp_device_init( CRYPTO_TypeDef *device, const mbedtls_ecp_group *grp) +{ + int ret = 0; + + /* Setup CRYPTO registers for ECC operation */ + device->CTRL = 0; + device->SEQCTRL = CRYPTO_SEQCTRL_BLOCKSIZE_32BYTES | 32; + device->SEQCTRLB = 0; + + switch( grp->id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + CRYPTO_ModulusSet( device, cryptoModulusEccP192 ); + CRYPTO_MulOperandWidthSet( device, cryptoMulOperandModulusBits ); + CRYPTO_ResultWidthSet( device, cryptoResult256Bits ); + break; +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + CRYPTO_ModulusSet( device, cryptoModulusEccP224 ); + CRYPTO_MulOperandWidthSet( device, cryptoMulOperandModulusBits ); + CRYPTO_ResultWidthSet( device, cryptoResult256Bits ); + break; +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + CRYPTO_ModulusSet( device, cryptoModulusEccP256 ); + CRYPTO_MulOperandWidthSet( device, cryptoMulOperandModulusBits ); + CRYPTO_ResultWidthSet( device, cryptoResult260Bits ); + break; +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + + default: + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + break; + } + + return( ret ); +} + +/***************************************************************************//** + * @brief + * Write 256 bits of data to a DDATAX register in the CRYPTO module. + * + * @details + * Write 256 bits of data into a DDATAX (Double Data) register in the crypto + * module. + * + * @param[in] ddataReg Data register identifier + * @param[in] val Value of the data to write to the DDATA register. + ******************************************************************************/ +__STATIC_INLINE void ecp_crypto_ddata_write(CRYPTO_DDataReg_TypeDef ddataReg, + const mbedtls_mpi* mpi) +{ + uint32_t volatile* regPtr = (volatile uint32_t *) ddataReg; + uint32_t* pVal = mpi->p; + register uint32_t v0; + register uint32_t v1; + register uint32_t v2; + register uint32_t v3; + int i; + + if (mpi->n <4) + { + /* Non optimal write of data. */ + for (i=0; i<(int)mpi->n; i++) + *regPtr = *pVal++; + for (; i<8; i++) + *regPtr = 0; + } + else + { + if (mpi->n < 8) + { + /* Optimal write of first 4 words. */ + v0 = *pVal++; + v1 = *pVal++; + v2 = *pVal++; + v3 = *pVal++; + *regPtr = v0; + *regPtr = v1; + *regPtr = v2; + *regPtr = v3; + + /* Non optimal write of remaining words */ + for (i=4; i<(int)mpi->n; i++) + *regPtr = *pVal++; + for (; i<8; i++) + *regPtr = 0; + } + else + { + /* Optimal write of all data. */ + v0 = *pVal++; + v1 = *pVal++; + v2 = *pVal++; + v3 = *pVal++; + *regPtr = v0; + *regPtr = v1; + *regPtr = v2; + *regPtr = v3; + + v0 = *pVal++; + v1 = *pVal++; + v2 = *pVal++; + v3 = *pVal++; + *regPtr = v0; + *regPtr = v1; + *regPtr = v2; + *regPtr = v3; + } + } +} + +/***************************************************************************//** + * @brief + * Read 256 bits of data from a DDATAX register in the CRYPTO module. + * + * @details + * Read 256 bits of data from a DDATAX (Double Data) register in the crypto + * module. + * + * @param[in] ddataReg Data register identifier + * @param[out] val Location where to store the value in memory. + ******************************************************************************/ + +__STATIC_INLINE int ecp_crypto_ddata_read(CRYPTO_DDataReg_TypeDef ddataReg, + mbedtls_mpi* mpi) +{ + CRYPTO_DData_TypeDef ddata; + uint32_t val32; + int i; + int used; + int ret = 0; + CORE_DECLARE_IRQ_STATE; + + if (mpi->n == 8) + { + CORE_ENTER_CRITICAL(); + CRYPTO_DDataRead(ddataReg, mpi->p); + CORE_EXIT_CRITICAL(); + } + else + { + if (mpi->n > 8) + { + CORE_ENTER_CRITICAL(); + CRYPTO_DDataRead(ddataReg, mpi->p); + CORE_EXIT_CRITICAL(); + memset(&mpi->p[8], 0, sizeof(uint32_t)*(mpi->n-8)); + } + else + { + uint32_t volatile* regPtr = (volatile uint32_t*) ddataReg; + used = 0; + for (i=0; i<8; i++) + { + ddata[i] = val32 = *regPtr; + if (val32) + used = i+1; + } + if (used > (int)mpi->n) + { + SLCL_ECP_CHK( mbedtls_mpi_grow(mpi, used) ); + memcpy(mpi->p, ddata, used*sizeof(uint32_t)); + mpi->s = 1; + } + else + { + memcpy(mpi->p, ddata, mpi->n*sizeof(uint32_t)); + } + } + } + cleanup: + return( ret ); +} + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ) +{ + switch( grp->id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + return( true ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + return( true ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + return( true ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + + default: + return( false ); + } +} + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) +{ + /* Crypto operations are atomic, so no need to setup any context here */ + (void) grp; + return 0; +} + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) +{ + /* Crypto operations are atomic, so no need to free any context here */ + (void) grp; +} + +#if defined(ECP_SHORTWEIERSTRASS) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + ecc_bigint_t l; + CORE_DECLARE_IRQ_STATE; + CRYPTO_TypeDef *crypto; + + /* Strategy: + * 1) Generate l such that 1 < l < p + * 2) Z = l (R1) * Z (R4) + * 3) ll (R1) = l (R4) * l + * 4) X = ll (R1) * X (R2) + * 5) lll (R1) = ll (R1) * l (R4) + * 6) Y = lll (R1) * Y (R3) + */ + + /* Acquire entropy before grabbing crypto, since the entropy function might use crypto */ + /* Generate l such that 1 < l < p */ + ret = f_rng(p_rng, (unsigned char *)l, sizeof(l)); + if ( ret != 0 ) { + return( ret ); + } + + crypto = crypto_management_acquire(); + mbedtls_ecp_device_init(crypto, grp); + + CORE_ENTER_CRITICAL(); + CRYPTO_DDataWrite(&crypto->DDATA1, l); + ecp_crypto_ddata_write(&crypto->DDATA2, &pt->X); + ecp_crypto_ddata_write(&crypto->DDATA3, &pt->Y); + ecp_crypto_ddata_write(&crypto->DDATA4, &pt->Z); + CORE_EXIT_CRITICAL(); + + /* Z = l * Z */ + CRYPTO_EXECUTE_2 ( crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL ); + CRYPTO_InstructionSequenceWait(crypto); + + MBEDTLS_MPI_CHK( ecp_crypto_ddata_read(&crypto->DDATA0, &pt->Z) ); + + /* X = l^2 * X */ + CRYPTO_EXECUTE_6 ( crypto, + CRYPTO_CMD_INSTR_DDATA1TODDATA4, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL ); + CRYPTO_InstructionSequenceWait(crypto); + + MBEDTLS_MPI_CHK( ecp_crypto_ddata_read(&crypto->DDATA0, &pt->X) ); + + /* Y = l^3 * Y */ + CRYPTO_EXECUTE_5 ( crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_MMUL ); + CRYPTO_InstructionSequenceWait(crypto); + + MBEDTLS_MPI_CHK( ecp_crypto_ddata_read(&crypto->DDATA0, &pt->Y) ); + +cleanup: + crypto_management_release( crypto ); + return( ret ); +} +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Special cases: (1) P or Q is zero, (2) R is zero, + * (3) P == Q. + * None of these cases can happen as intermediate step in + * ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base + * point, the factor being less than its order, so none of + * them is zero; + * - Q is an odd multiple of the base point, P an even + * multiple, due to the choice of precomputed points in the + * modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as + * meaning 1. + * + * Cost in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + int ret; + CORE_DECLARE_IRQ_STATE; + CRYPTO_TypeDef *crypto = crypto_management_acquire(); + + mbedtls_ecp_device_init(crypto, grp); + + /* + STEP 1: + + Goals: + A = Qx*Pz^2 + B = Qy*Pz^3 + + Write Operations: + + R0 = Pz + R0 = Qx + R0 = Qy + + Instructions to be executed: + + 1. R0 = DMA = Pz + 2. R1 = R0 = Pz + 3. R2 = R0 = Pz + 4. Select R1, R2 + 5. R0 = R1 * R2 = Pz^2 + 6. R1 = R0 = Pz^2 + + 7. R0 = DMA = Qx + 8. R3 = R0 = Qx + 9. Select R1, R3 + 10. R0 = R1 * R3 = Qx * Pz^2 + 11. R3 = R0 = Qx * Pz^2 + + 12. Select R1, R2 + 13. R0 = R1 * R2 = Pz^3 + 14. R1 = R0 = Pz^3 + + 15. R0 = DMA = Qy + 16. R4 = R0 = Qx + 17. Select R1, R4 + 18. R0 = R1 * R4 = Qy * Pz^3 + 19. Select R0, R1 (for MSUB in step 2) + + Output State: + R0 = B + R1 = FREE + R2 = FREE + R3 = A + R4 = Pz + + STEP 1: + */ + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA0, &P->Z); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_5(crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_DDATA0TODDATA4, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA1); + CRYPTO_InstructionSequenceWait(crypto); + + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA0, &Q->X); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_4 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA3, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA3); + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA1); + CRYPTO_InstructionSequenceWait(crypto); + + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA0, &Q->Y); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA2, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL + ); + CRYPTO_InstructionSequenceWait(crypto); + + /* + STEP 2: + + Goals: + C = A - Px + D = B - Py + R->Z = Pz * C + + Write Operations: + + R1 = Py + R0 = Px (via DMA) + + Input State: + R0 = B + R1 = Py + R2 = FREE + R3 = A + R4 = Pz + + Instructions to be executed: + + 0. Select R0, R1 + 1. R0 = R0 - R1 = B - Py = D + 2. R2 = R0 = D + 3. R1 = R3 = A + 4. R0 = DMA = Px + 5. R3 = R0 = Px + 6. Select R1, R3 + 7. R0 = R1 - R3 = A - Px = C + 8. R1 = R0 = C + 9. Select R1, R4 + 10. R0 = R1 * R4 = Pz * C = R->Z + + Read Operations: + + R->Z = R0 = Pz * C + + Output State: + R0 = FREE + R1 = C + R2 = D + R3 = Px + R4 = FREE + + STEP 2: + */ + + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA1, &P->Y); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_SELDDATA0DDATA1, + CRYPTO_CMD_INSTR_MSUB, + CRYPTO_CMD_INSTR_DDATA0TODDATA2); /* R2 = D */ + CRYPTO_InstructionSequenceWait(crypto); + + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA0, &P->X); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_7 (crypto, + CRYPTO_CMD_INSTR_DDATA3TODDATA1, + CRYPTO_CMD_INSTR_DDATA0TODDATA3, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_MSUB, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, /* R1 = C */ + + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL + ); + CRYPTO_InstructionSequenceWait(crypto); + + ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->Z); + + if (ret != 0) goto cleanup; + + /* + STEP 3: + + Goals: + X1C2 = Px * C^2 + C3 = C^3 + D2 = D^2 + + Input State: + R0 = FREE + R1 = C + R2 = D + R3 = Px + R4 = FREE + + Instructions to be executed: + + 1. R4 = R1 = C + 2. Select R1, R4 + 3. R0 = R1 * R4 = C^2 + 4. R1 = R0 = C^2 + 5. R0 = R1 * R4 = C^3 + 6. R4 = R0 = C^3 + 7. Select R1, R3 + 8. R0 = R1 * R3 = Px * C^2 + 9. R3 = R0 = Px * C^2 + 10. R1 = R2 = D + 11. Select R1, R1 + 12. R0 = R1 * R1 = D^2 + 13. Select R0, R4 + 14. R0 = R0 - R4 = D2 - C3 + + Output state: + + R0 = D2 - C3 + R1 = FREE + R2 = D + R3 = X1C2 = Px * C^2 + R4 = C3 = C^3 + + STEP 3: + */ + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA1TODDATA4, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA4); + CRYPTO_InstructionSequenceWait(crypto); + + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA3); + CRYPTO_InstructionSequenceWait(crypto); + + CRYPTO_EXECUTE_5 (crypto, + CRYPTO_CMD_INSTR_DDATA2TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_SELDDATA0DDATA4, + CRYPTO_CMD_INSTR_MSUB + ); + CRYPTO_InstructionSequenceWait(crypto); + + /* + STEP 3: + + Goals: + R->X = D2 - (C3 + 2 * X1C2) = D2 - C3 - X1C2- X1C2 + Y1C3 = Py * C3 + R->Y = D * (X1C2 - R->X) - Y1C3 + + Write Operations: + R1 = Py + + Input State: + R0 = D2 - C3 + R1 = FREE + R2 = D + R3 = X1C2 + R4 = C3 + + Instructions to be executed: + + 1. Select R0, R3 + 2. R0 = R0 - R3 = D2 - C3 - X1C2 + 3. R0 = R0 - R3 = D2 - C3 - X1C2 - X1C2 = R->X + 4. DMA = R0 = R->X + 5. R1 = R0 = R->X + + 6. Select R3, R1 + 7. R0 = R3 - R1 = X1C2 - R->X + 8. R1 = R0 = X1C2 - R->X + 9. Select R1, R2 + 10. R0 = R1 * R2 = D *(X1C2 - R->X) + 11. R2 = R0 + + 12. R0 = DMA = Py + 13. R1 = R0 = Py + 14. Select R1, R4 + 15. R0 = R1 * R4 = Py * C3 = Y1C3 + 16. R4 = R0 = Y1C3 + + 17. Select R2, R4 + 18. R0 = R2 - R4 + + Read Operations: + + R->X = R2 = D2 - (C3 + 2 * X1C2) + R->Y = R0 = D * (X1C2 - R->X) - Y1C3 + + STEP 4: + */ + + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_SELDDATA0DDATA3, + CRYPTO_CMD_INSTR_MSUB, + CRYPTO_CMD_INSTR_MSUB); + CRYPTO_InstructionSequenceWait(crypto); + + ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->X); + if ( ret != 0 ) goto cleanup; + + CRYPTO_EXECUTE_7 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + + CRYPTO_CMD_INSTR_SELDDATA3DDATA1, + CRYPTO_CMD_INSTR_MSUB, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA2); + CRYPTO_InstructionSequenceWait(crypto); + + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA0, &P->Y); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_6 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA4, + + CRYPTO_CMD_INSTR_SELDDATA2DDATA4, + CRYPTO_CMD_INSTR_MSUB + ); + CRYPTO_InstructionSequenceWait(crypto); + + ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->Y); + if ( ret != 0 ) goto cleanup; + + cleanup: + crypto_management_release( crypto ); + return ( ret ); +} +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ + int ret; + CORE_DECLARE_IRQ_STATE; + CRYPTO_TypeDef *crypto = crypto_management_acquire(); + + mbedtls_ecp_device_init(crypto, grp); + + ecc_bigint_t _2YY; + /* + STEP 1: + + Goals: + ZZ = Z^2 + R->Z = 2 * Y * Z + YY = Y^2 + 4YY = 4 * Y^2 + + Write Operations: + + R2 = Y + R3 = Z + + Instructions to be executed: + + 1. R0 = DMA = Z + 2. R1 = R0 = Z + 3. R2 = R0 = Z + 4. Select R1, R2 + 5. R0 = R1 * R2 = Z^2 = ZZ + 6. R3 = R0 = ZZ + + 7. R0 = DMA = Y + 8. R2 = R0 = Y + 9. R0 = R1 * R2 = Y * Z + 10. Select R0, R0 + 11. R0 = R0 + R0 = 2 * Y * Z = R->Z + + 12. DMA = R0 = R->Z + + 13. R1 = R2 = Y + 14. Select R1, R2 + 15. R0 = R1 * R2 = Y^2 = YY + 16. Select R0, R0 + 17. R0 = R0 + R0 = 2YY + + Read Operations: + + R->Z = R0 = 2 * Y * Z + 2YY = R0 + + Output State: + R0 = 2YY + R1 = FREE + R2 = FREE + R3 = ZZ + R4 = FREE + + STEP 1: + */ + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA0, &P->Z); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_5 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_DDATA0TODDATA2, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA3); + CRYPTO_InstructionSequenceWait(crypto); + + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA0, &P->Y); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_4 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA2, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_SELDDATA0DDATA0, + CRYPTO_CMD_INSTR_MADD); + CRYPTO_InstructionSequenceWait(crypto); + + ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->Z); + if ( ret != 0 ) goto cleanup; + + CRYPTO_EXECUTE_5 (crypto, + CRYPTO_CMD_INSTR_DDATA2TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_SELDDATA0DDATA0, + CRYPTO_CMD_INSTR_MADD + ); + CRYPTO_InstructionSequenceWait(crypto); + + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA4, &P->X); + CRYPTO_DDataRead(&crypto->DDATA0, _2YY); + CORE_EXIT_CRITICAL(); + + /* + STEP 2: + + Goals: + A = 4YY * X + C = 3(X - ZZ)(X + ZZ) + + Write Operations: + + R4 = X + + Input State: + R0 = 2YY + R1 = FREE + R2 = FREE + R3 = ZZ + R4 = X + + Instructions to be executed: + + 1. R0 = R0 + R0 = 4YY + 2. R1 = R0 = 4YY + 3. Select R1, R4 + 4. R0 = R1 * R4 = 4YY * X = A + 5. R2 = R0 = A + 6. Select R4, R3 + 7. R0 = R4 + R3 = X + ZZ + 8. R1 = R0 = X + ZZ + 9. R0 = R4 - R3 = X - ZZ + 0. R2 = R0 = X - ZZ + 11. Select R1, R2 + 12. R0 = R1 * R2 = (X + ZZ)(X - ZZ) + 13. R1 = R0 = (X + ZZ)(X - ZZ) + 14. Select R0, R1 + 15. R0 = R0 + R1 = 2(X + ZZ)(X - ZZ) + 16. R0 = R0 + R1 = 3(X + ZZ)(X - ZZ) = C + 17. R1 = R0 = C + + Output State: + R0 = FREE + R1 = C + R2 = A + R3 = FREE + R4 = FREE + + STEP 2: + */ + CRYPTO_EXECUTE_11(crypto, + CRYPTO_CMD_INSTR_SELDDATA0DDATA0, + CRYPTO_CMD_INSTR_MADD, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA2, + CRYPTO_CMD_INSTR_SELDDATA4DDATA3, + CRYPTO_CMD_INSTR_MADD, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_MSUB, + CRYPTO_CMD_INSTR_DDATA0TODDATA4); + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_7 (crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA0DDATA1, + CRYPTO_CMD_INSTR_MADD, + CRYPTO_CMD_INSTR_MADD, + CRYPTO_CMD_INSTR_DDATA0TODDATA1 + ); + CRYPTO_InstructionSequenceWait(crypto); + /* + STEP 3: + + Goals: + R->X = C^2 - 2A + D = C(A - R->X) + + Input State: + R0 = FREE + R1 = C + R2 = A + R3 = FREE + R4 = FREE + + Instructions to be executed: + + 1. R4 = R1 = C + 2. Select R1, R4 + 3. R0 = R1 * R4 = C^2 + 4. Select R0, R2 + 5. R0 = R0 - R2 = C^2 - 2A = R->X + 6. R4 = R0 = R->X + 7. Select R3, R4 + 8. R0 = R3 - R4 = A - R->X + 9. R2 = R0 = A - R->X + 10 Select R1, R2 + 11. R0 = R1 * R2 = C(A - R->X) = D + + Read Operations: + + R->X = R4 = C^2 - 2A + + Output State: + R0 = FREE + R1 = FREE + R2 = FREE + R3 = D + R4 = FREE + + STEP 3: + */ + + CRYPTO_EXECUTE_8 (crypto, + CRYPTO_CMD_INSTR_SELDDATA2DDATA2, + CRYPTO_CMD_INSTR_MADD, + CRYPTO_CMD_INSTR_DDATA0TODDATA4, + + CRYPTO_CMD_INSTR_DDATA1TODDATA3, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_MMUL, + + CRYPTO_CMD_INSTR_SELDDATA0DDATA4, + CRYPTO_CMD_INSTR_MSUB); + CRYPTO_InstructionSequenceWait(crypto); + + ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->X); + if ( ret != 0 ) goto cleanup; + + CRYPTO_EXECUTE_7 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA4, + + CRYPTO_CMD_INSTR_SELDDATA2DDATA4, + CRYPTO_CMD_INSTR_MSUB, + CRYPTO_CMD_INSTR_DDATA0TODDATA2, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA3 + ); + CRYPTO_InstructionSequenceWait(crypto); + + + /* + STEP 4: + + Goals: + B = 8 * Y^4 + R->Y = D - B + + Write Operations: + + R1 = YY + + Input State: + R0 = FREE + R1 = YY + R2 = FREE + R3 = D + R4 = FREE + + Instructions to be executed: + + 2. R0 = DMA0 + 3. R1 = R0 = Y^2 + 4. R2 = R0 = Y^2 + 5. Select R1, R2 + 6. R0 = R1 * R2 = Y^4 + 7. Select R0, R0 + 8. R0 = R0 + R0 = 2 * Y^4 + 9. R0 = R0 + R0 = 4 * Y^4 + 10. R0 = R0 + R0 = 8 * Y^4 + 11. R2 = R0 + 12. Select R3, R2 + 13. R0 = R3 - R2 = D - B = R->Y + + Read Operations: + + R->Y = R0 = D - B + + STEP 4: + */ + CORE_ENTER_CRITICAL(); + CRYPTO_DDataWrite(&crypto->DDATA0, _2YY); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_9 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_DDATA0TODDATA2, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL, + + CRYPTO_CMD_INSTR_SELDDATA0DDATA0, + CRYPTO_CMD_INSTR_MADD, + CRYPTO_CMD_INSTR_DDATA0TODDATA2, + + CRYPTO_CMD_INSTR_SELDDATA3DDATA2, + CRYPTO_CMD_INSTR_MSUB + ); + CRYPTO_InstructionSequenceWait(crypto); + + ret = ecp_crypto_ddata_read(&crypto->DDATA0, &R->Y); + if ( ret != 0 ) goto cleanup; + + cleanup: + crypto_management_release( crypto ); + + return ( ret ); +} +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], + size_t t_len ) +{ + int ret = 0; + size_t i; + ecc_bigint_t* cc; + ecc_bigint_t uu; + ecc_bigint_t one; + ecc_bigint_t modulus; + CORE_DECLARE_IRQ_STATE; + + if( t_len < 2 ) + return( mbedtls_internal_ecp_normalize_jac( grp, *T ) ); + + if( ( cc = mbedtls_calloc( t_len, sizeof( ecc_bigint_t ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MPI_TO_BIGINT( cc[0], &T[0]->Z ); + + CRYPTO_TypeDef *crypto = crypto_management_acquire(); + mbedtls_ecp_device_init(crypto, grp); + + for( i = 1; i < t_len; i++ ) + { + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write( &crypto->DDATA1, &T[i]->Z ); + CRYPTO_DDataWrite( &crypto->DDATA2, cc[i-1] ); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_2(crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + + CORE_ENTER_CRITICAL(); + CRYPTO_DDataRead( &crypto->DDATA0, cc[i] ); + CORE_EXIT_CRITICAL(); + } + + memset(one, 0, sizeof(one)); + one[0]=1; + MPI_TO_BIGINT( modulus, &grp->P ); + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + mbedtls_mpi_div_mod(crypto, one, cc[t_len-1], modulus, uu); + + for( i = t_len - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) + { + /* Z_inv (DDATA2) = uu */ + CORE_ENTER_CRITICAL(); + CRYPTO_DDataWrite(&crypto->DDATA2, uu); + CORE_EXIT_CRITICAL(); + } + else + { + /* Z_inv (DDATA1) = uu x cc[i-1] modulo p */ + /* uu = uu x T[i]->Z modulo p */ + CORE_ENTER_CRITICAL(); + CRYPTO_DDataWrite(&crypto->DDATA1, uu); + CRYPTO_DDataWrite(&crypto->DDATA2, cc[i-1]); + ecp_crypto_ddata_write( &crypto->DDATA3, &T[i]->Z ); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_3(crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL, + CRYPTO_CMD_INSTR_DDATA0TODDATA2); /* Z_inv (DDATA2) */ + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_2(crypto, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + + CORE_ENTER_CRITICAL(); + CRYPTO_DDataRead(&crypto->DDATA0, uu); + CORE_EXIT_CRITICAL(); + } + + /* + * proceed as in normalize() + */ + CORE_ENTER_CRITICAL(); + ecp_crypto_ddata_write(&crypto->DDATA3, &T[i]->X); + ecp_crypto_ddata_write(&crypto->DDATA4, &T[i]->Y); + CORE_EXIT_CRITICAL(); + + /* Z_inv already in DDATA2 */ + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA2TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA3, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + + ecp_crypto_ddata_read(&crypto->DDATA0, &T[i]->Y); + ecp_crypto_ddata_read(&crypto->DDATA3, &T[i]->X); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + SLCL_ECP_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + SLCL_ECP_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + + cleanup: + crypto_management_release( crypto ); + mbedtls_free( cc ); + + return( ret ); +} +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ) +{ + int ret = 0; + CORE_DECLARE_IRQ_STATE; + CRYPTO_TypeDef *crypto = crypto_management_acquire(); + + mbedtls_ecp_device_init(crypto, grp); + + ecc_bigint_t one; + ecc_bigint_t Z; + ecc_bigint_t modulus; + ecc_bigint_t Z_inv; + + memset(one, 0, sizeof(one)); + one[0]=1; + + MPI_TO_BIGINT( Z, &pt->Z ); + MPI_TO_BIGINT( modulus, &grp->P ); + + mbedtls_mpi_div_mod(crypto, one, Z, modulus, Z_inv); + + /* + + Goals: + R->X = P->X * Z_inv ^2 + R->Y = P->Y * Z_inv ^3 + + Write Operations: + + R1 = Z_inv + R3 = P->X + R4 = P->Y + + Instructions to be executed: + + 1. R2 = R1 = Z_inv + 2. Select R1, R2 + 3. R0 = R1 * R2 = Z_inv^2 + 4. R1 = R0 = Z_inv^2 + 5. Select R1, R3 + 6. R0 = R1 * R3 = P->X * Z_inv^2 = R->X + 7. R3 = R0 + 8. Select R1, R2 + 9. R0 = R1 * R2 = Z_inv^3 + 10. R1 = R0 = Z_inv^3 + 11. Select R1, R4 + 12. R0 = R1 * R4 = P->Y * Z_inv^3 = R->Y + + Read Operations: + + R->Y = R0 = P->Y * P->Z_inv^3 + R->X = R3 = P->X * P->Z_inv^2 + + */ + CORE_ENTER_CRITICAL(); + CRYPTO_DDataWrite(&crypto->DDATA1, Z_inv); + ecp_crypto_ddata_write(&crypto->DDATA3, &pt->X); + ecp_crypto_ddata_write(&crypto->DDATA4, &pt->Y); + CORE_EXIT_CRITICAL(); + + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA1TODDATA2, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA3, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA3, + CRYPTO_CMD_INSTR_SELDDATA1DDATA2, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + CRYPTO_EXECUTE_3 (crypto, + CRYPTO_CMD_INSTR_DDATA0TODDATA1, + CRYPTO_CMD_INSTR_SELDDATA1DDATA4, + CRYPTO_CMD_INSTR_MMUL); + CRYPTO_InstructionSequenceWait(crypto); + + ecp_crypto_ddata_read(&crypto->DDATA0, &pt->Y); + ecp_crypto_ddata_read(&crypto->DDATA3, &pt->X); + + crypto_management_release( crypto ); + + /* + * Z = 1 + */ + SLCL_ECP_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + + cleanup: + return( ret ); +} +#endif + +#endif /* ECP_SHORTWEIERSTRASS */ + +#endif /* #if defined( CRYPTO_PRESENT ) */ + +#endif /* #if defined( MBEDTLS_ECP_INTERNAL_ALT ) */ + +#endif /* #if defined( MBEDTLS_ECP_C ) */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.c new file mode 100644 index 0000000000..e506b91420 --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.c @@ -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 */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.h b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.h new file mode 100644 index 0000000000..d44c1717c2 --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.h @@ -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 + +#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 */ \ No newline at end of file diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c new file mode 100644 index 0000000000..765b264421 --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c @@ -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 + +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) */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/mbedtls_device.h b/features/mbedtls/targets/TARGET_Silicon_Labs/mbedtls_device.h new file mode 100644 index 0000000000..1646498a8a --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/mbedtls_device.h @@ -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 */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/sha1_alt.h b/features/mbedtls/targets/TARGET_Silicon_Labs/sha1_alt.h new file mode 100644 index 0000000000..cbf8cac37f --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/sha1_alt.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 */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/sha256_alt.h b/features/mbedtls/targets/TARGET_Silicon_Labs/sha256_alt.h new file mode 100644 index 0000000000..5a7bf9a676 --- /dev/null +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/sha256_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 +#include +#include + +#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 */ diff --git a/targets/targets.json b/targets/targets.json index 7da1bd6066..1e4396301d 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -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"], From e07ab46f325878f51a788a15529b8d529c4a23b9 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Wed, 2 Aug 2017 16:03:29 +0200 Subject: [PATCH 2/5] Apply feedback from @RonEld * Use _C flags at compile time in SHA to avoid compiling in unconfigured features * Don't define ECP_SHORTWEIERSTRASS since it is part of the application's configuration --- .../targets/TARGET_Silicon_Labs/crypto_sha.c | 16 ++++++++++++++-- .../targets/TARGET_Silicon_Labs/mbedtls_device.h | 1 - 2 files changed, 14 insertions(+), 3 deletions(-) diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c index 765b264421..429bec25b5 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c @@ -40,7 +40,7 @@ #include "mbedtls/sha1.h" #include "mbedtls/sha256.h" -#if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA1_ALT) +#if ( defined(MBEDTLS_SHA256_ALT) && defined(MBEDTLS_SHA256_C) ) || ( defined(MBEDTLS_SHA1_ALT) && defined (MBEDTLS_SHA1_C) ) #include "em_device.h" @@ -51,6 +51,7 @@ #include "em_assert.h" #include +#if defined(MBEDTLS_SHA1_C) static const uint32_t init_state_sha1[8] = { 0x67452301UL, @@ -62,7 +63,9 @@ static const uint32_t init_state_sha1[8] = 0x0UL, 0x0UL }; +#endif /* defined(MBEDTLS_SHA1_C) */ +#if defined(MBEDTLS_SHA256_C) static const uint32_t init_state_sha256[8] = { 0x6A09E667UL, @@ -86,6 +89,7 @@ static const uint32_t init_state_sha224[8] = 0x64F98FA7UL, 0xBEFA4FA4UL }; +#endif /* defined(MBEDTLS_SHA256_C) */ static const unsigned char sha_padding[64] = { @@ -96,8 +100,12 @@ static const unsigned char sha_padding[64] = }; typedef enum { +#if defined(MBEDTLS_SHA1_C) CRYPTO_SHA1, +#endif /* defined(MBEDTLS_SHA1_C) */ +#if defined(MBEDTLS_SHA256_C) CRYPTO_SHA2 +#endif /* defined(MBEDTLS_SHA256_C) */ } crypto_sha_mode_t; /* @@ -131,12 +139,16 @@ static void crypto_sha_update_state( uint32_t state[8], CRYPTO_TypeDef *crypto = crypto_management_acquire(); switch ( mode ) { +#if defined(MBEDTLS_SHA1_C) case CRYPTO_SHA1: crypto->CTRL = CRYPTO_CTRL_SHA_SHA1; break; +#endif /* defined(MBEDTLS_SHA1_C) */ +#if defined(MBEDTLS_SHA256_C) case CRYPTO_SHA2: crypto->CTRL = CRYPTO_CTRL_SHA_SHA2; break; +#endif /* defined(MBEDTLS_SHA256_C) */ } crypto->WAC = 0; @@ -446,4 +458,4 @@ void mbedtls_sha1_process( mbedtls_sha1_context *ctx, #endif /* #if defined(CRYPTO_PRESENT) */ -#endif /* #if defined(MBEDTLS_SHA256_ALT) || defined(MBEDTLS_SHA1_ALT) */ +#endif /* #if ( defined(MBEDTLS_SHA256_ALT) && defined(MBEDTLS_SHA256_C) ) || ( defined(MBEDTLS_SHA1_ALT) && defined (MBEDTLS_SHA1_C) ) */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/mbedtls_device.h b/features/mbedtls/targets/TARGET_Silicon_Labs/mbedtls_device.h index 1646498a8a..d76aba13c6 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/mbedtls_device.h +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/mbedtls_device.h @@ -29,7 +29,6 @@ #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 From 2e2fb6ff263e1ad0564481a00c5caa932ce34b78 Mon Sep 17 00:00:00 2001 From: stcoorem Date: Thu, 19 Oct 2017 12:00:09 +0200 Subject: [PATCH 3/5] Applied @yanesca and @andresag01 comments (#4825) --- .../targets/TARGET_Silicon_Labs/aes_aes.c | 64 +++++-------------- .../targets/TARGET_Silicon_Labs/aes_alt.h | 63 ++++++++++++++++-- .../targets/TARGET_Silicon_Labs/crypto_aes.c | 44 ++++++++----- .../targets/TARGET_Silicon_Labs/crypto_ecp.c | 34 ++++------ .../targets/TARGET_Silicon_Labs/sha1_alt.h | 2 + 5 files changed, 115 insertions(+), 92 deletions(-) diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/aes_aes.c b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_aes.c index 0cf54c25ad..822c7e6f46 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/aes_aes.c +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_aes.c @@ -19,13 +19,11 @@ */ #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) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_AES_ALT) #include "em_aes.h" #include "em_cmu.h" #include "em_bus.h" @@ -143,51 +141,21 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, /* * AES-ECB block encryption */ -void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) +int mbedtls_internal_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; - } + return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, input, output); } /* * AES-ECB block decryption */ -void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ) +int mbedtls_internal_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; - } + return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, input, output); } /* @@ -299,9 +267,9 @@ int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, const unsigned char *input, unsigned char *output ) { - size_t n = iv_off ? *iv_off : 0; + size_t n = ( iv_off != NULL ) ? *iv_off : 0; - if ( n || ( length & 0xf ) ) + if ( ( n > 0 ) || ( length & 0xf ) ) { // IV offset or length not aligned to block size int c; @@ -410,7 +378,7 @@ int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, /* * AES-CTR Nonce update function */ -void aes_ctr_update_nonce( uint8_t *nonce_counter ) +static void aes_ctr_update_nonce( uint8_t *nonce_counter ) { for( size_t i = 16; i > 0; i-- ) if( ++nonce_counter[i - 1] != 0 ) @@ -428,9 +396,9 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, const unsigned char *input, unsigned char *output ) { - size_t n = nc_off ? *nc_off : 0; + size_t n = ( nc_off != NULL ) ? *nc_off : 0; - if ( n || ( length & 0xf ) || ctx->keybits == 192 ) + if ( ( n > 0 ) || ( length & 0xf ) ) { // IV offset or length not aligned to block size int c, i; @@ -493,6 +461,6 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, } #endif /* MBEDTLS_CIPHER_MODE_CTR */ -#endif /* AES_PRESENT && (AES_COUNT == 1) */ #endif /* MBEDTLS_AES_ALT */ #endif /* MBEDTLS_AES_C */ +#endif /* AES_PRESENT && (AES_COUNT == 1) */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h index 099b7f097b..f08e62320c 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h @@ -237,10 +237,12 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, * \param ctx AES context * \param input Plaintext block * \param output Output (ciphertext) block + * + * \return 0 if successful */ -void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); /** * \brief Internal AES block decryption function @@ -250,10 +252,59 @@ void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, * \param ctx AES context * \param input Ciphertext block * \param output Output (plaintext) block + * + * \return 0 if successful */ -void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, - const unsigned char input[16], - unsigned char output[16] ); +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Internal AES block encryption function + * (Only exposed to allow overriding it, + * see MBEDTLS_AES_ENCRYPT_ALT) + * + * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0 + * + * \param ctx AES context + * \param input Plaintext block + * \param output Output (ciphertext) block + */ +MBEDTLS_DEPRECATED static inline void mbedtls_aes_encrypt( + mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_encrypt( ctx, input, output ); +} + +/** + * \brief Internal AES block decryption function + * (Only exposed to allow overriding it, + * see MBEDTLS_AES_DECRYPT_ALT) + * + * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0 + * + * \param ctx AES context + * \param input Ciphertext block + * \param output Output (plaintext) block + */ +MBEDTLS_DEPRECATED static inline void mbedtls_aes_decrypt( + mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_decrypt( ctx, input, output ); +} + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ #ifdef __cplusplus } diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_aes.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_aes.c index cfe87ef04b..8b3c75aba5 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_aes.c +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_aes.c @@ -31,13 +31,11 @@ */ #include "mbedtls/aes.h" - -#if defined(MBEDTLS_AES_C) -#if defined(MBEDTLS_AES_ALT) - #include "em_device.h" #if defined(CRYPTO_PRESENT) +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_AES_ALT) #include "crypto_management.h" #include "em_crypto.h" @@ -45,7 +43,7 @@ #include __STATIC_INLINE void CRYPTO_DataReadUnaligned(volatile uint32_t * reg, - const uint8_t * val) + uint8_t * const val) { /* Check data is 32bit aligned, if not, read into temporary buffer and then move to user buffer. */ @@ -53,16 +51,16 @@ __STATIC_INLINE void CRYPTO_DataReadUnaligned(volatile uint32_t * reg, { uint32_t temp[4]; CRYPTO_DataRead(reg, temp); - memcpy((void*)val, temp, 16); + memcpy(val, temp, 16); } else { - CRYPTO_DataRead(reg, (uint32_t*)val); + CRYPTO_DataRead(reg, (uint32_t* const)val); } } __STATIC_INLINE void CRYPTO_DataWriteUnaligned(volatile uint32_t * reg, - const uint8_t * val) + uint8_t * const val) { /* Check data is 32bit aligned, if not move to temporary buffer before writing.*/ @@ -74,7 +72,7 @@ __STATIC_INLINE void CRYPTO_DataWriteUnaligned(volatile uint32_t * reg, } else { - CRYPTO_DataWrite(reg, (uint32_t*)val); + CRYPTO_DataWrite(reg, (uint32_t* const)val); } } @@ -113,8 +111,6 @@ int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, 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 ); @@ -139,8 +135,6 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, 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 ); @@ -173,6 +167,26 @@ int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, * functions with in-place implemented functions, to get much shorter * critical sections */ +/* + * AES-ECB block encryption + */ +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, input, output); +} + +/* + * AES-ECB block decryption + */ +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + return mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_DECRYPT, input, output); +} + /* * AES-ECB block encryption/decryption */ @@ -538,8 +552,6 @@ int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, } #endif /* MBEDTLS_CIPHER_MODE_CTR */ -#endif /* CRYPTO_PRESENT */ - #endif /* MBEDTLS_AES_ALT */ - #endif /* MBEDTLS_AES_C */ +#endif /* CRYPTO_PRESENT */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c index 4ce61df01a..34f57fc13b 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c @@ -48,14 +48,16 @@ #include MBEDTLS_CONFIG_FILE #endif -#if defined( MBEDTLS_ECP_C ) -#if defined( MBEDTLS_ECP_INTERNAL_ALT ) #include "em_device.h" #if defined( CRYPTO_PRESENT ) +#if defined( MBEDTLS_ECP_C ) +#if defined( MBEDTLS_ECP_INTERNAL_ALT ) + #include "mbedtls/ecp.h" #include "mbedtls/ecp_internal.h" +#include "mbedtls/platform.h" #include "em_crypto.h" #include "em_core.h" #include "crypto_management.h" @@ -63,14 +65,6 @@ #include #include -#if defined(MBEDTLS_PLATFORM_C) -#include "mbedtls/platform.h" -#else -#include -#define mbedtls_calloc calloc -#define mbedtls_free free -#endif - /** ECC big integer type. */ #define ECC_BIGINT_SIZE_IN_BITS (256) #define ECC_BIGINT_SIZE_IN_BYTES (ECC_BIGINT_SIZE_IN_BITS/8) @@ -394,7 +388,7 @@ static void mbedtls_mpi_div_mod(CRYPTO_TypeDef *crypto, * @brief * Enable CRYPTO by setting up control registers for given ecc curve. ******************************************************************************/ -int mbedtls_ecp_device_init( CRYPTO_TypeDef *device, const mbedtls_ecp_group *grp) +static int crypto_device_init( CRYPTO_TypeDef *device, const mbedtls_ecp_group *grp) { int ret = 0; @@ -641,8 +635,6 @@ void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ) (void) grp; } -#if defined(ECP_SHORTWEIERSTRASS) - #if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) /** * \brief Randomize jacobian coordinates: @@ -686,7 +678,7 @@ int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, } crypto = crypto_management_acquire(); - mbedtls_ecp_device_init(crypto, grp); + crypto_device_init(crypto, grp); CORE_ENTER_CRITICAL(); CRYPTO_DDataWrite(&crypto->DDATA1, l); @@ -781,7 +773,7 @@ int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, CORE_DECLARE_IRQ_STATE; CRYPTO_TypeDef *crypto = crypto_management_acquire(); - mbedtls_ecp_device_init(crypto, grp); + crypto_device_init(crypto, grp); /* STEP 1: @@ -1138,7 +1130,7 @@ int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, CORE_DECLARE_IRQ_STATE; CRYPTO_TypeDef *crypto = crypto_management_acquire(); - mbedtls_ecp_device_init(crypto, grp); + crypto_device_init(crypto, grp); ecc_bigint_t _2YY; /* @@ -1491,7 +1483,7 @@ int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, MPI_TO_BIGINT( cc[0], &T[0]->Z ); CRYPTO_TypeDef *crypto = crypto_management_acquire(); - mbedtls_ecp_device_init(crypto, grp); + crypto_device_init(crypto, grp); for( i = 1; i < t_len; i++ ) { @@ -1633,7 +1625,7 @@ int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, CORE_DECLARE_IRQ_STATE; CRYPTO_TypeDef *crypto = crypto_management_acquire(); - mbedtls_ecp_device_init(crypto, grp); + crypto_device_init(crypto, grp); ecc_bigint_t one; ecc_bigint_t Z; @@ -1723,10 +1715,8 @@ int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, } #endif -#endif /* ECP_SHORTWEIERSTRASS */ - -#endif /* #if defined( CRYPTO_PRESENT ) */ - #endif /* #if defined( MBEDTLS_ECP_INTERNAL_ALT ) */ #endif /* #if defined( MBEDTLS_ECP_C ) */ + +#endif /* #if defined( CRYPTO_PRESENT ) */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/sha1_alt.h b/features/mbedtls/targets/TARGET_Silicon_Labs/sha1_alt.h index cbf8cac37f..891b0655c8 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/sha1_alt.h +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/sha1_alt.h @@ -34,6 +34,8 @@ #if defined(MBEDTLS_SHA1_ALT) +#include + #ifdef __cplusplus extern "C" { #endif From 2f02a23ac045d2eadc0495e90424ce97288b7bcb Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Tue, 31 Oct 2017 18:58:15 +0100 Subject: [PATCH 4/5] Cosmetic fix --- features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h index f08e62320c..6b18a334e6 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/aes_alt.h @@ -107,9 +107,9 @@ int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, * 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. + * call the 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. From 1dc3941a5f86387b2fd6814fefd5287eb2e353a9 Mon Sep 17 00:00:00 2001 From: Steven Cooreman Date: Sat, 11 Nov 2017 19:38:54 +0100 Subject: [PATCH 5/5] Apply feedback by @Patater --- .../targets/TARGET_Silicon_Labs/crypto_ecp.c | 31 ++++++++++--------- .../TARGET_Silicon_Labs/crypto_management.c | 25 ++++++++++----- .../TARGET_Silicon_Labs/crypto_management.h | 6 ++-- .../targets/TARGET_Silicon_Labs/crypto_sha.c | 26 ++++++++++------ targets/targets.json | 23 +++++++------- 5 files changed, 66 insertions(+), 45 deletions(-) diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c index 34f57fc13b..48fe271e8f 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_ecp.c @@ -69,13 +69,13 @@ #define ECC_BIGINT_SIZE_IN_BITS (256) #define ECC_BIGINT_SIZE_IN_BYTES (ECC_BIGINT_SIZE_IN_BITS/8) #define ECC_BIGINT_SIZE_IN_32BIT_WORDS (ECC_BIGINT_SIZE_IN_BYTES/sizeof(uint32_t)) -#define EC_BIGINT_COPY(X, Y) memcpy(X, Y, sizeof(ecc_bigint_t)); +#define EC_BIGINT_COPY(X, Y) memcpy((X), (Y), sizeof(ecc_bigint_t)); typedef uint32_t ecc_bigint_t[ECC_BIGINT_SIZE_IN_32BIT_WORDS]; -#define SLCL_ECP_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) +#define SLCL_ECP_CHK(f) do { if( ( ret = (f) ) != 0 ) goto cleanup; } while( 0 ) #if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) || defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) -#define MPI_TO_BIGINT(bigint, mpi) mpitobigint(bigint, mpi); +#define MPI_TO_BIGINT(bigint, mpi) mpitobigint((bigint), (mpi)); /***************************************************************************//** * @brief @@ -85,14 +85,17 @@ __STATIC_INLINE void mpitobigint( ecc_bigint_t bigint, const mbedtls_mpi* mpi ) { uint32_t* bi = bigint; - if ( mpi->n < 8 ) + if ( mpi->n < ECC_BIGINT_SIZE_IN_32BIT_WORDS ) { memcpy(bigint, mpi->p, mpi->n * sizeof(uint32_t)); - memset(&bi[mpi->n], 0, sizeof(ecc_bigint_t) - mpi->n * sizeof(uint32_t)); + memset(&bi[mpi->n], + 0, + ECC_BIGINT_SIZE_IN_BYTES - ( mpi->n * sizeof(uint32_t) ) ); } else { - memcpy(bigint, mpi->p, 8 * sizeof(uint32_t)); + /* mpi has more room than bigint, so only store up to sizeof(bigint) */ + memcpy(bigint, mpi->p, ECC_BIGINT_SIZE_IN_BYTES); } } @@ -137,11 +140,11 @@ __STATIC_INLINE bool crypto_ddata0_is_zero(CRYPTO_TypeDef* crypto, * * @return N/A ******************************************************************************/ -static void mbedtls_mpi_div_mod(CRYPTO_TypeDef *crypto, - ecc_bigint_t X, - ecc_bigint_t Y, - ecc_bigint_t N, - ecc_bigint_t R) +static void crypto_mpi_div_mod(CRYPTO_TypeDef *crypto, + ecc_bigint_t X, + ecc_bigint_t Y, + ecc_bigint_t N, + ecc_bigint_t R) { uint32_t D[9]; uint32_t status_reg; @@ -381,7 +384,7 @@ static void mbedtls_mpi_div_mod(CRYPTO_TypeDef *crypto, CORE_EXIT_CRITICAL(); } return; -} /* mbedtls_mpi_div_mod */ +} /* crypto_mpi_div_mod */ #endif /* MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT || MBEDTLS_ECP_NORMALIZE_JAC_ALT */ /***************************************************************************//** @@ -1509,7 +1512,7 @@ int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, /* * u = 1 / (Z_0 * ... * Z_n) mod P */ - mbedtls_mpi_div_mod(crypto, one, cc[t_len-1], modulus, uu); + crypto_mpi_div_mod(crypto, one, cc[t_len-1], modulus, uu); for( i = t_len - 1; ; i-- ) { @@ -1638,7 +1641,7 @@ int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, MPI_TO_BIGINT( Z, &pt->Z ); MPI_TO_BIGINT( modulus, &grp->P ); - mbedtls_mpi_div_mod(crypto, one, Z, modulus, Z_inv); + crypto_mpi_div_mod(crypto, one, Z, modulus, Z_inv); /* diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.c index e506b91420..b49fe08931 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.c +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.c @@ -22,6 +22,13 @@ #include "em_bus.h" #if defined( CRYPTO_PRESENT ) + +/* Conversion macro for compatibility with the 5.3.x release of the Gecko SDK */ +#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION ) +#warning "MBEDTLS_CRYPTO_DEVICE_PREEMPTION is deprecated, please define " \ + "CRYPTO_DEVICE_PREEMPTION instead." +#endif + #if defined( MBEDTLS_THREADING_C ) #include "mbedtls/threading.h" static mbedtls_threading_mutex_t crypto_locks[CRYPTO_COUNT]; @@ -29,7 +36,7 @@ static volatile bool crypto_locks_initialized = false; static unsigned int acquire_count = 0U; #endif /* MBEDTLS_THREADING_C */ -#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION ) +#if defined( CRYPTO_DEVICE_PREEMPTION ) /** Preemptable context of CRYPTO hardware module. */ typedef struct { @@ -52,7 +59,7 @@ typedef struct static crypto_context_t preemption_context; static bool is_preempted = false; static CORE_DECLARE_IRQ_STATE; -#endif /* MBEDTLS_CRYPTO_DEVICE_PREEMPTION */ +#endif /* CRYPTO_DEVICE_PREEMPTION */ typedef enum { @@ -106,9 +113,9 @@ static inline int crypto_management_index_by_device( CRYPTO_TypeDef *device ) } /* 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) +#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 ) @@ -130,6 +137,9 @@ CRYPTO_TypeDef *crypto_management_acquire( void ) CORE_EXIT_CRITICAL(); } +/* Wrapping this in SL_THREADING_ALT pending non-blocking mutex in official + * threading API. */ +#if defined( SL_THREADING_ALT ) /* Try to take an available crypto instance */ unsigned int devno = 0; for ( ; devno < CRYPTO_COUNT; devno++ ) { @@ -138,6 +148,7 @@ CRYPTO_TypeDef *crypto_management_acquire( void ) break; } } +#endif // SL_THREADING_ALT /* If no device immediately available, do naieve round-robin */ if ( device == NULL ) { @@ -213,7 +224,7 @@ void crypto_management_release( CRYPTO_TypeDef *device ) /* Acquire a device with preemption. NOT thread-safe! */ CRYPTO_TypeDef *crypto_management_acquire_preemption( uint32_t regmask ) { -#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION ) +#if defined( CRYPTO_DEVICE_PREEMPTION ) CRYPTO_TypeDef *device = NULL; /* Turn off interrupts */ CORE_ENTER_CRITICAL(); @@ -309,7 +320,7 @@ void crypto_management_release_preemption( CRYPTO_TypeDef *device ) if ( crypto_management_index_by_device( device ) < 0 ) { return; } -#if defined( MBEDTLS_CRYPTO_DEVICE_PREEMPTION ) +#if defined( CRYPTO_DEVICE_PREEMPTION ) if ( is_preempted ) { /* If we preempted something, put their context back */ diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.h b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.h index d44c1717c2..b1a4e9f151 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.h +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_management.h @@ -17,8 +17,8 @@ * limitations under the License. */ -#ifndef MBEDTLS_CRYPTO_MANAGEMENT_H -#define MBEDTLS_CRYPTO_MANAGEMENT_H +#ifndef CRYPTO_MANAGEMENT_H +#define CRYPTO_MANAGEMENT_H /***************************************************************************//** * \addtogroup sl_crypto @@ -125,4 +125,4 @@ void crypto_management_release_preemption( CRYPTO_TypeDef *device ); /** \} (end addtogroup sl_crypto_management) */ /** \} (end addtogroup sl_crypto) */ -#endif /* MBEDTLS_CRYPTO_MANAGEMENT_H */ \ No newline at end of file +#endif /* CRYPTO_MANAGEMENT_H */ \ No newline at end of file diff --git a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c index 429bec25b5..64d0398923 100644 --- a/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c +++ b/features/mbedtls/targets/TARGET_Silicon_Labs/crypto_sha.c @@ -51,6 +51,8 @@ #include "em_assert.h" #include +#define CRYPTO_SHA_BLOCK_SIZE (64) + #if defined(MBEDTLS_SHA1_C) static const uint32_t init_state_sha1[8] = { @@ -173,10 +175,10 @@ static void crypto_sha_update_state( uint32_t state[8], /* Load the data block(s) */ for ( size_t i = 0; i < blocks; i++ ) { - if ((uint32_t)(&data[i*64]) & 0x3) + if ((uint32_t)(&data[i*CRYPTO_SHA_BLOCK_SIZE]) & 0x3) { - uint32_t temp[16]; - memcpy(temp, &data[i*64], 64); + uint32_t temp[CRYPTO_SHA_BLOCK_SIZE/sizeof(uint32_t)]; + memcpy(temp, &data[i*CRYPTO_SHA_BLOCK_SIZE], CRYPTO_SHA_BLOCK_SIZE); CORE_ENTER_CRITICAL(); CRYPTO_QDataWrite(&crypto->QDATA1BIG, temp); CORE_EXIT_CRITICAL(); @@ -184,7 +186,8 @@ static void crypto_sha_update_state( uint32_t state[8], else { CORE_ENTER_CRITICAL(); - CRYPTO_QDataWrite(&crypto->QDATA1BIG, (uint32_t*) &data[i*64]); + CRYPTO_QDataWrite(&crypto->QDATA1BIG, + (uint32_t*) &data[i*CRYPTO_SHA_BLOCK_SIZE]); CORE_EXIT_CRITICAL(); } @@ -238,14 +241,15 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) if ( is224 != 0 ) { ctx->is224 = true; - memcpy(ctx->state, init_state_sha224, 32); + memcpy(ctx->state, init_state_sha224, sizeof(ctx->state)); } else { ctx->is224 = false; - memcpy(ctx->state, init_state_sha256, 32); + memcpy(ctx->state, init_state_sha256, sizeof(ctx->state)); } } -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) { crypto_sha_update_state( ctx->state, data, 1, CRYPTO_SHA2 ); } @@ -253,8 +257,9 @@ void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char da /* * SHA-256 process buffer */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) { size_t fill; uint32_t left; @@ -296,7 +301,8 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in /* * SHA-256 final digest */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) { uint32_t last, padn; uint32_t high, low; diff --git a/targets/targets.json b/targets/targets.json index 1e4396301d..8ff782c0f3 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -2314,13 +2314,14 @@ "EFM32": { "inherits": ["Target"], "extra_labels": ["Silicon_Labs", "EFM32"], + "macros": ["MBEDTLS_CONFIG_HW_SUPPORT"], "public": false }, "EFM32GG990F1024": { "inherits": ["EFM32"], "extra_labels_add": ["EFM32GG", "1024K", "SL_AES"], "core": "Cortex-M3", - "macros": ["EFM32GG990F1024", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFM32GG990F1024", "TRANSACTION_QUEUE_SIZE_SPI=4"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"], "release_versions": ["2", "5"], "device_name": "EFM32GG990F1024", @@ -2374,7 +2375,7 @@ "inherits": ["EFM32"], "extra_labels_add": ["EFM32LG", "256K", "SL_AES"], "core": "Cortex-M3", - "macros": ["EFM32LG990F256", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFM32LG990F256", "TRANSACTION_QUEUE_SIZE_SPI=4"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"], "release_versions": ["2", "5"], "device_name": "EFM32LG990F256", @@ -2428,7 +2429,7 @@ "inherits": ["EFM32"], "extra_labels_add": ["EFM32WG", "256K", "SL_AES"], "core": "Cortex-M4F", - "macros": ["EFM32WG990F256", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFM32WG990F256", "TRANSACTION_QUEUE_SIZE_SPI=4"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"], "release_versions": ["2", "5"], "device_name": "EFM32WG990F256", @@ -2483,7 +2484,7 @@ "extra_labels_add": ["EFM32ZG", "32K", "SL_AES"], "core": "Cortex-M0+", "default_toolchain": "uARM", - "macros": ["EFM32ZG222F32", "TRANSACTION_QUEUE_SIZE_SPI=0", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFM32ZG222F32", "TRANSACTION_QUEUE_SIZE_SPI=0"], "supported_toolchains": ["GCC_ARM", "uARM", "IAR"], "default_lib": "small", "release_versions": ["2"], @@ -2537,7 +2538,7 @@ "extra_labels_add": ["EFM32HG", "64K", "SL_AES"], "core": "Cortex-M0+", "default_toolchain": "uARM", - "macros": ["EFM32HG322F64", "TRANSACTION_QUEUE_SIZE_SPI=0", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFM32HG322F64", "TRANSACTION_QUEUE_SIZE_SPI=0"], "supported_toolchains": ["GCC_ARM", "uARM", "IAR"], "default_lib": "small", "release_versions": ["2"], @@ -2590,7 +2591,7 @@ "inherits": ["EFM32"], "extra_labels_add": ["EFM32PG", "256K", "SL_CRYPTO"], "core": "Cortex-M4F", - "macros": ["EFM32PG1B100F256GM32", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFM32PG1B100F256GM32", "TRANSACTION_QUEUE_SIZE_SPI=4"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"], "release_versions": ["2", "5"], "device_name": "EFM32PG1B100F256GM32", @@ -2643,7 +2644,7 @@ "inherits": ["EFM32"], "extra_labels_add": ["EFR32MG1", "256K", "SL_RAIL", "SL_CRYPTO"], "core": "Cortex-M4F", - "macros": ["EFR32MG1P132F256GM48", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFR32MG1P132F256GM48", "TRANSACTION_QUEUE_SIZE_SPI=4"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"], "release_versions": ["2", "5"], "device_name": "EFR32MG1P132F256GM48", @@ -2654,7 +2655,7 @@ "inherits": ["EFM32"], "extra_labels_add": ["EFR32MG1", "256K", "SL_RAIL", "SL_CRYPTO"], "core": "Cortex-M4F", - "macros": ["EFR32MG1P233F256GM48", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFR32MG1P233F256GM48", "TRANSACTION_QUEUE_SIZE_SPI=4"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"], "release_versions": ["2", "5"], "public": false, @@ -2744,7 +2745,7 @@ "inherits": ["EFM32"], "extra_labels_add": ["EFM32PG12", "1024K", "SL_CRYPTO"], "core": "Cortex-M4F", - "macros": ["EFM32PG12B500F1024GL125", "TRANSACTION_QUEUE_SIZE_SPI=4", "MBEDTLS_CONFIG_HW_SUPPORT"], + "macros_add": ["EFM32PG12B500F1024GL125", "TRANSACTION_QUEUE_SIZE_SPI=4"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"], "release_versions": ["2", "5"], "public": false, @@ -2794,9 +2795,9 @@ }, "EFR32MG12P332F1024GL125": { "inherits": ["EFM32"], - "extra_labels_add": ["EFR32MG12", "1024K", "SL_RAIL", "SL_CRYPTO", "MBEDTLS_CONFIG_HW_SUPPORT"], + "extra_labels_add": ["EFR32MG12", "1024K", "SL_RAIL", "SL_CRYPTO"], "core": "Cortex-M4F", - "macros": ["EFR32MG12P332F1024GL125", "TRANSACTION_QUEUE_SIZE_SPI=4"], + "macros_add": ["EFR32MG12P332F1024GL125", "TRANSACTION_QUEUE_SIZE_SPI=4"], "supported_toolchains": ["GCC_ARM", "ARM", "uARM", "IAR"], "release_versions": ["2", "5"], "public": false,