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 +7/−0
- cbits/aes/armv8.c +6/−23
- cbits/crypton_cpu.c +108/−0
- cbits/crypton_cpu.h +19/−0
- cbits/sha1_armv8.c +2/−11
- cbits/sha256_armv8.c +2/−11
- cbits/sha3_armv8.c +2/−18
- cbits/sha512_armv8.c +2/−20
- crypton.cabal +14/−3
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