Do not use NEON for AES-CBC on aarch64
Signed-off-by: Dave Rodgman <dave.rodgman@arm.com>
diff --git a/library/aes.c b/library/aes.c
index 6d8cf2e..6a7e610 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -1035,6 +1035,24 @@
}
#if defined(MBEDTLS_CIPHER_MODE_CBC)
+
+#if defined(__ARM_NEON) && defined(__aarch64__)
+ /* Avoid using the NEON implementation of mbedtls_xor. Because of the dependency on
+ * the result for the next block in CBC, and the cost of transferring that data from
+ * NEON registers, it is faster to use the following on aarch64.
+ * For 32-bit arm, NEON should be faster. */
+#define CBC_XOR_16(r, a, b) do { \
+ mbedtls_put_unaligned_uint64(r, \
+ mbedtls_get_unaligned_uint64(a) ^ \
+ mbedtls_get_unaligned_uint64(b)); \
+ mbedtls_put_unaligned_uint64(r + 8, \
+ mbedtls_get_unaligned_uint64(a + 8) ^ \
+ mbedtls_get_unaligned_uint64(b + 8)); \
+} while (0)
+#else
+#define CBC_XOR_16(r, a, b) mbedtls_xor(r, a, b, 16)
+#endif
+
/*
* AES-CBC buffer encryption/decryption
*/
@@ -1077,8 +1095,7 @@
if (ret != 0) {
goto exit;
}
-
- mbedtls_xor(output, output, iv, 16);
+ CBC_XOR_16(output, output, iv);
memcpy(iv, temp, 16);
@@ -1088,7 +1105,7 @@
}
} else {
while (length > 0) {
- mbedtls_xor(output, input, ivp, 16);
+ CBC_XOR_16(output, input, ivp);
ret = mbedtls_aes_crypt_ecb(ctx, mode, output, output);
if (ret != 0) {