1
0
mirror of https://git.tartarus.org/simon/putty.git synced 2025-01-09 17:38:00 +00:00

mp_modmul: cope with oversized base values.

Previously, I checked by assertion that the base was less than the
modulus. There were two things wrong with this policy. Firstly, it's
perfectly _meaningful_ to want to raise a large number to a power mod
a smaller number, even if it doesn't come up often in cryptography;
secondly, I didn't do it right, because the check was based on the
formal sizes (nw fields) of the mp_ints, which meant that it was
possible to have a failure of the assertion even in the case where the
numerical value of the base _was_ less than the modulus.

In particular, this could come up in Diffie-Hellman with a fixed
group, because the fixed group modulus was decoded from an MP_LITERAL
in sshdh.c which gave a minimal value of nw, but the base was the
public value sent by the other end of the connection, which would
sometimes be sent with the leading zero byte required by the SSH-2
mpint encoding, and would cause a value of nw one larger, failing the
assertion.

Fixed by simply using mp_modmul in monty_import, replacing the
previous clever-but-restricted strategy that I wrote when I thought I
could get away without having to write a general division-based
modular reduction at all.
This commit is contained in:
Simon Tatham 2019-02-04 20:19:13 +00:00
parent 10f80777de
commit bd84c5e4b3
2 changed files with 14 additions and 13 deletions

23
mpint.c
View File

@ -1373,21 +1373,19 @@ mp_int *monty_invert(MontyContext *mc, mp_int *x)
/*
* Importing a number into Montgomery representation involves
* multiplying it by r and reducing mod m. We could do this using the
* straightforward mp_modmul, but since we have the machinery to avoid
* division, why don't we use it? If we multiply the number not by r
* itself, but by the residue of r^2 mod m, then we can do an actual
* Montgomery reduction to reduce the result and remove the extra
* factor of r.
* multiplying it by r and reducing mod m. We use the general-purpose
* mp_modmul for this, in case the input number is out of range.
*/
void monty_import_into(MontyContext *mc, mp_int *r, mp_int *x)
{
monty_mul_into(mc, r, x, mc->powers_of_r_mod_m[1]);
}
mp_int *monty_import(MontyContext *mc, mp_int *x)
{
return monty_mul(mc, x, mc->powers_of_r_mod_m[1]);
return mp_modmul(x, mc->powers_of_r_mod_m[0], mc->m);
}
void monty_import_into(MontyContext *mc, mp_int *r, mp_int *x)
{
mp_int *imported = monty_import(mc, x);
mp_copy_into(r, imported);
mp_free(imported);
}
/*
@ -1450,7 +1448,6 @@ mp_int *monty_pow(MontyContext *mc, mp_int *base, mp_int *exponent)
mp_int *mp_modpow(mp_int *base, mp_int *exponent, mp_int *modulus)
{
assert(base->nw <= modulus->nw);
assert(modulus->nw > 0);
assert(modulus->w[0] & 1);

View File

@ -473,6 +473,10 @@ class mpint(MyTestBase):
b, e, m = 0x2B5B93812F253FF91F56B3B4DAD01CA2884B6A80719B0DA4E2159A230C6009EDA97C5C8FD4636B324F9594706EE3AD444831571BA5E17B1B2DFA92DEA8B7E, 0x25, 0xC8FCFD0FD7371F4FE8D0150EFC124E220581569587CCD8E50423FA8D41E0B2A0127E100E92501E5EE3228D12EA422A568C17E0AD2E5C5FCC2AE9159D2B7FB8CB
assert(int(mp_modpow(b, e, m)) == pow(b, e, m))
# Make sure mp_modpow can handle a base larger than the
# modulus, by pre-reducing it
assert(int(mp_modpow(1<<877, 907, 999979)) == pow(2, 877*907, 999979))
def testModsqrt(self):
moduli = [
5, 19, 2**16+1, 2**31-1, 2**128-159, 2**255-19,