diff --git a/.github/workflows/build-and-test-refactor.yml b/.github/workflows/build-and-test-refactor.yml index 6f8178d87..e1523de87 100644 --- a/.github/workflows/build-and-test-refactor.yml +++ b/.github/workflows/build-and-test-refactor.yml @@ -57,6 +57,10 @@ jobs: - name: Build and test refactor DMA ASAN MLDSA verify-only run: cd test-refactor/posix && make clean && make -j DMA=1 ASAN=1 MLDSA_VERIFY_ONLY=1 WOLFSSL_DIR=../../wolfssl && make run + # Build and test with Ed25519 enabled but Curve25519 disabled + - name: Build and test refactor DMA ASAN NOCURVE25519 + run: cd test-refactor/posix && make clean && make -j DMA=1 ASAN=1 NOCURVE25519=1 WOLFSSL_DIR=../../wolfssl && make run + # Build and test ASAN build, with wolfCrypt tests enabled. - name: Build and test refactor ASAN TESTWOLFCRYPT run: cd test-refactor/posix && make clean && make -j ASAN=1 TESTWOLFCRYPT=1 WOLFSSL_DIR=../../wolfssl && make run diff --git a/.github/workflows/build-and-test.yml b/.github/workflows/build-and-test.yml index 278f49dc8..85aa98ecd 100644 --- a/.github/workflows/build-and-test.yml +++ b/.github/workflows/build-and-test.yml @@ -57,6 +57,10 @@ jobs: - name: Build and test DMA ASAN MLDSA verify-only run: cd test && make clean && make -j DMA=1 ASAN=1 MLDSA_VERIFY_ONLY=1 WOLFSSL_DIR=../wolfssl && make run + # Build and test with Ed25519 enabled but Curve25519 disabled + - name: Build and test DMA ASAN NOCURVE25519 + run: cd test && make clean && make -j DMA=1 ASAN=1 NOCURVE25519=1 WOLFSSL_DIR=../wolfssl && make run + # Build and test ASAN build, with wolfCrypt tests enabled. - name: Build and test ASAN TESTWOLFCRYPT run: cd test && make clean && make -j ASAN=1 TESTWOLFCRYPT=1 WOLFSSL_DIR=../wolfssl && make run diff --git a/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index 8ad889399..8c0bb0118 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -467,6 +467,7 @@ int wh_Client_CryptoCbStd(int devId, wc_CryptoInfo* info, void* inCtx) *out_len = len; } } break; +#endif /* HAVE_CURVE25519 */ #ifdef HAVE_ED25519 case WC_PK_TYPE_ED25519_KEYGEN: { @@ -529,7 +530,6 @@ int wh_Client_CryptoCbStd(int devId, wc_CryptoInfo* info, void* inCtx) } } break; #endif /* HAVE_ED25519 */ -#endif /* HAVE_CURVE25519 */ #if defined(WOLFSSL_HAVE_MLKEM) case WC_PK_TYPE_PQC_KEM_KEYGEN: diff --git a/test-refactor/client-server/wh_test_crypto_ed25519.c b/test-refactor/client-server/wh_test_crypto_ed25519.c index a3eb56921..eed5299bd 100644 --- a/test-refactor/client-server/wh_test_crypto_ed25519.c +++ b/test-refactor/client-server/wh_test_crypto_ed25519.c @@ -24,6 +24,10 @@ * _whTest_CryptoEd25519Inline - pure wolfCrypt (sign+verify locally, * plus negative case for tampered sig) * _whTest_CryptoEd25519ServerKey - server-cached sign and verify keyIds + * _whTest_CryptoEd25519CryptoCbHsmKey + * - server-only keyIds driven through the + * wolfCrypt API, so the cryptocb must + * dispatch the operation * _whTest_CryptoEd25519Dma - same, via the DMA messaging path */ @@ -361,6 +365,99 @@ static int _whTest_CryptoEd25519ServerKey(whClientContext* ctx) return ret; } +/* Signs and verifies through the wolfCrypt API on a key whose private material + * lives only in the server, so the crypto callback must handle the operation. + * A software fallback has no private scalar and returns BAD_FUNC_ARG. */ +static int _whTest_CryptoEd25519CryptoCbHsmKey(whClientContext* ctx) +{ + int devId = WH_CLIENT_DEVID(ctx); + int ret = 0; + WC_RNG rng[1]; + ed25519_key key[1] = {0}; + ed25519_key pubKey[1] = {0}; + whKeyId signKeyId = WH_KEYID_ERASED; + whKeyId verifyKeyId = WH_KEYID_ERASED; + byte msg[] = "Ed25519 cryptocb dispatch message"; + byte sig[ED25519_SIG_SIZE]; + word32 sigSz = sizeof(sig); + int verified = 0; + uint8_t label[] = "Ed25519 CryptoCb Key"; + + /* Pin the standard (non-DMA) callback. This test exists to prove the + * WC_PK_TYPE_ED25519_* cases in wh_Client_CryptoCbStd are compiled in, so + * it must not depend on the ambient DMA mode left by an earlier suite. */ + (void)wh_Client_SetDmaMode(ctx, 0); + + ret = wc_InitRng_ex(rng, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to wc_InitRng_ex %d\n", ret); + return ret; + } + + ret = wc_ed25519_init_ex(key, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to initialize Ed25519 key: %d\n", ret); + (void)wc_FreeRng(rng); + return ret; + } + + ret = wc_ed25519_init_ex(pubKey, NULL, devId); + if (ret != 0) { + WH_ERROR_PRINT("Failed to initialize Ed25519 public key: %d\n", ret); + wc_ed25519_free(key); + (void)wc_FreeRng(rng); + return ret; + } + + ret = wc_ed25519_make_key(rng, ED25519_KEY_SIZE, key); + if (ret != 0) { + WH_ERROR_PRINT("Failed to generate Ed25519 key: %d\n", ret); + } + else { + ret = whTest_Ed25519ImportToServer(ctx, devId, key, pubKey, label, + sizeof(label), &signKeyId, + &verifyKeyId); + } + + if (ret == 0) { + sigSz = sizeof(sig); + ret = wc_ed25519_sign_msg(msg, (word32)sizeof(msg), sig, &sigSz, key); + if (ret != 0) { + WH_ERROR_PRINT("wc_ed25519_sign_msg on server key failed: %d\n", + ret); + } + } + + if (ret == 0) { + ret = wc_ed25519_verify_msg(sig, sigSz, msg, (word32)sizeof(msg), + &verified, pubKey); + if (ret != 0) { + WH_ERROR_PRINT("wc_ed25519_verify_msg on server key failed: %d\n", + ret); + } + else if (verified != 1) { + WH_ERROR_PRINT("Server key Ed25519 signature did not verify\n"); + ret = -1; + } + } + + if (!WH_KEYID_ISERASED(signKeyId)) { + (void)wh_Client_KeyEvict(ctx, signKeyId); + } + if (!WH_KEYID_ISERASED(verifyKeyId)) { + (void)wh_Client_KeyEvict(ctx, verifyKeyId); + } + + if (ret == 0) { + WH_TEST_PRINT("Ed25519 CRYPTOCB DEVID=0x%X SUCCESS\n", devId); + } + + wc_ed25519_free(pubKey); + wc_ed25519_free(key); + (void)wc_FreeRng(rng); + return ret; +} + #ifdef WOLFHSM_CFG_DMA static int _whTest_CryptoEd25519Dma(whClientContext* ctx) { @@ -731,6 +828,7 @@ int whTest_Crypto_Ed25519(whClientContext* ctx) { WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519Inline(ctx)); WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519ServerKey(ctx)); + WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519CryptoCbHsmKey(ctx)); #ifdef WOLFHSM_CFG_DMA WH_TEST_RETURN_ON_FAIL(_whTest_CryptoEd25519Dma(ctx)); #endif diff --git a/test-refactor/posix/Makefile b/test-refactor/posix/Makefile index 61027aba5..8b6bad8e4 100644 --- a/test-refactor/posix/Makefile +++ b/test-refactor/posix/Makefile @@ -100,6 +100,11 @@ ifeq ($(DMA),1) DEF += -DWOLFHSM_CFG_DMA endif +# Build without Curve25519, leaving Ed25519 enabled +ifeq ($(NOCURVE25519),1) + DEF += -DWOLFHSM_CFG_TEST_NO_CURVE25519 +endif + # Build LMS/XMSS in verify-only mode (omits private-key, sign, and keygen # paths). May be combined to exercise the mixed (one verify-only) case. ifeq ($(LMS_VERIFY_ONLY),1) diff --git a/test/Makefile b/test/Makefile index c76e877a7..c37c2193c 100644 --- a/test/Makefile +++ b/test/Makefile @@ -130,6 +130,11 @@ ifeq ($(NOCRYPTO),1) DEF += -DWOLFHSM_CFG_NO_CRYPTO endif +# Build without Curve25519, leaving Ed25519 enabled +ifeq ($(NOCURVE25519),1) + DEF += -DWOLFHSM_CFG_TEST_NO_CURVE25519 +endif + # Enable scan-build ifeq ($(SCAN),1) SCAN_LOG = scan_test.log diff --git a/test/config/user_settings.h b/test/config/user_settings.h index f237ccaa4..448963250 100644 --- a/test/config/user_settings.h +++ b/test/config/user_settings.h @@ -107,7 +107,11 @@ #define ECC_SHAMIR /** Curve25519 Options */ +/* Curve25519 and Ed25519 are independent options. Allow a build that omits + * Curve25519 so the Ed25519-only configuration stays exercised. */ +#ifndef WOLFHSM_CFG_TEST_NO_CURVE25519 #define HAVE_CURVE25519 +#endif /** DH and DHE Options */ #define NO_DH