Remove remaining running pointers in BN_div Expressing everything in terms of i makes it at lot easier to tell what words are being written to where, and convince oneself that everything stays in bounds. I kept a wnum variable in there since it's used so frequently but added a note about the bounds. In a higher-level language, wnum would be a slice of width div_n + 1. Bug: 358687140 Change-Id: Iae39b1915f80008ab5ed91e1e7fc5cd1349e8c1e Reviewed-on: https://boringssl-review.googlesource.com/c/boringssl/+/70227 Reviewed-by: Bob Beck <bbe@google.com> Commit-Queue: David Benjamin <davidben@google.com>
diff --git a/crypto/fipsmodule/bn/div.c b/crypto/fipsmodule/bn/div.c index f1588c1..aa2e2e5 100644 --- a/crypto/fipsmodule/bn/div.c +++ b/crypto/fipsmodule/bn/div.c
@@ -236,15 +236,6 @@ } int loop = num_n - div_n; - // Lets setup a 'window' into snum - // This is the part that corresponds to the current - // 'area' being divided - BIGNUM wnum; - wnum.neg = 0; - wnum.d = &(snum->d[loop]); - wnum.width = div_n; - // only needed when BN_ucmp messes up the values between width and max - wnum.dmax = snum->dmax - loop; // so we don't step out of bounds // Get the top 2 words of sdiv. const BN_ULONG d0 = sdiv->d[div_n - 1]; @@ -253,9 +244,6 @@ // The normalization step ensures that |sdiv|'s MSB is one. assert(d0 & (((BN_ULONG)1) << (BN_BITS2 - 1))); - // pointer to the 'top' of snum - BN_ULONG *wnump = &(snum->d[num_n - 1]); - // Setup |res|. |numerator| and |res| may alias, so we save |numerator->neg| // for later. const int numerator_neg = numerator->neg; @@ -273,19 +261,19 @@ // division. Note that Knuth indexes words from most to least significant, so // our index is reversed. Each loop iteration computes res->d[i] of the // quotient and updates snum with the running remainder. Before each loop - // iteration, wnum <= sdiv. - for (int i = loop - 1; i >= 0; i--, wnump--) { - // TODO(crbug.com/358687140): Remove these running pointers. - wnum.d--; - assert(wnum.d == snum->d + i); - assert(wnump == wnum.d + div_n); - - // Knuth step D3: Compute q', an estimate of q = floor(wnum / sdiv) by - // looking at the top words. We must estimate such that q' = q or - // q' = q + 1. + // iteration, the div_n words beginning at snum->d[i+1] must be less than + // snum. + for (int i = loop - 1; i >= 0; i--) { + // The next word of the quotient, q, is floor(wnum / sdiv), where wnum is + // the div_n + 1 words beginning at snum->d[i]. i starts at + // num_n - div_n - 1, so there are at least div_n + 1 words available. + // + // Knuth step D3: Compute q', an estimate of q by looking at the top words + // of wnum and sdiv. We must estimate such that q' = q or q' = q + 1. BN_ULONG q, rm = 0; - BN_ULONG n0 = wnump[0]; - BN_ULONG n1 = wnump[-1]; + BN_ULONG *wnum = snum->d + i; + BN_ULONG n0 = wnum[div_n]; + BN_ULONG n1 = wnum[div_n - 1]; if (n0 == d0) { // Estimate q' = b - 1, where b is the base. q = BN_MASK2; @@ -325,10 +313,11 @@ // q + 1, Knuth uses a loop. A loop will often also correct q + 1 to q, // saving the slightly more expensive underflow handling below. if (div_n > 1) { + BN_ULONG n2 = wnum[div_n - 2]; #ifdef BN_ULLONG BN_ULLONG t2 = (BN_ULLONG)d1 * q; for (;;) { - if (t2 <= ((((BN_ULLONG)rm) << BN_BITS2) | wnump[-2])) { + if (t2 <= ((((BN_ULLONG)rm) << BN_BITS2) | n2)) { break; } q--; @@ -344,7 +333,7 @@ BN_ULONG t2l, t2h; BN_UMULT_LOHI(t2l, t2h, d1, q); for (;;) { - if (t2h < rm || (t2h == rm && t2l <= wnump[-2])) { + if (t2h < rm || (t2h == rm && t2l <= n2)) { break; } q--; @@ -367,10 +356,10 @@ // -sdiv < wnum - sdiv * q < sdiv. If q' = q + 1, the subtraction will // underflow, and we fix it up below. tmp->d[div_n] = bn_mul_words(tmp->d, sdiv->d, div_n, q); - if (bn_sub_words(wnum.d, wnum.d, tmp->d, div_n + 1)) { + if (bn_sub_words(wnum, wnum, tmp->d, div_n + 1)) { q--; // The final addition is expected to overflow, canceling the underflow. - wnum.d[div_n] += bn_add_words(wnum.d, wnum.d, sdiv->d, div_n); + wnum[div_n] += bn_add_words(wnum, wnum, sdiv->d, div_n); } // q is now correct, and wnum has been updated to the running remainder.