Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions .github/workflows/os-check.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
name: Ubuntu-Macos-Windows Tests

# START OF COMMON SECTION
Expand Down Expand Up @@ -243,6 +243,10 @@
{"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"]},
Expand Down
187 changes: 187 additions & 0 deletions tests/api/test_sha3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}

9 changes: 7 additions & 2 deletions tests/api/test_sha3.h
Original file line number Diff line number Diff line change
Expand Up @@ -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), \
Expand All @@ -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), \
Expand All @@ -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 changes: 34 additions & 0 deletions wolfcrypt/src/cryptocb.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
53 changes: 53 additions & 0 deletions wolfcrypt/src/sha3.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand All @@ -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;
Expand Down Expand Up @@ -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);
}

Expand All @@ -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;
Expand Down
Loading
Loading