Fix big-endian IV initialization in opt8/opt8_lowsize AEAD128 - #30
Fix big-endian IV initialization in opt8/opt8_lowsize AEAD128#30Scottcjn wants to merge 3 commits into
Conversation
The byte-oriented opt8 and opt8_lowsize implementations keep the sponge state as a little-endian byte array: the key and nonce are inserted as raw bytes and the permutation operates on the byte view. The IV, however, is assigned as a numeric 64-bit constant (s->x[0] = ASCON_128_IV). On a little-endian host the numeric word and the byte-array view agree, so the code works. On big-endian they disagree, the initial state is laid out with the IV bytes reversed, and every test vector fails. Route the IV through the same U64TOWORD conversion that LOADBYTES already applies to every other word, so the IV byte layout matches the rest of the state on both endiannesses. U64TOWORD is identity on little-endian, so this is a no-op there. Verified against the NIST KAT on native ppc64 big-endian hardware and on big-endian MIPS under qemu: the genkat self-test goes from failing to passing for both implementations, with ref unchanged as a control. Part of ascon#25.
The byte-oriented opt8 and opt8_lowsize implementations of Ascon-Hash256 and Ascon-XOF128 had the same big-endian defect as the AEAD128 ones: the initial state words come from numeric IV constants (via the IV() macro) without the U64TOWORD conversion the byte path uses everywhere else, so on big-endian the initial state is laid out wrong and the KAT fails. Wrap the IV macro in U64TOWORD so the constants match the byte-array layout on both endiannesses. No-op on little-endian. Verified with genkat on big-endian MIPS under qemu: Hash256 and XOF128 opt8/opt8_lowsize go from failing to passing.
|
Expanded this PR to cover the full byte-oriented opt8 family, since they share the exact same root cause:
For the hash/XOF ones the IV enters via the Still outstanding (happy to follow up or extend here, your call)The bit-interleaved |
The crypto_*/.../opt8 trees are generated from src/ via scripts/copy_src_to_crypto.sh, so fixing only the generated copies would be reverted on the next regeneration. Apply the identical U64TOWORD wrap to the canonical src/opt8 and src/opt8_lowsize aead.c and hash.c so the source of truth matches and the fix survives a copy_src_to_crypto run.
|
Follow-up: I also applied the identical fix to the canonical |
This addresses #25 for the byte-oriented
opt8andopt8_lowsizeAEAD128 implementations.Root cause
These implementations keep the sponge state as a little-endian byte array: the key and nonce go in as raw bytes (
INSERT/memcpy) and the permutation operates on the byte view. The IV, though, is assigned as a numeric 64-bit constant:On little-endian the numeric word and the byte-array view agree, so it works. On big-endian they disagree: the IV bytes get laid out reversed relative to the rest of the state, the initial state is wrong, and every test vector fails.
Fix
Route the IV through the same
U64TOWORDconversion thatLOADBYTESalready applies to every other word, so the IV byte layout matches the rest of the state on both endiannesses.U64TOWORDis identity on little-endian, so this is a no-op there.Verification
Reproduced and verified with the project's own
genkatself-test, built with-DREL_FLAGS="-std=c99;-O2;-fomit-frame-pointer"(dropping-march=nativefor cross builds):Before the fix
opt8/opt8_lowsizefail the KAT; after, they pass.refpasses throughout as a control.Scope / follow-up
This PR covers the AEAD128 byte-oriented impls. The same root cause affects the
Hash256/XOF128byte-oriented impls (different IV-init path) and the bit-interleavedbi8/bi32family (which needs an interleaving-aware fix, not just the IV wrap). Happy to extend this PR to those or send follow-ups, whichever you prefer.