diff --git a/wolfcrypt/src/port/maxim/README.md b/wolfcrypt/src/port/maxim/README.md index 3919ffd0f9..3970fd896f 100644 --- a/wolfcrypt/src/port/maxim/README.md +++ b/wolfcrypt/src/port/maxim/README.md @@ -84,9 +84,11 @@ 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. +By default `MAX3266X_SHA` drives the TPU directly, feeding the message to the +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): diff --git a/wolfcrypt/src/port/maxim/max3266x.c b/wolfcrypt/src/port/maxim/max3266x.c index e326ecadbe..06c6b8c7e9 100644 --- a/wolfcrypt/src/port/maxim/max3266x.c +++ b/wolfcrypt/src/port/maxim/max3266x.c @@ -136,6 +136,8 @@ 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, @@ -202,9 +204,150 @@ int wc_MxcShaCryptoCb(wc_CryptoInfo* info) 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, + 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, 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, + stateWords, blockSz, algo, in, inSz); + } + if (in == NULL && outDigest != NULL) { + int ret; + MAX3266X_MSG("Final CB"); + 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 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, + &ctx->devCtx, 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->digest, + 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); + #endif + #ifdef WOLFSSL_SHA224 + case WC_HASH_TYPE_SHA224: + return wc_MxcShaCbDispatch( + info->hash.sha224->digest, + 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); + #endif + #ifndef NO_SHA256 + case WC_HASH_TYPE_SHA256: + return wc_MxcShaCbDispatch( + info->hash.sha256->digest, + 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); + #endif + #ifdef WOLFSSL_SHA384 + case WC_HASH_TYPE_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_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); + } +} + +#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) { @@ -268,6 +411,55 @@ static int wc_MxcCopyCb(wc_CryptoInfo* info) return WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); } } +#else /* WOLFSSL_MAX3266X_SHA_ONESHOT */ +static int wc_MxcCopyCb(wc_CryptoInfo* info) +{ + word32 sz; + + 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: + wc_ShaFree((wc_Sha*)info->copy.dst); + sz = sizeof(wc_Sha); + break; + #endif + #ifdef WOLFSSL_SHA224 + 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: + wc_Sha256Free((wc_Sha256*)info->copy.dst); + sz = sizeof(wc_Sha256); + break; + #endif + #ifdef WOLFSSL_SHA384 + 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: + wc_Sha512Free((wc_Sha512*)info->copy.dst); + 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 /* WOLFSSL_MAX3266X_SHA_ONESHOT */ #endif /* WOLF_CRYPTO_CB_COPY */ #ifdef WOLF_CRYPTO_CB_FREE @@ -370,7 +562,7 @@ int wc_MxcCryptoCb(int devIdArg, wc_CryptoInfo* info, void* ctx) break; #endif /* WOLF_CRYPTO_CB_FREE */ 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,6 +883,8 @@ 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, @@ -853,7 +1047,285 @@ int wc_MXC_TPU_SHA_Final(unsigned char** msg, unsigned int* used, return status; } +#else /* WOLFSSL_MAX3266X_SHA_ONESHOT */ + +/* TPU hash helpers (bare-metal SHA accelerator) */ + +/* Reset TPU, select hash function, and restore intermediate state into + * the HASH_DIGEST registers. */ +void wc_MXC_TPU_Hash_Setup(MXC_TPU_HASH_TYPE algo, + const unsigned int* state, int stateWords) +{ + 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]; + } +} + +/* 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; + unsigned int fill; + + if (len == 0) { + return 0; + } + + /* Update total length */ + { + unsigned int oldLo = *loLen; + *loLen += len; + if (*loLen < oldLo) { + (*hiLen)++; + } + } + + /* 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(); + } + + /* Buffer remaining data (1..blockSz bytes) */ + if (len > 0) { + XMEMCPY((unsigned char*)buffer, data, len); + *buffLen = len; + } + + return 0; +} + +/* 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; + + 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; +} + +#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) @@ -1198,7 +1670,428 @@ WOLFSSL_API void wc_Sha512Free(wc_Sha512* sha512) } #endif /* WOLFSSL_SHA512 */ -#endif /* !MAX3266X_SHA_CB*/ + +#else /* WOLFSSL_MAX3266X_SHA_ONESHOT */ +/* 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) +{ + if (sha == NULL) { + return BAD_FUNC_ARG; + } + (void)devId; + XMEMSET(sha, 0, sizeof(*sha)); + sha->heap = heap; + 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) +{ + if (sha == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + 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; + } + 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) +{ + if (sha == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + 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) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + XMEMCPY(dst, src, sizeof(wc_Sha)); + return 0; +} + +WOLFSSL_API void wc_ShaFree(wc_Sha* sha) +{ + if (sha == NULL) { + return; + } + ForceZero(sha, sizeof(wc_Sha)); +} + +#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 wc_MXC_TPU_SHA_Init(sha224->digest, MXC_SHA224_STATE_WORDS, + MXC_TPU_HASH_SHA224); +} + +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_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; + } + 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) +{ + if (sha224 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + 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) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + XMEMCPY(dst, src, sizeof(wc_Sha224)); + return 0; +} + +WOLFSSL_API void wc_Sha224Free(wc_Sha224* sha224) +{ + if (sha224 == NULL) { + return; + } + ForceZero(sha224, sizeof(wc_Sha224)); +} + +#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 wc_MXC_TPU_SHA_Init(sha256->digest, MXC_SHA256_STATE_WORDS, + MXC_TPU_HASH_SHA256); +} + +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_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; + } + 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) +{ + if (sha256 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + 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) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + XMEMCPY(dst, src, sizeof(wc_Sha256)); + return 0; +} + +WOLFSSL_API void wc_Sha256Free(wc_Sha256* sha256) +{ + if (sha256 == NULL) { + return; + } + ForceZero(sha256, sizeof(wc_Sha256)); +} + +#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 wc_MXC_TPU_SHA_Init((word32*)sha384->digest, + MXC_SHA384_STATE_WORDS, MXC_TPU_HASH_SHA384); +} + +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) +{ + word32 loLen, hiLen; + int ret; + if (sha384 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + /* 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); + + 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); + return ret; +} + +WOLFSSL_API int wc_Sha384Final(wc_Sha384* sha384, unsigned char* hash) +{ + int ret; + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + 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) +{ + if (sha384 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + 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) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + XMEMCPY(dst, src, sizeof(wc_Sha384)); + return 0; +} + +WOLFSSL_API void wc_Sha384Free(wc_Sha384* sha384) +{ + if (sha384 == NULL) { + return; + } + ForceZero(sha384, sizeof(wc_Sha384)); +} + +#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 wc_MXC_TPU_SHA_Init((word32*)sha512->digest, + MXC_SHA512_STATE_WORDS, MXC_TPU_HASH_SHA512); +} + +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) +{ + word32 loLen, hiLen; + int ret; + if (sha512 == NULL || (data == NULL && len > 0)) { + return BAD_FUNC_ARG; + } + + 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; + } + 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) +{ + if (sha512 == NULL || hash == NULL) { + return BAD_FUNC_ARG; + } + 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) +{ + if (src == NULL || dst == NULL) { + return BAD_FUNC_ARG; + } + XMEMCPY(dst, src, sizeof(wc_Sha512)); + return 0; +} + +WOLFSSL_API void wc_Sha512Free(wc_Sha512* sha512) +{ + if (sha512 == NULL) { + return; + } + ForceZero(sha512, sizeof(wc_Sha512)); +} + +#endif /* WOLFSSL_SHA512 */ + +#endif /* WOLFSSL_MAX3266X_SHA_ONESHOT */ +#endif /* !MAX3266X_SHA_CB */ #endif /* MAX3266X_SHA || MAX3266X_SHA_CB */ #if defined(MAX3266X_MATH) @@ -1285,6 +2178,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"); @@ -1296,19 +2190,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; @@ -1331,7 +2229,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; diff --git a/wolfssl/wolfcrypt/port/maxim/max3266x.h b/wolfssl/wolfcrypt/port/maxim/max3266x.h index 9acc799c75..67c5c2fe39 100644 --- a/wolfssl/wolfcrypt/port/maxim/max3266x.h +++ b/wolfssl/wolfcrypt/port/maxim/max3266x.h @@ -57,13 +57,16 @@ #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 + /* 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 @@ -246,6 +249,20 @@ #if defined(MAX3266X_SHA) || defined(MAX3266X_SHA_CB) + #if defined(WOLFSSL_SHA512) + /* Does not support these SHA512 Macros */ + #ifndef WOLFSSL_NOSHA512_224 + #warning "MAX3266X Port does not support SHA-512/224" + #define WOLFSSL_NOSHA512_224 + #endif + #ifndef WOLFSSL_NOSHA512_256 + #warning "MAX3266X Port does not support SHA-512/256" + #define WOLFSSL_NOSHA512_256 + #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 @@ -293,16 +310,6 @@ #endif /* WOLFSSL_SHA384 */ #if defined(WOLFSSL_SHA512) - /* Does not support these SHA512 Macros */ - #ifndef WOLFSSL_NOSHA512_224 - #warning "MAX3266X Port does not support SHA-512/224" - #define WOLFSSL_NOSHA512_224 - #endif - #ifndef WOLFSSL_NOSHA512_256 - #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] = { @@ -354,6 +361,54 @@ 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 */ + #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) */ + + /* 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 /* WOLFSSL_MAX3266X_SHA_ONESHOT */ #endif /* defined(MAX3266X_SHA) || defined(MAX3266X_SHA_CB) */