mirror of https://github.com/ARMmbed/mbed-os.git
323 lines
10 KiB
C++
323 lines
10 KiB
C++
/*
|
|
* 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 STMicroelectronics SHA256 with HW services based on API
|
|
* from mbed TLS
|
|
*/
|
|
/*
|
|
* The SHA-256 Secure Hash Standard was published by NIST in 2002.
|
|
*
|
|
* http://csrc.nist.gov/publications/fips/fips180-2/fips180-2.pdf
|
|
*/
|
|
|
|
/* Includes ------------------------------------------------------------------*/
|
|
#include "mbedtls/sha256.h"
|
|
|
|
#if defined(MBEDTLS_SHA256_C)
|
|
#if defined(MBEDTLS_SHA256_ALT)
|
|
#include <string.h>
|
|
#include "mbedtls/platform.h"
|
|
#include "mbedtls/platform_util.h"
|
|
|
|
#include "platform/PlatformMutex.h"
|
|
#include "platform/SingletonPtr.h"
|
|
|
|
static SingletonPtr<PlatformMutex> sha256_mutex;
|
|
|
|
/* Private typedef -----------------------------------------------------------*/
|
|
/* Private define ------------------------------------------------------------*/
|
|
/* Private macro -------------------------------------------------------------*/
|
|
#define SHA256_VALIDATE_RET(cond) \
|
|
MBEDTLS_INTERNAL_VALIDATE_RET( cond, MBEDTLS_ERR_SHA256_BAD_INPUT_DATA )
|
|
#define SHA256_VALIDATE(cond) MBEDTLS_INTERNAL_VALIDATE( cond )
|
|
|
|
/* Private variables ---------------------------------------------------------*/
|
|
/* Private function prototypes -----------------------------------------------*/
|
|
/* Private functions ---------------------------------------------------------*/
|
|
|
|
|
|
void mbedtls_sha256_init(mbedtls_sha256_context *ctx)
|
|
{
|
|
SHA256_VALIDATE(ctx != NULL);
|
|
|
|
sha256_mutex->lock();
|
|
hash_context_count++;
|
|
sha256_mutex->unlock();
|
|
|
|
hash_zeroize(ctx, sizeof(mbedtls_sha256_context));
|
|
}
|
|
|
|
void mbedtls_sha256_free(mbedtls_sha256_context *ctx)
|
|
{
|
|
if (ctx == NULL) {
|
|
return;
|
|
}
|
|
|
|
sha256_mutex->lock();
|
|
if (hash_context_count > 0) {
|
|
hash_context_count--;
|
|
|
|
/* Shut down HASH on last context */
|
|
if (hash_context_count == 0) {
|
|
HAL_HASH_DeInit(&ctx->hhash);
|
|
}
|
|
}
|
|
sha256_mutex->unlock();
|
|
|
|
hash_zeroize(ctx, sizeof(mbedtls_sha256_context));
|
|
}
|
|
|
|
void mbedtls_sha256_clone(mbedtls_sha256_context *dst,
|
|
const mbedtls_sha256_context *src)
|
|
{
|
|
SHA256_VALIDATE(dst != NULL);
|
|
SHA256_VALIDATE(src != NULL);
|
|
|
|
*dst = *src;
|
|
}
|
|
|
|
int mbedtls_sha256_starts_ret(mbedtls_sha256_context *ctx, int is224)
|
|
{
|
|
int ret = 0;
|
|
|
|
SHA256_VALIDATE_RET(ctx != NULL);
|
|
SHA256_VALIDATE_RET(is224 == 0 || is224 == 1);
|
|
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) {
|
|
return (ret);
|
|
}
|
|
#endif /* MBEDTLS_THREADING_C */
|
|
|
|
/* HASH Configuration */
|
|
if (HAL_HASH_DeInit(&ctx->hhash) != HAL_OK) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
ctx->hhash.Init.DataType = HASH_DATATYPE_8B;
|
|
if (HAL_HASH_Init(&ctx->hhash) != HAL_OK) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
|
|
ctx->is224 = is224;
|
|
|
|
/* 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_sha256_process(mbedtls_sha256_context *ctx,
|
|
const unsigned char data[ST_SHA256_BLOCK_SIZE])
|
|
{
|
|
int ret = 0;
|
|
|
|
SHA256_VALIDATE_RET(ctx != NULL);
|
|
SHA256_VALIDATE_RET((const unsigned char *)data != NULL);
|
|
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) {
|
|
return (ret);
|
|
}
|
|
#endif /* MBEDTLS_THREADING_C */
|
|
|
|
/* restore hw context */
|
|
HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs);
|
|
|
|
if (ctx->is224 == 0) {
|
|
if (HAL_HASHEx_SHA256_Accmlt(&ctx->hhash,
|
|
(uint8_t *) data,
|
|
ST_SHA256_BLOCK_SIZE) != 0) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
} else {
|
|
if (HAL_HASHEx_SHA224_Accmlt(&ctx->hhash,
|
|
(uint8_t *) data,
|
|
ST_SHA256_BLOCK_SIZE) != 0) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
/* 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_sha256_update_ret(mbedtls_sha256_context *ctx,
|
|
const unsigned char *input,
|
|
size_t ilen)
|
|
{
|
|
int ret = 0;
|
|
size_t currentlen = ilen;
|
|
|
|
SHA256_VALIDATE_RET(ctx != NULL);
|
|
SHA256_VALIDATE_RET(ilen == 0 || input != NULL);
|
|
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) {
|
|
return (ret);
|
|
}
|
|
#endif /* MBEDTLS_THREADING_C */
|
|
|
|
/* restore hw context */
|
|
HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs);
|
|
|
|
if (currentlen < (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len)) {
|
|
/* only store input data in context buffer */
|
|
memcpy(ctx->sbuf + ctx->sbuf_len, input, currentlen);
|
|
ctx->sbuf_len += currentlen;
|
|
} else {
|
|
/* fill context buffer until ST_SHA256_BLOCK_SIZE bytes, and process it */
|
|
memcpy(ctx->sbuf + ctx->sbuf_len,
|
|
input,
|
|
(ST_SHA256_BLOCK_SIZE - ctx->sbuf_len));
|
|
currentlen -= (ST_SHA256_BLOCK_SIZE - ctx->sbuf_len);
|
|
|
|
if (ctx->is224 == 0) {
|
|
if (HAL_HASHEx_SHA256_Accmlt(&ctx->hhash,
|
|
(uint8_t *)(ctx->sbuf),
|
|
ST_SHA256_BLOCK_SIZE) != 0) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
} else {
|
|
if (HAL_HASHEx_SHA224_Accmlt(&ctx->hhash,
|
|
(uint8_t *)(ctx->sbuf),
|
|
ST_SHA256_BLOCK_SIZE) != 0) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
/* Process following input data
|
|
with size multiple of ST_SHA256_BLOCK_SIZE bytes */
|
|
size_t iter = currentlen / ST_SHA256_BLOCK_SIZE;
|
|
if (iter != 0) {
|
|
if (ctx->is224 == 0) {
|
|
if (HAL_HASHEx_SHA256_Accmlt(&ctx->hhash,
|
|
(uint8_t *)(input + ST_SHA256_BLOCK_SIZE - ctx->sbuf_len),
|
|
(iter * ST_SHA256_BLOCK_SIZE)) != 0) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
} else {
|
|
if (HAL_HASHEx_SHA224_Accmlt(&ctx->hhash,
|
|
(uint8_t *)(input + ST_SHA256_BLOCK_SIZE - ctx->sbuf_len),
|
|
(iter * ST_SHA256_BLOCK_SIZE)) != 0) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
}
|
|
}
|
|
|
|
/* Store only the remaining input data
|
|
up to (ST_SHA256_BLOCK_SIZE - 1) bytes */
|
|
ctx->sbuf_len = currentlen % ST_SHA256_BLOCK_SIZE;
|
|
if (ctx->sbuf_len != 0) {
|
|
memcpy(ctx->sbuf, input + ilen - ctx->sbuf_len, ctx->sbuf_len);
|
|
}
|
|
}
|
|
|
|
/* 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_sha256_finish_ret(mbedtls_sha256_context *ctx,
|
|
unsigned char output[32])
|
|
{
|
|
int ret = 0;
|
|
|
|
SHA256_VALIDATE_RET(ctx != NULL);
|
|
SHA256_VALIDATE_RET((unsigned char *)output != NULL);
|
|
|
|
#if defined(MBEDTLS_THREADING_C)
|
|
if ((ret = mbedtls_mutex_lock(&hash_mutex)) != 0) {
|
|
return (ret);
|
|
}
|
|
#endif /* MBEDTLS_THREADING_C */
|
|
|
|
/* restore hw context */
|
|
HAL_HASH_ContextRestoring(&ctx->hhash, (uint8_t *)ctx->ctx_save_regs);
|
|
|
|
/* Last accumulation for pending bytes in sbuf_len,
|
|
then trig processing and get digest */
|
|
if (ctx->is224 == 0) {
|
|
if (HAL_HASHEx_SHA256_Accmlt_End(&ctx->hhash,
|
|
ctx->sbuf,
|
|
ctx->sbuf_len,
|
|
output,
|
|
ST_HASH_TIMEOUT) != 0) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
} else {
|
|
if (HAL_HASHEx_SHA224_Accmlt_End(&ctx->hhash,
|
|
ctx->sbuf,
|
|
ctx->sbuf_len,
|
|
output,
|
|
ST_HASH_TIMEOUT) != 0) {
|
|
ret = MBEDTLS_ERR_PLATFORM_HW_ACCEL_FAILED;
|
|
goto exit;
|
|
}
|
|
}
|
|
|
|
ctx->sbuf_len = 0;
|
|
|
|
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);
|
|
}
|
|
|
|
#endif /* MBEDTLS_SHA256_ALT*/
|
|
#endif /* MBEDTLS_SHA256_C */
|