SHAKE 128/256 callback wiring and tests, along with fix to devCTX initialization.

This commit is contained in:
night1rider
2026-06-13 23:11:02 -06:00
committed by Zackery Backman
parent dd6da70d39
commit fed375fcea
7 changed files with 350 additions and 2 deletions
+4
View File
@@ -243,6 +243,10 @@ jobs:
{"name": "cryptocb-utils-setkey-export-find", "minutes": 2.2,
"configure": ["--enable-cryptocb", "--enable-keygen",
"--enable-cryptocbutils=setkey,export", "CPPFLAGS=-DWOLF_CRYPTO_CB_FIND"]},
{"name": "cryptocb-shake", "minutes": 2.2,
"comment": "Exercises the SHAKE128/SHAKE256 crypto callback wiring (wc_CryptoCb_Shake, the sha3.c Update/Final hooks, and the dedicated offload unit tests). A normal (non-ONLY) cryptocb build keeps the host software SHA3/SHAKE present as the callbacks' offload fallback.",
"configure": ["--enable-cryptocb", "--enable-sha3",
"--enable-shake128", "--enable-shake256"]},
{"name": "opensslall-rng-seed-cb-no-getpid", "minutes": 2.1,
"configure": ["--enable-opensslall", "--enable-opensslextra",
"CPPFLAGS=-DWC_RNG_SEED_CB -DWOLFSSL_NO_GETPID"]},
+187
View File
@@ -1456,3 +1456,190 @@ int test_wc_Shake256_XOF(void)
return EXPECT_RESULT();
}
/*----------------------------------------------------------------------------*
| CryptoCB SHAKE128/SHAKE256 End-to-End Offload Tests
*----------------------------------------------------------------------------*/
#if defined(WOLF_CRYPTO_CB) && \
(defined(WOLFSSL_SHAKE128) || defined(WOLFSSL_SHAKE256))
#include <wolfssl/wolfcrypt/cryptocb.h>
#define TEST_CRYPTOCB_SHAKE_DEVID 12
static int cryptoCbShakeUpdateCalled = 0;
static int cryptoCbShakeFinalCalled = 0;
/* Mock CryptoCB callback that "offloads" SHAKE. It routes the request back to
* the software implementation, temporarily setting devId to INVALID_DEVID so
* the nested wc_Shake*_Update/Final() call runs in software (a SHAKE lookup by
* INVALID_DEVID finds no device) instead of recursing into the callback. */
static int test_CryptoCb_Shake_Cb(int devId, wc_CryptoInfo* info, void* ctx)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
wc_Shake* shake;
(void)ctx;
if (devId != TEST_CRYPTOCB_SHAKE_DEVID)
return CRYPTOCB_UNAVAILABLE;
if (info->algo_type != WC_ALGO_TYPE_HASH)
return CRYPTOCB_UNAVAILABLE;
if (info->hash.type != WC_HASH_TYPE_SHAKE128 &&
info->hash.type != WC_HASH_TYPE_SHAKE256)
return CRYPTOCB_UNAVAILABLE;
shake = info->hash.sha3; /* wc_Shake is a wc_Sha3 */
if (shake == NULL)
return BAD_FUNC_ARG;
/* run software, no recursion */
shake->devId = INVALID_DEVID;
#ifdef WOLFSSL_SHAKE128
if (info->hash.type == WC_HASH_TYPE_SHAKE128) {
if (info->hash.in != NULL) {
cryptoCbShakeUpdateCalled++;
ret = wc_Shake128_Update(shake, info->hash.in, info->hash.inSz);
}
if (info->hash.digest != NULL) {
cryptoCbShakeFinalCalled++;
ret = wc_Shake128_Final(shake, info->hash.digest, info->hash.outSz);
}
}
#endif
#ifdef WOLFSSL_SHAKE256
if (info->hash.type == WC_HASH_TYPE_SHAKE256) {
if (info->hash.in != NULL) {
cryptoCbShakeUpdateCalled++;
ret = wc_Shake256_Update(shake, info->hash.in, info->hash.inSz);
}
if (info->hash.digest != NULL) {
cryptoCbShakeFinalCalled++;
ret = wc_Shake256_Final(shake, info->hash.digest, info->hash.outSz);
}
}
#endif
shake->devId = TEST_CRYPTOCB_SHAKE_DEVID;
return ret;
}
#endif /* WOLF_CRYPTO_CB && (WOLFSSL_SHAKE128 || WOLFSSL_SHAKE256) */
/*
* Test: End-to-End SHAKE128 Offload via CryptoCB
* Verifies that wc_Shake128_Update/Final route through a registered CryptoCB
* device, that the callback is invoked for both the update and final calls, and
* that the offloaded digest matches a software-only reference.
*/
int test_wc_CryptoCb_Shake128_HashOffload(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHAKE128)
wc_Shake shake;
wc_Shake ref;
static const byte msg[] = {
0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96,
0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c
};
byte refDigest[32];
byte digest[32];
int devRegistered = 0;
XMEMSET(&shake, 0, sizeof(shake));
XMEMSET(&ref, 0, sizeof(ref));
XMEMSET(refDigest, 0, sizeof(refDigest));
XMEMSET(digest, 0, sizeof(digest));
cryptoCbShakeUpdateCalled = 0;
cryptoCbShakeFinalCalled = 0;
/* Software-only reference digest (no devId, no callback). */
ExpectIntEQ(wc_InitShake128(&ref, HEAP_HINT, INVALID_DEVID), 0);
ExpectIntEQ(wc_Shake128_Update(&ref, msg, (word32)sizeof(msg)), 0);
ExpectIntEQ(wc_Shake128_Final(&ref, refDigest, (word32)sizeof(refDigest)), 0);
wc_Shake128_Free(&ref);
/* Register the offload callback. */
ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_SHAKE_DEVID,
test_CryptoCb_Shake_Cb, NULL), 0);
if (EXPECT_SUCCESS())
devRegistered = 1;
/* Drive the public streaming API with the offload devId. */
ExpectIntEQ(wc_InitShake128(&shake, HEAP_HINT, TEST_CRYPTOCB_SHAKE_DEVID), 0);
ExpectIntEQ(wc_Shake128_Update(&shake, msg, (word32)sizeof(msg)), 0);
ExpectIntEQ(cryptoCbShakeUpdateCalled, 1);
ExpectIntEQ(wc_Shake128_Final(&shake, digest, (word32)sizeof(digest)), 0);
ExpectIntEQ(cryptoCbShakeFinalCalled, 1);
/* Offloaded digest must match the software reference. */
ExpectBufEQ(digest, refDigest, sizeof(refDigest));
wc_Shake128_Free(&shake);
if (devRegistered)
wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_SHAKE_DEVID);
#endif /* WOLF_CRYPTO_CB && WOLFSSL_SHAKE128 */
return EXPECT_RESULT();
}
/*
* Test: End-to-End SHAKE256 Offload via CryptoCB
* Verifies that wc_Shake256_Update/Final route through a registered CryptoCB
* device, that the callback is invoked for both the update and final calls, and
* that the offloaded digest matches a software-only reference.
*/
int test_wc_CryptoCb_Shake256_HashOffload(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && defined(WOLFSSL_SHAKE256)
wc_Shake shake;
wc_Shake ref;
static const byte msg[] = {
0x6b,0xc1,0xbe,0xe2, 0x2e,0x40,0x9f,0x96,
0xe9,0x3d,0x7e,0x11, 0x73,0x93,0x17,0x2a,
0xae,0x2d,0x8a,0x57, 0x1e,0x03,0xac,0x9c
};
byte refDigest[64];
byte digest[64];
int devRegistered = 0;
XMEMSET(&shake, 0, sizeof(shake));
XMEMSET(&ref, 0, sizeof(ref));
XMEMSET(refDigest, 0, sizeof(refDigest));
XMEMSET(digest, 0, sizeof(digest));
cryptoCbShakeUpdateCalled = 0;
cryptoCbShakeFinalCalled = 0;
/* Software-only reference digest (no devId, no callback). */
ExpectIntEQ(wc_InitShake256(&ref, HEAP_HINT, INVALID_DEVID), 0);
ExpectIntEQ(wc_Shake256_Update(&ref, msg, (word32)sizeof(msg)), 0);
ExpectIntEQ(wc_Shake256_Final(&ref, refDigest, (word32)sizeof(refDigest)), 0);
wc_Shake256_Free(&ref);
/* Register the offload callback. */
ExpectIntEQ(wc_CryptoCb_RegisterDevice(TEST_CRYPTOCB_SHAKE_DEVID,
test_CryptoCb_Shake_Cb, NULL), 0);
if (EXPECT_SUCCESS())
devRegistered = 1;
/* Drive the public streaming API with the offload devId. */
ExpectIntEQ(wc_InitShake256(&shake, HEAP_HINT, TEST_CRYPTOCB_SHAKE_DEVID), 0);
ExpectIntEQ(wc_Shake256_Update(&shake, msg, (word32)sizeof(msg)), 0);
ExpectIntEQ(cryptoCbShakeUpdateCalled, 1);
ExpectIntEQ(wc_Shake256_Final(&shake, digest, (word32)sizeof(digest)), 0);
ExpectIntEQ(cryptoCbShakeFinalCalled, 1);
/* Offloaded digest must match the software reference. */
ExpectBufEQ(digest, refDigest, sizeof(refDigest));
wc_Shake256_Free(&shake);
if (devRegistered)
wc_CryptoCb_UnRegisterDevice(TEST_CRYPTOCB_SHAKE_DEVID);
#endif /* WOLF_CRYPTO_CB && WOLFSSL_SHAKE256 */
return EXPECT_RESULT();
}
+7 -2
View File
@@ -58,6 +58,9 @@ int test_wc_Shake256_Absorb(void);
int test_wc_Shake256_SqueezeBlocks(void);
int test_wc_Shake256_XOF(void);
int test_wc_CryptoCb_Shake128_HashOffload(void);
int test_wc_CryptoCb_Shake256_HashOffload(void);
#define TEST_SHA3_DECLS \
TEST_DECL_GROUP("sha3", test_wc_InitSha3), \
TEST_DECL_GROUP("sha3", test_wc_Sha3_Update), \
@@ -81,7 +84,8 @@ int test_wc_Shake256_XOF(void);
TEST_DECL_GROUP("shake128", test_wc_Shake128Hash), \
TEST_DECL_GROUP("shake128", test_wc_Shake128_Absorb), \
TEST_DECL_GROUP("shake128", test_wc_Shake128_SqueezeBlocks), \
TEST_DECL_GROUP("shake128", test_wc_Shake128_XOF)
TEST_DECL_GROUP("shake128", test_wc_Shake128_XOF), \
TEST_DECL_GROUP("shake128", test_wc_CryptoCb_Shake128_HashOffload)
#define TEST_SHAKE256_DECLS \
TEST_DECL_GROUP("shake256", test_wc_InitShake256), \
@@ -93,6 +97,7 @@ int test_wc_Shake256_XOF(void);
TEST_DECL_GROUP("shake256", test_wc_Shake256Hash), \
TEST_DECL_GROUP("shake256", test_wc_Shake256_Absorb), \
TEST_DECL_GROUP("shake256", test_wc_Shake256_SqueezeBlocks), \
TEST_DECL_GROUP("shake256", test_wc_Shake256_XOF)
TEST_DECL_GROUP("shake256", test_wc_Shake256_XOF), \
TEST_DECL_GROUP("shake256", test_wc_CryptoCb_Shake256_HashOffload)
#endif /* WOLFCRYPT_TEST_SHA3_H */
+34
View File
@@ -2219,6 +2219,40 @@ int wc_CryptoCb_Sha3Hash(wc_Sha3* sha3, int type, const byte* in,
return wc_CryptoCb_TranslateErrorCode(ret);
}
#if defined(WOLFSSL_SHAKE128) || defined(WOLFSSL_SHAKE256)
int wc_CryptoCb_Shake(wc_Sha3* shake, int type, const byte* in,
word32 inSz, byte* out, word32 outSz)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
CryptoCb* dev;
/* locate registered callback */
if (shake) {
dev = wc_CryptoCb_FindDevice(shake->devId, WC_ALGO_TYPE_HASH);
}
else {
/* locate first callback and try using it */
dev = wc_CryptoCb_FindDeviceByIndex(0);
}
if (dev && dev->cb) {
wc_CryptoInfo cryptoInfo;
XMEMSET(&cryptoInfo, 0, sizeof(cryptoInfo));
cryptoInfo.algo_type = WC_ALGO_TYPE_HASH;
cryptoInfo.hash.type = type;
cryptoInfo.hash.sha3 = shake; /* wc_Shake is a wc_Sha3 */
cryptoInfo.hash.in = in;
cryptoInfo.hash.inSz = inSz;
cryptoInfo.hash.digest = out;
cryptoInfo.hash.outSz = outSz;
ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
}
return wc_CryptoCb_TranslateErrorCode(ret);
}
#endif /* WOLFSSL_SHAKE128 || WOLFSSL_SHAKE256 */
#endif /* WOLFSSL_SHA3 && (!HAVE_FIPS || FIPS_VERSION_GE(6, 0)) */
#ifndef NO_HMAC
+53
View File
@@ -1122,6 +1122,7 @@ static int wc_InitSha3(wc_Sha3* sha3, void* heap, int devId)
#endif
#if defined(WOLF_CRYPTO_CB)
sha3->devId = devId;
sha3->devCtx = NULL;
/* Set to none to determine the hash type later */
/* in the update/final functions based on the p value */
sha3->hashType = WC_HASH_TYPE_NONE;
@@ -1832,6 +1833,19 @@ int wc_Shake128_Update(wc_Shake* shake, const byte* data, word32 len)
return 0;
}
#ifdef WOLF_CRYPTO_CB
#ifndef WOLF_CRYPTO_CB_FIND
if (shake->devId != INVALID_DEVID)
#endif
{
int ret = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE128, data, len,
NULL, 0);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
}
#endif
return Sha3Update(shake, data, len, WC_SHA3_128_COUNT);
}
@@ -1850,6 +1864,19 @@ int wc_Shake128_Final(wc_Shake* shake, byte* hash, word32 hashLen)
return BAD_FUNC_ARG;
}
#ifdef WOLF_CRYPTO_CB
#ifndef WOLF_CRYPTO_CB_FIND
if (shake->devId != INVALID_DEVID)
#endif
{
ret = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE128, NULL, 0, hash,
hashLen);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
}
#endif
ret = Sha3Final(shake, 0x1f, hash, WC_SHA3_128_COUNT, hashLen);
if (ret != 0)
return ret;
@@ -2079,6 +2106,19 @@ int wc_Shake256_Update(wc_Shake* shake, const byte* data, word32 len)
return 0;
}
#ifdef WOLF_CRYPTO_CB
#ifndef WOLF_CRYPTO_CB_FIND
if (shake->devId != INVALID_DEVID)
#endif
{
int ret = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE256, data, len,
NULL, 0);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
}
#endif
return Sha3Update(shake, data, len, WC_SHA3_256_COUNT);
}
@@ -2098,6 +2138,19 @@ int wc_Shake256_Final(wc_Shake* shake, byte* hash, word32 hashLen)
return BAD_FUNC_ARG;
}
#ifdef WOLF_CRYPTO_CB
#ifndef WOLF_CRYPTO_CB_FIND
if (shake->devId != INVALID_DEVID)
#endif
{
ret = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE256, NULL, 0, hash,
hashLen);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
}
#endif
ret = Sha3Final(shake, 0x1f, hash, WC_SHA3_256_COUNT, hashLen);
if (ret != 0)
return ret;
+58
View File
@@ -73755,6 +73755,56 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
/* reset devId */
info->hash.sha3->devId = devIdArg;
}
#ifdef WOLFSSL_SHAKE128
else if (info->hash.type == WC_HASH_TYPE_SHAKE128) {
if (info->hash.sha3 == NULL)
return NOT_COMPILED_IN;
/* set devId to invalid, so software is used */
info->hash.sha3->devId = INVALID_DEVID;
if (info->hash.in != NULL) {
ret = wc_Shake128_Update(
info->hash.sha3,
info->hash.in,
info->hash.inSz);
}
if (info->hash.digest != NULL) {
ret = wc_Shake128_Final(
info->hash.sha3,
info->hash.digest,
info->hash.outSz);
}
/* reset devId */
info->hash.sha3->devId = devIdArg;
}
#endif /* WOLFSSL_SHAKE128 */
#ifdef WOLFSSL_SHAKE256
else if (info->hash.type == WC_HASH_TYPE_SHAKE256) {
if (info->hash.sha3 == NULL)
return NOT_COMPILED_IN;
/* set devId to invalid, so software is used */
info->hash.sha3->devId = INVALID_DEVID;
if (info->hash.in != NULL) {
ret = wc_Shake256_Update(
info->hash.sha3,
info->hash.in,
info->hash.inSz);
}
if (info->hash.digest != NULL) {
ret = wc_Shake256_Final(
info->hash.sha3,
info->hash.digest,
info->hash.outSz);
}
/* reset devId */
info->hash.sha3->devId = devIdArg;
}
#endif /* WOLFSSL_SHAKE256 */
else
#endif
{
@@ -74844,6 +74894,14 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
#ifdef WOLFSSL_SHA3
if (ret == 0)
ret = sha3_test();
#ifdef WOLFSSL_SHAKE128
if (ret == 0)
ret = shake128_test();
#endif
#ifdef WOLFSSL_SHAKE256
if (ret == 0)
ret = shake256_test();
#endif
#endif
#endif
#ifndef NO_HMAC
+7
View File
@@ -455,6 +455,7 @@ typedef struct wc_CryptoInfo {
const byte* in;
word32 inSz;
byte* digest;
word32 outSz; /* SHAKE extendable output length (0 for fixed hashes) */
#ifdef HAVE_ANONYMOUS_INLINE_AGGREGATES
union {
#endif
@@ -881,6 +882,12 @@ WOLFSSL_LOCAL int wc_CryptoCb_Sha512Hash(wc_Sha512* sha512, const byte* in,
#ifdef WOLFSSL_SHA3
WOLFSSL_LOCAL int wc_CryptoCb_Sha3Hash(wc_Sha3* sha3, int type, const byte* in,
word32 inSz, byte* digest);
#if defined(WOLFSSL_SHAKE128) || defined(WOLFSSL_SHAKE256)
/* SHAKE is an extendable output function: out/outSz carry the requested output
* on the final call (in/inSz carry message data on update calls). */
WOLFSSL_LOCAL int wc_CryptoCb_Shake(wc_Sha3* shake, int type, const byte* in,
word32 inSz, byte* out, word32 outSz);
#endif
#endif
#ifndef NO_HMAC