Prefer AES when hardware acceleration is available

ChaCha20-Poly1305 is more efficient in software, but many modern CPUs
have acceleration for AES which makes AES-GCM the more preferable choice
in terms of throughput and battery consumption (i.e., less CPU cycles
per byte).

Use the CPU features as reported by BoringSSL to determine when to
prioritize AES-GCM over ChaCha20-Poly1305. This should be good enough to
say when the trade-off should be made.

(cherry picked from commit 4209803a99fe1c26e5ef66c16dc70e302a428e8a)

Bug: 26945889
Change-Id: I7ae2f3e422e30e83324c08514509cb3e9a506d97
diff --git a/src/main/java/org/conscrypt/NativeCrypto.java b/src/main/java/org/conscrypt/NativeCrypto.java
index be7edc7..693d702 100644
--- a/src/main/java/org/conscrypt/NativeCrypto.java
+++ b/src/main/java/org/conscrypt/NativeCrypto.java
@@ -757,6 +757,12 @@
         SUPPORTED_CIPHER_SUITES[size + 1] = TLS_FALLBACK_SCSV;
     }
 
+    /**
+     * Returns 1 if the BoringSSL believes the CPU has AES accelerated hardware
+     * instructions. Used to determine cipher suite ordering.
+     */
+    public static native int EVP_has_aes_hardware();
+
     public static native long SSL_CTX_new();
 
     // IMPLEMENTATION NOTE: The default list of cipher suites is a trade-off between what we'd like
@@ -768,6 +774,7 @@
     // servers are not required to honor the order. The key rules governing the preference order
     // are:
     // * Prefer Forward Secrecy (i.e., cipher suites that use ECDHE and DHE for key agreement).
+    // * Prefer ChaCha20-Poly1305 to AES-GCM unless hardware support for AES is available.
     // * Prefer AES-GCM to AES-CBC whose MAC-pad-then-encrypt approach leads to weaknesses (e.g.,
     //   Lucky 13).
     // * Prefer 128-bit bulk encryption to 256-bit one, because 128-bit is safe enough while
@@ -777,26 +784,47 @@
     // prevent apps from connecting to servers they were previously able to connect to.
 
     /** X.509 based cipher suites enabled by default (if requested), in preference order. */
-    static final String[] DEFAULT_X509_CIPHER_SUITES = new String[] {
-        "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
-        "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
-        "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
-        "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
-        "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
-        "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
-        "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
-        "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
-        "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
-        "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
-        "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
-        "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
-        "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
-        "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
-        "TLS_RSA_WITH_AES_128_GCM_SHA256",
-        "TLS_RSA_WITH_AES_256_GCM_SHA384",
-        "TLS_RSA_WITH_AES_128_CBC_SHA",
-        "TLS_RSA_WITH_AES_256_CBC_SHA",
-    };
+    static final String[] DEFAULT_X509_CIPHER_SUITES = EVP_has_aes_hardware() == 1 ?
+            new String[] {
+                    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+                    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+                    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+                    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+                    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+                    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+                    "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+                    "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+                    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+                    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+                    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+                    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+                    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+                    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+                    "TLS_RSA_WITH_AES_128_GCM_SHA256",
+                    "TLS_RSA_WITH_AES_256_GCM_SHA384",
+                    "TLS_RSA_WITH_AES_128_CBC_SHA",
+                    "TLS_RSA_WITH_AES_256_CBC_SHA",
+            } :
+            new String[] {
+                    "TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256",
+                    "TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256",
+                    "TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
+                    "TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256",
+                    "TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256",
+                    "TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
+                    "TLS_DHE_RSA_WITH_AES_128_GCM_SHA256",
+                    "TLS_DHE_RSA_WITH_AES_256_GCM_SHA384",
+                    "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+                    "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+                    "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+                    "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+                    "TLS_DHE_RSA_WITH_AES_128_CBC_SHA",
+                    "TLS_DHE_RSA_WITH_AES_256_CBC_SHA",
+                    "TLS_RSA_WITH_AES_128_GCM_SHA256",
+                    "TLS_RSA_WITH_AES_256_GCM_SHA384",
+                    "TLS_RSA_WITH_AES_128_CBC_SHA",
+                    "TLS_RSA_WITH_AES_256_CBC_SHA",
+            };
 
     /** TLS-PSK cipher suites enabled by default (if requested), in preference order. */
     static final String[] DEFAULT_PSK_CIPHER_SUITES = new String[] {
diff --git a/src/main/native/org_conscrypt_NativeCrypto.cpp b/src/main/native/org_conscrypt_NativeCrypto.cpp
index e36a5c5..43ed0aa 100644
--- a/src/main/native/org_conscrypt_NativeCrypto.cpp
+++ b/src/main/native/org_conscrypt_NativeCrypto.cpp
@@ -8024,6 +8024,15 @@
     return tmp_dh;
 }
 
+static jint NativeCrypto_EVP_has_aes_hardware(JNIEnv*, jclass) {
+    int ret = 0;
+#if defined(OPENSSL_IS_BORINGSSL)
+    ret = EVP_has_aes_hardware();
+#endif
+    JNI_TRACE("EVP_has_aes_hardware => %d", ret);
+    return ret;
+}
+
 /*
  * public static native int SSL_CTX_new();
  */
@@ -11197,6 +11206,7 @@
     NATIVE_METHOD(NativeCrypto, i2d_X509_REVOKED, "(J)[B"),
     NATIVE_METHOD(NativeCrypto, X509_supported_extension, "(J)I"),
     NATIVE_METHOD(NativeCrypto, ASN1_TIME_to_Calendar, "(JLjava/util/Calendar;)V"),
+    NATIVE_METHOD(NativeCrypto, EVP_has_aes_hardware, "()I"),
     NATIVE_METHOD(NativeCrypto, SSL_CTX_new, "()J"),
     NATIVE_METHOD(NativeCrypto, SSL_CTX_free, "(J)V"),
     NATIVE_METHOD(NativeCrypto, SSL_CTX_set_session_id_context, "(J[B)V"),