Repository navigation
Conversation
plat_local.h tests __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__ without checking that the macros exist. MSVC defines neither, so the preprocessor replaces both with 0 and the condition is true. The byte-swap helpers rev8_be32 and rev8_be64 then become no-ops on little-endian MSVC targets, and SLH-DSA computes non-standard results. Guard both tests with defined(...) so that the byte-swapping versions are used when the macros are missing. Tested with MSVC 19.44 (x64): building xfips205 and running the ACVP keyGen vectors (v1.1.0.40) gives 0/120 passes before this change (SHA2 0/60, SHAKE 0/60) and 120/120 after (60/60 each). Signed-off-by: MrWater00 <amansingh15605@gmail.com>
I think that would be a good idea: if a compiler lacks the GCC macros, the code now assumes little-endian with no warning. |
That would be great to have too! |
|
Do you think we should add |
mkannwischer
left a comment
There was a problem hiding this comment.
Thanks @MrWater00. Do you mind aligning this with mlkem-native?
There should be centralized macro for detecting endianness. If endianness cannot be detected, we should use portable code.
|
Thanks for the reviews, and agreed. I'll rework this:
|
Move endianness detection into slh_sys.h, following mlkem-native and mldsa-native: use __BYTE_ORDER__ when the compiler provides it, and assume little endian for MSVC on x86, x64 and ARM64, which does not define it. plat_local.h now selects rev8_be32 and rev8_be64 from SLH_SYS_BIG_ENDIAN / SLH_SYS_LITTLE_ENDIAN. If the endianness cannot be detected, they use portable code that checks the byte order at run time instead of assuming little endian. Tested with MSVC 19.44 (x64): the ACVP keyGen vectors (v1.1.0.40) pass 120/120. Signed-off-by: MrWater00 <amansingh15605@gmail.com>
|
Thanks for the reviews. I reworked the change and pushed it as a second commit:
Testing:
On I'll open the Windows/MSVC CI job as a separate PR after this one. |
mkannwischer
left a comment
There was a problem hiding this comment.
If I see correctly, we are currently not testing on a big endian platform. Could you please port the big endian tests from mlkem-native? https://github.com/pq-code-package/mlkem-native/blob/c2827a8e8be4cd09b20dfe3544fe854777bcaefb/.github/workflows/ci.yml#L108
| static SLH_INLINE int plat_is_little_endian(void) | ||
| { | ||
| const uint16_t one = 1; | ||
| return *(const uint8_t *)&one == 1; | ||
| } |
There was a problem hiding this comment.
Instead of detecting endianness at runtime, I'd prefer a portable version:
static SLH_INLINE uint32_t rev8_be32(uint32_t x)
{
const uint8_t *p = (const uint8_t *)&x;
return ((uint32_t)p[0] << 24) | ((uint32_t)p[1] << 16) |
((uint32_t)p[2] << 8) | (uint32_t)p[3];
}There was a problem hiding this comment.
Done in 63ed897: replaced the run-time check with your portable version, and
used the same pattern for rev8_be64.
| #if defined(SLH_SYS_BIG_ENDIAN) | ||
| /* nop */ | ||
| #define rev8_be32(x) (x) | ||
| #define rev8_be64(x) (x) |
There was a problem hiding this comment.
I believe introducing 3 code paths here is a risk that's not really justified.
Can we have two implementations: one little endian and one portable, please?
There was a problem hiding this comment.
Done in 63ed897: there are two implementations now. The little-endian
shift/mask version is selected by SLH_SYS_LITTLE_ENDIAN, and the portable
version is used otherwise. SLH_SYS_BIG_ENDIAN is still defined in slh_sys.h,
as in mlkem-native, but plat_local.h no longer uses it, so big-endian hosts
take the portable path.
mkannwischer
left a comment
There was a problem hiding this comment.
If I see correctly, we are currently not testing on a big endian platform. Could you please port the big endian tests from mlkem-native? https://github.com/pq-code-package/mlkem-native/blob/c2827a8e8be4cd09b20dfe3544fe854777bcaefb/.github/workflows/ci.yml#L108
I'll do that as a follow-up. I see that there are more big endian issues. |
Address review feedback: instead of three code paths (big-endian no-op, little-endian swap and run-time detection), use two: - SLH_SYS_LITTLE_ENDIAN: byte swap with shifts and masks. - Otherwise: portable code that reads the bytes of the argument and assembles the value in big-endian order, independent of the host byte order. Signed-off-by: MrWater00 <amansingh15605@gmail.com>
|
Re-tested after the rework:
I have not tested on a big-endian machine. Thanks for taking the big-endian CI |
Problem
plat_local.hselects the byte-swap helpers with#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__without checking that the macros exist. MSVC defines neither, so the preprocessor replaces both with 0 (warning C4668), the condition is true, and
rev8_be32/rev8_be64become no-ops on little-endian MSVC targets. The SHA2 core and the address helpers inslh_adrs.hthen work with the wrong byte order, and the library produces non-standard results.Change
Guard both tests with
defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__), so the byte-swapping versions are used when the macros are missing. No other lines change.Testing
xfips205from the root sources plustest/xfips205.cwithcl /O2, running the existing ACVP keyGen vectors (v1.1.0.40) throughtest/acvp_client.pywith the binary path redirected:plat_local.hlines 110 and 123 disappearmake(with the project's-Werror -pedanticflags) andmake test: 1248/1248 PASS.I only ran keyGen on MSVC:
acvp_client.pypasses sigGen/sigVer data on the command line, which exceeds thecmd.exelength limit on Windows for sigVer. I did not test 32-bit MSVC.Notes
SLH_DSA_PURE_SHA2_*signatures failed to verify on MSVC builds (SLH-DSA SHA2 parameter sets fail signature verification on Windows/MSVC build (SHAKE variants unaffected) open-quantum-safe/liboqs#2516). The liboqs maintainers asked for the fix to land here first.plat_local.h(64)also triggers C4668 for__WORDSIZEon MSVC. It falls through to the 64-bit default, which is right for x64, so I left it alone..github/workflows. I'm happy to add one in a separate PR if you want it.defined(__BYTE_ORDER__)check plus an MSVC little-endian fallback for x86/x64/ARM64), I can rework the change that way.