From a9a55f14cbbb7e5b8c78f4399beae260b80cf735 Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Tue, 11 Aug 2026 13:54:18 -0600 Subject: [PATCH 1/3] Allow for builds without ED25519 & MD5 --- src/benchmark/clu_bench_setup.c | 8 ++++++++ src/hash/clu_hash_setup.c | 5 ++--- src/sign-verify/clu_dgst_setup.c | 5 +++++ src/sign-verify/clu_sign.c | 6 ++++++ src/sign-verify/clu_verify.c | 11 +++++++++++ src/tools/clu_funcs.c | 5 +++++ tests/bench/bench-test.py | 4 +++- tests/genkey_sign_ver/genkey-sign-ver-test.py | 7 ++++++- tests/hash/hash-test.py | 5 ++++- tests/wolfclu_test.py | 17 +++++++++++++++++ 10 files changed, 67 insertions(+), 6 deletions(-) diff --git a/src/benchmark/clu_bench_setup.c b/src/benchmark/clu_bench_setup.c index 9efc7219..9d669031 100644 --- a/src/benchmark/clu_bench_setup.c +++ b/src/benchmark/clu_bench_setup.c @@ -105,6 +105,8 @@ static const struct option bench_options[] = { #endif #ifndef NO_MD5 {"md5", no_argument, 0, WOLFCLU_BENCH_MD5 }, +#else + {"md5", no_argument, 0, WOLFCLU_MD5 }, #endif #ifndef NO_SHA {"sha", no_argument, 0, WOLFCLU_BENCH_SHA }, @@ -176,6 +178,12 @@ int wolfCLU_benchSetup(int argc, char** argv) } break; +#ifdef NO_MD5 + case WOLFCLU_MD5: + wolfCLU_LogError("MD5 not compiled in"); + return NOT_COMPILED_IN; +#endif + case ARG_FOUND_TWICE: wolfCLU_LogError("Found duplicate argument"); return WOLFCLU_FATAL_ERROR; diff --git a/src/hash/clu_hash_setup.c b/src/hash/clu_hash_setup.c index bc10564f..bd3ad04a 100644 --- a/src/hash/clu_hash_setup.c +++ b/src/hash/clu_hash_setup.c @@ -130,9 +130,8 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_MD5: #ifdef NO_MD5 - wolfCLU_LogError("MD5 not avalable in your current wolfSSL " - "build"); - return WOLFCLU_FATAL_ERROR; + wolfCLU_LogError("MD5 not compiled in"); + return NOT_COMPILED_IN; #else if (alg != NULL) { wolfCLU_LogError("alg already set"); diff --git a/src/sign-verify/clu_dgst_setup.c b/src/sign-verify/clu_dgst_setup.c index 9ed448bf..b36f8d3d 100644 --- a/src/sign-verify/clu_dgst_setup.c +++ b/src/sign-verify/clu_dgst_setup.c @@ -620,7 +620,12 @@ int wolfCLU_dgst_setup(int argc, char** argv) switch (option) { case WOLFCLU_MD5: + #ifdef NO_MD5 + wolfCLU_LogError("MD5 not compiled in"); + ret = NOT_COMPILED_IN; + #else hashType = WC_HASH_TYPE_MD5; + #endif break; case WOLFCLU_CERT_SHA: diff --git a/src/sign-verify/clu_sign.c b/src/sign-verify/clu_sign.c index 4be2dbcf..4af6fec9 100644 --- a/src/sign-verify/clu_sign.c +++ b/src/sign-verify/clu_sign.c @@ -714,6 +714,12 @@ int wolfCLU_sign_data_ed25519 (byte* data, char* out, word32 fSz, char* privKey, /* expected ret == WOLFCLU_SUCCESS */ return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else + (void)data; + (void)fSz; + (void)out; + (void)privKey; + (void)inForm; + return NOT_COMPILED_IN; #endif } diff --git a/src/sign-verify/clu_verify.c b/src/sign-verify/clu_verify.c index b3d56d34..c5660764 100644 --- a/src/sign-verify/clu_verify.c +++ b/src/sign-verify/clu_verify.c @@ -179,6 +179,9 @@ int wolfCLU_verify_signature(char* sig, char* hashFile, char* out, XFCLOSE(h); ret = wolfCLU_verify_signature_ed25519(data, (int)fSz, hash, (int)hSz, keyPath, pubIn, inForm); + #else + wolfCLU_LogError("ED25519 not compiled in"); + ret = NOT_COMPILED_IN; #endif break; @@ -830,6 +833,14 @@ int wolfCLU_verify_signature_ed25519(byte* sig, int sigSz, /* expected ret == WOLFCLU_SUCCESS */ return (ret >= 0) ? WOLFCLU_SUCCESS : ret; #else + (void)sig; + (void)sigSz; + (void)hash; + (void)hashSz; + (void)pubIn; + (void)keyPath; + (void)inForm; + return NOT_COMPILED_IN; #endif /* HAVE_ED25519 */ } diff --git a/src/tools/clu_funcs.c b/src/tools/clu_funcs.c index 364bef3f..9af2d243 100644 --- a/src/tools/clu_funcs.c +++ b/src/tools/clu_funcs.c @@ -1392,8 +1392,13 @@ int wolfCLU_hmacHash(WOLFSSL_HMAC_CTX *ctx, void* key, word32 len, * Cast to int so unrelated hash types don't trip -Wswitch-enum. */ switch ((int)alg) { case WC_HASH_TYPE_MD5: +#ifndef NO_MD5 md = wolfSSL_EVP_md5(); break; +#else + wolfCLU_LogError("MD5 not compiled in"); + ret = NOT_COMPILED_IN; +#endif case WC_HASH_TYPE_SHA: md = wolfSSL_EVP_sha1(); break; diff --git a/tests/bench/bench-test.py b/tests/bench/bench-test.py index 1a6a3c77..ac357f50 100644 --- a/tests/bench/bench-test.py +++ b/tests/bench/bench-test.py @@ -6,7 +6,7 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import run_wolfssl, test_main +from wolfclu_test import not_compiled_in, run_wolfssl, test_main class BenchTest(unittest.TestCase): @@ -21,6 +21,8 @@ def test_bench_sha(self): def test_bench_md5(self): result = run_wolfssl("-bench", "md5", "-time", "1") + if not_compiled_in(result): + self.skipTest("MD5 not compiled into wolfSSL") self.assertEqual(result.returncode, 0, result.stderr) def test_bench_missing_time_value(self): diff --git a/tests/genkey_sign_ver/genkey-sign-ver-test.py b/tests/genkey_sign_ver/genkey-sign-ver-test.py index 615fe385..14a777df 100644 --- a/tests/genkey_sign_ver/genkey-sign-ver-test.py +++ b/tests/genkey_sign_ver/genkey-sign-ver-test.py @@ -6,7 +6,8 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import WOLFSSL_BIN, CERTS_DIR, run_wolfssl, test_main +from wolfclu_test import (WOLFSSL_BIN, CERTS_DIR, not_compiled_in, + run_wolfssl, test_main) # Files that tests may create; cleaned up by tearDownClass _TEMP_FILES = [] @@ -95,6 +96,10 @@ def _genkey(self, algo, keybase, fmt, extra_args=None, pub = keybase + ".pub" self._track(priv, pub) r = run_wolfssl(*args) + # Builds that omit an optional key type (e.g. wolfSSL without + # --enable-ed25519) report NOT_COMPILED_IN; skip rather than fail. + if not_compiled_in(r): + self.skipTest(f"{algo} not compiled into wolfSSL") self.assertEqual(r.returncode, 0, f"genkey {algo} failed: {r.stderr}") return priv, pub diff --git a/tests/hash/hash-test.py b/tests/hash/hash-test.py index 5e62759e..42c6e5dc 100644 --- a/tests/hash/hash-test.py +++ b/tests/hash/hash-test.py @@ -8,7 +8,8 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import (CERTS_DIR, run_wolfssl, test_main, truncate_sparse) +from wolfclu_test import (CERTS_DIR, not_compiled_in, run_wolfssl, test_main, + truncate_sparse) HASH_DIR = os.path.dirname(os.path.abspath(__file__)) CERT_FILE = os.path.join(CERTS_DIR, "ca-cert.pem") @@ -90,6 +91,8 @@ def setUpClass(cls): def test_md5(self): r = run_wolfssl("md5", CERT_FILE) + if not_compiled_in(r): + self.skipTest("MD5 not compiled into wolfSSL") self.assertEqual(r.returncode, 0, r.stderr) self.assertEqual(r.stdout.strip(), _read_expected("md5-expect.hex")) diff --git a/tests/wolfclu_test.py b/tests/wolfclu_test.py index d49e4ada..6909c2e3 100644 --- a/tests/wolfclu_test.py +++ b/tests/wolfclu_test.py @@ -94,6 +94,23 @@ def is_fips(): return "FIPS" in (r.stdout + r.stderr) +# wolfSSL's NOT_COMPILED_IN. wolfCLU returns it whenever an algorithm is +# named explicitly but is absent from the linked wolfSSL build, and main() +# reports it as "Error returned: -174.". +NOT_COMPILED_IN = -174 + + +def not_compiled_in(result): + """True when wolfCLU rejected the command because the requested algorithm + is not compiled into the linked wolfSSL build. + + Lets tests for optional algorithms skip rather than fail on builds that + omit them (e.g. wolfSSL built with NO_MD5 or without --enable-ed25519). + """ + return "Error returned: {}.".format(NOT_COMPILED_IN) in ( + result.stdout + result.stderr) + + def make_sparse(fileobj): """Mark an open file as sparse on Windows before it is extended. From 7acff6c6cc2db29ea64ab757b1ec75ac16434ace Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Thu, 13 Aug 2026 15:24:17 -0600 Subject: [PATCH 2/3] Addressing skoll feedback and adding requested testing --- src/hash/clu_hash_setup.c | 37 ++++++++++++++++---------------- src/sign-verify/clu_dgst_setup.c | 2 ++ src/sign-verify/clu_sign.c | 1 + src/sign-verify/clu_verify.c | 2 +- src/tools/clu_funcs.c | 2 +- tests/dgst/dgst-test.py | 19 ++++++++++++---- tests/hash/hash-test.py | 9 +++++++- 7 files changed, 47 insertions(+), 25 deletions(-) diff --git a/src/hash/clu_hash_setup.c b/src/hash/clu_hash_setup.c index bd3ad04a..67d62dc2 100644 --- a/src/hash/clu_hash_setup.c +++ b/src/hash/clu_hash_setup.c @@ -130,7 +130,8 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_MD5: #ifdef NO_MD5 - wolfCLU_LogError("MD5 not compiled in"); + wolfCLU_LogError("MD5 not available in your current wolfSSL " + "build"); return NOT_COMPILED_IN; #else if (alg != NULL) { @@ -145,9 +146,9 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_SHA: #ifdef NO_SHA - wolfCLU_LogError("SHA not avalible in your current wolfSSL " + wolfCLU_LogError("SHA not available in your current wolfSSL " "build"); - return WOLFCLU_FATAL_ERROR; + return NOT_COMPILED_IN; #else if (alg != NULL) { wolfCLU_LogError("alg already set"); @@ -161,9 +162,9 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_SHA256: #ifdef NO_SHA256 - wolfCLU_LogError("SHA-256 not avalible in your current wolfSSL " - "build"); - return WOLFCLU_FATAL_ERROR; + wolfCLU_LogError("SHA-256 not available in your current wolfSSL" + " build"); + return NOT_COMPILED_IN; #else if (alg != NULL) { wolfCLU_LogError("alg already set"); @@ -177,9 +178,9 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_SHA384: #ifndef WOLFSSL_SHA384 - wolfCLU_LogError("SHA-384 not avalible in your current wolfSSL " - "build"); - return WOLFCLU_FATAL_ERROR; + wolfCLU_LogError("SHA-384 not available in your current wolfSSL" + " build"); + return NOT_COMPILED_IN; #else if (alg != NULL) { wolfCLU_LogError("alg already set"); @@ -194,9 +195,9 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_SHA512: #ifndef WOLFSSL_SHA512 - wolfCLU_LogError("SHA-512 not avalible in your current wolfSSL " - "build"); - return WOLFCLU_FATAL_ERROR; + wolfCLU_LogError("SHA-512 not available in your current wolfSSL" + " build"); + return NOT_COMPILED_IN; #else if (alg != NULL) { wolfCLU_LogError("alg already set"); @@ -211,9 +212,9 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_BLAKE: #ifndef HAVE_BLAKE2B - wolfCLU_LogError("BLAKE2 not avalible in your current wolfSSL " + wolfCLU_LogError("BLAKE2 not available in your current wolfSSL " "build"); - return WOLFCLU_FATAL_ERROR; + return NOT_COMPILED_IN; #else if (alg != NULL) { wolfCLU_LogError("alg already set"); @@ -235,9 +236,9 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_BASE64ENC: #if defined(NO_CODING) || !defined(WOLFSSL_BASE64_ENCODE) - wolfCLU_LogError("BASE64 encoding not avalible in your " + wolfCLU_LogError("BASE64 encoding not available in your " "current wolfSSL build"); - return WOLFCLU_FATAL_ERROR; + return NOT_COMPILED_IN; #else if (alg != NULL) { wolfCLU_LogError("alg already set"); @@ -251,9 +252,9 @@ int wolfCLU_hashSetup(int argc, char** argv) case WOLFCLU_BASE64DEC: #if defined(NO_CODING) - wolfCLU_LogError("BASE64 encoding not avalible in your " + wolfCLU_LogError("BASE64 encoding not available in your " "current wolfSSL build"); - return WOLFCLU_FATAL_ERROR; + return NOT_COMPILED_IN; #else if (alg != NULL) { wolfCLU_LogError("alg already set"); diff --git a/src/sign-verify/clu_dgst_setup.c b/src/sign-verify/clu_dgst_setup.c index b36f8d3d..ceec1d51 100644 --- a/src/sign-verify/clu_dgst_setup.c +++ b/src/sign-verify/clu_dgst_setup.c @@ -64,7 +64,9 @@ static void wolfCLU_dgstHelp(void) WOLFCLU_LOG(WOLFCLU_L0, "dgst: (Data can be passed in via stdin or via " "a file as the last argument)"); WOLFCLU_LOG(WOLFCLU_L0, "Hash algos supported:"); +#ifndef NO_MD5 WOLFCLU_LOG(WOLFCLU_L0, "\t-md5"); +#endif WOLFCLU_LOG(WOLFCLU_L0, "\t-sha"); WOLFCLU_LOG(WOLFCLU_L0, "\t-sha224"); WOLFCLU_LOG(WOLFCLU_L0, "\t-sha256"); diff --git a/src/sign-verify/clu_sign.c b/src/sign-verify/clu_sign.c index 4af6fec9..63217f9f 100644 --- a/src/sign-verify/clu_sign.c +++ b/src/sign-verify/clu_sign.c @@ -720,6 +720,7 @@ int wolfCLU_sign_data_ed25519 (byte* data, char* out, word32 fSz, char* privKey, (void)privKey; (void)inForm; + wolfCLU_LogError("ED25519 not compiled in"); return NOT_COMPILED_IN; #endif } diff --git a/src/sign-verify/clu_verify.c b/src/sign-verify/clu_verify.c index c5660764..385671b5 100644 --- a/src/sign-verify/clu_verify.c +++ b/src/sign-verify/clu_verify.c @@ -837,8 +837,8 @@ int wolfCLU_verify_signature_ed25519(byte* sig, int sigSz, (void)sigSz; (void)hash; (void)hashSz; - (void)pubIn; (void)keyPath; + (void)pubIn; (void)inForm; return NOT_COMPILED_IN; diff --git a/src/tools/clu_funcs.c b/src/tools/clu_funcs.c index 9af2d243..71c74c8a 100644 --- a/src/tools/clu_funcs.c +++ b/src/tools/clu_funcs.c @@ -1394,11 +1394,11 @@ int wolfCLU_hmacHash(WOLFSSL_HMAC_CTX *ctx, void* key, word32 len, case WC_HASH_TYPE_MD5: #ifndef NO_MD5 md = wolfSSL_EVP_md5(); - break; #else wolfCLU_LogError("MD5 not compiled in"); ret = NOT_COMPILED_IN; #endif + break; case WC_HASH_TYPE_SHA: md = wolfSSL_EVP_sha1(); break; diff --git a/tests/dgst/dgst-test.py b/tests/dgst/dgst-test.py index 456224b5..b412c6fb 100644 --- a/tests/dgst/dgst-test.py +++ b/tests/dgst/dgst-test.py @@ -9,8 +9,8 @@ import unittest sys.path.insert(0, os.path.join(os.path.dirname(__file__), "..")) -from wolfclu_test import (CERTS_DIR, is_fips, run_wolfssl, test_main, - truncate_sparse) +from wolfclu_test import (CERTS_DIR, is_fips, not_compiled_in, run_wolfssl, + test_main, truncate_sparse) DGST_DIR = os.path.dirname(os.path.abspath(__file__)) @@ -41,6 +41,8 @@ def test_verify_md5_rsa(self): os.path.join(CERTS_DIR, "server-keyPub.pem"), "-signature", os.path.join(DGST_DIR, "md5-rsa.sig"), os.path.join(CERTS_DIR, "server-key.der")) + if not_compiled_in(r): + self.skipTest("MD5 not compiled into wolfSSL") self.assertEqual(r.returncode, 0, r.stderr) def test_verify_sha256_ecc(self): @@ -72,7 +74,9 @@ def test_fail_private_key_as_verify(self): self.assertNotEqual(r.returncode, 0) def test_fail_wrong_digest(self): - r = run_wolfssl("dgst", "-md5", "-verify", + """Verifying a sha256 signature under a different digest must fail. + """ + r = run_wolfssl("dgst", "-sha384", "-verify", os.path.join(CERTS_DIR, "server-keyPub.pem"), "-signature", os.path.join(DGST_DIR, "sha256-rsa.sig"), os.path.join(CERTS_DIR, "server-key.der")) @@ -88,7 +92,8 @@ def test_sign_verify_all_hash_algs(self): """Sign/verify round-trip for each supported hash algorithm. Covers the per-algorithm digest-selection branches in - clu_dgst_setup.c. -md5 is skipped under FIPS. + clu_dgst_setup.c. -md5 is skipped under FIPS, and any algorithm + the linked wolfSSL build omits is skipped. """ algs = ["sha", "sha224", "sha256", "sha384", "sha512"] if not is_fips(): @@ -103,6 +108,9 @@ def test_sign_verify_all_hash_algs(self): r = run_wolfssl("dgst", "-" + alg, "-sign", os.path.join(CERTS_DIR, "server-key.pem"), "-out", sig_file, input_file) + if not_compiled_in(r): + self.skipTest( + "{} not compiled into wolfSSL".format(alg)) self.assertEqual(r.returncode, 0, r.stderr) r = run_wolfssl("dgst", "-" + alg, "-verify", @@ -471,6 +479,9 @@ def test_hmac_vectors(self): with self.subTest(alg=alg): r = run_wolfssl("dgst", "-" + alg, "-hmac", "-mackey", self.KEY, self.data_file) + if not_compiled_in(r): + self.skipTest( + "{} not compiled into wolfSSL".format(alg)) self.assertEqual(r.returncode, 0, r.stderr) self.assertIn(expected, r.stdout, "HMAC-{} mismatch".format(alg)) diff --git a/tests/hash/hash-test.py b/tests/hash/hash-test.py index 42c6e5dc..a51d6286 100644 --- a/tests/hash/hash-test.py +++ b/tests/hash/hash-test.py @@ -35,6 +35,13 @@ def setUpClass(cls): if "disable-filesystem" in f.read(): raise unittest.SkipTest("filesystem support disabled") + def test_md5(self): + r = run_wolfssl("-hash", "-md5", "-in", CERT_FILE) + if not_compiled_in(r): + self.skipTest("MD5 not compiled into wolfSSL") + self.assertEqual(r.returncode, 0, r.stderr) + self.assertEqual(r.stdout.strip(), _read_expected("md5-expect.hex")) + def test_sha(self): r = run_wolfssl("-hash", "-sha", "-in", CERT_FILE) self.assertEqual(r.returncode, 0, r.stderr) @@ -69,7 +76,7 @@ def test_base64dec(self): def test_blake2b(self): r = run_wolfssl("-hash", "-blake2b", "64", "-in", CERT_FILE) - if r.returncode != 0 and "BLAKE2 not avalible" in (r.stdout + r.stderr): + if not_compiled_in(r): self.skipTest("BLAKE2 not compiled into wolfSSL") self.assertEqual(r.returncode, 0, r.stderr) self.assertEqual(r.stdout.strip(), _read_expected("blake2b-expect.hex")) From 2f3173d78f4a0540a8c450d09ac1a67b0580a310 Mon Sep 17 00:00:00 2001 From: Lealem Amedie Date: Fri, 14 Aug 2026 10:44:45 -0600 Subject: [PATCH 3/3] Address peer review feedback --- src/sign-verify/clu_dgst_setup.c | 4 ++++ src/sign-verify/clu_verify.c | 1 + src/x509/clu_x509_sign.c | 2 +- 3 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/sign-verify/clu_dgst_setup.c b/src/sign-verify/clu_dgst_setup.c index ceec1d51..b7da5420 100644 --- a/src/sign-verify/clu_dgst_setup.c +++ b/src/sign-verify/clu_dgst_setup.c @@ -619,6 +619,10 @@ int wolfCLU_dgst_setup(int argc, char** argv) while ((option = wolfCLU_GetOpt(argc, argv, "", dgst_options, &longIndex )) != END_OF_ARGS) { + if (ret != WOLFCLU_SUCCESS) { + break; + } + switch (option) { case WOLFCLU_MD5: diff --git a/src/sign-verify/clu_verify.c b/src/sign-verify/clu_verify.c index 385671b5..3f8adc09 100644 --- a/src/sign-verify/clu_verify.c +++ b/src/sign-verify/clu_verify.c @@ -841,6 +841,7 @@ int wolfCLU_verify_signature_ed25519(byte* sig, int sigSz, (void)pubIn; (void)inForm; + wolfCLU_LogError("ED25519 not compiled in"); return NOT_COMPILED_IN; #endif /* HAVE_ED25519 */ } diff --git a/src/x509/clu_x509_sign.c b/src/x509/clu_x509_sign.c index 75d5b382..717ad910 100644 --- a/src/x509/clu_x509_sign.c +++ b/src/x509/clu_x509_sign.c @@ -1304,7 +1304,7 @@ int wolfCLU_CertSign(WOLFCLU_CERT_SIGN* csign, WOLFSSL_X509* x509) md = wolfSSL_EVP_md5(); #else wolfCLU_LogError("MD5 not compiled in"); - ret = WOLFCLU_FATAL_ERROR; + ret = NOT_COMPILED_IN; #endif } else if (csign->hashType == WC_HASH_TYPE_SHA) {