Merge pull request #7384 from yuhaoth/pr/add-aes-accelerator-only-mode

AES: Add accelerator only mode
diff --git a/.travis.yml b/.travis.yml
index bf5ccd9..3a608f5 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -129,6 +129,30 @@
         - tests/scripts/travis-log-failure.sh
         - tests/context-info.sh
 
+    - name: Arm64 accelerators tests on arm64 host
+      os: linux
+      dist: focal
+      arch: arm64
+      addons:
+        apt:
+          packages:
+          - gcc
+      script:
+        # Do a manual build+test sequence rather than using all.sh.
+        #
+        # This is arm64 host only test for no runtime detection case. Internal
+        # and Open CI do not include Arm64 host, and they check if components
+        # are be tested. As result, it will always fail on `pre-test-check` in
+        # them.
+        - scripts/config.py unset MBEDTLS_AESNI_C
+        - scripts/config.py unset MBEDTLS_PADLOCK_C
+        - scripts/config.py set MBEDTLS_AESCE_C
+        - scripts/config.py set MBEDTLS_AES_USE_HARDWARE_ONLY
+        - make generated_files
+        - make
+        - programs/test/selftest aes | grep "using AESCE"
+        - tests/context-info.sh
+
 after_failure:
 - tests/scripts/travis-log-failure.sh
 
diff --git a/ChangeLog.d/add-aes-hardware-only-option.txt b/ChangeLog.d/add-aes-hardware-only-option.txt
new file mode 100644
index 0000000..a185aff
--- /dev/null
+++ b/ChangeLog.d/add-aes-hardware-only-option.txt
@@ -0,0 +1,6 @@
+Features
+   * New configuration option MBEDTLS_AES_USE_HARDWARE_ONLY introduced. When
+     using CPU-accelerated AES (e.g., Arm Crypto Extensions), this option
+     disables the plain C implementation and the run-time detection for the
+     CPU feature, which reduces code size and avoids the vulnerability of the
+     plain C implementation.
diff --git a/include/mbedtls/check_config.h b/include/mbedtls/check_config.h
index 3d6353e..ca267bd 100644
--- a/include/mbedtls/check_config.h
+++ b/include/mbedtls/check_config.h
@@ -412,10 +412,6 @@
 #error "MBEDTLS_MEMORY_DEBUG defined, but not all prerequisites"
 #endif
 
-#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM)
-#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
-#endif
-
 #if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C)
 #error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites"
 #endif
diff --git a/include/mbedtls/mbedtls_config.h b/include/mbedtls/mbedtls_config.h
index 6a76e88..6ebda97 100644
--- a/include/mbedtls/mbedtls_config.h
+++ b/include/mbedtls/mbedtls_config.h
@@ -4016,4 +4016,18 @@
  */
 //#define MBEDTLS_ECP_WITH_MPI_UINT
 
+/*
+ * Disable plain C implementation for AES.
+ *
+ * When the plain C implementation is enabled, and an implementation using a
+ * special CPU feature (such as MBEDTLS_AESCE_C) is also enabled, runtime
+ * detection will be used to select between them.
+ *
+ * If only one implementation is present, runtime detection will not be used.
+ * This configuration will crash at runtime if running on a CPU without the
+ * necessary features. It will not build unless at least one of MBEDTLS_AESCE_C
+ * and/or MBEDTLS_AESNI_C is enabled & present in the build.
+ */
+//#define MBEDTLS_AES_USE_HARDWARE_ONLY
+
 /** \} name SECTION: Module configuration options */
diff --git a/library/aes.c b/library/aes.c
index fa773ec..774c2ee 100644
--- a/library/aes.c
+++ b/library/aes.c
@@ -33,6 +33,36 @@
 #include "mbedtls/platform.h"
 #include "mbedtls/platform_util.h"
 #include "mbedtls/error.h"
+
+#if defined(__aarch64__)
+#if !defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
+#endif
+#endif
+
+#if defined(__amd64__) || defined(__x86_64__) || \
+    ((defined(_M_X64) || defined(_M_AMD64)) && !defined(_M_ARM64EC))
+#if !defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
+#endif
+#endif
+
+#if defined(__i386__) || defined(_M_IX86)
+#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY) && !defined(MBEDTLS_AESNI_C)
+#error "MBEDTLS_AES_USE_HARDWARE_ONLY defined, but not all prerequisites"
+#endif
+
+#if defined(MBEDTLS_PADLOCK_C)
+#if !defined(MBEDTLS_HAVE_ASM)
+#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites"
+#endif
+#if defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+#error "MBEDTLS_AES_USE_HARDWARE_ONLY cannot be defined when " \
+    "MBEDTLS_PADLOCK_C is set"
+#endif
+#endif
+#endif
+
 #if defined(MBEDTLS_PADLOCK_C)
 #include "padlock.h"
 #endif
@@ -47,7 +77,7 @@
 
 #if !defined(MBEDTLS_AES_ALT)
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
 static int aes_padlock_ace = -1;
 #endif
 
@@ -542,7 +572,7 @@
  * Note that the offset is in units of elements of buf, i.e. 32-bit words,
  * i.e. an offset of 1 means 4 bytes and so on.
  */
-#if (defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)) ||        \
+#if (defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)) ||        \
     (defined(MBEDTLS_AESNI_C) && MBEDTLS_AESNI_HAVE_CODE == 2)
 #define MAY_NEED_TO_ALIGN
 #endif
@@ -554,7 +584,7 @@
 #if defined(MAY_NEED_TO_ALIGN)
     int align_16_bytes = 0;
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
     if (aes_padlock_ace == -1) {
         aes_padlock_ace = mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE);
     }
@@ -595,7 +625,6 @@
 int mbedtls_aes_setkey_enc(mbedtls_aes_context *ctx, const unsigned char *key,
                            unsigned int keybits)
 {
-    unsigned int i;
     uint32_t *RK;
 
     switch (keybits) {
@@ -629,14 +658,15 @@
     }
 #endif
 
-    for (i = 0; i < (keybits >> 5); i++) {
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+    for (unsigned int i = 0; i < (keybits >> 5); i++) {
         RK[i] = MBEDTLS_GET_UINT32_LE(key, i << 2);
     }
 
     switch (ctx->nr) {
         case 10:
 
-            for (i = 0; i < 10; i++, RK += 4) {
+            for (unsigned int i = 0; i < 10; i++, RK += 4) {
                 RK[4]  = RK[0] ^ RCON[i] ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[3])]) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[3])] <<  8) ^
@@ -652,7 +682,7 @@
 #if !defined(MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH)
         case 12:
 
-            for (i = 0; i < 8; i++, RK += 6) {
+            for (unsigned int i = 0; i < 8; i++, RK += 6) {
                 RK[6]  = RK[0] ^ RCON[i] ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[5])]) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[5])] <<  8) ^
@@ -669,7 +699,7 @@
 
         case 14:
 
-            for (i = 0; i < 7; i++, RK += 8) {
+            for (unsigned int i = 0; i < 7; i++, RK += 8) {
                 RK[8]  = RK[0] ^ RCON[i] ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_1(RK[7])]) ^
                          ((uint32_t) FSb[MBEDTLS_BYTE_2(RK[7])] <<  8) ^
@@ -695,6 +725,7 @@
     }
 
     return 0;
+#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
 }
 #endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */
 
@@ -705,10 +736,13 @@
 int mbedtls_aes_setkey_dec(mbedtls_aes_context *ctx, const unsigned char *key,
                            unsigned int keybits)
 {
-    int i, j, ret;
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+    uint32_t *SK;
+#endif
+    int ret;
     mbedtls_aes_context cty;
     uint32_t *RK;
-    uint32_t *SK;
+
 
     mbedtls_aes_init(&cty);
 
@@ -740,15 +774,16 @@
     }
 #endif
 
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
     SK = cty.buf + cty.rk_offset + cty.nr * 4;
 
     *RK++ = *SK++;
     *RK++ = *SK++;
     *RK++ = *SK++;
     *RK++ = *SK++;
-
-    for (i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8) {
-        for (j = 0; j < 4; j++, SK++) {
+    SK -= 8;
+    for (int i = ctx->nr - 1; i > 0; i--, SK -= 8) {
+        for (int j = 0; j < 4; j++, SK++) {
             *RK++ = AES_RT0(FSb[MBEDTLS_BYTE_0(*SK)]) ^
                     AES_RT1(FSb[MBEDTLS_BYTE_1(*SK)]) ^
                     AES_RT2(FSb[MBEDTLS_BYTE_2(*SK)]) ^
@@ -760,7 +795,7 @@
     *RK++ = *SK++;
     *RK++ = *SK++;
     *RK++ = *SK++;
-
+#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
 exit:
     mbedtls_aes_free(&cty);
 
@@ -1062,17 +1097,20 @@
     }
 #endif
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
     if (aes_padlock_ace > 0) {
         return mbedtls_padlock_xcryptecb(ctx, mode, input, output);
     }
 #endif
 
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
     if (mode == MBEDTLS_AES_ENCRYPT) {
         return mbedtls_internal_aes_encrypt(ctx, input, output);
     } else {
         return mbedtls_internal_aes_decrypt(ctx, input, output);
     }
+#endif
+
 }
 
 #if defined(MBEDTLS_CIPHER_MODE_CBC)
@@ -1103,7 +1141,7 @@
         return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH;
     }
 
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
     if (aes_padlock_ace > 0) {
         if (mbedtls_padlock_xcryptcbc(ctx, mode, length, iv, input, output) == 0) {
             return 0;
@@ -1855,11 +1893,6 @@
 #if defined(MBEDTLS_AES_ALT)
         mbedtls_printf("  AES note: alternative implementation.\n");
 #else /* MBEDTLS_AES_ALT */
-#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86)
-        if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
-            mbedtls_printf("  AES note: using VIA Padlock.\n");
-        } else
-#endif
 #if defined(MBEDTLS_AESNI_HAVE_CODE)
 #if MBEDTLS_AESNI_HAVE_CODE == 1
         mbedtls_printf("  AES note: AESNI code present (assembly implementation).\n");
@@ -1872,12 +1905,21 @@
             mbedtls_printf("  AES note: using AESNI.\n");
         } else
 #endif
+#if defined(MBEDTLS_VIA_PADLOCK_HAVE_CODE)
+        if (mbedtls_padlock_has_support(MBEDTLS_PADLOCK_ACE)) {
+            mbedtls_printf("  AES note: using VIA Padlock.\n");
+        } else
+#endif
 #if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
         if (mbedtls_aesce_has_support()) {
             mbedtls_printf("  AES note: using AESCE.\n");
         } else
 #endif
-        mbedtls_printf("  AES note: built-in implementation.\n");
+        {
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
+            mbedtls_printf("  AES note: built-in implementation.\n");
+#endif
+        }
 #endif /* MBEDTLS_AES_ALT */
     }
 
diff --git a/library/aesce.c b/library/aesce.c
index ed3cca1..8aa0789 100644
--- a/library/aesce.c
+++ b/library/aesce.c
@@ -99,6 +99,7 @@
 #include <sys/auxv.h>
 #endif
 
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
 /*
  * AES instruction support detection routine
  */
@@ -113,6 +114,7 @@
     return 1;
 #endif
 }
+#endif
 
 /* Single round of AESCE encryption */
 #define AESCE_ENCRYPT_ROUND                   \
diff --git a/library/aesce.h b/library/aesce.h
index b12bf76..9b8b0bc 100644
--- a/library/aesce.h
+++ b/library/aesce.h
@@ -47,7 +47,12 @@
  *
  * \return         1 if CPU has support for the feature, 0 otherwise
  */
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
 int mbedtls_aesce_has_support(void);
+#else
+#define mbedtls_aesce_has_support() 1
+#endif
+
 
 /**
  * \brief          Internal AES-ECB block encryption and decryption
diff --git a/library/aesni.c b/library/aesni.c
index 3e3dccb..5f25a82 100644
--- a/library/aesni.c
+++ b/library/aesni.c
@@ -41,6 +41,7 @@
 #include <immintrin.h>
 #endif
 
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
 /*
  * AES-NI support detection routine
  */
@@ -70,6 +71,7 @@
 
     return (c & what) != 0;
 }
+#endif /* !MBEDTLS_AES_USE_HARDWARE_ONLY */
 
 #if MBEDTLS_AESNI_HAVE_CODE == 2
 
diff --git a/library/aesni.h b/library/aesni.h
index 82947e4..332a0f0 100644
--- a/library/aesni.h
+++ b/library/aesni.h
@@ -35,13 +35,20 @@
 /* Can we do AESNI with inline assembly?
  * (Only implemented with gas syntax, only for 64-bit.)
  */
-#if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && \
-    (defined(__amd64__) || defined(__x86_64__))   &&  \
-    !defined(MBEDTLS_HAVE_X86_64)
+#if !defined(MBEDTLS_HAVE_X86_64) && \
+    (defined(__amd64__) || defined(__x86_64__) || \
+    defined(_M_X64) || defined(_M_AMD64)) && \
+    !defined(_M_ARM64EC)
 #define MBEDTLS_HAVE_X86_64
 #endif
 
-#if defined(MBEDTLS_AESNI_C)
+#if !defined(MBEDTLS_HAVE_X86) && \
+    (defined(__i386__) || defined(_M_IX86))
+#define MBEDTLS_HAVE_X86
+#endif
+
+#if defined(MBEDTLS_AESNI_C) && \
+    (defined(MBEDTLS_HAVE_X86_64) || defined(MBEDTLS_HAVE_X86))
 
 /* Can we do AESNI with intrinsics?
  * (Only implemented with certain compilers, only for certain targets.)
@@ -67,8 +74,13 @@
  * In the long run, we will likely remove the assembly implementation. */
 #if defined(MBEDTLS_AESNI_HAVE_INTRINSICS)
 #define MBEDTLS_AESNI_HAVE_CODE 2 // via intrinsics
-#elif defined(MBEDTLS_HAVE_X86_64)
+#elif defined(MBEDTLS_HAVE_ASM) && \
+    defined(__GNUC__) && defined(MBEDTLS_HAVE_X86_64)
 #define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly
+#elif defined(__GNUC__)
+#   error "Must use `-mpclmul -msse2 -maes` for MBEDTLS_AESNI_C"
+#else
+#error "MBEDTLS_AESNI_C defined, but neither intrinsics nor assembly available"
 #endif
 
 #if defined(MBEDTLS_AESNI_HAVE_CODE)
@@ -88,7 +100,11 @@
  *
  * \return         1 if CPU has support for the feature, 0 otherwise
  */
+#if !defined(MBEDTLS_AES_USE_HARDWARE_ONLY)
 int mbedtls_aesni_has_support(unsigned int what);
+#else
+#define mbedtls_aesni_has_support(what) 1
+#endif
 
 /**
  * \brief          Internal AES-NI AES-ECB block encryption and decryption
diff --git a/library/gcm.c b/library/gcm.c
index a05e4c3..d49725c 100644
--- a/library/gcm.c
+++ b/library/gcm.c
@@ -884,6 +884,13 @@
             mbedtls_printf("  GCM note: using AESNI.\n");
         } else
 #endif
+
+#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_HAVE_ARM64)
+        if (mbedtls_aesce_has_support()) {
+            mbedtls_printf("  GCM note: using AESCE.\n");
+        } else
+#endif
+
         mbedtls_printf("  GCM note: built-in implementation.\n");
 #endif /* MBEDTLS_GCM_ALT */
     }
diff --git a/library/padlock.h b/library/padlock.h
index b5f0d7d..ae5c486 100644
--- a/library/padlock.h
+++ b/library/padlock.h
@@ -42,6 +42,8 @@
 #if defined(MBEDTLS_HAVE_ASM) && defined(__GNUC__) && defined(__i386__) && \
     !defined(MBEDTLS_HAVE_ASAN)
 
+#define MBEDTLS_VIA_PADLOCK_HAVE_CODE
+
 #ifndef MBEDTLS_HAVE_X86
 #define MBEDTLS_HAVE_X86
 #endif
diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh
index ef3345e..483e6f7 100755
--- a/tests/scripts/all.sh
+++ b/tests/scripts/all.sh
@@ -3950,7 +3950,7 @@
     # We can only grep /proc/cpuinfo on Linux, so this also checks for Linux
     (gcc -v 2>&1 | grep Target | grep -q x86_64) &&
         [[ "$HOSTTYPE" == "x86_64" && "$OSTYPE" == "linux-gnu" ]] &&
-        (grep '^flags' /proc/cpuinfo | grep -qw aes)
+        (lscpu | grep -qw aes)
 }
 
 component_test_aesni () { # ~ 60s
@@ -3963,29 +3963,136 @@
 
     msg "build: default config with different AES implementations"
     scripts/config.py set MBEDTLS_AESNI_C
+    scripts/config.py unset MBEDTLS_AES_USE_HARDWARE_ONLY
     scripts/config.py set MBEDTLS_HAVE_ASM
 
     # test the intrinsics implementation
     msg "AES tests, test intrinsics"
     make clean
-    make test programs/test/selftest CC=gcc CFLAGS='-Werror -Wall -Wextra -mpclmul -msse2 -maes'
+    make CC=gcc CFLAGS='-Werror -Wall -Wextra -mpclmul -msse2 -maes'
     # check that we built intrinsics - this should be used by default when supported by the compiler
-    ./programs/test/selftest | grep "AESNI code" | grep -q "intrinsics"
+    ./programs/test/selftest aes | grep "AESNI code" | grep -q "intrinsics"
 
     # test the asm implementation
     msg "AES tests, test assembly"
     make clean
-    make test programs/test/selftest CC=gcc CFLAGS='-Werror -Wall -Wextra -mno-pclmul -mno-sse2 -mno-aes'
+    make CC=gcc CFLAGS='-Werror -Wall -Wextra -mno-pclmul -mno-sse2 -mno-aes'
     # check that we built assembly - this should be built if the compiler does not support intrinsics
-    ./programs/test/selftest | grep "AESNI code" | grep -q "assembly"
+    ./programs/test/selftest aes | grep "AESNI code" | grep -q "assembly"
 
     # test the plain C implementation
     scripts/config.py unset MBEDTLS_AESNI_C
+    scripts/config.py unset MBEDTLS_AES_USE_HARDWARE_ONLY
     msg "AES tests, plain C"
     make clean
-    make test programs/test/selftest CC=gcc CFLAGS='-O2 -Werror'
+    make CC=gcc CFLAGS='-O2 -Werror'
     # check that there is no AESNI code present
-    ./programs/test/selftest | not grep -q "AESNI code"
+    ./programs/test/selftest aes | not grep -q "AESNI code"
+    not grep -q "AES note: using AESNI" ./programs/test/selftest
+    grep -q "AES note: built-in implementation." ./programs/test/selftest
+
+    # test the intrinsics implementation
+    scripts/config.py set MBEDTLS_AESNI_C
+    scripts/config.py set MBEDTLS_AES_USE_HARDWARE_ONLY
+    msg "AES tests, test AESNI only"
+    make clean
+    make CC=gcc CFLAGS='-Werror -Wall -Wextra -mpclmul -msse2 -maes'
+    ./programs/test/selftest aes | grep -q "AES note: using AESNI"
+    ./programs/test/selftest aes | not grep -q "AES note: built-in implementation."
+    grep -q "AES note: using AESNI" ./programs/test/selftest
+    not grep -q "AES note: built-in implementation." ./programs/test/selftest
+}
+
+
+
+support_test_aesni_m32() {
+    support_test_m32_o0 && (lscpu | grep -qw aes)
+}
+
+component_test_aesni_m32 () { # ~ 60s
+    # This tests are duplicated from component_test_aesni for i386 target
+    #
+    # AESNI intrinsic code supports i386 and assembly code does not support it.
+
+    msg "build: default config with different AES implementations"
+    scripts/config.py set MBEDTLS_AESNI_C
+    scripts/config.py set MBEDTLS_PADLOCK_C
+    scripts/config.py unset MBEDTLS_AES_USE_HARDWARE_ONLY
+    scripts/config.py set MBEDTLS_HAVE_ASM
+
+    # test the intrinsics implementation
+    msg "AES tests, test intrinsics"
+    make clean
+    make CC=gcc CFLAGS='-m32 -Werror -Wall -Wextra -mpclmul -msse2 -maes' LDFLAGS='-m32'
+    # check that we built intrinsics - this should be used by default when supported by the compiler
+    ./programs/test/selftest aes | grep "AESNI code" | grep -q "intrinsics"
+    grep -q "AES note: using AESNI" ./programs/test/selftest
+    grep -q "AES note: built-in implementation." ./programs/test/selftest
+    grep -q "AES note: using VIA Padlock" ./programs/test/selftest
+    grep -q mbedtls_aesni_has_support ./programs/test/selftest
+
+    scripts/config.py set MBEDTLS_AESNI_C
+    scripts/config.py unset MBEDTLS_PADLOCK_C
+    scripts/config.py set MBEDTLS_AES_USE_HARDWARE_ONLY
+    msg "AES tests, test AESNI only"
+    make clean
+    make CC=gcc CFLAGS='-m32 -Werror -Wall -Wextra -mpclmul -msse2 -maes' LDFLAGS='-m32'
+    ./programs/test/selftest aes | grep -q "AES note: using AESNI"
+    ./programs/test/selftest aes | not grep -q "AES note: built-in implementation."
+    grep -q "AES note: using AESNI" ./programs/test/selftest
+    not grep -q "AES note: built-in implementation." ./programs/test/selftest
+    not grep -q "AES note: using VIA Padlock" ./programs/test/selftest
+    not grep -q mbedtls_aesni_has_support ./programs/test/selftest
+}
+
+# For timebeing, no aarch64 gcc available in CI and no arm64 CI node.
+component_build_aes_aesce_armcc () {
+    msg "Build: AESCE test on arm64 platform without plain C."
+    scripts/config.py baremetal
+
+    # armc[56] don't support SHA-512 intrinsics
+    scripts/config.py unset MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT
+
+    # Stop armclang warning about feature detection for A64_CRYPTO.
+    # With this enabled, the library does build correctly under armclang,
+    # but in baremetal builds (as tested here), feature detection is
+    # unavailable, and the user is notified via a #warning. So enabling
+    # this feature would prevent us from building with -Werror on
+    # armclang. Tracked in #7198.
+    scripts/config.py unset MBEDTLS_SHA256_USE_A64_CRYPTO_IF_PRESENT
+    scripts/config.py set MBEDTLS_HAVE_ASM
+
+    msg "AESCE, build with default configuration."
+    scripts/config.py set MBEDTLS_AESCE_C
+    scripts/config.py unset MBEDTLS_AES_USE_HARDWARE_ONLY
+    armc6_build_test "-O1 --target=aarch64-arm-none-eabi -march=armv8-a+crypto"
+
+    msg "AESCE, build AESCE only"
+    scripts/config.py set MBEDTLS_AESCE_C
+    scripts/config.py set MBEDTLS_AES_USE_HARDWARE_ONLY
+    armc6_build_test "-O1 --target=aarch64-arm-none-eabi -march=armv8-a+crypto"
+}
+
+# For timebeing, no VIA Padlock platform available.
+component_build_aes_via_padlock () {
+
+    msg "AES:VIA PadLock, build with default configuration."
+    scripts/config.py unset MBEDTLS_AESNI_C
+    scripts/config.py set MBEDTLS_PADLOCK_C
+    scripts/config.py unset MBEDTLS_AES_USE_HARDWARE_ONLY
+    make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS"
+    grep -q mbedtls_padlock_has_support ./programs/test/selftest
+
+}
+
+support_build_aes_via_padlock_only () {
+    ( [ "$MBEDTLS_TEST_PLATFORM" == "Linux-x86_64" ] || \
+        [ "$MBEDTLS_TEST_PLATFORM" == "Linux-amd64" ] ) && \
+    [ "`dpkg --print-foreign-architectures`" == "i386" ]
+}
+
+support_build_aes_aesce_armcc () {
+    support_build_armcc
 }
 
 component_test_aes_only_128_bit_keys () {
@@ -4253,6 +4360,7 @@
     # build) and not the i386-specific inline assembly.
     msg "build: i386, make, gcc -O0 (ASan build)" # ~ 30s
     scripts/config.py full
+    scripts/config.py unset MBEDTLS_AESNI_C # AESNI depends on cpu modifiers
     make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O0" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, make, gcc -O0 (ASan build)"
@@ -4270,6 +4378,7 @@
     # and go faster for tests.
     msg "build: i386, make, gcc -O2 (ASan build)" # ~ 30s
     scripts/config.py full
+    scripts/config.py unset MBEDTLS_AESNI_C # AESNI depends on cpu modifiers
     make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, make, gcc -O2 (ASan build)"
@@ -4285,6 +4394,7 @@
 component_test_m32_everest () {
     msg "build: i386, Everest ECDH context (ASan build)" # ~ 6 min
     scripts/config.py set MBEDTLS_ECDH_VARIANT_EVEREST_ENABLED
+    scripts/config.py unset MBEDTLS_AESNI_C # AESNI depends on cpu modifiers
     make CC=gcc CFLAGS="$ASAN_CFLAGS -m32 -O2" LDFLAGS="-m32 $ASAN_CFLAGS"
 
     msg "test: i386, Everest ECDH context - main suites (inc. selftests) (ASan build)" # ~ 50s
@@ -4738,6 +4848,7 @@
 
 component_build_mingw () {
     msg "build: Windows cross build - mingw64, make (Link Library)" # ~ 30s
+    scripts/config.py unset MBEDTLS_AESNI_C # AESNI depends on cpu modifiers
     make CC=i686-w64-mingw32-gcc AR=i686-w64-mingw32-ar LD=i686-w64-minggw32-ld CFLAGS='-Werror -Wall -Wextra' WINDOWS_BUILD=1 lib programs
 
     # note Make tests only builds the tests, but doesn't run them
@@ -5042,6 +5153,7 @@
     python3 -m unittest tests/scripts/translate_ciphers.py 2>&1
 }
 
+
 ################################################################
 #### Termination
 ################################################################