Skip to content

Commit 994b806

Browse files
committed
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.
1 parent bd5e435 commit 994b806

8 files changed

Lines changed: 170 additions & 3 deletions

File tree

.github/workflows/cryptocb-only.yml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,13 @@ jobs:
2828
# software path via cryptocb.
2929
- name: RSA
3030
cppflags: -DWOLF_CRYPTO_CB_ONLY_RSA
31+
# WOLF_CRYPTO_CB_ONLY_SHA256: strips software SHA-256; swdev provides
32+
# the software path via cryptocb. SHA-224 piggybacks on the SHA-256
33+
# software core so it is incompatible with this strip and must be
34+
# explicitly disabled (it is default-on on x86_64/aarch64).
35+
- name: SHA256
36+
extra_config: --disable-sha224
37+
cppflags: -DWOLF_CRYPTO_CB_ONLY_SHA256
3138
name: make check (${{ matrix.name }})
3239
if: github.repository_owner == 'wolfssl'
3340
runs-on: ubuntu-24.04

tests/api.c

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -28472,6 +28472,7 @@ static int test_SSL_CIPHER_get_xxx(void)
2847228472
}
2847328473

2847428474
#if defined(WOLF_CRYPTO_CB) && defined(HAVE_IO_TESTS_DEPENDENCIES) && \
28475+
!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && \
2847528476
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)
2847628477

2847728478
static int load_pem_key_file_as_der(const char* privKeyFile, DerBuffer** pDer,
@@ -29475,6 +29476,7 @@ static int test_wc_CryptoCb(void)
2947529476
{
2947629477
EXPECT_DECLS;
2947729478
#if defined(WOLF_CRYPTO_CB) && \
29479+
!defined(WOLF_CRYPTO_CB_ONLY_SHA256) && \
2947829480
!defined(WOLF_CRYPTO_CB_ONLY_ECC) && !defined(WOLF_CRYPTO_CB_ONLY_RSA)
2947929481
/* TODO: Add crypto callback API tests */
2948029482

tests/swdev/swdev.c

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,9 @@
1313
#ifdef HAVE_ECC
1414
#include <wolfssl/wolfcrypt/ecc.h>
1515
#endif
16+
#ifndef NO_SHA256
17+
#include <wolfssl/wolfcrypt/sha256.h>
18+
#endif
1619

1720
static int swdev_initialized = 0;
1821

@@ -120,6 +123,62 @@ static int swdev_ecc_get_sig_size(wc_CryptoInfo* info)
120123
}
121124
#endif /* HAVE_ECC */
122125

126+
#ifndef NO_SHA256
127+
/* Copy hash state between caller's wc_Sha256 and swdev's shadow, leaving
128+
* admin fields (heap, devId, devCtx, W, async, HW ctx) per-side. */
129+
static void swdev_sha256_copy_state(wc_Sha256* dst, const wc_Sha256* src)
130+
{
131+
XMEMCPY(dst->digest, src->digest, sizeof(dst->digest));
132+
XMEMCPY(dst->buffer, src->buffer, sizeof(dst->buffer));
133+
dst->buffLen = src->buffLen;
134+
dst->loLen = src->loLen;
135+
dst->hiLen = src->hiLen;
136+
#ifdef WC_C_DYNAMIC_FALLBACK
137+
dst->sha_method = src->sha_method;
138+
#endif
139+
#ifdef WOLFSSL_HASH_FLAGS
140+
dst->flags = src->flags;
141+
#endif
142+
}
143+
144+
/* Run the op on a per-call shadow wc_Sha256 owned by swdev, copying state
145+
* in and out around it. The caller's struct, allocated by libwolfssl with
146+
* the software init stripped, can't be used directly. */
147+
static int swdev_sha256(wc_CryptoInfo* info)
148+
{
149+
wc_Sha256* sha256 = info->hash.sha256;
150+
wc_Sha256 shadow;
151+
int ret;
152+
153+
if (sha256 == NULL)
154+
return BAD_FUNC_ARG;
155+
156+
ret = wc_InitSha256(&shadow);
157+
if (ret != 0)
158+
return ret;
159+
160+
swdev_sha256_copy_state(&shadow, sha256);
161+
162+
if (info->hash.in != NULL) {
163+
ret = wc_Sha256Update(&shadow, info->hash.in, info->hash.inSz);
164+
if (ret != 0)
165+
goto out;
166+
}
167+
168+
if (info->hash.digest != NULL) {
169+
ret = wc_Sha256Final(&shadow, info->hash.digest);
170+
if (ret != 0)
171+
goto out;
172+
}
173+
174+
swdev_sha256_copy_state(sha256, &shadow);
175+
176+
out:
177+
wc_Sha256Free(&shadow);
178+
return ret;
179+
}
180+
#endif /* !NO_SHA256 */
181+
123182
WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
124183
void* ctx)
125184
{
@@ -164,6 +223,15 @@ WC_SWDEV_EXPORT int wc_SwDev_Callback(int devId, wc_CryptoInfo* info,
164223
default:
165224
return CRYPTOCB_UNAVAILABLE;
166225
}
226+
#endif
227+
#ifndef NO_SHA256
228+
case WC_ALGO_TYPE_HASH:
229+
switch (info->hash.type) {
230+
case WC_HASH_TYPE_SHA256:
231+
return swdev_sha256(info);
232+
default:
233+
return CRYPTOCB_UNAVAILABLE;
234+
}
167235
#endif
168236
default:
169237
return CRYPTOCB_UNAVAILABLE;

tests/swdev/user_settings.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515

1616
#undef WOLF_CRYPTO_CB_ONLY_RSA
1717
#undef WOLF_CRYPTO_CB_ONLY_ECC
18+
#undef WOLF_CRYPTO_CB_ONLY_SHA256
1819

1920
#ifndef WOLF_CRYPTO_CB
2021
#error "wc_swdev requires the main build to define WOLF_CRYPTO_CB"

wolfcrypt/src/cryptocb.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@ Crypto Callback Build Options:
5252
* and SHA-512 operations.
5353
* WOLF_CRYPTO_CB_ONLY_ECC: Use only callbacks for ECC default: off
5454
* WOLF_CRYPTO_CB_ONLY_RSA: Use only callbacks for RSA default: off
55+
* WOLF_CRYPTO_CB_ONLY_SHA256: Use only callbacks for SHA-256 default: off
5556
*/
5657

5758
#include <wolfssl/wolfcrypt/libwolfssl_sources.h>

wolfcrypt/src/sha256.c

Lines changed: 22 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,10 @@ on the specific device platform.
6060

6161
#if !defined(NO_SHA256) && !defined(WOLFSSL_RISCV_ASM)
6262

63+
#if defined(WOLF_CRYPTO_CB_ONLY_SHA256) && defined(WOLFSSL_SHA224)
64+
#error "WOLF_CRYPTO_CB_ONLY_SHA256 is incompatible with WOLFSSL_SHA224"
65+
#endif
66+
6367
#if defined(HAVE_FIPS) && defined(HAVE_FIPS_VERSION) && (HAVE_FIPS_VERSION >= 2)
6468
/* set NO_WRAPPERS before headers, use direct internal f()s not wrappers */
6569
#define FIPS_NO_WRAPPERS
@@ -1205,6 +1209,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
12051209

12061210
#ifdef NEED_SOFT_SHA256
12071211

1212+
#ifndef WOLF_CRYPTO_CB_ONLY_SHA256
12081213
static const FLASH_QUALIFIER ALIGN32 word32 K[64] = {
12091214
0x428A2F98L, 0x71374491L, 0xB5C0FBCFL, 0xE9B5DBA5L, 0x3956C25BL,
12101215
0x59F111F1L, 0x923F82A4L, 0xAB1C5ED5L, 0xD807AA98L, 0x12835B01L,
@@ -1580,6 +1585,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
15801585

15811586
return ret;
15821587
}
1588+
#endif /* !WOLF_CRYPTO_CB_ONLY_SHA256 */
15831589

15841590
#if defined(WOLFSSL_KCAPI_HASH)
15851591
/* implemented in wolfcrypt/src/port/kcapi/kcapi_hash.c */
@@ -1609,6 +1615,9 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
16091615
/* fall-through when unavailable */
16101616
}
16111617
#endif
1618+
#ifdef WOLF_CRYPTO_CB_ONLY_SHA256
1619+
return NO_VALID_DEVID;
1620+
#else
16121621
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
16131622
if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) {
16141623
#if defined(HAVE_INTEL_QA)
@@ -1618,9 +1627,11 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
16181627
#endif /* WOLFSSL_ASYNC_CRYPT */
16191628

16201629
return Sha256Update(sha256, data, len);
1630+
#endif /* !WOLF_CRYPTO_CB_ONLY_SHA256 */
16211631
}
16221632
#endif
16231633

1634+
#ifndef WOLF_CRYPTO_CB_ONLY_SHA256
16241635
static WC_INLINE int Sha256Final(wc_Sha256* sha256)
16251636
{
16261637
int ret;
@@ -1771,9 +1782,11 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
17711782

17721783
return ret;
17731784
}
1785+
#endif /* !WOLF_CRYPTO_CB_ONLY_SHA256 */
17741786

17751787
#if !defined(WOLFSSL_KCAPI_HASH)
17761788

1789+
#ifndef WOLFSSL_NO_HASH_RAW
17771790
int wc_Sha256FinalRaw(wc_Sha256* sha256, byte* hash)
17781791
{
17791792
#ifdef LITTLE_ENDIAN_ORDER
@@ -1797,6 +1810,7 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
17971810

17981811
return 0;
17991812
}
1813+
#endif /* !WOLFSSL_NO_HASH_RAW */
18001814

18011815
int wc_Sha256Final(wc_Sha256* sha256, byte* hash)
18021816
{
@@ -1818,6 +1832,9 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
18181832
}
18191833
#endif
18201834

1835+
#ifdef WOLF_CRYPTO_CB_ONLY_SHA256
1836+
return NO_VALID_DEVID;
1837+
#else
18211838
#if defined(WOLFSSL_ASYNC_CRYPT) && defined(WC_ASYNC_ENABLE_SHA256)
18221839
if (sha256->asyncDev.marker == WOLFSSL_ASYNC_MARKER_SHA256) {
18231840
#if defined(HAVE_INTEL_QA)
@@ -1841,9 +1858,11 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
18411858
XMEMCPY(hash, sha256->digest, WC_SHA256_DIGEST_SIZE);
18421859

18431860
return InitSha256(sha256); /* reset state */
1861+
#endif /* !WOLF_CRYPTO_CB_ONLY_SHA256 */
18441862
}
18451863

1846-
#if defined(OPENSSL_EXTRA) || defined(HAVE_CURL)
1864+
#if (defined(OPENSSL_EXTRA) || defined(HAVE_CURL)) && \
1865+
!defined(WOLF_CRYPTO_CB_ONLY_SHA256)
18471866
/* Apply SHA256 transformation to the data */
18481867
/* @param sha a pointer to wc_Sha256 structure */
18491868
/* @param data data to be applied SHA256 transformation */
@@ -1867,7 +1886,8 @@ static WC_INLINE int Transform_Sha256_Len(wc_Sha256* sha256, const byte* data,
18671886
}
18681887
#endif /* OPENSSL_EXTRA || HAVE_CURL */
18691888

1870-
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH)
1889+
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH) && \
1890+
!defined(WOLF_CRYPTO_CB_ONLY_SHA256)
18711891
/* One block will be used from data.
18721892
* hash must be big enough to hold all of digest output.
18731893
*/

wolfcrypt/test/test.c

Lines changed: 63 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5665,7 +5665,8 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t sha256_test(void)
56655665
#undef LARGE_HASH_TEST_INPUT_SZ
56665666
#endif /* NO_LARGE_HASH_TEST */
56675667

5668-
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH)
5668+
#if defined(WOLFSSL_HAVE_LMS) && !defined(WOLFSSL_LMS_FULL_HASH) && \
5669+
!defined(WOLF_CRYPTO_CB_ONLY_SHA256)
56695670
{
56705671
WOLFSSL_SMALL_STACK_STATIC const unsigned char
56715672
data_hb[WC_SHA256_BLOCK_SIZE] = {
@@ -68106,6 +68107,52 @@ static wc_test_ret_t ecc_onlycb_test(myCryptoDevCtx *ctx)
6810668107
}
6810768108
#endif
6810868109

68110+
#ifdef WOLF_CRYPTO_CB_ONLY_SHA256
68111+
/* Exercise SHA-256 dispatch under CB_ONLY_SHA256: cb-handled then cb-delegated. */
68112+
static wc_test_ret_t sha256_onlycb_test(myCryptoDevCtx *ctx)
68113+
{
68114+
wc_test_ret_t ret = 0;
68115+
#if !defined(NO_SHA256)
68116+
wc_Sha256 sha;
68117+
byte hash[WC_SHA256_DIGEST_SIZE];
68118+
const byte in[] = "abc";
68119+
68120+
ret = wc_InitSha256_ex(&sha, HEAP_HINT, devId);
68121+
if (ret != 0)
68122+
return WC_TEST_RET_ENC_EC(ret);
68123+
68124+
/* cb handles the op, expects 0(success) */
68125+
ctx->exampleVar = 99;
68126+
ret = wc_Sha256Update(&sha, in, (word32)sizeof(in) - 1);
68127+
if (ret != 0)
68128+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb);
68129+
ret = wc_Sha256Final(&sha, hash);
68130+
if (ret != 0)
68131+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb);
68132+
68133+
/* cb delegates to software, expects NO_VALID_DEVID(failure) */
68134+
ctx->exampleVar = 1;
68135+
ret = wc_Sha256Update(&sha, in, (word32)sizeof(in) - 1);
68136+
if (ret != WC_NO_ERR_TRACE(NO_VALID_DEVID)) {
68137+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb);
68138+
} else {
68139+
ret = 0;
68140+
}
68141+
ret = wc_Sha256Final(&sha, hash);
68142+
if (ret != WC_NO_ERR_TRACE(NO_VALID_DEVID)) {
68143+
ERROR_OUT(WC_TEST_RET_ENC_EC(ret), exit_onlycb);
68144+
} else {
68145+
ret = 0;
68146+
}
68147+
68148+
exit_onlycb:
68149+
wc_Sha256Free(&sha);
68150+
#endif /* !NO_SHA256 */
68151+
(void)ctx;
68152+
return ret;
68153+
}
68154+
#endif /* WOLF_CRYPTO_CB_ONLY_SHA256 */
68155+
6810968156
/* Example crypto dev callback function that calls software version */
6811068157
static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
6811168158
{
@@ -68727,6 +68774,15 @@ static int myCryptoDevCb(int devIdArg, wc_CryptoInfo* info, void* ctx)
6872768774

6872868775
/* set devId to invalid, so software is used */
6872968776
info->hash.sha256->devId = INVALID_DEVID;
68777+
#if defined(WOLF_CRYPTO_CB_ONLY_SHA256)
68778+
#ifdef DEBUG_WOLFSSL
68779+
printf("CryptoDevCb: exampleVar %d\n", myCtx->exampleVar);
68780+
#endif
68781+
if (myCtx->exampleVar == 99) {
68782+
info->hash.sha256->devId = devIdArg;
68783+
return 0;
68784+
}
68785+
#endif
6873068786

6873168787
if (info->hash.in != NULL) {
6873268788
ret = wc_Sha256Update(
@@ -69857,6 +69913,12 @@ WOLFSSL_TEST_SUBROUTINE wc_test_ret_t cryptocb_test(void)
6985769913
ret = ecc_onlycb_test(&myCtx);
6985869914
PRIVATE_KEY_LOCK();
6985969915
#endif
69916+
#if defined(WOLF_CRYPTO_CB_ONLY_SHA256) && !defined(WOLFSSL_SWDEV)
69917+
PRIVATE_KEY_UNLOCK();
69918+
if (ret == 0)
69919+
ret = sha256_onlycb_test(&myCtx);
69920+
PRIVATE_KEY_LOCK();
69921+
#endif
6986069922
#ifdef WOLFSSL_HAVE_MLKEM
6986169923
if (ret == 0)
6986269924
ret = mlkem_test();

wolfssl/wolfcrypt/sha256.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,12 @@
102102
#define WOLFSSL_NO_HASH_RAW
103103
#endif
104104

105+
/* no raw hash access when software transform is stripped */
106+
#if defined(WOLF_CRYPTO_CB_ONLY_SHA256)
107+
#undef WOLFSSL_NO_HASH_RAW
108+
#define WOLFSSL_NO_HASH_RAW
109+
#endif
110+
105111
#define SHA256_NOINLINE WC_NO_INLINE
106112

107113
#if !defined(NO_OLD_SHA_NAMES)

0 commit comments

Comments
 (0)