New release portability issue
Damien Miller
djm at mindrot.org
Fri Feb 21 15:43:17 AEDT 2025
On Fri, 21 Feb 2025, Damien Miller wrote:
> > sparc64$ grep -n '__builtin_popcount' openssh-9.8p1/libcrux_mlkem768_sha3.h
> > grep: openssh-9.8p1/libcrux_mlkem768_sha3.h: No such file or directory
> > sparc64$
>
> Ah sorry, I was driving "git diff" badly. The code is indeed new.
>
> Can you provide some more details about your compiler? We already have
> logic to disable ML-KEM if the compiler is too old (search defines.h for
> USE_MLKEM768X25519), and it would be trivial to extend that.
>
> It's probably fairly easy to put a simple popcount in for compatibility
> too, but I don't think we need to be very fancy there.
>
> To do either of these in OpenSSH though, we need to be able to identify
> compilers that lack __builtin_popcount...
Try the attached patch. You'll need to rebuild configure after applying
it.
-------------- next part --------------
diff --git a/configure.ac b/configure.ac
index b802d0e60..254b2d9cb 100644
--- a/configure.ac
+++ b/configure.ac
@@ -2072,6 +2072,19 @@ AC_CHECK_FUNCS([ \
warn \
])
+AC_MSG_CHECKING([whether compiler supports __builtin_popcount])
+AC_LINK_IFELSE([AC_LANG_PROGRAM([[
+ #include <stdlib.h>
+ ]],
+ [[ int x = 123, y;
+ y = __builtin_popcount(123);
+ exit(y == 6 ? 0 : -1); ]])],
+ [ AC_MSG_RESULT([yes]) ], [
+ AC_MSG_RESULT([no])
+ AC_DEFINE([MISSING_BUILTIN_POPCOUNT], [1], [Define if your compiler lacks __builtin_popcount])
+ ]
+)
+
AC_CHECK_DECLS([bzero, memmem])
dnl Wide character support.
diff --git a/libcrux_mlkem768_sha3.h b/libcrux_mlkem768_sha3.h
index b8ac1436f..885e82baf 100644
--- a/libcrux_mlkem768_sha3.h
+++ b/libcrux_mlkem768_sha3.h
@@ -177,10 +177,14 @@ static inline uint32_t core_num__u32_8__from_le_bytes(uint8_t buf[4]) {
}
static inline uint32_t core_num__u8_6__count_ones(uint8_t x0) {
-#ifdef _MSC_VER
+#if defined(_MSC_VER)
return __popcnt(x0);
-#else
+#elif !defined(MISSING_BUILTIN_POPCOUNT)
return __builtin_popcount(x0);
+#else
+ const uint8_t v[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+ return v[x0 & 0xf] + v[(x0 >> 4) & 0xf];
+
#endif
}
diff --git a/mlkem768.sh b/mlkem768.sh
index 3d12b2ed8..cbc3d14da 100644
--- a/mlkem768.sh
+++ b/mlkem768.sh
@@ -49,6 +49,11 @@ echo '#define KRML_HOST_EPRINTF(...)'
echo '#define KRML_HOST_EXIT(x) fatal_f("internal error")'
echo
+__builtin_popcount_replacement='
+ const uint8_t v[16] = { 0, 1, 1, 2, 1, 2, 2, 3, 1, 2, 2, 3, 2, 3, 3, 4 };
+ return v[x0 & 0xf] + v[(x0 >> 4) & 0xf];
+'
+
for i in $FILES; do
echo "/* from $i */"
# Changes to all files:
@@ -62,7 +67,10 @@ for i in $FILES; do
# Replace endian functions with versions that work.
perl -0777 -pe 's/(static inline void core_num__u64_9__to_le_bytes.*\n)([^}]*\n)/\1 v = htole64(v);\n\2/' |
perl -0777 -pe 's/(static inline uint64_t core_num__u64_9__from_le_bytes.*?)return v;/\1return le64toh(v);/s' |
- perl -0777 -pe 's/(static inline uint32_t core_num__u32_8__from_le_bytes.*?)return v;/\1return le32toh(v);/s'
+ perl -0777 -pe 's/(static inline uint32_t core_num__u32_8__from_le_bytes.*?)return v;/\1return le32toh(v);/s' |
+ # Compat for popcount.
+ perl -0777 -pe 's/\#ifdef (_MSC_VER)(.*?return __popcnt\(x0\);)/\#if defined(\1)\2/s' |
+ perl -0777 -pe "s/\\#else(\\n\\s+return __builtin_popcount\\(x0\\);)/\\#elif !defined(MISSING_BUILTIN_POPCOUNT)\\1\\n#else$__builtin_popcount_replacement/s"
;;
# Default: pass through.
*)
More information about the openssh-unix-dev
mailing list