diff --git a/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/mbedtls_device.h b/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/mbedtls_device.h new file mode 100644 index 0000000000..9a06a1cba5 --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/TARGET_STM32F4/TARGET_NUCLEO_F439ZI/mbedtls_device.h @@ -0,0 +1,26 @@ +/* + * mbedtls_device.h + ******************************************************************************* + * Copyright (c) 2017, STMicroelectronics + * 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 + +#define MBEDTLS_AES_ALT + + +#endif /* MBEDTLS_DEVICE_H */ diff --git a/features/mbedtls/targets/TARGET_STM/aes_alt.c b/features/mbedtls/targets/TARGET_STM/aes_alt.c new file mode 100644 index 0000000000..a5a8fa4dce --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/aes_alt.c @@ -0,0 +1,295 @@ +/* + * Hardware aes collector for the STM32F4 family + ******************************************************************************* + * Copyright (c) 2017, STMicroelectronics + * 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 +#include "mbedtls/aes.h" + +#if defined(MBEDTLS_AES_ALT) + +static int aes_set_key( mbedtls_aes_context *ctx, const unsigned char *key, unsigned int keybits ) +{ + switch( keybits ) + { + case 128: + ctx->hcryp_aes.Init.KeySize = CRYP_KEYSIZE_128B; + memcpy(ctx->aes_key, key, 16); + break; + case 192: + ctx->hcryp_aes.Init.KeySize = CRYP_KEYSIZE_192B; + memcpy(ctx->aes_key, key, 24); + break; + case 256: + ctx->hcryp_aes.Init.KeySize = CRYP_KEYSIZE_256B; + memcpy(ctx->aes_key, key, 32); + break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + /* Deinitializes the CRYP peripheral */ + if (HAL_CRYP_DeInit(&ctx->hcryp_aes) == HAL_ERROR) + return (HAL_ERROR); + + ctx->hcryp_aes.Init.DataType = CRYP_DATATYPE_8B; + ctx->hcryp_aes.Instance = CRYP; + /* Enable CRYP clock */ + __HAL_RCC_CRYP_CLK_ENABLE(); + + ctx->hcryp_aes.Init.pKey = ctx->aes_key; + if (HAL_CRYP_Init(&ctx->hcryp_aes) == HAL_ERROR) + return (HAL_ERROR); + + /* allow multi-instance of CRYP use: save context for CRYP HW module CR */ + ctx->ctx_save_cr = ctx->hcryp_aes.Instance->CR; + return(0); + +} + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_zeroize( void *v, size_t n ) { + volatile unsigned char *p = (unsigned char*)v; while( n-- ) *p++ = 0; +} + + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); + +} + + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + /* Force the CRYP Periheral Clock Reset */ + __HAL_RCC_CRYP_FORCE_RESET(); + + /* Release the CRYP Periheral Clock Reset */ + __HAL_RCC_CRYP_RELEASE_RESET(); + + mbedtls_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + + +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int ret_val = 0; + ret_val = aes_set_key(ctx, key, keybits); + return(ret_val); +} + +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int ret_val = 0; + ret_val = aes_set_key(ctx, key, keybits); + return( ret_val ); +} + + +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + + /* allow multi-instance of CRYP use: restore context for CRYP hw module */ + ctx->hcryp_aes.Instance->CR = ctx->ctx_save_cr; + + if(mode == MBEDTLS_AES_DECRYPT) /* AES decryption */ + { + ctx->hcryp_aes.Init.DataType = CRYP_DATATYPE_8B; + ctx->hcryp_aes.Init.pKey = ctx->aes_key; + mbedtls_aes_decrypt( ctx, input, output ); + } + else /* AES encryption */ + { + ctx->hcryp_aes.Init.DataType = CRYP_DATATYPE_8B; + ctx->hcryp_aes.Init.pKey = ctx->aes_key; + mbedtls_aes_encrypt( ctx, input, output ); + } + /* allow multi-instance of CRYP use: save context for CRYP HW module CR */ + ctx->ctx_save_cr = ctx->hcryp_aes.Instance->CR; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int status=0; + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ctx->hcryp_aes.Init.pInitVect = &iv[0]; // used in process, not in the init + + status = HAL_CRYP_AESCBC_Decrypt(&ctx->hcryp_aes, (uint8_t *)input, length, (uint8_t *)output, 10); + } + else + { + ctx->hcryp_aes.Init.pInitVect = &iv[0]; // used in process, not in the init + + status = HAL_CRYP_AESCBC_Encrypt(&ctx->hcryp_aes, (uint8_t *)input, length, (uint8_t *)output, 10); + } + return( status ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +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 ) +{ + int c; + size_t n = *iv_off; + + 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; + } + } + + *iv_off = n; + + return( 0 ); +} + + +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) +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + 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; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + + if (HAL_CRYP_AESECB_Encrypt(&ctx->hcryp_aes, (uint8_t *)input, 16, (uint8_t *)output, 10) !=0) { + // error found to be returned + } + +} + +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + + if(HAL_CRYP_AESECB_Decrypt(&ctx->hcryp_aes, (uint8_t *)input, 16, (uint8_t *)output, 10)) { + // error found to be returned + } +} + + +#endif /*MBEDTLS_AES_ALT*/ diff --git a/features/mbedtls/targets/TARGET_STM/aes_alt.h b/features/mbedtls/targets/TARGET_STM/aes_alt.h new file mode 100644 index 0000000000..dbe4fdeec3 --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/aes_alt.h @@ -0,0 +1,264 @@ +/* + * aes_alt.h AES block cipher + ******************************************************************************* + * Copyright (c) 2016, STMicroelectronics + * 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 + + +#if defined(MBEDTLS_AES_ALT) +#include "mbedtls/platform.h" +#include "mbedtls/config.h" + +#include "cmsis.h" + +#ifdef __cplusplus +extern "C" { +#endif +/** + * \brief AES context structure + * + * \note buf is able to hold 32 extra bytes, which can be used: + * - for alignment purposes if VIA padlock is used, and/or + * - to simplify key expansion in the 256-bit case by + * generating an extra round key + */ +typedef struct +{ + unsigned char aes_key[32]; /* Decryption key */ + CRYP_HandleTypeDef hcryp_aes; + uint32_t ctx_save_cr; /* save context for multi-instance */ +} +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, 192 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, 192 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 */ + +#endif /* MBEDTLS_AES_ALT_H */ + diff --git a/targets/targets.json b/targets/targets.json index ee38b950b9..7fdba09e19 100644 --- a/targets/targets.json +++ b/targets/targets.json @@ -903,7 +903,7 @@ "extra_labels": ["STM", "STM32F4", "STM32F439", "STM32F439ZI", "STM32F439xx", "STM32F439xI", "FLASH_CMSIS_ALGO"], "supported_toolchains": ["ARM", "uARM", "GCC_ARM", "IAR"], "progen": {"target": "nucleo-f439zi"}, - "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2"], + "macros": ["TRANSACTION_QUEUE_SIZE_SPI=2", "MBEDTLS_CONFIG_HW_SUPPORT"], "device_has": ["ANALOGIN", "ANALOGOUT", "CAN", "ERROR_RED", "I2C", "I2CSLAVE", "I2C_ASYNCH", "INTERRUPTIN", "LOWPOWERTIMER", "PORTIN", "PORTINOUT", "PORTOUT", "PWMOUT", "RTC", "SERIAL", "SERIAL_FC", "SLEEP", "SPI", "SPISLAVE", "SPI_ASYNCH", "STDIO_MESSAGES", "TRNG", "FLASH"], "detect_code": ["0797"], "features": ["LWIP"],