Skip to content

x86_64 asm: load 32-bit parameters as 32-bit and ArrowLake/LunarLake change - #11986

Open
SparkiDev wants to merge 1 commit into
wolfSSL:masterfrom
SparkiDev:intel_asm_arrowlake
Open

SparkiDev wants to merge 1 commit into
wolfSSL:masterfrom
SparkiDev:intel_asm_arrowlake

Conversation

@SparkiDev

Copy link
Copy Markdown
Contributor

Description

On Windows x64, chacha20_poly1305_small_enc/_dec read the word32 mLen argument from the stack with a QWORD load. MSVC writes only the low dword of that slot, so the upper half came from the caller's stack contents and corrupted the length. Encrypting or decrypting <= 64 bytes crashed when that stack slot was non-zero. The SysV build was not affected.

The same QWORD load of a 32-bit stack parameter is also fixed in chacha20_poly1305_avx512/_ifma/_ifma_decrypt, the SHA-3 LMS/XMSS x4/x8 block functions, FrodoKEM, and ML-KEM keygen/encapsulate/decapsulate. In the .S files, register moves of 32-bit parameters become 32-bit (movl), which zero-extends them.

Every changed 32-bit parameter was checked against its C prototype: all are non-pointer 32-bit scalars.

On Intel Arrow Lake the VAES AES code is no faster than the AVX2/AES-NI code, and the single-stream AVX2 SHA-3 block is slower than the BMI2 and C blocks. Lunar Lake uses the same cores and is treated the same way.

Add two tuning bits to the Intel cpuid flags. They are not instruction set features: they mark a CPU where an implementation the feature bits allow is measured to be slower than a narrower one.
CPUID_SLOW_VAES AES does not use VAES
CPUID_SLOW_AVX2_SHA3 SHA-3 and ML-DSA do not use the AVX2 Keccak block

cpuid.c sets both from the family/model on Intel family 6 models 0xB5, 0xC5, 0xC6 (Arrow Lake U/H/S) and 0xBD (Lunar Lake M). Define WC_CPUID_NO_TUNING to turn this off. The bits can also be changed at run time with cpuid_set_flag()/cpuid_clear_flag(). The CPUID_VAES and CPUID_AVX2 feature bits are unchanged, so FrodoKEM, ChaCha20 and Poly1305 dispatch as before.

aes.c: all VAES selection goes through AES_USE_VAES(f), which is false when CPUID_SLOW_VAES is set. This covers ECB, CBC, CTR, GCM, XTS and AES-GCM-SIV (CTR and POLYVAL). Those CPUs fall back to the AVX2 / AVX1 / AES-NI code.

sha3.h: SHA3_USE_AVX2() also requires !IS_CPU_SLOW_AVX2_SHA3(f), so ML-DSA, which selected the AVX2 block first on Intel, uses BMI2 instead. SHA-3 already preferred BMI2. WOLFSSL_SHA3_AVX2 still forces AVX2. The 4-way AVX2 Keccak and the ML-DSA AVX2 NTT/poly code are unchanged.

Fixes zd#22620

Testing

Intel x86_64.
Whitebox testing covers different flags.

@SparkiDev SparkiDev self-assigned this Nov 4, 2026
Copilot AI balanced review requested due to automatic review settings November 4, 2026 00:48
@SparkiDev

Copy link
Copy Markdown
Contributor Author

Code generated with PR:
https://github.com/wolfSSL/scripts/pull/705

@github-actions

github-actions Bot commented Nov 4, 2026 •

Copy link
Copy Markdown

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.

🟡 Changes recommended

AES tests never force CPUID_SLOW_VAES, leaving the new tuning-controlled VAES fallback untested, including ciphertext and tag checks for streaming GCM and GCM-SIV at dispatch-threshold sizes.

1 open issue
What changed in this PR

This PR corrects 32-bit argument handling in wolfCrypt’s x86_64 assembly, addressing Windows x64 crashes, and tunes AES and single-stream Keccak dispatch for Intel Arrow Lake and Lunar Lake.

Changes:

  • Use 32-bit loads and register moves for 32-bit scalar parameters.
  • Add CPU tuning flags that avoid slower implementations without changing instruction-feature flags.
  • Report tuning flags in benchmarks and extend SHA-3/ML-DSA white-box dispatch tests.
File Description
wolfssl/​wolfcrypt/​sha3.h Honor the slow-AVX2 Keccak tuning flag.
wolfssl/​wolfcrypt/​cpuid.h Define tuning flags and access macros.
wolfcrypt/​src/​wc_mlkem_asm.S Correct ML-KEM scalar argument widths.
wolfcrypt/​src/​wc_mlkem_asm.asm Correct Windows ML-KEM stack loads.
wolfcrypt/​src/​wc_mldsa_asm.S Correct ML-DSA scalar register moves.
wolfcrypt/​src/​wc_mldsa_asm.asm Correct Windows ML-DSA scalar moves.
wolfcrypt/​src/​wc_frodokem_asm.S Correct FrodoKEM scalar stack loads.
wolfcrypt/​src/​wc_frodokem_asm.asm Correct Windows FrodoKEM scalar loads.
wolfcrypt/​src/​sha512_asm.S Use 32-bit SHA-512 length moves.
wolfcrypt/​src/​sha512_asm.asm Correct Windows SHA-512 length moves.
wolfcrypt/​src/​sha3_asm.asm Correct LMS/XMSS scalar stack loads.
wolfcrypt/​src/​sha256_asm.S Use 32-bit SHA-256 length moves.
wolfcrypt/​src/​sha256_asm.asm Correct Windows SHA-256 length moves.
wolfcrypt/​src/​cpuid.c Detect targeted Intel models and set tuning flags.
wolfcrypt/​src/​chacha_asm.asm Correct Windows ChaCha20-Poly1305 length loads.
wolfcrypt/​src/​aes.c Apply tuning-aware selection across VAES paths.
wolfcrypt/​src/​aes_xts_asm.S Correct AES-XTS length register moves.
wolfcrypt/​src/​aes_xts_asm.asm Correct Windows AES-XTS length moves.
wolfcrypt/​src/​aes_gcm_asm.asm Correct AES-GCM round-count moves.
wolfcrypt/​benchmark/​benchmark.c Display active CPU tuning flags.
tests/​unit-mcdc/​test_wc_mldsa_whitebox.c Add tuning-controlled Keccak dispatch coverage.
tests/​unit-mcdc/​test_sha3_whitebox.c Exercise the slow-AVX2 SHA-3 flag.

Review effort: Balanced

Comment thread wolfcrypt/src/aes.c Resolved
@SparkiDev
SparkiDev force-pushed the intel_asm_arrowlake branch from 1a401b3 to 4ad3ad0 Compare November 4, 2026 01:13
@SparkiDev

Copy link
Copy Markdown
Contributor Author

Jenkins: retest this please

…change

On Windows x64, chacha20_poly1305_small_enc/_dec read the word32 mLen
argument from the stack with a QWORD load. MSVC writes only the low
dword of that slot, so the upper half came from the caller's stack
contents and corrupted the length. Encrypting or decrypting <= 64 bytes
crashed when that stack slot was non-zero. The SysV build was not
affected.

The same QWORD load of a 32-bit stack parameter is also fixed in
chacha20_poly1305_avx512/_ifma/_ifma_decrypt, the SHA-3 LMS/XMSS x4/x8
block functions, FrodoKEM, and ML-KEM keygen/encapsulate/decapsulate.
In the .S files, register moves of 32-bit parameters become 32-bit
(movl), which zero-extends them.

Every changed 32-bit parameter was checked against its C prototype: all
are non-pointer 32-bit scalars.

On Intel Arrow Lake the VAES AES code is no faster than the AVX2/AES-NI
code, and the single-stream AVX2 SHA-3 block is slower than the BMI2 and
C blocks. Lunar Lake uses the same cores and is treated the same way.

Add two tuning bits to the Intel cpuid flags. They are not instruction
set features: they mark a CPU where an implementation the feature bits
allow is measured to be slower than a narrower one.
  CPUID_SLOW_VAES       AES does not use VAES
  CPUID_SLOW_AVX2_SHA3  SHA-3 and ML-DSA do not use the AVX2 Keccak block

cpuid.c sets both from the family/model on Intel family 6 models 0xB5,
0xC5, 0xC6 (Arrow Lake U/H/S) and 0xBD (Lunar Lake M). Define
WC_CPUID_NO_TUNING to turn this off. The bits can also be changed at
run time with cpuid_set_flag()/cpuid_clear_flag(). The CPUID_VAES and
CPUID_AVX2 feature bits are unchanged, so FrodoKEM, ChaCha20 and
Poly1305 dispatch as before.

aes.c: all VAES selection goes through AES_USE_VAES(f), which is false
when CPUID_SLOW_VAES is set. This covers ECB, CBC, CTR, GCM, XTS and
AES-GCM-SIV (CTR and POLYVAL). Those CPUs fall back to the AVX2 / AVX1
/ AES-NI code.

sha3.h: SHA3_USE_AVX2() also requires !IS_CPU_SLOW_AVX2_SHA3(f), so
ML-DSA, which selected the AVX2 block first on Intel, uses BMI2
instead. SHA-3 already preferred BMI2. WOLFSSL_SHA3_AVX2 still forces
AVX2. The 4-way AVX2 Keccak and the ML-DSA AVX2 NTT/poly code are
unchanged.
@SparkiDev
SparkiDev force-pushed the intel_asm_arrowlake branch from 4ad3ad0 to e29b951 Compare November 4, 2026 05:10
@SparkiDev

Copy link
Copy Markdown
Contributor Author

Jenkins: retest this please

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