Add STM32MP13 HAL support for more SHA types

This adds STM32 HAL support for:

* SHA384
* SHA512 (with -224 and -256)
* SHA3 (all variants apart from SHAKE)

The partial FIFO block calculations have been adjusted based in the
STM32 code to support the larger hash sizes.

This should work with other chips such as the STM32U5xx, but is not
enabled for that yet.
pull/8231/head
Andrew Hutchings 2024-11-27 14:57:26 +00:00
parent e9a4f7de5f
commit f15dbb9110
6 changed files with 375 additions and 16 deletions

View File

@ -137,6 +137,9 @@ static void wc_Stm32_Hash_SaveContext(STM32_HASH_Context* ctx)
ctx->HASH_IMR = HASH->IMR;
ctx->HASH_STR = HASH->STR;
ctx->HASH_CR = HASH->CR;
#ifdef STM32_HASH_SHA3
ctx->SHA3CFGR = HASH->SHA3CFGR;
#endif
for (i=0; i<HASH_CR_SIZE; i++) {
ctx->HASH_CSR[i] = HASH->CSR[i];
}
@ -184,6 +187,9 @@ static void wc_Stm32_Hash_RestoreContext(STM32_HASH_Context* ctx, int algo)
HASH->IMR = ctx->HASH_IMR;
HASH->STR = ctx->HASH_STR;
HASH->CR = ctx->HASH_CR;
#ifdef STM32_HASH_SHA3
HASH->SHA3CFGR = ctx->SHA3CFGR;
#endif
/* Initialize the hash processor */
HASH->CR |= HASH_CR_INIT;
@ -329,11 +335,11 @@ int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo,
while (len) {
word32 add;
/* fill the FIFO plus one additional to flush the block */
chunkSz = ((STM32_HASH_FIFO_SIZE + 1) * STM32_HASH_REG_SIZE);
/* account for extra bytes in the FIFO (use mask 0x3F to get remain) */
chunkSz -= (stmCtx->fifoBytes &
((STM32_HASH_FIFO_SIZE * STM32_HASH_REG_SIZE)-1));
chunkSz = blockSize;
/* fill the FIFO plus one additional to flush the first block */
if (!stmCtx->fifoBytes) {
chunkSz += STM32_HASH_REG_SIZE;
}
add = min(len, chunkSz - stmCtx->buffLen);
XMEMCPY(&local[stmCtx->buffLen], data, add);

View File

@ -299,7 +299,7 @@ void BlockSha3(word64* s)
*/
#define ROTL64(a, n) (((a)<<(n))|((a)>>(64-(n))))
#if !defined(STM32_HASH_SHA3)
/* An array of values to XOR for block operation. */
static const word64 hash_keccak_r[24] =
{
@ -316,6 +316,7 @@ static const word64 hash_keccak_r[24] =
W64LIT(0x8000000080008081), W64LIT(0x8000000000008080),
W64LIT(0x0000000080000001), W64LIT(0x8000000080008008)
};
#endif
/* Indices used in swap and rotate operation. */
#define KI_0 6
@ -533,6 +534,7 @@ do { \
while (0)
#endif /* SHA3_BY_SPEC */
#if !defined(STM32_HASH_SHA3)
/* The block operation performed on the state.
*
* s The state.
@ -562,8 +564,10 @@ void BlockSha3(word64* s)
}
}
#endif /* WOLFSSL_SHA3_SMALL */
#endif /* STM32_HASH_SHA3 */
#endif /* !WOLFSSL_ARMASM && !WOLFSSL_RISCV_ASM */
#if !defined(STM32_HASH_SHA3)
static WC_INLINE word64 Load64Unaligned(const unsigned char *a)
{
return ((word64)a[0] << 0) |
@ -617,6 +621,7 @@ static word64 Load64BitBigEndian(const byte* a)
* sha3 wc_Sha3 object holding state.
* returns 0 on success.
*/
static int InitSha3(wc_Sha3* sha3)
{
int i;
@ -797,6 +802,84 @@ static int Sha3Final(wc_Sha3* sha3, byte padChar, byte* hash, byte p, word32 l)
return 0;
}
#endif
#if defined(STM32_HASH_SHA3)
/* Supports CubeMX HAL or Standard Peripheral Library */
static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)
{
if (sha3 == NULL)
return BAD_FUNC_ARG;
(void)devId;
(void)heap;
XMEMSET(sha3, 0, sizeof(wc_Sha3));
wc_Stm32_Hash_Init(&sha3->stmCtx);
return 0;
}
static int Stm32GetAlgo(byte p)
{
switch(p) {
case WC_SHA3_224_COUNT:
return HASH_ALGOSELECTION_SHA3_224;
case WC_SHA3_256_COUNT:
return HASH_ALGOSELECTION_SHA3_256;
case WC_SHA3_384_COUNT:
return HASH_ALGOSELECTION_SHA3_384;
case WC_SHA3_512_COUNT:
return HASH_ALGOSELECTION_SHA3_512;
}
/* Should never get here */
return WC_SHA3_224_COUNT;
}
static int wc_Sha3Update(wc_Sha3* sha3, const byte* data, word32 len, byte p)
{
int ret = 0;
if (sha3 == NULL) {
return BAD_FUNC_ARG;
}
if (data == NULL && len == 0) {
/* valid, but do nothing */
return 0;
}
if (data == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Update(&sha3->stmCtx,
Stm32GetAlgo(p), data, len, p * 8);
wolfSSL_CryptHwMutexUnLock();
}
return ret;
}
static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len)
{
int ret = 0;
if (sha3 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Final(&sha3->stmCtx,
Stm32GetAlgo(p), hash, len);
wolfSSL_CryptHwMutexUnLock();
}
(void)wc_InitSha3(sha3, NULL, 0); /* reset state */
return ret;
}
#else
/* Initialize the state for a SHA-3 hash operation.
*
@ -944,7 +1027,7 @@ static int wc_Sha3Final(wc_Sha3* sha3, byte* hash, byte p, byte len)
return InitSha3(sha3); /* reset state */
}
#endif
/* Dispose of any dynamically allocated data from the SHA3-384 operation.
* (Required for async ops.)
*

View File

@ -219,6 +219,66 @@
{
se050_hash_free(&sha512->se050Ctx);
}
#elif defined(STM32_HASH_SHA512)
/* Supports CubeMX HAL or Standard Peripheral Library */
int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId)
{
if (sha512 == NULL)
return BAD_FUNC_ARG;
(void)devId;
(void)heap;
XMEMSET(sha512, 0, sizeof(wc_Sha512));
wc_Stm32_Hash_Init(&sha512->stmCtx);
return 0;
}
int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
{
int ret = 0;
if (sha512 == NULL) {
return BAD_FUNC_ARG;
}
if (data == NULL && len == 0) {
/* valid, but do nothing */
return 0;
}
if (data == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Update(&sha512->stmCtx,
HASH_ALGOSELECTION_SHA512, data, len, WC_SHA512_BLOCK_SIZE);
wolfSSL_CryptHwMutexUnLock();
}
return ret;
}
int wc_Sha512Final(wc_Sha512* sha512, byte* hash)
{
int ret = 0;
if (sha512 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Final(&sha512->stmCtx,
HASH_ALGOSELECTION_SHA512, hash, WC_SHA512_DIGEST_SIZE);
wolfSSL_CryptHwMutexUnLock();
}
(void)wc_InitSha512(sha512); /* reset state */
return ret;
}
#else
@ -1174,7 +1234,7 @@ int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len)
#elif defined(MAX3266X_SHA)
/* Functions defined in wolfcrypt/src/port/maxim/max3266x.c */
#elif defined(STM32_HASH_SHA512)
#else
static WC_INLINE int Sha512Final(wc_Sha512* sha512)
@ -1337,7 +1397,7 @@ static WC_INLINE int Sha512Final(wc_Sha512* sha512)
#elif defined(MAX3266X_SHA)
/* Functions defined in wolfcrypt/src/port/maxim/max3266x.c */
#elif defined(STM32_HASH_SHA512)
#else
static int Sha512FinalRaw(wc_Sha512* sha512, byte* hash, size_t digestSz)
@ -1407,10 +1467,12 @@ static int Sha512_Family_Final(wc_Sha512* sha512, byte* hash, size_t digestSz,
return initfp(sha512);
}
#ifndef STM32_HASH_SHA512
int wc_Sha512Final(wc_Sha512* sha512, byte* hash)
{
return Sha512_Family_Final(sha512, hash, WC_SHA512_DIGEST_SIZE, InitSha512);
}
#endif
#endif /* WOLFSSL_KCAPI_HASH */
@ -1592,6 +1654,64 @@ int wc_Sha512Transform(wc_Sha512* sha, const unsigned char* data)
#elif defined(MAX3266X_SHA)
/* Functions defined in wolfcrypt/src/port/maxim/max3266x.c */
#elif defined(STM32_HASH_SHA384)
int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId)
{
if (sha384 == NULL)
return BAD_FUNC_ARG;
(void)devId;
(void)heap;
XMEMSET(sha384, 0, sizeof(wc_Sha384));
wc_Stm32_Hash_Init(&sha384->stmCtx);
return 0;
}
int wc_Sha384Update(wc_Sha384* sha384, const byte* data, word32 len)
{
int ret = 0;
if (sha384 == NULL) {
return BAD_FUNC_ARG;
}
if (data == NULL && len == 0) {
/* valid, but do nothing */
return 0;
}
if (data == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Update(&sha384->stmCtx,
HASH_ALGOSELECTION_SHA384, data, len, WC_SHA384_BLOCK_SIZE);
wolfSSL_CryptHwMutexUnLock();
}
return ret;
}
int wc_Sha384Final(wc_Sha384* sha384, byte* hash)
{
int ret = 0;
if (sha384 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Final(&sha384->stmCtx,
HASH_ALGOSELECTION_SHA384, hash, WC_SHA384_DIGEST_SIZE);
wolfSSL_CryptHwMutexUnLock();
}
(void)wc_InitSha384(sha384); /* reset state */
return ret;
}
#else
@ -2011,17 +2131,75 @@ int wc_Sha512GetFlags(wc_Sha512* sha512, word32* flags)
#if !defined(WOLFSSL_NOSHA512_224) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
#if defined(STM32_HASH_SHA512_224)
int wc_InitSha512_224_ex(wc_Sha512* sha512, void* heap, int devId)
{
if (sha512 == NULL)
return BAD_FUNC_ARG;
(void)devId;
(void)heap;
XMEMSET(sha512, 0, sizeof(wc_Sha512));
wc_Stm32_Hash_Init(&sha512->stmCtx);
return 0;
}
int wc_Sha512_224Update(wc_Sha512* sha512, const byte* data, word32 len)
{
int ret = 0;
if (sha512 == NULL) {
return BAD_FUNC_ARG;
}
if (data == NULL && len == 0) {
/* valid, but do nothing */
return 0;
}
if (data == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Update(&sha512->stmCtx,
HASH_ALGOSELECTION_SHA512_224, data, len, WC_SHA512_224_BLOCK_SIZE);
wolfSSL_CryptHwMutexUnLock();
}
return ret;
}
int wc_Sha512_224Final(wc_Sha512* sha512, byte* hash)
{
int ret = 0;
if (sha512 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Final(&sha512->stmCtx,
HASH_ALGOSELECTION_SHA512_224, hash, WC_SHA512_224_DIGEST_SIZE);
wolfSSL_CryptHwMutexUnLock();
}
(void)wc_InitSha512_224(sha512); /* reset state */
return ret;
}
#endif
int wc_InitSha512_224(wc_Sha512* sha)
{
return wc_InitSha512_224_ex(sha, NULL, INVALID_DEVID);
}
#if !defined(STM32_HASH_SHA512_224)
int wc_Sha512_224Update(wc_Sha512* sha, const byte* data, word32 len)
{
return wc_Sha512Update(sha, data, len);
}
#endif
#if defined(WOLFSSL_KCAPI_HASH)
/* functions defined in wolfcrypt/src/port/kcapi/kcapi_hash.c */
#elif defined(WOLFSSL_RENESAS_RSIP) && \
@ -2029,6 +2207,7 @@ int wc_Sha512_224Update(wc_Sha512* sha, const byte* data, word32 len)
/* functions defined in wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c */
#elif defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)
#elif defined(STM32_HASH_SHA512_224)
#else
int wc_Sha512_224FinalRaw(wc_Sha512* sha, byte* hash)
@ -2091,16 +2270,75 @@ int wc_Sha512_224Transform(wc_Sha512* sha, const unsigned char* data)
#if !defined(WOLFSSL_NOSHA512_256) && \
(!defined(HAVE_FIPS) || FIPS_VERSION_GE(5, 3)) && !defined(HAVE_SELFTEST)
#if defined(STM32_HASH_SHA512_256)
int wc_InitSha512_256_ex(wc_Sha512* sha512, void* heap, int devId)
{
if (sha512 == NULL)
return BAD_FUNC_ARG;
(void)devId;
(void)heap;
XMEMSET(sha512, 0, sizeof(wc_Sha512));
wc_Stm32_Hash_Init(&sha512->stmCtx);
return 0;
}
int wc_Sha512_256Update(wc_Sha512* sha512, const byte* data, word32 len)
{
int ret = 0;
if (sha512 == NULL) {
return BAD_FUNC_ARG;
}
if (data == NULL && len == 0) {
/* valid, but do nothing */
return 0;
}
if (data == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Update(&sha512->stmCtx,
HASH_ALGOSELECTION_SHA512_256, data, len, WC_SHA512_256_BLOCK_SIZE);
wolfSSL_CryptHwMutexUnLock();
}
return ret;
}
int wc_Sha512_256Final(wc_Sha512* sha512, byte* hash)
{
int ret = 0;
if (sha512 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) {
ret = wc_Stm32_Hash_Final(&sha512->stmCtx,
HASH_ALGOSELECTION_SHA512_256, hash, WC_SHA512_256_DIGEST_SIZE);
wolfSSL_CryptHwMutexUnLock();
}
(void)wc_InitSha512_256(sha512); /* reset state */
return ret;
}
#endif
int wc_InitSha512_256(wc_Sha512* sha)
{
return wc_InitSha512_256_ex(sha, NULL, INVALID_DEVID);
}
#if !defined(STM32_HASH_SHA512_256)
int wc_Sha512_256Update(wc_Sha512* sha, const byte* data, word32 len)
{
return wc_Sha512Update(sha, data, len);
}
#endif
#if defined(WOLFSSL_KCAPI_HASH)
/* functions defined in wolfcrypt/src/port/kcapi/kcapi_hash.c */
#elif defined(WOLFSSL_RENESAS_RSIP) && \
@ -2108,7 +2346,7 @@ int wc_Sha512_256Update(wc_Sha512* sha, const byte* data, word32 len)
/* functions defined in wolfcrypt/src/port/Renesas/renesas_fspsm_sha.c */
#elif defined(WOLFSSL_SE050) && defined(WOLFSSL_SE050_HASH)
#elif defined(STM32_HASH_SHA512_256)
#else
int wc_Sha512_256FinalRaw(wc_Sha512* sha, byte* hash)
{
@ -2176,6 +2414,7 @@ int wc_Sha512_256Transform(wc_Sha512* sha, const unsigned char* data)
/* functions defined in wolfcrypt/src/port/renesas/renesas_fspsm_sha.c */
#elif defined(MAX3266X_SHA)
/* Functions defined in wolfcrypt/src/port/maxim/max3266x.c */
#else
int wc_Sha384GetHash(wc_Sha384* sha384, byte* hash)

View File

@ -35,13 +35,20 @@
#ifdef HASH_DIGEST
/* The HASH_DIGEST register indicates SHA224/SHA256 support */
#define STM32_HASH_SHA2
#if defined(WOLFSSL_STM32H5)
#if defined(WOLFSSL_STM32H5) || defined(WOLFSSL_STM32MP13)
#define HASH_CR_SIZE 103
#define HASH_MAX_DIGEST 64 /* Up to SHA512 */
#else
#define HASH_CR_SIZE 54
#define HASH_MAX_DIGEST 32
#endif
#if defined(WOLFSSL_STM32MP13)
#define STM32_HASH_SHA512
#define STM32_HASH_SHA512_224
#define STM32_HASH_SHA512_256
#define STM32_HASH_SHA384
#define STM32_HASH_SHA3
#endif
#else
#define HASH_CR_SIZE 50
#define HASH_MAX_DIGEST 20
@ -69,7 +76,15 @@
/* STM32 register size in bytes */
#define STM32_HASH_REG_SIZE 4
#define STM32_HASH_FIFO_SIZE 16 /* FIFO is 16 deep 32-bits wide */
/* Maximum FIFO buffer is 64 bits for SHA256, 128 bits for SHA512 and 144 bits
* for SHA3 */
#if defined(STM32_HASH_SHA3)
#define STM32_HASH_FIFO_SIZE 36
#elif defined(STM32_HASH_SHA512) || defined(STM32_HASH_SHA384)
#define STM32_HASH_FIFO_SIZE 32
#else
#define STM32_HASH_FIFO_SIZE 16
#endif
/* STM32 Hash Context */
typedef struct {
@ -78,6 +93,9 @@ typedef struct {
uint32_t HASH_STR;
uint32_t HASH_CR;
uint32_t HASH_CSR[HASH_CR_SIZE];
#ifdef STM32_HASH_SHA3
uint32_t SHA3CFGR;
#endif
/* Hash state / buffers */
word32 buffer[STM32_HASH_FIFO_SIZE+1]; /* partial word buffer */
@ -112,7 +130,6 @@ int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
#define HASH_AlgoSelection_MD5 HASH_ALGOSELECTION_MD5
#define HASH_AlgoSelection_SHA1 HASH_ALGOSELECTION_SHA1
#define HASH_AlgoSelection_SHA224 HASH_ALGOSELECTION_SHA224
#define HASH_AlgoSelection_SHA256 HASH_ALGOSELECTION_SHA256
#define STM32_NOMD5 /* The HASH HAL has no MD5 implementation */

View File

@ -45,6 +45,10 @@
#include <wolfssl/wolfcrypt/async.h>
#endif
#ifdef STM32_HASH
#include <wolfssl/wolfcrypt/port/st/stm32.h>
#endif
/* in bytes */
enum {
/* SHAKE-128 */
@ -140,6 +144,9 @@ struct wc_Sha3 {
#ifdef WOLFSSL_HASH_FLAGS
word32 flags; /* enum wc_HashFlags in hash.h */
#endif
#if defined(STM32_HASH_SHA3)
STM32_HASH_Context stmCtx;
#endif
};
#ifndef WC_SHA3_TYPE_DEFINED

View File

@ -73,6 +73,10 @@
#include "fsl_caam.h"
#endif
#ifdef STM32_HASH
#include <wolfssl/wolfcrypt/port/st/stm32.h>
#endif
#if defined(_MSC_VER)
#define SHA512_NOINLINE __declspec(noinline)
#elif defined(__IAR_SYSTEMS_ICC__) || defined(__GNUC__)
@ -202,6 +206,9 @@ struct wc_Sha512 {
#ifdef HAVE_ARIA
MC_HSESSION hSession;
#endif
#if defined(STM32_HASH_SHA512)
STM32_HASH_Context stmCtx;
#endif
#endif /* WOLFSSL_PSOC6_CRYPTO */
};