Michael Weiser michael@weiser.dinsnail.net writes:
What board and linux (dist?) are you running this on?
I have a number of Cubieboard2s that run Gentoo Linux with a vanilla, mainline Linus kernel.
# uname -a Linux b 4.15.0-gentoo #2 SMP Sun Feb 4 18:46:30 CET 2018 armv7b ARMv7 Processor rev 4 (v7b) Allwinner sun7i (A20) Family GNU/Linux
The only difference between little- and big-endian boards is the following Linux kernel config options:
-# CONFIG_CPU_BIG_ENDIAN is not set +CONFIG_CPU_BIG_ENDIAN=y +CONFIG_CPU_ENDIAN_BE8=y
This makes the kernel switch the CPU to big-endian mode on boot. Userland is big-endian as well.
Cool.
What's the host triplet?
armv7veb-hardfloat-linux-gnueabi
^^
And the "eb" is for big-endian?
Are you cross compiling, or compiling natively?
It's all native on the board. I have a cross-toolchain and qemu on standby on x86_64 if necessary.
Does configure detect it as big-endian (check for WORDS_BIGENDIAN in config.h)?
It seems so:
nettle-3.4 # grep WORDS_BIG config.h /* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most # define WORDS_BIGENDIAN 1 # ifndef WORDS_BIGENDIAN # define WORDS_BIGENDIAN 1
Can you check if it's detected correctly also when cross-compiling?
Which of nettle's own tests (make check) fail?
With --disable-assembler all checks pass. Here's the make check output with arm asm:
FAIL: chacha
The chacha code doesn't look endian-dependent to me. I'd guess it's a consequence of incorrect memxor (below).
FAIL: memxor
This also does some tricks with word reads and rotate. (The C code does that too, but with conditions on WORDS_BIGENDIAN).
FAIL: hkdf
Probably due to broken sha1 or sha256.
FAIL: sha1
This one you have already looked into.
FAIL: sha256
Similar problems.
FAIL: umac
Similar problem, I would guess. But this time, loading 64 bits at a time into neon registers.
The remaining failures are most likely not independent issues.
Yes, the masking and shifting needs some adjustment, too. I got sha1-test to succeed with below patch. What do you think: Could we go some route like that for the other arm asm code as well?
Sounds reasonable, I'm happy to apply patches. If you feel like, v6/aes-*.asm could also use better code for aligned reading of input data.
I'd be willing to throw in aarch64 as well because I've got some Pine64s running BE floating around also. :)
Aarch64 assembly (for both endian flavors) would be nice, but it's a separate project. I haven't yet looked into aarch64-assembly. I made an attempt to build nettle under termux on my android phone a while ago, but it failed because it didn't provide /bin/sh at the expected place.
Before attempting to support big-endian arm, I'd need some idea on how to test it.
Any halfway current ARM cross toolchain should be able to also output big-endian arm binaries (-mbig-endian). Then you could test those with qemu-user-armeb, which is very light-weight in that it doesn't need a kernel or emulated system and allows to run binaries directly.
Sounds good. I hope the needed tools are packaged in debian, I'll have to check that.
From f876368b333c72878808e74a0af5aa631d42d357 Mon Sep 17 00:00:00 2001 From: Michael Weiser michael.weiser@gmx.de Date: Wed, 7 Feb 2018 00:11:24 +0100 Subject: [PATCH] Support big-endian arm in sha1 armv6 assembly code
arm/v6/sha1-compress.asm | 10 ++++++++++ asm.m4 | 10 ++++++++++ config.m4.in | 1 + configure.ac | 2 ++ 4 files changed, 23 insertions(+)
diff --git a/arm/v6/sha1-compress.asm b/arm/v6/sha1-compress.asm index 59d6297e..116a80f0 100644 --- a/arm/v6/sha1-compress.asm +++ b/arm/v6/sha1-compress.asm @@ -52,7 +52,9 @@ define(<LOAD>, < sel W, WPREV, T0 ror W, W, SHIFT mov WPREV, T0 +NOT_IF_BE(< rev W, W +>)
I'd prefer IF_LE or IF_NOT_BE or UNLESS_BE over NOT_IF_BE. And it might look better as a single line,
IF_LE(< rev W, W>)
+IF_BE(<
- neg SHIFT, SHIFT C Rotate right by 32-SHIFT bits
- add SHIFT, SHIFT, #32 C because there's no rotate left
+>, <>)
Can the rsb instruction be used for this?
+define(<IF_BE>, +<ifelse(WORDS_BIGENDIAN,yes, +<$1>, +<$2>)>)
Would be good to check explicitly for the supported values "yes" and "no" (m4 ifelse can have more than two alternatives), and fail with m4exit if configure produced any other value, e.g., "unknown".
+define(<NOT_IF_BE>, +<ifelse(WORDS_BIGENDIAN,no, +<$1>, +<>)>)
As above, I'm not so fond of the name. And for symmetry, it would be nice with an else clause just as for IF_BE.
--- a/configure.ac +++ b/configure.ac @@ -691,6 +691,7 @@ ASM_TYPE_FUNCTION='@function' ASM_TYPE_PROGBITS='@progbits' ASM_MARK_NOEXEC_STACK='' ASM_ALIGN_LOG='' +ASM_WORDS_BIGENDIAN="$ac_cv_c_bigendian"
If you have the time, it would be good to file an autoconf bug report, asking them to document (and support) that AC_C_BIGENDIAN sets the shell variable ac_cv_c_bigendian.
Regards, /Niels