From 6b4b14ae719c4f46ea70600d63b0d50dc727ff3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Manuel=20P=C3=A9gouri=C3=A9-Gonnard?= Date: Mon, 13 Apr 2026 12:34:03 +0200 Subject: [PATCH] ecp: fix implementation-defined behaviour MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The comment about optimizing compiler's likely behaviour has been checked with GCC and Clang on x86-64, 32-bit Arm and 64-bit Arm. Signed-off-by: Manuel Pégourié-Gonnard --- library/ecp_curves.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/library/ecp_curves.c b/library/ecp_curves.c index 0da1d974f7..3baed93439 100644 --- a/library/ecp_curves.c +++ b/library/ecp_curves.c @@ -5018,7 +5018,16 @@ int mbedtls_ecp_mod_p192_raw(mbedtls_mpi_uint *Np, size_t Nn) static inline int8_t extract_carry(int64_t cur) { - return (int8_t) (cur >> 32); + /* + * Extract the signed carry without relying on `cur >> 32` for negative `cur`, + * since signed right shift is implementation-defined. Shift as uint64_t, then + * sign-extend explicitly. + * + * Modern optimizing compilers will likely generate the same code + * as the less portable (int8_t) (cur >> 32) anyway. + */ + uint32_t hi = (uint32_t) (((uint64_t) cur) >> 32); + return (int8_t) ((int64_t) hi - ((int64_t) (hi >> 31) << 32)); } #define ADD(j) cur += A(j)