Avoid negative zero.
authorjsing <jsing@openbsd.org>
Mon, 13 Feb 2023 04:25:37 +0000 (04:25 +0000)
committerjsing <jsing@openbsd.org>
Mon, 13 Feb 2023 04:25:37 +0000 (04:25 +0000)
Whenever setting negative to one (or when it could potentially be one),
always use BN_set_negative() since it checks for a zero valued bignum and
will not permit negative to be set in this case. Since BN_is_zero()
currently relies on top == 0, call BN_set_negative() after top has been
set (or bn_correct_top() has been called).

This fixes a long standing issue where -0 and +0 have been permitted,
however multiple code paths (such as BN_cmp()) fail to treat these as
equivalent.

Prompted by Guido Vranken who is adding negative zero fuzzing to oss-fuzz.

ok tb@

lib/libcrypto/bn/bn_add.c
lib/libcrypto/bn/bn_div.c
lib/libcrypto/bn/bn_mont.c
lib/libcrypto/bn/bn_mpi.c
lib/libcrypto/bn/bn_mul.c
lib/libcrypto/bn/bn_print.c
lib/libcrypto/bn/bn_recp.c
lib/libcrypto/bn/bn_shift.c
lib/libcrypto/bn/bn_sqr.c
lib/libcrypto/bn/bn_word.c

index dc525db..8ae9bbe 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_add.c,v 1.21 2023/02/02 18:39:26 jsing Exp $ */
+/* $OpenBSD: bn_add.c,v 1.22 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -381,7 +381,8 @@ BN_add(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
                }
        }
 
-       r->neg = r_neg;
+       BN_set_negative(r, r_neg);
+
        return ret;
 }
 
@@ -409,6 +410,7 @@ BN_sub(BIGNUM *r, const BIGNUM *a, const BIGNUM *b)
                }
        }
 
-       r->neg = r_neg;
+       BN_set_negative(r, r_neg);
+
        return ret;
 }
index acacfb1..7ada277 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_div.c,v 1.36 2023/01/31 06:08:23 jsing Exp $ */
+/* $OpenBSD: bn_div.c,v 1.37 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -338,10 +338,10 @@ BN_div_internal(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
        wnump = &(snum->d[num_n - 1]);
 
        /* Setup to 'res' */
-       res->neg = (numerator->neg ^ divisor->neg);
        if (!bn_wexpand(res, (loop + 1)))
                goto err;
        res->top = loop - no_branch;
+       BN_set_negative(res, numerator->neg ^ divisor->neg);
        resp = &(res->d[loop - 1]);
 
        /* space for temp */
@@ -414,8 +414,7 @@ BN_div_internal(BIGNUM *quotient, BIGNUM *remainder, const BIGNUM *numerator,
                int neg = numerator->neg;
 
                BN_rshift(remainder, snum, norm_shift);
-               if (!BN_is_zero(remainder))
-                       remainder->neg = neg;
+               BN_set_negative(remainder, neg);
        }
 
        if (no_branch)
index 6e3d3fa..4f2d454 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_mont.c,v 1.36 2023/02/01 06:23:13 jsing Exp $ */
+/* $OpenBSD: bn_mont.c,v 1.37 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -413,9 +413,9 @@ BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
                if (!bn_wexpand(r, num))
                        return (0);
                if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
-                       r->neg = a->neg^b->neg;
                        r->top = num;
                        bn_correct_top(r);
+                       BN_set_negative(r, a->neg ^ b->neg);
                        return (1);
                }
        }
@@ -471,7 +471,7 @@ BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
        if (!bn_wexpand(r, max))
                return (0);
 
-       r->neg ^= n->neg;
+       BN_set_negative(r, r->neg ^ n->neg);
        np = n->d;
        rp = r->d;
 
@@ -497,7 +497,7 @@ BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
        if (!bn_wexpand(ret, nl))
                return (0);
        ret->top = nl;
-       ret->neg = r->neg;
+       BN_set_negative(ret, r->neg);
 
        rp = ret->d;
        ap = &(r->d[nl]);
index 9ad28b9..e3b9ba0 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_mpi.c,v 1.11 2022/11/26 16:08:51 tb Exp $ */
+/* $OpenBSD: bn_mpi.c,v 1.12 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -127,7 +127,7 @@ BN_mpi2bn(const unsigned char *d, int n, BIGNUM *ain)
                        BN_free(a);
                return (NULL);
        }
-       a->neg = neg;
+       BN_set_negative(a, neg);
        if (neg) {
                BN_clear_bit(a, BN_num_bits(a) - 1);
        }
index bd67910..38c01da 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_mul.c,v 1.30 2023/01/23 12:17:57 jsing Exp $ */
+/* $OpenBSD: bn_mul.c,v 1.31 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -1003,10 +1003,10 @@ BN_mul(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, BN_CTX *ctx)
        }
 
        rr->top = rn;
-       rr->neg = a->neg ^ b->neg;
-
        bn_correct_top(rr);
 
+       BN_set_negative(rr, a->neg ^ b->neg);
+
        if (r != rr)
                BN_copy(r, rr);
  done:
index 7251e4d..7e0683b 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_print.c,v 1.37 2022/11/26 16:08:51 tb Exp $ */
+/* $OpenBSD: bn_print.c,v 1.38 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -251,7 +251,8 @@ BN_hex2bn(BIGNUM **bn, const char *a)
        }
        ret->top = h;
        bn_correct_top(ret);
-       ret->neg = neg;
+
+       BN_set_negative(ret, neg);
 
        *bn = ret;
        return (num);
@@ -317,9 +318,11 @@ BN_dec2bn(BIGNUM **bn, const char *a)
                        j = 0;
                }
        }
-       ret->neg = neg;
 
        bn_correct_top(ret);
+
+       BN_set_negative(ret, neg);
+
        *bn = ret;
        return (num);
 
@@ -344,7 +347,7 @@ BN_asc2bn(BIGNUM **bn, const char *a)
                        return 0;
        }
        if (*a == '-')
-               (*bn)->neg = 1;
+               BN_set_negative(*bn, 1);
        return 1;
 }
 
index 150b588..117f893 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_recp.c,v 1.17 2022/11/26 16:08:51 tb Exp $ */
+/* $OpenBSD: bn_recp.c,v 1.18 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -221,8 +221,9 @@ BN_div_recp(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, BN_RECP_CTX *recp,
        }
 #endif
 
-       r->neg = BN_is_zero(r) ? 0 : m->neg;
-       d->neg = m->neg^recp->N.neg;
+       BN_set_negative(r, m->neg);
+       BN_set_negative(d, m->neg ^ recp->N.neg);
+
        ret = 1;
 
 err:
index 5fd6687..eee3436 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_shift.c,v 1.20 2023/01/11 04:26:24 jsing Exp $ */
+/* $OpenBSD: bn_shift.c,v 1.21 2023/02/13 04:25:37 jsing Exp $ */
 /*
  * Copyright (c) 2022, 2023 Joel Sing <jsing@openbsd.org>
  *
@@ -83,10 +83,10 @@ bn_lshift(BIGNUM *r, const BIGNUM *a, int n)
        }
 
        r->top = count;
-       r->neg = a->neg;
-
        bn_correct_top(r);
 
+       BN_set_negative(r, a->neg);
+
        return 1;
 }
 
@@ -139,10 +139,10 @@ bn_rshift(BIGNUM *r, const BIGNUM *a, int n)
        *dst = *src >> rshift;
 
        r->top = count;
-       r->neg = a->neg;
-
        bn_correct_top(r);
 
+       BN_set_negative(r, a->neg);
+
        return 1;
 }
 
index bd5f43b..5332d17 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_sqr.c,v 1.24 2023/02/09 09:58:53 jsing Exp $ */
+/* $OpenBSD: bn_sqr.c,v 1.25 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -420,10 +420,10 @@ BN_sqr(BIGNUM *r, const BIGNUM *a, BN_CTX *ctx)
        }
 
        rr->top = rn;
-       rr->neg = 0;
-
        bn_correct_top(rr);
 
+       rr->neg = 0;
+
        if (rr != r)
                BN_copy(r, rr);
 
index 7077d3a..a44221c 100644 (file)
@@ -1,4 +1,4 @@
-/* $OpenBSD: bn_word.c,v 1.17 2023/01/28 16:33:34 jsing Exp $ */
+/* $OpenBSD: bn_word.c,v 1.18 2023/02/13 04:25:37 jsing Exp $ */
 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
@@ -152,8 +152,7 @@ BN_add_word(BIGNUM *a, BN_ULONG w)
        if (a->neg) {
                a->neg = 0;
                i = BN_sub_word(a, w);
-               if (!BN_is_zero(a))
-                       a->neg=!(a->neg);
+               BN_set_negative(a, 1);
                return (i);
        }
        for (i = 0; w != 0 && i < a->top; i++) {
@@ -190,13 +189,13 @@ BN_sub_word(BIGNUM *a, BN_ULONG w)
        if (a->neg) {
                a->neg = 0;
                i = BN_add_word(a, w);
-               a->neg = 1;
+               BN_set_negative(a, 1);
                return (i);
        }
 
        if ((a->top == 1) && (a->d[0] < w)) {
                a->d[0] = w - a->d[0];
-               a->neg = 1;
+               BN_set_negative(a, 1);
                return (1);
        }
        i = 0;