diff --git a/.github/workflows/build-and-test-refactor.yml b/.github/workflows/build-and-test-refactor.yml index 15253f618..004cc2f2e 100644 --- a/.github/workflows/build-and-test-refactor.yml +++ b/.github/workflows/build-and-test-refactor.yml @@ -53,6 +53,10 @@ jobs: - name: Build and test refactor DMA ASAN LMS verify-only XMSS full run: cd test-refactor/posix && make clean && make -j DMA=1 ASAN=1 LMS_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/src/wh_client_cryptocb.c b/src/wh_client_cryptocb.c index 71158d3ba..a4490f40d 100644 --- a/src/wh_client_cryptocb.c +++ b/src/wh_client_cryptocb.c @@ -426,6 +426,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: { @@ -488,7 +489,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..692fbcdbd 100644 --- a/test-refactor/client-server/wh_test_crypto_ed25519.c +++ b/test-refactor/client-server/wh_test_crypto_ed25519.c @@ -361,6 +361,94 @@ 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"; + + 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 +819,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 e26ec57f5..f99ad96f3 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 faf251850..00152baae 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