From db9cb4c4972974346e31825ad3f0cdc9858f3194 Mon Sep 17 00:00:00 2001 From: Frank Denis Date: Mon, 14 Sep 2026 18:47:30 +0000 Subject: [PATCH] Fix crash on x86 CPUs without AES support in clang-cl builds When built with clang-cl, the library could pick an implementation that uses AES instructions even on a CPU that doesn't have them, which crashes on the first call. It happened because different source files disagreed about whether the plain software version was available, and the picker had a fallback that assumed AES was always present. This reorganizes the code the same way libaegis does it: the compiler and CPU checks now live in one shared header that every file uses, so they all agree, and an implementation is only chosen when the CPU really supports it. Keeping the two projects consistent should make them easier to maintain. Also lets clang-cl use the fastest HiAE implementation, which was needlessly turned off for it, and adds a clang-cl build to CI. --- .github/workflows/clang-cl.yml | 38 +++++++++++++ Makefile | 7 +-- scripts/amalgamate.py | 18 +++++++ src/common/common.h | 82 ++++++++++++++++++++++++++++ src/common/cpu.h | 32 +++++++++++ src/hiae/HiAE.c | 94 ++++---------------------------- src/hiae/HiAE_internal.h | 2 + src/hiae/HiAE_software.c | 5 +- src/hiae/HiAE_vaes_avx512.c | 3 +- src/hiaex2/HiAEx2.c | 99 ++++------------------------------ src/hiaex2/HiAEx2_internal.h | 2 + src/hiaex2/HiAEx2_software.c | 4 +- src/hiaex4/HiAEx4.c | 94 ++++---------------------------- src/hiaex4/HiAEx4_internal.h | 2 + src/hiaex4/HiAEx4_software.c | 5 +- 15 files changed, 215 insertions(+), 272 deletions(-) create mode 100644 .github/workflows/clang-cl.yml create mode 100644 src/common/common.h create mode 100644 src/common/cpu.h diff --git a/.github/workflows/clang-cl.yml b/.github/workflows/clang-cl.yml new file mode 100644 index 0000000..15dfbbb --- /dev/null +++ b/.github/workflows/clang-cl.yml @@ -0,0 +1,38 @@ +name: Clang-CL + +permissions: + contents: read + +on: + push: + branches: [ "main" ] + pull_request: + branches: [ "main" ] + +env: + BUILD_TYPE: Release + +jobs: + build: + runs-on: windows-latest + + steps: + - uses: actions/checkout@v4 + + - uses: ilammy/msvc-dev-cmd@v1 + + - name: Environment + run: clang-cl -E -Xclang -dM nul + + - name: Configure CMake + env: + CC: clang-cl + CMAKE_GENERATOR: Ninja + run: cmake -B ${{github.workspace}}/build -DCMAKE_BUILD_TYPE=${{env.BUILD_TYPE}} + + - name: Build + run: cmake --build ${{github.workspace}}/build --config ${{env.BUILD_TYPE}} + + - name: Test + working-directory: ${{github.workspace}}/build + run: ctest -C ${{env.BUILD_TYPE}} --output-on-failure -LE performance diff --git a/Makefile b/Makefile index f0dca46..c561f64 100644 --- a/Makefile +++ b/Makefile @@ -33,9 +33,10 @@ IMPL_SOURCES += src/hiaex4/HiAEx4_vaes_avx512.c ALL_SOURCES = $(MAIN_SOURCE) $(IMPL_SOURCES) # Header dependencies -HIAE_HEADERS = include/HiAE.h src/hiae/HiAE_internal.h src/hiae/softaes.h -HIAEX2_HEADERS = include/HiAEx2.h src/hiaex2/HiAEx2_internal.h src/hiaex2/softaes.h -HIAEX4_HEADERS = include/HiAEx4.h src/hiaex4/HiAEx4_internal.h src/hiaex4/softaes.h +COMMON_HEADERS = src/common/common.h src/common/cpu.h +HIAE_HEADERS = include/HiAE.h src/hiae/HiAE_internal.h src/hiae/softaes.h $(COMMON_HEADERS) +HIAEX2_HEADERS = include/HiAEx2.h src/hiaex2/HiAEx2_internal.h src/hiaex2/softaes.h $(COMMON_HEADERS) +HIAEX4_HEADERS = include/HiAEx4.h src/hiaex4/HiAEx4_internal.h src/hiaex4/softaes.h $(COMMON_HEADERS) CLI_HEADERS = hiae-cli/src/platform.h hiae-cli/src/key_utils.h hiae-cli/src/file_ops.h TEST_HEADERS = test/timing.h diff --git a/scripts/amalgamate.py b/scripts/amalgamate.py index 364edaf..72b68d9 100755 --- a/scripts/amalgamate.py +++ b/scripts/amalgamate.py @@ -107,6 +107,8 @@ def remove_includes(content, implementation_file=None): # Keep system includes, remove local includes if ('"HiAE.h"' in include_file or '"HiAE_internal.h"' in include_file or + '"../common/common.h"' in include_file or + '"../common/cpu.h"' in include_file or '"softaes.h"' in include_file): continue # Keep all other includes (system headers, intrinsics, etc.) @@ -307,6 +309,21 @@ def create_amalgamation(): header_body = re.sub(r'#ifdef __cplusplus.*?#endif', '', header_body, flags=re.DOTALL) amalgamated_content += header_body + # Add shared capability-detection headers (src/common) + for common_name, guard in (("common.h", "hiae_common_H"), ("cpu.h", "hiae_cpu_H")): + common_header = read_file(repo_root / "src" / "common" / common_name) + if not common_header: + print(f"Failed to read src/common/{common_name}") + return False + common_content = re.search(r'#define ' + guard + r'\s*\n(.*?)#endif /\* ' + guard + r' \*/', + common_header, re.DOTALL) + if not common_content: + print(f"Failed to parse src/common/{common_name}") + return False + common_body = common_content.group(1) + common_body = re.sub(r'#include\s+"[^"]+"', '', common_body) + amalgamated_content += f"\n/* Shared definitions from src/common/{common_name} */\n{common_body}\n" + # Add internal header content internal_header = read_file(source_path / "HiAE_internal.h") if not internal_header: @@ -320,6 +337,7 @@ def create_amalgamation(): internal_body = internal_content.group(1) # Remove includes we've already handled internal_body = re.sub(r'#include\s+"HiAE\.h"', '', internal_body) + internal_body = re.sub(r'#include\s+"\.\./common/[^"]+"', '', internal_body) internal_body = re.sub(r'#include\s+<[^>]+>', '', internal_body) amalgamated_content += f"\n/* Internal definitions from HiAE_internal.h */\n{internal_body}\n" diff --git a/src/common/common.h b/src/common/common.h new file mode 100644 index 0000000..b6cf210 --- /dev/null +++ b/src/common/common.h @@ -0,0 +1,82 @@ +#ifndef hiae_common_H +#define hiae_common_H + +/* + * Compiler / target capability detection shared by every translation unit. + * + * This header must be included by all implementation files and by the + * dispatchers, so that all of them agree on which implementations exist. + * Keeping this block in a single place is what prevents two translation + * units from disagreeing about the availability of an implementation. + */ + +#ifdef __linux__ +# define HAVE_SYS_AUXV_H +# define HAVE_GETAUXVAL +#endif +#ifdef __ANDROID_API__ +# if __ANDROID_API__ < 18 +# undef HAVE_GETAUXVAL +# endif +# define HAVE_ANDROID_GETCPUFEATURES +#endif +#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64) +# define HAVE_CPUID +# define NATIVE_LITTLE_ENDIAN +# if defined(__clang__) || defined(__GNUC__) +# define HAVE_AVX_ASM +# endif +# define HAVE_AVXINTRIN_H +# define HAVE_AVX2INTRIN_H +# define HAVE_AVX512FINTRIN_H +# define HAVE_TMMINTRIN_H +# define HAVE_WMMINTRIN_H +# define HAVE_VAESINTRIN_H +# ifdef __GNUC__ +# if !__has_include() +# undef HAVE_VAESINTRIN_H +# endif +# endif +/* target pragmas don't define these flags on clang-cl (an alternative clang driver for Windows) */ +# if defined(__clang__) && defined(_MSC_BUILD) && defined(_MSC_VER) && \ + (defined(_M_IX86) || defined(_M_AMD64)) && !defined(__SSE3__) +# undef __SSE3__ +# undef __SSSE3__ +# undef __SSE4_1__ +# undef __AVX__ +# undef __AVX2__ +# undef __AVX512F__ +# undef __AES__ +# undef __VAES__ + +# define __SSE3__ 1 +# define __SSSE3__ 1 +# define __SSE4_1__ 1 +# define __AVX__ 1 +# define __AVX2__ 1 +# define __AVX512F__ 1 +# define __AES__ 1 +# define __VAES__ 1 + +/* + * The macros above were synthesized so that the intrinsics headers expose + * everything the target pragmas can emit. They describe the compiler, not + * the CPU the code will run on, and must therefore never be used to decide + * which implementations get compiled in. See cpu.h. + */ +# define HIAE_ISA_MACROS_SYNTHESIZED 1 +# endif + +#endif + +#ifdef DISABLE_AVX2 +# undef HAVE_AVXINTRIN_H +# undef HAVE_AVX2INTRIN_H +# undef HAVE_AVX512FINTRIN_H +# undef HAVE_VAESINTRIN_H +#endif +#ifdef DISABLE_AVX512 +# undef HAVE_AVX512FINTRIN_H +#endif + +#endif /* hiae_common_H */ diff --git a/src/common/cpu.h b/src/common/cpu.h new file mode 100644 index 0000000..3b3b826 --- /dev/null +++ b/src/common/cpu.h @@ -0,0 +1,32 @@ +#ifndef hiae_cpu_H +#define hiae_cpu_H + +#include "common.h" + +/* + * HIAE*_HAS_HW_AES is set when the compilation baseline itself guarantees that + * a hardware implementation of the corresponding variant is present. In that + * case the software implementation is not compiled in at all. + * + * Every translation unit that needs to know whether the software + * implementation exists must test these macros, and only these macros. + * Testing __AES__ & friends directly is not equivalent: on clang-cl they are + * synthesized in common.h so that the intrinsics headers work, and they then + * describe the compiler rather than the target CPU. + */ + +#if defined(__ARM_FEATURE_CRYPTO) +# define HIAE_HAS_HW_AES +# define HIAEX2_HAS_HW_AES +# define HIAEX4_HAS_HW_AES +#elif !defined(HIAE_ISA_MACROS_SYNTHESIZED) +# if defined(__AES__) && defined(__VAES__) && defined(__AVX512F__) +# define HIAE_HAS_HW_AES +# define HIAEX4_HAS_HW_AES +# endif +# if defined(__AES__) && defined(__VAES__) && defined(__AVX2__) +# define HIAEX2_HAS_HW_AES +# endif +#endif + +#endif /* hiae_cpu_H */ diff --git a/src/hiae/HiAE.c b/src/hiae/HiAE.c index 34e21bb..76d1263 100644 --- a/src/hiae/HiAE.c +++ b/src/hiae/HiAE.c @@ -11,67 +11,6 @@ #include #include -#ifdef __linux__ -# define HAVE_SYS_AUXV_H -# define HAVE_GETAUXVAL -#endif -#ifdef __ANDROID_API__ -# if __ANDROID_API__ < 18 -# undef HAVE_GETAUXVAL -# endif -# define HAVE_ANDROID_GETCPUFEATURES -#endif -#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64) -# define HAVE_CPUID -# define NATIVE_LITTLE_ENDIAN -# if defined(__clang__) || defined(__GNUC__) -# define HAVE_AVX_ASM -# endif -# define HAVE_AVXINTRIN_H -# define HAVE_AVX2INTRIN_H -# define HAVE_AVX512FINTRIN_H -# define HAVE_TMMINTRIN_H -# define HAVE_WMMINTRIN_H -# define HAVE_VAESINTRIN_H -# ifdef __GNUC__ -# if !__has_include() -# undef HAVE_VAESINTRIN_H -# endif -# endif -/* target pragmas don't define these flags on clang-cl (an alternative clang driver for Windows) */ -# if defined(__clang__) && defined(_MSC_BUILD) && defined(_MSC_VER) && \ - (defined(_M_IX86) || defined(_M_AMD64)) && !defined(__SSE3__) -# undef __SSE3__ -# undef __SSSE3__ -# undef __SSE4_1__ -# undef __AVX__ -# undef __AVX2__ -# undef __AVX512F__ -# undef __AES__ -# undef __VAES__ - -# define __SSE3__ 1 -# define __SSSE3__ 1 -# define __SSE4_1__ 1 -# define __AVX__ 1 -# define __AVX2__ 1 -# define __AVX512F__ 1 -# define __AES__ 1 -# define __VAES__ 1 -# endif - -#endif - -#ifdef DISABLE_AVX2 -# undef HAVE_AVXINTRIN_H -# undef HAVE_AVX2INTRIN_H -# undef HAVE_AVX512FINTRIN_H -# undef HAVE_VAESINTRIN_H -#endif -#ifdef DISABLE_AVX512 -# undef HAVE_AVX512FINTRIN_H -#endif - #ifdef HAVE_ANDROID_GETCPUFEATURES # include #endif @@ -374,8 +313,7 @@ hiae_runtime_get_cpu_features(void) } // External declarations for implementation tables -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || \ - defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAE_HAS_HW_AES extern const HiAE_impl_t hiae_software_impl; #endif #if defined(__x86_64__) || defined(_M_X64) @@ -395,8 +333,7 @@ hiae_get_impl_by_name(const char *name) return NULL; } -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || \ - defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAE_HAS_HW_AES if (strcmp(name, "Software") == 0) { return (HiAE_impl_t *) &hiae_software_impl; } @@ -450,10 +387,14 @@ hiae_init_dispatch(void) hiae_runtime_get_cpu_features(); } -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || \ - defined(__ARM_FEATURE_CRYPTO)) - // Default to software implementation when hardware AES+VAES+AVX512 is not available + // Start from the implementation the compilation baseline guarantees, then + // upgrade it below if the CPU actually supports something faster. +#ifndef HIAE_HAS_HW_AES hiae_impl = (HiAE_impl_t *) &hiae_software_impl; +#elif defined(__x86_64__) || defined(_M_X64) + hiae_impl = (HiAE_impl_t *) &hiae_aesni_impl; +#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64__) + hiae_impl = (HiAE_impl_t *) &hiae_arm_impl; #endif // Select best available implementation based on CPU features @@ -471,23 +412,6 @@ hiae_init_dispatch(void) } #endif -#if (defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || defined(__ARM_FEATURE_CRYPTO) - // When hardware AES+VAES+AVX512 is available, ensure we have a valid implementation - if (hiae_impl == NULL) { -# if defined(__x86_64__) || defined(_M_X64) - // Fallback to AES-NI on x86-64 if available - if (hiae_aesni_impl.init != NULL) { - hiae_impl = (HiAE_impl_t *) &hiae_aesni_impl; - } -# elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64__) - // Fallback to ARM NEON on ARM64 if available - if (hiae_arm_impl.init != NULL) { - hiae_impl = (HiAE_impl_t *) &hiae_arm_impl; - } -# endif - } -#endif - #ifdef SOFTAES_ENABLED (void) softaes_block_zero; (void) softaes_block_load; diff --git a/src/hiae/HiAE_internal.h b/src/hiae/HiAE_internal.h index e266a62..5e13028 100644 --- a/src/hiae/HiAE_internal.h +++ b/src/hiae/HiAE_internal.h @@ -1,6 +1,8 @@ #ifndef HIAE_INTERNAL_H #define HIAE_INTERNAL_H +#include "../common/common.h" +#include "../common/cpu.h" #include "HiAE.h" #include diff --git a/src/hiae/HiAE_software.c b/src/hiae/HiAE_software.c index e0d37bd..ae35c07 100644 --- a/src/hiae/HiAE_software.c +++ b/src/hiae/HiAE_software.c @@ -2,8 +2,7 @@ #include "HiAE_internal.h" // Only compile software implementation if hardware AES+VAES+AVX512 is not available -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || \ - defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAE_HAS_HW_AES # define FAVOR_PERFORMANCE # include "softaes.h" @@ -720,4 +719,4 @@ const HiAE_impl_t hiae_software_impl = { .name = "Software", .decrypt = HiAE_decrypt_software, .mac = HiAE_mac_software }; -#endif // !defined(__AES__) && !defined(__ARM_FEATURE_CRYPTO) +#endif /* !HIAE_HAS_HW_AES */ diff --git a/src/hiae/HiAE_vaes_avx512.c b/src/hiae/HiAE_vaes_avx512.c index df32914..3fc2589 100644 --- a/src/hiae/HiAE_vaes_avx512.c +++ b/src/hiae/HiAE_vaes_avx512.c @@ -1,8 +1,9 @@ #include "HiAE.h" #include "HiAE_internal.h" +/* clang-cl can build this implementation; MSVC proper cannot (no target pragmas) */ #if (defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64)) && \ - !defined(_MSC_VER) + (!defined(_MSC_VER) || defined(__clang__)) # ifdef __clang__ # if __clang_major__ >= 18 diff --git a/src/hiaex2/HiAEx2.c b/src/hiaex2/HiAEx2.c index 6aa2cfd..d328d08 100644 --- a/src/hiaex2/HiAEx2.c +++ b/src/hiaex2/HiAEx2.c @@ -11,67 +11,6 @@ #include #include -#ifdef __linux__ -# define HAVE_SYS_AUXV_H -# define HAVE_GETAUXVAL -#endif -#ifdef __ANDROID_API__ -# if __ANDROID_API__ < 18 -# undef HAVE_GETAUXVAL -# endif -# define HAVE_ANDROID_GETCPUFEATURES -#endif -#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64) -# define HAVE_CPUID -# define NATIVE_LITTLE_ENDIAN -# if defined(__clang__) || defined(__GNUC__) -# define HAVE_AVX_ASM -# endif -# define HAVE_AVXINTRIN_H -# define HAVE_AVX2INTRIN_H -# define HAVE_AVX512FINTRIN_H -# define HAVE_TMMINTRIN_H -# define HAVE_WMMINTRIN_H -# define HAVE_VAESINTRIN_H -# ifdef __GNUC__ -# if !__has_include() -# undef HAVE_VAESINTRIN_H -# endif -# endif -/* target pragmas don't define these flags on clang-cl (an alternative clang driver for Windows) */ -# if defined(__clang__) && defined(_MSC_BUILD) && defined(_MSC_VER) && \ - (defined(_M_IX86) || defined(_M_AMD64)) && !defined(__SSE3__) -# undef __SSE3__ -# undef __SSSE3__ -# undef __SSE4_1__ -# undef __AVX__ -# undef __AVX2__ -# undef __AVX512F__ -# undef __AES__ -# undef __VAES__ - -# define __SSE3__ 1 -# define __SSSE3__ 1 -# define __SSE4_1__ 1 -# define __AVX__ 1 -# define __AVX2__ 1 -# define __AVX512F__ 1 -# define __AES__ 1 -# define __VAES__ 1 -# endif - -#endif - -#ifdef DISABLE_AVX2 -# undef HAVE_AVXINTRIN_H -# undef HAVE_AVX2INTRIN_H -# undef HAVE_AVX512FINTRIN_H -# undef HAVE_VAESINTRIN_H -#endif -#ifdef DISABLE_AVX512 -# undef HAVE_AVX512FINTRIN_H -#endif - #ifdef HAVE_ANDROID_GETCPUFEATURES # include #endif @@ -374,7 +313,7 @@ hiaex2_runtime_get_cpu_features(void) } // External declarations for implementation tables -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX2__)) || defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAEX2_HAS_HW_AES extern const HiAEx2_impl_t hiaex2_software_impl; #endif #if defined(__x86_64__) || defined(_M_X64) @@ -394,7 +333,7 @@ hiaex2_get_impl_by_name(const char *name) return NULL; } -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX2__)) || defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAEX2_HAS_HW_AES if (strcmp(name, "Software") == 0) { return (HiAEx2_impl_t *) &hiaex2_software_impl; } @@ -448,9 +387,14 @@ hiaex2_init_dispatch(void) hiaex2_runtime_get_cpu_features(); } -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX2__)) || defined(__ARM_FEATURE_CRYPTO)) - // Default to software implementation when hardware AES+VAES+AVX2 is not available + // Start from the implementation the compilation baseline guarantees, then + // upgrade it below if the CPU actually supports something faster. +#ifndef HIAEX2_HAS_HW_AES hiaex2_impl = (HiAEx2_impl_t *) &hiaex2_software_impl; +#elif defined(__x86_64__) || defined(_M_X64) + hiaex2_impl = (HiAEx2_impl_t *) &hiaex2_vaes_avx2_impl; +#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64__) + hiaex2_impl = (HiAEx2_impl_t *) &hiaex2_arm_impl; #endif // Select best available implementation based on CPU features @@ -468,31 +412,6 @@ hiaex2_init_dispatch(void) hiaex2_impl = (HiAEx2_impl_t *) &hiaex2_arm_impl; } #endif - -#if (defined(__AES__) && defined(__VAES__) && defined(__AVX2__)) || defined(__ARM_FEATURE_CRYPTO) - // When hardware AES+VAES+AVX2 is available, ensure we have a valid implementation - if (hiaex2_impl == NULL) { -# if defined(__x86_64__) || defined(_M_X64) - // Fallback to VAES-AVX2 on x86-64 if available - if (hiaex2_vaes_avx2_impl.init != NULL) { - hiaex2_impl = (HiAEx2_impl_t *) &hiaex2_vaes_avx2_impl; - } -# elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64__) - // Fallback to ARM NEON on ARM64 if available - if (hiaex2_arm_impl.init != NULL) { - hiaex2_impl = (HiAEx2_impl_t *) &hiaex2_arm_impl; - } -# endif - } -#elif defined(__AES__) && defined(__AVX__) && (defined(__x86_64__) || defined(_M_X64)) - // When hardware AES+AVX is available, ensure we have a valid implementation - if (hiaex2_impl == NULL) { - // Fallback to AESNI-AVX on x86-64 if available - if (hiaex2_aesni_avx_impl.init != NULL) { - hiaex2_impl = (HiAEx2_impl_t *) &hiaex2_aesni_avx_impl; - } - } -#endif } // Public API function to initialize library diff --git a/src/hiaex2/HiAEx2_internal.h b/src/hiaex2/HiAEx2_internal.h index 58769b6..b06f13c 100644 --- a/src/hiaex2/HiAEx2_internal.h +++ b/src/hiaex2/HiAEx2_internal.h @@ -1,6 +1,8 @@ #ifndef HiAEx2_INTERNAL_H #define HiAEx2_INTERNAL_H +#include "../common/common.h" +#include "../common/cpu.h" #include "HiAEx2.h" #include diff --git a/src/hiaex2/HiAEx2_software.c b/src/hiaex2/HiAEx2_software.c index 9b67e77..a0bcef6 100644 --- a/src/hiaex2/HiAEx2_software.c +++ b/src/hiaex2/HiAEx2_software.c @@ -2,7 +2,7 @@ #include "HiAEx2_internal.h" // Only compile software implementation if hardware AES+VAES+AVX2 is not available -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX2__)) || defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAEX2_HAS_HW_AES # define FAVOR_PERFORMANCE # include "softaes.h" @@ -681,4 +681,4 @@ const HiAEx2_impl_t hiaex2_software_impl = { .name = "Software", .decrypt = HiAEx2_decrypt_software, .mac = HiAEx2_mac_software }; -#endif // !defined(__AES__) && !defined(__ARM_FEATURE_CRYPTO) +#endif /* !HIAEX2_HAS_HW_AES */ diff --git a/src/hiaex4/HiAEx4.c b/src/hiaex4/HiAEx4.c index 183f9b8..1b9b23f 100644 --- a/src/hiaex4/HiAEx4.c +++ b/src/hiaex4/HiAEx4.c @@ -11,67 +11,6 @@ #include #include -#ifdef __linux__ -# define HAVE_SYS_AUXV_H -# define HAVE_GETAUXVAL -#endif -#ifdef __ANDROID_API__ -# if __ANDROID_API__ < 18 -# undef HAVE_GETAUXVAL -# endif -# define HAVE_ANDROID_GETCPUFEATURES -#endif -#if defined(__i386__) || defined(_M_IX86) || defined(__x86_64__) || defined(_M_AMD64) -# define HAVE_CPUID -# define NATIVE_LITTLE_ENDIAN -# if defined(__clang__) || defined(__GNUC__) -# define HAVE_AVX_ASM -# endif -# define HAVE_AVXINTRIN_H -# define HAVE_AVX2INTRIN_H -# define HAVE_AVX512FINTRIN_H -# define HAVE_TMMINTRIN_H -# define HAVE_WMMINTRIN_H -# define HAVE_VAESINTRIN_H -# ifdef __GNUC__ -# if !__has_include() -# undef HAVE_VAESINTRIN_H -# endif -# endif -/* target pragmas don't define these flags on clang-cl (an alternative clang driver for Windows) */ -# if defined(__clang__) && defined(_MSC_BUILD) && defined(_MSC_VER) && \ - (defined(_M_IX86) || defined(_M_AMD64)) && !defined(__SSE3__) -# undef __SSE3__ -# undef __SSSE3__ -# undef __SSE4_1__ -# undef __AVX__ -# undef __AVX2__ -# undef __AVX512F__ -# undef __AES__ -# undef __VAES__ - -# define __SSE3__ 1 -# define __SSSE3__ 1 -# define __SSE4_1__ 1 -# define __AVX__ 1 -# define __AVX2__ 1 -# define __AVX512F__ 1 -# define __AES__ 1 -# define __VAES__ 1 -# endif - -#endif - -#ifdef DISABLE_AVX2 -# undef HAVE_AVXINTRIN_H -# undef HAVE_AVX2INTRIN_H -# undef HAVE_AVX512FINTRIN_H -# undef HAVE_VAESINTRIN_H -#endif -#ifdef DISABLE_AVX512 -# undef HAVE_AVX512FINTRIN_H -#endif - #ifdef HAVE_ANDROID_GETCPUFEATURES # include #endif @@ -374,8 +313,7 @@ hiaex4_runtime_get_cpu_features(void) } // External declarations for implementation tables -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || \ - defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAEX4_HAS_HW_AES extern const HiAEx4_impl_t hiaex4_software_impl; #endif #if defined(__x86_64__) || defined(_M_X64) @@ -394,8 +332,7 @@ hiaex4_get_impl_by_name(const char *name) return NULL; } -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || \ - defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAEX4_HAS_HW_AES if (strcmp(name, "Software") == 0) { return (HiAEx4_impl_t *) &hiaex4_software_impl; } @@ -446,10 +383,14 @@ hiaex4_init_dispatch(void) hiaex4_runtime_get_cpu_features(); } -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || \ - defined(__ARM_FEATURE_CRYPTO)) - // Default to software implementation when hardware AES+VAES+AVX512 is not available + // Start from the implementation the compilation baseline guarantees, then + // upgrade it below if the CPU actually supports something faster. +#ifndef HIAEX4_HAS_HW_AES hiaex4_impl = (HiAEx4_impl_t *) &hiaex4_software_impl; +#elif defined(__x86_64__) || defined(_M_X64) + hiaex4_impl = (HiAEx4_impl_t *) &hiaex4_vaes_avx512_impl; +#elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64__) + hiaex4_impl = (HiAEx4_impl_t *) &hiaex4_arm_impl; #endif // Select best available implementation based on CPU features @@ -465,23 +406,6 @@ hiaex4_init_dispatch(void) hiaex4_impl = (HiAEx4_impl_t *) &hiaex4_arm_impl; } #endif - -#if (defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || defined(__ARM_FEATURE_CRYPTO) - // When hardware AES+VAES+AVX512 is available, ensure we have a valid implementation - if (hiaex4_impl == NULL) { -# if defined(__x86_64__) || defined(_M_X64) - // Fallback to VAES-AVX512 on x86-64 if available - if (hiaex4_vaes_avx512_impl.init != NULL) { - hiaex4_impl = (HiAEx4_impl_t *) &hiaex4_vaes_avx512_impl; - } -# elif defined(__aarch64__) || defined(_M_ARM64) || defined(__arm64__) - // Fallback to ARM NEON on ARM64 if available - if (hiaex4_arm_impl.init != NULL) { - hiaex4_impl = (HiAEx4_impl_t *) &hiaex4_arm_impl; - } -# endif - } -#endif } // Public API function to initialize library diff --git a/src/hiaex4/HiAEx4_internal.h b/src/hiaex4/HiAEx4_internal.h index be4f3e5..171438e 100644 --- a/src/hiaex4/HiAEx4_internal.h +++ b/src/hiaex4/HiAEx4_internal.h @@ -1,6 +1,8 @@ #ifndef HiAEx4_INTERNAL_H #define HiAEx4_INTERNAL_H +#include "../common/common.h" +#include "../common/cpu.h" #include "HiAEx4.h" #include diff --git a/src/hiaex4/HiAEx4_software.c b/src/hiaex4/HiAEx4_software.c index 8b22b30..6179bd6 100644 --- a/src/hiaex4/HiAEx4_software.c +++ b/src/hiaex4/HiAEx4_software.c @@ -2,8 +2,7 @@ #include "HiAEx4_internal.h" // Only compile software implementation if hardware AES+VAES+AVX512 is not available -#if !((defined(__AES__) && defined(__VAES__) && defined(__AVX512F__)) || \ - defined(__ARM_FEATURE_CRYPTO)) +#ifndef HIAEX4_HAS_HW_AES # define FAVOR_PERFORMANCE # include "softaes.h" @@ -706,4 +705,4 @@ const HiAEx4_impl_t hiaex4_software_impl = { .name = "Software", .decrypt = HiAEx4_decrypt_software, .mac = HiAEx4_mac_software }; -#endif // !defined(__AES__) && !defined(__ARM_FEATURE_CRYPTO) +#endif /* !HIAEX4_HAS_HW_AES */