diff --git a/ssh.h b/ssh.h index d8bbf465..57ef5eb7 100644 --- a/ssh.h +++ b/ssh.h @@ -1335,7 +1335,6 @@ int eddsa_generate(struct eddsa_key *key, int bits, progfn_t pfn, mp_int *primegen( int bits, int modulus, int residue, mp_int *factor, int phase, progfn_t pfn, void *pfnparam, unsigned firstbits); -void invent_firstbits(unsigned *one, unsigned *two, unsigned min_separation); /* * Connection-sharing API provided by platforms. This function must diff --git a/sshprime.c b/sshprime.c index 79f35c14..638eac22 100644 --- a/sshprime.c +++ b/sshprime.c @@ -239,114 +239,3 @@ mp_int *primegen( */ return p; } - -/* - * Invent a pair of values suitable for use as 'firstbits' in the - * above function, such that their product is at least 2, and such - * that their difference is also at least min_separation. - * - * This is used for generating both RSA and DSA keys which have - * exactly the specified number of bits rather than one fewer - if you - * generate an a-bit and a b-bit number completely at random and - * multiply them together, you could end up with either an (ab-1)-bit - * number or an (ab)-bit number. The former happens log(2)*2-1 of the - * time (about 39%) and, though actually harmless, every time it - * occurs it has a non-zero probability of sparking a user email along - * the lines of 'Hey, I asked PuTTYgen for a 2048-bit key and I only - * got 2047 bits! Bug!' - */ -static inline unsigned firstbits_b_min( - unsigned a, unsigned lo, unsigned hi, unsigned min_separation) -{ - /* To get a large enough product, b must be at least this much */ - unsigned b_min = (2*lo*lo + a - 1) / a; - /* Now enforce a hi) - b_min = hi; - return b_min; -} - -void invent_firstbits(unsigned *one, unsigned *two, unsigned min_separation) -{ - /* - * We'll pick 12 initial bits (number selected at random) for each - * prime, not counting the leading 1. So we want to return two - * values in the range [2^12,2^13) whose product is at least 2^25. - * - * Strategy: count up all the viable pairs, then select a random - * number in that range and use it to pick a pair. - * - * To keep things simple, we'll ensure a < b, and randomly swap - * them at the end. - */ - const unsigned lo = 1<<12, hi = 1<<13, minproduct = 2*lo*lo; - unsigned a, b; - - /* - * Count up the number of prefixes of b that would be valid for - * each prefix of a. - */ - mp_int *total = mp_new(32); - for (a = lo; a < hi; a++) { - unsigned b_min = firstbits_b_min(a, lo, hi, min_separation); - mp_add_integer_into(total, total, hi - b_min); - } - - /* - * Make up a random number in the range [0,2*total). - */ - mp_int *mlo = mp_from_integer(0), *mhi = mp_new(32); - mp_lshift_fixed_into(mhi, total, 1); - mp_int *randval = mp_random_in_range(mlo, mhi); - mp_free(mlo); - mp_free(mhi); - - /* - * Use the low bit of randval as our swap indicator, leaving the - * rest of it in the range [0,total). - */ - unsigned swap = mp_get_bit(randval, 0); - mp_rshift_fixed_into(randval, randval, 1); - - /* - * Now do the same counting loop again to make the actual choice. - */ - a = b = 0; - for (unsigned a_candidate = lo; a_candidate < hi; a_candidate++) { - unsigned b_min = firstbits_b_min(a_candidate, lo, hi, min_separation); - unsigned limit = hi - b_min; - - unsigned b_candidate = b_min + mp_get_integer(randval); - unsigned use_it = 1 ^ mp_hs_integer(randval, limit); - a ^= (a ^ a_candidate) & -use_it; - b ^= (b ^ b_candidate) & -use_it; - - mp_sub_integer_into(randval, randval, limit); - } - - mp_free(randval); - mp_free(total); - - /* - * Check everything came out right. - */ - assert(lo <= a); - assert(a < hi); - assert(lo <= b); - assert(b < hi); - assert(a * b >= minproduct); - assert(b >= a + min_separation); - - /* - * Last-minute optional swap of a and b. - */ - unsigned diff = (a ^ b) & (-swap); - a ^= diff; - b ^= diff; - - *one = a; - *two = b; -} diff --git a/sshrsag.c b/sshrsag.c index c3e39f63..c1418e37 100644 --- a/sshrsag.c +++ b/sshrsag.c @@ -9,6 +9,9 @@ #define RSA_EXPONENT 37 /* we like this prime */ +static void invent_firstbits(unsigned *one, unsigned *two, + unsigned min_separation); + int rsa_generate(RSAKey *key, int bits, progfn_t pfn, void *pfnparam) { @@ -129,3 +132,115 @@ int rsa_generate(RSAKey *key, int bits, progfn_t pfn, return 1; } + +/* + * Invent a pair of values suitable for use as the 'firstbits' values + * for the two RSA primes, such that their product is at least 2, and + * such that their difference is also at least min_separation. + * + * This is used for generating RSA keys which have exactly the + * specified number of bits rather than one fewer - if you generate an + * a-bit and a b-bit number completely at random and multiply them + * together, you could end up with either an (ab-1)-bit number or an + * (ab)-bit number. The former happens log(2)*2-1 of the time (about + * 39%) and, though actually harmless, every time it occurs it has a + * non-zero probability of sparking a user email along the lines of + * 'Hey, I asked PuTTYgen for a 2048-bit key and I only got 2047 bits! + * Bug!' + */ +static inline unsigned firstbits_b_min( + unsigned a, unsigned lo, unsigned hi, unsigned min_separation) +{ + /* To get a large enough product, b must be at least this much */ + unsigned b_min = (2*lo*lo + a - 1) / a; + /* Now enforce a hi) + b_min = hi; + return b_min; +} + +static void invent_firstbits(unsigned *one, unsigned *two, + unsigned min_separation) +{ + /* + * We'll pick 12 initial bits (number selected at random) for each + * prime, not counting the leading 1. So we want to return two + * values in the range [2^12,2^13) whose product is at least 2^25. + * + * Strategy: count up all the viable pairs, then select a random + * number in that range and use it to pick a pair. + * + * To keep things simple, we'll ensure a < b, and randomly swap + * them at the end. + */ + const unsigned lo = 1<<12, hi = 1<<13, minproduct = 2*lo*lo; + unsigned a, b; + + /* + * Count up the number of prefixes of b that would be valid for + * each prefix of a. + */ + mp_int *total = mp_new(32); + for (a = lo; a < hi; a++) { + unsigned b_min = firstbits_b_min(a, lo, hi, min_separation); + mp_add_integer_into(total, total, hi - b_min); + } + + /* + * Make up a random number in the range [0,2*total). + */ + mp_int *mlo = mp_from_integer(0), *mhi = mp_new(32); + mp_lshift_fixed_into(mhi, total, 1); + mp_int *randval = mp_random_in_range(mlo, mhi); + mp_free(mlo); + mp_free(mhi); + + /* + * Use the low bit of randval as our swap indicator, leaving the + * rest of it in the range [0,total). + */ + unsigned swap = mp_get_bit(randval, 0); + mp_rshift_fixed_into(randval, randval, 1); + + /* + * Now do the same counting loop again to make the actual choice. + */ + a = b = 0; + for (unsigned a_candidate = lo; a_candidate < hi; a_candidate++) { + unsigned b_min = firstbits_b_min(a_candidate, lo, hi, min_separation); + unsigned limit = hi - b_min; + + unsigned b_candidate = b_min + mp_get_integer(randval); + unsigned use_it = 1 ^ mp_hs_integer(randval, limit); + a ^= (a ^ a_candidate) & -use_it; + b ^= (b ^ b_candidate) & -use_it; + + mp_sub_integer_into(randval, randval, limit); + } + + mp_free(randval); + mp_free(total); + + /* + * Check everything came out right. + */ + assert(lo <= a); + assert(a < hi); + assert(lo <= b); + assert(b < hi); + assert(a * b >= minproduct); + assert(b >= a + min_separation); + + /* + * Last-minute optional swap of a and b. + */ + unsigned diff = (a ^ b) & (-swap); + a ^= diff; + b ^= diff; + + *one = a; + *two = b; +}