From 581c4601612e39ab32b55dfef92efd4d40c1c6fe Mon Sep 17 00:00:00 2001 From: Gilles Peskine Date: Wed, 9 Nov 2022 22:02:16 +0100 Subject: [PATCH] Fix negative zero created by (-A) + (+A) or (-A) - (-A) In mbedtls_mpi_add_mpi() and mbedtls_mpi_sub_mpi(), and by extention mbedtls_mpi_add_int() and mbedtls_mpi_sub_int(), when the resulting value was zero, the sign bit of the result was incorrectly set to -1 when the left-hand operand was negative. This is not a valid mbedtls_mpi representation. Fix this: always set the sign to +1 when the result is 0. Signed-off-by: Gilles Peskine --- library/bignum.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/library/bignum.c b/library/bignum.c index d96c88f09..0e9ff196e 100644 --- a/library/bignum.c +++ b/library/bignum.c @@ -1264,14 +1264,19 @@ static int add_sub_mpi( mbedtls_mpi *X, s = A->s; if( A->s * B->s * flip_B < 0 ) { - if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + int cmp = mbedtls_mpi_cmp_abs( A, B ); + if( cmp >= 0 ) { MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); - X->s = s; + /* If |A| = |B|, the result is 0 and we must set the sign bit + * to +1 regardless of which of A or B was negative. Otherwise, + * since |A| > |B|, the sign is the sign of A. */ + X->s = cmp == 0 ? 1 : s; } else { MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + /* Since |A| < |B|, the sign is the opposite of A. */ X->s = -s; } }