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..484964a184 --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/aes_alt.c @@ -0,0 +1,914 @@ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved + * 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 implements ST AES HW services based on API from mbed TLS + * + * 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 + */ + + +/* Includes ------------------------------------------------------------------*/ + +#if !(TARGET_STM32L4) + +#include "mbedtls/aes.h" + +#if defined(MBEDTLS_AES_C) +#if defined(MBEDTLS_AES_ALT) + +#include + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#define MBEDTLS_DEBUG 0 + +/* Parameter validation macros based on platform_util.h */ +#define AES_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_AES_BAD_INPUT_DATA ) +#define AES_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +static int aes_set_key(mbedtls_aes_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + unsigned int i; + int ret = 0; + +#if (MBEDTLS_DEBUG) + printf("[ALT] aes_set_key\n"); +#endif + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + /* include the appropriate instance name */ +#if defined (AES) + ctx->hcryp_aes.Instance = AES; +#elif defined (AES1) + ctx->hcryp_aes.Instance = AES1; +#else /* CRYP */ + ctx->hcryp_aes.Instance = CRYP; +#endif /* AES */ + + switch (keybits) { + case 128: + ctx->hcryp_aes.Init.KeySize = CRYP_KEYSIZE_128B; + break; + + case 192: +#if ( USE_AES_KEY192 == 1 ) + ctx->hcryp_aes.Init.KeySize = CRYP_KEYSIZE_192B; + break; +#else + ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + goto exit; +#endif /* USE_AES_KEY192 */ + + case 256: + ctx->hcryp_aes.Init.KeySize = CRYP_KEYSIZE_256B; + break; + + default : + ret = MBEDTLS_ERR_AES_INVALID_KEY_LENGTH; + goto exit; + } + + /* Format and fill AES key */ + for (i = 0; i < (keybits / 32); i++) { + GET_UINT32_BE(ctx->aes_key[i], key, 4 * i); + } + + ctx->hcryp_aes.Init.DataType = CRYP_DATATYPE_8B; + ctx->hcryp_aes.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE; + ctx->hcryp_aes.Init.pKey = ctx->aes_key; + + if (HAL_CRYP_Init(&ctx->hcryp_aes) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_aes.Instance->CR; + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); +} + +void mbedtls_aes_init(mbedtls_aes_context *ctx) +{ + AES_VALIDATE(ctx != NULL); + + __disable_irq(); +#if defined(MBEDTLS_THREADING_C) + /* mutex cannot be initialized twice */ + if (!cryp_mutex_started) { + mbedtls_mutex_init(&cryp_mutex); + cryp_mutex_started = 1; + } +#endif /* MBEDTLS_THREADING_C */ + cryp_context_count++; + __enable_irq(); + + cryp_zeroize((void *)ctx, sizeof(mbedtls_aes_context)); + +#if (MBEDTLS_DEBUG) + printf("[ALT] mbedtls_aes_init %u\n", cryp_context_count); +#endif +} + + +void mbedtls_aes_free(mbedtls_aes_context *ctx) +{ +#if (MBEDTLS_DEBUG) + printf("[ALT] mbedtls_aes_free %u\n", cryp_context_count); +#endif + + if (ctx == NULL) { + return; + } + + __disable_irq(); + if (cryp_context_count > 0) { + cryp_context_count--; + } + +#if defined(MBEDTLS_THREADING_C) + if (cryp_mutex_started) { + mbedtls_mutex_free(&cryp_mutex); + cryp_mutex_started = 0; + } +#endif /* MBEDTLS_THREADING_C */ + __enable_irq(); + + /* Shut down CRYP on last context */ + if (cryp_context_count == 0) { + HAL_CRYP_DeInit(&ctx->hcryp_aes); + } + + cryp_zeroize((void *)ctx, sizeof(mbedtls_aes_context)); +} + +/* XTS SW implementation inherited code from aes.c */ +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init(mbedtls_aes_xts_context *ctx) +{ + AES_VALIDATE(ctx != NULL); + + mbedtls_aes_init(&ctx->crypt); + mbedtls_aes_init(&ctx->tweak); +} + +void mbedtls_aes_xts_free(mbedtls_aes_xts_context *ctx) +{ + if (ctx == NULL) { + return; + } + + mbedtls_aes_free(&ctx->crypt); + mbedtls_aes_free(&ctx->tweak); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * AES key schedule (encryption) + */ +int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits) +{ +#if (MBEDTLS_DEBUG) + printf("[ALT] mbedtls_aes_setkey_enc\n"); +#endif + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + return (aes_set_key(ctx, key, keybits)); +} + +/* + * AES key schedule (decryption) + */ +int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits) +{ +#if (MBEDTLS_DEBUG) + printf("[ALT] mbedtls_aes_setkey_dec\n"); +#endif + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + return (aes_set_key(ctx, key, keybits)); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys(const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch (keybits) { + case 256: + break; + case 512: + break; + default : + return (MBEDTLS_ERR_AES_INVALID_KEY_LENGTH); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return (0); +} + +int mbedtls_aes_xts_setkey_enc(mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, + &key2, &key2bits); + if (ret != 0) { + return (ret); + } + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits); + if (ret != 0) { + return (ret); + } + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc(&ctx->crypt, key1, key1bits); +} + +int mbedtls_aes_xts_setkey_dec(mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(key != NULL); + + ret = mbedtls_aes_xts_decode_keys(key, keybits, &key1, &key1bits, + &key2, &key2bits); + if (ret != 0) { + return (ret); + } + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc(&ctx->tweak, key2, key2bits); + if (ret != 0) { + return (ret); + } + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec(&ctx->crypt, key1, key1bits); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * 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; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + /* allow multi-context of CRYP use: restore context */ + ctx->hcryp_aes.Instance->CR = ctx->ctx_save_cr; + + ctx->hcryp_aes.Init.DataType = CRYP_DATATYPE_8B; + ctx->hcryp_aes.Init.pKey = ctx->aes_key; + + /* Set the Algo if not configured till now */ + if (CRYP_AES_ECB != ctx->hcryp_aes.Init.Algorithm) { + ctx->hcryp_aes.Init.Algorithm = CRYP_AES_ECB; + + /* Configure the CRYP */ + if (HAL_CRYP_SetConfig(&ctx->hcryp_aes, + &ctx->hcryp_aes.Init) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + } + + if (mode == MBEDTLS_AES_DECRYPT) { + /* AES decryption */ + ret = mbedtls_internal_aes_decrypt(ctx, input, output); + if (ret != 0) { + goto exit; + } + } else { + /* AES encryption */ + ret = mbedtls_internal_aes_encrypt(ctx, input, output); + if (ret != 0) { + goto exit; + } + } + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_aes.Instance->CR; + +exit: + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + 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) +{ + unsigned int i; + __ALIGN_BEGIN static uint32_t iv_32B[4]; + __ALIGN_END + int ret = 0; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + if (length % 16) { + return (MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH); + } + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + /* allow multi-context of CRYP use: restore context */ + ctx->hcryp_aes.Instance->CR = ctx->ctx_save_cr; + + /* Set the Algo if not configured till now */ + if (CRYP_AES_CBC != ctx->hcryp_aes.Init.Algorithm) { + ctx->hcryp_aes.Init.Algorithm = CRYP_AES_CBC; + } + + /* Set IV with invert endianness */ + for (i = 0; i < 4; i++) { + GET_UINT32_BE(iv_32B[i], iv, 4 * i); + } + + ctx->hcryp_aes.Init.pInitVect = iv_32B; + + /* reconfigure the CRYP */ + if (HAL_CRYP_SetConfig(&ctx->hcryp_aes, + &ctx->hcryp_aes.Init) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + if (mode == MBEDTLS_AES_DECRYPT) { + /* current input is the IV vector for the next decrypt */ + memcpy(iv, input, 16); + + if (HAL_CRYP_Decrypt(&ctx->hcryp_aes, + (uint32_t *)input, + length, + (uint32_t *)output, + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + } else { + if (HAL_CRYP_Encrypt(&ctx->hcryp_aes, + (uint32_t *)input, + length, + (uint32_t *)output, + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + /* current output is the IV vector for the next encrypt */ + memcpy(iv, output, 16); + } + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_aes.Instance->CR; + +exit: + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble(unsigned char r[16], + const unsigned char x[16]) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE(a, x, 0); + GET_UINT64_LE(b, x, 8); + + ra = (a << 1) ^ 0x0087 >> (8 - ((b >> 63) << 3)); + rb = (a >> 63) | (b << 1); + + PUT_UINT64_LE(ra, r, 0); + PUT_UINT64_LE(rb, r, 8); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts(mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + AES_VALIDATE_RET(data_unit != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + /* Data units must be at least 16 bytes long. */ + if (length < 16) { + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + /* NIST SP 800-38E disallows data units larger than 2**20 blocks. */ + if (length > (1 << 20) * 16) { + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + } + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb(&ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak); + if (ret != 0) { + return (ret); + } + + while (blocks--) { + size_t i; + + if (leftover && (mode == MBEDTLS_AES_DECRYPT) && blocks == 0) { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy(prev_tweak, tweak, sizeof(tweak)); + mbedtls_gf128mul_x_ble(tweak, tweak); + } + + for (i = 0; i < 16; i++) { + tmp[i] = input[i] ^ tweak[i]; + } + + ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); + if (ret != 0) { + return (ret); + } + + for (i = 0; i < 16; i++) { + output[i] = tmp[i] ^ tweak[i]; + } + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble(tweak, tweak); + + output += 16; + input += 16; + } + + if (leftover) { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for (i = 0; i < leftover; i++) { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for (; i < 16; i++) { + tmp[i] = prev_output[i] ^ t[i]; + } + + ret = mbedtls_aes_crypt_ecb(&ctx->crypt, mode, tmp, tmp); + if (ret != 0) { + return ret; + } + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for (i = 0; i < 16; i++) { + prev_output[i] = tmp[i] ^ t[i]; + } + } + + return (0); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#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) +{ + int ret; + int c; + size_t n; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + AES_VALIDATE_RET(iv_off != NULL); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + n = *iv_off; + + if (mode == MBEDTLS_AES_DECRYPT) { + while (length--) { + if (n == 0) { + ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); + if (ret != 0) { + return (ret); + } + } + + c = *input++; + *output++ = (unsigned char)(c ^ iv[n]); + iv[n] = (unsigned char) c; + + n = (n + 1) & 0x0F; + } + } else { + while (length--) { + if (n == 0) { + ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); + if (ret != 0) { + return (ret); + } + } + + iv[n] = *output++ = (unsigned char)(iv[n] ^ *input++); + + n = (n + 1) & 0x0F; + } + } + + *iv_off = n; + + 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) +{ + int ret; + unsigned char c; + unsigned char ov[17]; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(mode == MBEDTLS_AES_ENCRYPT || + mode == MBEDTLS_AES_DECRYPT); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + while (length--) { + memcpy(ov, iv, 16); + ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); + if (ret != 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 (0); +} + +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb(mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output) +{ + int ret = 0; + size_t n; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(iv_off != NULL); + AES_VALIDATE_RET(iv != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + n = *iv_off; + + if (n > 15) { + return (MBEDTLS_ERR_AES_BAD_INPUT_DATA); + } + + while (length--) { + if (n == 0) { + ret = mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, iv, iv); + if (ret != 0) { + goto exit; + } + } + *output++ = *input++ ^ iv[n]; + + n = (n + 1) & 0x0F; + } + + *iv_off = n; + +exit: + return (ret); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#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) +{ + int c, i; + size_t n; + + AES_VALIDATE_RET(ctx != NULL); + AES_VALIDATE_RET(nc_off != NULL); + AES_VALIDATE_RET(nonce_counter != NULL); + AES_VALIDATE_RET(stream_block != NULL); + AES_VALIDATE_RET(input != NULL); + AES_VALIDATE_RET(output != NULL); + + n = *nc_off; + + if (n > 0x0F) { + return (MBEDTLS_ERR_AES_BAD_INPUT_DATA); + } + + while (length--) { + if (n == 0) { + if (mbedtls_aes_crypt_ecb(ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block) != 0) { + return (MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED); + } + + 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 */ + +int mbedtls_internal_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + + if (HAL_CRYP_Encrypt(&ctx->hcryp_aes, + (uint32_t *)input, + 16, + (uint32_t *)output, + ST_CRYP_TIMEOUT) != HAL_OK) { + return (MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED); + } + return (0); + +} + +int mbedtls_internal_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ + if (HAL_CRYP_Decrypt(&ctx->hcryp_aes, + (uint32_t *)input, + 16, + (uint32_t *)output, + ST_CRYP_TIMEOUT) != HAL_OK) { + return (MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED); + } + return (0); +} + +#if defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ +#error "mbedtls_aes_encrypt() is a deprecated function (not implemented)" +} + +void mbedtls_aes_decrypt(mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16]) +{ +#error "mbedtls_aes_decrypt() is a deprecated function (not implemented)" +} +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /*MBEDTLS_AES_ALT*/ +#endif /* MBEDTLS_AES_C */ +#endif /* !(TARGET_STM32L4) */ 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..6949c09b3e --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/aes_alt.h @@ -0,0 +1,96 @@ +/** + * \file aes_alt.h + * + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * Copyright (C) 2019-2020 STMicroelectronics, All Rights Reserved + * 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 implements ST AES HW services based on API from mbed TLS + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef MBEDTLS_AES_ALT_H +#define MBEDTLS_AES_ALT_H + +#if (TARGET_STM32L4) +#include "aes_alt_stm32l4.h" +#else +#if defined(MBEDTLS_AES_ALT) +/* Includes ------------------------------------------------------------------*/ +#include "cryp_stm32.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/** + * \brief AES context structure + */ +typedef struct { + /* Encryption/Decryption key */ + uint32_t aes_key[8]; + + CRYP_HandleTypeDef hcryp_aes; /* AES context */ + uint32_t ctx_save_cr; /* save context for multi-context */ +} +mbedtls_aes_context; + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context { + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_AES_ALT */ + +#endif /* MBEDTLS_AES_ALT_H */ + +#endif /* ! TARGET_STM32L4 */ diff --git a/features/mbedtls/targets/TARGET_STM/ccm_alt.c b/features/mbedtls/targets/TARGET_STM/ccm_alt.c new file mode 100644 index 0000000000..e82fba6fe3 --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/ccm_alt.c @@ -0,0 +1,511 @@ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2019-2020 STMicroelectronics, All Rights Reserved + * 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 implements ST CCM HW services based on API from mbed TLS + */ + +/* + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + */ + +/* Includes ------------------------------------------------------------------*/ +#include "mbedtls/ccm.h" + +#if defined(MBEDTLS_CCM_C) +#if defined(MBEDTLS_CCM_ALT) + +#include + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#define MBEDTLS_DEBUG 0 + +/* Parameter validation macros */ +#define CCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_CCM_BAD_INPUT ) +#define CCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define CCM_ENCRYPT 0 +#define CCM_DECRYPT 1 + +#define H_LENGTH 2 /* Formatting of the Associated Data */ +/* If 0 < a < 2e16-2e8, */ +/* then a is encoded as [a]16, i.e., two octets */ + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ +/* + * Initialize context + */ +void mbedtls_ccm_init(mbedtls_ccm_context *ctx) +{ + CCM_VALIDATE(ctx != NULL); + + __disable_irq(); +#if defined(MBEDTLS_THREADING_C) + /* mutex cannot be initialized twice */ + if (!cryp_mutex_started) { + mbedtls_mutex_init(&cryp_mutex); + cryp_mutex_started = 1; + } +#endif /* MBEDTLS_THREADING_C */ + cryp_context_count++; + __enable_irq(); + + cryp_zeroize((void *)ctx, sizeof(mbedtls_ccm_context)); + +#if (MBEDTLS_DEBUG) + printf("[ALT] mbedtls_ccm_init %u\n", cryp_context_count); +#endif +} + +int mbedtls_ccm_setkey(mbedtls_ccm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits) +{ + unsigned int i; + int ret = 0; + +#if (MBEDTLS_DEBUG) + printf("[ALT] mbedtls_ccm_setkey\n"); +#endif + + CCM_VALIDATE_RET(ctx != NULL); + CCM_VALIDATE_RET(key != NULL); + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + switch (keybits) { + case 128: + ctx->hcryp_ccm.Init.KeySize = CRYP_KEYSIZE_128B;; + break; + + case 192: +#if ( USE_AES_KEY192 == 1 ) + ctx->hcryp_ccm.Init.KeySize = CRYP_KEYSIZE_192B; + break; +#else + ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + goto exit; +#endif /* USE_AES_KEY192 */ + + case 256: + ctx->hcryp_ccm.Init.KeySize = CRYP_KEYSIZE_256B; + break; + + default : + ret = MBEDTLS_ERR_CCM_BAD_INPUT; + goto exit; + } + + /* Format and fill AES key */ + for (i = 0; i < (keybits / 32) ; i++) { + GET_UINT32_BE(ctx->ccm_key[i], key, 4 * i); + } + + /* include the appropriate instance name */ +#if defined (AES) + ctx->hcryp_ccm.Instance = AES; +#elif defined (AES1) + ctx->hcryp_ccm.Instance = AES1; +#else /* CRYP */ + ctx->hcryp_ccm.Instance = CRYP; +#endif /* AES */ + + ctx->hcryp_ccm.Init.DataType = CRYP_DATATYPE_8B; + ctx->hcryp_ccm.Init.pKey = ctx->ccm_key; + ctx->hcryp_ccm.Init.pInitVect = NULL; + ctx->hcryp_ccm.Init.Algorithm = CRYP_AES_CCM; + ctx->hcryp_ccm.Init.Header = NULL; + ctx->hcryp_ccm.Init.HeaderSize = 0; + ctx->hcryp_ccm.Init.B0 = NULL; + ctx->hcryp_ccm.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE; + + if (HAL_CRYP_Init(&ctx->hcryp_ccm) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_ccm.Instance->CR; + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); +} + +/* + * Free context + */ +void mbedtls_ccm_free(mbedtls_ccm_context *ctx) +{ +#if (MBEDTLS_DEBUG) + printf("[ALT] mbedtls_ccm_free %u\n", cryp_context_count); +#endif + + if (ctx == NULL) { + return; + } + + __disable_irq(); + if (cryp_context_count > 0) { + cryp_context_count--; + } + +#if defined(MBEDTLS_THREADING_C) + if (cryp_mutex_started) { + mbedtls_mutex_free(&cryp_mutex); + cryp_mutex_started = 0; + } +#endif /* MBEDTLS_THREADING_C */ + __enable_irq(); + + /* Shut down CRYP on last context */ + if (cryp_context_count == 0) { + HAL_CRYP_DeInit(&ctx->hcryp_ccm); + } + + cryp_zeroize((void *)ctx, sizeof(mbedtls_ccm_context)); +} + +/* + * Authenticated encryption or decryption + */ +static int ccm_auth_crypt(mbedtls_ccm_context *ctx, int mode, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len) +{ + int ret = 0; + unsigned char i; + unsigned char q; + size_t len_left; + unsigned int j; + + __ALIGN_BEGIN unsigned char b0[16] __ALIGN_END; /* Formatting of B0 */ + __ALIGN_BEGIN uint32_t b0_32B[4] __ALIGN_END; /* B0 data swapping */ + unsigned char *b1_padded_addr = NULL; /* Formatting of B1 */ + unsigned char *b1_aligned_addr = NULL; + size_t b1_length; /* B1 with padding */ + uint8_t b1_padding; /* B1 word alignement */ + + __ALIGN_BEGIN uint8_t mac[16] __ALIGN_END; /* temporary mac */ + + + CCM_VALIDATE_RET(mode != CCM_ENCRYPT || mode != CCM_DECRYPT); + + /* + * Check length requirements: SP800-38C A.1 + * Additional requirement: a < 2^16 - 2^8 to simplify the code. + * 'length' checked later (when writing it to the first block) + * + * Also, loosen the requirements to enable support for CCM* (IEEE 802.15.4). + */ + + /* tag_len, aka t, is an element of {4, 6, 8, 10, 12, 14, 16} */ + if (tag_len < 4 || tag_len > 16 || tag_len % 2 != 0) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + /* Also implies q is within bounds */ + /* iv_len, aka n, is an element of {7, 8, 9, 10, 11, 12, 13} */ + if (iv_len < 7 || iv_len > 13) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + /* add_len, aka a, a < 2^16 - 2^8 */ + if (add_len > 0xFF00) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + /* The octet length of Q, denoted q */ + q = 15 - (unsigned char) iv_len; + + /* + * First block B_0: + * 0 .. 0 flags + * 1 .. iv_len nonce (aka iv) + * iv_len+1 .. 15 length + * + * With flags as (bits): + * 7 0 + * 6 add present? + * 5 .. 3 (t - 2) / 2 + * 2 .. 0 q - 1 + */ + memset(b0, 0, 16); + if (add_len > 0) { + b0[0] |= 0x40; + } + b0[0] |= ((tag_len - 2) / 2) << 3; + b0[0] |= q - 1; + + /* Nonce concatenation */ + memcpy(b0 + 1, iv, iv_len); + + /* Data length concatenation */ + for (i = 0, len_left = length; i < q; i++, len_left >>= 8) { + b0[15 - i] = (unsigned char)(len_left & 0xFF); + } + + if (len_left > 0) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + /* allow multi-context of CRYP use: restore context */ + ctx->hcryp_ccm.Instance->CR = ctx->ctx_save_cr; + /* + * If there is additional data, update with + * add_len, add, 0 (padding to a block boundary) + */ + if (add_len > 0) { + /* Extra bytes to deal with data padding such that */ + /* the resulting string can be partitioned into words */ + b1_padding = ((add_len + H_LENGTH) % 4); + b1_length = add_len + H_LENGTH + b1_padding; + + /* reserve extra bytes to deal with 4-bytes memory alignement */ + b1_padded_addr = + mbedtls_calloc(1, b1_length + 3); + + if (b1_padded_addr == NULL) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + /* move up to a 4-bytes aligned address in the reserved memory chuck */ + b1_aligned_addr = + (unsigned char *)((uint32_t)(b1_padded_addr + 3) & 0xFFFFFFFC); + + /* Header length */ + b1_aligned_addr[0] = (unsigned char)((add_len >> 8) & 0xFF); + b1_aligned_addr[1] = (unsigned char)((add_len) & 0xFF); + + /* data concatenation */ + memcpy(b1_aligned_addr + H_LENGTH, add, add_len); + + /* blocks (B) associated to the Associated Data (A) */ + ctx->hcryp_ccm.Init.Header = (uint32_t *)b1_aligned_addr; + + ctx->hcryp_ccm.Init.HeaderSize = b1_length / 4; + } else { + ctx->hcryp_ccm.Init.Header = NULL; + ctx->hcryp_ccm.Init.HeaderSize = 0; + } + + /* first authentication block */ + for (j = 0; j < 4; j++) { + GET_UINT32_BE(b0_32B[j], b0, 4 * j); + } + + ctx->hcryp_ccm.Init.B0 = b0_32B; + + /* reconfigure the CRYP */ + if (HAL_CRYP_SetConfig(&ctx->hcryp_ccm, &ctx->hcryp_ccm.Init) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto free_block; + } + + /* blocks (B) associated to the plaintext message (P) */ + if (mode == CCM_DECRYPT) { + if (HAL_CRYP_Decrypt(&ctx->hcryp_ccm, + (uint32_t *)input, + length, + (uint32_t *)output, + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto free_block; + } + } else { + if (HAL_CRYP_Encrypt(&ctx->hcryp_ccm, + (uint32_t *)input, + length, + (uint32_t *)output, + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto free_block; + } + } + + /* Tag has a variable length */ + memset(mac, 0, sizeof(mac)); + + /* Generate the authentication TAG */ + if (HAL_CRYPEx_AESCCM_GenerateAuthTAG(&ctx->hcryp_ccm, + (uint32_t *)mac, + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto free_block; + } + + memcpy(tag, mac, tag_len); + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_ccm.Instance->CR; + +free_block: + if (add_len > 0) { + mbedtls_free(b1_padded_addr); + } + +exit: + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); +} + +/* + * Authenticated encryption + */ +int mbedtls_ccm_star_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len) +{ + CCM_VALIDATE_RET(ctx != NULL); + CCM_VALIDATE_RET(iv != NULL); + CCM_VALIDATE_RET(add_len == 0 || add != NULL); + CCM_VALIDATE_RET(length == 0 || input != NULL); + CCM_VALIDATE_RET(length == 0 || output != NULL); + CCM_VALIDATE_RET(tag_len == 0 || tag != NULL); + return (ccm_auth_crypt(ctx, CCM_ENCRYPT, length, iv, iv_len, + add, add_len, input, output, tag, tag_len)); +} + +int mbedtls_ccm_encrypt_and_tag(mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + unsigned char *tag, size_t tag_len) +{ + CCM_VALIDATE_RET(ctx != NULL); + CCM_VALIDATE_RET(iv != NULL); + CCM_VALIDATE_RET(add_len == 0 || add != NULL); + CCM_VALIDATE_RET(length == 0 || input != NULL); + CCM_VALIDATE_RET(length == 0 || output != NULL); + CCM_VALIDATE_RET(tag_len == 0 || tag != NULL); + if (tag_len == 0) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + return (mbedtls_ccm_star_encrypt_and_tag(ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len)); +} + +/* + * Authenticated decryption + */ +int mbedtls_ccm_star_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len) +{ + int ret; + unsigned char check_tag[16]; + unsigned char i; + int diff; + + CCM_VALIDATE_RET(ctx != NULL); + CCM_VALIDATE_RET(iv != NULL); + CCM_VALIDATE_RET(add_len == 0 || add != NULL); + CCM_VALIDATE_RET(length == 0 || input != NULL); + CCM_VALIDATE_RET(length == 0 || output != NULL); + CCM_VALIDATE_RET(tag_len == 0 || tag != NULL); + + if ((ret = ccm_auth_crypt(ctx, CCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, check_tag, tag_len)) != 0) { + return (ret); + } + + /* Check tag in "constant-time" */ + for (diff = 0, i = 0; i < tag_len; i++) { + diff |= tag[i] ^ check_tag[i]; + } + + if (diff != 0) { + mbedtls_platform_zeroize(output, length); + return (MBEDTLS_ERR_CCM_AUTH_FAILED); + } + + return (0); +} + +int mbedtls_ccm_auth_decrypt(mbedtls_ccm_context *ctx, size_t length, + const unsigned char *iv, size_t iv_len, + const unsigned char *add, size_t add_len, + const unsigned char *input, unsigned char *output, + const unsigned char *tag, size_t tag_len) +{ + CCM_VALIDATE_RET(ctx != NULL); + CCM_VALIDATE_RET(iv != NULL); + CCM_VALIDATE_RET(add_len == 0 || add != NULL); + CCM_VALIDATE_RET(length == 0 || input != NULL); + CCM_VALIDATE_RET(length == 0 || output != NULL); + CCM_VALIDATE_RET(tag_len == 0 || tag != NULL); + + if (tag_len == 0) { + return (MBEDTLS_ERR_CCM_BAD_INPUT); + } + + return (mbedtls_ccm_star_auth_decrypt(ctx, length, iv, iv_len, add, + add_len, input, output, tag, tag_len)); +} + +#endif /*MBEDTLS_CCM_ALT*/ +#endif /*MBEDTLS_CCM_C*/ diff --git a/features/mbedtls/targets/TARGET_STM/ccm_alt.h b/features/mbedtls/targets/TARGET_STM/ccm_alt.h new file mode 100644 index 0000000000..f9a21f465b --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/ccm_alt.h @@ -0,0 +1,86 @@ +/** + * \file ccm.h + * + * \brief This file provides an API for the CCM authenticated encryption + * mode for block ciphers. + * + * CCM combines Counter mode encryption with CBC-MAC authentication + * for 128-bit block ciphers. + * + * Input to CCM includes the following elements: + *
  • Payload - data that is both authenticated and encrypted.
  • + *
  • Associated data (Adata) - data that is authenticated but not + * encrypted, For example, a header.
  • + *
  • Nonce - A unique value that is assigned to the payload and the + * associated data.
+ * + * Definition of CCM: + * http://csrc.nist.gov/publications/nistpubs/800-38C/SP800-38C_updated-July20_2007.pdf + * RFC 3610 "Counter with CBC-MAC (CCM)" + * + * Related: + * RFC 5116 "An Interface and Algorithms for Authenticated Encryption" + * + * Definition of CCM*: + * IEEE 802.15.4 - IEEE Standard for Local and metropolitan area networks + * Integer representation is fixed most-significant-octet-first order and + * the representation of octets is most-significant-bit-first order. This is + * consistent with RFC 3610. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright (C) 2019-2020 STMicroelectronics, All Rights Reserved + * 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 implements ST CCM HW services based on API from mbed TLS + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef MBEDTLS_CCM_ALT_H +#define MBEDTLS_CCM_ALT_H + +#if defined(MBEDTLS_CCM_ALT) +/* Includes ------------------------------------------------------------------*/ +#include "cryp_stm32.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/** + * \brief The CCM context-type definition. The CCM context is passed + * to the APIs called. + */ +typedef struct mbedtls_ccm_context { + /* Encryption/Decryption key */ + uint32_t ccm_key[8]; + + CRYP_HandleTypeDef hcryp_ccm; /* CCM context */ + uint32_t ctx_save_cr; /* save context for multi-context */ +} +mbedtls_ccm_context; + +/* Exported constants --------------------------------------------------------*/ +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CCM_ALT */ +#endif /* MBEDTLS_CCM_ALT_H */ diff --git a/features/mbedtls/targets/TARGET_STM/gcm_alt.c b/features/mbedtls/targets/TARGET_STM/gcm_alt.c new file mode 100644 index 0000000000..dce9e83ed0 --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/gcm_alt.c @@ -0,0 +1,527 @@ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2019-2020 STMicroelectronics, All Rights Reserved + * 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 implements ST GCM HW services based on API from mbed TLS + */ + +/* Includes ------------------------------------------------------------------*/ +#include "mbedtls/gcm.h" + +#if defined(MBEDTLS_GCM_C) +#if defined(MBEDTLS_GCM_ALT) + +#include + +#include "mbedtls/platform_util.h" +#include "mbedtls/platform.h" + + +/* Parameter validation macros */ +#define GCM_VALIDATE_RET( cond ) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_GCM_BAD_INPUT ) +#define GCM_VALIDATE( cond ) \ + MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +#define IV_LENGTH 12U /* implementations restrict support to 96 bits */ + +#if !defined(STM32_AAD_ANY_LENGTH_SUPPORT) +#define AAD_WORD_ALIGN 4U /* implementations restrict AAD support on a */ +/* buffer multiple of 32 bits */ +#endif + +/* Private macro -------------------------------------------------------------*/ +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ + +/* + * Initialize a context + */ +void mbedtls_gcm_init(mbedtls_gcm_context *ctx) +{ + GCM_VALIDATE(ctx != NULL); + + __disable_irq(); +#if defined(MBEDTLS_THREADING_C) + /* mutex cannot be initialized twice */ + if (!cryp_mutex_started) { + mbedtls_mutex_init(&cryp_mutex); + cryp_mutex_started = 1; + } +#endif /* MBEDTLS_THREADING_C */ + cryp_context_count++; + __enable_irq(); + + cryp_zeroize((void *)ctx, sizeof(mbedtls_gcm_context)); +} + +int mbedtls_gcm_setkey(mbedtls_gcm_context *ctx, + mbedtls_cipher_id_t cipher, + const unsigned char *key, + unsigned int keybits) +{ + unsigned int i; + int ret = 0; + + GCM_VALIDATE_RET(ctx != NULL); + GCM_VALIDATE_RET(key != NULL); + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + switch (keybits) { + case 128: + ctx->hcryp_gcm.Init.KeySize = CRYP_KEYSIZE_128B; + break; + + case 192: +#if ( USE_AES_KEY192 == 1 ) + ctx->hcryp_gcm.Init.KeySize = CRYP_KEYSIZE_192B; + break; +#else + ret = MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED; + goto exit; +#endif /* USE_AES_KEY192 */ + + case 256: + ctx->hcryp_gcm.Init.KeySize = CRYP_KEYSIZE_256B; + break; + + default : + ret = MBEDTLS_ERR_GCM_BAD_INPUT; + goto exit; + } + + /* Format and fill AES key */ + for (i = 0; i < (keybits / 32); i++) { + GET_UINT32_BE(ctx->gcm_key[i], key, 4 * i); + } + + /* include the appropriate instance name */ +#if defined (AES) + ctx->hcryp_gcm.Instance = AES; + ctx->hcryp_gcm.Init.Algorithm = CRYP_AES_GCM_GMAC; +#elif defined (AES1) + ctx->hcryp_gcm.Instance = AES1; + ctx->hcryp_gcm.Init.Algorithm = CRYP_AES_GCM_GMAC; +#else /* CRYP */ + ctx->hcryp_gcm.Instance = CRYP; + ctx->hcryp_gcm.Init.Algorithm = CRYP_AES_GCM; +#endif /* AES */ + + ctx->hcryp_gcm.Init.DataType = CRYP_DATATYPE_8B; + ctx->hcryp_gcm.Init.DataWidthUnit = CRYP_DATAWIDTHUNIT_BYTE; + ctx->hcryp_gcm.Init.pKey = ctx->gcm_key; + + if (HAL_CRYP_Init(&ctx->hcryp_gcm) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_gcm.Instance->CR; + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); +} + +int mbedtls_gcm_starts(mbedtls_gcm_context *ctx, + int mode, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len) +{ + int ret = 0; + unsigned int i; + __ALIGN_BEGIN static uint32_t iv_32B[4] __ALIGN_END; + + GCM_VALIDATE_RET(ctx != NULL); + GCM_VALIDATE_RET(mode != MBEDTLS_GCM_ENCRYPT || mode != MBEDTLS_GCM_DECRYPT); + GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(add_len == 0 || add != NULL); + + /* IV and AD are limited to 2^64 bits, so 2^61 bytes */ + /* IV is not allowed to be zero length */ + if (iv_len == 0 || + ((uint64_t) iv_len) >> 61 != 0 || + ((uint64_t) add_len) >> 61 != 0) { + return (MBEDTLS_ERR_GCM_BAD_INPUT); + } + + /* implementation restrict support to the length of 96 bits */ + if (IV_LENGTH != iv_len) { + return (MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED); + } + +#if !defined(STM32_AAD_ANY_LENGTH_SUPPORT) + /* implementation restrict support to a buffer multiple of 32 bits */ + if ((add_len % AAD_WORD_ALIGN) != 0U) { + return (MBEDTLS_ERR_PLATFORM_FEATURE_UNSUPPORTED); + } +#endif + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + if (HAL_CRYP_Init(&ctx->hcryp_gcm) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + /* allow multi-context of CRYP use: restore context */ + ctx->hcryp_gcm.Instance->CR = ctx->ctx_save_cr; + + ctx->mode = mode; + ctx->len = 0; + + /* Set IV with invert endianness */ + for (i = 0; i < 3; i++) { + GET_UINT32_BE(iv_32B[i], iv, 4 * i); + } + + /* According to NIST specification, the counter value is 0x2 when + processing the first block of payload */ + iv_32B[3] = 0x00000002; + + ctx->hcryp_gcm.Init.pInitVect = iv_32B; + + if (add_len > 0) { + ctx->hcryp_gcm.Init.Header = (uint32_t *)add; +#if defined(STM32_AAD_ANY_LENGTH_SUPPORT) + /* header buffer in byte length */ + ctx->hcryp_gcm.Init.HeaderSize = (uint32_t)add_len; +#else + /* header buffer in word length */ + ctx->hcryp_gcm.Init.HeaderSize = (uint32_t)(add_len / AAD_WORD_ALIGN); +#endif + } else { + ctx->hcryp_gcm.Init.Header = NULL; + ctx->hcryp_gcm.Init.HeaderSize = 0; + } + +#if defined(STM32_AAD_ANY_LENGTH_SUPPORT) + /* Additional Authentication Data in bytes unit */ + ctx->hcryp_gcm.Init.HeaderWidthUnit = CRYP_HEADERWIDTHUNIT_BYTE; +#endif + + /* Do not Allow IV reconfiguration at every gcm update */ + ctx->hcryp_gcm.Init.KeyIVConfigSkip = CRYP_KEYIVCONFIG_ONCE; + + /* reconfigure the CRYP */ + if (HAL_CRYP_SetConfig(&ctx->hcryp_gcm, &ctx->hcryp_gcm.Init) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_gcm.Instance->CR; + +exit: + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); +} + +int mbedtls_gcm_update(mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *input, + unsigned char *output) +{ + int ret = 0; +#if !defined(STM32_AAD_ANY_LENGTH_SUPPORT) + size_t rest_length = 0; +#endif + + GCM_VALIDATE_RET(ctx != NULL); + GCM_VALIDATE_RET(length == 0 || input != NULL); + GCM_VALIDATE_RET(length == 0 || output != NULL); + + if (output > input && (size_t)(output - input) < length) { + return (MBEDTLS_ERR_GCM_BAD_INPUT); + } + + /* Total length is restricted to 2^39 - 256 bits, ie 2^36 - 2^5 bytes + * Also check for possible overflow */ + if (((ctx->len + length) < ctx->len) || + ((uint64_t)(ctx->len + length) > 0xFFFFFFFE0ull)) { + return (MBEDTLS_ERR_GCM_BAD_INPUT); + } + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + /* allow multi-context of CRYP use: restore context */ + ctx->hcryp_gcm.Instance->CR = ctx->ctx_save_cr; + + ctx->len += length; + +#if !defined(STM32_AAD_ANY_LENGTH_SUPPORT) + /* compute remaining data (data buffer in word) */ + if ((length % AAD_WORD_ALIGN) != 0U) { + rest_length = length % AAD_WORD_ALIGN; + } +#endif + + if (ctx->mode == MBEDTLS_GCM_DECRYPT) { + if (HAL_CRYP_Decrypt(&ctx->hcryp_gcm, + (uint32_t *)input, + length, + (uint32_t *)output, + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } +#if !defined(STM32_AAD_ANY_LENGTH_SUPPORT) + /* manage last bytes */ + if (rest_length != 0) { + if (HAL_CRYP_Decrypt(&ctx->hcryp_gcm, + (uint32_t *)(input + (length / AAD_WORD_ALIGN)), + rest_length, + (uint32_t *)(output + (length / AAD_WORD_ALIGN)), + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + } +#endif + } else { + if (HAL_CRYP_Encrypt(&ctx->hcryp_gcm, + (uint32_t *)input, + length, + (uint32_t *)output, + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } +#if !defined(STM32_AAD_ANY_LENGTH_SUPPORT) + /* manage last bytes */ + if (rest_length != 0) { + if (HAL_CRYP_Encrypt(&ctx->hcryp_gcm, + (uint32_t *)(input + (length / AAD_WORD_ALIGN)), + rest_length, + (uint32_t *)(output + (length / AAD_WORD_ALIGN)), + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + } +#endif + } + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_gcm.Instance->CR; + +exit: + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); +} + +int mbedtls_gcm_finish(mbedtls_gcm_context *ctx, + unsigned char *tag, + size_t tag_len) +{ + int ret = 0; + __ALIGN_BEGIN uint8_t mac[16] __ALIGN_END; /* temporary mac */ + + GCM_VALIDATE_RET(ctx != NULL); + GCM_VALIDATE_RET(tag != NULL); + + if (tag_len > 16 || tag_len < 4) { + return (MBEDTLS_ERR_GCM_BAD_INPUT); + } + + /* Protect context access */ + /* (it may occur at a same time in a threaded environment) */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_lock(&cryp_mutex) != 0) { + return (MBEDTLS_ERR_THREADING_MUTEX_ERROR); + } +#endif /* MBEDTLS_THREADING_C */ + + /* allow multi-context of CRYP use: restore context */ + ctx->hcryp_gcm.Instance->CR = ctx->ctx_save_cr; + + /* Tag has a variable length */ + memset(mac, 0, sizeof(mac)); + + /* Generate the authentication TAG */ + if (HAL_CRYPEx_AESGCM_GenerateAuthTAG(&ctx->hcryp_gcm, + (uint32_t *)mac, + ST_CRYP_TIMEOUT) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + + memcpy(tag, mac, tag_len); + + /* allow multi-context of CRYP : save context */ + ctx->ctx_save_cr = ctx->hcryp_gcm.Instance->CR; + +exit: + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&cryp_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); +} + +int mbedtls_gcm_crypt_and_tag(mbedtls_gcm_context *ctx, + int mode, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *input, + unsigned char *output, + size_t tag_len, + unsigned char *tag) +{ + int ret; + + GCM_VALIDATE_RET(ctx != NULL); + GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(add_len == 0 || add != NULL); + GCM_VALIDATE_RET(length == 0 || input != NULL); + GCM_VALIDATE_RET(length == 0 || output != NULL); + GCM_VALIDATE_RET(tag != NULL); + + if ((ret = mbedtls_gcm_starts(ctx, mode, iv, iv_len, add, add_len)) != 0) { + return (ret); + } + + if ((ret = mbedtls_gcm_update(ctx, length, input, output)) != 0) { + return (ret); + } + + if ((ret = mbedtls_gcm_finish(ctx, tag, tag_len)) != 0) { + return (ret); + } + + return (0); +} + +int mbedtls_gcm_auth_decrypt(mbedtls_gcm_context *ctx, + size_t length, + const unsigned char *iv, + size_t iv_len, + const unsigned char *add, + size_t add_len, + const unsigned char *tag, + size_t tag_len, + const unsigned char *input, + unsigned char *output) +{ + int ret; + unsigned char check_tag[16]; + size_t i; + int diff; + + GCM_VALIDATE_RET(ctx != NULL); + GCM_VALIDATE_RET(iv != NULL); + GCM_VALIDATE_RET(add_len == 0 || add != NULL); + GCM_VALIDATE_RET(tag != NULL); + GCM_VALIDATE_RET(length == 0 || input != NULL); + GCM_VALIDATE_RET(length == 0 || output != NULL); + + if ((ret = mbedtls_gcm_crypt_and_tag(ctx, MBEDTLS_GCM_DECRYPT, length, + iv, iv_len, add, add_len, + input, output, tag_len, check_tag)) != 0) { + return (ret); + } + + /* Check tag in "constant-time" */ + for (diff = 0, i = 0; i < tag_len; i++) { + diff |= tag[i] ^ check_tag[i]; + } + + if (diff != 0) { + mbedtls_platform_zeroize(output, length); + return (MBEDTLS_ERR_GCM_AUTH_FAILED); + } + + return (0); +} + +void mbedtls_gcm_free(mbedtls_gcm_context *ctx) +{ + if (ctx == NULL) { + return; + } + + __disable_irq(); + if (cryp_context_count > 0) { + cryp_context_count--; + } + +#if defined(MBEDTLS_THREADING_C) + if (cryp_mutex_started) { + mbedtls_mutex_free(&cryp_mutex); + cryp_mutex_started = 0; + } +#endif /* MBEDTLS_THREADING_C */ + __enable_irq(); + + /* Shut down CRYP on last context */ + if (cryp_context_count == 0) { + HAL_CRYP_DeInit(&ctx->hcryp_gcm); + } + + cryp_zeroize((void *)ctx, sizeof(mbedtls_gcm_context)); +} + +#endif /*MBEDTLS_GCM_ALT*/ +#endif /*MBEDTLS_GCM_C*/ diff --git a/features/mbedtls/targets/TARGET_STM/gcm_alt.h b/features/mbedtls/targets/TARGET_STM/gcm_alt.h new file mode 100644 index 0000000000..957ed02814 --- /dev/null +++ b/features/mbedtls/targets/TARGET_STM/gcm_alt.h @@ -0,0 +1,76 @@ +/** + * \file gcm_alt.h.h + * + * \brief This file contains GCM definitions and functions. + * + * The Galois/Counter Mode (GCM) for 128-bit block ciphers is defined + * in D. McGrew, J. Viega, The Galois/Counter Mode of Operation + * (GCM), Natl. Inst. Stand. Technol. + * + * For more information on GCM, see NIST SP 800-38D: Recommendation for + * Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright (C) 2019-2020 STMicroelectronics, All Rights Reserved + * 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 implements ST GCM HW services based on API from mbed TLS + */ + +/* Define to prevent recursive inclusion -------------------------------------*/ +#ifndef MBEDTLS_GCM_ALT_H +#define MBEDTLS_GCM_ALT_H + +#if defined(MBEDTLS_GCM_ALT) +/* Includes ------------------------------------------------------------------*/ +#include "cryp_stm32.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Exported types ------------------------------------------------------------*/ +/** + * \brief AES context structure + * + */ +typedef struct mbedtls_gcm_context { + /* Encryption/Decryption key */ + uint32_t gcm_key[8]; + + CRYP_HandleTypeDef hcryp_gcm; /* HW driver handle */ + uint32_t ctx_save_cr; /* save context for multi-context */ + uint64_t len; /* total length of the encrypted data. */ + int mode; /* The operation to perform: + #MBEDTLS_GCM_ENCRYPT or + #MBEDTLS_GCM_DECRYPT. */ +} +mbedtls_gcm_context; + +/* Exported constants --------------------------------------------------------*/ +/* Uncomment if ADD (Additional Authentication Data) may have not a length */ +/* over a multiple of 32 bits (Hw implementation dependance) */ +//#define STM32_AAD_ANY_LENGTH_SUPPORT +/* Exported macro ------------------------------------------------------------*/ +/* Exported functions --------------------------------------------------------*/ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_GCM_ALT */ +#endif /* MBEDTLS_GCM_ALT_H */ diff --git a/features/mbedtls/targets/TARGET_STM/md5_alt.c b/features/mbedtls/targets/TARGET_STM/md5_alt.c index 49d9087999..d1646f46a6 100644 --- a/features/mbedtls/targets/TARGET_STM/md5_alt.c +++ b/features/mbedtls/targets/TARGET_STM/md5_alt.c @@ -1,7 +1,6 @@ /* - * MD5 hw acceleration - ******************************************************************************* - * Copyright (c) 2017, STMicroelectronics + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -16,69 +15,52 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * This file implements STMicroelectronics MD5 with HW services based on API + * from mbed TLS */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +/* Includes ------------------------------------------------------------------*/ #include "mbedtls/md5.h" + #if defined(MBEDTLS_MD5_C) - #if defined(MBEDTLS_MD5_ALT) +#include #include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize(void *v, size_t n) -{ - volatile unsigned char *p = v; - while (n--) { - *p++ = 0; - } -} -static int st_md5_restore_hw_context(mbedtls_md5_context *ctx) -{ - uint32_t i; - uint32_t tickstart; - /* allow multi-instance of HASH use: save context for HASH HW module CR */ - /* Check that there is no HASH activity on going */ - tickstart = HAL_GetTick(); - while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) { - if ((HAL_GetTick() - tickstart) > ST_MD5_TIMEOUT) { - return 0; // timeout: HASH processor is busy - } - } - HASH->STR = ctx->ctx_save_str; - HASH->CR = (ctx->ctx_save_cr | HASH_CR_INIT); - for (i = 0; i < 38; i++) { - HASH->CSR[i] = ctx->ctx_save_csr[i]; - } - return 1; -} +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +#define MD5_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MD5_BAD_INPUT_DATA ) +#define MD5_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) -static int st_md5_save_hw_context(mbedtls_md5_context *ctx) -{ - uint32_t i; - uint32_t tickstart; - /* Check that there is no HASH activity on going */ - tickstart = HAL_GetTick(); - while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) { - if ((HAL_GetTick() - tickstart) > ST_MD5_TIMEOUT) { - return 0; // timeout: HASH processor is busy - } - } - /* allow multi-instance of HASH use: restore context for HASH HW module CR */ - ctx->ctx_save_cr = HASH->CR; - ctx->ctx_save_str = HASH->STR; - for (i = 0; i < 38; i++) { - ctx->ctx_save_csr[i] = HASH->CSR[i]; - } - return 1; -} +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ void mbedtls_md5_init(mbedtls_md5_context *ctx) { - mbedtls_zeroize(ctx, sizeof(mbedtls_md5_context)); + MD5_VALIDATE(ctx != NULL); - /* Enable HASH clock */ - __HAL_RCC_HASH_CLK_ENABLE(); + __disable_irq(); +#if defined(MBEDTLS_THREADING_C) + /* mutex cannot be initialized twice */ + if (!hash_mutex_started) { + mbedtls_mutex_init(&hash_mutex); + hash_mutex_started = 1; + } +#endif /* MBEDTLS_THREADING_C */ + hash_context_count++; + __enable_irq(); + hash_zeroize(ctx, sizeof(mbedtls_md5_context)); } void mbedtls_md5_free(mbedtls_md5_context *ctx) @@ -86,124 +68,222 @@ void mbedtls_md5_free(mbedtls_md5_context *ctx) if (ctx == NULL) { return; } - mbedtls_zeroize(ctx, sizeof(mbedtls_md5_context)); + + __disable_irq(); + if (hash_context_count > 0) { + hash_context_count--; + } + +#if defined(MBEDTLS_THREADING_C) + if (hash_mutex_started) { + mbedtls_mutex_free(&hash_mutex); + hash_mutex_started = 0; + } +#endif /* MBEDTLS_THREADING_C */ + __enable_irq(); + + /* Shut down HASH on last context */ + if (hash_context_count == 0) { + HAL_HASH_DeInit(&ctx->hhash); + } + + hash_zeroize(ctx, sizeof(mbedtls_md5_context)); } void mbedtls_md5_clone(mbedtls_md5_context *dst, const mbedtls_md5_context *src) { + MD5_VALIDATE(dst != NULL); + MD5_VALIDATE(src != NULL); + *dst = *src; } int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx) { - /* HASH IP initialization */ - if (HAL_HASH_DeInit(&ctx->hhash_md5) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + MD5_VALIDATE_RET(ctx != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); } +#endif /* MBEDTLS_THREADING_C */ /* HASH Configuration */ - ctx->hhash_md5.Init.DataType = HASH_DATATYPE_8B; - /* clear CR ALGO value */ - HASH->CR &= ~HASH_CR_ALGO_Msk; - if (HAL_HASH_Init(&ctx->hhash_md5) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (HAL_HASH_DeInit(&ctx->hhash) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - if (st_md5_save_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + ctx->hhash.Init.DataType = HASH_DATATYPE_8B; + if (HAL_HASH_Init(&ctx->hhash) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - return 0; + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, const unsigned char data[ST_MD5_BLOCK_SIZE]) +int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, + const unsigned char data[ST_MD5_BLOCK_SIZE]) { - if (st_md5_restore_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + MD5_VALIDATE_RET(ctx != NULL); + MD5_VALIDATE_RET((const unsigned char *)data != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); } - if (HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, (uint8_t *)data, ST_MD5_BLOCK_SIZE) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + + if (HAL_HASH_MD5_Accmlt(&ctx->hhash, + (uint8_t *) data, + ST_MD5_BLOCK_SIZE) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - if (st_md5_save_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen) +int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen) { - int err; + int ret = 0; size_t currentlen = ilen; - /* If ilen = 0 : do nothing */ - if (currentlen != 0) { - if (st_md5_restore_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + + MD5_VALIDATE_RET(ctx != NULL); + MD5_VALIDATE_RET(ilen == 0 || input != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); + } +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + + if (currentlen < (ST_MD5_BLOCK_SIZE - ctx->sbuf_len)) { + /* only store input data in context buffer */ + memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen); + ctx->sbuf_len += currentlen; + } else { + /* fill context buffer until ST_MD5_BLOCK_SIZE bytes, and process it */ + memcpy(ctx->sbuf + ctx->sbuf_len, + input, + (ST_MD5_BLOCK_SIZE - ctx->sbuf_len)); + currentlen -= (ST_MD5_BLOCK_SIZE - ctx->sbuf_len); + + if (HAL_HASH_MD5_Accmlt(&ctx->hhash, + (uint8_t *)(ctx->sbuf), + ST_MD5_BLOCK_SIZE) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - // store mechanism to accumulate ST_MD5_BLOCK_SIZE bytes (512 bits) in the HW - if (currentlen < (ST_MD5_BLOCK_SIZE - ctx->sbuf_len)) { - // only buffurize - memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen); - ctx->sbuf_len += currentlen; - } else { - // fill buffer and process it - memcpy(ctx->sbuf + ctx->sbuf_len, input, (ST_MD5_BLOCK_SIZE - ctx->sbuf_len)); - currentlen -= (ST_MD5_BLOCK_SIZE - ctx->sbuf_len); - err = mbedtls_internal_md5_process(ctx, ctx->sbuf); - if (err != 0) { - return err; - } - // Process every input as long as it is %64 bytes, ie 512 bits - size_t iter = currentlen / ST_MD5_BLOCK_SIZE; - if (iter != 0) { - if (HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, (uint8_t *)(input + ST_MD5_BLOCK_SIZE - ctx->sbuf_len), (iter * ST_MD5_BLOCK_SIZE)) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - } - // sbuf is completely accumulated, now copy up to 63 remaining bytes - ctx->sbuf_len = currentlen % ST_MD5_BLOCK_SIZE; - if (ctx->sbuf_len != 0) { - memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len); + /* Process following input data + with size multiple of ST_MD5_BLOCK_SIZE bytes */ + size_t iter = currentlen / ST_MD5_BLOCK_SIZE; + if (iter != 0) { + if (HAL_HASH_MD5_Accmlt(&ctx->hhash, + (uint8_t *)(input + ST_MD5_BLOCK_SIZE - ctx->sbuf_len), + (iter * ST_MD5_BLOCK_SIZE)) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } } - if (st_md5_save_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + /* Store only the remaining input data + up to (ST_MD5_BLOCK_SIZE - 1) bytes */ + ctx->sbuf_len = currentlen % ST_MD5_BLOCK_SIZE; + if (ctx->sbuf_len != 0) { + memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len); } } - return 0; + + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, unsigned char output[16]) +int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, unsigned char output[32]) { - if (st_md5_restore_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + MD5_VALIDATE_RET(ctx != NULL); + MD5_VALIDATE_RET((unsigned char *)output != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); } - /* Last accumulation for extra bytes in sbuf_len */ - /* This sets HW flags in case mbedtls_md5_update has not been called yet */ - if (HAL_HASH_MD5_Accumulate(&ctx->hhash_md5, ctx->sbuf, ctx->sbuf_len) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + + /* Last accumulation for pending bytes in sbuf_len, + then trig processing and get digest */ + if (HAL_HASH_MD5_Accmlt_End(&ctx->hhash, + ctx->sbuf, + ctx->sbuf_len, + output, + ST_HASH_TIMEOUT) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - mbedtls_zeroize(ctx->sbuf, ST_MD5_BLOCK_SIZE); ctx->sbuf_len = 0; - __HAL_HASH_START_DIGEST(); - if (HAL_HASH_MD5_Finish(&ctx->hhash_md5, output, 10)) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - if (st_md5_save_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -#endif /* MBEDTLS_MD5_ALT */ +#endif /* MBEDTLS_MD5_ALT*/ #endif /* MBEDTLS_MD5_C */ diff --git a/features/mbedtls/targets/TARGET_STM/md5_alt.h b/features/mbedtls/targets/TARGET_STM/md5_alt.h index 43a549d357..7eb6200702 100644 --- a/features/mbedtls/targets/TARGET_STM/md5_alt.h +++ b/features/mbedtls/targets/TARGET_STM/md5_alt.h @@ -1,9 +1,15 @@ /** - * \file md5_alt.h + * \file md5.h * - * \brief MD5 hw acceleration (hash function) + * \brief MD5 message digest algorithm (hash function) * - * Copyright (c) 2017, STMicroelectronics + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,172 +24,40 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * This file implements STMicroelectronics MD5 API with HW services based + * on mbed TLS API */ + #ifndef MBEDTLS_MD5_ALT_H #define MBEDTLS_MD5_ALT_H -#if defined(MBEDTLS_MD5_ALT) +#if defined (MBEDTLS_MD5_ALT) +/* Includes ------------------------------------------------------------------*/ +#include "hash_stm32.h" -#include "cmsis.h" -#include - -#ifdef __cplusplus -extern "C" { +#ifndef MBEDTLS_ERR_MD5_BAD_INPUT_DATA +#define MBEDTLS_ERR_MD5_BAD_INPUT_DATA -0x00AF #endif -#define ST_MD5_BLOCK_SIZE ((size_t)(64)) // HW handles 512 bits, ie 64 bytes -#define ST_MD5_TIMEOUT ((uint32_t) 3) +#define ST_MD5_BLOCK_SIZE ((size_t) 64) /*!< HW handles 512 bits, ie 64 bytes */ +#define ST_MD5_NB_HASH_REG ((uint32_t)57) /*!< Number of HASH HW context Registers: + CR + STR + IMR + CSR[54] */ /** * \brief MD5 context structure - * \note HAL_HASH_MD5_Accumulate will accumulate 512 bits packets, unless it is the last call to the function - * A ST_MD5_BLOCK_SIZE bytes buffer is used to save values and handle the processing - * ST_MD5_BLOCK_SIZE bytes per ST_MD5_BLOCK_SIZE bytes - * If MD5_finish is called and sbuf_len>0, the remaining bytes are accumulated prior to the call to HAL_HASH_MD5_Finish + * + * STMicroelectronics edition */ -typedef struct { - HASH_HandleTypeDef hhash_md5;/*!< ST HAL HASH struct */ - unsigned char sbuf[ST_MD5_BLOCK_SIZE]; /*!< MBEDTLS_MD5_BLOCK_SIZE buffer to store values so that algorithm is caled once the buffer is filled */ - unsigned char sbuf_len; /*!< number of bytes to be processed in sbuf */ - uint32_t ctx_save_cr; - uint32_t ctx_save_str; - uint32_t ctx_save_csr[38]; +typedef struct mbedtls_md5_context { + HASH_HandleTypeDef hhash; /*!< Handle of HASH HAL */ + uint8_t sbuf[ST_MD5_BLOCK_SIZE]; /*!< Buffer to store input data until ST_MD5_BLOCK_SIZE + is reached, or until last input data is reached */ + uint8_t sbuf_len; /*!< Number of bytes stored in sbuf */ + uint32_t ctx_save_regs[ST_MD5_NB_HASH_REG]; } mbedtls_md5_context; -/** - * \brief Initialize MD5 context - * - * \param ctx MD5 context to be initialized - */ -void mbedtls_md5_init(mbedtls_md5_context *ctx); - -/** - * \brief Clear MD5 context - * - * \param ctx MD5 context to be cleared - */ -void mbedtls_md5_free(mbedtls_md5_context *ctx); - -/** - * \brief Clone (the state of) an MD5 context - * - * \param dst The destination context - * \param src The context to be cloned - */ -void mbedtls_md5_clone(mbedtls_md5_context *dst, - const mbedtls_md5_context *src); - -/** - * \brief MD5 context setup - * - * \param ctx context to be initialized - * - * \returns error code - */ -int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx); - -/** - * \brief MD5 process buffer - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \returns error code - */ -int mbedtls_md5_update_ret(mbedtls_md5_context *ctx, const unsigned char *input, size_t ilen); - -/** - * \brief MD5 final digest - * - * \param ctx MD5 context - * \param output MD5 checksum result - * - * \returns error code - */ -int mbedtls_md5_finish_ret(mbedtls_md5_context *ctx, unsigned char output[16]); - -/* Internal use */ -int mbedtls_internal_md5_process(mbedtls_md5_context *ctx, const unsigned char data[ST_MD5_BLOCK_SIZE]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief MD5 context setup - * - * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 - * - * \param ctx context to be initialized - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5_starts(mbedtls_md5_context *ctx); - -/** - * \brief MD5 process buffer - * - * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 - * - * \param ctx MD5 context - * \param input buffer holding the data - * \param ilen length of the input data - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5_update(mbedtls_md5_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief MD5 final digest - * - * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 - * - * \param ctx MD5 context - * \param output MD5 checksum result - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5_finish(mbedtls_md5_context *ctx, - unsigned char output[16]); - -/** - * \brief MD5 process data block (internal use only) - * - * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 - * - * \param ctx MD5 context - * \param data buffer holding one block of data - * - * \warning MD5 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_md5_process(mbedtls_md5_context *ctx, - const unsigned char data[64]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#ifdef __cplusplus -} -#endif #endif /* MBEDTLS_MD5_ALT */ -#endif /* md5_alt.h */ +#endif /* MBEDTLS_MD5_ALT_H */ \ No newline at end of file diff --git a/features/mbedtls/targets/TARGET_STM/sha1_alt.c b/features/mbedtls/targets/TARGET_STM/sha1_alt.c index 3e5368112c..8a8614a60e 100644 --- a/features/mbedtls/targets/TARGET_STM/sha1_alt.c +++ b/features/mbedtls/targets/TARGET_STM/sha1_alt.c @@ -1,7 +1,6 @@ /* - * sha1_alt.c for SHA1 HASH - ******************************************************************************* - * Copyright (c) 2017, STMicroelectronics + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -16,67 +15,52 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * This file implements STMicroelectronics SHA1 with HW services based on API + * from mbed TLS */ +/* + * The SHA-1 standard was published by NIST in 1993. + * + * http://www.itl.nist.gov/fipspubs/fip180-1.htm + */ + +/* Includes ------------------------------------------------------------------*/ #include "mbedtls/sha1.h" + +#if defined(MBEDTLS_SHA1_C) #if defined(MBEDTLS_SHA1_ALT) +#include #include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize(void *v, size_t n) -{ - volatile unsigned char *p = (unsigned char *)v; - while (n--) { - *p++ = 0; - } -} -static int st_sha1_restore_hw_context(mbedtls_sha1_context *ctx) -{ - uint32_t i; - uint32_t tickstart; - /* allow multi-instance of HASH use: save context for HASH HW module CR */ - /* Check that there is no HASH activity on going */ - tickstart = HAL_GetTick(); - while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) { - if ((HAL_GetTick() - tickstart) > ST_SHA1_TIMEOUT) { - return 0; // timeout: HASH processor is busy - } - } - HASH->STR = ctx->ctx_save_str; - HASH->CR = (ctx->ctx_save_cr | HASH_CR_INIT); - for (i = 0; i < 38; i++) { - HASH->CSR[i] = ctx->ctx_save_csr[i]; - } - return 1; -} +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +#define SHA1_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA ) +#define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) -static int st_sha1_save_hw_context(mbedtls_sha1_context *ctx) -{ - uint32_t i; - uint32_t tickstart; - /* Check that there is no HASH activity on going */ - tickstart = HAL_GetTick(); - while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) { - if ((HAL_GetTick() - tickstart) > ST_SHA1_TIMEOUT) { - return 0; // timeout: HASH processor is busy - } - } - /* allow multi-instance of HASH use: restore context for HASH HW module CR */ - ctx->ctx_save_cr = HASH->CR; - ctx->ctx_save_str = HASH->STR; - for (i = 0; i < 38; i++) { - ctx->ctx_save_csr[i] = HASH->CSR[i]; - } - return 1; -} +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ void mbedtls_sha1_init(mbedtls_sha1_context *ctx) { - mbedtls_zeroize(ctx, sizeof(mbedtls_sha1_context)); + SHA1_VALIDATE(ctx != NULL); - /* Enable HASH clock */ - __HAL_RCC_HASH_CLK_ENABLE(); + __disable_irq(); +#if defined(MBEDTLS_THREADING_C) + /* mutex cannot be initialized twice */ + if (!hash_mutex_started) { + mbedtls_mutex_init(&hash_mutex); + hash_mutex_started = 1; + } +#endif /* MBEDTLS_THREADING_C */ + hash_context_count++; + __enable_irq(); + hash_zeroize(ctx, sizeof(mbedtls_sha1_context)); } void mbedtls_sha1_free(mbedtls_sha1_context *ctx) @@ -84,124 +68,223 @@ void mbedtls_sha1_free(mbedtls_sha1_context *ctx) if (ctx == NULL) { return; } - mbedtls_zeroize(ctx, sizeof(mbedtls_sha1_context)); + + __disable_irq(); + if (hash_context_count > 0) { + hash_context_count--; + } + +#if defined(MBEDTLS_THREADING_C) + if (hash_mutex_started) { + mbedtls_mutex_free(&hash_mutex); + hash_mutex_started = 0; + } +#endif /* MBEDTLS_THREADING_C */ + __enable_irq(); + + /* Shut down HASH on last context */ + if (hash_context_count == 0) { + HAL_HASH_DeInit(&ctx->hhash); + } + + hash_zeroize(ctx, sizeof(mbedtls_sha1_context)); } void mbedtls_sha1_clone(mbedtls_sha1_context *dst, const mbedtls_sha1_context *src) { + SHA1_VALIDATE(dst != NULL); + SHA1_VALIDATE(src != NULL); + *dst = *src; } int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx) { - /* Deinitializes the HASH peripheral */ - if (HAL_HASH_DeInit(&ctx->hhash_sha1) == HAL_ERROR) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + SHA1_VALIDATE_RET(ctx != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); } +#endif /* MBEDTLS_THREADING_C */ /* HASH Configuration */ - ctx->hhash_sha1.Init.DataType = HASH_DATATYPE_8B; - /* clear CR ALGO value */ - HASH->CR &= ~HASH_CR_ALGO_Msk; - if (HAL_HASH_Init(&ctx->hhash_sha1) == HAL_ERROR) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (HAL_HASH_DeInit(&ctx->hhash) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - if (st_sha1_save_hw_context(ctx) != 1) { - // return HASH_BUSY timeout Error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + ctx->hhash.Init.DataType = HASH_DATATYPE_8B; + if (HAL_HASH_Init(&ctx->hhash) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - return 0; + + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; + } +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[ST_SHA1_BLOCK_SIZE]) +int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, + const unsigned char data[ST_SHA1_BLOCK_SIZE]) { - if (st_sha1_restore_hw_context(ctx) != 1) { - // return HASH_BUSY timeout Error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + SHA1_VALIDATE_RET(ctx != NULL); + SHA1_VALIDATE_RET((const unsigned char *)data != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); } - if (HAL_HASH_SHA1_Accumulate(&ctx->hhash_sha1, (uint8_t *) data, ST_SHA1_BLOCK_SIZE) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + + if (HAL_HASH_SHA1_Accmlt(&ctx->hhash, + (uint8_t *) data, + ST_SHA1_BLOCK_SIZE) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - if (st_sha1_save_hw_context(ctx) != 1) { - // return HASH_BUSY timeout Error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, const unsigned char *input, size_t ilen) +int mbedtls_sha1_update_ret(mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen) { - int err; + int ret = 0; size_t currentlen = ilen; - if (st_sha1_restore_hw_context(ctx) != 1) { - // return HASH_BUSY timeout Error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - // store mechanism to accumulate ST_SHA1_BLOCK_SIZE bytes (512 bits) in the HW - if (currentlen == 0) { // only change HW status is size if 0 - if (ctx->hhash_sha1.Phase == HAL_HASH_PHASE_READY) { - /* Select the SHA1 mode and reset the HASH processor core, so that the HASH will be ready to compute - the message digest of a new message */ - HASH->CR |= HASH_ALGOSELECTION_SHA1 | HASH_CR_INIT; - } - ctx->hhash_sha1.Phase = HAL_HASH_PHASE_PROCESS; - } else if (currentlen < (ST_SHA1_BLOCK_SIZE - ctx->sbuf_len)) { - // only buffurize + SHA1_VALIDATE_RET(ctx != NULL); + SHA1_VALIDATE_RET(ilen == 0 || input != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); + } +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + + if (currentlen < (ST_SHA1_BLOCK_SIZE - ctx->sbuf_len)) { + /* only store input data in context buffer */ memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen); ctx->sbuf_len += currentlen; } else { - // fill buffer and process it - memcpy(ctx->sbuf + ctx->sbuf_len, input, (ST_SHA1_BLOCK_SIZE - ctx->sbuf_len)); + /* fill context buffer until ST_SHA1_BLOCK_SIZE bytes, and process it */ + memcpy(ctx->sbuf + ctx->sbuf_len, + input, + (ST_SHA1_BLOCK_SIZE - ctx->sbuf_len)); currentlen -= (ST_SHA1_BLOCK_SIZE - ctx->sbuf_len); - err = mbedtls_internal_sha1_process(ctx, ctx->sbuf); - if (err != 0) { - return err; + + if (HAL_HASH_SHA1_Accmlt(&ctx->hhash, + (uint8_t *)(ctx->sbuf), + ST_SHA1_BLOCK_SIZE) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - // Process every input as long as it is %64 bytes, ie 512 bits + + /* Process following input data + with size multiple of ST_SHA1_BLOCK_SIZE bytes */ size_t iter = currentlen / ST_SHA1_BLOCK_SIZE; - if (HAL_HASH_SHA1_Accumulate(&ctx->hhash_sha1, (uint8_t *)(input + ST_SHA1_BLOCK_SIZE - ctx->sbuf_len), (iter * ST_SHA1_BLOCK_SIZE)) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (iter != 0) { + if (HAL_HASH_SHA1_Accmlt(&ctx->hhash, + (uint8_t *)(input + ST_SHA1_BLOCK_SIZE - ctx->sbuf_len), + (iter * ST_SHA1_BLOCK_SIZE)) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } } - // sbuf is completely accumulated, now copy up to 63 remaining bytes + + /* Store only the remaining input data + up to (ST_SHA1_BLOCK_SIZE - 1) bytes */ ctx->sbuf_len = currentlen % ST_SHA1_BLOCK_SIZE; if (ctx->sbuf_len != 0) { memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len); } } - if (st_sha1_save_hw_context(ctx) != 1) { - // return HASH_BUSY timeout Error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, unsigned char output[20]) +int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, + unsigned char output[32]) { - if (st_sha1_restore_hw_context(ctx) != 1) { - // return HASH_BUSY timeout Error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + SHA1_VALIDATE_RET(ctx != NULL); + SHA1_VALIDATE_RET((unsigned char *)output != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); + } +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + + /* Last accumulation for pending bytes in sbuf_len, + then trig processing and get digest */ + if (HAL_HASH_SHA1_Accmlt_End(&ctx->hhash, + ctx->sbuf, + ctx->sbuf_len, + output, + ST_HASH_TIMEOUT) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } - /* Last accumulation for extra bytes in sbuf_len */ - /* This allows the HW flags to be in place in case mbedtls_sha256_update has not been called yet */ - if (HAL_HASH_SHA1_Accumulate(&ctx->hhash_sha1, ctx->sbuf, ctx->sbuf_len) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - mbedtls_zeroize(ctx->sbuf, ST_SHA1_BLOCK_SIZE); ctx->sbuf_len = 0; - __HAL_HASH_START_DIGEST(); - if (HAL_HASH_SHA1_Finish(&ctx->hhash_sha1, output, 10) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - if (st_sha1_save_hw_context(ctx) != 1) { - // return HASH_BUSY timeout Error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -#endif /*MBEDTLS_SHA1_ALT*/ +#endif /* MBEDTLS_SHA1_ALT*/ +#endif /* MBEDTLS_SHA1_C */ diff --git a/features/mbedtls/targets/TARGET_STM/sha1_alt.h b/features/mbedtls/targets/TARGET_STM/sha1_alt.h index bb4991d580..7b3bd7a5ab 100644 --- a/features/mbedtls/targets/TARGET_STM/sha1_alt.h +++ b/features/mbedtls/targets/TARGET_STM/sha1_alt.h @@ -1,9 +1,18 @@ +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ /* - * \file sha1_alt.h - * - * \brief SHA1 hw acceleration (hash function) - * - * Copyright (C) 2017, STMicroelectronics + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,172 +27,34 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * This file implements STMicroelectronics SHA1 API with HW services based + * on mbed TLS API */ + #ifndef MBEDTLS_SHA1_ALT_H #define MBEDTLS_SHA1_ALT_H #if defined (MBEDTLS_SHA1_ALT) +/* Includes ------------------------------------------------------------------*/ +#include "hash_stm32.h" +#define ST_SHA1_BLOCK_SIZE ((size_t) 64) /*!< HW handles 512 bits, ie 64 bytes */ +#define ST_SHA1_NB_HASH_REG ((uint32_t)57) /*!< Number of HASH HW context Registers: + CR + STR + IMR + CSR[54] */ -#include "cmsis.h" -#include - -#ifdef __cplusplus -extern "C" { -#endif - -#define ST_SHA1_BLOCK_SIZE ((size_t) 64) // HW handles 512 bits, ie 64 bytes -#define ST_SHA1_TIMEOUT ((uint32_t) 3) /** - * \brief SHA-1 context structure - * \note HAL_HASH_SHA1_Accumulate will accumulate 512 bits packets, unless it is the last call to the function - * A ST_SHA1_BLOCK_SIZE bytes buffer is used to save values and handle the processing - * multiples of ST_SHA1_BLOCK_SIZE bytes - * If SHA1_finish is called and sbuf_len>0, the remaining bytes are accumulated prior to the call to HAL_HASH_SHA1_Finish + * \brief SHA-1 context structure */ -typedef struct { - unsigned char sbuf[ST_SHA1_BLOCK_SIZE]; /*!< MBEDTLS_SHA1_BLOCK_SIZE buffer to store values so that algorithm is caled once the buffer is filled */ - unsigned char sbuf_len; /*!< number of bytes remaining in sbuf to be processed */ - HASH_HandleTypeDef hhash_sha1; /*!< ST HAL HASH struct */ - uint32_t ctx_save_cr; - uint32_t ctx_save_str; - uint32_t ctx_save_csr[38]; +typedef struct mbedtls_sha1_context { + HASH_HandleTypeDef hhash; /*!< Handle of HASH HAL */ + uint8_t sbuf[ST_SHA1_BLOCK_SIZE]; /*!< Buffer to store input data until ST_SHA1_BLOCK_SIZE + is reached, or until last input data is reached */ + uint8_t sbuf_len; /*!< Number of bytes stored in sbuf */ + uint32_t ctx_save_regs[ST_SHA1_NB_HASH_REG]; } 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 - * - * \returns error code - */ -int mbedtls_sha1_starts_ret(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 - * - * \returns error code - */ -int mbedtls_sha1_update_ret(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 - * - * \returns error code - */ -int mbedtls_sha1_finish_ret(mbedtls_sha1_context *ctx, unsigned char output[20]); - -/* Internal use */ -int mbedtls_internal_sha1_process(mbedtls_sha1_context *ctx, const unsigned char data[ST_SHA1_BLOCK_SIZE]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief SHA-1 context setup - * - * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0 - * - * \param ctx The SHA-1 context to be initialized. - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_sha1_starts(mbedtls_sha1_context *ctx); - -/** - * \brief SHA-1 process buffer - * - * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0 - * - * \param ctx The SHA-1 context. - * \param input The buffer holding the input data. - * \param ilen The length of the input data. - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_sha1_update(mbedtls_sha1_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief SHA-1 final digest - * - * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0 - * - * \param ctx The SHA-1 context. - * \param output The SHA-1 checksum result. - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_sha1_finish(mbedtls_sha1_context *ctx, - unsigned char output[20]); - -/** - * \brief SHA-1 process data block (internal use only) - * - * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0 - * - * \param ctx The SHA-1 context. - * \param data The data block being processed. - * - * \warning SHA-1 is considered a weak message digest and its use - * constitutes a security risk. We recommend considering - * stronger message digests instead. - * - */ -MBEDTLS_DEPRECATED void mbedtls_sha1_process(mbedtls_sha1_context *ctx, - const unsigned char data[64]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#ifdef __cplusplus -} -#endif #endif /* MBEDTLS_SHA1_ALT */ -#endif /* sha1_alt.h */ +#endif /* MBEDTLS_SHA1_ALT_H */ \ No newline at end of file diff --git a/features/mbedtls/targets/TARGET_STM/sha256_alt.c b/features/mbedtls/targets/TARGET_STM/sha256_alt.c index 6915ffa917..5a80b23c46 100644 --- a/features/mbedtls/targets/TARGET_STM/sha256_alt.c +++ b/features/mbedtls/targets/TARGET_STM/sha256_alt.c @@ -1,7 +1,6 @@ /* - * sha256_alt.c for SHA256 HASH - ******************************************************************************* - * Copyright (c) 2017, STMicroelectronics + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -16,67 +15,53 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * This file implements STMicroelectronics SHA256 with HW services based on API + * from mbed TLS */ +/* + * The SHA-256 Secure Hash Standard was published by NIST in 2002. + * + * http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf + */ + +/* Includes ------------------------------------------------------------------*/ #include "mbedtls/sha256.h" +#if defined(MBEDTLS_SHA256_C) #if defined(MBEDTLS_SHA256_ALT) +#include #include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" -/* Implementation that should never be optimized out by the compiler */ -static void mbedtls_zeroize(void *v, size_t n) -{ - volatile unsigned char *p = v; - while (n--) { - *p++ = 0; - } -} -static int st_sha256_restore_hw_context(mbedtls_sha256_context *ctx) -{ - uint32_t i; - uint32_t tickstart; - /* allow multi-instance of HASH use: save context for HASH HW module CR */ - /* Check that there is no HASH activity on going */ - tickstart = HAL_GetTick(); - while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) { - if ((HAL_GetTick() - tickstart) > ST_SHA256_TIMEOUT) { - return 0; // timeout: HASH processor is busy - } - } - HASH->STR = ctx->ctx_save_str; - HASH->CR = (ctx->ctx_save_cr | HASH_CR_INIT); - for (i = 0; i < 38; i++) { - HASH->CSR[i] = ctx->ctx_save_csr[i]; - } - return 1; -} +/* Private typedef -----------------------------------------------------------*/ +/* Private define ------------------------------------------------------------*/ +/* Private macro -------------------------------------------------------------*/ +#define SHA256_VALIDATE_RET(cond) \ + MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA ) +#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond ) + +/* Private variables ---------------------------------------------------------*/ +/* Private function prototypes -----------------------------------------------*/ +/* Private functions ---------------------------------------------------------*/ -static int st_sha256_save_hw_context(mbedtls_sha256_context *ctx) -{ - uint32_t i; - uint32_t tickstart; - /* Check that there is no HASH activity on going */ - tickstart = HAL_GetTick(); - while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) { - if ((HAL_GetTick() - tickstart) > ST_SHA256_TIMEOUT) { - return 0; // timeout: HASH processor is busy - } - } - /* allow multi-instance of HASH use: restore context for HASH HW module CR */ - ctx->ctx_save_cr = HASH->CR; - ctx->ctx_save_str = HASH->STR; - for (i = 0; i < 38; i++) { - ctx->ctx_save_csr[i] = HASH->CSR[i]; - } - return 1; -} void mbedtls_sha256_init(mbedtls_sha256_context *ctx) { - mbedtls_zeroize(ctx, sizeof(mbedtls_sha256_context)); + SHA256_VALIDATE(ctx != NULL); - /* Enable HASH clock */ - __HAL_RCC_HASH_CLK_ENABLE(); + __disable_irq(); +#if defined(MBEDTLS_THREADING_C) + /* mutex cannot be initialized twice */ + if (!hash_mutex_started) { + mbedtls_mutex_init(&hash_mutex); + hash_mutex_started = 1; + } +#endif /* MBEDTLS_THREADING_C */ + hash_context_count++; + __enable_irq(); + + hash_zeroize(ctx, sizeof(mbedtls_sha256_context)); } void mbedtls_sha256_free(mbedtls_sha256_context *ctx) @@ -84,156 +69,264 @@ void mbedtls_sha256_free(mbedtls_sha256_context *ctx) if (ctx == NULL) { return; } - mbedtls_zeroize(ctx, sizeof(mbedtls_sha256_context)); + + __disable_irq(); + if (hash_context_count > 0) { + hash_context_count--; + } + +#if defined(MBEDTLS_THREADING_C) + if (hash_mutex_started) { + mbedtls_mutex_free(&hash_mutex); + hash_mutex_started = 0; + } +#endif /* MBEDTLS_THREADING_C */ + __enable_irq(); + + /* Shut down HASH on last context */ + if (hash_context_count == 0) { + HAL_HASH_DeInit(&ctx->hhash); + } + + hash_zeroize(ctx, sizeof(mbedtls_sha256_context)); } void mbedtls_sha256_clone(mbedtls_sha256_context *dst, const mbedtls_sha256_context *src) { + SHA256_VALIDATE(dst != NULL); + SHA256_VALIDATE(src != NULL); + *dst = *src; } int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224) { - /* HASH IP initialization */ - if (HAL_HASH_DeInit(&ctx->hhash_sha256) == HAL_ERROR) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + SHA256_VALIDATE_RET(ctx != NULL); + SHA256_VALIDATE_RET(is224 == 0 || is224 == 1); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); + } +#endif /* MBEDTLS_THREADING_C */ + + /* HASH Configuration */ + if (HAL_HASH_DeInit(&ctx->hhash) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + ctx->hhash.Init.DataType = HASH_DATATYPE_8B; + if (HAL_HASH_Init(&ctx->hhash) != HAL_OK) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } ctx->is224 = is224; - /* HASH Configuration */ - ctx->hhash_sha256.Init.DataType = HASH_DATATYPE_8B; - /* clear CR ALGO value */ - HASH->CR &= ~HASH_CR_ALGO_Msk; - if (HAL_HASH_Init(&ctx->hhash_sha256) == HAL_ERROR) { - // error found to be returned - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - if (st_sha256_save_hw_context(ctx) != 1) { - // return HASH_BUSY timeout Error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[ST_SHA256_BLOCK_SIZE]) +int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, + const unsigned char data[ST_SHA256_BLOCK_SIZE]) { - if (st_sha256_restore_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + SHA256_VALIDATE_RET(ctx != NULL); + SHA256_VALIDATE_RET((const unsigned char *)data != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); } +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + if (ctx->is224 == 0) { - if (HAL_HASHEx_SHA256_Accumulate(&ctx->hhash_sha256, (uint8_t *) data, ST_SHA256_BLOCK_SIZE) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (HAL_HASHEx_SHA256_Accmlt(&ctx->hhash, + (uint8_t *) data, + ST_SHA256_BLOCK_SIZE) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } } else { - if (HAL_HASHEx_SHA224_Accumulate(&ctx->hhash_sha256, (uint8_t *) data, ST_SHA256_BLOCK_SIZE) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (HAL_HASHEx_SHA224_Accmlt(&ctx->hhash, + (uint8_t *) data, + ST_SHA256_BLOCK_SIZE) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } } - if (st_sha256_save_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, const unsigned char *input, size_t ilen) +int mbedtls_sha256_update_ret(mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen) { - int err; + int ret = 0; size_t currentlen = ilen; - if (st_sha256_restore_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - // store mechanism to accumulate ST_SHA256_BLOCK_SIZE bytes (512 bits) in the HW - if (currentlen == 0) { // only change HW status is size if 0 - if (ctx->hhash_sha256.Phase == HAL_HASH_PHASE_READY) { - /* Select the SHA256 or SHA224 mode and reset the HASH processor core, so that the HASH will be ready to compute - the message digest of a new message */ - if (ctx->is224 == 0) { - HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT; - } else { - HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT; - } - } - ctx->hhash_sha256.Phase = HAL_HASH_PHASE_PROCESS; - } else if (currentlen < (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len)) { - // only buffurize + SHA256_VALIDATE_RET(ctx != NULL); + SHA256_VALIDATE_RET(ilen == 0 || input != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); + } +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + + if (currentlen < (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len)) { + /* only store input data in context buffer */ memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen); ctx->sbuf_len += currentlen; } else { - // fill buffer and process it - memcpy(ctx->sbuf + ctx->sbuf_len, input, (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len)); + /* fill context buffer until ST_SHA256_BLOCK_SIZE bytes, and process it */ + memcpy(ctx->sbuf + ctx->sbuf_len, + input, + (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len)); currentlen -= (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len); - err = mbedtls_internal_sha256_process(ctx, ctx->sbuf); - if (err != 0) { - return err; + + if (ctx->is224 == 0) { + if (HAL_HASHEx_SHA256_Accmlt(&ctx->hhash, + (uint8_t *)(ctx->sbuf), + ST_SHA256_BLOCK_SIZE) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } + } else { + if (HAL_HASHEx_SHA224_Accmlt(&ctx->hhash, + (uint8_t *)(ctx->sbuf), + ST_SHA256_BLOCK_SIZE) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; + } } - // Process every input as long as it is %64 bytes, ie 512 bits + + /* Process following input data + with size multiple of ST_SHA256_BLOCK_SIZE bytes */ size_t iter = currentlen / ST_SHA256_BLOCK_SIZE; if (iter != 0) { if (ctx->is224 == 0) { - if (HAL_HASHEx_SHA256_Accumulate(&ctx->hhash_sha256, (uint8_t *)(input + ST_SHA256_BLOCK_SIZE - ctx->sbuf_len), (iter * ST_SHA256_BLOCK_SIZE)) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (HAL_HASHEx_SHA256_Accmlt(&ctx->hhash, + (uint8_t *)(input + ST_SHA256_BLOCK_SIZE - ctx->sbuf_len), + (iter * ST_SHA256_BLOCK_SIZE)) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } } else { - if (HAL_HASHEx_SHA224_Accumulate(&ctx->hhash_sha256, (uint8_t *)(input + ST_SHA256_BLOCK_SIZE - ctx->sbuf_len), (iter * ST_SHA256_BLOCK_SIZE)) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (HAL_HASHEx_SHA224_Accmlt(&ctx->hhash, + (uint8_t *)(input + ST_SHA256_BLOCK_SIZE - ctx->sbuf_len), + (iter * ST_SHA256_BLOCK_SIZE)) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } } } - // sbuf is completely accumulated, now copy up to 63 remaining bytes + + /* Store only the remaining input data + up to (ST_SHA256_BLOCK_SIZE - 1) bytes */ ctx->sbuf_len = currentlen % ST_SHA256_BLOCK_SIZE; if (ctx->sbuf_len != 0) { memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len); } } - if (st_sha256_save_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + + /* save hw context */ + HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, unsigned char output[32]) +int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, + unsigned char output[32]) { - if (st_sha256_restore_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + int ret = 0; + + SHA256_VALIDATE_RET(ctx != NULL); + SHA256_VALIDATE_RET((unsigned char *)output != NULL); + +#if defined(MBEDTLS_THREADING_C) + if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) { + return (ret); } - /* Last accumulation for extra bytes in sbuf_len */ - /* This allows the HW flags to be in place in case mbedtls_sha256_update has not been called yet */ +#endif /* MBEDTLS_THREADING_C */ + + /* restore hw context */ + HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs); + + /* Last accumulation for pending bytes in sbuf_len, + then trig processing and get digest */ if (ctx->is224 == 0) { - if (HAL_HASHEx_SHA256_Accumulate(&ctx->hhash_sha256, ctx->sbuf, ctx->sbuf_len) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (HAL_HASHEx_SHA256_Accmlt_End(&ctx->hhash, + ctx->sbuf, + ctx->sbuf_len, + output, + ST_HASH_TIMEOUT) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } } else { - if (HAL_HASHEx_SHA224_Accumulate(&ctx->hhash_sha256, ctx->sbuf, ctx->sbuf_len) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + if (HAL_HASHEx_SHA224_Accmlt_End(&ctx->hhash, + ctx->sbuf, + ctx->sbuf_len, + output, + ST_HASH_TIMEOUT) != 0) { + ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; + goto exit; } } - mbedtls_zeroize(ctx->sbuf, ST_SHA256_BLOCK_SIZE); ctx->sbuf_len = 0; - __HAL_HASH_START_DIGEST(); - if (ctx->is224 == 0) { - if (HAL_HASHEx_SHA256_Finish(&ctx->hhash_sha256, output, 10) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - } else { - if (HAL_HASHEx_SHA224_Finish(&ctx->hhash_sha256, output, 10) != 0) { - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } +exit : + /* Free context access */ +#if defined(MBEDTLS_THREADING_C) + if (mbedtls_mutex_unlock(&hash_mutex) != 0) { + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; } - if (st_sha256_save_hw_context(ctx) != 1) { - // Return HASH_BUSY timeout error here - return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; - } - return 0; +#endif /* MBEDTLS_THREADING_C */ + + return (ret); } -#endif /*MBEDTLS_SHA256_ALT*/ +#endif /* MBEDTLS_SHA256_ALT*/ +#endif /* MBEDTLS_SHA256_C */ diff --git a/features/mbedtls/targets/TARGET_STM/sha256_alt.h b/features/mbedtls/targets/TARGET_STM/sha256_alt.h index 522319cc8c..3eb3cdd312 100644 --- a/features/mbedtls/targets/TARGET_STM/sha256_alt.h +++ b/features/mbedtls/targets/TARGET_STM/sha256_alt.h @@ -1,9 +1,14 @@ /** - * \file sha256_alt.h + * \file sha256.h * - * \brief SHA256 hw acceleration (hash function) + * \brief This file contains SHA-224 and SHA-256 definitions and functions. * - * Copyright (c) 2017, STMicroelectronics + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved * SPDX-License-Identifier: Apache-2.0 * * Licensed under the Apache License, Version 2.0 (the "License"); you may @@ -18,163 +23,38 @@ * See the License for the specific language governing permissions and * limitations under the License. * + * This file implements STMicroelectronics SHA256 API with HW services based + * on mbed TLS API */ + #ifndef MBEDTLS_SHA256_ALT_H #define MBEDTLS_SHA256_ALT_H #if defined (MBEDTLS_SHA256_ALT) +/* Includes ------------------------------------------------------------------*/ +#include "hash_stm32.h" -#include "cmsis.h" -#include +#define ST_SHA256_BLOCK_SIZE ((size_t) 64) /*!< HW handles 512 bits, ie 64 bytes */ +#define ST_SHA256_NB_HASH_REG ((uint32_t)57) /*!< Number of HASH HW context Registers: + CR + STR + IMR + CSR[54] */ -#ifdef __cplusplus -extern "C" { -#endif - -#define ST_SHA256_BLOCK_SIZE ((size_t) 64) // HW handles 512 bits, ie 64 bytes -#define ST_SHA256_TIMEOUT ((uint32_t) 3) /** * \brief SHA-256 context structure - * \note HAL_HASH_SHA256_Accumulate will accumulate 512 bits packets, unless it is the last call to the function - * A ST_SHA256_BLOCK_SIZE bytes buffer is used to save values and handle the processing - * ST_SHA256_BLOCK_SIZE bytes per ST_SHA256_BLOCK_SIZE bytes - * If sha256_finish is called and sbuf_len>0, the remaining bytes are accumulated prior to the call to HAL_HASH_SHA256_Finish + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). */ -typedef struct { - int is224; /*!< 0 => SHA-256, else SHA-224 */ - HASH_HandleTypeDef hhash_sha256; - unsigned char sbuf[ST_SHA256_BLOCK_SIZE]; /*!< ST_SHA256_BLOCK_SIZE buffer to store values so that algorithm is called once the buffer is filled */ - unsigned char sbuf_len; /*!< number of bytes to be processed in sbuf */ - uint32_t ctx_save_cr; - uint32_t ctx_save_str; - uint32_t ctx_save_csr[38]; +typedef struct mbedtls_sha256_context { + int is224; /*!< 0 = use SHA256, 1 = use SHA224 */ + HASH_HandleTypeDef hhash; /*!< Handle of HASH HAL */ + uint8_t sbuf[ST_SHA256_BLOCK_SIZE]; /*!< Buffer to store input data until ST_SHA256_BLOCK_SIZE + is reached, or until last input data is reached */ + uint8_t sbuf_len; /*!< Number of bytes stored in sbuf */ + uint32_t ctx_save_regs[ST_SHA256_NB_HASH_REG]; } 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 - * - * \returns error code - */ -int mbedtls_sha256_starts_ret(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 - * - * \returns error code - */ -int mbedtls_sha256_update_ret(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 - * - * \returns error code - */ -int mbedtls_sha256_finish_ret(mbedtls_sha256_context *ctx, unsigned char output[32]); - -/* Internal use */ -int mbedtls_internal_sha256_process(mbedtls_sha256_context *ctx, const unsigned char data[ST_SHA256_BLOCK_SIZE]); - -#if !defined(MBEDTLS_DEPRECATED_REMOVED) -#if defined(MBEDTLS_DEPRECATED_WARNING) -#define MBEDTLS_DEPRECATED __attribute__((deprecated)) -#else -#define MBEDTLS_DEPRECATED -#endif -/** - * \brief This function starts a SHA-256 checksum calculation. - * - * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. - * - * \param ctx The SHA-256 context to initialize. - * \param is224 Determines which function to use. - *
  • 0: Use SHA-256.
  • - *
  • 1: Use SHA-224.
- */ -MBEDTLS_DEPRECATED void mbedtls_sha256_starts(mbedtls_sha256_context *ctx, - int is224); - -/** - * \brief This function feeds an input buffer into an ongoing - * SHA-256 checksum calculation. - * - * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. - * - * \param ctx The SHA-256 context to initialize. - * \param input The buffer holding the data. - * \param ilen The length of the input data. - */ -MBEDTLS_DEPRECATED void mbedtls_sha256_update(mbedtls_sha256_context *ctx, - const unsigned char *input, - size_t ilen); - -/** - * \brief This function finishes the SHA-256 operation, and writes - * the result to the output buffer. - * - * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. - * - * \param ctx The SHA-256 context. - * \param output The SHA-224or SHA-256 checksum result. - */ -MBEDTLS_DEPRECATED void mbedtls_sha256_finish(mbedtls_sha256_context *ctx, - unsigned char output[32]); - -/** - * \brief This function processes a single data block within - * the ongoing SHA-256 computation. This function is for - * internal use only. - * - * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. - * - * \param ctx The SHA-256 context. - * \param data The buffer holding one block of data. - */ -MBEDTLS_DEPRECATED void mbedtls_sha256_process(mbedtls_sha256_context *ctx, - const unsigned char data[64]); - -#undef MBEDTLS_DEPRECATED -#endif /* !MBEDTLS_DEPRECATED_REMOVED */ - -#ifdef __cplusplus -} -#endif #endif /* MBEDTLS_SHA256_ALT */ - -#endif /* sha256_alt.h */ +#endif /* MBEDTLS_SHA256_ALT_H */ \ No newline at end of file