From f15dbb9110e9ba88775a968eef86676e73cf701c Mon Sep 17 00:00:00 2001 From: Andrew Hutchings Date: Wed, 27 Nov 2024 14:57:26 +0000 Subject: [PATCH 1/2] 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. --- wolfcrypt/src/port/st/stm32.c | 16 +- wolfcrypt/src/sha3.c | 87 ++++++++++- wolfcrypt/src/sha512.c | 251 +++++++++++++++++++++++++++++- wolfssl/wolfcrypt/port/st/stm32.h | 23 ++- wolfssl/wolfcrypt/sha3.h | 7 + wolfssl/wolfcrypt/sha512.h | 7 + 6 files changed, 375 insertions(+), 16 deletions(-) diff --git a/wolfcrypt/src/port/st/stm32.c b/wolfcrypt/src/port/st/stm32.c index 4f8d651ed4..aedef554c8 100644 --- a/wolfcrypt/src/port/st/stm32.c +++ b/wolfcrypt/src/port/st/stm32.c @@ -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; iHASH_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); diff --git a/wolfcrypt/src/sha3.c b/wolfcrypt/src/sha3.c index c40afbd909..f6b8c2f03f 100644 --- a/wolfcrypt/src/sha3.c +++ b/wolfcrypt/src/sha3.c @@ -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.) * diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index 7f3e745c60..16c3c0f204 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -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) diff --git a/wolfssl/wolfcrypt/port/st/stm32.h b/wolfssl/wolfcrypt/port/st/stm32.h index 6b8d76186f..0ff65fa7f1 100644 --- a/wolfssl/wolfcrypt/port/st/stm32.h +++ b/wolfssl/wolfcrypt/port/st/stm32.h @@ -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 */ diff --git a/wolfssl/wolfcrypt/sha3.h b/wolfssl/wolfcrypt/sha3.h index f65c41d322..5e733a10e9 100644 --- a/wolfssl/wolfcrypt/sha3.h +++ b/wolfssl/wolfcrypt/sha3.h @@ -45,6 +45,10 @@ #include #endif +#ifdef STM32_HASH + #include +#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 diff --git a/wolfssl/wolfcrypt/sha512.h b/wolfssl/wolfcrypt/sha512.h index e971a8df13..cfc357ff1f 100644 --- a/wolfssl/wolfcrypt/sha512.h +++ b/wolfssl/wolfcrypt/sha512.h @@ -73,6 +73,10 @@ #include "fsl_caam.h" #endif +#ifdef STM32_HASH + #include +#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 */ }; From cf450a3f377551eb72613ea96f1cc7365678b310 Mon Sep 17 00:00:00 2001 From: David Garske Date: Wed, 27 Nov 2024 14:06:20 -0800 Subject: [PATCH 2/2] Fix STM32 example broken in #8143. --- IDE/STM32Cube/wolfssl_example.c | 1 + 1 file changed, 1 insertion(+) diff --git a/IDE/STM32Cube/wolfssl_example.c b/IDE/STM32Cube/wolfssl_example.c index be6195a60a..b6d76b3a7e 100644 --- a/IDE/STM32Cube/wolfssl_example.c +++ b/IDE/STM32Cube/wolfssl_example.c @@ -1759,6 +1759,7 @@ static int tls13_uart_client(void) if (wolfSSL_UseKeyShare(ssl, WOLFSSL_KYBER_LEVEL1) != WOLFSSL_SUCCESS) { printf("wolfSSL_UseKeyShare Error!!"); } +#endif #endif do {