File nss-fix_mpi_division.patch of Package mozilla-nss.1915
# HG changeset patch
# User Wan-Teh Chang <wtc@google.com>
# Date 1440523271 25200
# Tue Aug 25 10:21:11 2015 -0700
# Branch NSS_3_20_BRANCH
# Node ID f78a7cba9a4f91dfe6ed85b47884a7361800fbdf
# Parent 099b97bb90938a11c1b826312be1b613655517c2
CVE-2016-1938
MFSA 2016-07
bmo#1190248
bsc#963731
Import of changesets:
a555bf0fc23a981f22ed8ea6da89ef8d0c5ecf56
Bug 1190248: Compute a guess for the next quotient digit correctly in s_mp_div.
r=rrelyea.
608645309ab97aff5f6bf5bb71ddf13cc8a820f5
Bug 1190248: Delete a space at the end of a line.
cfd0ad4726cb1ba1d90946ac194390f56c40fd5b
Bug 1190248: Just initialize the |sign| field of |part| in s_mp_div().
r=rrelyea.
from 3.21
diff --git a/lib/freebl/mpi/mpi.c b/lib/freebl/mpi/mpi.c
--- a/lib/freebl/mpi/mpi.c
+++ b/lib/freebl/mpi/mpi.c
@@ -4191,66 +4191,77 @@ mp_err s_mp_div(mp_int *rem, /* i: di
s_mp_div_2d(quot, (mp_digit)ix);
s_mp_mod_2d(rem, (mp_digit)ix);
return MP_OKAY;
}
MP_SIGN(rem) = ZPOS;
MP_SIGN(div) = ZPOS;
+ MP_SIGN(&part) = ZPOS;
/* A working temporary for division */
MP_CHECKOK( mp_init_size(&t, MP_ALLOC(rem)));
/* Normalize to optimize guessing */
MP_CHECKOK( s_mp_norm(rem, div, &d) );
- part = *rem;
-
/* Perform the division itself...woo! */
MP_USED(quot) = MP_ALLOC(quot);
/* Find a partial substring of rem which is at least div */
/* If we didn't find one, we're finished dividing */
while (MP_USED(rem) > MP_USED(div) || s_mp_cmp(rem, div) >= 0) {
int i;
int unusedRem;
+ int partExtended = 0; /* set to true if we need to extend part */
unusedRem = MP_USED(rem) - MP_USED(div);
MP_DIGITS(&part) = MP_DIGITS(rem) + unusedRem;
MP_ALLOC(&part) = MP_ALLOC(rem) - unusedRem;
MP_USED(&part) = MP_USED(div);
+
+ /* We have now truncated the part of the remainder to the same length as
+ * the divisor. If part is smaller than div, extend part by one digit. */
if (s_mp_cmp(&part, div) < 0) {
-- unusedRem;
#if MP_ARGCHK == 2
assert(unusedRem >= 0);
#endif
-- MP_DIGITS(&part);
++ MP_USED(&part);
++ MP_ALLOC(&part);
+ partExtended = 1;
}
/* Compute a guess for the next quotient digit */
q_msd = MP_DIGIT(&part, MP_USED(&part) - 1);
div_msd = MP_DIGIT(div, MP_USED(div) - 1);
- if (q_msd >= div_msd) {
+ if (!partExtended) {
+ /* In this case, q_msd /= div_msd is always 1. First, since div_msd is
+ * normalized to have the high bit set, 2*div_msd > MP_DIGIT_MAX. Since
+ * we didn't extend part, q_msd >= div_msd. Therefore we know that
+ * div_msd <= q_msd <= MP_DIGIT_MAX < 2*div_msd. Dividing by div_msd we
+ * get 1 <= q_msd/div_msd < 2. So q_msd /= div_msd must be 1. */
q_msd = 1;
- } else if (MP_USED(&part) > 1) {
+ } else {
#if !defined(MP_NO_MP_WORD) && !defined(MP_NO_DIV_WORD)
q_msd = (q_msd << MP_DIGIT_BIT) | MP_DIGIT(&part, MP_USED(&part) - 2);
q_msd /= div_msd;
if (q_msd == RADIX)
--q_msd;
#else
- mp_digit r;
- MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2),
- div_msd, &q_msd, &r) );
+ if (q_msd == div_msd) {
+ q_msd = MP_DIGIT_MAX;
+ } else {
+ mp_digit r;
+ MP_CHECKOK( s_mpv_div_2dx1d(q_msd, MP_DIGIT(&part, MP_USED(&part) - 2),
+ div_msd, &q_msd, &r) );
+ }
#endif
- } else {
- q_msd = 0;
}
#if MP_ARGCHK == 2
assert(q_msd > 0); /* This case should never occur any more. */
#endif
if (q_msd <= 0)
break;
/* See what that multiplies out to */