forked from wolfSSL/wolfssl
Fix for STM32U5 hash/crypto support. ZD 14305.
This commit is contained in:
committed by
Daniele Lacamera
parent
af3a55a94c
commit
502cbc3847
@@ -78,7 +78,7 @@ int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
|
||||
ret = wolfSSL_CryptHwMutexLock();
|
||||
if (ret == 0) {
|
||||
ret = wc_Stm32_Hash_Update(&md5->stmCtx, HASH_AlgoSelection_MD5,
|
||||
data, len);
|
||||
data, len, WC_MD5_BLOCK_SIZE);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
}
|
||||
return ret;
|
||||
|
@@ -46,9 +46,7 @@
|
||||
|
||||
#ifdef STM32_HASH
|
||||
|
||||
#ifdef WOLFSSL_STM32L4
|
||||
#define HASH_STR_NBW HASH_STR_NBLW
|
||||
#endif
|
||||
/* #define DEBUG_STM32_HASH */
|
||||
|
||||
/* User can override STM32_HASH_CLOCK_ENABLE and STM32_HASH_CLOCK_DISABLE */
|
||||
#ifndef STM32_HASH_CLOCK_ENABLE
|
||||
@@ -77,8 +75,22 @@
|
||||
#define STM32_HASH_CLOCK_DISABLE(ctx) wc_Stm32_Hash_Clock_Disable(ctx)
|
||||
#endif
|
||||
|
||||
|
||||
/* STM32 Port Internal Functions */
|
||||
static WC_INLINE void wc_Stm32_Hash_SaveContext(STM32_HASH_Context* ctx)
|
||||
static void wc_Stm32_Hash_NumValidBits(word32 len)
|
||||
{
|
||||
/* calculate number of valid bits in last word */
|
||||
/* NBLW = 0x00 (all 32-bits are valid) */
|
||||
word32 nbvalidbytesdata = (len % STM32_HASH_REG_SIZE);
|
||||
HASH->STR &= ~HASH_STR_NBW;
|
||||
HASH->STR |= (8 * nbvalidbytesdata) & HASH_STR_NBW;
|
||||
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("STM Valid Last bits (%d)\n", 8 * nbvalidbytesdata);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void wc_Stm32_Hash_SaveContext(STM32_HASH_Context* ctx)
|
||||
{
|
||||
int i;
|
||||
|
||||
@@ -89,13 +101,46 @@ static WC_INLINE void wc_Stm32_Hash_SaveContext(STM32_HASH_Context* ctx)
|
||||
for (i=0; i<HASH_CR_SIZE; i++) {
|
||||
ctx->HASH_CSR[i] = HASH->CSR[i];
|
||||
}
|
||||
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("STM Save CR %lx, IMR %lx, STR %lx\n",
|
||||
HASH->CR, HASH->IMR, HASH->STR);
|
||||
#endif
|
||||
}
|
||||
|
||||
static WC_INLINE int wc_Stm32_Hash_RestoreContext(STM32_HASH_Context* ctx)
|
||||
static void wc_Stm32_Hash_RestoreContext(STM32_HASH_Context* ctx, int algo)
|
||||
{
|
||||
int i;
|
||||
|
||||
if (ctx->HASH_CR != 0) {
|
||||
if (ctx->HASH_CR == 0) {
|
||||
/* init content */
|
||||
|
||||
#if defined(HASH_IMR_DINIE) && defined(HASH_IMR_DCIE)
|
||||
/* enable IRQ's */
|
||||
HASH->IMR |= (HASH_IMR_DINIE | HASH_IMR_DCIE);
|
||||
#endif
|
||||
|
||||
/* reset the control register */
|
||||
HASH->CR &= ~(HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_DATATYPE
|
||||
#ifdef HASH_CR_LKEY
|
||||
| HASH_CR_LKEY
|
||||
#endif
|
||||
);
|
||||
|
||||
/* configure algorithm, mode and data type */
|
||||
HASH->CR |= (algo | HASH_ALGOMODE_HASH | HASH_DATATYPE_8B);
|
||||
|
||||
/* reset HASH processor */
|
||||
HASH->CR |= HASH_CR_INIT;
|
||||
|
||||
/* by default mark all bits valid */
|
||||
wc_Stm32_Hash_NumValidBits(0);
|
||||
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("STM Init algo %x\n", algo);
|
||||
#endif
|
||||
}
|
||||
else {
|
||||
/* restore context registers */
|
||||
HASH->IMR = ctx->HASH_IMR;
|
||||
HASH->STR = ctx->HASH_STR;
|
||||
@@ -108,12 +153,15 @@ static WC_INLINE int wc_Stm32_Hash_RestoreContext(STM32_HASH_Context* ctx)
|
||||
for (i=0; i<HASH_CR_SIZE; i++) {
|
||||
HASH->CSR[i] = ctx->HASH_CSR[i];
|
||||
}
|
||||
return 1;
|
||||
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("STM Restore CR %lx, IMR %lx, STR %lx\n",
|
||||
HASH->CR, HASH->IMR, HASH->STR);
|
||||
#endif
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static WC_INLINE void wc_Stm32_Hash_GetDigest(byte* hash, int digestSize)
|
||||
static void wc_Stm32_Hash_GetDigest(byte* hash, int digestSize)
|
||||
{
|
||||
word32 digest[HASH_MAX_DIGEST/sizeof(word32)];
|
||||
|
||||
@@ -137,17 +185,35 @@ static WC_INLINE void wc_Stm32_Hash_GetDigest(byte* hash, int digestSize)
|
||||
ByteReverseWords(digest, digest, digestSize);
|
||||
|
||||
XMEMCPY(hash, digest, digestSize);
|
||||
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
{
|
||||
word32 i;
|
||||
printf("STM Digest %d\n", digestSize);
|
||||
for (i=0; i<digestSize/sizeof(word32); i++) {
|
||||
printf("\tDIG 0x%04x\n", digest[i]);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/* STM32 Port Exposed Functions */
|
||||
static WC_INLINE int wc_Stm32_Hash_WaitDone(void)
|
||||
static int wc_Stm32_Hash_WaitDone(STM32_HASH_Context* stmCtx)
|
||||
{
|
||||
/* wait until hash hardware is not busy */
|
||||
int timeout = 0;
|
||||
while ((HASH->SR & HASH_SR_BUSY) && ++timeout < STM32_HASH_TIMEOUT) {
|
||||
(void)stmCtx;
|
||||
|
||||
/* wait until hash digest is complete */
|
||||
while ((HASH->SR & HASH_SR_BUSY) &&
|
||||
#ifdef HASH_IMR_DCIE
|
||||
(HASH->SR & HASH_SR_DCIS) == 0 &&
|
||||
#endif
|
||||
++timeout < STM32_HASH_TIMEOUT) {
|
||||
};
|
||||
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("STM Wait done %d, HASH->SR %lx\n", timeout, HASH->SR);
|
||||
#endif
|
||||
|
||||
}
|
||||
/* verify timeout did not occur */
|
||||
if (timeout >= STM32_HASH_TIMEOUT) {
|
||||
return WC_TIMEOUT_E;
|
||||
@@ -155,22 +221,58 @@ static WC_INLINE int wc_Stm32_Hash_WaitDone(void)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void wc_Stm32_Hash_Data(STM32_HASH_Context* stmCtx, word32 len)
|
||||
{
|
||||
word32 i, blocks;
|
||||
|
||||
if (len > stmCtx->buffLen)
|
||||
len = stmCtx->buffLen;
|
||||
|
||||
/* calculate number of 32-bit blocks */
|
||||
blocks = ((len + STM32_HASH_REG_SIZE-1) / STM32_HASH_REG_SIZE);
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("STM DIN %d blocks\n", blocks);
|
||||
#endif
|
||||
for (i=0; i<blocks; i++) {
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("\tDIN 0x%04x\n", stmCtx->buffer[i]);
|
||||
#endif
|
||||
HASH->DIN = stmCtx->buffer[i];
|
||||
}
|
||||
stmCtx->loLen += len; /* total */
|
||||
stmCtx->buffLen -= len;
|
||||
if (stmCtx->buffLen > 0) {
|
||||
XMEMMOVE(stmCtx->buffer, (byte*)stmCtx->buffer+len, stmCtx->buffLen);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* STM32 Port Exposed Functions */
|
||||
void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx)
|
||||
{
|
||||
/* clear context */
|
||||
/* this also gets called after finish */
|
||||
XMEMSET(stmCtx, 0, sizeof(STM32_HASH_Context));
|
||||
}
|
||||
|
||||
int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
const byte* data, int len)
|
||||
const byte* data, word32 len, word32 blockSize)
|
||||
{
|
||||
int ret = 0;
|
||||
byte* local = (byte*)stmCtx->buffer;
|
||||
int wroteToFifo = 0;
|
||||
const word32 fifoSz = (STM32_HASH_FIFO_SIZE * STM32_HASH_REG_SIZE);
|
||||
|
||||
if (blockSize > fifoSz)
|
||||
blockSize = fifoSz;
|
||||
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("STM Hash Update: algo %x, len %d, blockSz %d\n",
|
||||
algo, len, blockSize);
|
||||
#endif
|
||||
|
||||
/* check that internal buffLen is valid */
|
||||
if (stmCtx->buffLen >= STM32_HASH_REG_SIZE) {
|
||||
if (stmCtx->buffLen > blockSize) {
|
||||
return BUFFER_E;
|
||||
}
|
||||
|
||||
@@ -178,36 +280,38 @@ int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
STM32_HASH_CLOCK_ENABLE(stmCtx);
|
||||
|
||||
/* restore hash context or init as new hash */
|
||||
if (wc_Stm32_Hash_RestoreContext(stmCtx) == 0) {
|
||||
/* reset the control register */
|
||||
HASH->CR &= ~(HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE);
|
||||
wc_Stm32_Hash_RestoreContext(stmCtx, algo);
|
||||
|
||||
/* configure algorithm, mode and data type */
|
||||
HASH->CR |= (algo | HASH_ALGOMODE_HASH | HASH_DATATYPE_8B);
|
||||
|
||||
/* reset HASH processor */
|
||||
HASH->CR |= HASH_CR_INIT;
|
||||
}
|
||||
|
||||
/* write 4-bytes at a time into FIFO */
|
||||
/* write blocks to FIFO */
|
||||
while (len) {
|
||||
word32 add = min(len, STM32_HASH_REG_SIZE - stmCtx->buffLen);
|
||||
word32 fillBlockSz = blockSize, add;
|
||||
|
||||
/* if FIFO already has bytes written then fill remainder first */
|
||||
if (stmCtx->fifoBytes > 0) {
|
||||
fillBlockSz -= stmCtx->fifoBytes;
|
||||
stmCtx->fifoBytes = 0;
|
||||
}
|
||||
|
||||
add = min(len, fillBlockSz - stmCtx->buffLen);
|
||||
XMEMCPY(&local[stmCtx->buffLen], data, add);
|
||||
|
||||
stmCtx->buffLen += add;
|
||||
data += add;
|
||||
len -= add;
|
||||
|
||||
if (stmCtx->buffLen == STM32_HASH_REG_SIZE) {
|
||||
if (len > 0 && stmCtx->buffLen == fillBlockSz) {
|
||||
wc_Stm32_Hash_Data(stmCtx, stmCtx->buffLen);
|
||||
wroteToFifo = 1;
|
||||
HASH->DIN = *(word32*)stmCtx->buffer;
|
||||
|
||||
stmCtx->loLen += STM32_HASH_REG_SIZE;
|
||||
stmCtx->buffLen = 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (wroteToFifo) {
|
||||
/* If we wrote a block send one more 32-bit to FIFO to trigger
|
||||
* start. We cannot leave 16 deep FIFO filled before saving off
|
||||
* context */
|
||||
wc_Stm32_Hash_Data(stmCtx, 4);
|
||||
stmCtx->fifoBytes += 4;
|
||||
|
||||
/* save hash state for next operation */
|
||||
wc_Stm32_Hash_SaveContext(stmCtx);
|
||||
}
|
||||
@@ -219,33 +323,34 @@ int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
}
|
||||
|
||||
int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
byte* hash, int digestSize)
|
||||
byte* hash, word32 digestSize)
|
||||
{
|
||||
int ret = 0;
|
||||
word32 nbvalidbitsdata = 0;
|
||||
|
||||
#ifdef DEBUG_STM32_HASH
|
||||
printf("STM Hash Final: algo %x, digestSz %d\n", algo, digestSize);
|
||||
#endif
|
||||
|
||||
/* turn on hash clock */
|
||||
STM32_HASH_CLOCK_ENABLE(stmCtx);
|
||||
|
||||
/* restore hash state */
|
||||
wc_Stm32_Hash_RestoreContext(stmCtx);
|
||||
/* restore hash context or init as new hash */
|
||||
wc_Stm32_Hash_RestoreContext(stmCtx, algo);
|
||||
|
||||
/* finish reading any trailing bytes into FIFO */
|
||||
if (stmCtx->buffLen > 0) {
|
||||
HASH->DIN = *(word32*)stmCtx->buffer;
|
||||
stmCtx->loLen += stmCtx->buffLen;
|
||||
/* send remainder of data */
|
||||
wc_Stm32_Hash_Data(stmCtx, stmCtx->buffLen);
|
||||
}
|
||||
|
||||
/* calculate number of valid bits in last word */
|
||||
nbvalidbitsdata = 8 * (stmCtx->loLen % STM32_HASH_REG_SIZE);
|
||||
HASH->STR &= ~HASH_STR_NBW;
|
||||
HASH->STR |= nbvalidbitsdata;
|
||||
wc_Stm32_Hash_NumValidBits(stmCtx->loLen + stmCtx->buffLen);
|
||||
|
||||
/* start hash processor */
|
||||
HASH->STR |= HASH_STR_DCAL;
|
||||
|
||||
/* wait for hash done */
|
||||
ret = wc_Stm32_Hash_WaitDone();
|
||||
ret = wc_Stm32_Hash_WaitDone(stmCtx);
|
||||
if (ret == 0) {
|
||||
/* read message digest */
|
||||
wc_Stm32_Hash_GetDigest(hash, digestSize);
|
||||
|
@@ -137,7 +137,7 @@
|
||||
ret = wolfSSL_CryptHwMutexLock();
|
||||
if (ret == 0) {
|
||||
ret = wc_Stm32_Hash_Update(&sha->stmCtx, HASH_AlgoSelection_SHA1,
|
||||
data, len);
|
||||
data, len, WC_SHA_BLOCK_SIZE);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
}
|
||||
return ret;
|
||||
|
@@ -567,7 +567,7 @@ static int InitSha256(wc_Sha256* sha256)
|
||||
ret = wolfSSL_CryptHwMutexLock();
|
||||
if (ret == 0) {
|
||||
ret = wc_Stm32_Hash_Update(&sha256->stmCtx,
|
||||
HASH_AlgoSelection_SHA256, data, len);
|
||||
HASH_AlgoSelection_SHA256, data, len, WC_SHA256_BLOCK_SIZE);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
}
|
||||
return ret;
|
||||
@@ -1405,7 +1405,7 @@ static int InitSha256(wc_Sha256* sha256)
|
||||
ret = wolfSSL_CryptHwMutexLock();
|
||||
if (ret == 0) {
|
||||
ret = wc_Stm32_Hash_Update(&sha224->stmCtx,
|
||||
HASH_AlgoSelection_SHA224, data, len);
|
||||
HASH_AlgoSelection_SHA224, data, len, WC_SHA224_BLOCK_SIZE);
|
||||
wolfSSL_CryptHwMutexUnLock();
|
||||
}
|
||||
return ret;
|
||||
|
@@ -93,6 +93,13 @@ typedef WOLFSSL_SHA_CTX SHA_CTX;
|
||||
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
|
||||
#endif /* !NO_SHA */
|
||||
|
||||
/* adder for HW crypto */
|
||||
#ifdef STM32_HASH
|
||||
#define CTX_SHA2_HW_ADDER 30
|
||||
#else
|
||||
#define CTX_SHA2_HW_ADDER 0
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_SHA224
|
||||
|
||||
/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256
|
||||
@@ -100,7 +107,8 @@ typedef WOLFSSL_SHA_CTX SHA_CTX;
|
||||
* to Sha224, is expected to also be 16 byte aligned addresses. */
|
||||
typedef struct WOLFSSL_SHA224_CTX {
|
||||
/* big enough to hold wolfcrypt Sha224, but check on init */
|
||||
ALIGN16 void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
|
||||
ALIGN16 void* holder[(274 + CTX_SHA2_HW_ADDER + WC_ASYNC_DEV_SIZE) /
|
||||
sizeof(void*)];
|
||||
} WOLFSSL_SHA224_CTX;
|
||||
|
||||
WOLFSSL_API int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha);
|
||||
@@ -133,7 +141,8 @@ typedef WOLFSSL_SHA224_CTX SHA224_CTX;
|
||||
* to Sha256, is expected to also be 16 byte aligned addresses. */
|
||||
typedef struct WOLFSSL_SHA256_CTX {
|
||||
/* big enough to hold wolfcrypt Sha256, but check on init */
|
||||
ALIGN16 void* holder[(272 + WC_ASYNC_DEV_SIZE) / sizeof(void*)];
|
||||
ALIGN16 void* holder[(274 + CTX_SHA2_HW_ADDER + WC_ASYNC_DEV_SIZE) /
|
||||
sizeof(void*)];
|
||||
} WOLFSSL_SHA256_CTX;
|
||||
|
||||
WOLFSSL_API int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256);
|
||||
|
@@ -60,6 +60,11 @@
|
||||
|
||||
/* STM32 register size in bytes */
|
||||
#define STM32_HASH_REG_SIZE 4
|
||||
#if defined(WOLFSSL_STM32U5)
|
||||
#define STM32_HASH_FIFO_SIZE 16 /* FIFO is 16 deep 32-bits wide */
|
||||
#else
|
||||
#define STM32_HASH_FIFO_SIZE 1
|
||||
#endif
|
||||
|
||||
/* STM32 Hash Context */
|
||||
typedef struct {
|
||||
@@ -70,19 +75,20 @@ typedef struct {
|
||||
uint32_t HASH_CSR[HASH_CR_SIZE];
|
||||
|
||||
/* Hash state / buffers */
|
||||
word32 buffer[STM32_HASH_REG_SIZE / sizeof(word32)]; /* partial word buffer */
|
||||
word32 buffer[STM32_HASH_FIFO_SIZE]; /* partial word buffer */
|
||||
word32 buffLen; /* partial word remain */
|
||||
word32 loLen; /* total update bytes
|
||||
(only lsb 6-bits is used for nbr valid bytes in last word) */
|
||||
int fifoBytes; /* number of currently filled FIFO bytes */
|
||||
} STM32_HASH_Context;
|
||||
|
||||
|
||||
/* API's */
|
||||
void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx);
|
||||
int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
const byte* data, int len);
|
||||
const byte* data, word32 len, word32 blockSize);
|
||||
int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
byte* hash, int digestSize);
|
||||
byte* hash, word32 digestSize);
|
||||
|
||||
#endif /* STM32_HASH */
|
||||
|
||||
@@ -92,7 +98,8 @@ int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
#ifndef NO_AES
|
||||
#if !defined(STM32_CRYPTO_AES_GCM) && (defined(WOLFSSL_STM32F4) || \
|
||||
defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32L4) || \
|
||||
defined(WOLFSSL_STM32L5) || defined(WOLFSSL_STM32H7))
|
||||
defined(WOLFSSL_STM32L5) || defined(WOLFSSL_STM32H7) || \
|
||||
defined(WOLFSSL_STM32U5))
|
||||
/* Hardware supports AES GCM acceleration */
|
||||
#define STM32_CRYPTO_AES_GCM
|
||||
#endif
|
||||
@@ -102,7 +109,8 @@ int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
#define CRYP AES1
|
||||
#define STM32_HAL_V2
|
||||
#endif
|
||||
#if defined(WOLFSSL_STM32L4) || defined(WOLFSSL_STM32L5)
|
||||
#if defined(WOLFSSL_STM32L4) || defined(WOLFSSL_STM32L5) || \
|
||||
defined(WOLFSSL_STM32U5)
|
||||
#ifdef WOLFSSL_STM32L4
|
||||
#define STM32_CRYPTO_AES_ONLY /* crypto engine only supports AES */
|
||||
#endif
|
||||
@@ -114,7 +122,8 @@ int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
|
||||
|
||||
/* Detect newer CubeMX crypto HAL (HAL_CRYP_Encrypt / HAL_CRYP_Decrypt) */
|
||||
#if !defined(STM32_HAL_V2) && defined(CRYP_AES_GCM) && \
|
||||
(defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32L5) || defined(WOLFSSL_STM32H7))
|
||||
(defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32L5) || \
|
||||
defined(WOLFSSL_STM32H7) || defined(WOLFSSL_STM32U5))
|
||||
#define STM32_HAL_V2
|
||||
#endif
|
||||
|
||||
|
Reference in New Issue
Block a user