From 1fb8cf0d619ea50de99b797e12e927cbd597d108 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Thu, 9 Apr 2026 16:53:39 +0200 Subject: [PATCH 1/9] MAX32666 bare-metal SHA accelerator --- wolfcrypt/src/port/maxim/max3266x.c | 873 ++++++++++++++---------- wolfssl/wolfcrypt/port/maxim/max3266x.h | 141 ++-- 2 files changed, 553 insertions(+), 461 deletions(-) diff --git a/wolfcrypt/src/port/maxim/max3266x.c b/wolfcrypt/src/port/maxim/max3266x.c index e326ecadbe..efbec9424a 100644 --- a/wolfcrypt/src/port/maxim/max3266x.c +++ b/wolfcrypt/src/port/maxim/max3266x.c @@ -136,67 +136,126 @@ int wc_MxcAesCryptoCb(wc_CryptoInfo* info) #ifdef MAX3266X_SHA_CB -/* Shared callback handler: Update grows buffer, Final computes hash. */ -static int wc_MxcShaCbDispatch(byte** msg, word32* used, word32* len, - void* heap, const byte* in, word32 inSz, - byte* digest, MXC_TPU_HASH_TYPE algo) +int wc_MXC_TPU_SHA_Update(unsigned int* digest, unsigned int* buffer, + unsigned int* buffLen, unsigned int* loLen, + unsigned int* hiLen, int stateWords, + unsigned int blockSz, MXC_TPU_HASH_TYPE algo, + const unsigned char* data, unsigned int len); +int wc_MXC_TPU_SHA_Final(unsigned int* digest, unsigned int* buffer, + unsigned int* buffLen, unsigned int loLen, + unsigned int hiLen, int stateWords, + unsigned int digestSz, MXC_TPU_HASH_TYPE algo, + unsigned char* hash); +static int wc_MXC_TPU_SHA_Init(unsigned int* digest, int stateWords, + MXC_TPU_HASH_TYPE algo); + +static int wc_MxcShaCbDispatch( + unsigned int* digest, unsigned int* buffer, + unsigned int* buffLen, unsigned int* loLen, + unsigned int* hiLen, int stateWords, + unsigned int blockSz, unsigned int digestSz, + MXC_TPU_HASH_TYPE algo, + const unsigned char* in, unsigned int inSz, + unsigned char* outDigest) { - if (in != NULL && digest == NULL) { + if (in != NULL && outDigest == NULL) { MAX3266X_MSG("Update CB"); - return _wc_Hash_Grow(msg, used, len, in, (int)inSz, heap); + return wc_MXC_TPU_SHA_Update(digest, buffer, buffLen, loLen, hiLen, + stateWords, blockSz, algo, in, inSz); } - if (in == NULL && digest != NULL) { + if (in == NULL && outDigest != NULL) { + int ret; MAX3266X_MSG("Final CB"); - return wc_MXC_TPU_SHA_Final(msg, used, len, heap, digest, algo); + ret = wc_MXC_TPU_SHA_Final(digest, buffer, buffLen, + *loLen, *hiLen, stateWords, + digestSz, algo, outDigest); + /* Reset context state for reuse */ + if (ret == 0) { + *buffLen = 0; + *loLen = 0; + *hiLen = 0; + XMEMSET(buffer, 0, blockSz); + ret = wc_MXC_TPU_SHA_Init(digest, stateWords, algo); + } + return ret; } if (inSz == 0) { - return 0; /* Don't need to Update when Size is Zero */ + return 0; /* Don't need to Update when size is zero */ } return BAD_FUNC_ARG; } +/* SHA-384/512 callback helper: bridges word64 loLen to unsigned int pair + * and delegates to wc_MxcShaCbDispatch. */ +static int wc_MxcShaCbDispatch512(wc_Sha512* ctx, int stateWords, + unsigned int blockSz, unsigned int digestSz, + MXC_TPU_HASH_TYPE algo, + const unsigned char* in, unsigned int inSz, + unsigned char* digest) +{ + unsigned int loLen = (unsigned int)ctx->loLen; + unsigned int hiLen = (unsigned int)(ctx->loLen >> 32); + int ret; + + ret = wc_MxcShaCbDispatch((unsigned int*)ctx->digest, + (unsigned int*)ctx->buffer, + &ctx->buffLen, &loLen, &hiLen, + stateWords, blockSz, digestSz, algo, + in, inSz, digest); + + ctx->loLen = (word64)loLen | ((word64)hiLen << 32); + return ret; +} + int wc_MxcShaCryptoCb(wc_CryptoInfo* info) { switch (info->hash.type) { #ifndef NO_SHA case WC_HASH_TYPE_SHA: - return wc_MxcShaCbDispatch(&info->hash.sha1->msg, - &info->hash.sha1->used, &info->hash.sha1->len, - info->hash.sha1->heap, info->hash.in, - info->hash.inSz, info->hash.digest, - MXC_TPU_HASH_SHA1); + return wc_MxcShaCbDispatch( + info->hash.sha1->digest, + info->hash.sha1->buffer, + &info->hash.sha1->buffLen, + &info->hash.sha1->loLen, &info->hash.sha1->hiLen, + MXC_SHA1_STATE_WORDS, WC_SHA_BLOCK_SIZE, + WC_SHA_DIGEST_SIZE, MXC_TPU_HASH_SHA1, + info->hash.in, info->hash.inSz, info->hash.digest); #endif #ifdef WOLFSSL_SHA224 case WC_HASH_TYPE_SHA224: - return wc_MxcShaCbDispatch(&info->hash.sha224->msg, - &info->hash.sha224->used, &info->hash.sha224->len, - info->hash.sha224->heap, info->hash.in, - info->hash.inSz, info->hash.digest, - MXC_TPU_HASH_SHA224); + return wc_MxcShaCbDispatch( + info->hash.sha224->digest, + info->hash.sha224->buffer, + &info->hash.sha224->buffLen, + &info->hash.sha224->loLen, &info->hash.sha224->hiLen, + MXC_SHA224_STATE_WORDS, WC_SHA224_BLOCK_SIZE, + WC_SHA224_DIGEST_SIZE, MXC_TPU_HASH_SHA224, + info->hash.in, info->hash.inSz, info->hash.digest); #endif #ifndef NO_SHA256 case WC_HASH_TYPE_SHA256: - return wc_MxcShaCbDispatch(&info->hash.sha256->msg, - &info->hash.sha256->used, &info->hash.sha256->len, - info->hash.sha256->heap, info->hash.in, - info->hash.inSz, info->hash.digest, - MXC_TPU_HASH_SHA256); + return wc_MxcShaCbDispatch( + info->hash.sha256->digest, + info->hash.sha256->buffer, + &info->hash.sha256->buffLen, + &info->hash.sha256->loLen, &info->hash.sha256->hiLen, + MXC_SHA256_STATE_WORDS, WC_SHA256_BLOCK_SIZE, + WC_SHA256_DIGEST_SIZE, MXC_TPU_HASH_SHA256, + info->hash.in, info->hash.inSz, info->hash.digest); #endif #ifdef WOLFSSL_SHA384 case WC_HASH_TYPE_SHA384: - return wc_MxcShaCbDispatch(&info->hash.sha384->msg, - &info->hash.sha384->used, &info->hash.sha384->len, - info->hash.sha384->heap, info->hash.in, - info->hash.inSz, info->hash.digest, - MXC_TPU_HASH_SHA384); + return wc_MxcShaCbDispatch512(info->hash.sha384, + MXC_SHA384_STATE_WORDS, WC_SHA384_BLOCK_SIZE, + WC_SHA384_DIGEST_SIZE, MXC_TPU_HASH_SHA384, + info->hash.in, info->hash.inSz, info->hash.digest); #endif #ifdef WOLFSSL_SHA512 case WC_HASH_TYPE_SHA512: - return wc_MxcShaCbDispatch(&info->hash.sha512->msg, - &info->hash.sha512->used, &info->hash.sha512->len, - info->hash.sha512->heap, info->hash.in, - info->hash.inSz, info->hash.digest, - MXC_TPU_HASH_SHA512); + return wc_MxcShaCbDispatch512(info->hash.sha512, + MXC_SHA512_STATE_WORDS, WC_SHA512_BLOCK_SIZE, + WC_SHA512_DIGEST_SIZE, MXC_TPU_HASH_SHA512, + info->hash.in, info->hash.inSz, info->hash.digest); #endif default: return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); @@ -207,6 +266,8 @@ int wc_MxcShaCryptoCb(wc_CryptoInfo* info) #ifdef WOLF_CRYPTO_CB_COPY static int wc_MxcCopyCb(wc_CryptoInfo* info) { + word32 sz; + if (info == NULL || info->copy.src == NULL || info->copy.dst == NULL) { return BAD_FUNC_ARG; } @@ -214,123 +275,29 @@ static int wc_MxcCopyCb(wc_CryptoInfo* info) switch (info->copy.type) { #ifdef MAX3266X_SHA_CB #ifndef NO_SHA - case WC_HASH_TYPE_SHA: - return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, - sizeof(wc_Sha), - &((wc_Sha*)info->copy.dst)->msg, - &((wc_Sha*)info->copy.dst)->used, - &((wc_Sha*)info->copy.dst)->len, - ((wc_Sha*)info->copy.dst)->heap, - ((wc_Sha*)info->copy.src)->heap); + case WC_HASH_TYPE_SHA: sz = sizeof(wc_Sha); break; #endif #ifdef WOLFSSL_SHA224 - case WC_HASH_TYPE_SHA224: - return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, - sizeof(wc_Sha224), - &((wc_Sha224*)info->copy.dst)->msg, - &((wc_Sha224*)info->copy.dst)->used, - &((wc_Sha224*)info->copy.dst)->len, - ((wc_Sha224*)info->copy.dst)->heap, - ((wc_Sha224*)info->copy.src)->heap); + case WC_HASH_TYPE_SHA224: sz = sizeof(wc_Sha224); break; #endif #ifndef NO_SHA256 - case WC_HASH_TYPE_SHA256: - return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, - sizeof(wc_Sha256), - &((wc_Sha256*)info->copy.dst)->msg, - &((wc_Sha256*)info->copy.dst)->used, - &((wc_Sha256*)info->copy.dst)->len, - ((wc_Sha256*)info->copy.dst)->heap, - ((wc_Sha256*)info->copy.src)->heap); + case WC_HASH_TYPE_SHA256: sz = sizeof(wc_Sha256); break; #endif #ifdef WOLFSSL_SHA384 - case WC_HASH_TYPE_SHA384: - return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, - sizeof(wc_Sha384), - &((wc_Sha384*)info->copy.dst)->msg, - &((wc_Sha384*)info->copy.dst)->used, - &((wc_Sha384*)info->copy.dst)->len, - ((wc_Sha384*)info->copy.dst)->heap, - ((wc_Sha384*)info->copy.src)->heap); + case WC_HASH_TYPE_SHA384: sz = sizeof(wc_Sha384); break; #endif #ifdef WOLFSSL_SHA512 - case WC_HASH_TYPE_SHA512: - return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, - sizeof(wc_Sha512), - &((wc_Sha512*)info->copy.dst)->msg, - &((wc_Sha512*)info->copy.dst)->used, - &((wc_Sha512*)info->copy.dst)->len, - ((wc_Sha512*)info->copy.dst)->heap, - ((wc_Sha512*)info->copy.src)->heap); + case WC_HASH_TYPE_SHA512: sz = sizeof(wc_Sha512); break; #endif #endif /* MAX3266X_SHA_CB */ default: return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); } + XMEMCPY(info->copy.dst, info->copy.src, sz); + return 0; } #endif /* WOLF_CRYPTO_CB_COPY */ -#ifdef WOLF_CRYPTO_CB_FREE -static int wc_MxcFreeCb(wc_CryptoInfo* info) -{ - if (info == NULL || info->free.obj == NULL) { - return BAD_FUNC_ARG; - } - - switch (info->free.type) { -#ifdef MAX3266X_SHA_CB - #ifndef NO_SHA - case WC_HASH_TYPE_SHA: - wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha), - &((wc_Sha*)info->free.obj)->msg, - &((wc_Sha*)info->free.obj)->used, - &((wc_Sha*)info->free.obj)->len, - ((wc_Sha*)info->free.obj)->heap); - return 0; - #endif - #ifdef WOLFSSL_SHA224 - case WC_HASH_TYPE_SHA224: - wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha224), - &((wc_Sha224*)info->free.obj)->msg, - &((wc_Sha224*)info->free.obj)->used, - &((wc_Sha224*)info->free.obj)->len, - ((wc_Sha224*)info->free.obj)->heap); - return 0; - #endif - #ifndef NO_SHA256 - case WC_HASH_TYPE_SHA256: - wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha256), - &((wc_Sha256*)info->free.obj)->msg, - &((wc_Sha256*)info->free.obj)->used, - &((wc_Sha256*)info->free.obj)->len, - ((wc_Sha256*)info->free.obj)->heap); - return 0; - #endif - #ifdef WOLFSSL_SHA384 - case WC_HASH_TYPE_SHA384: - wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha384), - &((wc_Sha384*)info->free.obj)->msg, - &((wc_Sha384*)info->free.obj)->used, - &((wc_Sha384*)info->free.obj)->len, - ((wc_Sha384*)info->free.obj)->heap); - return 0; - #endif - #ifdef WOLFSSL_SHA512 - case WC_HASH_TYPE_SHA512: - wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha512), - &((wc_Sha512*)info->free.obj)->msg, - &((wc_Sha512*)info->free.obj)->used, - &((wc_Sha512*)info->free.obj)->len, - ((wc_Sha512*)info->free.obj)->heap); - return 0; - #endif -#endif /* MAX3266X_SHA_CB */ - default: - return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); - } -} -#endif /* WOLF_CRYPTO_CB_FREE */ - /* General Callback Function to determine ALGO Type */ int wc_MxcCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx) { @@ -363,14 +330,10 @@ int wc_MxcCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx) ret = wc_MxcCopyCb(info); break; #endif /* WOLF_CRYPTO_CB_COPY */ -#ifdef WOLF_CRYPTO_CB_FREE - case WC_ALGO_TYPE_FREE: - MAX3266X_MSG("Using MXC Free Callback:"); - ret = wc_MxcFreeCb(info); - break; -#endif /* WOLF_CRYPTO_CB_FREE */ + /* No WC_ALGO_TYPE_FREE needed: SHA contexts have no heap + * allocations to clean up. */ default: - MAX3266X_MSG("Callback not support with MXC, using SW"); + MAX3266X_MSG("Callback not supported with MXC, using SW"); /* return this to bypass HW and use SW */ ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); } @@ -691,169 +654,280 @@ int wc_MxcCb_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) #if defined(MAX3266X_SHA) || defined(MAX3266X_SHA_CB) -/* Check for empty message and provide pre-computed digest if so */ -/* Returns 1 if empty (digest filled), 0 if needs hardware processing */ -int wc_MXC_TPU_SHA_GetDigest(const unsigned char* msg, unsigned int msgSz, - unsigned char* digest, - MXC_TPU_HASH_TYPE algo) +/* TPU hash helpers (bare-metal SHA accelerator) */ + +/* Reset TPU, select hash function, and restore intermediate state into + * the HASH_DIGEST registers. Does NOT set INIT - caller provides state. */ +void wc_MXC_TPU_Hash_Setup(MXC_TPU_HASH_TYPE algo, + const unsigned int* state, int stateWords) { - if (digest == NULL) { - return BAD_FUNC_ARG; + int i; + + /* Init TPU clock */ + MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TPU); + + /* Reset TPU */ + MXC_TPU->ctrl = MXC_F_TPU_CTRL_RST; + while (!(MXC_TPU->ctrl & MXC_F_TPU_CTRL_RDY)) {} + MXC_TPU->ctrl |= MXC_F_TPU_CTRL_FLAG_MODE; + + /* Select hash function and INIT to prime the hardware's internal state */ + MXC_TPU->hash_ctrl = ((unsigned int)algo << MXC_F_TPU_HASH_CTRL_HASH_POS) + | MXC_F_TPU_HASH_CTRL_INIT; + while (MXC_TPU->hash_ctrl & MXC_F_TPU_HASH_CTRL_INIT) {} + + /* Overwrite the standard IV with our saved intermediate state */ + for (i = 0; i < stateWords; i++) { + MXC_TPU->hash_digest[i] = state[i]; } - if (msg == NULL && msgSz == 0) { - switch (algo) { - #ifndef NO_SHA - case MXC_TPU_HASH_SHA1: - XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA1, WC_SHA_DIGEST_SIZE); - break; - #endif /* NO_SHA */ - #ifdef WOLFSSL_SHA224 - case MXC_TPU_HASH_SHA224: - XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA224, WC_SHA224_DIGEST_SIZE); - break; - #endif /* WOLFSSL_SHA224 */ - #ifndef NO_SHA256 - case MXC_TPU_HASH_SHA256: - XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA256, WC_SHA256_DIGEST_SIZE); - break; - #endif /* NO_SHA256 */ - #ifdef WOLFSSL_SHA384 - case MXC_TPU_HASH_SHA384: - XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA384, WC_SHA384_DIGEST_SIZE); - break; - #endif /* WOLFSSL_SHA384 */ - #ifdef WOLFSSL_SHA512 - case MXC_TPU_HASH_SHA512: - XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA512, WC_SHA512_DIGEST_SIZE); - break; - #endif /* WOLFSSL_SHA512 */ - default: - return BAD_FUNC_ARG; - } - return 1; /* True: empty digest provided */ - } - return 0; /* False: needs hardware processing */ } -/* Compute hash from accumulated message using TPU hardware */ -int wc_MXC_TPU_SHA_GetHash(const unsigned char* msg, unsigned int msgSz, - unsigned char* digest, - MXC_TPU_HASH_TYPE algo) +/* Feed one complete block to the TPU and wait for completion. */ +void wc_MXC_TPU_Hash_Feed_Block(const unsigned char* data, + unsigned int blockSz) +{ + unsigned int word; + + MXC_TPU->ctrl |= MXC_F_TPU_CTRL_DMA_DONE | MXC_F_TPU_CTRL_GLS_DONE | + MXC_F_TPU_CTRL_HSH_DONE | MXC_F_TPU_CTRL_CPH_DONE | + MXC_F_TPU_CTRL_MAA_DONE; + + for (word = 0; word < blockSz; word += 4) { + while (!(MXC_TPU->ctrl & MXC_F_TPU_CTRL_RDY)) {} + MXC_TPU->data_in[0] = (unsigned int)data[word] + | ((unsigned int)data[word + 1] << 8) + | ((unsigned int)data[word + 2] << 16) + | ((unsigned int)data[word + 3] << 24); + } + + while (!(MXC_TPU->ctrl & MXC_F_TPU_CTRL_HSH_DONE)) {} +} + +/* Feed the last (possibly partial) block with LAST flag and msg size. */ +void wc_MXC_TPU_Hash_Feed_Last(const unsigned char* data, + unsigned int dataLen, + unsigned int totalLenLo, + unsigned int totalLenHi) +{ + unsigned int word; + + /* Set total message size for padding calculation */ + MXC_TPU->hash_msg_sz[0] = totalLenLo; + MXC_TPU->hash_msg_sz[1] = totalLenHi; + + /* Signal this is the last block */ + MXC_TPU->hash_ctrl |= MXC_F_TPU_HASH_CTRL_LAST; + + /* Empty message: the hardware needs a dummy write to data_in to + * trigger processing of the padding-only block. */ + if (totalLenLo == 0 && totalLenHi == 0) { + while (!(MXC_TPU->ctrl & MXC_F_TPU_CTRL_RDY)) {} + MXC_TPU->data_in[0] = 0; + } + + for (word = 0; word < dataLen; word += 4) { + while (!(MXC_TPU->ctrl & MXC_F_TPU_CTRL_RDY)) {} + if (dataLen >= (word + 4)) { + MXC_TPU->data_in[0] = (unsigned int)data[word] + | ((unsigned int)data[word + 1] << 8) + | ((unsigned int)data[word + 2] << 16) + | ((unsigned int)data[word + 3] << 24); + } + else if ((dataLen & 3) == 1) { + MXC_TPU->data_in[0] = (unsigned int)data[word]; + } + else if ((dataLen & 3) == 2) { + MXC_TPU->data_in[0] = (unsigned int)data[word] + | ((unsigned int)data[word + 1] << 8); + } + else if ((dataLen & 3) == 3) { + MXC_TPU->data_in[0] = (unsigned int)data[word] + | ((unsigned int)data[word + 1] << 8) + | ((unsigned int)data[word + 2] << 16); + } + } + + while (!(MXC_TPU->ctrl & MXC_F_TPU_CTRL_HSH_DONE)) {} +} + +/* Save intermediate hash state from hardware registers into context. */ +void wc_MXC_TPU_Hash_Save_State(unsigned int* state, int stateWords) +{ + int i; + for (i = 0; i < stateWords; i++) { + state[i] = MXC_TPU->hash_digest[i]; + } +} + +/* Read final digest from hardware registers. */ +void wc_MXC_TPU_Hash_Read_Digest(unsigned char* digest, unsigned int digestSz) +{ + XMEMCPY(digest, (const void*)MXC_TPU->hash_digest, digestSz); +} + +/* Generic Update */ +int wc_MXC_TPU_SHA_Update(unsigned int* digest, unsigned int* buffer, + unsigned int* buffLen, unsigned int* loLen, + unsigned int* hiLen, int stateWords, + unsigned int blockSz, MXC_TPU_HASH_TYPE algo, + const unsigned char* data, unsigned int len) { int status; - if (digest == NULL || (msg == NULL && msgSz != 0)) { - return BAD_FUNC_ARG; - } - status = wc_MXC_TPU_SHA_GetDigest(msg, msgSz, digest, algo); - /* True Case that msg is an empty string */ - if (status == 1) { - /* Hardware cannot handle the case of an empty string */ - /* so in the case of this we will provide the hash via software */ + unsigned int fill; + + if (len == 0) { return 0; } - /* False Case where msg needs to be processed */ - else if (status == 0) { - status = wolfSSL_HwHashMutexLock(); /* Set Mutex */ - if (status != 0) { /* Mutex Call Check */ - return status; + + /* Update total length */ + { + unsigned int oldLo = *loLen; + *loLen += len; + if (*loLen < oldLo) { + (*hiLen)++; } - MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TPU); - MXC_TPU_Hash_Config(algo); - status = MXC_TPU_Hash_SHA((const char *)msg, algo, msgSz, - (char *)digest); + } + + /* If there's existing buffered data, try to complete a block */ + if (*buffLen > 0) { + fill = blockSz - *buffLen; + if (len < fill) { + XMEMCPY((unsigned char*)buffer + *buffLen, data, len); + *buffLen += len; + return 0; + } + XMEMCPY((unsigned char*)buffer + *buffLen, data, fill); + data += fill; + len -= fill; + + /* Only process the completed buffer block if there's more data + * coming. The TPU requires LAST to be set with real data (unless the + * entire message is empty), so we always keep at least one block + * buffered for Final. */ + if (len > 0) { + *buffLen = 0; + status = wolfSSL_HwHashMutexLock(); + if (status != 0) return status; + wc_MXC_TPU_Hash_Setup(algo, digest, stateWords); + wc_MXC_TPU_Hash_Feed_Block((const unsigned char*)buffer, blockSz); + wc_MXC_TPU_Hash_Save_State(digest, stateWords); + MAX3266X_MSG("SHA HW Acceleration Used"); + wolfSSL_HwHashMutexUnLock(); + } + else { + *buffLen = blockSz; + return 0; + } + } + + /* Process full blocks directly from input, always leaving the last + * complete block buffered so Final has data to feed with LAST. */ + if (len > blockSz) { + status = wolfSSL_HwHashMutexLock(); + if (status != 0) return status; + wc_MXC_TPU_Hash_Setup(algo, digest, stateWords); + + while (len > blockSz) { + wc_MXC_TPU_Hash_Feed_Block(data, blockSz); + data += blockSz; + len -= blockSz; + } + + wc_MXC_TPU_Hash_Save_State(digest, stateWords); MAX3266X_MSG("SHA HW Acceleration Used"); - wolfSSL_HwHashMutexUnLock(); /* Release Mutex */ - if (wc_MXC_error(&status) != 0) { - MAX3266X_MSG("SHA HW Error Occurred"); - return status; - } - } - /* Error Occurred */ - return status; -} - -/* Free HASH_KEEP message buffer and reset fields */ -void wc_MXC_TPU_SHA_Free(byte** msg, word32* used, word32* len, void* heap) -{ - if (msg == NULL) { - return; - } - if (*msg != NULL) { - XFREE(*msg, heap, DYNAMIC_TYPE_TMP_BUFFER); - *msg = NULL; - } - if (used != NULL) { - *used = 0; - } - if (len != NULL) { - *len = 0; - } -} - -/* Free HASH_KEEP message buffer and zero the full SHA context struct */ -void wc_MXC_TPU_SHA_FreeCtx(void* ctx, word32 ctxSz, byte** msg, word32* used, - word32* len, void* heap) -{ - if (ctx == NULL) { - return; - } - wc_MXC_TPU_SHA_Free(msg, used, len, heap); - XMEMSET(ctx, 0, ctxSz); -} - -/* Copy SHA context struct and deep copy the HASH_KEEP message buffer. - * Frees any existing dst msg buffer to prevent memory leaks when copying - * into an already-used context. */ -int wc_MXC_TPU_SHA_Copy(void* src, void* dst, word32 ctxSz, - byte** dstMsg, word32* dstUsed, word32* dstLen, - void* dstHeap, void* srcHeap) -{ - byte* srcBuf = NULL; - - if (src == NULL || dst == NULL || dstMsg == NULL || - dstUsed == NULL || dstLen == NULL || ctxSz == 0) { - return BAD_FUNC_ARG; + wolfSSL_HwHashMutexUnLock(); } - /* Free existing dst msg buffer using dst's original heap */ - wc_MXC_TPU_SHA_Free(dstMsg, dstUsed, dstLen, dstHeap); - - /* Shallow copy the full context struct */ - XMEMCPY(dst, src, ctxSz); - - /* Deep copy src msg buffer if present. Since dstMsg points into the dst - * struct, the XMEMCPY above overwrites it with the src's msg pointer. - * Save that pointer, allocate a new buffer for dst, and copy the data. - * Do NOT move srcBuf assignment before XMEMCPY - it must capture the - * src msg pointer that lands in *dstMsg after the shallow copy. */ - if (*dstMsg != NULL) { - srcBuf = *dstMsg; - *dstMsg = (byte*)XMALLOC(*dstLen, srcHeap, DYNAMIC_TYPE_TMP_BUFFER); - if (*dstMsg == NULL) { - return MEMORY_E; - } - XMEMCPY(*dstMsg, srcBuf, *dstUsed); + /* Buffer remaining data (1..blockSz bytes) */ + if (len > 0) { + XMEMCPY((unsigned char*)buffer, data, len); + *buffLen = len; } return 0; } -/* Compute hash, free message buffer, and reset HASH_KEEP fields */ -int wc_MXC_TPU_SHA_Final(unsigned char** msg, unsigned int* used, - unsigned int* len, void* heap, - unsigned char* digest, - MXC_TPU_HASH_TYPE algo) +/* Generic Final */ +int wc_MXC_TPU_SHA_Final(unsigned int* digest, unsigned int* buffer, + unsigned int* buffLen, unsigned int loLen, + unsigned int hiLen, int stateWords, + unsigned int digestSz, MXC_TPU_HASH_TYPE algo, + unsigned char* hash) { int status; - if (msg == NULL || used == NULL || len == NULL || digest == NULL) { - return BAD_FUNC_ARG; - } - status = wc_MXC_TPU_SHA_GetHash(*msg, *used, digest, algo); - wc_MXC_TPU_SHA_Free(msg, used, len, heap); - return status; + + status = wolfSSL_HwHashMutexLock(); + if (status != 0) return status; + + wc_MXC_TPU_Hash_Setup(algo, digest, stateWords); + wc_MXC_TPU_Hash_Feed_Last((const unsigned char*)buffer, *buffLen, + loLen, hiLen); + wc_MXC_TPU_Hash_Read_Digest(hash, digestSz); + MAX3266X_MSG("SHA HW Acceleration Used"); + + wolfSSL_HwHashMutexUnLock(); + return 0; } +/* Generic GetHash */ +int wc_MXC_TPU_SHA_GetHash(unsigned int* digest, unsigned int* buffer, + unsigned int buffLen, unsigned int loLen, + unsigned int hiLen, int stateWords, + unsigned int digestSz, MXC_TPU_HASH_TYPE algo, + unsigned char* hash) +{ + int status; + /* Use copies so we don't modify the real context */ + unsigned int tmpDigest[MXC_SHA512_STATE_WORDS]; + unsigned int tmpBuf[128 / sizeof(unsigned int)]; /* max block: 1024 bits */ + + XMEMCPY(tmpDigest, digest, stateWords * sizeof(unsigned int)); + if (buffLen > 0) { + XMEMCPY(tmpBuf, buffer, buffLen); + } + + status = wolfSSL_HwHashMutexLock(); + if (status != 0) return status; + + wc_MXC_TPU_Hash_Setup(algo, tmpDigest, stateWords); + wc_MXC_TPU_Hash_Feed_Last((const unsigned char*)tmpBuf, buffLen, + loLen, hiLen); + wc_MXC_TPU_Hash_Read_Digest(hash, digestSz); + MAX3266X_MSG("SHA HW Acceleration Used"); + + wolfSSL_HwHashMutexUnLock(); + return 0; +} + +/* Init helper: use TPU INIT to get the standard IV for any algorithm */ +static int wc_MXC_TPU_SHA_Init(unsigned int* digest, int stateWords, + MXC_TPU_HASH_TYPE algo) +{ + int status = wolfSSL_HwHashMutexLock(); + if (status != 0) return status; + + MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TPU); + MXC_TPU->ctrl = MXC_F_TPU_CTRL_RST; + while (!(MXC_TPU->ctrl & MXC_F_TPU_CTRL_RDY)) {} + MXC_TPU->ctrl |= MXC_F_TPU_CTRL_FLAG_MODE; + + /* Select hash function and trigger INIT to load standard IV */ + MXC_TPU->hash_ctrl = (unsigned int)algo << MXC_F_TPU_HASH_CTRL_HASH_POS; + MXC_TPU->hash_ctrl |= MXC_F_TPU_HASH_CTRL_INIT; + while (MXC_TPU->hash_ctrl & MXC_F_TPU_HASH_CTRL_INIT) {} + + /* Save the standard IV into the context */ + wc_MXC_TPU_Hash_Save_State(digest, stateWords); + + wolfSSL_HwHashMutexUnLock(); + return 0; +} + +/* Per-algorithm Init / Update / Final / GetHash / Copy / Free */ + #ifndef MAX3266X_SHA_CB +/* Non-callback path: provide the wc_Sha* API functions directly */ + #if !defined(NO_SHA) WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) @@ -864,26 +938,36 @@ WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) (void)devId; XMEMSET(sha, 0, sizeof(*sha)); sha->heap = heap; - return 0; + return wc_MXC_TPU_SHA_Init(sha->digest, MXC_SHA1_STATE_WORDS, + MXC_TPU_HASH_SHA1); } WOLFSSL_API int wc_ShaUpdate(wc_Sha* sha, const unsigned char* data, - unsigned int len) + unsigned int len) { if (sha == NULL || (data == NULL && len > 0)) { return BAD_FUNC_ARG; } - return _wc_Hash_Grow(&sha->msg, &sha->used, &sha->len, - data, (int)len, sha->heap); + return wc_MXC_TPU_SHA_Update(sha->digest, + sha->buffer, &sha->buffLen, &sha->loLen, &sha->hiLen, + MXC_SHA1_STATE_WORDS, WC_SHA_BLOCK_SIZE, + MXC_TPU_HASH_SHA1, data, len); } WOLFSSL_API int wc_ShaFinal(wc_Sha* sha, unsigned char* hash) { + int ret; if (sha == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Final(&sha->msg, &sha->used, &sha->len, - sha->heap, hash, MXC_TPU_HASH_SHA1); + ret = wc_MXC_TPU_SHA_Final(sha->digest, + sha->buffer, &sha->buffLen, sha->loLen, sha->hiLen, + MXC_SHA1_STATE_WORDS, + WC_SHA_DIGEST_SIZE, MXC_TPU_HASH_SHA1, hash); + if (ret == 0) { + return wc_InitSha_ex(sha, sha->heap, INVALID_DEVID); + } + return ret; } WOLFSSL_API int wc_ShaGetHash(wc_Sha* sha, unsigned char* hash) @@ -891,8 +975,10 @@ WOLFSSL_API int wc_ShaGetHash(wc_Sha* sha, unsigned char* hash) if (sha == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha->msg, - sha->used, hash, MXC_TPU_HASH_SHA1); + return wc_MXC_TPU_SHA_GetHash(sha->digest, + sha->buffer, sha->buffLen, sha->loLen, sha->hiLen, + MXC_SHA1_STATE_WORDS, + WC_SHA_DIGEST_SIZE, MXC_TPU_HASH_SHA1, hash); } WOLFSSL_API int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) @@ -900,9 +986,8 @@ WOLFSSL_API int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha), - &dst->msg, &dst->used, &dst->len, - dst->heap, src->heap); + XMEMCPY(dst, src, sizeof(wc_Sha)); + return 0; } WOLFSSL_API void wc_ShaFree(wc_Sha* sha) @@ -910,11 +995,10 @@ WOLFSSL_API void wc_ShaFree(wc_Sha* sha) if (sha == NULL) { return; } - wc_MXC_TPU_SHA_FreeCtx(sha, sizeof(wc_Sha), &sha->msg, &sha->used, - &sha->len, sha->heap); + ForceZero(sha, sizeof(wc_Sha)); } -#endif /* NO_SHA */ +#endif /* !NO_SHA */ #if defined(WOLFSSL_SHA224) @@ -926,7 +1010,8 @@ WOLFSSL_API int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId) (void)devId; XMEMSET(sha224, 0, sizeof(*sha224)); sha224->heap = heap; - return 0; + return wc_MXC_TPU_SHA_Init(sha224->digest, MXC_SHA224_STATE_WORDS, + MXC_TPU_HASH_SHA224); } WOLFSSL_API int wc_InitSha224(wc_Sha224* sha224) @@ -935,23 +1020,33 @@ WOLFSSL_API int wc_InitSha224(wc_Sha224* sha224) } WOLFSSL_API int wc_Sha224Update(wc_Sha224* sha224, const unsigned char* data, - unsigned int len) + unsigned int len) { if (sha224 == NULL || (data == NULL && len > 0)) { return BAD_FUNC_ARG; } - return _wc_Hash_Grow(&sha224->msg, &sha224->used, &sha224->len, - data, (int)len, sha224->heap); + return wc_MXC_TPU_SHA_Update(sha224->digest, + sha224->buffer, &sha224->buffLen, + &sha224->loLen, &sha224->hiLen, + MXC_SHA224_STATE_WORDS, WC_SHA224_BLOCK_SIZE, + MXC_TPU_HASH_SHA224, data, len); } WOLFSSL_API int wc_Sha224Final(wc_Sha224* sha224, unsigned char* hash) { + int ret; if (sha224 == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Final(&sha224->msg, &sha224->used, &sha224->len, - sha224->heap, hash, - MXC_TPU_HASH_SHA224); + ret = wc_MXC_TPU_SHA_Final(sha224->digest, + sha224->buffer, &sha224->buffLen, + sha224->loLen, sha224->hiLen, + MXC_SHA224_STATE_WORDS, + WC_SHA224_DIGEST_SIZE, MXC_TPU_HASH_SHA224, hash); + if (ret == 0) { + return wc_InitSha224_ex(sha224, sha224->heap, INVALID_DEVID); + } + return ret; } WOLFSSL_API int wc_Sha224GetHash(wc_Sha224* sha224, unsigned char* hash) @@ -959,9 +1054,11 @@ WOLFSSL_API int wc_Sha224GetHash(wc_Sha224* sha224, unsigned char* hash) if (sha224 == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha224->msg, - sha224->used, hash, - MXC_TPU_HASH_SHA224); + return wc_MXC_TPU_SHA_GetHash(sha224->digest, + sha224->buffer, sha224->buffLen, + sha224->loLen, sha224->hiLen, + MXC_SHA224_STATE_WORDS, + WC_SHA224_DIGEST_SIZE, MXC_TPU_HASH_SHA224, hash); } WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) @@ -969,9 +1066,8 @@ WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha224), - &dst->msg, &dst->used, &dst->len, - dst->heap, src->heap); + XMEMCPY(dst, src, sizeof(wc_Sha224)); + return 0; } WOLFSSL_API void wc_Sha224Free(wc_Sha224* sha224) @@ -979,9 +1075,7 @@ WOLFSSL_API void wc_Sha224Free(wc_Sha224* sha224) if (sha224 == NULL) { return; } - wc_MXC_TPU_SHA_FreeCtx(sha224, sizeof(wc_Sha224), &sha224->msg, - &sha224->used, &sha224->len, - sha224->heap); + ForceZero(sha224, sizeof(wc_Sha224)); } #endif /* WOLFSSL_SHA224 */ @@ -996,7 +1090,8 @@ WOLFSSL_API int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) (void)devId; XMEMSET(sha256, 0, sizeof(*sha256)); sha256->heap = heap; - return 0; + return wc_MXC_TPU_SHA_Init(sha256->digest, MXC_SHA256_STATE_WORDS, + MXC_TPU_HASH_SHA256); } WOLFSSL_API int wc_InitSha256(wc_Sha256* sha256) @@ -1005,23 +1100,33 @@ WOLFSSL_API int wc_InitSha256(wc_Sha256* sha256) } WOLFSSL_API int wc_Sha256Update(wc_Sha256* sha256, const unsigned char* data, - unsigned int len) + unsigned int len) { if (sha256 == NULL || (data == NULL && len > 0)) { return BAD_FUNC_ARG; } - return _wc_Hash_Grow(&sha256->msg, &sha256->used, &sha256->len, - data, (int)len, sha256->heap); + return wc_MXC_TPU_SHA_Update(sha256->digest, + sha256->buffer, &sha256->buffLen, + &sha256->loLen, &sha256->hiLen, + MXC_SHA256_STATE_WORDS, WC_SHA256_BLOCK_SIZE, + MXC_TPU_HASH_SHA256, data, len); } WOLFSSL_API int wc_Sha256Final(wc_Sha256* sha256, unsigned char* hash) { + int ret; if (sha256 == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Final(&sha256->msg, &sha256->used, &sha256->len, - sha256->heap, hash, - MXC_TPU_HASH_SHA256); + ret = wc_MXC_TPU_SHA_Final(sha256->digest, + sha256->buffer, &sha256->buffLen, + sha256->loLen, sha256->hiLen, + MXC_SHA256_STATE_WORDS, + WC_SHA256_DIGEST_SIZE, MXC_TPU_HASH_SHA256, hash); + if (ret == 0) { + return wc_InitSha256_ex(sha256, sha256->heap, INVALID_DEVID); + } + return ret; } WOLFSSL_API int wc_Sha256GetHash(wc_Sha256* sha256, unsigned char* hash) @@ -1029,9 +1134,11 @@ WOLFSSL_API int wc_Sha256GetHash(wc_Sha256* sha256, unsigned char* hash) if (sha256 == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha256->msg, - sha256->used, hash, - MXC_TPU_HASH_SHA256); + return wc_MXC_TPU_SHA_GetHash(sha256->digest, + sha256->buffer, sha256->buffLen, + sha256->loLen, sha256->hiLen, + MXC_SHA256_STATE_WORDS, + WC_SHA256_DIGEST_SIZE, MXC_TPU_HASH_SHA256, hash); } WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) @@ -1039,9 +1146,8 @@ WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha256), - &dst->msg, &dst->used, &dst->len, - dst->heap, src->heap); + XMEMCPY(dst, src, sizeof(wc_Sha256)); + return 0; } WOLFSSL_API void wc_Sha256Free(wc_Sha256* sha256) @@ -1049,12 +1155,10 @@ WOLFSSL_API void wc_Sha256Free(wc_Sha256* sha256) if (sha256 == NULL) { return; } - wc_MXC_TPU_SHA_FreeCtx(sha256, sizeof(wc_Sha256), &sha256->msg, - &sha256->used, &sha256->len, - sha256->heap); + ForceZero(sha256, sizeof(wc_Sha256)); } -#endif /* NO_SHA256 */ +#endif /* !NO_SHA256 */ #if defined(WOLFSSL_SHA384) @@ -1066,7 +1170,8 @@ WOLFSSL_API int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) (void)devId; XMEMSET(sha384, 0, sizeof(*sha384)); sha384->heap = heap; - return 0; + return wc_MXC_TPU_SHA_Init((word32*)sha384->digest, + MXC_SHA384_STATE_WORDS, MXC_TPU_HASH_SHA384); } WOLFSSL_API int wc_InitSha384(wc_Sha384* sha384) @@ -1075,23 +1180,47 @@ WOLFSSL_API int wc_InitSha384(wc_Sha384* sha384) } WOLFSSL_API int wc_Sha384Update(wc_Sha384* sha384, const unsigned char* data, - unsigned int len) + unsigned int len) { + word32 loLen, hiLen, oldLo; + int ret; if (sha384 == NULL || (data == NULL && len > 0)) { return BAD_FUNC_ARG; } - return _wc_Hash_Grow(&sha384->msg, &sha384->used, &sha384->len, - data, (int)len, sha384->heap); + + /* SHA-384/512 context uses word64 loLen/hiLen; the generic Update helper + * uses word32. We bridge by converting here. */ + loLen = (word32)sha384->loLen; + hiLen = (word32)(sha384->loLen >> 32); + oldLo = loLen; + + ret = wc_MXC_TPU_SHA_Update((word32*)sha384->digest, + (word32*)sha384->buffer, &sha384->buffLen, + &loLen, &hiLen, + MXC_SHA384_STATE_WORDS, WC_SHA384_BLOCK_SIZE, + MXC_TPU_HASH_SHA384, data, len); + + /* Write back the updated length */ + sha384->loLen = (word64)loLen | ((word64)hiLen << 32); + (void)oldLo; + return ret; } WOLFSSL_API int wc_Sha384Final(wc_Sha384* sha384, unsigned char* hash) { + int ret; if (sha384 == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Final(&sha384->msg, &sha384->used, &sha384->len, - sha384->heap, hash, - MXC_TPU_HASH_SHA384); + ret = wc_MXC_TPU_SHA_Final((word32*)sha384->digest, + (word32*)sha384->buffer, &sha384->buffLen, + (word32)sha384->loLen, (word32)(sha384->loLen >> 32), + MXC_SHA384_STATE_WORDS, + WC_SHA384_DIGEST_SIZE, MXC_TPU_HASH_SHA384, hash); + if (ret == 0) { + return wc_InitSha384_ex(sha384, sha384->heap, INVALID_DEVID); + } + return ret; } WOLFSSL_API int wc_Sha384GetHash(wc_Sha384* sha384, unsigned char* hash) @@ -1099,9 +1228,11 @@ WOLFSSL_API int wc_Sha384GetHash(wc_Sha384* sha384, unsigned char* hash) if (sha384 == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha384->msg, - sha384->used, hash, - MXC_TPU_HASH_SHA384); + return wc_MXC_TPU_SHA_GetHash((word32*)sha384->digest, + (word32*)sha384->buffer, sha384->buffLen, + (word32)sha384->loLen, (word32)(sha384->loLen >> 32), + MXC_SHA384_STATE_WORDS, + WC_SHA384_DIGEST_SIZE, MXC_TPU_HASH_SHA384, hash); } WOLFSSL_API int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) @@ -1109,9 +1240,8 @@ WOLFSSL_API int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha384), - &dst->msg, &dst->used, &dst->len, - dst->heap, src->heap); + XMEMCPY(dst, src, sizeof(wc_Sha384)); + return 0; } WOLFSSL_API void wc_Sha384Free(wc_Sha384* sha384) @@ -1119,9 +1249,7 @@ WOLFSSL_API void wc_Sha384Free(wc_Sha384* sha384) if (sha384 == NULL) { return; } - wc_MXC_TPU_SHA_FreeCtx(sha384, sizeof(wc_Sha384), &sha384->msg, - &sha384->used, &sha384->len, - sha384->heap); + ForceZero(sha384, sizeof(wc_Sha384)); } #endif /* WOLFSSL_SHA384 */ @@ -1139,7 +1267,8 @@ WOLFSSL_API int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId) #if defined(WOLFSSL_SHA512_HASHTYPE) sha512->hashType = WC_HASH_TYPE_SHA512; #endif - return 0; + return wc_MXC_TPU_SHA_Init((word32*)sha512->digest, + MXC_SHA512_STATE_WORDS, MXC_TPU_HASH_SHA512); } WOLFSSL_API int wc_InitSha512(wc_Sha512* sha512) @@ -1148,23 +1277,42 @@ WOLFSSL_API int wc_InitSha512(wc_Sha512* sha512) } WOLFSSL_API int wc_Sha512Update(wc_Sha512* sha512, const unsigned char* data, - unsigned int len) + unsigned int len) { + word32 loLen, hiLen; + int ret; if (sha512 == NULL || (data == NULL && len > 0)) { return BAD_FUNC_ARG; } - return _wc_Hash_Grow(&sha512->msg, &sha512->used, &sha512->len, - data, (int)len, sha512->heap); + + loLen = (word32)sha512->loLen; + hiLen = (word32)(sha512->loLen >> 32); + + ret = wc_MXC_TPU_SHA_Update((word32*)sha512->digest, + (word32*)sha512->buffer, &sha512->buffLen, + &loLen, &hiLen, + MXC_SHA512_STATE_WORDS, WC_SHA512_BLOCK_SIZE, + MXC_TPU_HASH_SHA512, data, len); + + sha512->loLen = (word64)loLen | ((word64)hiLen << 32); + return ret; } WOLFSSL_API int wc_Sha512Final(wc_Sha512* sha512, unsigned char* hash) { + int ret; if (sha512 == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Final(&sha512->msg, &sha512->used, &sha512->len, - sha512->heap, hash, - MXC_TPU_HASH_SHA512); + ret = wc_MXC_TPU_SHA_Final((word32*)sha512->digest, + (word32*)sha512->buffer, &sha512->buffLen, + (word32)sha512->loLen, (word32)(sha512->loLen >> 32), + MXC_SHA512_STATE_WORDS, + WC_SHA512_DIGEST_SIZE, MXC_TPU_HASH_SHA512, hash); + if (ret == 0) { + return wc_InitSha512_ex(sha512, sha512->heap, INVALID_DEVID); + } + return ret; } WOLFSSL_API int wc_Sha512GetHash(wc_Sha512* sha512, unsigned char* hash) @@ -1172,9 +1320,11 @@ WOLFSSL_API int wc_Sha512GetHash(wc_Sha512* sha512, unsigned char* hash) if (sha512 == NULL || hash == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha512->msg, - sha512->used, hash, - MXC_TPU_HASH_SHA512); + return wc_MXC_TPU_SHA_GetHash((word32*)sha512->digest, + (word32*)sha512->buffer, sha512->buffLen, + (word32)sha512->loLen, (word32)(sha512->loLen >> 32), + MXC_SHA512_STATE_WORDS, + WC_SHA512_DIGEST_SIZE, MXC_TPU_HASH_SHA512, hash); } WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) @@ -1182,9 +1332,8 @@ WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) if (src == NULL || dst == NULL) { return BAD_FUNC_ARG; } - return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha512), - &dst->msg, &dst->used, &dst->len, - dst->heap, src->heap); + XMEMCPY(dst, src, sizeof(wc_Sha512)); + return 0; } WOLFSSL_API void wc_Sha512Free(wc_Sha512* sha512) @@ -1192,13 +1341,11 @@ WOLFSSL_API void wc_Sha512Free(wc_Sha512* sha512) if (sha512 == NULL) { return; } - wc_MXC_TPU_SHA_FreeCtx(sha512, sizeof(wc_Sha512), &sha512->msg, - &sha512->used, &sha512->len, - sha512->heap); + ForceZero(sha512, sizeof(wc_Sha512)); } #endif /* WOLFSSL_SHA512 */ -#endif /* !MAX3266X_SHA_CB*/ +#endif /* !MAX3266X_SHA_CB */ #endif /* MAX3266X_SHA || MAX3266X_SHA_CB */ #if defined(MAX3266X_MATH) diff --git a/wolfssl/wolfcrypt/port/maxim/max3266x.h b/wolfssl/wolfcrypt/port/maxim/max3266x.h index 9acc799c75..7f357d6b95 100644 --- a/wolfssl/wolfcrypt/port/maxim/max3266x.h +++ b/wolfssl/wolfcrypt/port/maxim/max3266x.h @@ -57,14 +57,11 @@ #endif #endif -/* Enable copy/free callbacks when using callback mode */ +/* Enable copy callback when using callback mode (SHA Copy needs it) */ #if defined(MAX3266X_SHA_CB) #ifndef WOLF_CRYPTO_CB_COPY #define WOLF_CRYPTO_CB_COPY #endif - #ifndef WOLF_CRYPTO_CB_FREE - #define WOLF_CRYPTO_CB_FREE - #endif #endif /* Crypto HW can be used in parallel on this device */ @@ -246,52 +243,6 @@ #if defined(MAX3266X_SHA) || defined(MAX3266X_SHA_CB) - /* Use HASH_KEEP to accumulate message data for one-shot TPU hardware */ - #ifndef WOLFSSL_HASH_KEEP - #define WOLFSSL_HASH_KEEP - #endif - - #if !defined(NO_SHA) - /* Define the SHA digest for an empty string */ - /* as a constant byte array */ - static const unsigned char MXC_EMPTY_DIGEST_SHA1[20] = { - 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, - 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, - 0xaf, 0xd8, 0x07, 0x09}; - #endif /* NO_SHA */ - - #if defined(WOLFSSL_SHA224) - /* Define the SHA-224 digest for an empty string */ - /* as a constant byte array */ - static const unsigned char MXC_EMPTY_DIGEST_SHA224[28] = { - 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, - 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, - 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, - 0xc5, 0xb3, 0xe4, 0x2f}; - #endif /* WOLFSSL_SHA224 */ - - #if !defined(NO_SHA256) - /* Define the SHA-256 digest for an empty string */ - /* as a constant byte array */ - static const unsigned char MXC_EMPTY_DIGEST_SHA256[32] = { - 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, - 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, - 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, - 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; - #endif /* NO_SHA256 */ - - #if defined(WOLFSSL_SHA384) - /* Define the SHA-384 digest for an empty string */ - /* as a constant byte array */ - static const unsigned char MXC_EMPTY_DIGEST_SHA384[48] = { - 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, - 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, - 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, - 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, - 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, - 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b}; - #endif /* WOLFSSL_SHA384 */ - #if defined(WOLFSSL_SHA512) /* Does not support these SHA512 Macros */ #ifndef WOLFSSL_NOSHA512_224 @@ -302,58 +253,52 @@ #warning "MAX3266X Port does not support SHA-512/256" #define WOLFSSL_NOSHA512_256 #endif - - /* Define the SHA-512 digest for an empty string */ - /* as a constant byte array */ - static const unsigned char MXC_EMPTY_DIGEST_SHA512[64] = { - 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, - 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, - 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, - 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, - 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, - 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, - 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, - 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e}; #endif /* WOLFSSL_SHA512 */ + /* Number of HASH_DIGEST register words for each algorithm's state */ + #define MXC_SHA1_STATE_WORDS 5 /* 160-bit state */ + #define MXC_SHA224_STATE_WORDS 8 /* 256-bit internal state */ + #define MXC_SHA256_STATE_WORDS 8 /* 256-bit state */ + #define MXC_SHA384_STATE_WORDS 16 /* 512-bit internal state (word32) */ + #define MXC_SHA512_STATE_WORDS 16 /* 512-bit state (word32) */ - /* Check for empty message and provide pre-computed digest if so */ - WOLFSSL_LOCAL int wc_MXC_TPU_SHA_GetDigest(const unsigned char* msg, - unsigned int msgSz, - unsigned char* digest, - MXC_TPU_HASH_TYPE algo); - /* Compute hash from accumulated message using TPU hardware */ - WOLFSSL_LOCAL int wc_MXC_TPU_SHA_GetHash(const unsigned char* msg, - unsigned int msgSz, - unsigned char* digest, - MXC_TPU_HASH_TYPE algo); - /* Free HASH_KEEP message buffer and reset fields */ - WOLFSSL_LOCAL void wc_MXC_TPU_SHA_Free(unsigned char** msg, - unsigned int* used, - unsigned int* len, - void* heap); - /* Free HASH_KEEP message buffer and zero the full SHA context */ - WOLFSSL_LOCAL void wc_MXC_TPU_SHA_FreeCtx(void* ctx, - unsigned int ctxSz, - unsigned char** msg, - unsigned int* used, - unsigned int* len, - void* heap); - /* Copy SHA context and deep copy HASH_KEEP message buffer */ - WOLFSSL_LOCAL int wc_MXC_TPU_SHA_Copy(void* src, void* dst, - unsigned int ctxSz, - unsigned char** dstMsg, - unsigned int* dstUsed, - unsigned int* dstLen, - void* dstHeap, void* srcHeap); - /* Compute hash, free message buffer, and reset fields */ - WOLFSSL_LOCAL int wc_MXC_TPU_SHA_Final(unsigned char** msg, - unsigned int* used, - unsigned int* len, - void* heap, - unsigned char* digest, - MXC_TPU_HASH_TYPE algo); + /* TPU hash helpers - bare-metal SHA acceleration */ + WOLFSSL_LOCAL void wc_MXC_TPU_Hash_Setup(MXC_TPU_HASH_TYPE algo, + const unsigned int* state, int stateWords); + WOLFSSL_LOCAL void wc_MXC_TPU_Hash_Feed_Block(const unsigned char* data, + unsigned int blockSz); + WOLFSSL_LOCAL void wc_MXC_TPU_Hash_Feed_Last(const unsigned char* data, + unsigned int dataLen, + unsigned int totalLenLo, + unsigned int totalLenHi); + WOLFSSL_LOCAL void wc_MXC_TPU_Hash_Save_State(unsigned int* state, + int stateWords); + WOLFSSL_LOCAL void wc_MXC_TPU_Hash_Read_Digest(unsigned char* digest, + unsigned int digestSz); + /* Generic SHA Update/Final/GetHash */ + WOLFSSL_LOCAL int wc_MXC_TPU_SHA_Update(unsigned int* digest, + unsigned int* buffer, + unsigned int* buffLen, + unsigned int* loLen, unsigned int* hiLen, + int stateWords, unsigned int blockSz, + MXC_TPU_HASH_TYPE algo, + const unsigned char* data, + unsigned int len); + WOLFSSL_LOCAL int wc_MXC_TPU_SHA_Final(unsigned int* digest, + unsigned int* buffer, + unsigned int* buffLen, + unsigned int loLen, unsigned int hiLen, + int stateWords, unsigned int digestSz, + MXC_TPU_HASH_TYPE algo, + unsigned char* hash); + WOLFSSL_LOCAL int wc_MXC_TPU_SHA_GetHash(unsigned int* digest, + unsigned int* buffer, + unsigned int buffLen, + unsigned int loLen, unsigned int hiLen, + int stateWords, unsigned int digestSz, + MXC_TPU_HASH_TYPE algo, + unsigned char* hash); #endif /* defined(MAX3266X_SHA) || defined(MAX3266X_SHA_CB) */ From 36acdef662cf1e17f69d142bb2918e6f875ded82 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Fri, 8 May 2026 04:23:47 +0200 Subject: [PATCH 2/9] Update README --- wolfcrypt/src/port/maxim/README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/wolfcrypt/src/port/maxim/README.md b/wolfcrypt/src/port/maxim/README.md index 3919ffd0f9..e759472b94 100644 --- a/wolfcrypt/src/port/maxim/README.md +++ b/wolfcrypt/src/port/maxim/README.md @@ -84,10 +84,6 @@ hardware. - SHA-384 - SHA-512 -Please note that when using `MAX3266X_SHA` there will be a limitation when -attempting to do a larger sized hash as the SDK for the hardware currently -expects a the whole msg buffer to be given. - `#define MAX3266X_MATH` (Replaces math operation calls for algos like RSA and ECC key generation): From e8d3e19da527800bb31ce356d58782f9f7b9be0c Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Fri, 8 May 2026 21:59:32 +0200 Subject: [PATCH 3/9] Address Copilot suggestions --- wolfcrypt/src/port/maxim/max3266x.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/wolfcrypt/src/port/maxim/max3266x.c b/wolfcrypt/src/port/maxim/max3266x.c index efbec9424a..bd285b26a9 100644 --- a/wolfcrypt/src/port/maxim/max3266x.c +++ b/wolfcrypt/src/port/maxim/max3266x.c @@ -275,19 +275,34 @@ static int wc_MxcCopyCb(wc_CryptoInfo* info) switch (info->copy.type) { #ifdef MAX3266X_SHA_CB #ifndef NO_SHA - case WC_HASH_TYPE_SHA: sz = sizeof(wc_Sha); break; + case WC_HASH_TYPE_SHA: + wc_ShaFree((wc_Sha*)info->copy.dst); + sz = sizeof(wc_Sha); + break; #endif #ifdef WOLFSSL_SHA224 - case WC_HASH_TYPE_SHA224: sz = sizeof(wc_Sha224); break; + case WC_HASH_TYPE_SHA224: + wc_Sha224Free((wc_Sha224*)info->copy.dst); + sz = sizeof(wc_Sha224); + break; #endif #ifndef NO_SHA256 - case WC_HASH_TYPE_SHA256: sz = sizeof(wc_Sha256); break; + case WC_HASH_TYPE_SHA256: + wc_Sha256Free((wc_Sha256*)info->copy.dst); + sz = sizeof(wc_Sha256); + break; #endif #ifdef WOLFSSL_SHA384 - case WC_HASH_TYPE_SHA384: sz = sizeof(wc_Sha384); break; + case WC_HASH_TYPE_SHA384: + wc_Sha384Free((wc_Sha384*)info->copy.dst); + sz = sizeof(wc_Sha384); + break; #endif #ifdef WOLFSSL_SHA512 - case WC_HASH_TYPE_SHA512: sz = sizeof(wc_Sha512); break; + case WC_HASH_TYPE_SHA512: + wc_Sha512Free((wc_Sha512*)info->copy.dst); + sz = sizeof(wc_Sha512); + break; #endif #endif /* MAX3266X_SHA_CB */ default: @@ -657,7 +672,7 @@ int wc_MxcCb_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) /* TPU hash helpers (bare-metal SHA accelerator) */ /* Reset TPU, select hash function, and restore intermediate state into - * the HASH_DIGEST registers. Does NOT set INIT - caller provides state. */ + * the HASH_DIGEST registers. */ void wc_MXC_TPU_Hash_Setup(MXC_TPU_HASH_TYPE algo, const unsigned int* state, int stateWords) { From 11b207e57f28bc29fa38c0c33523cf587b7b6947 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Fri, 8 May 2026 22:01:15 +0200 Subject: [PATCH 4/9] Remove unused variable --- wolfcrypt/src/port/maxim/max3266x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/wolfcrypt/src/port/maxim/max3266x.c b/wolfcrypt/src/port/maxim/max3266x.c index bd285b26a9..a2637183c7 100644 --- a/wolfcrypt/src/port/maxim/max3266x.c +++ b/wolfcrypt/src/port/maxim/max3266x.c @@ -1197,7 +1197,7 @@ WOLFSSL_API int wc_InitSha384(wc_Sha384* sha384) WOLFSSL_API int wc_Sha384Update(wc_Sha384* sha384, const unsigned char* data, unsigned int len) { - word32 loLen, hiLen, oldLo; + word32 loLen, hiLen; int ret; if (sha384 == NULL || (data == NULL && len > 0)) { return BAD_FUNC_ARG; @@ -1207,7 +1207,6 @@ WOLFSSL_API int wc_Sha384Update(wc_Sha384* sha384, const unsigned char* data, * uses word32. We bridge by converting here. */ loLen = (word32)sha384->loLen; hiLen = (word32)(sha384->loLen >> 32); - oldLo = loLen; ret = wc_MXC_TPU_SHA_Update((word32*)sha384->digest, (word32*)sha384->buffer, &sha384->buffLen, @@ -1217,7 +1216,6 @@ WOLFSSL_API int wc_Sha384Update(wc_Sha384* sha384, const unsigned char* data, /* Write back the updated length */ sha384->loLen = (word64)loLen | ((word64)hiLen << 32); - (void)oldLo; return ret; } From c9a534a63e10b6ed4f00812ab176958e5ecb5a77 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Tue, 12 May 2026 01:31:26 +0200 Subject: [PATCH 5/9] Fix issues in wc_MXC_MAA_zeroPad --- wolfcrypt/src/port/maxim/max3266x.c | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/port/maxim/max3266x.c b/wolfcrypt/src/port/maxim/max3266x.c index a2637183c7..c8527b9964 100644 --- a/wolfcrypt/src/port/maxim/max3266x.c +++ b/wolfcrypt/src/port/maxim/max3266x.c @@ -1445,6 +1445,7 @@ int wc_MXC_MAA_zeroPad(mp_int* multiplier, mp_int* multiplicand, MXC_TPU_MAA_TYPE clc, unsigned int length) { mp_digit* zero_tmp; + unsigned int zero_size; MAX3266X_MSG("Zero Padding Buffers for Hardware"); if (length > MXC_MAA_MAX_SIZE) { MAX3266X_MSG("Hardware cannot exceed 2048 bit input"); @@ -1456,19 +1457,23 @@ int wc_MXC_MAA_zeroPad(mp_int* multiplier, mp_int* multiplicand, } /* Create an array to compare values to to check edge for error edge case */ - zero_tmp = (mp_digit*)XMALLOC(multiplier->size*sizeof(mp_digit), NULL, + zero_size = mod->size; + if ((exp != NULL) && (exp->size > zero_size)) { + zero_size = exp->size; + } + zero_tmp = (mp_digit*)XMALLOC(zero_size*sizeof(mp_digit), NULL, DYNAMIC_TYPE_TMP_BUFFER); if (zero_tmp == NULL) { MAX3266X_MSG("NULL pointer found after XMALLOC call"); return MEMORY_E; } - XMEMSET(zero_tmp, 0x00, multiplier->size*sizeof(mp_digit)); + XMEMSET(zero_tmp, 0x00, zero_size*sizeof(mp_digit)); /* Check for invalid arguments before padding */ switch ((char)clc) { case MXC_TPU_MAA_EXP: /* Cannot be 0 for a^e mod m operation */ - if (XMEMCMP(zero_tmp, exp, (exp->used*sizeof(mp_digit))) == 0) { + if (XMEMCMP(zero_tmp, exp->dp, (exp->used*sizeof(mp_digit))) == 0) { XFREE(zero_tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); MAX3266X_MSG("Cannot use Value 0 for Exp"); return BAD_FUNC_ARG; @@ -1491,7 +1496,7 @@ int wc_MXC_MAA_zeroPad(mp_int* multiplier, mp_int* multiplicand, case MXC_TPU_MAA_ADD: case MXC_TPU_MAA_SUB: /* Cannot be 0 for mod m value */ - if (XMEMCMP(zero_tmp, mod, (exp->used*sizeof(mp_digit))) == 0) { + if (XMEMCMP(zero_tmp, mod->dp, (mod->used*sizeof(mp_digit))) == 0) { XFREE(zero_tmp, NULL, DYNAMIC_TYPE_TMP_BUFFER); MAX3266X_MSG("Cannot use Value 0 for Exp"); return BAD_FUNC_ARG; From 03e695a9c675b1df1133a7a4eea34035eff0c398 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Wed, 20 May 2026 22:31:33 +0200 Subject: [PATCH 6/9] Lazy-initialize `digest` in cryptocb mode --- wolfcrypt/src/port/maxim/max3266x.c | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/wolfcrypt/src/port/maxim/max3266x.c b/wolfcrypt/src/port/maxim/max3266x.c index c8527b9964..494999f100 100644 --- a/wolfcrypt/src/port/maxim/max3266x.c +++ b/wolfcrypt/src/port/maxim/max3266x.c @@ -152,12 +152,19 @@ static int wc_MXC_TPU_SHA_Init(unsigned int* digest, int stateWords, static int wc_MxcShaCbDispatch( unsigned int* digest, unsigned int* buffer, unsigned int* buffLen, unsigned int* loLen, - unsigned int* hiLen, int stateWords, + unsigned int* hiLen, void** devCtx, int stateWords, unsigned int blockSz, unsigned int digestSz, MXC_TPU_HASH_TYPE algo, const unsigned char* in, unsigned int inSz, unsigned char* outDigest) { + if (*devCtx == NULL) { + int initRet = wc_MXC_TPU_SHA_Init(digest, stateWords, algo); + if (initRet != 0) + return initRet; + *devCtx = (void*)1; + } + if (in != NULL && outDigest == NULL) { MAX3266X_MSG("Update CB"); return wc_MXC_TPU_SHA_Update(digest, buffer, buffLen, loLen, hiLen, @@ -200,8 +207,8 @@ static int wc_MxcShaCbDispatch512(wc_Sha512* ctx, int stateWords, ret = wc_MxcShaCbDispatch((unsigned int*)ctx->digest, (unsigned int*)ctx->buffer, &ctx->buffLen, &loLen, &hiLen, - stateWords, blockSz, digestSz, algo, - in, inSz, digest); + &ctx->devCtx, stateWords, blockSz, digestSz, + algo, in, inSz, digest); ctx->loLen = (word64)loLen | ((word64)hiLen << 32); return ret; @@ -217,6 +224,7 @@ int wc_MxcShaCryptoCb(wc_CryptoInfo* info) info->hash.sha1->buffer, &info->hash.sha1->buffLen, &info->hash.sha1->loLen, &info->hash.sha1->hiLen, + &info->hash.sha1->devCtx, MXC_SHA1_STATE_WORDS, WC_SHA_BLOCK_SIZE, WC_SHA_DIGEST_SIZE, MXC_TPU_HASH_SHA1, info->hash.in, info->hash.inSz, info->hash.digest); @@ -228,6 +236,7 @@ int wc_MxcShaCryptoCb(wc_CryptoInfo* info) info->hash.sha224->buffer, &info->hash.sha224->buffLen, &info->hash.sha224->loLen, &info->hash.sha224->hiLen, + &info->hash.sha224->devCtx, MXC_SHA224_STATE_WORDS, WC_SHA224_BLOCK_SIZE, WC_SHA224_DIGEST_SIZE, MXC_TPU_HASH_SHA224, info->hash.in, info->hash.inSz, info->hash.digest); @@ -239,6 +248,7 @@ int wc_MxcShaCryptoCb(wc_CryptoInfo* info) info->hash.sha256->buffer, &info->hash.sha256->buffLen, &info->hash.sha256->loLen, &info->hash.sha256->hiLen, + &info->hash.sha256->devCtx, MXC_SHA256_STATE_WORDS, WC_SHA256_BLOCK_SIZE, WC_SHA256_DIGEST_SIZE, MXC_TPU_HASH_SHA256, info->hash.in, info->hash.inSz, info->hash.digest); From 6291af4e8838e5572d9fa2e5814b2393286652df Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Thu, 4 Jun 2026 20:59:29 +0200 Subject: [PATCH 7/9] Add WOLFSSL_MAX3266X_SHA_ONESHOT to go to previous behavior --- wolfcrypt/src/port/maxim/max3266x.c | 727 +++++++++++++++++++++++- wolfssl/wolfcrypt/port/maxim/max3266x.h | 110 ++++ 2 files changed, 835 insertions(+), 2 deletions(-) diff --git a/wolfcrypt/src/port/maxim/max3266x.c b/wolfcrypt/src/port/maxim/max3266x.c index 494999f100..06c6b8c7e9 100644 --- a/wolfcrypt/src/port/maxim/max3266x.c +++ b/wolfcrypt/src/port/maxim/max3266x.c @@ -136,6 +136,77 @@ int wc_MxcAesCryptoCb(wc_CryptoInfo* info) #ifdef MAX3266X_SHA_CB +#ifdef WOLFSSL_MAX3266X_SHA_ONESHOT + +/* Shared callback handler: Update grows buffer, Final computes hash. */ +static int wc_MxcShaCbDispatch(byte** msg, word32* used, word32* len, + void* heap, const byte* in, word32 inSz, + byte* digest, MXC_TPU_HASH_TYPE algo) +{ + if (in != NULL && digest == NULL) { + MAX3266X_MSG("Update CB"); + return _wc_Hash_Grow(msg, used, len, in, (int)inSz, heap); + } + if (in == NULL && digest != NULL) { + MAX3266X_MSG("Final CB"); + return wc_MXC_TPU_SHA_Final(msg, used, len, heap, digest, algo); + } + if (inSz == 0) { + return 0; /* Don't need to Update when Size is Zero */ + } + return BAD_FUNC_ARG; +} + +int wc_MxcShaCryptoCb(wc_CryptoInfo* info) +{ + switch (info->hash.type) { + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + return wc_MxcShaCbDispatch(&info->hash.sha1->msg, + &info->hash.sha1->used, &info->hash.sha1->len, + info->hash.sha1->heap, info->hash.in, + info->hash.inSz, info->hash.digest, + MXC_TPU_HASH_SHA1); + #endif + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + return wc_MxcShaCbDispatch(&info->hash.sha224->msg, + &info->hash.sha224->used, &info->hash.sha224->len, + info->hash.sha224->heap, info->hash.in, + info->hash.inSz, info->hash.digest, + MXC_TPU_HASH_SHA224); + #endif + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + return wc_MxcShaCbDispatch(&info->hash.sha256->msg, + &info->hash.sha256->used, &info->hash.sha256->len, + info->hash.sha256->heap, info->hash.in, + info->hash.inSz, info->hash.digest, + MXC_TPU_HASH_SHA256); + #endif + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + return wc_MxcShaCbDispatch(&info->hash.sha384->msg, + &info->hash.sha384->used, &info->hash.sha384->len, + info->hash.sha384->heap, info->hash.in, + info->hash.inSz, info->hash.digest, + MXC_TPU_HASH_SHA384); + #endif + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + return wc_MxcShaCbDispatch(&info->hash.sha512->msg, + &info->hash.sha512->used, &info->hash.sha512->len, + info->hash.sha512->heap, info->hash.in, + info->hash.inSz, info->hash.digest, + MXC_TPU_HASH_SHA512); + #endif + default: + return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + } +} + +#else /* WOLFSSL_MAX3266X_SHA_ONESHOT */ + int wc_MXC_TPU_SHA_Update(unsigned int* digest, unsigned int* buffer, unsigned int* buffLen, unsigned int* loLen, unsigned int* hiLen, int stateWords, @@ -271,9 +342,76 @@ int wc_MxcShaCryptoCb(wc_CryptoInfo* info) return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); } } + +#endif /* WOLFSSL_MAX3266X_SHA_ONESHOT */ #endif /* MAX3266X_SHA_CB */ #ifdef WOLF_CRYPTO_CB_COPY +#ifdef WOLFSSL_MAX3266X_SHA_ONESHOT +static int wc_MxcCopyCb(wc_CryptoInfo* info) +{ + if (info == NULL || info->copy.src == NULL || info->copy.dst == NULL) { + return BAD_FUNC_ARG; + } + + switch (info->copy.type) { +#ifdef MAX3266X_SHA_CB + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, + sizeof(wc_Sha), + &((wc_Sha*)info->copy.dst)->msg, + &((wc_Sha*)info->copy.dst)->used, + &((wc_Sha*)info->copy.dst)->len, + ((wc_Sha*)info->copy.dst)->heap, + ((wc_Sha*)info->copy.src)->heap); + #endif + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, + sizeof(wc_Sha224), + &((wc_Sha224*)info->copy.dst)->msg, + &((wc_Sha224*)info->copy.dst)->used, + &((wc_Sha224*)info->copy.dst)->len, + ((wc_Sha224*)info->copy.dst)->heap, + ((wc_Sha224*)info->copy.src)->heap); + #endif + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, + sizeof(wc_Sha256), + &((wc_Sha256*)info->copy.dst)->msg, + &((wc_Sha256*)info->copy.dst)->used, + &((wc_Sha256*)info->copy.dst)->len, + ((wc_Sha256*)info->copy.dst)->heap, + ((wc_Sha256*)info->copy.src)->heap); + #endif + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, + sizeof(wc_Sha384), + &((wc_Sha384*)info->copy.dst)->msg, + &((wc_Sha384*)info->copy.dst)->used, + &((wc_Sha384*)info->copy.dst)->len, + ((wc_Sha384*)info->copy.dst)->heap, + ((wc_Sha384*)info->copy.src)->heap); + #endif + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + return wc_MXC_TPU_SHA_Copy(info->copy.src, info->copy.dst, + sizeof(wc_Sha512), + &((wc_Sha512*)info->copy.dst)->msg, + &((wc_Sha512*)info->copy.dst)->used, + &((wc_Sha512*)info->copy.dst)->len, + ((wc_Sha512*)info->copy.dst)->heap, + ((wc_Sha512*)info->copy.src)->heap); + #endif +#endif /* MAX3266X_SHA_CB */ + default: + return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + } +} +#else /* WOLFSSL_MAX3266X_SHA_ONESHOT */ static int wc_MxcCopyCb(wc_CryptoInfo* info) { word32 sz; @@ -321,8 +459,70 @@ static int wc_MxcCopyCb(wc_CryptoInfo* info) XMEMCPY(info->copy.dst, info->copy.src, sz); return 0; } +#endif /* WOLFSSL_MAX3266X_SHA_ONESHOT */ #endif /* WOLF_CRYPTO_CB_COPY */ +#ifdef WOLF_CRYPTO_CB_FREE +static int wc_MxcFreeCb(wc_CryptoInfo* info) +{ + if (info == NULL || info->free.obj == NULL) { + return BAD_FUNC_ARG; + } + + switch (info->free.type) { +#ifdef MAX3266X_SHA_CB + #ifndef NO_SHA + case WC_HASH_TYPE_SHA: + wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha), + &((wc_Sha*)info->free.obj)->msg, + &((wc_Sha*)info->free.obj)->used, + &((wc_Sha*)info->free.obj)->len, + ((wc_Sha*)info->free.obj)->heap); + return 0; + #endif + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha224), + &((wc_Sha224*)info->free.obj)->msg, + &((wc_Sha224*)info->free.obj)->used, + &((wc_Sha224*)info->free.obj)->len, + ((wc_Sha224*)info->free.obj)->heap); + return 0; + #endif + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha256), + &((wc_Sha256*)info->free.obj)->msg, + &((wc_Sha256*)info->free.obj)->used, + &((wc_Sha256*)info->free.obj)->len, + ((wc_Sha256*)info->free.obj)->heap); + return 0; + #endif + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_SHA384: + wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha384), + &((wc_Sha384*)info->free.obj)->msg, + &((wc_Sha384*)info->free.obj)->used, + &((wc_Sha384*)info->free.obj)->len, + ((wc_Sha384*)info->free.obj)->heap); + return 0; + #endif + #ifdef WOLFSSL_SHA512 + case WC_HASH_TYPE_SHA512: + wc_MXC_TPU_SHA_FreeCtx(info->free.obj, sizeof(wc_Sha512), + &((wc_Sha512*)info->free.obj)->msg, + &((wc_Sha512*)info->free.obj)->used, + &((wc_Sha512*)info->free.obj)->len, + ((wc_Sha512*)info->free.obj)->heap); + return 0; + #endif +#endif /* MAX3266X_SHA_CB */ + default: + return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); + } +} +#endif /* WOLF_CRYPTO_CB_FREE */ + /* General Callback Function to determine ALGO Type */ int wc_MxcCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx) { @@ -355,8 +555,12 @@ int wc_MxcCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx) ret = wc_MxcCopyCb(info); break; #endif /* WOLF_CRYPTO_CB_COPY */ - /* No WC_ALGO_TYPE_FREE needed: SHA contexts have no heap - * allocations to clean up. */ +#ifdef WOLF_CRYPTO_CB_FREE + case WC_ALGO_TYPE_FREE: + MAX3266X_MSG("Using MXC Free Callback:"); + ret = wc_MxcFreeCb(info); + break; +#endif /* WOLF_CRYPTO_CB_FREE */ default: MAX3266X_MSG("Callback not supported with MXC, using SW"); /* return this to bypass HW and use SW */ @@ -679,6 +883,172 @@ int wc_MxcCb_AesCbcDecrypt(Aes* aes, byte* out, const byte* in, word32 sz) #if defined(MAX3266X_SHA) || defined(MAX3266X_SHA_CB) +#ifdef WOLFSSL_MAX3266X_SHA_ONESHOT + +/* Check for empty message and provide pre-computed digest if so */ +/* Returns 1 if empty (digest filled), 0 if needs hardware processing */ +int wc_MXC_TPU_SHA_GetDigest(const unsigned char* msg, unsigned int msgSz, + unsigned char* digest, + MXC_TPU_HASH_TYPE algo) +{ + if (digest == NULL) { + return BAD_FUNC_ARG; + } + if (msg == NULL && msgSz == 0) { + switch (algo) { + #ifndef NO_SHA + case MXC_TPU_HASH_SHA1: + XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA1, WC_SHA_DIGEST_SIZE); + break; + #endif /* NO_SHA */ + #ifdef WOLFSSL_SHA224 + case MXC_TPU_HASH_SHA224: + XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA224, WC_SHA224_DIGEST_SIZE); + break; + #endif /* WOLFSSL_SHA224 */ + #ifndef NO_SHA256 + case MXC_TPU_HASH_SHA256: + XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA256, WC_SHA256_DIGEST_SIZE); + break; + #endif /* NO_SHA256 */ + #ifdef WOLFSSL_SHA384 + case MXC_TPU_HASH_SHA384: + XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA384, WC_SHA384_DIGEST_SIZE); + break; + #endif /* WOLFSSL_SHA384 */ + #ifdef WOLFSSL_SHA512 + case MXC_TPU_HASH_SHA512: + XMEMCPY(digest, MXC_EMPTY_DIGEST_SHA512, WC_SHA512_DIGEST_SIZE); + break; + #endif /* WOLFSSL_SHA512 */ + default: + return BAD_FUNC_ARG; + } + return 1; /* True: empty digest provided */ + } + return 0; /* False: needs hardware processing */ +} + +/* Compute hash from accumulated message using TPU hardware */ +int wc_MXC_TPU_SHA_GetHash(const unsigned char* msg, unsigned int msgSz, + unsigned char* digest, + MXC_TPU_HASH_TYPE algo) +{ + int status; + if (digest == NULL || (msg == NULL && msgSz != 0)) { + return BAD_FUNC_ARG; + } + status = wc_MXC_TPU_SHA_GetDigest(msg, msgSz, digest, algo); + /* True Case that msg is an empty string */ + if (status == 1) { + /* Hardware cannot handle the case of an empty string */ + /* so in the case of this we will provide the hash via software */ + return 0; + } + /* False Case where msg needs to be processed */ + else if (status == 0) { + status = wolfSSL_HwHashMutexLock(); /* Set Mutex */ + if (status != 0) { /* Mutex Call Check */ + return status; + } + MXC_TPU_Init(MXC_SYS_PERIPH_CLOCK_TPU); + MXC_TPU_Hash_Config(algo); + status = MXC_TPU_Hash_SHA((const char *)msg, algo, msgSz, + (char *)digest); + MAX3266X_MSG("SHA HW Acceleration Used"); + wolfSSL_HwHashMutexUnLock(); /* Release Mutex */ + if (wc_MXC_error(&status) != 0) { + MAX3266X_MSG("SHA HW Error Occurred"); + return status; + } + } + /* Error Occurred */ + return status; +} + +/* Free HASH_KEEP message buffer and reset fields */ +void wc_MXC_TPU_SHA_Free(byte** msg, word32* used, word32* len, void* heap) +{ + if (msg == NULL) { + return; + } + if (*msg != NULL) { + XFREE(*msg, heap, DYNAMIC_TYPE_TMP_BUFFER); + *msg = NULL; + } + if (used != NULL) { + *used = 0; + } + if (len != NULL) { + *len = 0; + } +} + +/* Free HASH_KEEP message buffer and zero the full SHA context struct */ +void wc_MXC_TPU_SHA_FreeCtx(void* ctx, word32 ctxSz, byte** msg, word32* used, + word32* len, void* heap) +{ + if (ctx == NULL) { + return; + } + wc_MXC_TPU_SHA_Free(msg, used, len, heap); + XMEMSET(ctx, 0, ctxSz); +} + +/* Copy SHA context struct and deep copy the HASH_KEEP message buffer. + * Frees any existing dst msg buffer to prevent memory leaks when copying + * into an already-used context. */ +int wc_MXC_TPU_SHA_Copy(void* src, void* dst, word32 ctxSz, + byte** dstMsg, word32* dstUsed, word32* dstLen, + void* dstHeap, void* srcHeap) +{ + byte* srcBuf = NULL; + + if (src == NULL || dst == NULL || dstMsg == NULL || + dstUsed == NULL || dstLen == NULL || ctxSz == 0) { + return BAD_FUNC_ARG; + } + + /* Free existing dst msg buffer using dst's original heap */ + wc_MXC_TPU_SHA_Free(dstMsg, dstUsed, dstLen, dstHeap); + + /* Shallow copy the full context struct */ + XMEMCPY(dst, src, ctxSz); + + /* Deep copy src msg buffer if present. Since dstMsg points into the dst + * struct, the XMEMCPY above overwrites it with the src's msg pointer. + * Save that pointer, allocate a new buffer for dst, and copy the data. + * Do NOT move srcBuf assignment before XMEMCPY - it must capture the + * src msg pointer that lands in *dstMsg after the shallow copy. */ + if (*dstMsg != NULL) { + srcBuf = *dstMsg; + *dstMsg = (byte*)XMALLOC(*dstLen, srcHeap, DYNAMIC_TYPE_TMP_BUFFER); + if (*dstMsg == NULL) { + return MEMORY_E; + } + XMEMCPY(*dstMsg, srcBuf, *dstUsed); + } + + return 0; +} + +/* Compute hash, free message buffer, and reset HASH_KEEP fields */ +int wc_MXC_TPU_SHA_Final(unsigned char** msg, unsigned int* used, + unsigned int* len, void* heap, + unsigned char* digest, + MXC_TPU_HASH_TYPE algo) +{ + int status; + if (msg == NULL || used == NULL || len == NULL || digest == NULL) { + return BAD_FUNC_ARG; + } + status = wc_MXC_TPU_SHA_GetHash(*msg, *used, digest, algo); + wc_MXC_TPU_SHA_Free(msg, used, len, heap); + return status; +} + +#else /* WOLFSSL_MAX3266X_SHA_ONESHOT */ + /* TPU hash helpers (bare-metal SHA accelerator) */ /* Reset TPU, select hash function, and restore intermediate state into @@ -948,9 +1318,360 @@ static int wc_MXC_TPU_SHA_Init(unsigned int* digest, int stateWords, return 0; } +#endif /* WOLFSSL_MAX3266X_SHA_ONESHOT */ + /* Per-algorithm Init / Update / Final / GetHash / Copy / Free */ #ifndef MAX3266X_SHA_CB + +#ifdef WOLFSSL_MAX3266X_SHA_ONESHOT + +#if !defined(NO_SHA) + +WOLFSSL_API int wc_InitSha_ex(wc_Sha* sha, void* heap, int devId) +{ + if (sha == NULL) { + return BAD_FUNC_ARG; + } + (void)devId; + XMEMSET(sha, 0, sizeof(*sha)); + sha->heap = heap; + return 0; +} + +WOLFSSL_API int wc_ShaUpdate(wc_Sha* sha, const unsigned char* data, + unsigned int len) +{ + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return _wc_Hash_Grow(&sha->msg, &sha->used, &sha->len, + data, (int)len, sha->heap); +} + +WOLFSSL_API int wc_ShaFinal(wc_Sha* sha, unsigned char* hash) +{ + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Final(&sha->msg, &sha->used, &sha->len, + sha->heap, hash, MXC_TPU_HASH_SHA1); +} + +WOLFSSL_API int wc_ShaGetHash(wc_Sha* sha, unsigned char* hash) +{ + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha->msg, + sha->used, hash, MXC_TPU_HASH_SHA1); +} + +WOLFSSL_API int wc_ShaCopy(wc_Sha* src, wc_Sha* dst) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha), + &dst->msg, &dst->used, &dst->len, + dst->heap, src->heap); +} + +WOLFSSL_API void wc_ShaFree(wc_Sha* sha) +{ + if (sha == NULL) { + return; + } + wc_MXC_TPU_SHA_FreeCtx(sha, sizeof(wc_Sha), &sha->msg, &sha->used, + &sha->len, sha->heap); +} + +#endif /* NO_SHA */ + +#if defined(WOLFSSL_SHA224) + +WOLFSSL_API int wc_InitSha224_ex(wc_Sha224* sha224, void* heap, int devId) +{ + if (sha224 == NULL) { + return BAD_FUNC_ARG; + } + (void)devId; + XMEMSET(sha224, 0, sizeof(*sha224)); + sha224->heap = heap; + return 0; +} + +WOLFSSL_API int wc_InitSha224(wc_Sha224* sha224) +{ + return wc_InitSha224_ex(sha224, NULL, INVALID_DEVID); +} + +WOLFSSL_API int wc_Sha224Update(wc_Sha224* sha224, const unsigned char* data, + unsigned int len) +{ + if (sha224 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return _wc_Hash_Grow(&sha224->msg, &sha224->used, &sha224->len, + data, (int)len, sha224->heap); +} + +WOLFSSL_API int wc_Sha224Final(wc_Sha224* sha224, unsigned char* hash) +{ + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Final(&sha224->msg, &sha224->used, &sha224->len, + sha224->heap, hash, + MXC_TPU_HASH_SHA224); +} + +WOLFSSL_API int wc_Sha224GetHash(wc_Sha224* sha224, unsigned char* hash) +{ + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha224->msg, + sha224->used, hash, + MXC_TPU_HASH_SHA224); +} + +WOLFSSL_API int wc_Sha224Copy(wc_Sha224* src, wc_Sha224* dst) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha224), + &dst->msg, &dst->used, &dst->len, + dst->heap, src->heap); +} + +WOLFSSL_API void wc_Sha224Free(wc_Sha224* sha224) +{ + if (sha224 == NULL) { + return; + } + wc_MXC_TPU_SHA_FreeCtx(sha224, sizeof(wc_Sha224), &sha224->msg, + &sha224->used, &sha224->len, + sha224->heap); +} + +#endif /* WOLFSSL_SHA224 */ + +#if !defined(NO_SHA256) + +WOLFSSL_API int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId) +{ + if (sha256 == NULL) { + return BAD_FUNC_ARG; + } + (void)devId; + XMEMSET(sha256, 0, sizeof(*sha256)); + sha256->heap = heap; + return 0; +} + +WOLFSSL_API int wc_InitSha256(wc_Sha256* sha256) +{ + return wc_InitSha256_ex(sha256, NULL, INVALID_DEVID); +} + +WOLFSSL_API int wc_Sha256Update(wc_Sha256* sha256, const unsigned char* data, + unsigned int len) +{ + if (sha256 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return _wc_Hash_Grow(&sha256->msg, &sha256->used, &sha256->len, + data, (int)len, sha256->heap); +} + +WOLFSSL_API int wc_Sha256Final(wc_Sha256* sha256, unsigned char* hash) +{ + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Final(&sha256->msg, &sha256->used, &sha256->len, + sha256->heap, hash, + MXC_TPU_HASH_SHA256); +} + +WOLFSSL_API int wc_Sha256GetHash(wc_Sha256* sha256, unsigned char* hash) +{ + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha256->msg, + sha256->used, hash, + MXC_TPU_HASH_SHA256); +} + +WOLFSSL_API int wc_Sha256Copy(wc_Sha256* src, wc_Sha256* dst) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha256), + &dst->msg, &dst->used, &dst->len, + dst->heap, src->heap); +} + +WOLFSSL_API void wc_Sha256Free(wc_Sha256* sha256) +{ + if (sha256 == NULL) { + return; + } + wc_MXC_TPU_SHA_FreeCtx(sha256, sizeof(wc_Sha256), &sha256->msg, + &sha256->used, &sha256->len, + sha256->heap); +} + +#endif /* NO_SHA256 */ + +#if defined(WOLFSSL_SHA384) + +WOLFSSL_API int wc_InitSha384_ex(wc_Sha384* sha384, void* heap, int devId) +{ + if (sha384 == NULL) { + return BAD_FUNC_ARG; + } + (void)devId; + XMEMSET(sha384, 0, sizeof(*sha384)); + sha384->heap = heap; + return 0; +} + +WOLFSSL_API int wc_InitSha384(wc_Sha384* sha384) +{ + return wc_InitSha384_ex(sha384, NULL, INVALID_DEVID); +} + +WOLFSSL_API int wc_Sha384Update(wc_Sha384* sha384, const unsigned char* data, + unsigned int len) +{ + if (sha384 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return _wc_Hash_Grow(&sha384->msg, &sha384->used, &sha384->len, + data, (int)len, sha384->heap); +} + +WOLFSSL_API int wc_Sha384Final(wc_Sha384* sha384, unsigned char* hash) +{ + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Final(&sha384->msg, &sha384->used, &sha384->len, + sha384->heap, hash, + MXC_TPU_HASH_SHA384); +} + +WOLFSSL_API int wc_Sha384GetHash(wc_Sha384* sha384, unsigned char* hash) +{ + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha384->msg, + sha384->used, hash, + MXC_TPU_HASH_SHA384); +} + +WOLFSSL_API int wc_Sha384Copy(wc_Sha384* src, wc_Sha384* dst) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha384), + &dst->msg, &dst->used, &dst->len, + dst->heap, src->heap); +} + +WOLFSSL_API void wc_Sha384Free(wc_Sha384* sha384) +{ + if (sha384 == NULL) { + return; + } + wc_MXC_TPU_SHA_FreeCtx(sha384, sizeof(wc_Sha384), &sha384->msg, + &sha384->used, &sha384->len, + sha384->heap); +} + +#endif /* WOLFSSL_SHA384 */ + +#if defined(WOLFSSL_SHA512) + +WOLFSSL_API int wc_InitSha512_ex(wc_Sha512* sha512, void* heap, int devId) +{ + if (sha512 == NULL) { + return BAD_FUNC_ARG; + } + (void)devId; + XMEMSET(sha512, 0, sizeof(*sha512)); + sha512->heap = heap; +#if defined(WOLFSSL_SHA512_HASHTYPE) + sha512->hashType = WC_HASH_TYPE_SHA512; +#endif + return 0; +} + +WOLFSSL_API int wc_InitSha512(wc_Sha512* sha512) +{ + return wc_InitSha512_ex(sha512, NULL, INVALID_DEVID); +} + +WOLFSSL_API int wc_Sha512Update(wc_Sha512* sha512, const unsigned char* data, + unsigned int len) +{ + if (sha512 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + return _wc_Hash_Grow(&sha512->msg, &sha512->used, &sha512->len, + data, (int)len, sha512->heap); +} + +WOLFSSL_API int wc_Sha512Final(wc_Sha512* sha512, unsigned char* hash) +{ + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Final(&sha512->msg, &sha512->used, &sha512->len, + sha512->heap, hash, + MXC_TPU_HASH_SHA512); +} + +WOLFSSL_API int wc_Sha512GetHash(wc_Sha512* sha512, unsigned char* hash) +{ + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_GetHash((const unsigned char*)sha512->msg, + sha512->used, hash, + MXC_TPU_HASH_SHA512); +} + +WOLFSSL_API int wc_Sha512Copy(wc_Sha512* src, wc_Sha512* dst) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + return wc_MXC_TPU_SHA_Copy(src, dst, sizeof(wc_Sha512), + &dst->msg, &dst->used, &dst->len, + dst->heap, src->heap); +} + +WOLFSSL_API void wc_Sha512Free(wc_Sha512* sha512) +{ + if (sha512 == NULL) { + return; + } + wc_MXC_TPU_SHA_FreeCtx(sha512, sizeof(wc_Sha512), &sha512->msg, + &sha512->used, &sha512->len, + sha512->heap); +} + +#endif /* WOLFSSL_SHA512 */ + +#else /* WOLFSSL_MAX3266X_SHA_ONESHOT */ /* Non-callback path: provide the wc_Sha* API functions directly */ #if !defined(NO_SHA) @@ -1368,6 +2089,8 @@ WOLFSSL_API void wc_Sha512Free(wc_Sha512* sha512) } #endif /* WOLFSSL_SHA512 */ + +#endif /* WOLFSSL_MAX3266X_SHA_ONESHOT */ #endif /* !MAX3266X_SHA_CB */ #endif /* MAX3266X_SHA || MAX3266X_SHA_CB */ diff --git a/wolfssl/wolfcrypt/port/maxim/max3266x.h b/wolfssl/wolfcrypt/port/maxim/max3266x.h index 7f357d6b95..67c5c2fe39 100644 --- a/wolfssl/wolfcrypt/port/maxim/max3266x.h +++ b/wolfssl/wolfcrypt/port/maxim/max3266x.h @@ -62,6 +62,12 @@ #ifndef WOLF_CRYPTO_CB_COPY #define WOLF_CRYPTO_CB_COPY #endif + /* One-shot mode buffers the whole message, so Free is needed too */ + #ifdef WOLFSSL_MAX3266X_SHA_ONESHOT + #ifndef WOLF_CRYPTO_CB_FREE + #define WOLF_CRYPTO_CB_FREE + #endif + #endif #endif /* Crypto HW can be used in parallel on this device */ @@ -255,6 +261,108 @@ #endif #endif /* WOLFSSL_SHA512 */ +#ifdef WOLFSSL_MAX3266X_SHA_ONESHOT + + /* Use HASH_KEEP to accumulate message data for one-shot TPU hardware */ + #ifndef WOLFSSL_HASH_KEEP + #define WOLFSSL_HASH_KEEP + #endif + + #if !defined(NO_SHA) + /* Define the SHA digest for an empty string */ + /* as a constant byte array */ + static const unsigned char MXC_EMPTY_DIGEST_SHA1[20] = { + 0xda, 0x39, 0xa3, 0xee, 0x5e, 0x6b, 0x4b, 0x0d, + 0x32, 0x55, 0xbf, 0xef, 0x95, 0x60, 0x18, 0x90, + 0xaf, 0xd8, 0x07, 0x09}; + #endif /* NO_SHA */ + + #if defined(WOLFSSL_SHA224) + /* Define the SHA-224 digest for an empty string */ + /* as a constant byte array */ + static const unsigned char MXC_EMPTY_DIGEST_SHA224[28] = { + 0xd1, 0x4a, 0x02, 0x8c, 0x2a, 0x3a, 0x2b, 0xc9, + 0x47, 0x61, 0x02, 0xbb, 0x28, 0x82, 0x34, 0xc4, + 0x15, 0xa2, 0xb0, 0x1f, 0x82, 0x8e, 0xa6, 0x2a, + 0xc5, 0xb3, 0xe4, 0x2f}; + #endif /* WOLFSSL_SHA224 */ + + #if !defined(NO_SHA256) + /* Define the SHA-256 digest for an empty string */ + /* as a constant byte array */ + static const unsigned char MXC_EMPTY_DIGEST_SHA256[32] = { + 0xe3, 0xb0, 0xc4, 0x42, 0x98, 0xfc, 0x1c, 0x14, + 0x9a, 0xfb, 0xf4, 0xc8, 0x99, 0x6f, 0xb9, 0x24, + 0x27, 0xae, 0x41, 0xe4, 0x64, 0x9b, 0x93, 0x4c, + 0xa4, 0x95, 0x99, 0x1b, 0x78, 0x52, 0xb8, 0x55}; + #endif /* NO_SHA256 */ + + #if defined(WOLFSSL_SHA384) + /* Define the SHA-384 digest for an empty string */ + /* as a constant byte array */ + static const unsigned char MXC_EMPTY_DIGEST_SHA384[48] = { + 0x38, 0xb0, 0x60, 0xa7, 0x51, 0xac, 0x96, 0x38, + 0x4c, 0xd9, 0x32, 0x7e, 0xb1, 0xb1, 0xe3, 0x6a, + 0x21, 0xfd, 0xb7, 0x11, 0x14, 0xbe, 0x07, 0x43, + 0x4c, 0x0c, 0xc7, 0xbf, 0x63, 0xf6, 0xe1, 0xda, + 0x27, 0x4e, 0xde, 0xbf, 0xe7, 0x6f, 0x65, 0xfb, + 0xd5, 0x1a, 0xd2, 0xf1, 0x48, 0x98, 0xb9, 0x5b}; + #endif /* WOLFSSL_SHA384 */ + + #if defined(WOLFSSL_SHA512) + /* Define the SHA-512 digest for an empty string */ + /* as a constant byte array */ + static const unsigned char MXC_EMPTY_DIGEST_SHA512[64] = { + 0xcf, 0x83, 0xe1, 0x35, 0x7e, 0xef, 0xb8, 0xbd, + 0xf1, 0x54, 0x28, 0x50, 0xd6, 0x6d, 0x80, 0x07, + 0xd6, 0x20, 0xe4, 0x05, 0x0b, 0x57, 0x15, 0xdc, + 0x83, 0xf4, 0xa9, 0x21, 0xd3, 0x6c, 0xe9, 0xce, + 0x47, 0xd0, 0xd1, 0x3c, 0x5d, 0x85, 0xf2, 0xb0, + 0xff, 0x83, 0x18, 0xd2, 0x87, 0x7e, 0xec, 0x2f, + 0x63, 0xb9, 0x31, 0xbd, 0x47, 0x41, 0x7a, 0x81, + 0xa5, 0x38, 0x32, 0x7a, 0xf9, 0x27, 0xda, 0x3e}; + #endif /* WOLFSSL_SHA512 */ + + + /* Check for empty message and provide pre-computed digest if so */ + WOLFSSL_LOCAL int wc_MXC_TPU_SHA_GetDigest(const unsigned char* msg, + unsigned int msgSz, + unsigned char* digest, + MXC_TPU_HASH_TYPE algo); + /* Compute hash from accumulated message using TPU hardware */ + WOLFSSL_LOCAL int wc_MXC_TPU_SHA_GetHash(const unsigned char* msg, + unsigned int msgSz, + unsigned char* digest, + MXC_TPU_HASH_TYPE algo); + /* Free HASH_KEEP message buffer and reset fields */ + WOLFSSL_LOCAL void wc_MXC_TPU_SHA_Free(unsigned char** msg, + unsigned int* used, + unsigned int* len, + void* heap); + /* Free HASH_KEEP message buffer and zero the full SHA context */ + WOLFSSL_LOCAL void wc_MXC_TPU_SHA_FreeCtx(void* ctx, + unsigned int ctxSz, + unsigned char** msg, + unsigned int* used, + unsigned int* len, + void* heap); + /* Copy SHA context and deep copy HASH_KEEP message buffer */ + WOLFSSL_LOCAL int wc_MXC_TPU_SHA_Copy(void* src, void* dst, + unsigned int ctxSz, + unsigned char** dstMsg, + unsigned int* dstUsed, + unsigned int* dstLen, + void* dstHeap, void* srcHeap); + /* Compute hash, free message buffer, and reset fields */ + WOLFSSL_LOCAL int wc_MXC_TPU_SHA_Final(unsigned char** msg, + unsigned int* used, + unsigned int* len, + void* heap, + unsigned char* digest, + MXC_TPU_HASH_TYPE algo); + +#else /* WOLFSSL_MAX3266X_SHA_ONESHOT */ + /* Number of HASH_DIGEST register words for each algorithm's state */ #define MXC_SHA1_STATE_WORDS 5 /* 160-bit state */ #define MXC_SHA224_STATE_WORDS 8 /* 256-bit internal state */ @@ -300,6 +408,8 @@ MXC_TPU_HASH_TYPE algo, unsigned char* hash); +#endif /* WOLFSSL_MAX3266X_SHA_ONESHOT */ + #endif /* defined(MAX3266X_SHA) || defined(MAX3266X_SHA_CB) */ #if defined(MAX3266X_MATH) From 8404459918d9bef8facafaef53a91ead342ed104 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Thu, 4 Jun 2026 21:04:34 +0200 Subject: [PATCH 8/9] Update README --- wolfcrypt/src/port/maxim/README.md | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/wolfcrypt/src/port/maxim/README.md b/wolfcrypt/src/port/maxim/README.md index e759472b94..171251fc18 100644 --- a/wolfcrypt/src/port/maxim/README.md +++ b/wolfcrypt/src/port/maxim/README.md @@ -84,6 +84,12 @@ hardware. - SHA-384 - SHA-512 +By default `MAX3266X_SHA` drives the TPU directly, feeding the message to the +hardware incrementally so hashes of any size are supported. Defining `#define +WOLFSSL_MAX3266X_SHA_ONESHOT` in `user_settings.h` instead buffers the whole +message in memory and hashes it in one shot using the SDK, which has slightly +better performance. + `#define MAX3266X_MATH` (Replaces math operation calls for algos like RSA and ECC key generation): From bd022d995adc90381b8dcc7b784f1f332dbef379 Mon Sep 17 00:00:00 2001 From: Mattia Moffa Date: Thu, 4 Jun 2026 23:11:53 +0200 Subject: [PATCH 9/9] Update README so the #define can be grepped by CI --- wolfcrypt/src/port/maxim/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/wolfcrypt/src/port/maxim/README.md b/wolfcrypt/src/port/maxim/README.md index 171251fc18..3970fd896f 100644 --- a/wolfcrypt/src/port/maxim/README.md +++ b/wolfcrypt/src/port/maxim/README.md @@ -85,10 +85,10 @@ hardware. - SHA-512 By default `MAX3266X_SHA` drives the TPU directly, feeding the message to the -hardware incrementally so hashes of any size are supported. Defining `#define -WOLFSSL_MAX3266X_SHA_ONESHOT` in `user_settings.h` instead buffers the whole -message in memory and hashes it in one shot using the SDK, which has slightly -better performance. +hardware incrementally so hashes of any size are supported. Adding +`#define WOLFSSL_MAX3266X_SHA_ONESHOT` to `user_settings.h` instead buffers +the whole message in memory and hashes it in one shot using the SDK, which +has slightly better performance. `#define MAX3266X_MATH` (Replaces math operation calls for algos like RSA and ECC key generation):