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 */