diff --git a/include/mbedtls/build_info.h b/include/mbedtls/build_info.h index 44ecacf12..7a70e2543 100644 --- a/include/mbedtls/build_info.h +++ b/include/mbedtls/build_info.h @@ -62,6 +62,11 @@ #define MBEDTLS_ARCH_IS_X86 #endif +#if !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ + (defined(_M_ARM64) || defined(_M_ARM64EC)) +#define MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64 +#endif + /* This is defined if the architecture is Armv8-A, or higher */ #if !defined(MBEDTLS_ARCH_IS_ARMV8_A) #if defined(__ARM_ARCH) && defined(__ARM_ARCH_PROFILE) diff --git a/library/aesce.c b/library/aesce.c index 279c5a280..eaaa5b5c3 100644 --- a/library/aesce.c +++ b/library/aesce.c @@ -23,7 +23,7 @@ * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * - * `arm_neon.h` could be included by any header file, so we put these defines + * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_CRYPTO 1 @@ -76,12 +76,6 @@ # endif #endif -#ifdef __ARM_NEON -#include -#else -#error "Target does not support NEON instructions" -#endif - #if !(defined(__ARM_FEATURE_CRYPTO) || defined(__ARM_FEATURE_AES)) || \ defined(MBEDTLS_ENABLE_ARM_CRYPTO_EXTENSIONS_COMPILER_FLAG) # if defined(__ARMCOMPILER_VERSION) @@ -619,6 +613,6 @@ void mbedtls_aesce_gcm_mult(unsigned char c[16], #undef MBEDTLS_POP_TARGET_PRAGMA #endif -#endif /* MBEDTLS_ARCH_IS_ARMV8_A */ +#endif /* MBEDTLS_AESCE_HAVE_CODE */ #endif /* MBEDTLS_AESCE_C */ diff --git a/library/aesce.h b/library/aesce.h index e2bf58a31..a14d085ef 100644 --- a/library/aesce.h +++ b/library/aesce.h @@ -20,7 +20,8 @@ #include "mbedtls/aes.h" -#if defined(MBEDTLS_AESCE_C) && defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(__ARM_NEON) \ +#if defined(MBEDTLS_AESCE_C) \ + && defined(MBEDTLS_ARCH_IS_ARMV8_A) && defined(MBEDTLS_HAVE_NEON_INTRINSICS) \ && (defined(MBEDTLS_COMPILER_IS_GCC) || defined(__clang__) || defined(MSC_VER)) /* MBEDTLS_AESCE_HAVE_CODE is defined if we have a suitable target platform, and a @@ -129,7 +130,7 @@ int mbedtls_aesce_setkey_enc(unsigned char *rk, #error "AES hardware acceleration not supported on this platform / compiler" #endif -#endif /* MBEDTLS_AESCE_C && MBEDTLS_ARCH_IS_ARMV8_A && __ARM_NEON && +#endif /* MBEDTLS_AESCE_C && MBEDTLS_ARCH_IS_ARMV8_A && MBEDTLS_HAVE_NEON_INTRINSICS && (MBEDTLS_COMPILER_IS_GCC || __clang__ || MSC_VER) */ #endif /* MBEDTLS_AESCE_H */ diff --git a/library/alignment.h b/library/alignment.h index 4bca10e8f..4aab8e027 100644 --- a/library/alignment.h +++ b/library/alignment.h @@ -23,11 +23,16 @@ * efficient when this is not defined. */ #if defined(__ARM_FEATURE_UNALIGNED) \ - || defined(__i386__) || defined(__amd64__) || defined(__x86_64__) + || defined(MBEDTLS_ARCH_IS_X86) || defined(MBEDTLS_ARCH_IS_X64) \ + || defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) /* * __ARM_FEATURE_UNALIGNED is defined where appropriate by armcc, gcc 7, clang 9 * (and later versions) for Arm v7 and later; all x86 platforms should have * efficient unaligned access. + * + * https://learn.microsoft.com/en-us/cpp/build/arm64-windows-abi-conventions?view=msvc-170#alignment + * specifies that on Windows-on-Arm64, unaligned access is safe (except for uncached + * device memory). */ #define MBEDTLS_EFFICIENT_UNALIGNED_ACCESS #endif diff --git a/library/bignum.c b/library/bignum.c index 1b7ff5863..1869137c4 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -102,7 +102,8 @@ int mbedtls_mpi_lt_mpi_ct(const mbedtls_mpi *X, * about whether the assignment was made or not. * (Leaking information about the respective sizes of X and Y is ok however.) */ -#if defined(_MSC_VER) && defined(_M_ARM64) && (_MSC_FULL_VER < 193131103) +#if defined(_MSC_VER) && defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) && \ + (_MSC_FULL_VER < 193131103) /* * MSVC miscompiles this function if it's inlined prior to Visual Studio 2022 version 17.1. See: * https://developercommunity.visualstudio.com/t/c-compiler-miscompiles-part-of-mbedtls-library-on/1646989 diff --git a/library/common.h b/library/common.h index bd5a0c392..e532777e7 100644 --- a/library/common.h +++ b/library/common.h @@ -21,7 +21,11 @@ #if defined(__ARM_NEON) #include -#endif /* __ARM_NEON */ +#define MBEDTLS_HAVE_NEON_INTRINSICS +#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) +#include +#define MBEDTLS_HAVE_NEON_INTRINSICS +#endif #if defined(__GNUC__) && !defined(__ARMCC_VERSION) && !defined(__clang__) \ @@ -178,16 +182,16 @@ inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned { size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) -#if defined(__ARM_NEON) && \ - (!defined(MBEDTLS_COMPILER_IS_GCC) || \ - (defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION >= 70300)) +#if defined(MBEDTLS_HAVE_NEON_INTRINSICS) && \ + (!(defined(MBEDTLS_COMPILER_IS_GCC) && MBEDTLS_GCC_VERSION < 70300)) + /* Old GCC versions generate a warning here, so disable the NEON path for these compilers */ for (; (i + 16) <= n; i += 16) { uint8x16_t v1 = vld1q_u8(a + i); uint8x16_t v2 = vld1q_u8(b + i); uint8x16_t x = veorq_u8(v1, v2); vst1q_u8(r + i, x); } -#elif defined(__amd64__) || defined(__x86_64__) || defined(__aarch64__) +#elif defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64) /* This codepath probably only makes sense on architectures with 64-bit registers */ for (; (i + 8) <= n; i += 8) { uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i); @@ -226,7 +230,7 @@ static inline void mbedtls_xor_no_simd(unsigned char *r, { size_t i = 0; #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) -#if defined(__amd64__) || defined(__x86_64__) || defined(__aarch64__) +#if defined(MBEDTLS_ARCH_IS_X64) || defined(MBEDTLS_ARCH_IS_ARM64) /* This codepath probably only makes sense on architectures with 64-bit registers */ for (; (i + 8) <= n; i += 8) { uint64_t x = mbedtls_get_unaligned_uint64(a + i) ^ mbedtls_get_unaligned_uint64(b + i); diff --git a/library/sha256.c b/library/sha256.c index 45ad6d86d..87889817a 100644 --- a/library/sha256.c +++ b/library/sha256.c @@ -28,7 +28,7 @@ * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * - * `arm_neon.h` could be included by any header file, so we put these defines + * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_CRYPTO 1 @@ -62,9 +62,7 @@ # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) -# ifdef __ARM_NEON -# include -# else +# if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) # if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) # warning "Target does not support NEON instructions" # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT @@ -126,12 +124,7 @@ # include # endif # endif -#elif defined(_M_ARM64) -# if defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT) || \ - defined(MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY) -# include -# endif -#else +#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_ONLY # undef MBEDTLS_SHA256_USE_ARMV8_A_CRYPTO_IF_PRESENT #endif @@ -156,7 +149,7 @@ static int mbedtls_a64_crypto_sha256_determine_support(void) { return 1; } -#elif defined(_M_ARM64) +#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) #define WIN32_LEAN_AND_MEAN #include #include diff --git a/library/sha512.c b/library/sha512.c index e7af12175..601125445 100644 --- a/library/sha512.c +++ b/library/sha512.c @@ -19,7 +19,7 @@ * By defining the macros ourselves we gain access to those declarations without * requiring -march on the command line. * - * `arm_neon.h` could be included by any header file, so we put these defines + * `arm_neon.h` is included by common.h, so we put these defines * at the top of this file, before any includes. */ #define __ARM_FEATURE_SHA512 1 @@ -48,9 +48,7 @@ # if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) /* *INDENT-OFF* */ -# ifdef __ARM_NEON -# include -# else +# if !defined(MBEDTLS_HAVE_NEON_INTRINSICS) # error "Target does not support NEON instructions" # endif /* @@ -109,12 +107,7 @@ # include # endif # endif -#elif defined(_M_ARM64) -# if defined(MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT) || \ - defined(MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY) -# include -# endif -#else +#elif !defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) # undef MBEDTLS_SHA512_USE_A64_CRYPTO_ONLY # undef MBEDTLS_SHA512_USE_A64_CRYPTO_IF_PRESENT #endif @@ -142,7 +135,7 @@ static int mbedtls_a64_crypto_sha512_determine_support(void) NULL, 0); return ret == 0 && value != 0; } -#elif defined(_M_ARM64) +#elif defined(MBEDTLS_PLATFORM_IS_WINDOWS_ON_ARM64) /* * As of March 2022, there don't appear to be any PF_ARM_V8_* flags * available to pass to IsProcessorFeaturePresent() to check for