diff --git a/ssh.h b/ssh.h index 1ccc0740c..c604554b2 100644 --- a/ssh.h +++ b/ssh.h @@ -550,7 +550,8 @@ int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn, int dsa_generate(struct dss_key *key, int bits, progfn_t pfn, void *pfnparam); Bignum primegen(int bits, int modulus, int residue, Bignum factor, - int phase, progfn_t pfn, void *pfnparam); + int phase, progfn_t pfn, void *pfnparam, unsigned firstbits); +void invent_firstbits(unsigned *one, unsigned *two); /* diff --git a/sshdssg.c b/sshdssg.c index 3eb68d46e..3d7b0ef69 100644 --- a/sshdssg.c +++ b/sshdssg.c @@ -9,6 +9,7 @@ int dsa_generate(struct dss_key *key, int bits, progfn_t pfn, void *pfnparam) { Bignum qm1, power, g, h, tmp; + unsigned pfirst, qfirst; int progress; /* @@ -70,15 +71,16 @@ int dsa_generate(struct dss_key *key, int bits, progfn_t pfn, pfn(pfnparam, PROGFN_READY, 0, 0); + invent_firstbits(&pfirst, &qfirst); /* * Generate q: a prime of length 160. */ - key->q = primegen(160, 2, 2, NULL, 1, pfn, pfnparam); + key->q = primegen(160, 2, 2, NULL, 1, pfn, pfnparam, qfirst); /* * Now generate p: a prime of length `bits', such that p-1 is * divisible by q. */ - key->p = primegen(bits-160, 2, 2, key->q, 2, pfn, pfnparam); + key->p = primegen(bits-160, 2, 2, key->q, 2, pfn, pfnparam, pfirst); /* * Next we need g. Raise 2 to the power (p-1)/q modulo p, and diff --git a/sshprime.c b/sshprime.c index 96fe49c7c..03b9c7282 100644 --- a/sshprime.c +++ b/sshprime.c @@ -838,11 +838,19 @@ static const unsigned short primes[] = { * more than a multiple of a dirty great bignum. In this case * `bits' gives the size of the factor by which we _multiply_ * that bignum, rather than the size of the whole number. + * + * - for the basically cosmetic purposes of generating keys of the + * length actually specified rather than off by one bit, we permit + * the caller to provide an unsigned integer 'firstbits' which will + * match the top few bits of the returned prime. (That is, there + * will exist some n such that (returnvalue >> n) == firstbits.) If + * 'firstbits' is not needed, specifying it to either 0 or 1 is + * an adequate no-op. */ Bignum primegen(int bits, int modulus, int residue, Bignum factor, - int phase, progfn_t pfn, void *pfnparam) + int phase, progfn_t pfn, void *pfnparam, unsigned firstbits) { - int i, k, v, byte, bitsleft, check, checks; + int i, k, v, byte, bitsleft, check, checks, fbsize; unsigned long delta; unsigned long moduli[NPRIMES + 1]; unsigned long residues[NPRIMES + 1]; @@ -853,6 +861,10 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor, byte = 0; bitsleft = 0; + fbsize = 0; + while (firstbits >> fbsize) /* work out how to align this */ + fbsize++; + STARTOVER: pfn(pfnparam, PROGFN_PROGRESS, phase, ++progress); @@ -865,9 +877,11 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor, */ p = bn_power_2(bits - 1); for (i = 0; i < bits; i++) { - if (i == 0 || i == bits - 1) + if (i == 0 || i == bits - 1) { v = (i != 0 || !factor) ? 1 : 0; - else { + } else if (i >= bits - fbsize) { + v = (firstbits >> (i - (bits - fbsize))) & 1; + } else { if (bitsleft <= 0) bitsleft = 8, byte = random_byte(); v = byte & 1; @@ -1041,3 +1055,32 @@ Bignum primegen(int bits, int modulus, int residue, Bignum factor, freebn(pm1); return p; } + +/* + * Invent a pair of values suitable for use as 'firstbits' in the + * above function, such that their product is at least 2. + * + * 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!' + */ +void invent_firstbits(unsigned *one, unsigned *two) +{ + /* + * Our criterion is that any number in the range [one,one+1) + * multiplied by any number in the range [two,two+1) should have + * the highest bit set. It should be clear that we can trivially + * test this by multiplying the smallest values in each interval, + * i.e. the ones we actually invented. + */ + do { + *one = 0x100 | random_byte(); + *two = 0x100 | random_byte(); + } while (*one * *two < 0x20000); +} diff --git a/sshrsag.c b/sshrsag.c index eb714ad60..dbe89409a 100644 --- a/sshrsag.c +++ b/sshrsag.c @@ -10,6 +10,7 @@ int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn, void *pfnparam) { Bignum pm1, qm1, phi_n; + unsigned pfirst, qfirst; /* * Set up the phase limits for the progress report. We do this @@ -59,10 +60,11 @@ int rsa_generate(struct RSAKey *key, int bits, progfn_t pfn, * general that's slightly more fiddly to arrange. By choosing * a prime e, we can simplify the criterion.) */ + invent_firstbits(&pfirst, &qfirst); key->p = primegen(bits / 2, RSA_EXPONENT, 1, NULL, - 1, pfn, pfnparam); + 1, pfn, pfnparam, pfirst); key->q = primegen(bits - bits / 2, RSA_EXPONENT, 1, NULL, - 2, pfn, pfnparam); + 2, pfn, pfnparam, qfirst); /* * Ensure p > q, by swapping them if not.