WOLF_CRYPTO_CB_ONLY_SHA256: strip software SHA-256 and dispatch via swdev

Add WOLF_CRYPTO_CB_ONLY_SHA256: when set, the SHA-256 software.
wc_Sha256FinalRaw is reduced to a stub returning NO_VALID_DEVID, and
sha256.h force-defines WOLFSSL_NO_HASH_RAW so the constant-time TLS HMAC
path falls back to its backend-opaque variant.

Incompatible with
WOLFSSL_SHA224, which aliases the SHA-256 statics; #error guard added.

Add wc_swdev support for SHA-256 for testing.
This commit is contained in:
rizlik
2026-04-29 15:02:47 +00:00
parent 65b49b2fb5
commit 61bfff1dac
8 changed files with 224 additions and 6 deletions
+7
View File
@@ -28,6 +28,13 @@ jobs:
# software path via cryptocb.
- name: RSA
cppflags: -DWOLF_CRYPTO_CB_ONLY_RSA
# WOLF_CRYPTO_CB_ONLY_SHA256: strips software SHA-256; swdev provides
# the software path via cryptocb. SHA-224 piggybacks on the SHA-256
# software core so it is incompatible with this strip and must be
# explicitly disabled (it is default-on on x86_64/aarch64).
- name: SHA256
extra_config: --disable-sha224
cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA256
name: make check (${{ matrix.name }})
if: github.repository_owner == 'wolfssl'
runs-on: ubuntu-24.04
+2
View File
@@ -30609,6 +30609,7 @@ static int test_SSL_CIPHER_get_xxx(void)
}
#if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && \
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)
static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer,
@@ -31612,6 +31613,7 @@ static int test_wc_CryptoCb(void)
{
EXPECT_DECLS;
#if defined(WOLF_CRYPTO_CB) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && \
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)
/* TODO: Add crypto callback API tests */
+68
View File
@@ -13,6 +13,9 @@
#ifdef HAVE_ECC
#include <wolfssl/wolfcrypt/ecc.h>
#endif
#ifndef NO_SHA256
#include <wolfssl/wolfcrypt/sha256.h>
#endif
static int swdev_initialized = 0;
@@ -120,6 +123,62 @@ static int swdev_ecc_get_sig_size(wc_CryptoInfo* info)
}
#endif /* HAVE_ECC */
#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. */
static void swdev_sha256_copy_state(wc_Sha256* dst, const wc_Sha256* src)
{
XMEMCPY(dst->digest, src->digest, sizeof(dst->digest));
XMEMCPY(dst->buffer, src->buffer, sizeof(dst->buffer));
dst->buffLen = src->buffLen;
dst->loLen = src->loLen;
dst->hiLen = src->hiLen;
#ifdef WC_C_DYNAMIC_FALLBACK
dst->sha_method = src->sha_method;
#endif
#ifdef WOLFSSL_HASH_FLAGS
dst->flags = src->flags;
#endif
}
/* Run the op on a per-call shadow wc_Sha256 owned by swdev, copying state
* in and out around it. The caller's struct, allocated by libwolfssl with
* the software init stripped, can't be used directly. */
static int swdev_sha256(wc_CryptoInfo* info)
{
wc_Sha256* sha256 = info->hash.sha256;
wc_Sha256 shadow;
int ret;
if (sha256 == NULL)
return BAD_FUNC_ARG;
ret = wc_InitSha256(&shadow);
if (ret != 0)
return ret;
swdev_sha256_copy_state(&shadow, sha256);
if (info->hash.in != NULL) {
ret = wc_Sha256Update(&shadow, info->hash.in, info->hash.inSz);
if (ret != 0)
goto out;
}
if (info->hash.digest != NULL) {
ret = wc_Sha256Final(&shadow, info->hash.digest);
if (ret != 0)
goto out;
}
swdev_sha256_copy_state(sha256, &shadow);
out:
wc_Sha256Free(&shadow);
return ret;
}
#endif /* !NO_SHA256 */
WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
void* ctx)
{
@@ -164,6 +223,15 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
default:
return CRYPTOCB_UNAVAILABLE;
}
#endif
#ifndef NO_SHA256
case WC_ALGO_TYPE_HASH:
switch (info->hash.type) {
case WC_HASH_TYPE_SHA256:
return swdev_sha256(info);
default:
return CRYPTOCB_UNAVAILABLE;
}
#endif
default:
return CRYPTOCB_UNAVAILABLE;
+1
View File
@@ -15,6 +15,7 @@
#undef WOLF_CRYPTO_CB_ONLY_RSA
#undef WOLF_CRYPTO_CB_ONLY_ECC
#undef WOLF_CRYPTO_CB_ONLY_SHA256
#ifndef WOLF_CRYPTO_CB
#error "wc_swdev requires the main build to define WOLF_CRYPTO_CB"
+1
View File
@@ -52,6 +52,7 @@ Crypto Callback Build Options:
* and SHA-512 operations.
* WOLF_CRYPTO_CB_ONLY_ECC: Use only callbacks for ECC default: off
* WOLF_CRYPTO_CB_ONLY_RSA: Use only callbacks for RSA default: off
* WOLF_CRYPTO_CB_ONLY_SHA256: Use only callbacks for SHA-256 default: off
*/
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>
+74 -4
View File
@@ -60,6 +60,10 @@ on the specific device platform.
#if !defined(NO_SHA256) && !defined(WOLFSSL_RISCV_ASM)
#if defined(WOLF_CRYPTO_CB_ONLY_SHA256) && defined(WOLFSSL_SHA224)
#error "WOLF_CRYPTO_CB_ONLY_SHA256 is incompatible with WOLFSSL_SHA224"
#endif
#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
/* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
#define FIPS_NO_WRAPPERS
@@ -291,7 +295,8 @@ static int InitSha256(wc_Sha256* sha256)
/* Hardware Acceleration */
#if defined(WOLFSSL_X86_64_BUILD) && defined(USE_INTEL_SPEEDUP) && \
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2))
(defined(HAVE_INTEL_AVX1) || defined(HAVE_INTEL_AVX2)) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA256)
/* in case intel instructions aren't available, plus we need the K[] global */
#define NEED_SOFT_SHA256
@@ -1084,7 +1089,7 @@ static int InitSha256(wc_Sha256* sha256)
#elif defined(WOLFSSL_RENESAS_RX64_HASH)
/* implemented in wolfcrypt/src/port/Renesas/renesas_rx64_hw_sha.c */
#elif defined(WOLFSSL_PPC32_ASM)
#elif defined(WOLFSSL_PPC32_ASM) && !defined(WOLF_CRYPTO_CB_ONLY_SHA256)
extern void Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
word32 len);
@@ -1114,7 +1119,7 @@ static int Transform_Sha256(wc_Sha256* sha256, const byte* data)
#define XTRANSFORM Transform_Sha256
#define XTRANSFORM_LEN Transform_Sha256_Len
#elif defined(WOLFSSL_ARMASM)
#elif defined(WOLFSSL_ARMASM) && !defined(WOLF_CRYPTO_CB_ONLY_SHA256)
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
{
@@ -1169,6 +1174,21 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
#define XTRANSFORM Transform_Sha256
#define XTRANSFORM_LEN Transform_Sha256_Len
#elif defined(WOLF_CRYPTO_CB_ONLY_SHA256)
/* Software SHA-256 stripped; every op dispatches via cryptocb. */
int wc_InitSha256_ex(wc_Sha256* sha256, void* heap, int devId)
{
int ret;
if (sha256 == NULL)
return BAD_FUNC_ARG;
ret = InitSha256(sha256);
if (ret != 0)
return ret;
sha256->heap = heap;
sha256->devId = devId;
sha256->devCtx = NULL;
return ret;
}
#else
#define NEED_SOFT_SHA256
@@ -1401,7 +1421,6 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
#endif
/* End wc_ software implementation */
#ifdef XTRANSFORM
static WC_INLINE void AddLength(wc_Sha256* sha256, word32 len)
@@ -1778,6 +1797,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
#if !defined(WOLFSSL_KCAPI_HASH)
#ifndef WOLFSSL_NO_HASH_RAW
int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash)
{
#ifdef LITTLE_ENDIAN_ORDER
@@ -1801,6 +1821,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
return 0;
}
#endif /* !WOLFSSL_NO_HASH_RAW */
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
{
@@ -1964,6 +1985,55 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
#endif /* XTRANSFORM */
#ifdef WOLF_CRYPTO_CB_ONLY_SHA256
int wc_Sha256Update(wc_Sha256* sha256, const byte* data, word32 len)
{
if (sha256 == NULL) {
return BAD_FUNC_ARG;
}
if (data == NULL && len == 0) {
/* valid, but do nothing */
return 0;
}
if (data == NULL) {
return BAD_FUNC_ARG;
}
#ifndef WOLF_CRYPTO_CB_FIND
if (sha256->devId != INVALID_DEVID)
#endif
{
int ret = wc_CryptoCb_Sha256Hash(sha256, data, len, NULL);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
}
return NO_VALID_DEVID;
}
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
{
int ret;
if (sha256 == NULL || hash == NULL) {
return BAD_FUNC_ARG;
}
#ifndef WOLF_CRYPTO_CB_FIND
if (sha256->devId != INVALID_DEVID)
#endif
{
ret = wc_CryptoCb_Sha256Hash(sha256, NULL, 0, hash);
if (ret != WC_NO_ERR_TRACE(CRYPTOCB_UNAVAILABLE))
return ret;
}
return NO_VALID_DEVID;
}
#endif /* WOLF_CRYPTO_CB_ONLY_SHA256 */
#ifdef WOLFSSL_SHA224
+65 -2
View File
@@ -5968,7 +5968,8 @@ exit:
#undef LARGE_HASH_TEST_INPUT_SZ
#endif /* NO_LARGE_HASH_TEST */
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH)
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA256)
static wc_test_ret_t sha256_lms_test(wc_Sha256* sha)
{
byte hash[WC_SHA256_DIGEST_SIZE];
@@ -6061,7 +6062,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha256_test(void)
if ((ret = sha256_large_hash_test(&sha)) != 0)
return ret;
#endif
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH)
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH) && \
!defined(WOLF_CRYPTO_CB_ONLY_SHA256)
if ((ret = sha256_lms_test(&sha)) != 0)
return ret;
#endif
@@ -71320,6 +71322,52 @@ exit_onlycb:
}
#endif
#ifdef WOLF_CRYPTO_CB_ONLY_SHA256
/* Exercise SHA-256 dispatch under CB_ONLY_SHA256: cb-handled then cb-delegated. */
static wc_test_ret_t sha256_onlycb_test(myCryptoDevCtx *ctx)
{
wc_test_ret_t ret = 0;
#if !defined(NO_SHA256)
wc_Sha256 sha;
byte hash[WC_SHA256_DIGEST_SIZE];
const byte in[] = "abc";
ret = wc_InitSha256_ex(&sha, HEAP_HINT, devId);
if (ret != 0)
return WC_TEST_RET_ENC_EC(ret);
/* cb handles the op, expects 0(success) */
ctx->exampleVar = 99;
ret = wc_Sha256Update(&sha, in, (word32)sizeof(in) - 1);
if (ret != 0)
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb);
ret = wc_Sha256Final(&sha, hash);
if (ret != 0)
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb);
/* cb delegates to software, expects NO_VALID_DEVID(failure) */
ctx->exampleVar = 1;
ret = wc_Sha256Update(&sha, in, (word32)sizeof(in) - 1);
if (ret != WC_NO_ERR_TRACE(NO_VALID_DEVID)) {
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb);
} else {
ret = 0;
}
ret = wc_Sha256Final(&sha, hash);
if (ret != WC_NO_ERR_TRACE(NO_VALID_DEVID)) {
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb);
} else {
ret = 0;
}
exit_onlycb:
wc_Sha256Free(&sha);
#endif /* !NO_SHA256 */
(void)ctx;
return ret;
}
#endif /* WOLF_CRYPTO_CB_ONLY_SHA256 */
/* Example crypto dev callback function that calls software version */
static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
{
@@ -72034,6 +72082,15 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
/* set devId to invalid, so software is used */
info->hash.sha256->devId = INVALID_DEVID;
#if defined(WOLF_CRYPTO_CB_ONLY_SHA256)
#ifdef DEBUG_WOLFSSL
printf("CryptoDevCb: exampleVar %d\n", myCtx->exampleVar);
#endif
if (myCtx->exampleVar == 99) {
info->hash.sha256->devId = devIdArg;
return 0;
}
#endif
if (info->hash.in != NULL) {
ret = wc_Sha256Update(
@@ -73162,6 +73219,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
ret = ecc_onlycb_test(&myCtx);
PRIVATE_KEY_LOCK();
#endif
#if defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLFSSL_SWDEV)
PRIVATE_KEY_UNLOCK();
if (ret == 0)
ret = sha256_onlycb_test(&myCtx);
PRIVATE_KEY_LOCK();
#endif
#ifdef WOLFSSL_HAVE_MLKEM
if (ret == 0)
ret = mlkem_test();
+6
View File
@@ -102,6 +102,12 @@
#define WOLFSSL_NO_HASH_RAW
#endif
/* no raw hash access when software transform is stripped */
#if defined(WOLF_CRYPTO_CB_ONLY_SHA256)
#undef WOLFSSL_NO_HASH_RAW
#define WOLFSSL_NO_HASH_RAW
#endif
#define SHA256_NOINLINE WC_NO_INLINE
#if !defined(NO_OLD_SHA_NAMES)