SP math: montgomery reduction edge case

4 and 6 word specific implementations now handle rare overflow correctly
in last mul-add of loop.
This commit is contained in:
Sean Parkinson
2021-07-06 09:26:07 +10:00
parent 197b959916
commit 08ebd34f31
2 changed files with 38 additions and 4 deletions

View File

@ -11896,10 +11896,12 @@ static int _sp_mont_red(sp_int* a, sp_int* m, sp_int_digit mp)
else if (m->used == 4) {
sp_int_digit l;
sp_int_digit h;
sp_int_digit o2;
l = 0;
h = 0;
o = 0;
o2 = 0;
for (i = 0; i < 4; i++) {
mu = mp * a->dp[i];
if ((i == 3) && (mask != 0)) {
@ -11919,15 +11921,17 @@ static int _sp_mont_red(sp_int* a, sp_int* m, sp_int_digit mp)
SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[2]);
a->dp[i + 2] = l;
l = h;
h = 0;
h = o2;
o2 = 0;
SP_ASM_ADDC_REG(l, h, o);
SP_ASM_ADDC(l, h, a->dp[i + 3]);
SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[3]);
SP_ASM_MUL_ADD(l, h, o2, mu, m->dp[3]);
a->dp[i + 3] = l;
o = h;
l = h;
h = 0;
}
h = o2;
SP_ASM_ADDC(l, h, a->dp[7]);
a->dp[7] = l;
a->dp[8] = h;
@ -11936,10 +11940,12 @@ static int _sp_mont_red(sp_int* a, sp_int* m, sp_int_digit mp)
else if (m->used == 6) {
sp_int_digit l;
sp_int_digit h;
sp_int_digit o2;
l = 0;
h = 0;
o = 0;
o2 = 0;
for (i = 0; i < 6; i++) {
mu = mp * a->dp[i];
if ((i == 5) && (mask != 0)) {
@ -11969,15 +11975,17 @@ static int _sp_mont_red(sp_int* a, sp_int* m, sp_int_digit mp)
SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[4]);
a->dp[i + 4] = l;
l = h;
h = 0;
h = o2;
o2 = 0;
SP_ASM_ADDC_REG(l, h, o);
SP_ASM_ADDC(l, h, a->dp[i + 5]);
SP_ASM_MUL_ADD_NO(l, h, mu, m->dp[5]);
SP_ASM_MUL_ADD(l, h, o2, mu, m->dp[5]);
a->dp[i + 5] = l;
o = h;
l = h;
h = 0;
}
h = o2;
SP_ASM_ADDC(l, h, a->dp[11]);
a->dp[11] = l;
a->dp[12] = h;

View File

@ -35852,6 +35852,7 @@ static int mp_test_mont(mp_int* a, mp_int* m, mp_int* n, mp_int* r, WC_RNG* rng)
0x01, 0x9f, 0x13, 0xbd,
0x1f, 0x13d, 0x45, 0x615
};
int bits[] = { 256, 384, 2048, 3072 };
int i;
int j;
@ -35909,6 +35910,31 @@ static int mp_test_mont(mp_int* a, mp_int* m, mp_int* n, mp_int* r, WC_RNG* rng)
}
}
/* Force carries. */
for (i = 0; i < (int)(sizeof(bits) / sizeof(*bits)); i++) {
/* a = 2^(bits*2) - 1 */
mp_zero(a);
mp_set_bit(a, bits[i] * 2);
mp_sub_d(a, 1, a);
/* m = 2^(bits) - 1 */
mp_zero(m);
mp_set_bit(m, bits[i]);
mp_sub_d(m, 1, m);
mp = 1;
/* result = r = 2^(bits) - 1 */
mp_zero(r);
mp_set_bit(r, bits[i]);
mp_sub_d(r, 1, r);
ret = mp_montgomery_reduce(a, m, mp);
if (ret != MP_OKAY)
return -13240;
/* Result is m or 0 if reduced to range of modulus. */
if (mp_cmp(a, r) != MP_EQ && mp_iszero(a) != MP_YES)
return -13241;
}
return 0;
}
#endif