From 12b0fc300fbd7c523b0c0c9ce9ce9b8dfd93762d Mon Sep 17 00:00:00 2001 From: Hanno Becker Date: Fri, 11 Oct 2024 15:06:18 +0100 Subject: [PATCH] Document implementation-defined C behaviour in montgomery_reduce() See https://github.com/pq-crystals/kyber/issues/77 Signed-off-by: Hanno Becker --- mlkem/reduce.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/mlkem/reduce.c b/mlkem/reduce.c index 258675139..13b7bb3d7 100644 --- a/mlkem/reduce.c +++ b/mlkem/reduce.c @@ -28,8 +28,6 @@ * < q (C/2^16 + 1/2). **************************************************/ int16_t montgomery_reduce(int32_t a) { - int16_t t; - // Bounds on paper // // - Case |a| < q * C, for some C @@ -43,7 +41,16 @@ int16_t montgomery_reduce(int32_t a) { // Replace C -> C * q in the above and estimate // q / 2^17 < 0.0254. - t = (int16_t)a * QINV; + uint16_t u; + int16_t t; + // Compute a*q^{-1} mod 2^16 in unsigned representatives + u = (uint16_t)a * QINV; + // Lift to signed canonical representative mod 2^16. + // PORTABILITY: This relies on uint16_t -> int16_t + // being implemented as the inverse of int16_t -> uint16_t, + // which is not mandated by the standard. + t = (int16_t)u; + // By construction, the LHS is divisible by 2^16 t = (a - (int32_t)t * KYBER_Q) >> 16; return t; }