From 9cbc3f97e58c43bcbdc0532eb02376bb491d03b7 Mon Sep 17 00:00:00 2001 From: Marco Oliverio Date: Mon, 6 Oct 2025 11:06:02 +0200 Subject: [PATCH] cryptocb: sha512_family: try specific digest length hashtype first If the cryptocb provider supports specific SHA512/224 and SHA512/256 hashtype, this commit allows to: 1. avoid a copy 2. do not touch the output buffer outside of the cryptocb handler 2 might be important for cryptocb provider that needs special handling of memory buffer (DMA, memory mapping). --- wolfcrypt/src/cryptocb.c | 31 +++++++++++++++++++++++++-- wolfcrypt/src/port/arm/armv8-sha512.c | 6 ++---- wolfcrypt/src/sha512.c | 6 ++---- wolfssl/wolfcrypt/cryptocb.h | 2 +- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/wolfcrypt/src/cryptocb.c b/wolfcrypt/src/cryptocb.c index 781af62a3..533380954 100644 --- a/wolfcrypt/src/cryptocb.c +++ b/wolfcrypt/src/cryptocb.c @@ -1720,7 +1720,7 @@ int wc_CryptoCb_Sha384Hash(wc_Sha384* sha384, const byte* in, #ifdef WOLFSSL_SHA512 int wc_CryptoCb_Sha512Hash(wc_Sha512* sha512, const byte* in, - word32 inSz, byte* digest) + word32 inSz, byte* digest, size_t digestSz) { int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE); CryptoCb* dev; @@ -1738,16 +1738,43 @@ int wc_CryptoCb_Sha512Hash(wc_Sha512* sha512, const byte* in, } if (dev && dev->cb) { + byte localHash[WC_SHA512_DIGEST_SIZE]; wc_CryptoInfo cryptoInfo; XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo)); cryptoInfo.algo_type = WC_ALGO_TYPE_HASH; - cryptoInfo.hash.type = WC_HASH_TYPE_SHA512; cryptoInfo.hash.sha512 = sha512; cryptoInfo.hash.in = in; cryptoInfo.hash.inSz = inSz; cryptoInfo.hash.digest = digest; + /* try the specific family callbacks first */ +#if !defined(WOLFSSL_NOSHA512_224) + if (digest != NULL && digestSz == WC_SHA512_224_DIGEST_SIZE) { + cryptoInfo.hash.type = WC_HASH_TYPE_SHA512_224; + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + ret = wc_CryptoCb_TranslateErrorCode(ret); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + } +#endif +#if !defined(WOLFSSL_NOSHA512_256) + if (digest != NULL && digestSz == WC_SHA512_256_DIGEST_SIZE) { + cryptoInfo.hash.type = WC_HASH_TYPE_SHA512_256; + ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + ret = wc_CryptoCb_TranslateErrorCode(ret); + if (ret != CRYPTOCB_UNAVAILABLE) + return ret; + } +#endif + cryptoInfo.hash.type = WC_HASH_TYPE_SHA512; + /* use local buffer if not full size */ + if (digest != NULL && digestSz != WC_SHA512_DIGEST_SIZE) + cryptoInfo.hash.digest = localHash; ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx); + ret = wc_CryptoCb_TranslateErrorCode(ret); + if (ret == 0 && digest != NULL && digestSz != WC_SHA512_DIGEST_SIZE) + XMEMCPY(digest, localHash, digestSz); + return ret; } return wc_CryptoCb_TranslateErrorCode(ret); diff --git a/wolfcrypt/src/port/arm/armv8-sha512.c b/wolfcrypt/src/port/arm/armv8-sha512.c index 57020f01c..1e88016da 100644 --- a/wolfcrypt/src/port/arm/armv8-sha512.c +++ b/wolfcrypt/src/port/arm/armv8-sha512.c @@ -543,7 +543,7 @@ int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) if (sha512->devId != INVALID_DEVID) #endif { - int ret = wc_CryptoCb_Sha512Hash(sha512, data, len, NULL); + int ret = wc_CryptoCb_Sha512Hash(sha512, data, len, NULL, 0); if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ @@ -675,10 +675,8 @@ static int Sha512_Family_Final(wc_Sha512* sha512, byte* hash, if (sha512->devId != INVALID_DEVID) #endif { - byte localHash[WC_SHA512_DIGEST_SIZE]; - ret = wc_CryptoCb_Sha512Hash(sha512, NULL, 0, localHash); + ret = wc_CryptoCb_Sha512Hash(sha512, NULL, 0, hash, digestSz); if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { - XMEMCPY(hash, localHash, digestSz); return ret; } /* fall-through when unavailable */ diff --git a/wolfcrypt/src/sha512.c b/wolfcrypt/src/sha512.c index 0454ab62f..9cdb2ae70 100644 --- a/wolfcrypt/src/sha512.c +++ b/wolfcrypt/src/sha512.c @@ -1192,7 +1192,7 @@ int wc_Sha512Update(wc_Sha512* sha512, const byte* data, word32 len) if (sha512->devId != INVALID_DEVID) #endif { - int ret = wc_CryptoCb_Sha512Hash(sha512, data, len, NULL); + int ret = wc_CryptoCb_Sha512Hash(sha512, data, len, NULL, 0); if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) return ret; /* fall-through when unavailable */ @@ -1429,10 +1429,8 @@ static int Sha512_Family_Final(wc_Sha512* sha512, byte* hash, size_t digestSz, if (sha512->devId != INVALID_DEVID) #endif { - byte localHash[WC_SHA512_DIGEST_SIZE]; - ret = wc_CryptoCb_Sha512Hash(sha512, NULL, 0, localHash); + ret = wc_CryptoCb_Sha512Hash(sha512, NULL, 0, hash, digestSz); if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE)) { - XMEMCPY(hash, localHash, digestSz); return ret; } /* fall-through when unavailable */ diff --git a/wolfssl/wolfcrypt/cryptocb.h b/wolfssl/wolfcrypt/cryptocb.h index 35b6f715c..05543eadc 100644 --- a/wolfssl/wolfcrypt/cryptocb.h +++ b/wolfssl/wolfcrypt/cryptocb.h @@ -676,7 +676,7 @@ WOLFSSL_LOCAL int wc_CryptoCb_Sha384Hash(wc_Sha384* sha384, const byte* in, #endif #ifdef WOLFSSL_SHA512 WOLFSSL_LOCAL int wc_CryptoCb_Sha512Hash(wc_Sha512* sha512, const byte* in, - word32 inSz, byte* digest); + word32 inSz, byte* digest, size_t digestSz); #endif #ifdef WOLFSSL_SHA3