diff --git a/build.rs b/build.rs index c6cb3a700..62b150170 100644 --- a/build.rs +++ b/build.rs @@ -65,6 +65,7 @@ const RING_SRCS: &[(&[&str], &str)] = &[ (&[], "third_party/fiat/curve25519.c"), (&[X86_64, X86], "crypto/cpu-intel.c"), + (&[AARCH64], "crypto/cpu-aarch64.c"), (&[X86], "crypto/fipsmodule/aes/asm/aes-586.pl"), (&[X86], "crypto/fipsmodule/aes/asm/aesni-x86.pl"), diff --git a/crypto/cpu-aarch64.c b/crypto/cpu-aarch64.c new file mode 100644 index 000000000..263c5b866 --- /dev/null +++ b/crypto/cpu-aarch64.c @@ -0,0 +1,46 @@ +// Copyright 2019 Greg V +// +// Permission to use, copy, modify, and/or distribute this software for any +// purpose with or without fee is hereby granted, provided that the above +// copyright notice and this permission notice appear in all copies. +// +// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHORS DISCLAIM ALL WARRANTIES +// WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +// MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY +// SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +// WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION +// OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN +// CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + + +// Run-time feature detection for aarch64 on any OS that emulates the mrs instruction. +// +// On FreeBSD >= 12.0, Linux >= 4.11 and other operating systems, it is possible to use +// privileged system registers from userspace to check CPU feature support. +// +// For proper support of SoCs where different cores have different capabilities +// the OS has to always report only the features supported by all cores, like FreeBSD does. +// +// Only FreeBSD uses this right now. + +#ifdef __FreeBSD__ +#pragma GCC diagnostic ignored "-Wgnu-statement-expression" +#include +#include +#include + +void GFp_mrs_setup(void) { + GFp_armcap_P = 0; + + uint64_t id_aa64isar0 = READ_SPECIALREG(ID_AA64ISAR0_EL1); + + if (ID_AA64ISAR0_AES(id_aa64isar0) >= ID_AA64ISAR0_AES_BASE) + GFp_armcap_P |= ARMV8_AES; + + if (ID_AA64ISAR0_AES(id_aa64isar0) >= ID_AA64ISAR0_AES_PMULL) + GFp_armcap_P |= ARMV8_PMULL; + + if (ID_AA64ISAR0_SHA2(id_aa64isar0) >= ID_AA64ISAR0_SHA2_BASE) + GFp_armcap_P |= ARMV8_SHA256; +} +#endif diff --git a/include/GFp/arm_arch.h b/include/GFp/arm_arch.h index ee5e32c8f..822783ebb 100644 --- a/include/GFp/arm_arch.h +++ b/include/GFp/arm_arch.h @@ -107,7 +107,13 @@ // ARMV7_NEON is true when a NEON unit is present in the current CPU. #define ARMV7_NEON (1 << 0) +// ARMV8_AES indicates support for hardware AES instructions. +#define ARMV8_AES (1 << 2) + // ARMV8_SHA256 indicates support for hardware SHA-256 instructions. #define ARMV8_SHA256 (1 << 4) +// ARMV8_PMULL indicates support for hardware polynomial multiply instructions. +#define ARMV8_PMULL (1 << 5) + #endif // OPENSSL_HEADER_ARM_ARCH_H diff --git a/include/GFp/cpu.h b/include/GFp/cpu.h index 462018afa..96a4917c9 100644 --- a/include/GFp/cpu.h +++ b/include/GFp/cpu.h @@ -89,4 +89,11 @@ extern uint32_t GFp_ia32cap_P[4]; #endif +#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) +// GFp_armcap_P contains feature flags when running on an ARM system. +// +// The flags are defined in . +extern uint32_t GFp_armcap_P; +#endif + #endif // OPENSSL_HEADER_CPU_H diff --git a/src/cpu.rs b/src/cpu.rs index bfd87c8de..d997f7223 100644 --- a/src/cpu.rs +++ b/src/cpu.rs @@ -60,6 +60,16 @@ pub(crate) fn features() -> Features { { arm::fuchsia_setup(); } + + #[cfg(all(any(target_os = "freebsd"), target_arch = "aarch64"))] + { + extern "C" { + fn GFp_mrs_setup(); + } + unsafe { + GFp_mrs_setup(); + } + } }); } @@ -171,7 +181,7 @@ pub(crate) mod arm { pub(crate) struct Feature { #[cfg_attr( not(all( - any(target_os = "android", target_os = "linux", target_os = "fuchsia"), + any(target_os = "android", all(target_os = "freebsd", target_arch = "aarch64"), target_os = "linux", target_os = "fuchsia"), any(target_arch = "arm", target_arch = "aarch64") )), allow(dead_code) @@ -191,7 +201,7 @@ pub(crate) mod arm { } #[cfg(all( - any(target_os = "android", target_os = "linux", target_os = "fuchsia"), + any(target_os = "android", all(target_os = "freebsd", target_arch = "aarch64"), target_os = "linux", target_os = "fuchsia"), any(target_arch = "arm", target_arch = "aarch64") ))] { @@ -199,7 +209,7 @@ pub(crate) mod arm { } #[cfg(not(all( - any(target_os = "android", target_os = "ios", target_os = "linux", target_os = "fuchsia"), + any(target_os = "android", all(target_os = "freebsd", target_arch = "aarch64"), target_os = "ios", target_os = "linux", target_os = "fuchsia"), any(target_arch = "arm", target_arch = "aarch64") )))] { @@ -231,7 +241,7 @@ pub(crate) mod arm { }; #[cfg(all( - any(target_os = "android", target_os = "linux", target_os = "fuchsia"), + any(target_os = "android", all(target_os = "freebsd", target_arch = "aarch64"), target_os = "linux", target_os = "fuchsia"), any(target_arch = "arm", target_arch = "aarch64") ))] extern "C" {