#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <wolfssl/wolfcrypt/settings.h>
#if defined(WOLFSSL_HAVE_PSA) && !defined(WOLFSSL_PSA_NO_HASH)
#if !defined(NO_SHA)
#include <wolfssl/wolfcrypt/sha.h>
#endif
#if !defined(NO_SHA256)
#include <wolfssl/wolfcrypt/sha256.h>
#endif
#include <wolfssl/wolfcrypt/error-crypt.h>
#include <wolfssl/wolfcrypt/port/psa/psa.h>
#if !defined(NO_SHA) || !defined(NO_SHA256) || defined(WOLFSSL_SHA224)
static int wc_psa_hash_init_and_setup(psa_hash_operation_t *ctx,
psa_algorithm_t alg)
{
psa_status_t s;
if (ctx == NULL)
return BAD_FUNC_ARG;
XMEMSET(ctx, 0, sizeof(*ctx));
PSA_LOCK();
s = psa_hash_setup(ctx, alg);
PSA_UNLOCK();
if (s != PSA_SUCCESS) {
PSA_LOCK();
psa_hash_abort(ctx);
PSA_UNLOCK();
return WC_HW_E;
}
return 0;
}
static int wc_psa_hash_update(psa_hash_operation_t *ctx, const uint8_t *input,
size_t input_length)
{
psa_status_t s;
if (ctx == NULL || (input == NULL && input_length > 0))
return BAD_FUNC_ARG;
PSA_LOCK();
s = psa_hash_update(ctx, input, input_length);
PSA_UNLOCK();
if (s != PSA_SUCCESS) {
PSA_LOCK();
psa_hash_abort(ctx);
PSA_UNLOCK();
return WC_HW_E;
}
return 0;
}
static int wc_psa_hash_finish_setup(psa_hash_operation_t *ctx,
uint8_t *output, psa_algorithm_t alg)
{
size_t hash_length;
psa_status_t s;
if (ctx == NULL || output == NULL)
return BAD_FUNC_ARG;
PSA_LOCK();
s = psa_hash_finish(ctx, output, PSA_HASH_LENGTH(alg), &hash_length);
PSA_UNLOCK();
if (s != PSA_SUCCESS) {
PSA_LOCK();
psa_hash_abort(ctx);
PSA_UNLOCK();
return WC_HW_E;
}
PSA_LOCK();
s = psa_hash_setup(ctx, alg);
PSA_UNLOCK();
if (s != PSA_SUCCESS) {
PSA_LOCK();
psa_hash_abort(ctx);
PSA_UNLOCK();
return WC_HW_E;
}
return 0;
}
static int wc_psa_hash_clone(const psa_hash_operation_t *src,
psa_hash_operation_t *dst)
{
psa_status_t s;
if (src == NULL || dst == NULL)
return BAD_FUNC_ARG;
PSA_LOCK();
s = psa_hash_abort(dst);
PSA_UNLOCK();
if (s != PSA_SUCCESS)
return WC_HW_E;
PSA_LOCK();
s = psa_hash_clone(src, dst);
PSA_UNLOCK();
if (s != PSA_SUCCESS)
return WC_HW_E;
return 0;
}
static int wc_psa_hash_abort(psa_hash_operation_t *ctx)
{
psa_status_t s;
if (ctx == NULL)
return BAD_FUNC_ARG;
PSA_LOCK();
s = psa_hash_abort(ctx);
PSA_UNLOCK();
if (s != PSA_SUCCESS)
return WC_HW_E;
return 0;
}
static int wc_psa_get_hash(psa_hash_operation_t *ctx,
uint8_t *out, psa_algorithm_t alg)
{
psa_hash_operation_t tmp;
size_t hash_length;
psa_status_t s;
(void)hash_length;
if (ctx == NULL || out == NULL)
return BAD_FUNC_ARG;
XMEMSET(&tmp, 0, sizeof(tmp));
PSA_LOCK();
s = psa_hash_clone(ctx, &tmp);
PSA_UNLOCK();
if (s != PSA_SUCCESS) {
PSA_LOCK();
psa_hash_abort(&tmp);
PSA_UNLOCK();
return WC_HW_E;
}
PSA_LOCK();
s = psa_hash_finish(&tmp, out, PSA_HASH_LENGTH(alg), &hash_length);
PSA_UNLOCK();
if (s != PSA_SUCCESS) {
PSA_LOCK();
psa_hash_abort(&tmp);
PSA_UNLOCK();
return WC_HW_E;
}
return 0;
}
#endif
#if !defined(NO_SHA)
int wc_InitSha_ex(wc_Sha *sha, void *heap, int devId)
{
(void)heap;
(void)devId;
return wc_psa_hash_init_and_setup(&sha->psa_ctx, PSA_ALG_SHA_1);
}
int wc_ShaUpdate(wc_Sha *sha, const byte *in, word32 size)
{
return wc_psa_hash_update(&sha->psa_ctx, in, size);
}
int wc_ShaFinal(wc_Sha *sha, byte *out)
{
return wc_psa_hash_finish_setup(&sha->psa_ctx, out, PSA_ALG_SHA_1);
}
int wc_ShaGetHash(wc_Sha *sha, byte *out)
{
return wc_psa_get_hash(&sha->psa_ctx, out, PSA_ALG_SHA_1);
}
int wc_ShaCopy(wc_Sha *src, wc_Sha *dst)
{
return wc_psa_hash_clone(&src->psa_ctx, &dst->psa_ctx);
}
void wc_ShaFree(wc_Sha *sha)
{
wc_psa_hash_abort(&sha->psa_ctx);
}
#endif
#if !defined(NO_SHA256)
int wc_InitSha256_ex(wc_Sha256 *sha, void *heap, int devId)
{
(void)heap;
(void)devId;
return wc_psa_hash_init_and_setup(&sha->psa_ctx, PSA_ALG_SHA_256);
}
int wc_Sha256Update(wc_Sha256 *sha, const byte *in, word32 size)
{
return wc_psa_hash_update(&sha->psa_ctx, in, size);
}
int wc_Sha256Final(wc_Sha256 *sha, byte *out)
{
return wc_psa_hash_finish_setup(&sha->psa_ctx, out, PSA_ALG_SHA_256);
}
int wc_Sha256GetHash(wc_Sha256 *sha, byte *out)
{
return wc_psa_get_hash(&sha->psa_ctx, out, PSA_ALG_SHA_256);
}
int wc_Sha256Copy(wc_Sha256 *src, wc_Sha256 *dst)
{
return wc_psa_hash_clone(&src->psa_ctx, &dst->psa_ctx);
}
void wc_Sha256Free(wc_Sha256 *sha)
{
wc_psa_hash_abort(&sha->psa_ctx);
}
#endif
#if defined(WOLFSSL_SHA224)
int wc_InitSha224_ex(wc_Sha224 *sha, void *heap, int devId)
{
(void)heap;
(void)devId;
return wc_psa_hash_init_and_setup(&sha->psa_ctx, PSA_ALG_SHA_224);
}
int wc_Sha224Update(wc_Sha224 *sha, const byte *in, word32 size)
{
return wc_psa_hash_update(&sha->psa_ctx, in, size);
}
int wc_Sha224Final(wc_Sha224 *sha, byte *out)
{
return wc_psa_hash_finish_setup(&sha->psa_ctx, out, PSA_ALG_SHA_224);
}
int wc_Sha224GetHash(wc_Sha224 *sha, byte *out)
{
return wc_psa_get_hash(&sha->psa_ctx, out, PSA_ALG_SHA_224);
}
int wc_Sha224Copy(wc_Sha224 *src, wc_Sha224 *dst)
{
return wc_psa_hash_clone(&src->psa_ctx, &dst->psa_ctx);
}
void wc_Sha224Free(wc_Sha224 *sha)
{
wc_psa_hash_abort(&sha->psa_ctx);
}
#endif
#endif