Skip to content

Commit fd112e1

Browse files
committed
Support for STM32 HMAC hardware
1 parent 6a44159 commit fd112e1

5 files changed

Lines changed: 390 additions & 0 deletions

File tree

wolfcrypt/src/hmac.c

Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -533,6 +533,54 @@ int wc_HmacSetKey_ex(Hmac* hmac, int type, const byte* key, word32 length,
533533
return 0;
534534
#else
535535

536+
#if defined(STM32_HASH) && defined(STM32_HMAC)
537+
{
538+
word32 stmAlgo, stmBlockSize, stmDigestSize;
539+
/* Check if this hash type is supported by STM32 HMAC hardware */
540+
if (wc_Stm32_Hmac_GetAlgoInfo(type, &stmAlgo, &stmBlockSize,
541+
&stmDigestSize) == 0) {
542+
/* Store raw key - pre-hash if longer than hash block size */
543+
if (length <= stmBlockSize) {
544+
if (key != NULL) {
545+
XMEMCPY(hmac->stmKey, key, length);
546+
}
547+
hmac->stmKeyLen = length;
548+
}
549+
else {
550+
/* Pre-hash long key using STM32 HASH hardware */
551+
STM32_HASH_Context tmpCtx;
552+
wc_Stm32_Hash_Init(&tmpCtx);
553+
ret = wolfSSL_CryptHwMutexLock();
554+
if (ret == 0) {
555+
ret = wc_Stm32_Hash_Update(&tmpCtx, stmAlgo,
556+
key, length, stmBlockSize);
557+
if (ret == 0) {
558+
ret = wc_Stm32_Hash_Final(&tmpCtx, stmAlgo,
559+
hmac->stmKey, stmDigestSize);
560+
}
561+
wolfSSL_CryptHwMutexUnLock();
562+
}
563+
if (ret != 0)
564+
return ret;
565+
hmac->stmKeyLen = stmDigestSize;
566+
}
567+
568+
/* HW HMAC Phase 1: feed key */
569+
ret = wolfSSL_CryptHwMutexLock();
570+
if (ret == 0) {
571+
ret = wc_Stm32_Hmac_SetKey(&hmac->stmCtx, type,
572+
hmac->stmKey, hmac->stmKeyLen);
573+
wolfSSL_CryptHwMutexUnLock();
574+
}
575+
if (ret == 0) {
576+
hmac->innerHashKeyed = WC_HMAC_INNER_HASH_KEYED_DEV;
577+
}
578+
return ret;
579+
}
580+
/* Unsupported algo falls through to software */
581+
}
582+
#endif /* STM32_HASH && STM32_HMAC */
583+
536584
ip = (byte*)hmac->ipad;
537585
op = (byte*)hmac->opad;
538586

@@ -853,6 +901,18 @@ int wc_HmacUpdate(Hmac* hmac, const byte* msg, word32 length)
853901
}
854902
#endif /* WOLFSSL_ASYNC_CRYPT */
855903

904+
#if defined(STM32_HASH) && defined(STM32_HMAC)
905+
if (hmac->innerHashKeyed == WC_HMAC_INNER_HASH_KEYED_DEV) {
906+
ret = wolfSSL_CryptHwMutexLock();
907+
if (ret == 0) {
908+
ret = wc_Stm32_Hmac_Update(&hmac->stmCtx, hmac->macType,
909+
msg, length);
910+
wolfSSL_CryptHwMutexUnLock();
911+
}
912+
return ret;
913+
}
914+
#endif /* STM32_HASH && STM32_HMAC */
915+
856916
if (!hmac->innerHashKeyed) {
857917
#ifndef WOLFSSL_HMAC_COPY_HASH
858918
ret = HmacKeyHashUpdate(hmac->macType, &hmac->hash, (byte*)hmac->ipad);
@@ -970,6 +1030,21 @@ int wc_HmacFinal(Hmac* hmac, byte* hash)
9701030
}
9711031
#endif /* WOLFSSL_ASYNC_CRYPT */
9721032

1033+
#if defined(STM32_HASH) && defined(STM32_HMAC)
1034+
if (hmac->innerHashKeyed == WC_HMAC_INNER_HASH_KEYED_DEV) {
1035+
ret = wolfSSL_CryptHwMutexLock();
1036+
if (ret == 0) {
1037+
ret = wc_Stm32_Hmac_Final(&hmac->stmCtx, hmac->macType,
1038+
hmac->stmKey, hmac->stmKeyLen, hash);
1039+
wolfSSL_CryptHwMutexUnLock();
1040+
}
1041+
if (ret == 0) {
1042+
hmac->innerHashKeyed = 0;
1043+
}
1044+
return ret;
1045+
}
1046+
#endif /* STM32_HASH && STM32_HMAC */
1047+
9731048
if (!hmac->innerHashKeyed) {
9741049
#ifndef WOLFSSL_HMAC_COPY_HASH
9751050
ret = HmacKeyHashUpdate(hmac->macType, &hmac->hash, (byte*)hmac->ipad);

wolfcrypt/src/port/st/stm32.c

Lines changed: 291 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -444,6 +444,297 @@ int wc_Stm32_Hash_Final(STM32_HASH_Context* stmCtx, word32 algo,
444444
return ret;
445445
}
446446

447+
#if defined(STM32_HMAC) && !defined(NO_HMAC)
448+
449+
/* STM32 Port HMAC Functions */
450+
#include <wolfssl/wolfcrypt/hmac.h>
451+
452+
int wc_Stm32_Hmac_GetAlgoInfo(int macType, word32* algo, word32* blockSize,
453+
word32* digestSize)
454+
{
455+
int ret = 0;
456+
457+
switch (macType) {
458+
#if !defined(NO_MD5) && !defined(STM32_NOMD5)
459+
case WC_MD5:
460+
if (algo) *algo = HASH_AlgoSelection_MD5;
461+
if (blockSize) *blockSize = WC_MD5_BLOCK_SIZE;
462+
if (digestSize) *digestSize = WC_MD5_DIGEST_SIZE;
463+
break;
464+
#endif
465+
#ifndef NO_SHA
466+
case WC_SHA:
467+
if (algo) *algo = HASH_AlgoSelection_SHA1;
468+
if (blockSize) *blockSize = WC_SHA_BLOCK_SIZE;
469+
if (digestSize) *digestSize = WC_SHA_DIGEST_SIZE;
470+
break;
471+
#endif
472+
#ifdef WOLFSSL_SHA224
473+
case WC_SHA224:
474+
if (algo) *algo = HASH_AlgoSelection_SHA224;
475+
if (blockSize) *blockSize = WC_SHA224_BLOCK_SIZE;
476+
if (digestSize) *digestSize = WC_SHA224_DIGEST_SIZE;
477+
break;
478+
#endif
479+
#ifndef NO_SHA256
480+
case WC_SHA256:
481+
if (algo) *algo = HASH_AlgoSelection_SHA256;
482+
if (blockSize) *blockSize = WC_SHA256_BLOCK_SIZE;
483+
if (digestSize) *digestSize = WC_SHA256_DIGEST_SIZE;
484+
break;
485+
#endif
486+
#ifdef STM32_HASH_SHA384
487+
case WC_SHA384:
488+
if (algo) *algo = HASH_ALGOSELECTION_SHA384;
489+
if (blockSize) *blockSize = WC_SHA384_BLOCK_SIZE;
490+
if (digestSize) *digestSize = WC_SHA384_DIGEST_SIZE;
491+
break;
492+
#endif
493+
#ifdef STM32_HASH_SHA512
494+
case WC_SHA512:
495+
if (algo) *algo = HASH_ALGOSELECTION_SHA512;
496+
if (blockSize) *blockSize = WC_SHA512_BLOCK_SIZE;
497+
if (digestSize) *digestSize = WC_SHA512_DIGEST_SIZE;
498+
break;
499+
#endif
500+
default:
501+
ret = BAD_FUNC_ARG;
502+
break;
503+
}
504+
505+
return ret;
506+
}
507+
508+
static void wc_Stm32_Hmac_RestoreContext(STM32_HASH_Context* ctx,
509+
word32 algo, word32 keyLen, word32 blockSize)
510+
{
511+
int i;
512+
513+
if (ctx->HASH_CR == 0) {
514+
/* first-time init */
515+
516+
#if defined(HASH_IMR_DINIE) && defined(HASH_IMR_DCIE)
517+
/* Disable IRQ's */
518+
HASH->IMR &= ~(HASH_IMR_DINIE | HASH_IMR_DCIE);
519+
#endif
520+
521+
/* reset the control register */
522+
HASH->CR &= ~(HASH_CR_ALGO | HASH_CR_MODE | HASH_CR_DATATYPE
523+
#ifdef HASH_CR_LKEY
524+
| HASH_CR_LKEY
525+
#endif
526+
);
527+
528+
/* configure algorithm, HMAC mode and data type */
529+
HASH->CR |= (algo | HASH_ALGOMODE_HMAC | HASH_DATATYPE_8B);
530+
531+
#ifdef HASH_CR_LKEY
532+
/* set LKEY bit if key is longer than block size */
533+
if (keyLen > blockSize) {
534+
HASH->CR |= HASH_CR_LKEY;
535+
}
536+
#endif
537+
538+
/* reset HASH processor */
539+
HASH->CR |= HASH_CR_INIT;
540+
541+
/* by default mark all bits valid */
542+
wc_Stm32_Hash_NumValidBits(0);
543+
544+
#ifdef DEBUG_STM32_HASH
545+
printf("STM HMAC Init algo %x, keyLen %d\n", (unsigned int)algo,
546+
(int)keyLen);
547+
#endif
548+
}
549+
else {
550+
/* restore context registers */
551+
HASH->IMR = ctx->HASH_IMR;
552+
HASH->STR = ctx->HASH_STR;
553+
HASH->CR = ctx->HASH_CR;
554+
#ifdef STM32_HASH_SHA3
555+
HASH->SHA3CFGR = ctx->SHA3CFGR;
556+
#endif
557+
558+
/* Initialize the hash processor */
559+
HASH->CR |= HASH_CR_INIT;
560+
561+
/* continue restoring context registers */
562+
for (i = 0; i < HASH_CR_SIZE; i++) {
563+
HASH->CSR[i] = ctx->HASH_CSR[i];
564+
}
565+
566+
#ifdef DEBUG_STM32_HASH
567+
printf("STM HMAC Restore CR %lx, IMR %lx, STR %lx\n",
568+
HASH->CR, HASH->IMR, HASH->STR);
569+
#endif
570+
}
571+
572+
(void)keyLen;
573+
(void)blockSize;
574+
}
575+
576+
static void wc_Stm32_Hmac_FeedKey(const byte* key, word32 keySz)
577+
{
578+
word32 i, blocks;
579+
word32 tmp;
580+
581+
/* feed key words into HASH->DIN */
582+
blocks = keySz / STM32_HASH_REG_SIZE;
583+
for (i = 0; i < blocks; i++) {
584+
XMEMCPY(&tmp, key + (i * STM32_HASH_REG_SIZE), STM32_HASH_REG_SIZE);
585+
HASH->DIN = tmp;
586+
}
587+
/* handle remaining bytes in last partial word */
588+
if (keySz % STM32_HASH_REG_SIZE) {
589+
tmp = 0;
590+
XMEMCPY(&tmp, key + (blocks * STM32_HASH_REG_SIZE),
591+
keySz % STM32_HASH_REG_SIZE);
592+
HASH->DIN = tmp;
593+
}
594+
595+
#ifdef DEBUG_STM32_HASH
596+
printf("STM HMAC FeedKey %d bytes\n", (int)keySz);
597+
#endif
598+
}
599+
600+
601+
/* STM32 HMAC Exposed Functions */
602+
603+
int wc_Stm32_Hmac_SetKey(STM32_HASH_Context* stmCtx, int macType,
604+
const byte* key, word32 keySz)
605+
{
606+
int ret;
607+
word32 algo, blockSize, digestSize;
608+
609+
if (stmCtx == NULL || key == NULL)
610+
return BAD_FUNC_ARG;
611+
612+
ret = wc_Stm32_Hmac_GetAlgoInfo(macType, &algo, &blockSize, &digestSize);
613+
if (ret != 0)
614+
return ret;
615+
616+
#ifdef DEBUG_STM32_HASH
617+
printf("STM HMAC SetKey: macType %d, keySz %d\n", macType, (int)keySz);
618+
#endif
619+
620+
/* clear context for fresh HMAC */
621+
wc_Stm32_Hash_Init(stmCtx);
622+
623+
/* turn on hash clock */
624+
STM32_HASH_CLOCK_ENABLE(stmCtx);
625+
626+
/* initialize hardware for HMAC mode */
627+
wc_Stm32_Hmac_RestoreContext(stmCtx, algo, keySz, blockSize);
628+
629+
/* Phase 1: Feed key into HASH->DIN */
630+
wc_Stm32_Hmac_FeedKey(key, keySz);
631+
632+
/* set number of valid bits in last word and trigger DCAL */
633+
wc_Stm32_Hash_NumValidBits(keySz);
634+
HASH->STR |= HASH_STR_DCAL;
635+
636+
/* wait for data input ready (phase 1 complete) */
637+
ret = wc_Stm32_Hash_WaitDataReady(stmCtx);
638+
639+
if (ret == 0) {
640+
/* save context for context switching */
641+
wc_Stm32_Hash_SaveContext(stmCtx);
642+
}
643+
644+
/* turn off hash clock */
645+
STM32_HASH_CLOCK_DISABLE(stmCtx);
646+
647+
return ret;
648+
}
649+
650+
int wc_Stm32_Hmac_Update(STM32_HASH_Context* stmCtx, int macType,
651+
const byte* data, word32 len)
652+
{
653+
int ret;
654+
word32 algo, blockSize, digestSize;
655+
656+
if (stmCtx == NULL || (data == NULL && len > 0))
657+
return BAD_FUNC_ARG;
658+
if (len == 0)
659+
return 0;
660+
661+
ret = wc_Stm32_Hmac_GetAlgoInfo(macType, &algo, &blockSize, &digestSize);
662+
if (ret != 0)
663+
return ret;
664+
665+
#ifdef DEBUG_STM32_HASH
666+
printf("STM HMAC Update: macType %d, len %d\n", macType, (int)len);
667+
#endif
668+
669+
/* Reuse Hash_Update - the saved context CR already contains
670+
* HASH_ALGOMODE_HMAC, so RestoreContext will preserve HMAC mode */
671+
ret = wc_Stm32_Hash_Update(stmCtx, algo, data, len, blockSize);
672+
673+
return ret;
674+
}
675+
676+
int wc_Stm32_Hmac_Final(STM32_HASH_Context* stmCtx, int macType,
677+
const byte* key, word32 keySz, byte* hash)
678+
{
679+
int ret;
680+
word32 algo, blockSize, digestSize;
681+
682+
if (stmCtx == NULL || key == NULL || hash == NULL)
683+
return BAD_FUNC_ARG;
684+
685+
ret = wc_Stm32_Hmac_GetAlgoInfo(macType, &algo, &blockSize, &digestSize);
686+
if (ret != 0)
687+
return ret;
688+
689+
#ifdef DEBUG_STM32_HASH
690+
printf("STM HMAC Final: macType %d, keySz %d, buffLen %d, fifoBytes %d\n",
691+
macType, (int)keySz, (int)stmCtx->buffLen, (int)stmCtx->fifoBytes);
692+
#endif
693+
694+
/* turn on hash clock */
695+
STM32_HASH_CLOCK_ENABLE(stmCtx);
696+
697+
/* restore HMAC context */
698+
wc_Stm32_Hash_RestoreContext(stmCtx, algo);
699+
700+
/* finish reading any trailing bytes into FIFO */
701+
if (stmCtx->buffLen > 0) {
702+
wc_Stm32_Hash_Data(stmCtx, stmCtx->buffLen);
703+
}
704+
705+
/* Phase 2 complete: set valid bits and trigger DCAL */
706+
wc_Stm32_Hash_NumValidBits(stmCtx->loLen + stmCtx->buffLen);
707+
HASH->STR |= HASH_STR_DCAL;
708+
709+
/* wait for data input ready (phase 2 complete, ready for phase 3) */
710+
ret = wc_Stm32_Hash_WaitDataReady(stmCtx);
711+
if (ret != 0) {
712+
STM32_HASH_CLOCK_DISABLE(stmCtx);
713+
return ret;
714+
}
715+
716+
/* Phase 3: Feed key again into HASH->DIN */
717+
wc_Stm32_Hmac_FeedKey(key, keySz);
718+
719+
/* set valid bits for key and trigger DCAL */
720+
wc_Stm32_Hash_NumValidBits(keySz);
721+
HASH->STR |= HASH_STR_DCAL;
722+
723+
/* wait for hash done (digest computation complete) */
724+
ret = wc_Stm32_Hash_WaitCalcComp(stmCtx);
725+
if (ret == 0) {
726+
/* read message digest */
727+
wc_Stm32_Hash_GetDigest(hash, digestSize);
728+
}
729+
730+
/* turn off hash clock */
731+
STM32_HASH_CLOCK_DISABLE(stmCtx);
732+
733+
return ret;
734+
}
735+
736+
#endif /* STM32_HMAC && !NO_HMAC */
737+
447738
#endif /* STM32_HASH */
448739

449740

0 commit comments

Comments
 (0)