packages feed

crypton 2.1.9 → 2.1.10

raw patch · 9 files changed

+162/−86 lines, 9 filesPVP ok

version bump matches the API change (PVP)

API changes (from Hackage documentation)

Files

CHANGELOG.md view
@@ -1,5 +1,12 @@ # CHANGELOG for crypton +## 2.1.10++* build: ask the processor for AES-NI on every x86 system, not four of them+  [#307](https://github.com/kazu-yamamoto/crypton/pull/307)+* fix: ask one place which ARMv8 instruction sets the machine has+  [#307](https://github.com/kazu-yamamoto/crypton/pull/307)+ ## 2.1.9  * feat(rsa): PKCS#1 v1.5 operations that take a digest, and ones that take a DigestInfo
cbits/aes/armv8.c view
@@ -20,12 +20,9 @@ #include <stdint.h> #include <string.h> #include <arm_neon.h>-#if defined(__linux__)-#include <sys/auxv.h>-#include <asm/hwcap.h>-#endif #include "crypton_aes.h" #include "crypton_bitfn.h"+#include "crypton_cpu.h"  /*  * The AES and PMULL instructions are extensions, so a translation unit@@ -123,21 +120,13 @@ }  /*- * Whether the extensions are actually present.- *- * They are mandatory on Apple silicon, and on other AArch64 systems the- * kernel reports them through the auxiliary vector.  A system without them- * keeps the generic implementation.+ * Whether the extensions are actually present.  crypton_cpu.c asks the+ * system once, in the one place that knows how each system answers; a+ * processor without them keeps the generic implementation.  */ int crypton_aes_armv8_available(void) {-#if defined(__APPLE__)-	return 1;-#elif defined(__linux__)-	return (getauxval(AT_HWCAP) & HWCAP_AES) != 0;-#else-	return 0;-#endif+	return (crypton_arm_features() & CRYPTON_ARM_AES) != 0; }  /*@@ -358,13 +347,7 @@  int crypton_aes_armv8_pmull_available(void) {-#if defined(__APPLE__)-	return 1;-#elif defined(__linux__)-	return (getauxval(AT_HWCAP) & HWCAP_PMULL) != 0;-#else-	return 0;-#endif+	return (crypton_arm_features() & CRYPTON_ARM_PMULL) != 0; }  /*
cbits/crypton_cpu.c view
@@ -60,6 +60,114 @@     CRYPTON_ARMCAP_NEON; #endif +#if defined(__aarch64__)+#if defined(__APPLE__)+#include <sys/sysctl.h>+#elif defined(__linux__)+#include <sys/auxv.h>+#include <asm/hwcap.h>+#elif defined(__FreeBSD__)+#include <sys/auxv.h>+#endif++/*+ * The HWCAP bit positions are the ARM ELF ABI's, so every system that+ * reports through the auxiliary vector agrees on them.  What differs is+ * AT_HWCAP itself -- 16 on Linux, 25 on FreeBSD -- and that comes from each+ * system's own header, which is why the tag is never written out here.+ * Defined only where the system's headers did not define them, the way+ * compiler-rt does it, so that a system which reports through the auxiliary+ * vector without shipping the ARM names still compiles.+ */+#ifndef HWCAP_AES+#define HWCAP_AES    (1 << 3)+#endif+#ifndef HWCAP_PMULL+#define HWCAP_PMULL  (1 << 4)+#endif+#ifndef HWCAP_SHA1+#define HWCAP_SHA1   (1 << 5)+#endif+#ifndef HWCAP_SHA2+#define HWCAP_SHA2   (1 << 6)+#endif+#ifndef HWCAP_SHA3+#define HWCAP_SHA3   (1 << 17)+#endif+#ifndef HWCAP_SHA512+#define HWCAP_SHA512 (1 << 21)+#endif++#if defined(__APPLE__)+static int apple_has(const char *name)+{+	int v = 0;+	size_t n = sizeof(v);++	if (sysctlbyname(name, &v, &n, NULL, 0) != 0)+		return 0;+	return v != 0;+}+#endif++/*+ * Systems still answering zero, and what each would need:+ *+ *   OpenBSD, NetBSD   sysctl on machdep.id_aa64isar0, which hands out the+ *                     ID_AA64ISAR0_EL1 fields rather than a HWCAP word, so+ *                     it is a different shape of answer rather than another+ *                     tag.+ *   Windows on ARM    IsProcessorFeaturePresent with+ *                     PF_ARM_V8_CRYPTO_INSTRUCTIONS_AVAILABLE, which covers+ *                     AES, PMULL, SHA-1 and SHA-256 as one bit and says+ *                     nothing about SHA-512 or SHA-3.  An ARM64 Windows+ *                     guest answers 1 to it, but GHC has no native ARM64+ *                     Windows target: there it builds x86-64 and the+ *                     emulator reports AES-NI, so this file is not reached.+ *+ * Neither is written here because neither can be built and run to see it+ * work, and an untested answer about whether a machine has AES is worse+ * than the honest zero it replaces.+ */+unsigned int crypton_arm_features(void)+{+	static unsigned int features;+	static int resolved;++	if (!resolved) {+		unsigned int f = 0;+#if defined(__APPLE__)+		/* AES, PMULL, SHA-1 and SHA-256 are not optional on Apple+		 * silicon.  The two later ones are. */+		f = CRYPTON_ARM_AES | CRYPTON_ARM_PMULL+		  | CRYPTON_ARM_SHA1 | CRYPTON_ARM_SHA2;+		if (apple_has("hw.optional.arm.FEAT_SHA512"))+			f |= CRYPTON_ARM_SHA512;+		if (apple_has("hw.optional.arm.FEAT_SHA3"))+			f |= CRYPTON_ARM_SHA3;+#else+		unsigned long cap = 0;++#if defined(__linux__)+		cap = getauxval(AT_HWCAP);+#elif defined(__FreeBSD__)+		if (elf_aux_info(AT_HWCAP, &cap, sizeof(cap)) != 0)+			cap = 0;+#endif+		if (cap & HWCAP_AES)    f |= CRYPTON_ARM_AES;+		if (cap & HWCAP_PMULL)  f |= CRYPTON_ARM_PMULL;+		if (cap & HWCAP_SHA1)   f |= CRYPTON_ARM_SHA1;+		if (cap & HWCAP_SHA2)   f |= CRYPTON_ARM_SHA2;+		if (cap & HWCAP_SHA512) f |= CRYPTON_ARM_SHA512;+		if (cap & HWCAP_SHA3)   f |= CRYPTON_ARM_SHA3;+#endif+		features = f;+		resolved = 1;+	}+	return features;+}+#endif /* __aarch64__ */+ #ifdef ARCH_X86 static void cpuid(uint32_t info, uint32_t *eax, uint32_t *ebx, uint32_t *ecx, uint32_t *edx) {
cbits/crypton_cpu.h view
@@ -98,6 +98,25 @@ extern unsigned int crypton_armcap_P; #endif +/*+ * Which of the optional ARMv8 instruction sets this processor has.+ *+ * Asked here rather than in each file that wants one.  Five files used to+ * carry the same three-way conditional -- Apple, Linux, and otherwise zero+ * -- and the "otherwise" is not a statement about the processor but about+ * which systems someone had thought of.  It is what left FreeBSD running+ * the table-driven AES and the C SHA on hardware that has the+ * instructions.  In one place the next system is added once.+ */+#if defined(__aarch64__)+#define CRYPTON_ARM_AES    (1u << 0)+#define CRYPTON_ARM_PMULL  (1u << 1)+#define CRYPTON_ARM_SHA1   (1u << 2)+#define CRYPTON_ARM_SHA2   (1u << 3)+#define CRYPTON_ARM_SHA512 (1u << 4)+#define CRYPTON_ARM_SHA3   (1u << 5)+unsigned int crypton_arm_features(void);+#endif #ifdef USE_AESNI void crypton_aesni_initialize_hw(void (*init_table)(int, int)); #else
cbits/sha1_armv8.c view
@@ -13,10 +13,7 @@  #include <stdint.h> #include <arm_neon.h>-#if defined(__linux__)-#include <sys/auxv.h>-#include <asm/hwcap.h>-#endif+#include "crypton_cpu.h"  /*  * The instructions are an extension, so a translation unit compiled for@@ -159,11 +156,5 @@  */ int crypton_sha1_armv8_available(void) {-#if defined(__APPLE__)-	return 1;-#elif defined(__linux__)-	return (getauxval(AT_HWCAP) & HWCAP_SHA1) != 0;-#else-	return 0;-#endif+	return (crypton_arm_features() & CRYPTON_ARM_SHA1) != 0; }
cbits/sha256_armv8.c view
@@ -12,10 +12,7 @@  #include <stdint.h> #include <arm_neon.h>-#if defined(__linux__)-#include <sys/auxv.h>-#include <asm/hwcap.h>-#endif+#include "crypton_cpu.h"  /*  * The SHA-2 instructions are an extension, so a translation unit compiled for@@ -131,11 +128,5 @@  */ int crypton_sha256_armv8_available(void) {-#if defined(__APPLE__)-	return 1;-#elif defined(__linux__)-	return (getauxval(AT_HWCAP) & HWCAP_SHA2) != 0;-#else-	return 0;-#endif+	return (crypton_arm_features() & CRYPTON_ARM_SHA2) != 0; }
cbits/sha3_armv8.c view
@@ -25,12 +25,7 @@  #include <stdint.h> #include <arm_neon.h>-#if defined(__APPLE__)-#include <sys/sysctl.h>-#elif defined(__linux__)-#include <sys/auxv.h>-#include <asm/hwcap.h>-#endif+#include "crypton_cpu.h"  /*  * The SHA-3 instructions are an ARMv8.2 extension, so a translation unit@@ -157,16 +152,5 @@  */ int crypton_sha3_armv8_available(void) {-#if defined(__APPLE__)-	int v = 0;-	size_t n = sizeof(v);--	if (sysctlbyname("hw.optional.arm.FEAT_SHA3", &v, &n, NULL, 0) != 0)-		return 0;-	return v != 0;-#elif defined(__linux__)-	return (getauxval(AT_HWCAP) & HWCAP_SHA3) != 0;-#else-	return 0;-#endif+	return (crypton_arm_features() & CRYPTON_ARM_SHA3) != 0; }
cbits/sha512_armv8.c view
@@ -14,14 +14,7 @@  #include <stdint.h> #include <arm_neon.h>-#if defined(__linux__)-#include <sys/auxv.h>-#include <asm/hwcap.h>-#endif-#if defined(__APPLE__)-#include <sys/sysctl.h>-#include <string.h>-#endif+#include "crypton_cpu.h"  /*  * The instructions are an extension, so a translation unit compiled for@@ -142,16 +135,5 @@  */ int crypton_sha512_armv8_available(void) {-#if defined(__APPLE__)-	int v = 0;-	size_t n = sizeof(v);--	if (sysctlbyname("hw.optional.arm.FEAT_SHA512", &v, &n, NULL, 0) != 0)-		return 0;-	return v != 0;-#elif defined(__linux__)-	return (getauxval(AT_HWCAP) & HWCAP_SHA512) != 0;-#else-	return 0;-#endif+	return (crypton_arm_features() & CRYPTON_ARM_SHA512) != 0; }
crypton.cabal view
@@ -1,6 +1,6 @@ cabal-version:      3.0 name:               crypton-version:            2.1.9+version:            2.1.10 -- 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@@ -792,7 +792,18 @@                     cbits/asm/sha1-armv8-linux64.S                     cbits/asm/sha256-armv8-linux64.S -    if ((flag(support_aesni) && (((os(linux) || os(freebsd)) || os(osx)) || os(windows))) && (arch(i386) || arch(x86_64)))+    -- No operating system condition.  The processor is asked with cpuid,+    -- which no kernel is involved in, and crypton_cpu.h turns USE_AESNI on+    -- from __i386__ or __x86_64__ alone -- so nothing here was ever decided+    -- by which system it is.  The list that used to stand here named linux,+    -- freebsd and osx when it arrived from cipher-aes in 2014 and gained+    -- windows later, each time because someone wanted that one system; it+    -- was never a statement that the rest could not do this.  What it did+    -- instead was send OpenBSD, NetBSD, DragonFly, Solaris and illumos down+    -- the table-driven fallback on processors that have had AES-NI since+    -- 2010.  The object format still has a say further down, where the GCM+    -- assembly is chosen, and there ELF is the default.+    if (flag(support_aesni) && (arch(i386) || arch(x86_64)))         cc-options: -DWITH_AESNI         c-sources:             cbits/aes/generic.c@@ -853,7 +864,7 @@     -- branch had already named every file it names.  Cabal drops the repeats,     -- so nothing was built twice, but the line read as the fallback for a     -- platform with no AES instructions and was not one.-    if !((flag(support_aesni) && arch(aarch64)) || ((flag(support_aesni) && (((os(linux) || os(freebsd)) || os(osx)) || os(windows))) && (arch(i386) || arch(x86_64))))+    if !((flag(support_aesni) && arch(aarch64)) || (flag(support_aesni) && (arch(i386) || arch(x86_64))))         c-sources:             cbits/aes/generic.c             cbits/aes/gf.c