Summary
Intel SHA-NI (SHA-256) and AES-NI/PCLMULQDQ (AES-256-GCM) intrinsics produce incorrect output when compiled by GCC on Linux, despite the provider being configured with `-msha -maes -mpclmul` etc. via CMake `target_compile_options`.
Both acceleration paths have been temporarily disabled on Linux CI via new CMake options:
- `SAFE_CRYPTO_IA_ASM_SHA_NI=OFF` — falls back to portable scalar SHA-256
- `SAFE_CRYPTO_IA_ASM_AES_NI=OFF` — skips the CrossProviderAesGcmTests
Symptoms
- SHA-256 produces deterministically wrong output (e.g. `273DC2FA...` instead of `E3B0C442...` for the empty message) regardless of code changes to the load/store/round logic.
- AES-256-GCM cross-provider parity tests fail — IA_ASM ciphertext doesn't match PSA/ARM_ASM reference.
- Wrong output is byte-for-byte identical across multiple CI runs and code changes, ruling out data-dependent bugs.
Investigation so far
The following approaches were tried and had no effect on the wrong output:
- Correcting the SHA-NI state load/store shuffles (verified correct against noloader/SHA-Intrinsics reference)
- Adding `[[gnu::target("sha,ssse3,sse4.1")]]` to all callers of `sha256_compress`
- Adding `[[gnu::noinline]]` to `sha256_compress`
- Adding `#pragma GCC target` in each individual header
- Consolidating `#pragma GCC target("aes,sha,pclmul,ssse3,sse4.1")` into `defs.hpp` (included by every IA_ASM header)
The fact that no code change affects the output strongly suggests the intrinsics are being silently replaced with incorrect emulation or that the target ISA is not being activated for the compiled functions despite the pragma.
Environment
- Compiler: GCC 13.3.0 (ubuntu-latest runner)
- `-march=x86-64-v2 -maes -msha -mpclmul -mssse3` via CMake INTERFACE options
- All code is header-only (INTERFACE library)
Next steps
- Investigate whether GCC 13 has a known bug with `#pragma GCC target` in header-only INTERFACE libraries
- Try moving the intrinsic implementations into a `.cpp` file to test whether the header-only model is the root cause
- Test with a newer GCC version (14/15) to see if the issue is version-specific
- Consider whether `attribute((target(...)))` on the function definitions (not declarations) behaves differently
Summary
Intel SHA-NI (SHA-256) and AES-NI/PCLMULQDQ (AES-256-GCM) intrinsics produce incorrect output when compiled by GCC on Linux, despite the provider being configured with `-msha -maes -mpclmul` etc. via CMake `target_compile_options`.
Both acceleration paths have been temporarily disabled on Linux CI via new CMake options:
Symptoms
Investigation so far
The following approaches were tried and had no effect on the wrong output:
The fact that no code change affects the output strongly suggests the intrinsics are being silently replaced with incorrect emulation or that the target ISA is not being activated for the compiled functions despite the pragma.
Environment
Next steps