diff --git a/ChangeLog.d/fix-ilp32.txt b/ChangeLog.d/fix-ilp32.txt new file mode 100644 index 0000000000..3f18ac5c5b --- /dev/null +++ b/ChangeLog.d/fix-ilp32.txt @@ -0,0 +1,4 @@ +Bugfix + * Fix a compilation failure in the constant_time module when + building for arm64_32 (e.g., for watchos). Reported by Paulo + Coutinho in #7787. diff --git a/library/bn_mul.h b/library/bn_mul.h index c5994f7049..43dd5c298f 100644 --- a/library/bn_mul.h +++ b/library/bn_mul.h @@ -248,27 +248,39 @@ #endif /* AMD64 */ -#if defined(__aarch64__) +// The following assembly code assumes that a pointer will fit in a 64-bit register +// (including ILP32 __aarch64__ ABIs such as on watchOS, hence the 2^32 - 1) +#if defined(__aarch64__) && (UINTPTR_MAX == 0xfffffffful || UINTPTR_MAX == 0xfffffffffffffffful) +/* + * There are some issues around different compilers requiring different constraint + * syntax for updating pointers from assembly code (see notes for + * MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT in common.h), especially on aarch64_32 (aka ILP32). + * + * For this reason we cast the pointers to/from uintptr_t here. + */ #define MULADDC_X1_INIT \ - asm( + do { uintptr_t muladdc_d = (uintptr_t) d, muladdc_s = (uintptr_t) s; asm( #define MULADDC_X1_CORE \ - "ldr x4, [%2], #8 \n\t" \ - "ldr x5, [%1] \n\t" \ + "ldr x4, [%x2], #8 \n\t" \ + "ldr x5, [%x1] \n\t" \ "mul x6, x4, %4 \n\t" \ "umulh x7, x4, %4 \n\t" \ "adds x5, x5, x6 \n\t" \ "adc x7, x7, xzr \n\t" \ "adds x5, x5, %0 \n\t" \ "adc %0, x7, xzr \n\t" \ - "str x5, [%1], #8 \n\t" + "str x5, [%x1], #8 \n\t" #define MULADDC_X1_STOP \ - : "+r" (c), "+r" (d), "+r" (s), "+m" (*(uint64_t (*)[16]) d) \ + : "+r" (c), \ + "+r" (muladdc_d), \ + "+r" (muladdc_s), \ + "+m" (*(uint64_t (*)[16]) d) \ : "r" (b), "m" (*(const uint64_t (*)[16]) s) \ : "x4", "x5", "x6", "x7", "cc" \ - ); + ); d = (mbedtls_mpi_uint *)muladdc_d; s = (mbedtls_mpi_uint *)muladdc_s; } while (0); #endif /* Aarch64 */ diff --git a/library/common.h b/library/common.h index b48a1fc667..ba9cb75c08 100644 --- a/library/common.h +++ b/library/common.h @@ -169,6 +169,27 @@ inline void mbedtls_xor(unsigned char *r, const unsigned char *a, const unsigned #endif /* *INDENT-ON* */ +/* + * Define the constraint used for pointer operands to asm. + * + * This is normally the usual "r", but for aarch64_32 (aka ILP32, + * as found in watchos), "p" is required to avoid warnings from clang. + * + * Note that clang does not recognise '+p' or '=p', and armclang + * does not recognise 'p' at all. + */ +#if defined(__aarch64__) && defined(MBEDTLS_HAVE_ASM) +#if UINTPTR_MAX == 0xfffffffful +/* ILP32: Specify the pointer operand slightly differently, as per #7787. */ +#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "p" +#elif UINTPTR_MAX == 0xfffffffffffffffful +/* Normal case (64-bit pointers): use "r" as the constraint for pointer operands to asm */ +#define MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT "r" +#else +#error Unrecognised pointer size for aarch64 +#endif +#endif + /* Always provide a static assert macro, so it can be used unconditionally. * It will expand to nothing on some systems. * Can be used outside functions (but don't add a trailing ';' in that case: diff --git a/library/constant_time.c b/library/constant_time.c index c823b78894..2faba69e45 100644 --- a/library/constant_time.c +++ b/library/constant_time.c @@ -63,7 +63,9 @@ * only used here. */ #if defined(MBEDTLS_EFFICIENT_UNALIGNED_ACCESS) && defined(MBEDTLS_HAVE_ASM) -#if defined(__arm__) || defined(__thumb__) || defined(__thumb2__) || defined(__aarch64__) +#if ((defined(__arm__) || defined(__thumb__) || defined(__thumb2__)) && \ + (UINTPTR_MAX == 0xfffffffful)) || defined(__aarch64__) +/* We check pointer sizes to avoid issues with them not matching register size requirements */ #define MBEDTLS_EFFICIENT_UNALIGNED_VOLATILE_ACCESS #endif #endif @@ -79,7 +81,7 @@ static inline uint32_t mbedtls_get_unaligned_volatile_uint32(volatile const unsi #if defined(__arm__) || defined(__thumb__) || defined(__thumb2__) asm volatile ("ldr %0, [%1]" : "=r" (r) : "r" (p) :); #elif defined(__aarch64__) - asm volatile ("ldr %w0, [%1]" : "=r" (r) : "r" (p) :); + asm volatile ("ldr %w0, [%1]" : "=r" (r) : MBEDTLS_ASM_AARCH64_PTR_CONSTRAINT(p) :); #endif return r; }