Skip to content

IA_ASM: SHA-NI and AES-NI intrinsics miscompiled by GCC on Linux despite #pragma GCC target #41

Description

@dnovick

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:

  1. Correcting the SHA-NI state load/store shuffles (verified correct against noloader/SHA-Intrinsics reference)
  2. Adding `[[gnu::target("sha,ssse3,sse4.1")]]` to all callers of `sha256_compress`
  3. Adding `[[gnu::noinline]]` to `sha256_compress`
  4. Adding `#pragma GCC target` in each individual header
  5. 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

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions