hcrypto: Better RSA key generation (ltm)

This commit is contained in:
Nicolas Williams
2020-04-26 22:10:39 -05:00
parent e4d1a91c13
commit 32517c0627

View File

@@ -466,12 +466,66 @@ mpz2BN(mp_int *s)
return (ret == MP_OKAY) ? bn : NULL;
}
enum gen_pq_type { GEN_P, GEN_Q };
static int
gen_p(int bits, enum gen_pq_type pq_type, uint8_t nibble_pair, mp_int *p, mp_int *e, BN_GENCB *cb)
{
unsigned char *buf;
mp_bool res;
mp_err ret = MP_MEM;
mp_int t1, t2;
size_t len = (bits + 7) / 8;
int trials = mp_prime_rabin_miller_trials(bits);
int counter = 0;
int where = 0; /* Ignore the set-but-unused warning from this */
FIRST(mp_init_multi(&t1, &t2, NULL));
if (ret == MP_OKAY && (buf = malloc(len))) do {
BN_GENCB_call(cb, 2, counter++);
/* random bytes */
ret = (RAND_bytes(buf, len) == 1) ? MP_OKAY : MP_ERR;
/* make it odd */
buf[len - 1] |= 1;
/* ensure the high nibble of the product is at least 128 */
if (pq_type == GEN_P)
buf[0] = (nibble_pair & 0xf0) | (buf[0] & 0x0f);
else
buf[0] = ((nibble_pair & 0x0f) << 4) | (buf[0] & 0x0f);
/* load number */
THEN_MP(mp_from_ubin(p, buf, len));
/* test primality; repeat if not */
THEN_MP(mp_prime_is_prime(p, trials, &res));
if (ret == MP_OKAY && res == MP_NO) continue;
/* check gcd(p - 1, e) == 1 */
THEN_MP(mp_sub_d(p, 1, &t1));
THEN_MP(mp_gcd(&t1, e, &t2));
} while (ret == MP_OKAY && mp_cmp_d(&t2, 1) != MP_EQ);
mp_clear_multi(&t1, &t2, NULL);
free(buf);
return ret;
}
static uint8_t pq_high_nibble_pairs[] = {
0x9f, 0xad, 0xae, 0xaf, 0xbc, 0xbd, 0xbe, 0xbf, 0xcb, 0xcc, 0xcd, 0xce, 0xcf,
0xda, 0xdb, 0xdc, 0xdd, 0xde, 0xdf, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf9,
0xfa, 0xfb, 0xfc, 0xfd, 0xfe, 0xff
};
static int
ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
{
mp_int el, p, q, n, d, dmp1, dmq1, iqmp, t1, t2, t3;
mp_err ret;
int counter, bitsp;
uint8_t high_nibbles = 0;
int bitsp;
int where = 0;
if (bits < 789)
@@ -486,34 +540,19 @@ ltm_rsa_generate_key(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb)
&t1, &t2, &t3, NULL));
THEN_MP(BN2mpz(&el, e));
/*
* randomly pick a pair of high nibbles for p and q to ensure the product's
* high nibble is at least 128
*/
if (ret == MP_OKAY)
ret = (RAND_bytes(&high_nibbles, 1) == 1) ? MP_OKAY : MP_ERR;
high_nibbles %= sizeof(pq_high_nibble_pairs);
high_nibbles = pq_high_nibble_pairs[high_nibbles];
/* generate p and q so that p != q and bits(pq) ~ bits */
counter = 0;
if (ret == MP_OKAY) do {
int trials = mp_prime_rabin_miller_trials(bitsp);
BN_GENCB_call(cb, 2, counter++);
CHECK(random_num(&p, bitsp));
CHECK(mp_prime_next_prime(&p, trials, 0));
THEN_MP(mp_sub_d(&p, 1, &t1));
THEN_MP(mp_gcd(&t1, &el, &t2));
} while(mp_cmp_d(&t2, 1) != 0);
THEN_MP(gen_p(bitsp, GEN_P, high_nibbles, &p, &el, cb));
BN_GENCB_call(cb, 3, 0);
counter = 0;
do {
int trials = mp_prime_rabin_miller_trials(bits - bitsp);
BN_GENCB_call(cb, 2, counter++);
CHECK(random_num(&q, bits - bitsp));
CHECK(mp_prime_next_prime(&q, trials, 0));
if (mp_cmp(&p, &q) == 0) /* don't let p and q be the same */
continue;
THEN_MP(mp_sub_d(&q, 1, &t1));
THEN_MP(mp_gcd(&t1, &el, &t2));
} while(mp_cmp_d(&t2, 1) != 0);
THEN_MP(gen_p(bitsp, GEN_Q, high_nibbles, &q, &el, cb));
/* make p > q */
if (mp_cmp(&p, &q) < 0) {