From 66dd1ff76b753796704318833f3eff0c459ed74a Mon Sep 17 00:00:00 2001 From: Arpan Sharma Date: Mon, 26 Oct 2026 21:10:43 -0500 Subject: [PATCH] SLH-DSA: fix configure parameter set options and reduced-build tests An --enable-slhdsa string that names no parameter set, such as verify-only, small or no-s, passed configure and then failed to compile. Start such a string from the six SHAKE sets, as 'yes' does. no-s, no-f, no-sha2-s and no-sha2-f added group NO macros that wc_slhdsa.h drops when a set in the group is defined, so they were ignored. Take the group out of the selected sets in configure instead, leave the SHA2 family out when no SHA2 set is left, and stop with an error when no set is left (checked after the FIPS section). test_wc_slhdsa_param_disabled now probes TEST_SLHDSA_DEFAULT_PARAM, so it passes in SHA2-only builds without SHA2-128s. test_wc_SignCRL_slhdsa runs each case only when its 128s set is built and is skipped when neither is (its helper's guard follows), so it no longer fails with NOT_COMPILED_IN when SHAKE-128s, or SHA2-128s in a SHA2 build, is left out. --- configure.ac | 76 ++++++++++++++++++++++++++++++++++++++--- tests/api.c | 16 ++++++--- tests/api/test_slhdsa.c | 16 ++------- 3 files changed, 86 insertions(+), 22 deletions(-) diff --git a/configure.ac b/configure.ac index 8a0d13936ec..ea784fd6883 100644 --- a/configure.ac +++ b/configure.ac @@ -2761,10 +2761,10 @@ do SLHDSA_PARAM_256F=yes ;; no-s) - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SLHDSA_PARAM_NO_SMALL" + SLHDSA_NO_SMALL=yes ;; no-f) - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SLHDSA_PARAM_NO_FAST" + SLHDSA_NO_FAST=yes ;; sha2) SLHDSA_SHA2=yes @@ -2800,16 +2800,74 @@ do SLHDSA_PARAM_SHA2_256F=yes ;; no-sha2-s) - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SLHDSA_PARAM_NO_SHA2_SMALL" + SLHDSA_NO_SHA2_SMALL=yes ;; no-sha2-f) - AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_SLHDSA_PARAM_NO_SHA2_FAST" + SLHDSA_NO_SHA2_FAST=yes ;; *) AC_MSG_ERROR([Invalid choice for SLH-DSA []: $ENABLED_SLHDSA.]) break;; esac done + +# If SLH-DSA is enabled but no parameter set was named, for example +# --enable-slhdsa=verify-only or =small, enable the SHAKE parameter sets as +# 'yes' does. The SHA2 parameter sets stay opt-in. +if test "$ENABLED_SLHDSA" != "no" && test "$SLHDSA_SHA2" != "yes" && \ + test "$SLHDSA_PARAM_128S" != "yes" && test "$SLHDSA_PARAM_128F" != "yes" && \ + test "$SLHDSA_PARAM_192S" != "yes" && test "$SLHDSA_PARAM_192F" != "yes" && \ + test "$SLHDSA_PARAM_256S" != "yes" && test "$SLHDSA_PARAM_256F" != "yes" +then + SLHDSA_PARAM_128S=yes + SLHDSA_PARAM_128F=yes + SLHDSA_PARAM_192S=yes + SLHDSA_PARAM_192F=yes + SLHDSA_PARAM_256S=yes + SLHDSA_PARAM_256F=yes +fi + +# no-s, no-f, no-sha2-s and no-sha2-f take that group out of the sets +# selected above, including sets named explicitly. A positive set macro +# overrides a group 'NO' macro in wc_slhdsa.h, so the group is removed here +# rather than with a CFLAG. +if test "$SLHDSA_NO_SMALL" = "yes" +then + SLHDSA_PARAM_128S=no + SLHDSA_PARAM_192S=no + SLHDSA_PARAM_256S=no +fi +if test "$SLHDSA_NO_FAST" = "yes" +then + SLHDSA_PARAM_128F=no + SLHDSA_PARAM_192F=no + SLHDSA_PARAM_256F=no +fi +if test "$SLHDSA_NO_SHA2_SMALL" = "yes" +then + SLHDSA_PARAM_SHA2_128S=no + SLHDSA_PARAM_SHA2_192S=no + SLHDSA_PARAM_SHA2_256S=no +fi +if test "$SLHDSA_NO_SHA2_FAST" = "yes" +then + SLHDSA_PARAM_SHA2_128F=no + SLHDSA_PARAM_SHA2_192F=no + SLHDSA_PARAM_SHA2_256F=no +fi + +# If that leaves no SHA2 parameter set, leave the SHA2 family out too, with +# its SHA-256, SHA-512 and HMAC requirements. +if test "$SLHDSA_PARAM_SHA2_128S" != "yes" && \ + test "$SLHDSA_PARAM_SHA2_128F" != "yes" && \ + test "$SLHDSA_PARAM_SHA2_192S" != "yes" && \ + test "$SLHDSA_PARAM_SHA2_192F" != "yes" && \ + test "$SLHDSA_PARAM_SHA2_256S" != "yes" && \ + test "$SLHDSA_PARAM_SHA2_256F" != "yes" +then + SLHDSA_SHA2=no +fi + # SINGLE THREADED AC_ARG_ENABLE([singlethreaded], [AS_HELP_STRING([--enable-singlethreaded],[Enable wolfSSL single threaded (default: disabled)])], @@ -9248,6 +9306,16 @@ then AM_CFLAGS="$AM_CFLAGS -DWOLFSSL_WC_SLHDSA" + # Checked here, after the FIPS section, which may still select sets. + if test "$SLHDSA_SHA2" != "yes" && \ + test "$SLHDSA_PARAM_128S" != "yes" && test "$SLHDSA_PARAM_128F" != "yes" && \ + test "$SLHDSA_PARAM_192S" != "yes" && test "$SLHDSA_PARAM_192F" != "yes" && \ + test "$SLHDSA_PARAM_256S" != "yes" && test "$SLHDSA_PARAM_256F" != "yes" + then + AC_MSG_ERROR([SLH-DSA: $ENABLED_SLHDSA leaves no parameter sets. Remove a \ +no-s/no-f/no-sha2-s/no-sha2-f option or name a set it does not exclude.]) + fi + # SLH-DSA is an X.509 certificate signature algorithm, so keep the # certificate/ASN code enabled (mirrors ML-DSA) - otherwise a build with # RSA, ECC and DH disabled turns ASN off and cannot authenticate a peer. diff --git a/tests/api.c b/tests/api.c index a2507e33259..64b9341fc3f 100644 --- a/tests/api.c +++ b/tests/api.c @@ -31036,7 +31036,10 @@ static int test_wc_MakeCRL_max_crlnum(void) !defined(NO_ASN) && \ ((defined(WOLFSSL_HAVE_MLDSA) && defined(WOLFSSL_PEM_TO_DER) && \ !defined(WOLFSSL_MLDSA_NO_SIGN) && !defined(WOLFSSL_MLDSA_NO_ASN1)) || \ - (defined(WOLFSSL_HAVE_SLHDSA) && !defined(WOLFSSL_SLHDSA_VERIFY_ONLY)) || \ + (defined(WOLFSSL_HAVE_SLHDSA) && !defined(WOLFSSL_SLHDSA_VERIFY_ONLY) && \ + (defined(WOLFSSL_SLHDSA_PARAM_128S) || \ + (defined(WOLFSSL_SLHDSA_SHA2) && \ + defined(WOLFSSL_SLHDSA_PARAM_SHA2_128S)))) || \ (defined(HAVE_ED25519) && defined(HAVE_ED25519_SIGN)) || \ (defined(HAVE_ED448) && defined(HAVE_ED448_SIGN))) /* Build a CRL, sign it with the given CA key through wc_MakeCRL_ex + @@ -31265,7 +31268,11 @@ static int test_wc_SignCRL_slhdsa(void) EXPECT_DECLS; #if defined(WOLFSSL_CERT_GEN) && defined(HAVE_CRL) && !defined(NO_FILESYSTEM) && \ !defined(NO_ASN) && defined(WOLFSSL_HAVE_SLHDSA) && \ - !defined(WOLFSSL_SLHDSA_VERIFY_ONLY) + !defined(WOLFSSL_SLHDSA_VERIFY_ONLY) && \ + (defined(WOLFSSL_SLHDSA_PARAM_128S) || \ + (defined(WOLFSSL_SLHDSA_SHA2) && defined(WOLFSSL_SLHDSA_PARAM_SHA2_128S))) + /* Only the 128s parameter sets have root certificates; run each case only + * when its parameter set is compiled in. */ static const struct { const char* certDer; const char* keyDer; @@ -31273,11 +31280,12 @@ static int test_wc_SignCRL_slhdsa(void) int sigType; int param; } cases[] = { - /* SHAKE variants are always built with --enable-slhdsa. */ +#ifdef WOLFSSL_SLHDSA_PARAM_128S { "./certs/slhdsa/root-slhdsa-shake-128s.der", "./certs/slhdsa/root-slhdsa-shake-128s-priv.der", SLH_DSA_SHAKE_128S_TYPE, CTC_SLH_DSA_SHAKE_128S, SLHDSA_SHAKE128S }, -#ifdef WOLFSSL_SLHDSA_SHA2 +#endif +#if defined(WOLFSSL_SLHDSA_SHA2) && defined(WOLFSSL_SLHDSA_PARAM_SHA2_128S) { "./certs/slhdsa/root-slhdsa-sha2-128s.der", "./certs/slhdsa/root-slhdsa-sha2-128s-priv.der", SLH_DSA_SHA2_128S_TYPE, CTC_SLH_DSA_SHA2_128S, SLHDSA_SHA2_128S }, diff --git a/tests/api/test_slhdsa.c b/tests/api/test_slhdsa.c index e642951e219..ed2fe3b7ffe 100644 --- a/tests/api/test_slhdsa.c +++ b/tests/api/test_slhdsa.c @@ -2966,20 +2966,8 @@ int test_wc_slhdsa_param_disabled(void) * documented purpose. The probe also validates the contract from the * other side -- Init must succeed for an enabled param. */ haveEnabled = 0; -#if defined(WOLFSSL_SLHDSA_PARAM_128S) - enabledProbe = SLHDSA_SHAKE128S; haveEnabled = 1; -#elif defined(WOLFSSL_SLHDSA_PARAM_128F) - enabledProbe = SLHDSA_SHAKE128F; haveEnabled = 1; -#elif defined(WOLFSSL_SLHDSA_PARAM_192S) - enabledProbe = SLHDSA_SHAKE192S; haveEnabled = 1; -#elif defined(WOLFSSL_SLHDSA_PARAM_192F) - enabledProbe = SLHDSA_SHAKE192F; haveEnabled = 1; -#elif defined(WOLFSSL_SLHDSA_PARAM_256S) - enabledProbe = SLHDSA_SHAKE256S; haveEnabled = 1; -#elif defined(WOLFSSL_SLHDSA_PARAM_256F) - enabledProbe = SLHDSA_SHAKE256F; haveEnabled = 1; -#elif defined(WOLFSSL_SLHDSA_SHA2) && defined(WOLFSSL_SLHDSA_PARAM_SHA2_128S) - enabledProbe = SLHDSA_SHA2_128S; haveEnabled = 1; +#ifdef TEST_SLHDSA_DEFAULT_PARAM + enabledProbe = TEST_SLHDSA_DEFAULT_PARAM; haveEnabled = 1; #endif ExpectIntEQ(haveEnabled, 1); if (haveEnabled) {