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

Fix RSA key gen at awkward sizes mod BIGNUM_INT_BITS.

If you try to generate (say) a 2049-bit RSA key, then primegen will
try to generate a 1025-bit prime. It will do it by making a random
1024-bit mp_int (that is, one strictly _less_ than 2^1024), and then
trying to set bit 1024. But that will fail an assertion in mp_set_bit,
because the number of random bits is a multiple of BIGNUM_INT_BITS, so
an mp_int of the minimum size that can hold the random bits is not
quite big enough to hold the extra bit at the top.

Fix: change the strategy in primegen so that we allocate the mp_int
large enough to hold even the top bit, and copy in the random numbers
via mp_or_into.

There's a second bug hiding behind that one. If the key has odd size,
then the two primes are generated with different bit lengths. If the
overall key size is congruent to 1 mod (2*BIGNUM_INT_BITS), then the
two primes will be allocated as mp_ints with different numbers of
words, leading to another assertion failure in the mp_cond_swap that
sorts the primes into a consistent order.

Fix for that one: if the primes are being generated different bit
lengths, then we arrange those lengths to be already in the right
order, and replace the mp_cond_swap with an assert() that checks the
ordering is already correct.

Combined effect: now you should be able to successfully generate a
2049-bit key without assertion failures.
This commit is contained in:
Simon Tatham 2019-04-17 18:15:23 +01:00
parent ca6d278c10
commit 36525cc003
2 changed files with 21 additions and 8 deletions

View File

@ -194,10 +194,12 @@ mp_int *primegen(
* random number with the top bit set and the bottom bit clear,
* multiply it by `factor', and add one.
*/
mp_int *p = mp_random_bits(bits - 1);
mp_int *p = mp_power_2(bits - 1); /* ensure top bit is 1 */
mp_int *r = mp_random_bits(bits - 1);
mp_or_into(p, p, r);
mp_free(r);
mp_set_bit(p, 0, factor ? 0 : 1); /* set bottom bit appropriately */
mp_set_bit(p, 0, factor ? 0 : 1); /* bottom bit */
mp_set_bit(p, bits-1, 1); /* top bit */
for (size_t i = 0; i < fbsize; i++)
mp_set_bit(p, bits-fbsize + i, 1 & (firstbits >> i));

View File

@ -71,15 +71,26 @@ int rsa_generate(RSAKey *key, int bits, progfn_t pfn,
* but it doesn't cost much to make sure.)
*/
invent_firstbits(&pfirst, &qfirst, 2);
mp_int *p = primegen(bits / 2, RSA_EXPONENT, 1, NULL,
1, pfn, pfnparam, pfirst);
mp_int *q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL,
2, pfn, pfnparam, qfirst);
int qbits = bits / 2;
int pbits = bits - qbits;
assert(pbits >= qbits);
mp_int *p = primegen(pbits, RSA_EXPONENT, 1, NULL,
1, pfn, pfnparam, pfirst);
mp_int *q = primegen(qbits, RSA_EXPONENT, 1, NULL,
2, pfn, pfnparam, qfirst);
/*
* Ensure p > q, by swapping them if not.
*
* We only need to do this if the two primes were generated with
* the same number of bits (i.e. if the requested key size is
* even) - otherwise it's already guaranteed!
*/
mp_cond_swap(p, q, mp_cmp_hs(q, p));
if (pbits == qbits) {
mp_cond_swap(p, q, mp_cmp_hs(q, p));
} else {
assert(mp_cmp_hs(p, q));
}
/*
* Now we have p, q and e. All we need to do now is work out