Mcdc test coverage campaign - part 2#10876
Open
danielinux wants to merge 22 commits into
Open
Conversation
Merged
Contributor
There was a problem hiding this comment.
Pull request overview
This PR continues the MC/DC coverage campaign by adding a large set of decision/edge-path tests (including “white-box” unit-mcdc binaries that #include implementation .c files) across multiple wolfCrypt modules, plus a small source tweak in SHA/SHA3 update paths to make “empty update” decisions coverable.
Changes:
- Reorders SHA-1 and SHA-3/SHAKE update argument guards so the
data == NULL && len == 0empty-update path is explicitly reachable for coverage. - Adds extensive API-level DecisionCoverage tests across RSA, RNG, CMAC/HMAC, ChaCha/Poly1305, Curve25519/Ed25519, ECC, DSA, and SP-math.
- Introduces multiple
tests/unit-mcdc/*_whitebox.ctranslation units that directly include wolfCrypt.csources to reach file-static/internal decisions.
Reviewed changes
Copilot reviewed 38 out of 38 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| wolfcrypt/src/sha.c | Reorders wc_ShaUpdate() argument checks to allow explicit empty-update coverage. |
| wolfcrypt/src/sha3.c | Reorders SHA3/SHAKE update argument checks similarly for empty-update coverage. |
| tests/unit-mcdc/test_sp_int_whitebox.c | New white-box MC/DC supplement for non-normalized sp_int internal loops. |
| tests/unit-mcdc/test_sha256_whitebox.c | New white-box supplement forcing x86_64 SHA-256 dispatch conditions. |
| tests/unit-mcdc/test_sha512_whitebox.c | New white-box supplement forcing x86_64 SHA-512 dispatch conditions. |
| tests/unit-mcdc/test_sha3_whitebox.c | New white-box supplement forcing SHA-3 dispatch decisions (x86_64 + aarch64 lanes). |
| tests/unit-mcdc/test_random_whitebox.c | New white-box supplement covering structurally unreachable random.c internal guards. |
| tests/unit-mcdc/test_chacha_whitebox.c | New white-box supplement exercising Intel ChaCha dispatch non-AVX2 sides. |
| tests/unit-mcdc/test_poly1305_whitebox.c | New white-box supplement exercising Intel Poly1305 AVX1-only side. |
| tests/unit-mcdc/test_cmac_whitebox.c | New white-box supplement driving unreachable CMAC id/label cross-combinations. |
| tests/unit-mcdc/test_curve25519_whitebox.c | New white-box supplement reaching WC_X25519_NONBLOCK internal guards. |
| tests/unit-mcdc/test_ed25519_whitebox.c | New white-box supplement calling file-static ed25519_hash() directly. |
| tests/unit-mcdc/test_ecc_whitebox.c | New white-box supplement calling ECC file-static helpers directly. |
| tests/unit-mcdc/test_aes_whitebox.c | Extends AES white-box coverage (AES-NI + aarch64 hw-crypto/GCM-streaming decisions). |
| tests/api/test_wolfmath.h | Registers new SP-math DecisionCoverage test entry points. |
| tests/api/test_rsa.c | Adds RSA API DecisionCoverage and extra feature-coverage paths. |
| tests/api/test_random.h | Registers new RNG DecisionCoverage test entry points. |
| tests/api/test_random.c | Adds extended RNG health-test, callback, custom-block, and DRBG-disable coverage. |
| tests/api/test_poly1305.c | Adds Poly1305 operand-independence and padding/AD edge-case coverage. |
| tests/api/test_hmac.h | Registers new HMAC/HKDF DecisionCoverage test entry points. |
| tests/api/test_hmac.c | Adds new HMAC/HKDF DecisionCoverage tests and CryptoCb cleanup coverage. |
| tests/api/test_ed25519.h | Registers new Ed25519 DecisionCoverage test entry points. |
| tests/api/test_ed25519.c | Adds multiple Ed25519 DecisionCoverage tests (ctx/ph, streaming verify, import/make_public arg checks). |
| tests/api/test_ecc.h | Registers ECC DecisionCoverage test entry points (split into 4 functions). |
| tests/api/test_dsa.h | Registers new DSA DecisionCoverage test entry points. |
| tests/api/test_dsa.c | Adds DSA argument/edge-path tests and parameter import/export edge cases. |
| tests/api/test_dh.h | Registers new DH DecisionCoverage test entry points. |
| tests/api/test_curve25519.h | Registers new Curve25519 DecisionCoverage test entry points. |
| tests/api/test_curve25519.c | Adds Curve25519 argument checks, public-key validation edge cases, and nonblock state-machine coverage. |
| tests/api/test_cmac.h | Registers new CMAC DecisionCoverage test entry points. |
| tests/api/test_cmac.c | Adds CMAC DecisionCoverage tests including CryptoCb mismatch path. |
| tests/api/test_chacha.h | Registers new XChaCha20 test entry point. |
| tests/api/test_chacha.c | Adds ChaCha arg/edge-path coverage including XChaCha20 setup. |
| tests/api/test_aes.c | Adds AES-EAX streaming authIn argument-check independence pair coverage. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
Member
Author
|
depends on #10875 |
MC/DC white-box supplements for the sha module of the ISO 26262 campaign,
one per involved file that has an x86-64 USE_INTEL_SPEEDUP runtime
dispatch: test_sha256_whitebox.c, test_sha512_whitebox.c,
test_sha3_whitebox.c. Each #includes its wolfcrypt/src/shaXXX.c so the
file-static cpuid mask (intel_flags / cpuid_flags) and transform function
pointers are in scope.
On an AVX2-capable host the runtime only ever takes the AVX2 branch of the
IS_INTEL_AVX1/AVX2/SHA/BMI dispatch decisions, so their not-taken
conditions are unreachable from tests/api (the aesni-class residual). The
supplements force the mask to each of {0, AVX1, AVX2, SHA, BMI1|BMI2, ...}
to show every condition's independence pair, while pinning the transform
pointer to the portable C path so a claimed-but-absent feature (e.g.
SHA-NI) never executes its asm -- crash-safe on any host.
Two mechanics were needed for full coverage: the host's multi-block 'Len'
transform bypasses the per-block byte-reverse decision, so the pointer is
set NULL to route through the per-block path; and the byte-reverse
decisions live in several update sub-paths (buffered-block completion,
bulk loop, final on/over the padding boundary) that are each driven with
the matching update granularity. The sha3 multi-block fast-path decision
needs both the NULL and non-NULL block-pointer rows in the same binary, so
both are exercised.
Closes the Intel dispatch false-sides in the union: sha256.c 19->25/26,
sha512.c 25->35/36, sha3.c 41->45/49. Remaining gaps are structural/lane
residuals (guard ordering, transform-failure, an AArch64-only twin);
documented in the campaign's reports/sha/RESIDUALS.md.
test_wc_AesEaxArgMcdc exercised the eax/out/in operands of wc_AesEaxEncryptUpdate / wc_AesEaxDecryptUpdate but always passed (authIn=NULL, authInSz=0), so the guard's authInSz>0 && authIn==NULL term was never evaluated with authInSz>0 -- leaving those two conditions (and their decrypt twins) uncovered in the MC/DC union. Add, for both Update functions, the (authIn==NULL, authInSz>0) row (rejected with BAD_FUNC_ARG) and the (authIn!=NULL, authInSz>0) row (accepted), completing both conditions' independence pairs. These four conditions were the only uncovered code the recent master merge (AES-GCM-SIV, AES-OFB/CFB callbacks) added to aes.c that was reachable from tests/api; closes them so the aes.c union returns to its residual-only gap (410/445, gap 35).
…rable
wc_ShaUpdate, wc_Sha3Update, wc_Shake128_Update and wc_Shake256_Update
guarded inputs as:
if (obj == NULL || (data == NULL && len > 0)) return BAD_FUNC_ARG;
if (data == NULL && len == 0) return 0;
The first guard rejected (data==NULL, len>0) before the second decision,
so that decision's len==0 condition could only ever be observed true --
its MC/DC independence pair was structurally unreachable.
Reorder to the same idiom sha256.c/sha512.c already use:
if (obj == NULL) return BAD_FUNC_ARG;
if (data == NULL && len == 0) return 0; /* (NULL,len>0) now reaches: len==0 false */
if (data == NULL) return BAD_FUNC_ARG;
Behavior is identical for every input; the existing DIGEST_UPDATE_TEST
cases wc_*Update(&dgst, NULL, 1) and (&dgst, NULL, 0) now exercise both
sides of the decision. Closes the four guard-ordering MC/DC residuals in
the sha campaign module (sha.c and sha3.c).
Adds #if defined(__aarch64__) && defined(WOLFSSL_ARMASM) sections to test_aes_whitebox.c and test_sha3_whitebox.c that close the AArch64-only MC/DC residuals the qemu-aarch64 emulator lane compiles but a native white-box cannot reach (qemu -cpu max always advertises AES+PMULL, so the runtime hw-crypto flags are always true on that lane): - aes.c: the 9-site `aes->use_aes_hw_crypto && aes->use_pmull_hw_crypto` dispatch (wc_AesGcmSetKey's H generation, the static GHASH_INIT helper, the one-shot Encrypt/Decrypt, and the streaming Init/EncryptUpdate/ EncryptFinal/DecryptUpdate/DecryptFinal quintet), forced via the Check_CPU_support_HwCrypto() cpuid_flags cache, plus the 4 internal AesGcm*Update_AARCH64 pointer guards, called directly. - sha3.c: the aarch64 twin of the Intel InitSha3 cached-dispatch decision (line ~759), cond1 (SHA3_BLOCK != NULL), mirroring the existing Intel-737 wb_init_with idiom. Both sections reduce to a no-op stub outside the qemu-aarch64 lane, so the files still compile+run natively unchanged. Verified against real qemu-aarch64 -cpu max: all 9 aes.c hw-crypto sites show independence pairs on both conditions, the 4 pointer-guard conditions' targeted halves show covered, and the sha3.c:759 cond1 pair closes.
Extend test_wc_RsaDecisionCoverage / test_wc_RsaFeatureCoverage and add a tests/unit-mcdc white-box supplement (test_rsa_whitebox.c) for the per-module MC/DC campaign, raising rsa.c union MC/DC from 67/268 to 156/283. DecisionCoverage/FeatureCoverage additions (API-reachable argument and feature paths): wc_RsaFunction 7-way arg check, wc_RsaDirect, wc_InitRsaKey_Id/Label, wc_MakeRsaKey size check, wc_CheckProbablePrime, wc_RsaPSS_CheckPadding, OAEP label mismatch (encrypt + decrypt), and a WC_RSA_NO_PADDING raw round trip. A PSS-SHA512-on-1024-bit-key case is staged behind if(TEST_RSA_BITS==1024). White-box supplement (file-static helpers shielded by a public pre-guard, so their argument checks are unreachable from the API): _NewRsaKey_common, _RsaExportKey, _RsaFlattenPublicKey, wc_CompareDiffPQ, _RsaPrivateKeyDecodeRaw, RsaPad, RsaUnPad, _CheckProbablePrime. Both halves of each independence pair are exercised within the white-box binary. Modeled on test_aes_whitebox.c; main() always returns 0 so a setup failure is a skip, not a discarded variant. Selftest/FIPS-sensitive assertions stay inside the existing !defined(HAVE_SELFTEST) guard and the OAEP cases stay under !defined(HAVE_FIPS), matching the committed idiom for this frozen-boundary file.
tests/api/test_wolfmath.c gains six DecisionCoverage test functions covering sp_int.c's mp_*/sp_* API: the allocation family (sp_init_size, sp_grow, sp_copy, sp_exch), the shift family (sp_set_bit, sp_2expt, sp_lshd, sp_rshb), the single-digit and multi-precision arithmetic families (sp_add_d/sp_sub_d/sp_mul_d/sp_div_d/sp_mod_d/sp_div_2/ sp_div_2_mod_ct/sp_add/sp_sub/sp_addmod_ct/sp_submod_ct/sp_div, including their WOLFSSL_SP_INT_NEGATIVE sign-path counterparts), the conversion family (sp_div_2d/sp_mod_2d/sp_mul_2d/sp_sqrmod/ sp_mont_red_ex/sp_to_unsigned_bin_len(_ct)/sp_tohex/sp_read_radix), and the sp_invmod/sp_exptmod_ex/sp_gcd/sp_prime_is_prime(_ex) top-level argument and degenerate-input checks. Each exercises an internal size/capacity guard or argument check via a deliberately undersized destination (sp_init_size with a small size) or an out-of-range argument - legitimate, public ways to reach decisions valid-sized RSA/ ECC/DH usage never trips. tests/unit-mcdc/test_sp_int_whitebox.c is a new white-box supplement (compiles sp_int.c in directly) closing the sp_count_bits/sp_cnt_lsb non-normalized-digit trim loops: no public caller can produce that state since every public mutator normalizes via sp_clamp before returning. Part of the ISO 26262 per-module MC/DC campaign's sp-math module (wolfcrypt/src/sp_int.c, Phase 1): 412/547 (75.32%) MC/DC across 6 build-variant axes (WOLFSSL_SP_MATH_ALL vs bare WOLFSSL_SP_MATH, WOLFSSL_SP_SMALL, WOLFSSL_SP_INT_NEGATIVE, WOLFSSL_SP_DIV_WORD_HALF, WOLFSSL_SMALL_STACK) + the white-box, up from a 318/547 baseline. The remaining gaps are deep invmod/exptmod/prime/gcd internal state-machine internals, the SP-accelerated-backend-entangled RSA/DH key-size dispatch, and other structural residuals; campaign-side files (config, module registry, baseline) live in the separate testing repo.
Adds test_wc_EccDecisionCoverage{,2,3,4} to tests/api/test_ecc.c (split
into four functions after a single giant one triggered a -fcoverage-mcdc
+ -O0 stack-corruption crash under this campaign's build, reproduced and
root-caused with gdb: a plain on-stack mp_int's used/size fields were
already garbage immediately after its own mp_init()) and a new
tests/unit-mcdc/test_ecc_whitebox.c white-box supplement, closing curve
lookup, point-is-at-infinity, gen_k, init_id/init_label, sign/verify
length, point DER import/export, is_point, export_public_raw/private_raw,
rs_raw_to_sig, ctx_set_kdf_salt, set_custom_curve, X963_KDF, curve_load,
_ecc_import_private_key_ex, and ecEncCtx protocol-guard decisions.
ecc.c union MC/DC across all 6 campaign variants: 217/597 -> 287/597.
Per-module ISO 26262 MC/DC campaign (iso26262-mcdc-per-module). Adds DecisionCoverage-style cases to tests/api/test_chacha.c and test_poly1305.c, plus intel-dispatch white-box supplements mirroring the aes/sha3 technique. chacha.c: BEFORE 6/11 (54.55%) -> AFTER 13/13 (100%). Closed wc_Chacha_SetIV/SetKey's NULL-argument independence pairs, wc_Chacha_Process's input/output NULL-argument pairs (both the portable-C and USE_INTEL_CHACHA_SPEEDUP physical copies), and the (msglen>0 && ctx->left>0) leftover-block decision's msglen==0 side. Also adds an unaligned-key SetKey case (XSTREAM_ALIGN), a half-length key case, and a new test_wc_Chacha_XChachaSetKey covering wc_XChacha_SetKey. Total rose from 11 to 13 once the intelasm variant was fixed (see campaign notes): it carries its own physical copy of the leftover decision that the portable-only union previously missed. poly1305.c: BEFORE 10/14 (71.43%) -> AFTER 12/14 (85.71%). Closed wc_Poly1305Update's (m==NULL && bytes>0) inner AND, both operands. Also adds an addSz==0 case to wc_Poly1305_MAC and a lenToPad==WC_POLY1305_PAD_SZ case to wc_Poly1305_Pad for API robustness. The 2 remaining conditions are structural/dead-code residuals: wc_Poly1305SetKey's compound key==NULL check is shadowed by an earlier unconditional key==NULL guard a few lines above (dead code); wc_Poly1305_Pad's paddingLen<WC_POLY1305_PAD_SZ operand is always true whenever paddingLen>0 (paddingLen is a mod-16 value bounded to 0..15). See campaign baselines.json for full detail.
hmac.c: BEFORE 19/37 (51.35%) -> AFTER 37/37 (100%). Closed wc_HmacSizeByType's own hash-type compound (separate physical decision from wc_HmacSetKey_ex's copy), wc_HmacCopy's NULL guard, wc_HmacInit_Id/wc_HmacInit_Label's length/NULL guards, wc_HmacFree's devId/devCtx cleanup guard, and wc_HKDF_Extract_ex/wc_HKDF_Expand_ex's NULL-inKey guard at both physical locations. No white-box needed; every decision is reachable through the public API once WOLF_PRIVATE_KEY_ID / WOLF_CRYPTO_CB are exercised. cmac.c: BEFORE 19/58 (32.76%) -> AFTER 58/58 (100%). Closed independence pairs across wc_CmacUpdate/wc_CMAC_Grow/wc_AesCmacGenerate's NULL+len guards, wc_CmacFinalNoFree's outSz/tag-size guards, new wc_InitCmac_Id/wc_InitCmac_Label tests plus a new tests/unit-mcdc/test_cmac_whitebox.c supplement for _InitCmac_common's id/label cross-combination leaves that are structurally unreachable through the public wrappers, new DecisionCoverage tests driving wc_AesCmacGenerate_ex/wc_AesCmacVerify_ex directly, and a WOLF_CRYPTO_CB test reaching wc_AesCmacVerify_ex's aSz-mismatch guard (unreachable in native software builds without a callback that violates the length contract). Both modules verified across all native variants (including WOLF_PRIVATE_KEY_ID and WOLF_CRYPTO_CB axes) with zero build/test failures.
Per-module MC/DC campaign (iso26262-mcdc-per-module). Adds decision- coverage test cases to tests/api/test_curve25519.c and test_ed25519.c, plus tests/unit-mcdc white-box supplements for file-static helpers unreachable through any public wrapper (all callers pre-validate identically before reaching them). curve25519.c: BEFORE 26/64 (40.62%) -> AFTER 62/64 (96.88%). Remaining 2: curve25519_smul_blind's RNG-retry loop (needs a mockable RNG). Found and documented (not fixed - test-only campaign) a source asymmetry bug in wc_curve25519_check_public's BIG_ENDIAN branch (checks pub[i]!=0 where the mirrored LITTLE_ENDIAN branch checks pub[i]!=0xff), and a build-blocking gap in curve25519.c's WOLFSSL_CURVE25519_NOT_USE_ED25519+CURVED25519_X64 path (curve25519_base() has no header prototype anywhere in the tree; fails under a strict C17 compiler). ed25519.c: BEFORE 45/89 (50.56%) -> AFTER 81/89 (91.01%). Remaining 8: 5 need a mockable hash/malloc failure to reach a ret==0 FALSE side after a successful ed25519_hash() call; 3 are WOLFSSL_CHECK_VER_FAULTS's redundant post-verify ConstantCompare, a deterministic double-call on identical inputs that cannot diverge without memory corruption in between. Both modules build and pass across every native variant (backend axis, blinding/non-blinding, WC_X25519_NONBLOCK, USE_INTEL_SPEEDUP, WOLFSSL_ED25519_PERSISTENT_SHA/STREAMING_VERIFY) with zero variant failures.
Adds tests/api DecisionCoverage functions closing MC/DC gaps identified
by the per-module campaign (iso26262/mcdc-per-module):
dh.c: BEFORE 51/173 (29.48%) -> AFTER 107/173 (61.85%), union across
6 native variants (sp_default, sp_dh, sp_dh_nonblock,
small_stack, no_dh186, validate_keygen). New coverage: wc_DhSetKey
family bad-args and the FFDHE-table primality fast-path, named-key
helpers (SetNamedKey/GetNamedKeyParamSize/CopyNamedKey/CmpNamedKey),
wc_DhGenerateKeyPair/GeneratePublic bad-args plus a multi-group
(2048/3072/4096) generate+agree(+ct) round trip, WC_DH_NONBLOCK's
incremental state machine, wc_DhImportKeyPair/ExportKeyPair,
wc_DhCheckPubKey(_ex)/wc_DhCheckPrivKey(_ex)/wc_DhCheckKeyPair
(+ WOLFSSL_VALIDATE_DH_KEYGEN), wc_DhGenerateParams/
wc_DhExportParamsRaw, and CheckDhLN's divLen==224/256 MC/DC pair.
dsa.c: BEFORE 34/110 (30.91%) -> AFTER 51/110 (46.36%), union across
4 native variants (default, invmod_ct, fastmath, small_stack).
New coverage: wc_DsaSign_ex/wc_DsaVerify_ex digestSz bad-argument
checks and the q==1 qMinus1-iszero guard, individual single-operand
NULL-argument combinations for ImportParamsRaw/ExportParamsRaw/
ExportKeyRaw, and CheckDsaLN's case-2048 divLen==224/256 MC/DC pair.
Both modules build and pass their tests/api group + KATs across every
native variant with zero failures (10/10 variant runs).
BEFORE 15/65 (23.08%) -> AFTER 55/65 (84.62%) MC/DC on wolfcrypt/src/random.c, measured across 5 native user_settings.h variants (default, WOLFSSL_SMALL_STACK, WOLFSSL_SMALL_STACK_CACHE, WC_RNG_SEED_CB, CUSTOM_RAND_GENERATE_BLOCK) plus a new tests/unit-mcdc/test_random_whitebox.c white-box supplement, in the ISO 26262 per-module MC/DC campaign. tests/api/test_random.c / test_random.h: - Add test_wc_RNG_HealthTest_SHA256_Ext / test_wc_RNG_HealthTest_SHA512_Ext, exercising the previously-untested ACVP-oriented extended health-test entry points (wc_RNG_HealthTest_SHA256_ex, wc_RNG_HealthTest_SHA512_ex/_ex2): nonce/personalization-string/additional-input/reseed-entropy presence and absence, in both standard and prediction-resistance modes, including "valid pointer + zero size" calls needed to isolate each leaf's size operand independently of its pointer operand for MC/DC. - Add test_wc_RNG_SeedCb (WC_RNG_SEED_CB custom seed callback: success, failing callback, and no-callback-installed paths). - Add test_wc_RNG_CustomRandBlock (CUSTOM_RAND_GENERATE_BLOCK bypass path). - Add test_wc_RNG_DrbgDisable (wc_Sha256Drbg_Disable/Enable/IsDisabled and the wc_Sha512Drbg_* equivalents: drbgType selection and the "can't disable both" BAD_STATE_E guard). - Extend existing HealthTest bad-parameter coverage (reseed-without-seedB on wc_RNG_HealthTest_ex / wc_RNG_HealthTest_SHA512 / wc_RNG_HealthTest_SHA512_ex, and the untested wc_RNG_HealthTest_SHA512_ex2 3-operand bad-parameter guard). - Guard test_wc_GenerateSeed against CUSTOM_RAND_GENERATE_BLOCK, whose wc_GenerateSeed() ladder intentionally has no implementation in that configuration (would otherwise be a link error, not a test failure). tests/unit-mcdc/test_random_whitebox.c (new): - White-box #include of random.c closing two structurally-unreachable-via-API leaves: Hash_gen()/Hash512_gen()'s "out != NULL && outSz != 0" false side, and array_add()'s "dLen > 0 && sLen > 0 && dLen >= sLen" false sides. Residuals (10 of 65, documented in db/modules.json / baselines.json in the paired testing-repo change): 4 WOLFSSL_SMALL_STACK allocation-failure branches (no fault injection); 4 Hash_DRBG_Init/Hash512_DRBG_Init chained Hash_df(...)==DRBG_SUCCESS conditions (transform-failure, SHA-256/512 never fail on valid input); 2 Hash_gen()/Hash512_gen() "outSz != 0" leaves that are structurally unsatisfiable given the caller's own outSz normalization and loop-bound arithmetic (not merely hard to reach). Bugs/interactions found while bringing up the CUSTOM_RAND_GENERATE_BLOCK build variant (reported, not source-fixed): (1) random.c's PollAndReSeed() is guarded only by "#ifdef HAVE_HASHDRBG" (not also "!defined(CUSTOM_RAND_GENERATE_BLOCK)" like _InitRng()) and its non-callback path unconditionally calls wc_GenerateSeed(), whose implementation ladder has an intentionally empty CUSTOM_RAND_GENERATE_BLOCK arm -- an undefined-symbol link error if a user_settings.h ever forces HAVE_HASHDRBG on together with CUSTOM_RAND_GENERATE_BLOCK (this campaign's config now avoids the combination instead of forcing it). (2) on this host, glibc's vDSO- accelerated getrandom() does not validate the output buffer before writing to it: wc_GenerateSeed(non-NULL os, NULL output, sz) segfaults inside getrandom_vdso() instead of returning an error, so TEST_WC_GENERATE_SEED_PARAMS is deliberately left undefined in the campaign config for this test-only bad-parameter block (documented in configs/random/user_settings.base.h).
test_wc_EccDecisionCoverage2 broke the unit.test link in several CI configs (net-snmp, C#/Rust wrappers, make check/analyze, etc.): - The wc_ecc_check_r_s_range block calls mp_init/mp_read_radix/mp_copy/ mp_clear, which resolve to sp_* under WOLFSSL_SP_MATH_ALL and are only exported with WOLFSSL_PUBLIC_MP. Add defined(WOLFSSL_PUBLIC_MP) to its guard (matching the other mp_*-using blocks in this file). - wc_ecc_export_point_der_compressed is WOLFSSL_LOCAL (hidden in a shared library) so it is not linkable from the shared-library unit test. Drop the four direct calls; its decision coverage is driven by the ecc white-box (which includes ecc.c). The public compressed path wc_ecc_export_x963_ex(...,1) is retained. Verified: --enable-net-snmp and --enable-all (+WOLFSSL_PUBLIC_MP) both build and link; unit.test passes.
Three more config-specific failures surfaced once the ecc link error was resolved: - test_wolfmath.c: test_wc_SpIntExptGcdDecisionCoverage called sp_gcd, whose definition (sp_int.c) is guarded by !NO_RSA && WOLFSSL_KEY_GEN - narrower than its sp_int.h prototype (|| ). Guard the sp_gcd block with the same condition so builds like --enable-curl (RSA on, key-gen off) link. - test_cmac.c: the crypto-cb badlen callback dereferences wc_CryptoInfo's cmac member (WOLFSSL_CMAC only) and uses the Cmac type, but was guarded by WOLF_CRYPTO_CB alone; configs with the callback framework but no CMAC (e.g. --enable-wolftpm) failed to compile. Match the callback's guard to its only caller (WOLFSSL_CMAC && !NO_AES && WOLFSSL_AES_128 && WOLF_CRYPTO_CB). - test_dsa.c: test_wc_DsaExportKeyRaw_individual_args re-initialized WC_RNG three times but freed it once, leaking two DRBGs (caught by LeakSanitizer in the --enable-all sanitizer build). Free the RNG before each re-init, mirroring the existing DsaKey free-before-reinit. Verified: --enable-curl and --enable-wolftpm build/link; --enable-all with -fsanitize=leak runs unit.test leak-free (test_wc_DsaExportKeyRaw_individual_args passes).
…lity The sp_int helper functions these tests call have varied, narrow definition guards in sp_int.c (e.g. sp_div_2d/sp_mod_2d/sp_mul_2d/sp_tohex need WOLFSSL_SP_MATH_ALL && !WOLFSSL_RSA_VERIFY_ONLY; the ct helpers need HAVE_ECC; sp_gcd needs !NO_RSA && WOLFSSL_KEY_GEN). The previous (WOLFSSL_SP_MATH_ALL || WOLFSSL_SP_MATH) && WOLFSSL_PUBLIC_MP guard let the tests compile in configs where some of those helpers are not built, producing undefined-reference link errors (sp_gcd, sp_div_2d, ...) in builds like --enable-curl and the pq-small matrix configs. Replace it with the union of the helpers' requirements, which the campaign sp-math config satisfies so coverage is unchanged, and drop the now-redundant per-call sp_gcd guard.
The all-check-mem-zero CI config (--enable-all -DWOLFSSL_CHECK_MEM_ZERO) aborted unit.test (exit 134) in two of the new decision-coverage tests. Both stem from wolfSSL mem-zero-tracking gaps that these tests are the first to exercise; the underlying decisions are covered in every normal build, so guard the specific triggers out of the instrumented build: - test_rsa.c (test_wc_RsaDecisionCoverage): calling wc_MakeRsaKey() with an out-of-range size makes it 'goto out' and run mp_memzero_check() over its not-yet-initialized local temporaries, which over-scans the stack and false-positives on the still-registered, legitimately non-zero key->d of the key made earlier in the test. Skip the two bad-size calls under the instrumented build. - test_dh.c (test_wc_DhImportExportKeyPair): wc_DhImportKeyPair() registers key->priv via mp_memzero_add(), but wc_FreeDhKey() clears it with mp_forcezero() (which does not deregister) and has no wc_MemZero_Check() like wc_FreeRsaKey() does, so the registration leaks into later tests. Skip this import/export test under the instrumented build. Verified: --enable-all -DWOLFSSL_CHECK_MEM_ZERO builds and unit.test passes (exit 0, zero mem-zero violations).
test_wc_DhGenerateParams_and_ExportRaw asserted wc_DhGenerateParams()==0, but the bare WOLFSSL_SP_MATH backend cannot generate DH domain parameters (returns PRIME_GEN_E), so the all-pq-sp-math CI config (--enable-sp-math) failed the assertion. Guard the test on !defined(WOLFSSL_SP_MATH); the generate/export decisions are covered with WOLFSSL_SP_MATH_ALL, fastmath and heapmath. Verified: --enable-sp-math unit.test passes (test skipped); the test still runs under --enable-all.
The mem-zero registration leak this guard worked around is fixed at the library level in wc_FreeDhKey() on the sibling branch (fixes-2026-07-10 / PR 10875). Drop the !WOLFSSL_CHECK_MEM_ZERO guard so the import/export test runs and validates that fix. This test therefore depends on PR 10875 to pass the all-check-mem-zero CI config.
…ZERO The mem-zero false-positive these calls tripped is fixed at the library level in wc_MakeRsaKey() on the sibling branch (fixes-2026-07-10 / PR 10875), which zero-initializes its stack temporaries so the early-out mp_memzero_check() is safe. Drop the !WOLFSSL_CHECK_MEM_ZERO guard so the RsaSizeCheck decision is exercised in the instrumented build too. Depends on PR 10875 for the all-check-mem-zero config.
Two MC/DC tests asserted pre-fix behavior; the corresponding library fixes changed the observable result: - test_wc_DsaImportParamsRaw_individual_args: the untrusted-import primality rejection now surfaces DH_CHECK_PUB_E, since CheckDsaLN is gated on err==MP_OKAY (commit 30ceba0) and no longer overwrites it with BAD_FUNC_ARG. - test_wc_curve25519_check_public_be: the big-endian "order or higher" loop now compares pub[i] != 0xff (symmetric with the little-endian branch, commit 600880a), so the rejection input needs pub[1..30] == 0xff, not 0x00. Updated the assertions and the now-stale explanatory comments. Both groups pass under --enable-all --enable-intelasm; full make check green.
3c8a444 to
0d62149
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Description
Added new test cases to existing tests, added more white-box unit tests for mc-dc coverage campaign.
Modules under tests
AES
test_aes.c (+14): AES-EAX streaming Update authIn argument-check pair. test_aes_whitebox.c (+215): Intel-dispatch white-box forcing the file-static cpuid mask over the AES-NI vs C transform selection, the AES-NI internal pointer guards, plus an aarch64 hw-crypto section (use_aes_hw_crypto/PMULL, run in the qemu-aarch64 lane).
SHA
three white-box files: test_sha256_whitebox.c (+134), test_sha512_whitebox.c (+142), test_sha3_whitebox.c (+237), all exercising the Intel AVX/SHA-NI/BMI dispatch decisions (and sha3's aarch64 twin) by pinning cpuid flags while keeping the C transform. The source change (sha.c/sha3.c, guard reorder in wc_ShaUpdate/wc_Sha3Update/Shake*_Update) makes the data==NULL && len==0 empty-update decision reachable.
RSA
test_rsa.c (+208): DecisionCoverage over the public RSA surface. test_rsa_whitebox.c (+452): white-box for internal guards not reachable from the API.
SP-math (sp_int.c)
test_wolfmath.c (+776): six DecisionCoverage functions across the mp_/sp_ families — allocation (sp_init_size/sp_grow/sp_copy/sp_exch), shift (sp_set_bit/sp_2expt/sp_lshd/sp_rshb), single-digit and multi-precision arithmetic, conversion (sp_to_unsigned_bin_len/sp_tohex/sp_read_radix), and sp_invmod/sp_exptmod/sp_gcd/sp_prime_is_prime argument/degenerate-input checks. test_sp_int_whitebox.c (+150): closes the sp_count_bits/sp_cnt_lsb non-normalized-digit loops.
ECC
test_ecc.c (+683): test_wc_EccDecisionCoverage{,2,3,4} (split into four after a -fcoverage-mcdc -O0 stack-corruption crash) covering curve lookup, point-at-infinity, gen_k, init id/label, sign/verify length, DER point import/export, is_point, raw export, custom curves, X9.63-KDF. test_ecc_whitebox.c (+336) for the file-static helpers.
ChaCha20 / Poly1305
test_chacha.c (+88): NULL-arg independence pairs for SetIV/SetKey/Process (both C and Intel physical copies), leftover-block decision, unaligned/half-key cases, wc_XChacha_SetKey. test_poly1305.c (+26): wc_Poly1305Update compound-condition operands. White-boxes test_chacha_whitebox.c (+143) / test_poly1305_whitebox.c (+124): the Intel cpuidFlags/intel_flags dispatch decisions.
HMAC / CMAC
test_hmac.c (+259): HmacSizeByType, HmacCopy, HmacInit_Id/_Label, HmacFree cleanup, HKDF NULL edge cases (drove hmac.c to 100%). test_cmac.c (+414): empty-message / NULL-outSz / small-tag pairs plus CMAC_Grow, InitCmac_Id/_Label, AesCmacGenerate/Verify DecisionCoverage. test_cmac_whitebox.c (+204): the static _InitCmac_common id/label paths, each paired with a same-binary all-false baseline (the cross-binary MC/DC-merge gotcha).
Curve25519 / Ed25519
test_curve25519.c (+453): make_priv, import_public_ex, check_public LE/BE boundaries, generic/generic_blind, set_rng, the full WC_X25519_NONBLOCK state machine. test_ed25519.c (+473): ctx/ph sign+verify, streaming verify_init/update/final incl. the S-order boundary, check_key, import variants, make_public arg-checks. White-boxes test_curve25519_whitebox.c (+246) / test_ed25519_whitebox.c (+148) for internal static guards.
DH / DSA
test_dh.c (+850): 12 DecisionCoverage functions — SetKey family, named-group helpers, GenerateKeyPair/GeneratePublic plus a full multi-group generate+agree(+CT) round trip, the WC_DH_NONBLOCK state machine, import/export key-pair, CheckPubKey/CheckPrivKey/CheckKeyPair (+WOLFSSL_VALIDATE_DH_KEYGEN), GenerateParams/ExportParamsRaw, CheckDhLN divLen pair. test_dsa.c (+305): Sign/Verify digest-size bad-args, per-arg NULL isolation for the import/export-params/export-key-raw calls, CheckDsaLN divLen pair. (No white-box needed — all decisions API-reachable.)
Random (random.c)
test_random.c (+404): RNG_HealthTest_SHA256/512_Ext (the ACVP _ex/_ex2 entry points), RNG_SeedCb, RNG_CustomRandBlock, RNG_DrbgDisable, extended HealthTest bad-parameter cases. test_random_whitebox.c (+224): the Hash_gen/Hash512_gen and array_add internal false-sides.
Net campaign result
union MC/DC of 1,875 / 2,609 conditions (71.9%) across those 14 files, with four modules (chacha, hmac, cmac, sha3) at 100%. The tests/unit-mcdc/ binaries are the reusable white-box machinery; the tests/api/ additions integrate into wolfSSL's normal test groups.
Commit recap:
02441c4 tests: MC/DC decision coverage for random.c (Hash_DRBG + seed layer)
bae034a tests: MC/DC decision coverage for dh.c and dsa.c
8fc164c tests: MC/DC decision coverage for curve25519.c and ed25519.c
7da1a94 tests: MC/DC decision coverage for hmac.c and cmac.c
617d8fa tests: MC/DC decision coverage for chacha.c and poly1305.c
000bc45 tests/ecc: MC/DC decision coverage + white-box for wolfcrypt/src/ecc.c
f75d0d2 tests: add sp_int.c (sp-math module) MC/DC DecisionCoverage + white-box
c7c9dba tests/rsa: MC/DC decision + white-box coverage for wolfcrypt/src/rsa.c
35a257a tests/unit-mcdc: aarch64 hw-crypto white-box supplements (qemu lane)
4cb8ccc sha: reorder update arg guards to make the empty-update decision coverable
befc8db tests: cover the AES-EAX streaming Update authIn arg-check
3102b88 tests/unit-mcdc: add SHA intel-dispatch white-box supplements
Surfaced defects
See PR #10875