Skip to content

Commit

Permalink
Allow ARM capabilities to be set at compile time.
Browse files Browse the repository at this point in the history
Some ARM environments don't support |getauxval| or signals and need to
configure the capabilities of the chip at compile time. This change adds
defines that allow them to do so.

Change-Id: I4e6987f69dd13444029bc7ac7ed4dbf8fb1faa76
Reviewed-on: https://boringssl-review.googlesource.com/6280
Reviewed-by: Adam Langley <agl@google.com>
  • Loading branch information
agl committed Oct 20, 2015
1 parent c2ae53d commit 6a7cfbe
Show file tree
Hide file tree
Showing 8 changed files with 111 additions and 22 deletions.
24 changes: 24 additions & 0 deletions BUILDING.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
5 changes: 3 additions & 2 deletions crypto/aes/aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@
#include <assert.h>
#include <stdlib.h>

#include <openssl/cpu.h>

#include "internal.h"


Expand Down Expand Up @@ -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 <openssl/arm_arch.h>

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,
Expand Down
4 changes: 2 additions & 2 deletions crypto/cipher/e_aes.c
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down Expand Up @@ -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
Expand Down
22 changes: 16 additions & 6 deletions crypto/cpu-arm.c
Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,14 @@

#include <openssl/cpu.h>

#if defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)
#if (defined(OPENSSL_ARM) || defined(OPENSSL_AARCH64)) && \
!defined(OPENSSL_STATIC_ARMCAP)

#include <inttypes.h>
#include <string.h>

#if !defined(OPENSSL_TRUSTY)
#include <setjmp.h>
#include <signal.h>
#endif

#include <openssl/arm_arch.h>

Expand All @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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) */
24 changes: 22 additions & 2 deletions crypto/crypto.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -57,7 +57,27 @@ uint32_t OPENSSL_ia32cap_P[4] = {0};

#include <openssl/arm_arch.h>

#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;
Expand Down
2 changes: 1 addition & 1 deletion crypto/modes/gcm.c
Original file line number Diff line number Diff line change
Expand Up @@ -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]);
Expand Down
9 changes: 0 additions & 9 deletions include/openssl/arm_arch.h
Original file line number Diff line number Diff line change
Expand Up @@ -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)

Expand Down
43 changes: 43 additions & 0 deletions include/openssl/cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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. */
Expand All @@ -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 */


Expand Down

0 comments on commit 6a7cfbe

Please sign in to comment.