Unwind RSA_generate_multi_prime_key.

Later CLs will unwind the rest of multiprime RSA support. Start with key
generation.

Change-Id: Id20473fd55cf32c27ea4a57f2d2ea11daaffedeb
Reviewed-on: https://boringssl-review.googlesource.com/14870
Reviewed-by: Adam Langley <agl@google.com>
This commit is contained in:
David Benjamin
2017-04-10 18:20:55 -04:00
committed by Adam Langley
parent 43780cbc37
commit 4a2cc28b8c
6 changed files with 14 additions and 196 deletions
-2
View File
@@ -79,8 +79,6 @@ int rsa_default_decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const uint8_t *in, size_t in_len, int padding);
int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
size_t len);
int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
BIGNUM *e_value, BN_GENCB *cb);
int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb);
-9
View File
@@ -213,15 +213,6 @@ int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
return rsa_default_keygen(rsa, bits, e_value, cb);
}
int RSA_generate_multi_prime_key(RSA *rsa, int bits, int num_primes,
BIGNUM *e_value, BN_GENCB *cb) {
if (rsa->meth->multi_prime_keygen) {
return rsa->meth->multi_prime_keygen(rsa, bits, num_primes, e_value, cb);
}
return rsa_default_multi_prime_keygen(rsa, bits, num_primes, e_value, cb);
}
int RSA_encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
const uint8_t *in, size_t in_len, int padding) {
if (rsa->meth->encrypt) {
+10 -144
View File
@@ -770,18 +770,10 @@ static int ensure_bignum(BIGNUM **out) {
return *out != NULL;
}
int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
BIGNUM *e_value, BN_GENCB *cb) {
int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
int prime_bits, ok = -1, n = 0, i, j;
int ok = -1, n = 0;
BN_CTX *ctx = NULL;
STACK_OF(RSA_additional_prime) *additional_primes = NULL;
if (num_primes < 2) {
ok = 0; /* we set our own err */
OPENSSL_PUT_ERROR(RSA, RSA_R_MUST_HAVE_AT_LEAST_TWO_PRIMES);
goto err;
}
ctx = BN_CTX_new();
if (ctx == NULL) {
@@ -796,33 +788,6 @@ int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
goto err;
}
if (num_primes > 2) {
additional_primes = sk_RSA_additional_prime_new_null();
if (additional_primes == NULL) {
goto err;
}
}
for (i = 2; i < num_primes; i++) {
RSA_additional_prime *ap = OPENSSL_malloc(sizeof(RSA_additional_prime));
if (ap == NULL) {
goto err;
}
OPENSSL_memset(ap, 0, sizeof(RSA_additional_prime));
ap->prime = BN_new();
ap->exp = BN_new();
ap->coeff = BN_new();
ap->r = BN_new();
if (ap->prime == NULL ||
ap->exp == NULL ||
ap->coeff == NULL ||
ap->r == NULL ||
!sk_RSA_additional_prime_push(additional_primes, ap)) {
RSA_additional_prime_free(ap);
goto err;
}
}
/* We need the RSA components non-NULL */
if (!ensure_bignum(&rsa->n) ||
!ensure_bignum(&rsa->d) ||
@@ -840,9 +805,10 @@ int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
}
/* generate p and q */
prime_bits = (bits + (num_primes - 1)) / num_primes;
int p_bits = (bits + 1) / 2;
int q_bits = bits - p_bits;
for (;;) {
if (!BN_generate_prime_ex(rsa->p, prime_bits, 0, NULL, NULL, cb) ||
if (!BN_generate_prime_ex(rsa->p, p_bits, 0, NULL, NULL, cb) ||
!BN_sub(r2, rsa->p, BN_value_one()) ||
!BN_gcd(r1, r2, rsa->e, ctx)) {
goto err;
@@ -857,14 +823,13 @@ int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
if (!BN_GENCB_call(cb, 3, 0)) {
goto err;
}
prime_bits = ((bits - prime_bits) + (num_primes - 2)) / (num_primes - 1);
for (;;) {
/* When generating ridiculously small keys, we can get stuck
* continually regenerating the same prime values. Check for
* this and bail if it happens 3 times. */
unsigned int degenerate = 0;
do {
if (!BN_generate_prime_ex(rsa->q, prime_bits, 0, NULL, NULL, cb)) {
if (!BN_generate_prime_ex(rsa->q, q_bits, 0, NULL, NULL, cb)) {
goto err;
}
} while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3));
@@ -890,79 +855,6 @@ int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
goto err;
}
for (i = 2; i < num_primes; i++) {
RSA_additional_prime *ap =
sk_RSA_additional_prime_value(additional_primes, i - 2);
prime_bits = ((bits - BN_num_bits(rsa->n)) + (num_primes - (i + 1))) /
(num_primes - i);
for (;;) {
if (!BN_generate_prime_ex(ap->prime, prime_bits, 0, NULL, NULL, cb)) {
goto err;
}
if (BN_cmp(rsa->p, ap->prime) == 0 ||
BN_cmp(rsa->q, ap->prime) == 0) {
continue;
}
for (j = 0; j < i - 2; j++) {
if (BN_cmp(sk_RSA_additional_prime_value(additional_primes, j)->prime,
ap->prime) == 0) {
break;
}
}
if (j != i - 2) {
continue;
}
if (!BN_sub(r2, ap->prime, BN_value_one()) ||
!BN_gcd(r1, r2, rsa->e, ctx)) {
goto err;
}
if (!BN_is_one(r1)) {
continue;
}
if (i != num_primes - 1) {
break;
}
/* For the last prime we'll check that it makes n large enough. In the
* two prime case this isn't a problem because we generate primes with
* the top two bits set and so the product is always of the expected
* size. In the multi prime case, this doesn't follow. */
if (!BN_mul(r1, rsa->n, ap->prime, ctx)) {
goto err;
}
if (BN_num_bits(r1) == (unsigned) bits) {
break;
}
if (!BN_GENCB_call(cb, 2, n++)) {
goto err;
}
}
/* ap->r is is the product of all the primes prior to the current one
* (including p and q). */
if (!BN_copy(ap->r, rsa->n)) {
goto err;
}
if (i == num_primes - 1) {
/* In the case of the last prime, we calculated n as |r1| in the loop
* above. */
if (!BN_copy(rsa->n, r1)) {
goto err;
}
} else if (!BN_mul(rsa->n, rsa->n, ap->prime, ctx)) {
goto err;
}
if (!BN_GENCB_call(cb, 3, 1)) {
goto err;
}
}
if (BN_cmp(rsa->p, rsa->q) < 0) {
tmp = rsa->p;
rsa->p = rsa->q;
@@ -979,14 +871,6 @@ int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
if (!BN_mul(r0, r1, r2, ctx)) {
goto err; /* (p-1)(q-1) */
}
for (i = 2; i < num_primes; i++) {
RSA_additional_prime *ap =
sk_RSA_additional_prime_value(additional_primes, i - 2);
if (!BN_sub(r3, ap->prime, BN_value_one()) ||
!BN_mul(r0, r0, r3, ctx)) {
goto err;
}
}
if (!BN_mod_inverse(rsa->d, rsa->e, r0, ctx)) {
goto err; /* d */
}
@@ -1011,20 +895,9 @@ int rsa_default_multi_prime_keygen(RSA *rsa, int bits, int num_primes,
goto err;
}
for (i = 2; i < num_primes; i++) {
RSA_additional_prime *ap =
sk_RSA_additional_prime_value(additional_primes, i - 2);
if (!BN_sub(ap->exp, ap->prime, BN_value_one()) ||
!BN_mod(ap->exp, rsa->d, ap->exp, ctx) ||
!BN_MONT_CTX_set_locked(&ap->mont, &rsa->lock, ap->prime, ctx) ||
!bn_mod_inverse_secret_prime(ap->coeff, ap->r, ap->prime, ctx,
ap->mont)) {
goto err;
}
}
rsa->additional_primes = additional_primes;
additional_primes = NULL;
sk_RSA_additional_prime_pop_free(rsa->additional_primes,
RSA_additional_prime_free);
rsa->additional_primes = NULL;
/* The key generation process is complex and thus error-prone. It could be
* disastrous to generate and then use a bad key so double-check that the key
@@ -1043,16 +916,9 @@ err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
sk_RSA_additional_prime_pop_free(additional_primes,
RSA_additional_prime_free);
return ok;
}
int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
return rsa_default_multi_prime_keygen(rsa, bits, 2 /* num primes */, e_value,
cb);
}
/* All of the methods are NULL to make it easier for the compiler/linker to drop
* unused functions. The wrapper functions will select the appropriate
* |rsa_default_*| implementation. */
@@ -1084,7 +950,7 @@ const RSA_METHOD RSA_default_method = {
RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE,
NULL /* keygen (defaults to rsa_default_keygen) */,
NULL /* multi_prime_keygen (defaults to rsa_default_multi_prime_keygen) */,
NULL /* multi_prime_keygen (ignored) */,
NULL /* supports_digest */,
};
-27
View File
@@ -641,33 +641,6 @@ TEST_P(RSAMultiPrimeTest, TestDecrypt) {
INSTANTIATE_TEST_CASE_P(, RSAMultiPrimeTest,
testing::ValuesIn(kRSAMultiPrimeParams));
TEST(RSATest, MultiPrimeKeygen) {
bssl::UniquePtr<RSA> rsa(RSA_new());
bssl::UniquePtr<BIGNUM> e(BN_new());
ASSERT_TRUE(rsa);
ASSERT_TRUE(e);
ASSERT_TRUE(BN_set_word(e.get(), RSA_F4));
// Test key generation.
static const size_t kBits = 1024;
ASSERT_TRUE(
RSA_generate_multi_prime_key(rsa.get(), kBits, 3, e.get(), nullptr));
ASSERT_TRUE(RSA_check_key(rsa.get()));
// Test the key round-trips.
static const char kMessage[] = "Hello world.";
uint8_t encrypted[kBits / 8], decrypted[kBits / 8];
size_t encrypted_len, decrypted_len;
ASSERT_TRUE(RSA_encrypt(rsa.get(), &encrypted_len, encrypted,
sizeof(encrypted), (const uint8_t *)kMessage,
sizeof(kMessage), RSA_PKCS1_PADDING));
ASSERT_TRUE(RSA_decrypt(rsa.get(), &decrypted_len, decrypted,
sizeof(decrypted), encrypted, encrypted_len,
RSA_PKCS1_PADDING));
EXPECT_EQ(Bytes((const uint8_t *)kMessage, sizeof(kMessage)),
Bytes(decrypted, decrypted_len));
}
TEST(RSATest, BadKey) {
bssl::UniquePtr<RSA> key(RSA_new());
bssl::UniquePtr<BIGNUM> e(BN_new());
+1 -6
View File
@@ -124,12 +124,6 @@ OPENSSL_EXPORT void RSA_get0_crt_params(const RSA *rsa, const BIGNUM **out_dmp1,
OPENSSL_EXPORT int RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *e,
BN_GENCB *cb);
/* RSA_generate_multi_prime_key acts like |RSA_generate_key_ex| but can
* generate an RSA private key with more than two primes. */
OPENSSL_EXPORT int RSA_generate_multi_prime_key(RSA *rsa, int bits,
int num_primes, BIGNUM *e,
BN_GENCB *cb);
/* Encryption / Decryption */
@@ -580,6 +574,7 @@ struct rsa_meth_st {
int (*keygen)(RSA *rsa, int bits, BIGNUM *e, BN_GENCB *cb);
/* Ignored. Set this to NULL. */
int (*multi_prime_keygen)(RSA *rsa, int bits, int num_primes, BIGNUM *e,
BN_GENCB *cb);
+3 -8
View File
@@ -22,10 +22,6 @@
static const struct argument kArguments[] = {
{
"-nprimes", kOptionalArgument,
"The number of primes to generate (default: 2)",
},
{
"-bits", kOptionalArgument,
"The number of bits in the modulus (default: 2048)",
@@ -43,9 +39,8 @@ bool GenerateRSAKey(const std::vector<std::string> &args) {
return false;
}
unsigned bits, nprimes = 0;
if (!GetUnsigned(&bits, "-bits", 2048, args_map) ||
!GetUnsigned(&nprimes, "-nprimes", 2, args_map)) {
unsigned bits;
if (!GetUnsigned(&bits, "-bits", 2048, args_map)) {
PrintUsage(kArguments);
return false;
}
@@ -55,7 +50,7 @@ bool GenerateRSAKey(const std::vector<std::string> &args) {
bssl::UniquePtr<BIO> bio(BIO_new_fp(stdout, BIO_NOCLOSE));
if (!BN_set_word(e.get(), RSA_F4) ||
!RSA_generate_multi_prime_key(rsa.get(), bits, nprimes, e.get(), NULL) ||
!RSA_generate_key_ex(rsa.get(), bits, e.get(), NULL) ||
!PEM_write_bio_RSAPrivateKey(bio.get(), rsa.get(), NULL /* cipher */,
NULL /* key */, 0 /* key len */,
NULL /* password callback */,