Fix for STM32U5 hash/crypto support. ZD 14305.

This commit is contained in:
David Garske
2022-06-06 12:11:06 -07:00
committed by Daniele Lacamera
parent af3a55a94c
commit 502cbc3847
6 changed files with 179 additions and 56 deletions

View File

@@ -78,7 +78,7 @@ int wc_Md5Update(wc_Md5* md5, const byte* data, word32 len)
ret = wolfSSL_CryptHwMutexLock(); ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) { if (ret == 0) {
ret = wc_Stm32_Hash_Update(&md5->stmCtx, HASH_AlgoSelection_MD5, ret = wc_Stm32_Hash_Update(&md5->stmCtx, HASH_AlgoSelection_MD5,
data, len); data, len, WC_MD5_BLOCK_SIZE);
wolfSSL_CryptHwMutexUnLock(); wolfSSL_CryptHwMutexUnLock();
} }
return ret; return ret;

View File

@@ -46,9 +46,7 @@
#ifdef STM32_HASH #ifdef STM32_HASH
#ifdef WOLFSSL_STM32L4 /* #define DEBUG_STM32_HASH */
#define HASH_STR_NBW HASH_STR_NBLW
#endif
/* User can override STM32_HASH_CLOCK_ENABLE and STM32_HASH_CLOCK_DISABLE */ /* User can override STM32_HASH_CLOCK_ENABLE and STM32_HASH_CLOCK_DISABLE */
#ifndef STM32_HASH_CLOCK_ENABLE #ifndef STM32_HASH_CLOCK_ENABLE
@@ -77,8 +75,22 @@
#define STM32_HASH_CLOCK_DISABLE(ctx) wc_Stm32_Hash_Clock_Disable(ctx) #define STM32_HASH_CLOCK_DISABLE(ctx) wc_Stm32_Hash_Clock_Disable(ctx)
#endif #endif
/* STM32 Port Internal Functions */ /* 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; 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++) { for (i=0; i<HASH_CR_SIZE; i++) {
ctx->HASH_CSR[i] = HASH->CSR[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; 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 */ /* restore context registers */
HASH->IMR = ctx->HASH_IMR; HASH->IMR = ctx->HASH_IMR;
HASH->STR = ctx->HASH_STR; 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++) { for (i=0; i<HASH_CR_SIZE; i++) {
HASH->CSR[i] = ctx->HASH_CSR[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)]; 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); ByteReverseWords(digest, digest, digestSize);
XMEMCPY(hash, 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
} }
static int wc_Stm32_Hash_WaitDone(STM32_HASH_Context* stmCtx)
/* STM32 Port Exposed Functions */
static WC_INLINE int wc_Stm32_Hash_WaitDone(void)
{ {
/* wait until hash hardware is not busy */
int timeout = 0; 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 */ /* verify timeout did not occur */
if (timeout >= STM32_HASH_TIMEOUT) { if (timeout >= STM32_HASH_TIMEOUT) {
return WC_TIMEOUT_E; return WC_TIMEOUT_E;
@@ -155,22 +221,58 @@ static WC_INLINE int wc_Stm32_Hash_WaitDone(void)
return 0; 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) void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx)
{ {
/* clear context */ /* clear context */
/* this also gets called after finish */
XMEMSET(stmCtx, 0, sizeof(STM32_HASH_Context)); XMEMSET(stmCtx, 0, sizeof(STM32_HASH_Context));
} }
int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo, 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; int ret = 0;
byte* local = (byte*)stmCtx->buffer; byte* local = (byte*)stmCtx->buffer;
int wroteToFifo = 0; 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 */ /* check that internal buffLen is valid */
if (stmCtx->buffLen >= STM32_HASH_REG_SIZE) { if (stmCtx->buffLen > blockSize) {
return BUFFER_E; return BUFFER_E;
} }
@@ -178,36 +280,38 @@ int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo,
STM32_HASH_CLOCK_ENABLE(stmCtx); STM32_HASH_CLOCK_ENABLE(stmCtx);
/* restore hash context or init as new hash */ /* restore hash context or init as new hash */
if (wc_Stm32_Hash_RestoreContext(stmCtx) == 0) { wc_Stm32_Hash_RestoreContext(stmCtx, algo);
/* reset the control register */
HASH->CR &= ~(HASH_CR_ALGO | HASH_CR_DATATYPE | HASH_CR_MODE);
/* configure algorithm, mode and data type */ /* write blocks to FIFO */
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 */
while (len) { 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); XMEMCPY(&local[stmCtx->buffLen], data, add);
stmCtx->buffLen += add; stmCtx->buffLen += add;
data += add; data += add;
len -= 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; wroteToFifo = 1;
HASH->DIN = *(word32*)stmCtx->buffer;
stmCtx->loLen += STM32_HASH_REG_SIZE;
stmCtx->buffLen = 0;
} }
} }
if (wroteToFifo) { 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 */ /* save hash state for next operation */
wc_Stm32_Hash_SaveContext(stmCtx); 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, int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
byte* hash, int digestSize) byte* hash, word32 digestSize)
{ {
int ret = 0; 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 */ /* turn on hash clock */
STM32_HASH_CLOCK_ENABLE(stmCtx); STM32_HASH_CLOCK_ENABLE(stmCtx);
/* restore hash state */ /* restore hash context or init as new hash */
wc_Stm32_Hash_RestoreContext(stmCtx); wc_Stm32_Hash_RestoreContext(stmCtx, algo);
/* finish reading any trailing bytes into FIFO */ /* finish reading any trailing bytes into FIFO */
if (stmCtx->buffLen > 0) { if (stmCtx->buffLen > 0) {
HASH->DIN = *(word32*)stmCtx->buffer; /* send remainder of data */
stmCtx->loLen += stmCtx->buffLen; wc_Stm32_Hash_Data(stmCtx, stmCtx->buffLen);
} }
/* calculate number of valid bits in last word */ /* calculate number of valid bits in last word */
nbvalidbitsdata = 8 * (stmCtx->loLen % STM32_HASH_REG_SIZE); wc_Stm32_Hash_NumValidBits(stmCtx->loLen + stmCtx->buffLen);
HASH->STR &= ~HASH_STR_NBW;
HASH->STR |= nbvalidbitsdata;
/* start hash processor */ /* start hash processor */
HASH->STR |= HASH_STR_DCAL; HASH->STR |= HASH_STR_DCAL;
/* wait for hash done */ /* wait for hash done */
ret = wc_Stm32_Hash_WaitDone(); ret = wc_Stm32_Hash_WaitDone(stmCtx);
if (ret == 0) { if (ret == 0) {
/* read message digest */ /* read message digest */
wc_Stm32_Hash_GetDigest(hash, digestSize); wc_Stm32_Hash_GetDigest(hash, digestSize);

View File

@@ -137,7 +137,7 @@
ret = wolfSSL_CryptHwMutexLock(); ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) { if (ret == 0) {
ret = wc_Stm32_Hash_Update(&sha->stmCtx, HASH_AlgoSelection_SHA1, ret = wc_Stm32_Hash_Update(&sha->stmCtx, HASH_AlgoSelection_SHA1,
data, len); data, len, WC_SHA_BLOCK_SIZE);
wolfSSL_CryptHwMutexUnLock(); wolfSSL_CryptHwMutexUnLock();
} }
return ret; return ret;

View File

@@ -567,7 +567,7 @@ static int InitSha256(wc_Sha256* sha256)
ret = wolfSSL_CryptHwMutexLock(); ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) { if (ret == 0) {
ret = wc_Stm32_Hash_Update(&sha256->stmCtx, ret = wc_Stm32_Hash_Update(&sha256->stmCtx,
HASH_AlgoSelection_SHA256, data, len); HASH_AlgoSelection_SHA256, data, len, WC_SHA256_BLOCK_SIZE);
wolfSSL_CryptHwMutexUnLock(); wolfSSL_CryptHwMutexUnLock();
} }
return ret; return ret;
@@ -1405,7 +1405,7 @@ static int InitSha256(wc_Sha256* sha256)
ret = wolfSSL_CryptHwMutexLock(); ret = wolfSSL_CryptHwMutexLock();
if (ret == 0) { if (ret == 0) {
ret = wc_Stm32_Hash_Update(&sha224->stmCtx, ret = wc_Stm32_Hash_Update(&sha224->stmCtx,
HASH_AlgoSelection_SHA224, data, len); HASH_AlgoSelection_SHA224, data, len, WC_SHA224_BLOCK_SIZE);
wolfSSL_CryptHwMutexUnLock(); wolfSSL_CryptHwMutexUnLock();
} }
return ret; return ret;

View File

@@ -93,6 +93,13 @@ typedef WOLFSSL_SHA_CTX SHA_CTX;
#endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */ #endif /* OPENSSL_EXTRA || OPENSSL_EXTRA_X509_SMALL */
#endif /* !NO_SHA */ #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 #ifdef WOLFSSL_SHA224
/* Using ALIGN16 because when AES-NI is enabled digest and buffer in Sha256 /* 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. */ * to Sha224, is expected to also be 16 byte aligned addresses. */
typedef struct WOLFSSL_SHA224_CTX { typedef struct WOLFSSL_SHA224_CTX {
/* big enough to hold wolfcrypt Sha224, but check on init */ /* 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_SHA224_CTX;
WOLFSSL_API int wolfSSL_SHA224_Init(WOLFSSL_SHA224_CTX* sha); 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. */ * to Sha256, is expected to also be 16 byte aligned addresses. */
typedef struct WOLFSSL_SHA256_CTX { typedef struct WOLFSSL_SHA256_CTX {
/* big enough to hold wolfcrypt Sha256, but check on init */ /* 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_SHA256_CTX;
WOLFSSL_API int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256); WOLFSSL_API int wolfSSL_SHA256_Init(WOLFSSL_SHA256_CTX* sha256);

View File

@@ -60,6 +60,11 @@
/* STM32 register size in bytes */ /* STM32 register size in bytes */
#define STM32_HASH_REG_SIZE 4 #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 */ /* STM32 Hash Context */
typedef struct { typedef struct {
@@ -70,19 +75,20 @@ typedef struct {
uint32_t HASH_CSR[HASH_CR_SIZE]; uint32_t HASH_CSR[HASH_CR_SIZE];
/* Hash state / buffers */ /* 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 buffLen; /* partial word remain */
word32 loLen; /* total update bytes word32 loLen; /* total update bytes
(only lsb 6-bits is used for nbr valid bytes in last word) */ (only lsb 6-bits is used for nbr valid bytes in last word) */
int fifoBytes; /* number of currently filled FIFO bytes */
} STM32_HASH_Context; } STM32_HASH_Context;
/* API's */ /* API's */
void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx); void wc_Stm32_Hash_Init(STM32_HASH_Context* stmCtx);
int wc_Stm32_Hash_Update(STM32_HASH_Context* stmCtx, word32 algo, 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, int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
byte* hash, int digestSize); byte* hash, word32 digestSize);
#endif /* STM32_HASH */ #endif /* STM32_HASH */
@@ -92,7 +98,8 @@ int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
#ifndef NO_AES #ifndef NO_AES
#if !defined(STM32_CRYPTO_AES_GCM) && (defined(WOLFSSL_STM32F4) || \ #if !defined(STM32_CRYPTO_AES_GCM) && (defined(WOLFSSL_STM32F4) || \
defined(WOLFSSL_STM32F7) || defined(WOLFSSL_STM32L4) || \ 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 */ /* Hardware supports AES GCM acceleration */
#define STM32_CRYPTO_AES_GCM #define STM32_CRYPTO_AES_GCM
#endif #endif
@@ -102,7 +109,8 @@ int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
#define CRYP AES1 #define CRYP AES1
#define STM32_HAL_V2 #define STM32_HAL_V2
#endif #endif
#if defined(WOLFSSL_STM32L4) || defined(WOLFSSL_STM32L5) #if defined(WOLFSSL_STM32L4) || defined(WOLFSSL_STM32L5) || \
defined(WOLFSSL_STM32U5)
#ifdef WOLFSSL_STM32L4 #ifdef WOLFSSL_STM32L4
#define STM32_CRYPTO_AES_ONLY /* crypto engine only supports AES */ #define STM32_CRYPTO_AES_ONLY /* crypto engine only supports AES */
#endif #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) */ /* Detect newer CubeMX crypto HAL (HAL_CRYP_Encrypt / HAL_CRYP_Decrypt) */
#if !defined(STM32_HAL_V2) && defined(CRYP_AES_GCM) && \ #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 #define STM32_HAL_V2
#endif #endif