diff --git a/library/aes.c b/library/aes.c index 0a61d1b07..bd0317c87 100644 --- a/library/aes.c +++ b/library/aes.c @@ -1824,6 +1824,13 @@ int mbedtls_aes_self_test(int verbose) } else #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) +#if MBEDTLS_AESNI_HAVE_CODE == 1 + mbedtls_printf(" AES note: AESNI code present (assembly implementation).\n"); +#elif MBEDTLS_AESNI_HAVE_CODE == 2 + mbedtls_printf(" AES note: AESNI code present (intrinsics implementation).\n"); +#else +#error Unrecognised value for MBEDTLS_AESNI_HAVE_CODE +#endif if (mbedtls_aesni_has_support(MBEDTLS_AESNI_AES)) { mbedtls_printf(" AES note: using AESNI.\n"); } else diff --git a/library/aesni.h b/library/aesni.h index 51b770f31..82947e458 100644 --- a/library/aesni.h +++ b/library/aesni.h @@ -59,16 +59,16 @@ #define MBEDTLS_AESNI_HAVE_INTRINSICS #endif -/* Choose the implementation of AESNI, if one is available. */ -#undef MBEDTLS_AESNI_HAVE_CODE -/* To minimize disruption when releasing the intrinsics-based implementation, - * favor the assembly-based implementation if it's available. We intend to - * revise this in a later release of Mbed TLS 3.x. In the long run, we will - * likely remove the assembly implementation. */ -#if defined(MBEDTLS_HAVE_X86_64) -#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly -#elif defined(MBEDTLS_AESNI_HAVE_INTRINSICS) +/* Choose the implementation of AESNI, if one is available. + * + * Favor the intrinsics-based implementation if it's available, for better + * maintainability. + * Performance is about the same (see #7380). + * 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) +#define MBEDTLS_AESNI_HAVE_CODE 1 // via assembly #endif #if defined(MBEDTLS_AESNI_HAVE_CODE) diff --git a/tests/scripts/all.sh b/tests/scripts/all.sh index 45f7e982f..a9ee51729 100755 --- a/tests/scripts/all.sh +++ b/tests/scripts/all.sh @@ -3581,6 +3581,56 @@ component_test_malloc_0_null () { tests/ssl-opt.sh -e 'proxy' } +support_test_aesni() { + # Check that gcc targets x86_64 (we can build AESNI), and check for + # AESNI support on the host (we can run AESNI). + # + # The name of this function is possibly slightly misleading, but needs to align + # with the name of the corresponding test, component_test_aesni. + # + # In principle 32-bit x86 can support AESNI, but our implementation does not + # support 32-bit x86, so we check for x86-64. + # 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) +} + +component_test_aesni () { # ~ 60s + # This tests the two AESNI implementations (intrinsics and assembly), and also the plain C + # fallback. It also tests the logic that is used to select which implementation(s) to build. + # + # This test does not require the host to have support for AESNI (if it doesn't, the run-time + # AESNI detection will fallback to the plain C implementation, so the tests will instead + # exercise the plain C impl). + + msg "build: default config with different AES implementations" + scripts/config.py set MBEDTLS_AESNI_C + 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' + # 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" + + # 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' + # 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" + + # test the plain C implementation + scripts/config.py unset MBEDTLS_AESNI_C + msg "AES tests, plain C" + make clean + make test programs/test/selftest CC=gcc CFLAGS='-O2 -Werror' + # check that there is no AESNI code present + ./programs/test/selftest | not grep -q "AESNI code" +} + component_test_aes_only_128_bit_keys () { msg "build: default config + AES_ONLY_128_BIT_KEY_LENGTH" scripts/config.py set MBEDTLS_AES_ONLY_128_BIT_KEY_LENGTH