packages feed

crypton 2.1.10 → 2.1.11

raw patch · 5 files changed

+114/−9 lines, 5 files

Files

CHANGELOG.md view
@@ -1,5 +1,16 @@ # CHANGELOG for crypton +## 2.1.11++**crypton runs again on x86-64 processors without AVX2.**  From 2.1.8 the+whole library was compiled with `-mavx2 -mbmi2`, so a program built on a+machine with AVX2 was killed on one without.  This is the fix 2.2.1 made.++* fix: stop raising the x86-64 baseline for the whole library+  [#351](https://github.com/kazu-yamamoto/crypton/pull/351)+* fix: ask the processor before using the ML-KEM and ML-DSA backends+  [#351](https://github.com/kazu-yamamoto/crypton/pull/351)+ ## 2.1.10  * build: ask the processor for AES-NI on every x86 system, not four of them
cbits/mldsa/crypton_mldsa.h view
@@ -4,7 +4,8 @@  * choice crypton makes is made here instead of by editing it.  *  * Included first by both crypton_mldsa.c and crypton_mldsa_asm.S, so it must- * hold nothing but preprocessor directives.+ * hold nothing the assembler cannot read: directives, and C behind+ * __ASSEMBLER__.  */ #ifndef CRYPTON_MLDSA_H #define CRYPTON_MLDSA_H@@ -36,6 +37,43 @@ #ifdef CRYPTON_MLDSA_NATIVE_BACKEND #define MLD_CONFIG_USE_NATIVE_BACKEND_ARITH #define MLD_CONFIG_USE_NATIVE_BACKEND_FIPS202++/*+ * Which of the backend's instructions this processor actually has.+ *+ * Without this both packages decide at compile time: the backend is built+ * because the architecture has the instructions in principle, and is then+ * called with no check.  Upstream says so plainly -- if the machine that+ * runs the binary may differ from the one that built it, this function+ * MUST be provided -- and crypton is a library whose builds are copied+ * between machines and shipped by distributions.  Without it a binary+ * built on a host with AVX2 dies with SIGILL on one without (#316).+ *+ * The dispatch sites are upstream's; each falls back to the portable C+ * when this answers no.  The answers come from crypton's own detection,+ * the same that AES-NI, PCLMUL and the s2n-bignum variants use.+ */+#define MLD_CONFIG_CUSTOM_CAPABILITY_FUNC+#ifndef __ASSEMBLER__+#include "src/sys.h"+#include "crypton_cpu.h"++static MLD_INLINE int mld_sys_check_capability(mld_sys_cap cap)+{+#if defined(__x86_64__)+    if (cap == MLD_SYS_CAP_X86_64_AVX2)+        return (crypton_x86_simd_features() & CRYPTON_X86_AVX2) != 0;+#elif defined(__aarch64__)+    /* NEON is not optional on AArch64; the Keccak instructions are. */+    if (cap == MLD_SYS_CAP_AARCH64_NEON)+        return 1;+    if (cap == MLD_SYS_CAP_AARCH64_SHA3)+        return (crypton_arm_features() & CRYPTON_ARM_SHA3) != 0;+#endif+    (void)cap;+    return 0;+}+#endif /* !__ASSEMBLER__ */ #endif  #endif /* CRYPTON_MLDSA_H */
cbits/mlkem/crypton_mlkem.h view
@@ -4,7 +4,8 @@  * choice crypton makes is made here instead of by editing it.  *  * Included first by both crypton_mlkem.c and crypton_mlkem_asm.S, so it must- * hold nothing but preprocessor directives.+ * hold nothing the assembler cannot read: directives, and C behind+ * __ASSEMBLER__.  */ #ifndef CRYPTON_MLKEM_H #define CRYPTON_MLKEM_H@@ -36,6 +37,43 @@ #ifdef CRYPTON_MLKEM_NATIVE_BACKEND #define MLK_CONFIG_USE_NATIVE_BACKEND_ARITH #define MLK_CONFIG_USE_NATIVE_BACKEND_FIPS202++/*+ * Which of the backend's instructions this processor actually has.+ *+ * Without this both packages decide at compile time: the backend is built+ * because the architecture has the instructions in principle, and is then+ * called with no check.  Upstream says so plainly -- if the machine that+ * runs the binary may differ from the one that built it, this function+ * MUST be provided -- and crypton is a library whose builds are copied+ * between machines and shipped by distributions.  Without it a binary+ * built on a host with AVX2 dies with SIGILL on one without (#316).+ *+ * The dispatch sites are upstream's; each falls back to the portable C+ * when this answers no.  The answers come from crypton's own detection,+ * the same that AES-NI, PCLMUL and the s2n-bignum variants use.+ */+#define MLK_CONFIG_CUSTOM_CAPABILITY_FUNC+#ifndef __ASSEMBLER__+#include "src/sys.h"+#include "crypton_cpu.h"++static MLK_INLINE int mlk_sys_check_capability(mlk_sys_cap cap)+{+#if defined(__x86_64__)+    if (cap == MLK_SYS_CAP_X86_64_AVX2)+        return (crypton_x86_simd_features() & CRYPTON_X86_AVX2) != 0;+#elif defined(__aarch64__)+    /* NEON is not optional on AArch64; the Keccak instructions are. */+    if (cap == MLK_SYS_CAP_AARCH64_NEON)+        return 1;+    if (cap == MLK_SYS_CAP_AARCH64_SHA3)+        return (crypton_arm_features() & CRYPTON_ARM_SHA3) != 0;+#endif+    (void)cap;+    return 0;+}+#endif /* !__ASSEMBLER__ */ #endif  #endif /* CRYPTON_MLKEM_H */
cbits/tests/ct/run.sh view
@@ -63,7 +63,11 @@ # And the hand-written backend, where the architecture has one.  Both builds # have to be silent: unlike the AES pair below there is no variable-time # implementation here for one of them to expose.-mlkem_native_src="$mlkem_src cbits/mlkem/crypton_mlkem_asm.S"+#+# crypton_cpu.c because the backend asks it whether this processor has the+# instructions before using them; without it the link fails on the+# capability function in cbits/mlkem/crypton_mlkem.h.+mlkem_native_src="$mlkem_src cbits/mlkem/crypton_mlkem_asm.S cbits/crypton_cpu.c" mlkem_native_inc="$mlkem_inc -DCRYPTON_MLKEM_NATIVE_BACKEND"  @@ -189,12 +193,22 @@  # The ML-KEM backend, on both architectures that have one.  x86-64 wants the # flags its own build system passes, or the AVX2 sources do not assemble.+#+# The backend now asks the processor before it runs, so on x86-64 without+# AVX2 this build measures the portable C under a name that says otherwise.+# Say so and skip, rather than pass while checking the thing the plain+# mlkem build above has already checked. case $(uname -m) in aarch64 | arm64) 	run_one mlkem_native "$mlkem_native_src" "$mlkem_native_inc" mlkem 	;; x86_64 | amd64)-	run_one mlkem_native "$mlkem_native_src" "$mlkem_native_inc -mavx2 -mbmi2" mlkem+	if grep -qw avx2 "${CRYPTON_CT_CPUINFO:-/proc/cpuinfo}" 2>/dev/null; then+		run_one mlkem_native "$mlkem_native_src" "$mlkem_native_inc -mavx2 -mbmi2" mlkem+	else+		echo "skip mlkem_native: this processor has no AVX2, so the backend"+		echo "     would fall back to the C the mlkem build above measured"+	fi 	;; esac 
crypton.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               crypton-version:            2.1.10+version:            2.1.11 -- crypton's own code is BSD-3-Clause.  The parts of -- cbits/aes/gcm_fused_x86.c that follow picotls's fusion are MIT, and the -- vendored s2n-bignum assembly in cbits/s2n is taken under ISC; each has@@ -716,11 +716,15 @@             cbits/mldsa/crypton_mldsa_asm.S          -- What the two packages' own build systems pass for the x86-64-        -- backend; without them the AVX2 sources do not assemble.  AArch64-        -- needs nothing beyond the baseline for the arithmetic, and takes-        -- the armv8.4 Keccak from the -march the block below already sets.+        -- backend, and only for the assembly: cc-options in a conditional+        -- are the component's, not the block's, so -mavx2 here would raise+        -- the baseline of every C file in the library -- Ed25519, Argon2,+        -- P-256 and the rest -- and gcc would vectorise code that asks for+        -- no such thing, with nothing to check at runtime.  The backends'+        -- own AVX2 is all in the .S.  AArch64 needs nothing beyond the+        -- baseline for the arithmetic, and takes the armv8.4 Keccak from+        -- the -march the block below already sets.         if arch(x86_64)-            cc-options:  -mavx2 -mbmi2             asm-options: -mavx2 -mbmi2      if ((flag(support_rdrand) && (arch(i386) || arch(x86_64))) && !os(windows))