mirror of
https://github.com/AntelopeIO/boringssl.git
synced 2026-07-21 14:43:53 +00:00
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:
committed by
Adam Langley
parent
43780cbc37
commit
4a2cc28b8c
@@ -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);
|
||||
|
||||
|
||||
|
||||
@@ -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
@@ -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 */,
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
@@ -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 */,
|
||||
|
||||
Reference in New Issue
Block a user