STM32 MBEDTLS: AES/CCM/GCM/MD5/SHA1/SHA256 ALT implementation

pull/12747/head
jeromecoutant 2020-03-30 14:30:00 +02:00
parent f62e3842ba
commit 3f42dfd47f
12 changed files with 2946 additions and 855 deletions

View File

@ -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 <string.h>
#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) */

View File

@ -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
* <em>FIPS Publication 197: Advanced Encryption Standard</em> and
* <em>ISO/IEC 18033-2:2006: Information technology -- Security
* techniques -- Encryption algorithms -- Part 2: Asymmetric
* ciphers</em>.
*
* The AES-XTS block mode is standardized by NIST SP 800-38E
* <https://nvlpubs.nist.gov/nistpubs/legacy/sp/nistspecialpublication800-38e.pdf>
* and described in detail by IEEE P1619
* <https://ieeexplore.ieee.org/servlet/opac?punumber=4375278>.
*/
/*
* 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 */

View File

@ -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 <string.h>
#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*/

View File

@ -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:
* <ul><li>Payload - data that is both authenticated and encrypted.</li>
* <li>Associated data (Adata) - data that is authenticated but not
* encrypted, For example, a header.</li>
* <li>Nonce - A unique value that is assigned to the payload and the
* associated data.</li></ul>
*
* 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 */

View File

@ -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 <string.h>
#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*/

View File

@ -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 <em>D. McGrew, J. Viega, The Galois/Counter Mode of Operation
* (GCM), Natl. Inst. Stand. Technol.</em>
*
* For more information on GCM, see <em>NIST SP 800-38D: Recommendation for
* Block Cipher Modes of Operation: Galois/Counter Mode (GCM) and GMAC</em>.
*
*/
/*
* 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 */

View File

@ -1,7 +1,6 @@
/* /*
* MD5 hw acceleration * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
******************************************************************************* * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved
* Copyright (c) 2017, STMicroelectronics
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * 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 * See the License for the specific language governing permissions and
* limitations under the License. * 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" #include "mbedtls/md5.h"
#if defined(MBEDTLS_MD5_C) #if defined(MBEDTLS_MD5_C)
#if defined(MBEDTLS_MD5_ALT) #if defined(MBEDTLS_MD5_ALT)
#include <string.h>
#include "mbedtls/platform.h" #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) /* Private typedef -----------------------------------------------------------*/
{ /* Private define ------------------------------------------------------------*/
uint32_t i; /* Private macro -------------------------------------------------------------*/
uint32_t tickstart; #define MD5_VALIDATE_RET(cond) \
/* allow multi-instance of HASH use: save context for HASH HW module CR */ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_MD5_BAD_INPUT_DATA )
/* Check that there is no HASH activity on going */ #define MD5_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
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;
}
static int st_md5_save_hw_context(mbedtls_md5_context *ctx) /* Private variables ---------------------------------------------------------*/
{ /* Private function prototypes -----------------------------------------------*/
uint32_t i; /* Private functions ---------------------------------------------------------*/
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;
}
void mbedtls_md5_init(mbedtls_md5_context *ctx) void mbedtls_md5_init(mbedtls_md5_context *ctx)
{ {
mbedtls_zeroize(ctx, sizeof(mbedtls_md5_context)); MD5_VALIDATE(ctx != NULL);
/* Enable HASH clock */ __disable_irq();
__HAL_RCC_HASH_CLK_ENABLE(); #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) void mbedtls_md5_free(mbedtls_md5_context *ctx)
@ -86,124 +68,222 @@ void mbedtls_md5_free(mbedtls_md5_context *ctx)
if (ctx == NULL) { if (ctx == NULL) {
return; 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, void mbedtls_md5_clone(mbedtls_md5_context *dst,
const mbedtls_md5_context *src) const mbedtls_md5_context *src)
{ {
MD5_VALIDATE(dst != NULL);
MD5_VALIDATE(src != NULL);
*dst = *src; *dst = *src;
} }
int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx) int mbedtls_md5_starts_ret(mbedtls_md5_context *ctx)
{ {
/* HASH IP initialization */ int ret = 0;
if (HAL_HASH_DeInit(&ctx->hhash_md5) != 0) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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 */ /* HASH Configuration */
ctx->hhash_md5.Init.DataType = HASH_DATATYPE_8B; if (HAL_HASH_DeInit(&ctx->hhash) != HAL_OK) {
/* clear CR ALGO value */ ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
HASH->CR &= ~HASH_CR_ALGO_Msk; goto exit;
if (HAL_HASH_Init(&ctx->hhash_md5) != 0) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
} }
if (st_md5_save_hw_context(ctx) != 1) { ctx->hhash.Init.DataType = HASH_DATATYPE_8B;
// Return HASH_BUSY timeout error here if (HAL_HASH_Init(&ctx->hhash) != HAL_OK) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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) { int ret = 0;
// Return HASH_BUSY timeout error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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) { #endif /* MBEDTLS_THREADING_C */
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
/* 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 /* save hw context */
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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; 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;
}
// store mechanism to accumulate ST_MD5_BLOCK_SIZE bytes (512 bits) in the HW 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)) { if (currentlen < (ST_MD5_BLOCK_SIZE - ctx->sbuf_len)) {
// only buffurize /* only store input data in context buffer */
memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen); memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen);
ctx->sbuf_len += currentlen; ctx->sbuf_len += currentlen;
} else { } else {
// fill buffer and process it /* 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)); memcpy(ctx->sbuf + ctx->sbuf_len,
input,
(ST_MD5_BLOCK_SIZE - ctx->sbuf_len));
currentlen -= (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) { if (HAL_HASH_MD5_Accmlt(&ctx->hhash,
return err; (uint8_t *)(ctx->sbuf),
ST_MD5_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_MD5_BLOCK_SIZE bytes */
size_t iter = currentlen / ST_MD5_BLOCK_SIZE; size_t iter = currentlen / ST_MD5_BLOCK_SIZE;
if (iter != 0) { 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) { if (HAL_HASH_MD5_Accmlt(&ctx->hhash,
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; (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;
} }
} }
// sbuf is completely accumulated, now copy up to 63 remaining bytes
/* Store only the remaining input data
up to (ST_MD5_BLOCK_SIZE - 1) bytes */
ctx->sbuf_len = currentlen % ST_MD5_BLOCK_SIZE; ctx->sbuf_len = currentlen % ST_MD5_BLOCK_SIZE;
if (ctx->sbuf_len != 0) { if (ctx->sbuf_len != 0) {
memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len); memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len);
} }
} }
if (st_md5_save_hw_context(ctx) != 1) { /* save hw context */
// Return HASH_BUSY timeout error here HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs);
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;
} }
} #endif /* MBEDTLS_THREADING_C */
return 0;
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) { int ret = 0;
// Return HASH_BUSY timeout error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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 */ #endif /* MBEDTLS_THREADING_C */
/* 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) { /* restore hw context */
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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; ctx->sbuf_len = 0;
__HAL_HASH_START_DIGEST();
if (HAL_HASH_MD5_Finish(&ctx->hhash_md5, output, 10)) { exit :
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; /* 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) { #endif /* MBEDTLS_THREADING_C */
// Return HASH_BUSY timeout error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; return (ret);
}
return 0;
} }
#endif /* MBEDTLS_MD5_ALT */ #endif /* MBEDTLS_MD5_ALT*/
#endif /* MBEDTLS_MD5_C */ #endif /* MBEDTLS_MD5_C */

View File

@ -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 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * 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 * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* This file implements STMicroelectronics MD5 API with HW services based
* on mbed TLS API
*/ */
#ifndef MBEDTLS_MD5_ALT_H #ifndef MBEDTLS_MD5_ALT_H
#define 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" #ifndef MBEDTLS_ERR_MD5_BAD_INPUT_DATA
#include <string.h> #define MBEDTLS_ERR_MD5_BAD_INPUT_DATA -0x00AF
#ifdef __cplusplus
extern "C" {
#endif #endif
#define ST_MD5_BLOCK_SIZE ((size_t)(64)) // HW handles 512 bits, ie 64 bytes #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_NB_HASH_REG ((uint32_t)57) /*!< Number of HASH HW context Registers:
CR + STR + IMR + CSR[54] */
/** /**
* \brief MD5 context structure * \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 * STMicroelectronics edition
* 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
*/ */
typedef struct { typedef struct mbedtls_md5_context {
HASH_HandleTypeDef hhash_md5;/*!< ST HAL HASH struct */ HASH_HandleTypeDef hhash; /*!< Handle of HASH HAL */
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 */ uint8_t sbuf[ST_MD5_BLOCK_SIZE]; /*!< Buffer to store input data until ST_MD5_BLOCK_SIZE
unsigned char sbuf_len; /*!< number of bytes to be processed in sbuf */ is reached, or until last input data is reached */
uint32_t ctx_save_cr; uint8_t sbuf_len; /*!< Number of bytes stored in sbuf */
uint32_t ctx_save_str; uint32_t ctx_save_regs[ST_MD5_NB_HASH_REG];
uint32_t ctx_save_csr[38];
} }
mbedtls_md5_context; 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 /* MBEDTLS_MD5_ALT */
#endif /* md5_alt.h */ #endif /* MBEDTLS_MD5_ALT_H */

View File

@ -1,7 +1,6 @@
/* /*
* sha1_alt.c for SHA1 HASH * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
******************************************************************************* * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved
* Copyright (c) 2017, STMicroelectronics
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * 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 * See the License for the specific language governing permissions and
* limitations under the License. * 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" #include "mbedtls/sha1.h"
#if defined(MBEDTLS_SHA1_C)
#if defined(MBEDTLS_SHA1_ALT) #if defined(MBEDTLS_SHA1_ALT)
#include <string.h>
#include "mbedtls/platform.h" #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) /* Private typedef -----------------------------------------------------------*/
{ /* Private define ------------------------------------------------------------*/
uint32_t i; /* Private macro -------------------------------------------------------------*/
uint32_t tickstart; #define SHA1_VALIDATE_RET(cond) \
/* allow multi-instance of HASH use: save context for HASH HW module CR */ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA1_BAD_INPUT_DATA )
/* Check that there is no HASH activity on going */ #define SHA1_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
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;
}
static int st_sha1_save_hw_context(mbedtls_sha1_context *ctx) /* Private variables ---------------------------------------------------------*/
{ /* Private function prototypes -----------------------------------------------*/
uint32_t i; /* Private functions ---------------------------------------------------------*/
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;
}
void mbedtls_sha1_init(mbedtls_sha1_context *ctx) void mbedtls_sha1_init(mbedtls_sha1_context *ctx)
{ {
mbedtls_zeroize(ctx, sizeof(mbedtls_sha1_context)); SHA1_VALIDATE(ctx != NULL);
/* Enable HASH clock */ __disable_irq();
__HAL_RCC_HASH_CLK_ENABLE(); #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) void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
@ -84,124 +68,223 @@ void mbedtls_sha1_free(mbedtls_sha1_context *ctx)
if (ctx == NULL) { if (ctx == NULL) {
return; 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, void mbedtls_sha1_clone(mbedtls_sha1_context *dst,
const mbedtls_sha1_context *src) const mbedtls_sha1_context *src)
{ {
SHA1_VALIDATE(dst != NULL);
SHA1_VALIDATE(src != NULL);
*dst = *src; *dst = *src;
} }
int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx) int mbedtls_sha1_starts_ret(mbedtls_sha1_context *ctx)
{ {
/* Deinitializes the HASH peripheral */ int ret = 0;
if (HAL_HASH_DeInit(&ctx->hhash_sha1) == HAL_ERROR) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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 */ /* HASH Configuration */
ctx->hhash_sha1.Init.DataType = HASH_DATATYPE_8B; if (HAL_HASH_DeInit(&ctx->hhash) != HAL_OK) {
/* clear CR ALGO value */ ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
HASH->CR &= ~HASH_CR_ALGO_Msk; goto exit;
if (HAL_HASH_Init(&ctx->hhash_sha1) == HAL_ERROR) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
} }
if (st_sha1_save_hw_context(ctx) != 1) { ctx->hhash.Init.DataType = HASH_DATATYPE_8B;
// return HASH_BUSY timeout Error here if (HAL_HASH_Init(&ctx->hhash) != HAL_OK) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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) { int ret = 0;
// return HASH_BUSY timeout Error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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) { #endif /* MBEDTLS_THREADING_C */
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
/* 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) { /* save hw context */
// return HASH_BUSY timeout Error here HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs);
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;
} }
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; 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 SHA1_VALIDATE_RET(ctx != NULL);
if (currentlen == 0) { // only change HW status is size if 0 SHA1_VALIDATE_RET(ilen == 0 || input != NULL);
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 #if defined(MBEDTLS_THREADING_C)
the message digest of a new message */ if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) {
HASH->CR |= HASH_ALGOSELECTION_SHA1 | HASH_CR_INIT; return (ret);
} }
ctx->hhash_sha1.Phase = HAL_HASH_PHASE_PROCESS; #endif /* MBEDTLS_THREADING_C */
} else if (currentlen < (ST_SHA1_BLOCK_SIZE - ctx->sbuf_len)) {
// only buffurize /* 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); memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen);
ctx->sbuf_len += currentlen; ctx->sbuf_len += currentlen;
} else { } else {
// fill buffer and process it /* 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)); memcpy(ctx->sbuf + ctx->sbuf_len,
input,
(ST_SHA1_BLOCK_SIZE - ctx->sbuf_len));
currentlen -= (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) { if (HAL_HASH_SHA1_Accmlt(&ctx->hhash,
return err; (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; 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) { if (iter != 0) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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; ctx->sbuf_len = currentlen % ST_SHA1_BLOCK_SIZE;
if (ctx->sbuf_len != 0) { if (ctx->sbuf_len != 0) {
memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len); 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 /* save hw context */
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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) { int ret = 0;
// return HASH_BUSY timeout Error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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; ctx->sbuf_len = 0;
__HAL_HASH_START_DIGEST();
if (HAL_HASH_SHA1_Finish(&ctx->hhash_sha1, output, 10) != 0) { exit :
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; /* 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) { #endif /* MBEDTLS_THREADING_C */
// return HASH_BUSY timeout Error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; return (ret);
}
return 0;
} }
#endif /*MBEDTLS_SHA1_ALT*/ #endif /* MBEDTLS_SHA1_ALT*/
#endif /* MBEDTLS_SHA1_C */

View File

@ -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
* <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
*
* \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 * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved
* * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved
* \brief SHA1 hw acceleration (hash function)
*
* Copyright (C) 2017, STMicroelectronics
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * 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 * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* This file implements STMicroelectronics SHA1 API with HW services based
* on mbed TLS API
*/ */
#ifndef MBEDTLS_SHA1_ALT_H #ifndef MBEDTLS_SHA1_ALT_H
#define MBEDTLS_SHA1_ALT_H #define MBEDTLS_SHA1_ALT_H
#if defined (MBEDTLS_SHA1_ALT) #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 <string.h>
#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 * \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
*/ */
typedef struct { typedef struct mbedtls_sha1_context {
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 */ HASH_HandleTypeDef hhash; /*!< Handle of HASH HAL */
unsigned char sbuf_len; /*!< number of bytes remaining in sbuf to be processed */ uint8_t sbuf[ST_SHA1_BLOCK_SIZE]; /*!< Buffer to store input data until ST_SHA1_BLOCK_SIZE
HASH_HandleTypeDef hhash_sha1; /*!< ST HAL HASH struct */ is reached, or until last input data is reached */
uint32_t ctx_save_cr; uint8_t sbuf_len; /*!< Number of bytes stored in sbuf */
uint32_t ctx_save_str; uint32_t ctx_save_regs[ST_SHA1_NB_HASH_REG];
uint32_t ctx_save_csr[38];
} }
mbedtls_sha1_context; 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 /* MBEDTLS_SHA1_ALT */
#endif /* sha1_alt.h */ #endif /* MBEDTLS_SHA1_ALT_H */

View File

@ -1,7 +1,6 @@
/* /*
* sha256_alt.c for SHA256 HASH * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved
******************************************************************************* * Copyright (C) 2019-2020, STMicroelectronics, All Rights Reserved
* Copyright (c) 2017, STMicroelectronics
* SPDX-License-Identifier: Apache-2.0 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * 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 * See the License for the specific language governing permissions and
* limitations under the License. * 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" #include "mbedtls/sha256.h"
#if defined(MBEDTLS_SHA256_C)
#if defined(MBEDTLS_SHA256_ALT) #if defined(MBEDTLS_SHA256_ALT)
#include <string.h>
#include "mbedtls/platform.h" #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) /* Private typedef -----------------------------------------------------------*/
{ /* Private define ------------------------------------------------------------*/
uint32_t i; /* Private macro -------------------------------------------------------------*/
uint32_t tickstart; #define SHA256_VALIDATE_RET(cond) \
/* allow multi-instance of HASH use: save context for HASH HW module CR */ MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA )
/* Check that there is no HASH activity on going */ #define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
tickstart = HAL_GetTick();
while ((HASH->SR & (HASH_FLAG_BUSY | HASH_FLAG_DMAS)) != 0) { /* Private variables ---------------------------------------------------------*/
if ((HAL_GetTick() - tickstart) > ST_SHA256_TIMEOUT) { /* Private function prototypes -----------------------------------------------*/
return 0; // timeout: HASH processor is busy /* Private functions ---------------------------------------------------------*/
}
}
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;
}
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) void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
{ {
mbedtls_zeroize(ctx, sizeof(mbedtls_sha256_context)); SHA256_VALIDATE(ctx != NULL);
/* Enable HASH clock */ __disable_irq();
__HAL_RCC_HASH_CLK_ENABLE(); #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) void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
@ -84,156 +69,264 @@ void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
if (ctx == NULL) { if (ctx == NULL) {
return; 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, void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
const mbedtls_sha256_context *src) const mbedtls_sha256_context *src)
{ {
SHA256_VALIDATE(dst != NULL);
SHA256_VALIDATE(src != NULL);
*dst = *src; *dst = *src;
} }
int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224) int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224)
{ {
/* HASH IP initialization */ int ret = 0;
if (HAL_HASH_DeInit(&ctx->hhash_sha256) == HAL_ERROR) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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; ctx->is224 = is224;
/* HASH Configuration */
ctx->hhash_sha256.Init.DataType = HASH_DATATYPE_8B; /* save hw context */
/* clear CR ALGO value */ HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs);
HASH->CR &= ~HASH_CR_ALGO_Msk;
if (HAL_HASH_Init(&ctx->hhash_sha256) == HAL_ERROR) { exit :
// error found to be returned /* Free context access */
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; #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) { #endif /* MBEDTLS_THREADING_C */
// return HASH_BUSY timeout Error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; return (ret);
}
return 0;
} }
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) { int ret = 0;
// Return HASH_BUSY timeout error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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 (ctx->is224 == 0) {
if (HAL_HASHEx_SHA256_Accumulate(&ctx->hhash_sha256, (uint8_t *) data, ST_SHA256_BLOCK_SIZE) != 0) { if (HAL_HASHEx_SHA256_Accmlt(&ctx->hhash,
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; (uint8_t *) data,
ST_SHA256_BLOCK_SIZE) != 0) {
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
goto exit;
} }
} else { } else {
if (HAL_HASHEx_SHA224_Accumulate(&ctx->hhash_sha256, (uint8_t *) data, ST_SHA256_BLOCK_SIZE) != 0) { if (HAL_HASHEx_SHA224_Accmlt(&ctx->hhash,
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; (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) { /* save hw context */
// Return HASH_BUSY timeout error here HAL_HASH_ContextSaving(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs);
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;
} }
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; 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 SHA256_VALIDATE_RET(ctx != NULL);
if (currentlen == 0) { // only change HW status is size if 0 SHA256_VALIDATE_RET(ilen == 0 || input != NULL);
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 #if defined(MBEDTLS_THREADING_C)
the message digest of a new message */ if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) {
if (ctx->is224 == 0) { return (ret);
HASH->CR |= HASH_ALGOSELECTION_SHA256 | HASH_CR_INIT;
} else {
HASH->CR |= HASH_ALGOSELECTION_SHA224 | HASH_CR_INIT;
} }
} #endif /* MBEDTLS_THREADING_C */
ctx->hhash_sha256.Phase = HAL_HASH_PHASE_PROCESS;
} else if (currentlen < (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len)) { /* restore hw context */
// only buffurize 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); memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen);
ctx->sbuf_len += currentlen; ctx->sbuf_len += currentlen;
} else { } else {
// fill buffer and process it /* 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)); memcpy(ctx->sbuf + ctx->sbuf_len,
input,
(ST_SHA256_BLOCK_SIZE - ctx->sbuf_len));
currentlen -= (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) { if (ctx->is224 == 0) {
return err; 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;
} }
// Process every input as long as it is %64 bytes, ie 512 bits } 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 following input data
with size multiple of ST_SHA256_BLOCK_SIZE bytes */
size_t iter = currentlen / ST_SHA256_BLOCK_SIZE; size_t iter = currentlen / ST_SHA256_BLOCK_SIZE;
if (iter != 0) { if (iter != 0) {
if (ctx->is224 == 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) { if (HAL_HASHEx_SHA256_Accmlt(&ctx->hhash,
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; (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 { } 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) { if (HAL_HASHEx_SHA224_Accmlt(&ctx->hhash,
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; (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; ctx->sbuf_len = currentlen % ST_SHA256_BLOCK_SIZE;
if (ctx->sbuf_len != 0) { if (ctx->sbuf_len != 0) {
memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len); 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 /* save hw context */
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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) { int ret = 0;
// Return HASH_BUSY timeout error here
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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 */ #endif /* MBEDTLS_THREADING_C */
/* This allows the HW flags to be in place in case mbedtls_sha256_update has not been called yet */
/* 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 (ctx->is224 == 0) {
if (HAL_HASHEx_SHA256_Accumulate(&ctx->hhash_sha256, ctx->sbuf, ctx->sbuf_len) != 0) { if (HAL_HASHEx_SHA256_Accmlt_End(&ctx->hhash,
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; ctx->sbuf,
ctx->sbuf_len,
output,
ST_HASH_TIMEOUT) != 0) {
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
goto exit;
} }
} else { } else {
if (HAL_HASHEx_SHA224_Accumulate(&ctx->hhash_sha256, ctx->sbuf, ctx->sbuf_len) != 0) { if (HAL_HASHEx_SHA224_Accmlt_End(&ctx->hhash,
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; 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; ctx->sbuf_len = 0;
__HAL_HASH_START_DIGEST();
if (ctx->is224 == 0) { exit :
if (HAL_HASHEx_SHA256_Finish(&ctx->hhash_sha256, output, 10) != 0) { /* Free context access */
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; #if defined(MBEDTLS_THREADING_C)
if (mbedtls_mutex_unlock(&hash_mutex) != 0) {
ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR;
} }
} else { #endif /* MBEDTLS_THREADING_C */
if (HAL_HASHEx_SHA224_Finish(&ctx->hhash_sha256, output, 10) != 0) {
return MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED; return (ret);
}
}
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_SHA256_ALT*/ #endif /* MBEDTLS_SHA256_ALT*/
#endif /* MBEDTLS_SHA256_C */

View File

@ -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 <em>FIPS 180-4: Secure Hash Standard (SHS)</em>.
*/
/*
* 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 * SPDX-License-Identifier: Apache-2.0
* *
* Licensed under the Apache License, Version 2.0 (the "License"); you may * 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 * See the License for the specific language governing permissions and
* limitations under the License. * limitations under the License.
* *
* This file implements STMicroelectronics SHA256 API with HW services based
* on mbed TLS API
*/ */
#ifndef MBEDTLS_SHA256_ALT_H #ifndef MBEDTLS_SHA256_ALT_H
#define MBEDTLS_SHA256_ALT_H #define MBEDTLS_SHA256_ALT_H
#if defined (MBEDTLS_SHA256_ALT) #if defined (MBEDTLS_SHA256_ALT)
/* Includes ------------------------------------------------------------------*/
#include "hash_stm32.h"
#include "cmsis.h" #define ST_SHA256_BLOCK_SIZE ((size_t) 64) /*!< HW handles 512 bits, ie 64 bytes */
#include <string.h> #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 * \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 * The structure is used both for SHA-256 and for SHA-224
* ST_SHA256_BLOCK_SIZE bytes per ST_SHA256_BLOCK_SIZE bytes * checksum calculations. The choice between these two is
* If sha256_finish is called and sbuf_len>0, the remaining bytes are accumulated prior to the call to HAL_HASH_SHA256_Finish * made in the call to mbedtls_sha256_starts_ret().
*/ */
typedef struct { typedef struct mbedtls_sha256_context {
int is224; /*!< 0 => SHA-256, else SHA-224 */ int is224; /*!< 0 = use SHA256, 1 = use SHA224 */
HASH_HandleTypeDef hhash_sha256; HASH_HandleTypeDef hhash; /*!< Handle of HASH HAL */
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 */ uint8_t sbuf[ST_SHA256_BLOCK_SIZE]; /*!< Buffer to store input data until ST_SHA256_BLOCK_SIZE
unsigned char sbuf_len; /*!< number of bytes to be processed in sbuf */ is reached, or until last input data is reached */
uint32_t ctx_save_cr; uint8_t sbuf_len; /*!< Number of bytes stored in sbuf */
uint32_t ctx_save_str; uint32_t ctx_save_regs[ST_SHA256_NB_HASH_REG];
uint32_t ctx_save_csr[38];
} }
mbedtls_sha256_context; 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.
* <ul><li>0: Use SHA-256.</li>
* <li>1: Use SHA-224.</li></ul>
*/
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 /* MBEDTLS_SHA256_ALT */
#endif /* MBEDTLS_SHA256_ALT_H */
#endif /* sha256_alt.h */