Skip to content

MC/DC coverage for wolfCrypt modules - Part 3#10912

Open
danielinux wants to merge 12 commits into
wolfSSL:masterfrom
danielinux:mcdc-test-coverage
Open

MC/DC coverage for wolfCrypt modules - Part 3#10912
danielinux wants to merge 12 commits into
wolfSSL:masterfrom
danielinux:mcdc-test-coverage

Conversation

@danielinux

Copy link
Copy Markdown
Member

Description

Adds/extends tests/api MC/DC DecisionCoverage + FeatureCoverage and tests/unit-mcdc white-box supplements for the remaining wolfCrypt primitives (first-pass per-module union; gap-closing to follow):

  • classic bigint: tfm.c, integer.c (extend test_wolfmath.c; tfm/integer whiteboxes)
  • coding.c, error.c, wc_encrypt.c, pwdbased.c
  • ed448.c + curve448.c (shared fe_448/ge_448 backends; ed448 whitebox)
  • random.c deepened + new wolfentropy.c (MemUse SP800-90B), whiteboxes
  • hash.c, kdf.c, signature.c, chacha20_poly1305.c
  • LMS/XMSS (wc_lms*.c, wc_xmss*.c) with impl whiteboxes
  • ML-KEM (wc_mlkem*.c), ML-DSA (wc_mldsa.c), SLH-DSA (wc_slhdsa.c) with whiteboxes

New tests register in tests/api.c + tests/api/include.am. Frozen-module guards (!HAVE_SELFTEST && !HAVE_FIPS) applied to new random.c/pwdbased.c tests that call post-v4.1.0 symbols.

Follow up to #10845 , #10876

Copilot AI review requested due to automatic review settings July 15, 2026 16:52
@danielinux danielinux self-assigned this Jul 15, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR extends the project’s ISO 26262 MC/DC test-coverage campaign by adding new DecisionCoverage/FeatureCoverage API tests and adding unit-mcdc white-box supplements for additional wolfCrypt primitives, then registering the new tests in the existing test harness.

Changes:

  • Added new tests/api DecisionCoverage/FeatureCoverage test cases for multiple wolfCrypt modules (e.g., entropy, coding, error, encrypt, hash, random/DRBG, PQC/signature families).
  • Added new tests/unit-mcdc white-box binaries that #include module .c files directly to exercise API-unreachable static decision paths.
  • Updated test registration/plumbing in tests/api.c and tests/api/include.am.

Reviewed changes

Copilot reviewed 46 out of 46 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
tests/unit-mcdc/test_wolfentropy_whitebox.c White-box coverage for wolfentropy health-test statics
tests/unit-mcdc/test_wc_xmss_impl_whitebox.c White-box XMSS/XMSS^MT impl roundtrip to hit static helpers
tests/unit-mcdc/test_wc_mlkem_poly_whitebox.c White-box ML-KEM poly core statics (cmp/rej_uniform/ntt)
tests/unit-mcdc/test_wc_lms_impl_whitebox.c White-box LMS/HSS impl roundtrip + targeted statics
tests/unit-mcdc/test_tfm_whitebox.c White-box for tfm.c FASTMATH static decisions
tests/unit-mcdc/test_slhdsa_whitebox.c White-box for SLH-DSA statics (param scan/base-2b/HA encode)
tests/unit-mcdc/test_random_whitebox.c Extended random.c white-box leaves for MC/DC
tests/unit-mcdc/test_integer_whitebox.c White-box for integer.c HEAPMATH static helpers
tests/unit-mcdc/test_ed448_whitebox.c White-box for ed448_hash() guard operands
tests/api/test_wolfmath.h Registers new wolfmath DecisionCoverage entry points
tests/api/test_wolfentropy.h Adds wolfentropy API test declarations/registration macro
tests/api/test_wolfentropy.c Adds wolfentropy API DecisionCoverage/FeatureCoverage tests
tests/api/test_wc_encrypt.h Registers new wc_encrypt API tests
tests/api/test_wc_encrypt.c Adds AES-CBC and BufferKeyEncrypt/Decrypt coverage tests
tests/api/test_slhdsa.h Registers SLH-DSA Decision/Feature coverage tests
tests/api/test_slhdsa.c Adds SLH-DSA API DecisionCoverage/FeatureCoverage tests
tests/api/test_signature.h Registers signature wrapper Decision/Feature coverage tests
tests/api/test_signature.c Adds signature wrapper DecisionCoverage/FeatureCoverage tests
tests/api/test_random.h Registers DRBG Decision/Feature coverage tests
tests/api/test_random.c Adds DRBG API DecisionCoverage/FeatureCoverage tests
tests/api/test_pwdbased.h Registers PBKDF DecisionCoverage tests
tests/api/test_pwdbased.c Adds PBKDF1/PBKDF2/PKCS12_PBKDF DecisionCoverage tests
tests/api/test_mlkem.h Registers ML-KEM Decision/Feature coverage tests
tests/api/test_mlkem.c Adds ML-KEM API DecisionCoverage/FeatureCoverage tests
tests/api/test_mldsa.h Registers ML-DSA Decision/Feature coverage tests
tests/api/test_mldsa.c Adds ML-DSA API coverage tests and adjusts PKCS12 guard
tests/api/test_lms_xmss.h Registers LMS/XMSS Decision/Feature coverage tests
tests/api/test_kdf.h Adds KDF test declarations/registration macro
tests/api/test_hash.h Registers hash wrapper Decision/Feature coverage tests
tests/api/test_hash.c Adds hash wrapper DecisionCoverage/FeatureCoverage tests
tests/api/test_error.h Adds error-string coverage test declarations/registration
tests/api/test_error.c Adds error.c switch-arm sweep coverage tests
tests/api/test_ed448.h Registers ed448 Decision/Feature coverage tests
tests/api/test_ed448.c Adds ed448 DecisionCoverage + streaming verify FeatureCoverage
tests/api/test_curve448.h Registers new curve448 decision-coverage test functions
tests/api/test_curve448.c Adds curve448 DecisionCoverage split tests
tests/api/test_coding.h Adds coding.c coverage test declarations/registration
tests/api/test_coding.c Adds Base64/Base16 DecisionCoverage + whitespace coverage
tests/api/test_chacha20_poly1305.h Registers ChaCha20-Poly1305/XChaCha20-Poly1305 coverage tests
tests/api/test_chacha20_poly1305.c Adds residual DecisionCoverage + large-buffer XChaCha test
tests/api/include.am Adds new test sources/headers to automake lists
tests/api.c Registers new test groups in the main API test runner

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/api/test_random.c
danielinux added a commit to danielinux/wolfssl that referenced this pull request Jul 15, 2026
Copilot review (test_random.c:1238): test_wc_DrbgFeatureCoverage claimed a
bounded burst of generate calls crosses WC_RESEED_INTERVAL, but the default
interval is 1,000,000 so 40 generates never reach it and the
DRBG_NEED_RESEED -> PollAndReSeed branch was not exercised in normal builds.

Force the path instead: probe one generate to confirm the Hash_DRBG path is
active (skipped under e.g. --enable-intelrand), then set the active DRBG's
reseedCtr to WC_RESEED_INTERVAL - 1 and generate across it, asserting the
reseed resets the counter (same idiom as test_wc_RNG_ReseedBoundary), for
both SHA-256 and SHA-512 DRBG widths. Comment corrected to match.
@danielinux
danielinux force-pushed the mcdc-test-coverage branch from a27b11a to 3a47bfb Compare July 17, 2026 06:55
Adds/extends tests/api MC/DC DecisionCoverage + FeatureCoverage and
tests/unit-mcdc white-box supplements for the remaining wolfCrypt
primitives (first-pass per-module union; gap-closing to follow):

- classic bigint: tfm.c, integer.c (extend test_wolfmath.c; tfm/integer whiteboxes)
- coding.c, error.c, wc_encrypt.c, pwdbased.c
- ed448.c + curve448.c (shared fe_448/ge_448 backends; ed448 whitebox)
- random.c deepened + new wolfentropy.c (MemUse SP800-90B), whiteboxes
- hash.c, kdf.c, signature.c, chacha20_poly1305.c
- LMS/XMSS (wc_lms*.c, wc_xmss*.c) with impl whiteboxes
- ML-KEM (wc_mlkem*.c), ML-DSA (wc_mldsa.c), SLH-DSA (wc_slhdsa.c) with whiteboxes

New tests register in tests/api.c + tests/api/include.am. Frozen-module
guards (!HAVE_SELFTEST && !HAVE_FIPS) applied to new random.c/pwdbased.c
tests that call post-v4.1.0 symbols.
- CMakeLists.txt: register the new tests/api sources (test_kdf.c,
  test_coding.c, test_error.c, test_wolfentropy.c) with the unit_test
  target; fixes cmake link failure (undefined
  test_wc_GetErrorStringDecisionCoverage/test_wc_ErrorStringDecisionCoverage).
- tests/api/test_mldsa.c: guard the wc_MlDsaKey_MakeKey NULL-arg checks
  in test_wc_MldsaDecisionCoverage with WOLFSSL_MLDSA_NO_MAKE_KEY; fixes
  link failure in verify-only builds (tinytls13-psk-mldsa,
  all-pq-verify-only-noasm).
- tests/unit-mcdc/*: reword 'statics' to 'static helpers' in comments to
  satisfy codespell.
Copilot review (test_random.c:1238): test_wc_DrbgFeatureCoverage claimed a
bounded burst of generate calls crosses WC_RESEED_INTERVAL, but the default
interval is 1,000,000 so 40 generates never reach it and the
DRBG_NEED_RESEED -> PollAndReSeed branch was not exercised in normal builds.

Force the path instead: probe one generate to confirm the Hash_DRBG path is
active (skipped under e.g. --enable-intelrand), then set the active DRBG's
reseedCtr to WC_RESEED_INTERVAL - 1 and generate across it, asserting the
reseed resets the counter (same idiom as test_wc_RNG_ReseedBoundary), for
both SHA-256 and SHA-512 DRBG widths. Comment corrected to match.
Close API-reachable and file-static MC/DC gaps identified by the per-module
GAPS.md reports (+291 conditions across the union):
  tfm.c 71->89, integer.c 49->92, ed448.c 62->92 (91%), wc_slhdsa.c 99->155
  (88%), wc_mldsa.c 169->252, wc_mlkem.c 46->65 (96%), wc_lms_impl.c 60->82,
  wc_xmss_impl.c 38->57.

Enriched DecisionCoverage in test_wolfmath.c (tfm/integer), test_ed448.c,
test_slhdsa.c; new arg/state/length cases in test_mldsa.c/test_mlkem.c; and
per-source *_gap white-box supplements under tests/unit-mcdc/ driving the
static internals (WOTS/FORS/NTT/poly/Merkle/comba/Montgomery, etc.). Remaining
uncovered conditions are justified residuals (AVX2/cpuid dispatch on an
always-AVX2 host, deep alloc/crypto-failure err-chains, asm-only paths).
Reword "statics" -> "static functions" in test_ed448_whitebox_gap.c and
test_wc_xmss_impl_whitebox_gap.c (codespell flags "statics").
Merge the _gap white-box drivers into their base file (tfm, integer, ed448,
mldsa, mlkem_poly, slhdsa, xmss_impl) and delete the _gap copies; a single
binary per source also satisfies more MC/DC independence pairs (tfm 89->91,
integer 92->100, mlkem_poly 25->27, mldsa 252->256). LMS is kept as two files:
its sign-side drivers reference internals absent under verify-only/small
builds and use per-driver state that does not share one main() safely.
…quence

test_wolfSSL_read_write_ex hard-coded the close-notify exchange as
NOT_DONE/NOT_DONE/SUCCESS/SUCCESS, which is protocol-version/config dependent
and fails under the cmake old-TLS build. Loop wolfSSL_shutdown on each side
until WOLFSSL_SUCCESS (pre-existing flake, not from this PR's new tests).
Close API-reachable and file-static gaps in the smaller modules (+52 union
conditions): kdf 75->91, coding 48->64, wolfentropy 9->13, curve448 54->58
(100%), chacha20_poly1305 43->46 (100%), hash 6->7 (100%), wc_encrypt 16->19,
pwdbased 14->17, signature 30->32. Additive cases in the existing tests (one
new test_wc_HashTypeConvert), plus wolfentropy/random white-box drivers.
Remaining are justified residuals (WOLFSSL_LOCAL wc_CryptKey, dead defensive
branches, alloc/crypto-failure err-chains, platform seed sources).
Under DEBUG_WOLFSSL, wc_HashUpdate/Final/Free first check (hash->type != type)
and return BAD_FUNC_ARG before the switch, so the "unsupported type ->
HASH_TYPE_E" arm is unreachable on an uninitialized hash (wc_HashInit refuses
those types). Guard those Update/Final/Free assertions with #ifndef
DEBUG_WOLFSSL; the arm's coverage comes from non-DEBUG variants in the union.
Fixes the cmake (old-TLS/debug) build failure. wc_HashInit assertions keep
running (Init has no such type check).

This bug is fixed in PR wolfSSL#10927
kdf: wc_Tls13_HKDF_Extract_ex / wc_Tls13_HKDF_Expand_Label_ex postdate the
frozen FIPS/selftest kdf.h and are undeclared there. Gate every _ex call site
behind WOLFSSL_TEST_HKDF_EX (!HAVE_FIPS && !HAVE_SELFTEST); the thin non-_ex
wrappers, which exist everywhere, keep their coverage.

wolfmath: test_wc_TfmDecisionCoverage / test_wc_TfmExptModDecisionCoverage /
test_wc_IntegerDecisionCoverage called library-internal fp_* and s_mp_*
functions that carry no MP_API decoration, so under -fvisibility=hidden they
are not exported from the shared library and unit.test failed to link them
(undefined reference to fp_set / s_mp_mul_digs / ...) in the default shared CI
build. Relocate those decision drivers into the tests/unit-mcdc white-boxes,
which reach the internals legally by #including tfm.c / integer.c; tests/api
now uses only the public mp_* interface. mp_rand_prime calls are gated by
WOLFSSL_KEY_GEN (and, for integer, !NO_DH || !NO_DSA) to match where the
library declares and defines it.
The FIPS build diverges from the OPEN build on KDF behavior these exhaustive
MC/DC probes assert: wc_HmacSetKey enforces the 14-byte HMAC_FIPS_MIN_KEY, so
wc_Tls13_HKDF_Extract with the short salt/ikm here returns HMAC_MIN_KEYLEN_E
(-200) instead of 0 (test_kdf.c:766), and wc_PRF with resLen==0 returns 0
instead of BAD_FUNC_ARG (test_kdf.c:118). kdf.c coverage is measured only in
non-FIPS campaign variants, so guard both test_wc_KdfDecisionCoverage and
test_wc_KdfFeatureCoverage bodies with !HAVE_FIPS && !HAVE_SELFTEST; they run
in full in OPEN builds and skip cleanly under FIPS/selftest. Verified against
a --enable-fips=v5 build (both now skip, 0 failures).
check-source-text (rule I) flags error-code identifiers used as comparison
operands even inside comments. Reword three comments so the code name is no
longer written as "(ret == PUBLIC_KEY_E)" / "(ret != CRYPTOCB_UNAVAILABLE)"
(test_kdf.c, test_ed448.c); the bare token on its own is fine.

clang-tidy reported a possible 0-byte malloc in test_mlkem.c: the ML-KEM
key/ciphertext sizes come from wc_MlKemKey_*Size() queries, which the analyzer
cannot prove nonzero. Guard each XMALLOC with a >0 check so the allocation
size is provably positive; the ExpectNotNull() checks still catch a 0-size
query at runtime.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants