Skip to content
Merged
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
5 changes: 5 additions & 0 deletions .github/configs/os-check-linux.json
Original file line number Diff line number Diff line change
Expand Up @@ -176,6 +176,11 @@
"configure": ["--enable-cryptocb", "--enable-sha3",
"--enable-shake128", "--enable-shake256",
"--enable-cryptocbutils=copy,free"]},
{"name": "cryptocb-shake-xof", "minutes": 2.2,
"comment": "Only WOLF_CRYPTO_CB_SHAKE_XOF dispatches SHAKE absorb and squeeze to the callback, so without this entry the offload counter tests never compile in CI.",
"configure": ["--enable-cryptocb", "--enable-sha3",
"--enable-shake128", "--enable-shake256",
"CPPFLAGS=-DWOLF_CRYPTO_CB_SHAKE_XOF"]},
{"name": "cryptocb-aes-cfb-ofb", "minutes": 2.2,
"comment": "Exercises the AES-CFB/OFB crypto callback wiring (wc_CryptoCb_AesCfb/Ofb Encrypt/Decrypt, the aes.c hooks, and the dedicated offload unit tests). A normal (non-ONLY) cryptocb build keeps the host software AES present as the callbacks' offload fallback; WOLF_CRYPTO_CB_ONLY_AES (no software fallback) is covered separately by cryptocb-only.yml via swdev.",
"configure": ["--enable-cryptocb", "--enable-aescfb",
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/cryptocb-only.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
name: cryptocb-only Tests

# START OF COMMON SECTION
Expand Down Expand Up @@ -151,6 +151,9 @@
{"name": "falcon-onlycb-no-swdev", "minutes": 1.0,
"comment": "WOLF_CRYPTO_CB_ONLY_FALCON without swdev, which has no Falcon handlers: builds the Falcon key API that a callback-only build keeps, including its TLS and ASN callers, and runs the tests that need no device.",
"configure": ["--disable-swdev", "--enable-falcon", "--enable-experimental", "CPPFLAGS=-DWOLF_CRYPTO_CB_ONLY_FALCON"]},
{"name": "shake-xof", "minutes": 4.0,
"comment": "WOLF_CRYPTO_CB_SHAKE_XOF: swdev handles SHAKE absorb and squeeze. No ONLY_* strip exists for SHAKE, so software SHAKE stays in. ML-KEM and ML-DSA reach swdev_shake through WOLF_CRYPTO_CB_FIND, and cryptocb_test runs shake_cb_xof_test.",
"configure": ["CPPFLAGS=-DWOLF_CRYPTO_CB_SHAKE_XOF"]},
{"name": "all", "minutes": 19,
"comment": "All nine ONLY_* macros at once: every supported software primitive is stripped and dispatched through cryptocb. Catches any cross-algorithm call that a single-strip entry would still resolve via the remaining software paths.",
"configure": ["--enable-slhdsa=yes,sha2", "CPPFLAGS=-DWOLF_CRYPTO_CB_ONLY_ECC -DWOLF_CRYPTO_CB_ONLY_RSA -DWOLF_CRYPTO_CB_ONLY_SHA256 -DWOLF_CRYPTO_CB_ONLY_SHA512 -DWOLF_CRYPTO_CB_ONLY_AES -DWOLF_CRYPTO_CB_ONLY_ED25519 -DWOLF_CRYPTO_CB_ONLY_CURVE25519 -DWOLF_CRYPTO_CB_ONLY_CURVE448 -DWOLF_CRYPTO_CB_ONLY_SLHDSA"]},
Expand Down
1 change: 1 addition & 0 deletions .wolfssl_known_macro_extras
Original file line number Diff line number Diff line change
Expand Up @@ -1224,6 +1224,7 @@ WOLFSSL_ZEPHYR_MAIN_ARGS
WOLF_ALLOW_BUILTIN
WOLF_CONF_ASN_TIME
WOLF_CRYPTO_CB_ASYNC_POLL
WOLF_CRYPTO_CB_SHAKE_XOF
WOLF_CRYPTO_DEV
WOLF_NO_TRAILING_ENUM_COMMAS
WindowsCE
Expand Down
124 changes: 123 additions & 1 deletion tests/swdev/swdev.c
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,117 @@ static int swdev_pqc_sig(wc_CryptoInfo* info, int type, int pkType)
}
#endif /* WOLFSSL_HAVE_SLHDSA */


#if defined(WOLFSSL_SHAKE128) || defined(WOLFSSL_SHAKE256)
/* Copy sponge state between the caller's wc_Shake and swdev's shadow */
static void swdev_shake_copy_state(wc_Shake* dst, const wc_Shake* src)
{
XMEMCPY(dst->s, src->s, sizeof(dst->s));
XMEMCPY(dst->t, src->t, sizeof(dst->t));
dst->i = src->i;
#ifdef WOLFSSL_HASH_FLAGS
dst->flags = src->flags;
#endif
}

static int swdev_shake_op(const wc_CryptoInfo* info)
{
#ifdef WOLF_CRYPTO_CB_SHAKE_XOF
return info->hash.shakeOp;
#else
(void)info;
return WC_SHAKE_OP_NONE;
#endif
}

typedef struct swdev_shake_funcs {
int type;
word32 rate;
int (*initFn)(wc_Shake*, void*, int);
int (*updateFn)(wc_Shake*, const byte*, word32);
int (*finalFn)(wc_Shake*, byte*, word32);
int (*absorbFn)(wc_Shake*, const byte*, word32);
int (*squeezeFn)(wc_Shake*, byte*, word32);
void (*freeFn)(wc_Shake*);
} swdev_shake_funcs;

static const swdev_shake_funcs swdev_shake_table[] = {
#ifdef WOLFSSL_SHAKE128
{ WC_HASH_TYPE_SHAKE128, WC_SHA3_128_COUNT * 8U, wc_InitShake128,
wc_Shake128_Update, wc_Shake128_Final, wc_Shake128_Absorb,
wc_Shake128_SqueezeBlocks, wc_Shake128_Free },
#endif
#ifdef WOLFSSL_SHAKE256
{ WC_HASH_TYPE_SHAKE256, WC_SHA3_256_COUNT * 8U, wc_InitShake256,
wc_Shake256_Update, wc_Shake256_Final, wc_Shake256_Absorb,
wc_Shake256_SqueezeBlocks, wc_Shake256_Free },
#endif
};

/* SHAKE handler. When shakeOp is WC_SHAKE_OP_NONE, update and final operations
* are determined by hash.digest. Otherwise hash.shakeOp selects the op. */
static int swdev_shake(wc_CryptoInfo* info)
{
wc_Shake* shake = info->hash.sha3;
wc_Shake shadow;
const swdev_shake_funcs* f = NULL;
size_t idx;
int ret;

if (shake == NULL)
return BAD_FUNC_ARG;

for (idx = 0; idx < sizeof(swdev_shake_table) /
sizeof(swdev_shake_table[0]); idx++) {
if (swdev_shake_table[idx].type == info->hash.type) {
f = &swdev_shake_table[idx];
break;
}
}
if (f == NULL)
return CRYPTOCB_UNAVAILABLE;

ret = f->initFn(&shadow, NULL, INVALID_DEVID);
if (ret != 0)
return ret;

swdev_shake_copy_state(&shadow, shake);

switch (swdev_shake_op(info)) {
case WC_SHAKE_OP_ABSORB:
ret = f->absorbFn(&shadow, info->hash.in, info->hash.inSz);
break;

case WC_SHAKE_OP_SQUEEZE:
/* outSz is the byte count; the API takes whole blocks. */
if ((info->hash.outSz % f->rate) != 0) {
ret = BAD_FUNC_ARG;
break;
}
ret = f->squeezeFn(&shadow, info->hash.digest,
info->hash.outSz / f->rate);
break;

default:
if (info->hash.in != NULL) {
ret = f->updateFn(&shadow, info->hash.in, info->hash.inSz);
}
if ((ret == 0) && (info->hash.digest != NULL)) {
ret = f->finalFn(&shadow, info->hash.digest, info->hash.outSz);
}
break;
}

if (ret == 0) {
swdev_shake_copy_state(shake, &shadow);
}

f->freeFn(&shadow);

return ret;
}
#endif /* WOLFSSL_SHAKE128 || WOLFSSL_SHAKE256 */

#ifndef NO_SHA256
/* Copy hash state between caller's wc_Sha256 and swdev's shadow, leaving
* admin fields (heap, devId, devCtx, W, async, HW ctx) per-side. */
Expand Down Expand Up @@ -1399,7 +1510,9 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
return CRYPTOCB_UNAVAILABLE;
}
#endif
#if !defined(NO_SHA256) || defined(WOLFSSL_SHA512) || defined(WOLFSSL_SHA384)
#if !defined(NO_SHA256) || defined(WOLFSSL_SHA512) || \
defined(WOLFSSL_SHA384) || defined(WOLFSSL_SHAKE128) || \
defined(WOLFSSL_SHAKE256)
case WC_ALGO_TYPE_HASH:
switch (info->hash.type) {
#ifndef NO_SHA256
Expand Down Expand Up @@ -1428,6 +1541,15 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
!defined(WOLFSSL_SWDEV_SHA512_GENERAL_ONLY)
case WC_HASH_TYPE_SHA384:
return swdev_sha384(info);
#endif
#if defined(WOLFSSL_SHAKE128) || defined(WOLFSSL_SHAKE256)
#ifdef WOLFSSL_SHAKE128
case WC_HASH_TYPE_SHAKE128:
#endif
#ifdef WOLFSSL_SHAKE256
case WC_HASH_TYPE_SHAKE256:
#endif
return swdev_shake(info);
#endif
default:
return CRYPTOCB_UNAVAILABLE;
Expand Down
2 changes: 1 addition & 1 deletion tests/unit-mcdc/test_cryptocb_whitebox.c
Original file line number Diff line number Diff line change
Expand Up @@ -816,7 +816,7 @@ int main(void)
#else
WC_HASH_TYPE_SHAKE256,
#endif
in, sizeof(in), out, outLen));
in, sizeof(in), out, outLen, WC_SHAKE_OP_NONE));
WB_NOTE("SHAKE: Shake dev&&dev->cb driven");
#endif
}
Expand Down
13 changes: 12 additions & 1 deletion wolfcrypt/src/cryptocb.c
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,10 @@ Crypto Callback Build Options:
* WOLF_CRYPTO_CB_ONLY_AES: Use only callbacks for AES default: off
* WOLF_CRYPTO_CB_ONLY_ED25519: Use only callbacks for Ed25519 default: off
* WOLF_CRYPTO_CB_ONLY_CURVE25519: Use only callbacks for X25519 default: off
* WOLF_CRYPTO_CB_SHAKE_XOF: Dispatch SHAKE absorb and squeeze default: off
* as well as update and final. Off by
* default because a callback that predates
* hash.shakeOp would misread them.
*/

#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
Expand Down Expand Up @@ -3699,11 +3703,15 @@ int wc_CryptoCb_Sha3Hash(wc_Sha3* sha3, int type, const byte* in,

#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)
word32 inSz, byte* out, word32 outSz, int shakeOp)
{
int ret = WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE);
CryptoCb* dev;

#ifndef WOLF_CRYPTO_CB_SHAKE_XOF
(void)shakeOp;
#endif

/* locate registered callback */
if (shake) {
dev = wc_CryptoCb_FindDevice(shake->devId, WC_ALGO_TYPE_HASH);
Expand All @@ -3723,6 +3731,9 @@ int wc_CryptoCb_Shake(wc_Sha3* shake, int type, const byte* in,
cryptoInfo.hash.inSz = inSz;
cryptoInfo.hash.digest = out;
cryptoInfo.hash.outSz = outSz;
#ifdef WOLF_CRYPTO_CB_SHAKE_XOF
cryptoInfo.hash.shakeOp = shakeOp;
#endif

ret = dev->cb(dev->devId, &cryptoInfo, dev->ctx);
}
Expand Down
7 changes: 7 additions & 0 deletions wolfcrypt/src/port/xilinx/versal_gen2_asu/asu_hash.c
Original file line number Diff line number Diff line change
Expand Up @@ -372,6 +372,13 @@ static int wc_AsuHashCompute(wc_CryptoInfo* info)
if (info == NULL) {
return BAD_FUNC_ARG;
}
#ifdef WOLF_CRYPTO_CB_SHAKE_XOF
/* No sponge state is kept here, so a software absorb would miss saved
* updates. Leave all of SHAKE256 to software. */
if (info->hash.type == WC_HASH_TYPE_SHAKE256) {
return CRYPTOCB_UNAVAILABLE;
}
#endif

ret = wc_AsuHashResolve(info, &devCtxPtr, &shaType, &shaMode, &hashLen);
if (ret != 0) {
Expand Down
66 changes: 62 additions & 4 deletions wolfcrypt/src/sha3.c
Original file line number Diff line number Diff line change
Expand Up @@ -2235,7 +2235,7 @@ int wc_Shake128_Update(wc_Shake* shake, const byte* data, word32 len)
#endif
{
int ret = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE128, data, len,
NULL, 0);
NULL, 0, WC_SHAKE_OP_NONE);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
Expand Down Expand Up @@ -2266,7 +2266,7 @@ int wc_Shake128_Final(wc_Shake* shake, byte* hash, word32 hashLen)
#endif
{
ret = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE128, NULL, 0, hash,
hashLen);
hashLen, WC_SHAKE_OP_NONE);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
Expand Down Expand Up @@ -2303,6 +2303,19 @@ int wc_Shake128_Absorb(wc_Shake* shake, const byte* data, word32 len)
return BAD_FUNC_ARG;
}

#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SHAKE_XOF)
#ifndef WOLF_CRYPTO_CB_FIND
if (shake->devId != INVALID_DEVID)
#endif
{
int cbRet = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE128,
data, len, NULL, 0, WC_SHAKE_OP_ABSORB);
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return cbRet;
/* fall-through when unavailable */
}
#endif

ret = Sha3Update(shake, data, len, WC_SHA3_128_COUNT);
if (ret == 0) {
byte hash[1];
Expand Down Expand Up @@ -2338,6 +2351,22 @@ int wc_Shake128_SqueezeBlocks(wc_Shake* shake, byte* out, word32 blockCnt)
return BAD_FUNC_ARG;
}

#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SHAKE_XOF)
/* Use software when the byte count does not fit in outSz. */
if (blockCnt <= WOLFSSL_MAX_32BIT / (WC_SHA3_128_COUNT * 8U)
#ifndef WOLF_CRYPTO_CB_FIND
&& shake->devId != INVALID_DEVID
#endif
) {
int cbRet = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE128,
NULL, 0, out, blockCnt * (WC_SHA3_128_COUNT * 8U),
WC_SHAKE_OP_SQUEEZE);
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return cbRet;
/* fall-through when unavailable */
}
#endif

#if defined(USE_INTEL_SPEEDUP) || defined(SHA3_NEEDS_VREG_CLAIM)
#ifdef WC_C_DYNAMIC_FALLBACK
sha3_block = SHA3_BLOCK;
Expand Down Expand Up @@ -2558,7 +2587,7 @@ int wc_Shake256_Update(wc_Shake* shake, const byte* data, word32 len)
#endif
{
int ret = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE256, data, len,
NULL, 0);
NULL, 0, WC_SHAKE_OP_NONE);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
Expand Down Expand Up @@ -2590,7 +2619,7 @@ int wc_Shake256_Final(wc_Shake* shake, byte* hash, word32 hashLen)
#endif
{
ret = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE256, NULL, 0, hash,
hashLen);
hashLen, WC_SHAKE_OP_NONE);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
/* fall-through when unavailable */
Expand Down Expand Up @@ -2627,6 +2656,19 @@ int wc_Shake256_Absorb(wc_Shake* shake, const byte* data, word32 len)
return BAD_FUNC_ARG;
}

#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SHAKE_XOF)
#ifndef WOLF_CRYPTO_CB_FIND
if (shake->devId != INVALID_DEVID)
#endif
{
int cbRet = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE256,
data, len, NULL, 0, WC_SHAKE_OP_ABSORB);
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return cbRet;
/* fall-through when unavailable */
}
#endif

ret = Sha3Update(shake, data, len, WC_SHA3_256_COUNT);
if (ret == 0) {
byte hash[1];
Expand Down Expand Up @@ -2655,6 +2697,22 @@ int wc_Shake256_SqueezeBlocks(wc_Shake* shake, byte* out, word32 blockCnt)
return BAD_FUNC_ARG;
}

#if defined(WOLF_CRYPTO_CB) && defined(WOLF_CRYPTO_CB_SHAKE_XOF)
/* Use software when the byte count does not fit in outSz. */
if (blockCnt <= WOLFSSL_MAX_32BIT / (WC_SHA3_256_COUNT * 8U)
#ifndef WOLF_CRYPTO_CB_FIND
&& shake->devId != INVALID_DEVID
#endif
) {
int cbRet = wc_CryptoCb_Shake(shake, WC_HASH_TYPE_SHAKE256,
NULL, 0, out, blockCnt * (WC_SHA3_256_COUNT * 8U),
WC_SHAKE_OP_SQUEEZE);
if (cbRet != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return cbRet;
/* fall-through when unavailable */
}
#endif

#if defined(USE_INTEL_SPEEDUP) || defined(SHA3_NEEDS_VREG_CLAIM)
#ifdef WC_C_DYNAMIC_FALLBACK
sha3_block = SHA3_BLOCK;
Expand Down
Loading
Loading