Merge pull request #10431 from mattia-moffa/20260330-max32666-sha-bare-metal

MAX32666 bare-metal SHA accelerator
This commit is contained in:
David Garske
2026-06-05 13:03:00 -07:00
committed by GitHub
3 changed files with 977 additions and 22 deletions
+5 -3
View File
@@ -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):
+904 -6
View File
@@ -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;
+68 -13
View File
@@ -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) */