Enable vpaes for AES_* functions.

This makes the AES_* functions meet our constant-time goals for
platforms where we have vpaes available. In particular, QUIC packet
number encryption needs single-block operations and those should have
vpaes available.

As a bonus, when vpaes is statically available, the aes_nohw_* functions
should be dropped by the linker. (Notably, NEON is guaranteed on
aarch64. Although vpaes-armv8.pl itself may take some more exploration.
https://crbug.com/boringssl/246#c4)

Bug: 263
Change-Id: Ie1c4727a166ec101a8453761757c87dadc188769
Reviewed-on: https://boringssl-review.googlesource.com/c/34875
Commit-Queue: David Benjamin <davidben@google.com>
Reviewed-by: Adam Langley <agl@google.com>
diff --git a/crypto/fipsmodule/aes/aes.c b/crypto/fipsmodule/aes/aes.c
index a9c20d2..8a1ca31 100644
--- a/crypto/fipsmodule/aes/aes.c
+++ b/crypto/fipsmodule/aes/aes.c
@@ -808,15 +808,16 @@
 
 #endif  // NO_ASM || (!X86 && !X86_64 && !ARM)
 
-// Be aware that on x86(-64), the |aes_nohw_*| functions are incompatible with
-// the aes_hw_* functions. The latter set |AES_KEY.rounds| to one less than the
-// true value, which breaks the former. Therefore the two functions cannot mix.
-// Also, on Aarch64, the plain-C code, above, is incompatible with the
-// |aes_hw_*| functions.
+// Be aware that different sets of AES functions use incompatible key
+// representations, varying in format of the key schedule, the |AES_KEY.rounds|
+// value, or both. Therefore they cannot mix. Also, on AArch64, the plain-C
+// code, above, is incompatible with the |aes_hw_*| functions.
 
 void AES_encrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
   if (hwaes_capable()) {
     aes_hw_encrypt(in, out, key);
+  } else if (vpaes_capable()) {
+    vpaes_encrypt(in, out, key);
   } else {
     aes_nohw_encrypt(in, out, key);
   }
@@ -825,6 +826,8 @@
 void AES_decrypt(const uint8_t *in, uint8_t *out, const AES_KEY *key) {
   if (hwaes_capable()) {
     aes_hw_decrypt(in, out, key);
+  } else if (vpaes_capable()) {
+    vpaes_decrypt(in, out, key);
   } else {
     aes_nohw_decrypt(in, out, key);
   }
@@ -833,6 +836,8 @@
 int AES_set_encrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
   if (hwaes_capable()) {
     return aes_hw_set_encrypt_key(key, bits, aeskey);
+  } else if (vpaes_capable()) {
+    return vpaes_set_encrypt_key(key, bits, aeskey);
   } else {
     return aes_nohw_set_encrypt_key(key, bits, aeskey);
   }
@@ -841,6 +846,8 @@
 int AES_set_decrypt_key(const uint8_t *key, unsigned bits, AES_KEY *aeskey) {
   if (hwaes_capable()) {
     return aes_hw_set_decrypt_key(key, bits, aeskey);
+  } else if (vpaes_capable()) {
+    return vpaes_set_decrypt_key(key, bits, aeskey);
   } else {
     return aes_nohw_set_decrypt_key(key, bits, aeskey);
   }
diff --git a/crypto/fipsmodule/aes/mode_wrappers.c b/crypto/fipsmodule/aes/mode_wrappers.c
index 36c657e..ae8a91b 100644
--- a/crypto/fipsmodule/aes/mode_wrappers.c
+++ b/crypto/fipsmodule/aes/mode_wrappers.c
@@ -80,14 +80,16 @@
   }
 
 #if defined(AES_NOHW_CBC)
-  aes_nohw_cbc_encrypt(in, out, len, key, ivec, enc);
-#else
+  if (!vpaes_capable()) {
+    aes_nohw_cbc_encrypt(in, out, len, key, ivec, enc);
+    return;
+  }
+#endif
   if (enc) {
     CRYPTO_cbc128_encrypt(in, out, len, key, ivec, AES_encrypt);
   } else {
     CRYPTO_cbc128_decrypt(in, out, len, key, ivec, AES_decrypt);
   }
-#endif
 }
 
 void AES_ofb128_encrypt(const uint8_t *in, uint8_t *out, size_t length,
diff --git a/crypto/impl_dispatch_test.cc b/crypto/impl_dispatch_test.cc
index efe12b4..f1192a7 100644
--- a/crypto/impl_dispatch_test.cc
+++ b/crypto/impl_dispatch_test.cc
@@ -122,7 +122,8 @@
   AssertFunctionsHit(
       {
           {kFlag_aes_hw_set_encrypt_key, aesni_},
-          // VPAES / BSAES will not be used for the |AES_*| functions.
+          {kFlag_vpaes_set_encrypt_key, ssse3_ && !aesni_},
+          // BSAES will not be used for the |AES_*| functions.
       },
       [] {
         AES_KEY key;
@@ -139,7 +140,8 @@
   AssertFunctionsHit(
       {
           {kFlag_aes_hw_encrypt, aesni_},
-          // VPAES / BSAES will not be used for the |AES_*| functions.
+          {kFlag_vpaes_encrypt, ssse3_ && !aesni_},
+          // BSAES will not be used for the |AES_*| functions.
       },
       [&key] {
         uint8_t in[AES_BLOCK_SIZE] = {0};