Skip to content

Fix unaligned memory access in ML-DSA#10816

Open
kojiws wants to merge 1 commit into
wolfSSL:masterfrom
kojiws:fix_mem_cast_on_mldsa
Open

Fix unaligned memory access in ML-DSA#10816
kojiws wants to merge 1 commit into
wolfSSL:masterfrom
kojiws:fix_mem_cast_on_mldsa

Conversation

@kojiws

@kojiws kojiws commented Jun 30, 2026

Copy link
Copy Markdown
Contributor

Description

Fix unaligned memory access in ML-DSA (Dilithium) encoding and decoding functions in wc_mldsa.c. Direct casts between byte* and (s)word32*/word16* are replaced with writeUnalignedWord32, readUnalignedWord32, writeUnalignedWord16 and readUnalignedWord16, which are safe on strict-alignment platforms such as ARM and AArch64. readUnalignedWord16/writeUnalignedWord16 are newly added to misc.c/misc.h, following the existing patterns of the word32/word64 helpers.

L2292 (WOLFSSL_MLDSA_ALIGNMENT <=4) and L2378 (<=8) are the cases that matter on real hardware: thise blocks are compiled on ARM 32-bit and AArch64 respectively, so the unaligned cast can cause a fault there.

The parts guarded by WOLFSSL_MLDSA_ALIGNMENT == 0 or <=2 don't cause faults, because those values are only used on x86/x64 and Apple AArch64 platforms that handle unaligned access in hardware. They are still fixed here to remove the undefined behavior and keep -Werror=cast-align clean across all configurations.

All cast-align compilation errors in wc_mldsa.c reproduced with the procedure below are fixed by this PR.
(An error also comes up in the misc.c, it's out of scope in this PR.)

  • ./configure with the patterns of the options below
    • --enable-mldsa CPPFLAGS="-DWOLFSSL_MLDSA_ALIGNMENT=0 -DWC_32BIT_CPU" CFLAGS="-Werror=cast-align"
    • --enable-mldsa CPPFLAGS="-DWOLFSSL_MLDSA_ALIGNMENT=0 -DWOLFSSL_MLDSA_NO_LARGE_CODE" CFLAGS="-Werror=cast-align"
    • --enable-mldsa CPPFLAGS="-DWOLFSSL_MLDSA_ALIGNMENT=0 -D WOLFSSL_MLDSA_SMALL" CFLAGS="-Werror=cast-align"
  • make wolfcrypt/src/wc_mldsa.o

Here is the solved error list.
(The locations are shifted by rebasing to master.)

wolfcrypt/src/wc_mldsa.c:1407:18: error: cast from 'byte *' (aka 'unsigned char *') to 'word32 *'
      (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 1407 |             tp = (word32*)t0;
      |                  ^~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:1433:18: error: cast from 'byte *' (aka 'unsigned char *') to 'word32 *'
      (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 1433 |             tp = (word32*)t1;
      |                  ^~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:1635:23: error: cast from 'const byte *' (aka 'const unsigned char *') to
      'const word16 *' (aka 'const unsigned short *') increases required alignment from 1 to 2 [-Werror,-Wcast-align]
 1635 |         word16 t16 = *(const word16*)(t1 + 8);
      |                       ^~~~~~~~~~~~~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:1771:24: error: cast from 'byte *' (aka 'unsigned char *') to 'word64 *'
      (aka 'unsigned long *') increases required alignment from 1 to 8 [-Werror,-Wcast-align]
 1771 |         word64* s64p = (word64*)s;
      |                        ^~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:1775:24: error: cast from 'byte *' (aka 'unsigned char *') to 'word32 *'
      (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 1775 |         word32* s32p = (word32*)s;
      |                        ^~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:1839:24: error: cast from 'byte *' (aka 'unsigned char *') to 'word16 *'
      (aka 'unsigned short *') increases required alignment from 1 to 2 [-Werror,-Wcast-align]
 1839 |         word16* s16p = (word16*)s;
      |                        ^~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:1841:24: error: cast from 'byte *' (aka 'unsigned char *') to 'word64 *'
      (aka 'unsigned long *') increases required alignment from 1 to 8 [-Werror,-Wcast-align]
 1841 |         word64* s64p = (word64*)s;
      |                        ^~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:1845:24: error: cast from 'byte *' (aka 'unsigned char *') to 'word32 *'
      (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 1845 |         word32* s32p = (word32*)s;
      |                        ^~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2088:29: error: cast from 'const byte *' (aka 'const unsigned char *') to
      'const word16 *' (aka 'const unsigned short *') increases required alignment from 1 to 2 [-Werror,-Wcast-align]
 2088 |             word16 s16_0 = ((const word16*)s)[4];
      |                             ^~~~~~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2129:29: error: cast from 'const byte *' (aka 'const unsigned char *') to
      'const word16 *' (aka 'const unsigned short *') increases required alignment from 1 to 2 [-Werror,-Wcast-align]
 2129 |             word16 s16_0 = ((const word16*)s)[4];
      |                             ^~~~~~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2130:29: error: cast from 'const byte *' (aka 'const unsigned char *') to
      'const word16 *' (aka 'const unsigned short *') increases required alignment from 1 to 2 [-Werror,-Wcast-align]
 2130 |             word16 s16_1 = ((const word16*)s)[9];
      |                             ^~~~~~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2292:25: error: cast from 'byte *' (aka 'unsigned char *') to 'word32 *'
      (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 2292 |         word32* w1e32 = (word32*)w1e;
      |                         ^~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2378:25: error: cast from 'byte *' (aka 'unsigned char *') to 'word32 *'
      (aka 'unsigned int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 2378 |         word32* w1e32 = (word32*)w1e;
      |                         ^~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2556:31: error: cast from 'byte *' (aka 'unsigned char *') to 'sword32 *'
      (aka 'int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 2556 |                 sword32 t = *((sword32*)(h + c)) & 0x7fffff;
      |                               ^~~~~~~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2594:27: error: cast from 'byte *' (aka 'unsigned char *') to 'sword32 *'
      (aka 'int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 2594 |             sword32 t = *((sword32*)(h + c)) & 0x7fffff;
      |                           ^~~~~~~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2610:27: error: cast from 'byte *' (aka 'unsigned char *') to 'sword32 *'
      (aka 'int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 2610 |             sword32 t = *((sword32*)(h + c)) & 0x7fffff;
      |                           ^~~~~~~~~~~~~~~~~
wolfcrypt/src/wc_mldsa.c:2713:31: error: cast from 'byte *' (aka 'unsigned char *') to 'sword32 *'
      (aka 'int *') increases required alignment from 1 to 4 [-Werror,-Wcast-align]
 2713 |                 sword32 t = *((sword32*)(h + c)) & 0x7fffff;
      |                               ^~~~~~~~~~~~~~~~~

Testing

  • ./configure with the patterns of the options below
    • On AArch64 Mac
      • ./configure --enable-mldsa CPPFLAGS="-DWOLFSSL_MLDSA_ALIGNMENT=0"
      • ./configure --enable-mldsa CPPFLAGS="-DWOLFSSL_MLDSA_ALIGNMENT=0 -DWOLFSSL_MLDSA_NO_LARGE_CODE"
      • ./configure --enable-mldsa CPPFLAGS="-DWOLFSSL_MLDSA_ALIGNMENT=0 -DWOLFSSL_MLDSA_SMALL"
      • ./configure --enable-mldsa
    • On ARM32
      • ./configure --enable-mldsa
  • make clean && make && ./wolfcrypt/test/testwolfcrypt

Checklist

  • added tests
  • updated/added doxygen
  • updated appropriate READMEs
  • Updated manual and documentation

@kojiws kojiws self-assigned this Jun 30, 2026
@kojiws kojiws force-pushed the fix_mem_cast_on_mldsa branch from 7f61577 to 93bdf07 Compare July 2, 2026 06:46
@kojiws kojiws marked this pull request as ready for review July 2, 2026 10:20
@github-actions

github-actions Bot commented Jul 2, 2026

Copy link
Copy Markdown

retest this please

@kojiws kojiws force-pushed the fix_mem_cast_on_mldsa branch from 93bdf07 to e1b394a Compare July 2, 2026 13:24
@kojiws kojiws requested a review from wolfSSL-Fenrir-bot July 2, 2026 23:12

@wolfSSL-Fenrir-bot wolfSSL-Fenrir-bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fenrir Automated Review — PR #10816

Scan targets checked: wolfcrypt-bugs, wolfcrypt-rs-bugs, wolfcrypt-src, wolfssl-bugs, wolfssl-src

No new issues found in the changed files. ✅

@kojiws kojiws assigned wolfSSL-Bot and unassigned kojiws Jul 2, 2026
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.

4 participants