Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/mono/boringssl.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crypto/arm_arch.h15
-rw-r--r--crypto/cpu-arm.c17
-rw-r--r--crypto/poly1305/poly1305.c6
-rw-r--r--include/openssl/cpu.h15
4 files changed, 44 insertions, 9 deletions
diff --git a/crypto/arm_arch.h b/crypto/arm_arch.h
index d528eeed..52e6f340 100644
--- a/crypto/arm_arch.h
+++ b/crypto/arm_arch.h
@@ -88,13 +88,22 @@
#endif
#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 unsigned int OPENSSL_armcap_P;
+extern uint32_t OPENSSL_armcap_P;
-#define ARMV7_NEON (1<<0)
-#endif
+/* ARMV7_NEON is true when a NEON unit is present in the current CPU. */
+#define ARMV7_NEON (1 << 0)
+
+/* ARMV7_NEON_FUNCTIONAL is true when the NEON unit doesn't contain subtle bugs.
+ * The Poly1305 NEON code is known to trigger bugs in the NEON units of some
+ * phones. If this bit isn't set then the Poly1305 NEON code won't be used.
+ * See https://code.google.com/p/chromium/issues/detail?id=341598. */
+#define ARMV7_NEON_FUNCTIONAL (1 << 1)
+
+#endif /* !__ASSEMBLER__ */
#endif /* OPENSSL_HEADER_THREAD_H */
diff --git a/crypto/cpu-arm.c b/crypto/cpu-arm.c
index 8b97fc1f..814df266 100644
--- a/crypto/cpu-arm.c
+++ b/crypto/cpu-arm.c
@@ -64,9 +64,9 @@
#include "arm_arch.h"
#if defined(__ARM_NEON__)
-uint32_t OPENSSL_armcap_P = ARMV7_NEON;
+uint32_t OPENSSL_armcap_P = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
#else
-uint32_t OPENSSL_armcap_P = ARMV7_NEON;
+uint32_t OPENSSL_armcap_P = ARMV7_NEON_FUNCTIONAL;
#endif
char CRYPTO_is_NEON_capable() {
@@ -81,4 +81,17 @@ void CRYPTO_set_NEON_capable(char neon_capable) {
}
}
+char CRYPTO_is_NEON_functional() {
+ static const uint32_t kWantFlags = ARMV7_NEON | ARMV7_NEON_FUNCTIONAL;
+ return (OPENSSL_armcap_P & kWantFlags) == kWantFlags;
+}
+
+void CRYPTO_set_NEON_functional(char neon_functional) {
+ if (neon_functional) {
+ OPENSSL_armcap_P |= ARMV7_NEON_FUNCTIONAL;
+ } else {
+ OPENSSL_armcap_P &= ~ARMV7_NEON_FUNCTIONAL;
+ }
+}
+
#endif /* defined(OPENSSL_ARM) */
diff --git a/crypto/poly1305/poly1305.c b/crypto/poly1305/poly1305.c
index 256ad69b..9b9c734c 100644
--- a/crypto/poly1305/poly1305.c
+++ b/crypto/poly1305/poly1305.c
@@ -166,7 +166,7 @@ void CRYPTO_poly1305_init(poly1305_state *statep, const uint8_t key[32]) {
uint32_t t0, t1, t2, t3;
#if defined(OPENSSL_ARM)
- if (CRYPTO_is_NEON_capable()) {
+ if (CRYPTO_is_NEON_functional()) {
CRYPTO_poly1305_init_neon(statep, key);
return;
}
@@ -213,7 +213,7 @@ void CRYPTO_poly1305_update(poly1305_state *statep, const uint8_t *in,
struct poly1305_state_st *state = (struct poly1305_state_st *)statep;
#if defined(OPENSSL_ARM)
- if (CRYPTO_is_NEON_capable()) {
+ if (CRYPTO_is_NEON_functional()) {
CRYPTO_poly1305_update_neon(statep, in, in_len);
return;
}
@@ -256,7 +256,7 @@ void CRYPTO_poly1305_finish(poly1305_state *statep, uint8_t mac[16]) {
uint32_t b, nb;
#if defined(OPENSSL_ARM)
- if (CRYPTO_is_NEON_capable()) {
+ if (CRYPTO_is_NEON_functional()) {
CRYPTO_poly1305_finish_neon(statep, mac);
return;
}
diff --git a/include/openssl/cpu.h b/include/openssl/cpu.h
index 7423338b..bec157f0 100644
--- a/include/openssl/cpu.h
+++ b/include/openssl/cpu.h
@@ -91,8 +91,21 @@ OPENSSL_EXPORT char CRYPTO_is_NEON_capable();
/* CRYPTO_set_NEON_capable sets the return value of |CRYPTO_is_NEON_capable|.
* By default, unless the code was compiled with |-mfpu=neon|, NEON is assumed
- * not to be present. It is not autodetected. */
+ * not to be present. It is not autodetected. Calling this with a zero
+ * argument also causes |CRYPTO_is_NEON_functional| to return false. */
OPENSSL_EXPORT void CRYPTO_set_NEON_capable(char neon_capable);
+
+/* CRYPTO_is_NEON_functional returns true if the current CPU has a /working/
+ * NEON unit. Some phones have a NEON unit, but the Poly1305 NEON code causes
+ * it to fail. See https://code.google.com/p/chromium/issues/detail?id=341598 */
+OPENSSL_EXPORT char CRYPTO_is_NEON_functional();
+
+/* CRYPTO_set_NEON_functional sets the "NEON functional" flag. For
+ * |CRYPTO_is_NEON_functional| to return true, both this flag and the NEON flag
+ * must be true. By default NEON is assumed to be functional if the code was
+ * 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);
#endif /* OPENSSL_ARM */