Unify BN_rshift design
authorCesar Pereida Garcia <cesar.pereidagarcia@tut.fi>
Wed, 16 Oct 2019 09:10:18 +0000 (12:10 +0300)
committerNicola Tuveri <nic.tuv@gmail.com>
Thu, 17 Oct 2019 11:25:10 +0000 (14:25 +0300)
This commit aims at refactoring the `BN_rshift` by making it a wrapper
around `bn_rshift_fixed_top`, in order to match the current design of
`BN_lshift`, as suggested in the discussion at
https://github.com/openssl/openssl/pull/10122#discussion_r332474277 .

As described in the code, by refactoring this function, `BN_rshift`
provides a constant-time behavior for sufficiently[!] zero-padded inputs
under the following assumptions: `|n < BN_BITS2|` or `|n / BN_BITS2|`
being non-secret.

Notice that `BN_rshift` returns a canonical representation of the
BIGNUM, if a `fixed_top` representation is required, the caller should
call `bn_rshift_fixed_top` instead.

Reviewed-by: Nicola Tuveri <nic.tuv@gmail.com>
Reviewed-by: Matt Caswell <matt@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/10196)

crypto/bn/bn_shift.c

index b1f8dbd2d343ac679f2c792eaa1b20d77f04ed88..cdf66933e9e80dd53cfdbab1f2b576e216b3cee5 100644 (file)
@@ -152,57 +152,19 @@ int bn_lshift_fixed_top(BIGNUM *r, const BIGNUM *a, int n)
 
 int BN_rshift(BIGNUM *r, const BIGNUM *a, int n)
 {
-    int i, j, nw, lb, rb;
-    BN_ULONG *t, *f;
-    BN_ULONG l, tmp;
-
-    bn_check_top(r);
-    bn_check_top(a);
+    int ret = 0;
 
     if (n < 0) {
         BNerr(BN_F_BN_RSHIFT, BN_R_INVALID_SHIFT);
         return 0;
     }
 
-    nw = n / BN_BITS2;
-    rb = n % BN_BITS2;
-    lb = BN_BITS2 - rb;
-    if (nw >= a->top || a->top == 0) {
-        BN_zero(r);
-        return 1;
-    }
-    i = (BN_num_bits(a) - n + (BN_BITS2 - 1)) / BN_BITS2;
-    if (r != a) {
-        if (bn_wexpand(r, i) == NULL)
-            return 0;
-        r->neg = a->neg;
-    } else {
-        if (n == 0)
-            return 1;           /* or the copying loop will go berserk */
-    }
-
-    f = &(a->d[nw]);
-    t = r->d;
-    j = a->top - nw;
-    r->top = i;
+    ret = bn_rshift_fixed_top(r, a, n);
 
-    if (rb == 0) {
-        for (i = j; i != 0; i--)
-            *(t++) = *(f++);
-    } else {
-        l = *(f++);
-        for (i = j - 1; i != 0; i--) {
-            tmp = (l >> rb) & BN_MASK2;
-            l = *(f++);
-            *(t++) = (tmp | (l << lb)) & BN_MASK2;
-        }
-        if ((l = (l >> rb) & BN_MASK2))
-            *(t) = l;
-    }
-    if (!r->top)
-        r->neg = 0; /* don't allow negative zero */
+    bn_correct_top(r);
     bn_check_top(r);
-    return 1;
+
+    return ret;
 }
 
 /*