diff --git a/BUILDING.md b/BUILDING.md index 65e88e87..99adbfd1 100644 --- a/BUILDING.md +++ b/BUILDING.md @@ -91,6 +91,30 @@ binaries. don't have steps for assembling the assembly language source files, so they currently cannot be used to build BoringSSL. +## Embedded ARM + +ARM, unlike Intel, does not have an instruction that allows applications to +discover the capabilities of the processor. Instead, the capability information +has to be provided by the operating system somehow. + +BoringSSL will try to use `getauxval` to discover the capabilities and, failing +that, will probe for NEON support by executing a NEON instruction and handling +any illegal-instruction signal. But some environments don't support that sort +of thing and, for them, it's possible to configure the CPU capabilities +at compile time. + +If you define `OPENSSL_STATIC_ARMCAP` then you can define any of the following +to enabling the corresponding ARM feature. + + * `OPENSSL_STATIC_ARMCAP_NEON` or `__ARM_NEON__` (note that the latter is set by compilers when NEON support is enabled). + * `OPENSSL_STATIC_ARMCAP_AES` + * `OPENSSL_STATIC_ARMCAP_SHA1` + * `OPENSSL_STATIC_ARMCAP_SHA256` + * `OPENSSL_STATIC_ARMCAP_PMULL` + +Note that if a feature is enabled in this way, but not actually supported at +run-time, BoringSSL will likely crash. + # Running tests There are two sets of tests: the C/C++ tests and the blackbox tests. For former diff --git a/crypto/aes/aes.c b/crypto/aes/aes.c index 1813eaeb..88239198 100644 --- a/crypto/aes/aes.c +++ b/crypto/aes/aes.c @@ -51,6 +51,8 @@ #include #include +#include + #include "internal.h" @@ -1059,10 +1061,9 @@ void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) { #else #if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) -#include static int hwaes_capable(void) { - return (OPENSSL_armcap_P & ARMV8_AES) != 0; + return CRYPTO_is_ARMv8_AES_capable(); } int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits, diff --git a/crypto/cipher/e_aes.c b/crypto/cipher/e_aes.c index 7d444626..74f32230 100644 --- a/crypto/cipher/e_aes.c +++ b/crypto/cipher/e_aes.c @@ -121,7 +121,7 @@ static char bsaes_capable(void) { #define HWAES static int hwaes_capable(void) { - return (OPENSSL_armcap_P & ARMV8_AES) != 0; + return CRYPTO_is_ARMv8_AES_capable(); } int aes_v8_set_encrypt_key(const uint8_t *user_key, const int bits, @@ -1756,7 +1756,7 @@ int EVP_has_aes_hardware(void) { #if defined(OPENSSL_X86) || defined(OPENSSL_X86_64) return aesni_capable() && crypto_gcm_clmul_enabled(); #elif defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) - return hwaes_capable() && (OPENSSL_armcap_P & ARMV8_PMULL); + return hwaes_capable() && CRYPTO_is_ARMv8_PMULL_capable(); #else return 0; #endif diff --git a/crypto/cpu-arm.c b/crypto/cpu-arm.c index 6e037ab9..14ad2ee4 100644 --- a/crypto/cpu-arm.c +++ b/crypto/cpu-arm.c @@ -14,15 +14,14 @@ #include -#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) +#if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \ + !defined(OPENSSL_STATIC_ARMCAP) #include #include -#if !defined(OPENSSL_TRUSTY) #include #include -#endif #include @@ -33,6 +32,8 @@ unsigned long getauxval(unsigned long type) __attribute__((weak)); +extern uint32_t OPENSSL_armcap_P; + char CRYPTO_is_NEON_capable(void) { return (OPENSSL_armcap_P & ARMV7_NEON) != 0; } @@ -62,7 +63,15 @@ void CRYPTO_set_NEON_functional(char neon_functional) { } } -#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM) && !defined(OPENSSL_TRUSTY) +int CRYPTO_is_ARMv8_AES_capable(void) { + return (OPENSSL_armcap_P & ARMV8_AES) != 0; +} + +int CRYPTO_is_ARMv8_PMULL_capable(void) { + return (OPENSSL_armcap_P & ARMV8_PMULL) != 0; +} + +#if !defined(OPENSSL_NO_ASM) && defined(OPENSSL_ARM) static sigjmp_buf sigill_jmp; @@ -120,7 +129,7 @@ static int probe_for_NEON(void) { return 0; } -#endif /* !OPENSSL_NO_ASM && OPENSSL_ARM && !OPENSSL_TRUSTY */ +#endif /* !OPENSSL_NO_ASM && OPENSSL_ARM */ void OPENSSL_cpuid_setup(void) { if (getauxval == NULL) { @@ -186,4 +195,5 @@ void OPENSSL_cpuid_setup(void) { } } -#endif /* defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) */ +#endif /* (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && + !defined(OPENSSL_STATIC_ARMCAP) */ diff --git a/crypto/crypto.c b/crypto/crypto.c index 34d04b4c..26fbd70c 100644 --- a/crypto/crypto.c +++ b/crypto/crypto.c @@ -17,7 +17,7 @@ #include "internal.h" -#if !defined(OPENSSL_NO_ASM) && \ +#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_STATIC_ARMCAP) && \ (defined(OPENSSL_X86) || defined(OPENSSL_X86_64) || \ defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) /* x86, x86_64 and the ARMs need to record the result of a cpuid call for the @@ -57,7 +57,27 @@ uint32_t OPENSSL_ia32cap_P[4] = {0}; #include -#if defined(__ARM_NEON__) +#if defined(OPENSSL_STATIC_ARMCAP) + +uint32_t OPENSSL_armcap_P = +#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__) + ARMV7_NEON | ARMV7_NEON_FUNCTIONAL | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_AES) + ARMV8_AES | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_SHA1) + ARMV8_SHA1 | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_SHA256) + ARMV8_SHA256 | +#endif +#if defined(OPENSSL_STATIC_ARMCAP_PMULL) + ARMV8_PMULL | +#endif + 0; + +#elif defined(__ARM_NEON__) uint32_t OPENSSL_armcap_P = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL; #else uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL; diff --git a/crypto/modes/gcm.c b/crypto/modes/gcm.c index 593dce88..b597f45b 100644 --- a/crypto/modes/gcm.c +++ b/crypto/modes/gcm.c @@ -355,7 +355,7 @@ void gcm_ghash_4bit_x86(uint64_t Xi[2], const u128 Htable[16], const uint8_t *in #define GCM_FUNCREF_4BIT static int pmull_capable(void) { - return (OPENSSL_armcap_P & ARMV8_PMULL) != 0; + return CRYPTO_is_ARMv8_PMULL_capable(); } void gcm_init_v8(u128 Htable[16], const uint64_t Xi[2]); diff --git a/include/openssl/arm_arch.h b/include/openssl/arm_arch.h index 123a890d..1471db90 100644 --- a/include/openssl/arm_arch.h +++ b/include/openssl/arm_arch.h @@ -102,15 +102,6 @@ * will be included. */ #define __ARM_MAX_ARCH__ 8 -#if !__ASSEMBLER__ - -/* OPENSSL_armcap_P contains flags describing the capabilities of the CPU and - * is easy for assembly code to acesss. For C code, see the functions in - * |cpu.h|. */ -extern uint32_t OPENSSL_armcap_P; - -#endif /* !__ASSEMBLER__ */ - /* ARMV7_NEON is true when a NEON unit is present in the current CPU. */ #define ARMV7_NEON (1 << 0) diff --git a/include/openssl/cpu.h b/include/openssl/cpu.h index 981d246b..bda5347a 100644 --- a/include/openssl/cpu.h +++ b/include/openssl/cpu.h @@ -94,6 +94,9 @@ extern uint32_t OPENSSL_ia32cap_P[4]; #endif #if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64) + +#if !defined(OPENSSL_STATIC_ARMCAP) + /* CRYPTO_is_NEON_capable returns true if the current CPU has a NEON unit. Note * that |OPENSSL_armcap_P| also exists and contains the same information in a * form that's easier for assembly to use. */ @@ -116,6 +119,46 @@ OPENSSL_EXPORT char CRYPTO_is_NEON_functional(void); * compiled with |-mfpu=neon| or if |CRYPTO_set_NEON_capable| has been called * with a non-zero argument. */ OPENSSL_EXPORT void CRYPTO_set_NEON_functional(char neon_functional); + +/* CRYPTO_is_ARMv8_AES_capable returns true if the current CPU supports the + * ARMv8 AES instruction. */ +int CRYPTO_is_ARMv8_AES_capable(void); + +/* CRYPTO_is_ARMv8_PMULL_capable returns true if the current CPU supports the + * ARMv8 PMULL instruction. */ +int CRYPTO_is_ARMv8_PMULL_capable(void); + +#else + +static inline int CRYPTO_is_NEON_capable(void) { +#if defined(OPENSSL_STATIC_ARMCAP_NEON) || defined(__ARM_NEON__) + return 1; +#else + return 0; +#endif +} + +static inline int CRYPTO_is_NEON_functional(void) { + return CRYPTO_is_NEON_capable(); +} + +static inline int CRYPTO_is_ARMv8_AES_capable(void) { +#if defined(OPENSSL_STATIC_ARMCAP_AES) + return 1; +#else + return 0; +#endif +} + +static inline int CRYPTO_is_ARMv8_PMULL_capable(void) { +#if defined(OPENSSL_STATIC_ARMCAP_PMULL) + return 1; +#else + return 0; +#endif +} + +#endif /* OPENSSL_STATIC_ARMCAP */ #endif /* OPENSSL_ARM */