mirror of
https://github.com/wolfSSL/wolfssl.git
synced 2026-08-17 04:01:36 +02:00
Under WC_C_DYNAMIC_FALLBACK, SAVE_VECTOR_REGISTERS2() can fail on any call, so two calls on the same object can dispatch differently. Each of these algorithms had state that silently assumed a single dispatch for its lifetime. wolfcrypt/src/wc_mldsa.c: add MLDSA_NTT_AVX2()/MLDSA_INVNTT_AVX2() selecting the "full" AVX2 NTT/invNTT under WC_C_DYNAMIC_FALLBACK. The non-full variants leave NTT-domain coefficients in a permuted, lane-interleaved order that only their matching consumers understand, whereas the full variants and the C implementations use standard order. NTT-domain data at rest (cached s1/s2/t0 vectors, the challenge polynomial) can be produced and consumed by differently-dispatched calls, so its representation must be dispatch-invariant. Without fallback, dispatch is invariant and the ~2%/~4% faster permuted-order variants are kept. Both pipelines are bit-identical end to end. wolfcrypt/src/wc_mlkem_poly.c: in mlkem_derive_secret(), re-initialize the shared SHAKE-256 object under WC_C_DYNAMIC_FALLBACK. The buffer-stuffing shortcut assumes a freshly initialized (zeroed) sponge, which no longer holds once the C fallback legs of mlkem_gen_matrix()/mlkem_get_noise() drive the XOF on that object and leave it mid-squeeze. wolfcrypt/src/wc_slhdsa.c: in slhdsakey_fors_sign(), replace the CAN_SAVE_VECTOR_REGISTERS() test with an actual SAVE_VECTOR_REGISTERS2() == 0 acquisition and a matching RESTORE_VECTOR_REGISTERS(), so the region is held rather than merely predicted to be available. wolfcrypt/src/wc_frodokem_mat.c: in the AES row kernels of frodokem_mul_add_as_plus_e_aes() and frodokem_mul_add_sa_plus_e_aes(), re-key with wc_AesSetKeyDirect() when IS_INTEL_AESNI() but !aes->use_aesni. The kernels consume aes->key directly, which holds an AES-NI-layout schedule only if SetKey ran with vector registers available; under fallback a failed SAVE_VECTOR_REGISTERS2() inside SetKey returns success having keyed only the C-fallback schedule. Re-keying happens inside the held region, where the nested save always succeeds. Loop conditions gain (ret == 0) so a re-key failure stops the run. wolfssl/wolfcrypt/settings.h: with the above, ML-KEM, ML-DSA, SLH-DSA and FrodoKEM are fuzzer-clean, so the DEBUG_VECTOR_REGISTER_ACCESS_FUZZING exclusion narrows from the _WC_BUILDING_WC_MLKEM_POLY_C / _WC_BUILDING_WC_MLDSA_C / _WC_BUILDING_WC_SLHDSA_C set to _WC_BUILDING_FALCON_C alone. Falcon stays excluded because it uses FP or vector registers in all of its asm implementations and there is no option yet to build the C-no-FP implementation alongside them. tests/api/test_mldsa.c: in test_mldsa_encode_w1_large_values(), pin dispatch to the C path with WC_DEBUG_SET_VECTOR_REGISTERS_RETVAL() for the duration of the test and restore it afterward. The two calls being compared are only specified -- and only equal -- on the valid input domain, so letting the fuzzer send them down different (AVX2 vs C) implementations is not a meaningful comparison.