summaryrefslogtreecommitdiffstats
path: root/src/crypto/rsa/rsa_impl.c
diff options
context:
space:
mode:
authorKenny Root <kroot@google.com>2015-09-25 02:36:32 +0000
committerAndroid Git Automerger <android-git-automerger@android.com>2015-09-25 02:36:32 +0000
commitd947d006e7a7ebcfdfe642e686250caf2028c2c1 (patch)
treedd743d9d64af3145fe96b8d5fc2f3427544794bd /src/crypto/rsa/rsa_impl.c
parent00bc53f6f4436972b7a8dcf2c1e5fd0ad7515872 (diff)
parentb8494591d1b1a143f3b192d845c238bbf3bc629d (diff)
downloadexternal_boringssl-d947d006e7a7ebcfdfe642e686250caf2028c2c1.zip
external_boringssl-d947d006e7a7ebcfdfe642e686250caf2028c2c1.tar.gz
external_boringssl-d947d006e7a7ebcfdfe642e686250caf2028c2c1.tar.bz2
am b8494591: Revert "Revert "external/boringssl: sync with upstream.""
* commit 'b8494591d1b1a143f3b192d845c238bbf3bc629d': Revert "Revert "external/boringssl: sync with upstream.""
Diffstat (limited to 'src/crypto/rsa/rsa_impl.c')
-rw-r--r--src/crypto/rsa/rsa_impl.c311
1 files changed, 255 insertions, 56 deletions
diff --git a/src/crypto/rsa/rsa_impl.c b/src/crypto/rsa/rsa_impl.c
index e14f0f5..eb4a36f 100644
--- a/src/crypto/rsa/rsa_impl.c
+++ b/src/crypto/rsa/rsa_impl.c
@@ -78,6 +78,15 @@ static int finish(RSA *rsa) {
BN_MONT_CTX_free(rsa->_method_mod_p);
BN_MONT_CTX_free(rsa->_method_mod_q);
+ if (rsa->additional_primes != NULL) {
+ size_t i;
+ for (i = 0; i < sk_RSA_additional_prime_num(rsa->additional_primes); i++) {
+ RSA_additional_prime *ap =
+ sk_RSA_additional_prime_value(rsa->additional_primes, i);
+ BN_MONT_CTX_free(ap->method_mod);
+ }
+ }
+
return 1;
}
@@ -94,24 +103,24 @@ static int encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
int i, ret = 0;
if (rsa_size > OPENSSL_RSA_MAX_MODULUS_BITS) {
- OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_MODULUS_TOO_LARGE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
return 0;
}
if (max_out < rsa_size) {
- OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
- OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_BAD_E_VALUE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
return 0;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
- OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_BAD_E_VALUE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
return 0;
}
@@ -125,7 +134,7 @@ static int encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
result = BN_CTX_get(ctx);
buf = OPENSSL_malloc(rsa_size);
if (!f || !result || !buf) {
- OPENSSL_PUT_ERROR(RSA, encrypt, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -142,7 +151,7 @@ static int encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
i = RSA_padding_add_none(buf, rsa_size, in, in_len);
break;
default:
- OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_UNKNOWN_PADDING_TYPE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
@@ -156,7 +165,7 @@ static int encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
if (BN_ucmp(f, rsa->n) >= 0) {
/* usually the padding functions would catch this */
- OPENSSL_PUT_ERROR(RSA, encrypt, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
@@ -175,7 +184,7 @@ static int encrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
/* put in leading 0 bytes if the number is less than the length of the
* modulus */
if (!BN_bn2bin_padded(out, rsa_size, result)) {
- OPENSSL_PUT_ERROR(RSA, encrypt, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -309,13 +318,13 @@ static int sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
int i, ret = 0;
if (max_out < rsa_size) {
- OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
buf = OPENSSL_malloc(rsa_size);
if (buf == NULL) {
- OPENSSL_PUT_ERROR(RSA, sign_raw, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -327,7 +336,7 @@ static int sign_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
i = RSA_padding_add_none(buf, rsa_size, in, in_len);
break;
default:
- OPENSSL_PUT_ERROR(RSA, sign_raw, RSA_R_UNKNOWN_PADDING_TYPE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
@@ -359,18 +368,23 @@ static int decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
int ret = 0;
if (max_out < rsa_size) {
- OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
- buf = OPENSSL_malloc(rsa_size);
- if (buf == NULL) {
- OPENSSL_PUT_ERROR(RSA, decrypt, ERR_R_MALLOC_FAILURE);
- goto err;
+ if (padding == RSA_NO_PADDING) {
+ buf = out;
+ } else {
+ /* Allocate a temporary buffer to hold the padded plaintext. */
+ buf = OPENSSL_malloc(rsa_size);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
}
if (in_len != rsa_size) {
- OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
goto err;
}
@@ -388,22 +402,22 @@ static int decrypt(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
NULL, 0, NULL, NULL);
break;
case RSA_NO_PADDING:
- r = RSA_padding_check_none(out, rsa_size, buf, rsa_size);
+ r = rsa_size;
break;
default:
- OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_UNKNOWN_PADDING_TYPE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (r < 0) {
- OPENSSL_PUT_ERROR(RSA, decrypt, RSA_R_PADDING_CHECK_FAILED);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
} else {
*out_len = r;
ret = 1;
}
err:
- if (buf != NULL) {
+ if (padding != RSA_NO_PADDING && buf != NULL) {
OPENSSL_cleanse(buf, rsa_size);
OPENSSL_free(buf);
}
@@ -421,24 +435,24 @@ static int verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
BN_CTX *ctx = NULL;
if (BN_num_bits(rsa->n) > OPENSSL_RSA_MAX_MODULUS_BITS) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_MODULUS_TOO_LARGE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_MODULUS_TOO_LARGE);
return 0;
}
if (BN_ucmp(rsa->n, rsa->e) <= 0) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_BAD_E_VALUE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
return 0;
}
if (max_out < rsa_size) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_OUTPUT_BUFFER_TOO_SMALL);
return 0;
}
/* for large moduli, enforce exponent limit */
if (BN_num_bits(rsa->n) > OPENSSL_RSA_SMALL_MODULUS_BITS &&
BN_num_bits(rsa->e) > OPENSSL_RSA_MAX_PUBEXP_BITS) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_BAD_E_VALUE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_BAD_E_VALUE);
return 0;
}
@@ -450,14 +464,23 @@ static int verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
BN_CTX_start(ctx);
f = BN_CTX_get(ctx);
result = BN_CTX_get(ctx);
- buf = OPENSSL_malloc(rsa_size);
- if (!f || !result || !buf) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, ERR_R_MALLOC_FAILURE);
+ if (padding == RSA_NO_PADDING) {
+ buf = out;
+ } else {
+ /* Allocate a temporary buffer to hold the padded plaintext. */
+ buf = OPENSSL_malloc(rsa_size);
+ if (buf == NULL) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
+ goto err;
+ }
+ }
+ if (!f || !result) {
+ OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
if (in_len != rsa_size) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_LEN_NOT_EQUAL_TO_MOD_LEN);
goto err;
}
@@ -466,7 +489,7 @@ static int verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
}
if (BN_ucmp(f, rsa->n) >= 0) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
@@ -483,7 +506,7 @@ static int verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
}
if (!BN_bn2bin_padded(buf, rsa_size, result)) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -492,15 +515,15 @@ static int verify_raw(RSA *rsa, size_t *out_len, uint8_t *out, size_t max_out,
r = RSA_padding_check_PKCS1_type_1(out, rsa_size, buf, rsa_size);
break;
case RSA_NO_PADDING:
- r = RSA_padding_check_none(out, rsa_size, buf, rsa_size);
+ r = rsa_size;
break;
default:
- OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_UNKNOWN_PADDING_TYPE);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_UNKNOWN_PADDING_TYPE);
goto err;
}
if (r < 0) {
- OPENSSL_PUT_ERROR(RSA, verify_raw, RSA_R_PADDING_CHECK_FAILED);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_PADDING_CHECK_FAILED);
} else {
*out_len = r;
ret = 1;
@@ -511,7 +534,7 @@ err:
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
- if (buf != NULL) {
+ if (padding != RSA_NO_PADDING && buf != NULL) {
OPENSSL_cleanse(buf, rsa_size);
OPENSSL_free(buf);
}
@@ -535,7 +558,7 @@ static int private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
result = BN_CTX_get(ctx);
if (f == NULL || result == NULL) {
- OPENSSL_PUT_ERROR(RSA, private_transform, ERR_R_MALLOC_FAILURE);
+ OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
goto err;
}
@@ -545,14 +568,14 @@ static int private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
if (BN_ucmp(f, rsa->n) >= 0) {
/* Usually the padding functions would catch this. */
- OPENSSL_PUT_ERROR(RSA, private_transform, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_DATA_TOO_LARGE_FOR_MODULUS);
goto err;
}
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
blinding = rsa_blinding_get(rsa, &blinding_index, ctx);
if (blinding == NULL) {
- OPENSSL_PUT_ERROR(RSA, private_transform, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
if (!BN_BLINDING_convert_ex(f, NULL, blinding, ctx)) {
@@ -593,7 +616,7 @@ static int private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
}
if (!BN_bn2bin_padded(out, len, result)) {
- OPENSSL_PUT_ERROR(RSA, private_transform, ERR_R_INTERNAL_ERROR);
+ OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
goto err;
}
@@ -616,6 +639,11 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
BIGNUM local_dmp1, local_dmq1, local_c, local_r1;
BIGNUM *dmp1, *dmq1, *c, *pr1;
int ret = 0;
+ size_t i, num_additional_primes = 0;
+
+ if (rsa->additional_primes != NULL) {
+ num_additional_primes = sk_RSA_additional_prime_num(rsa->additional_primes);
+ }
BN_CTX_start(ctx);
r1 = BN_CTX_get(ctx);
@@ -724,6 +752,42 @@ static int mod_exp(BIGNUM *r0, const BIGNUM *I, RSA *rsa, BN_CTX *ctx) {
goto err;
}
+ for (i = 0; i < num_additional_primes; i++) {
+ /* multi-prime RSA. */
+ BIGNUM local_exp, local_prime;
+ BIGNUM *exp = &local_exp, *prime = &local_prime;
+ RSA_additional_prime *ap =
+ sk_RSA_additional_prime_value(rsa->additional_primes, i);
+
+ BN_with_flags(exp, ap->exp, BN_FLG_CONSTTIME);
+ BN_with_flags(prime, ap->prime, BN_FLG_CONSTTIME);
+
+ /* c will already point to a BIGNUM with the correct flags. */
+ if (!BN_mod(r1, c, prime, ctx)) {
+ goto err;
+ }
+
+ if ((rsa->flags & RSA_FLAG_CACHE_PRIVATE) &&
+ !BN_MONT_CTX_set_locked(&ap->method_mod, &rsa->lock, prime, ctx)) {
+ goto err;
+ }
+
+ if (!rsa->meth->bn_mod_exp(m1, r1, exp, prime, ctx, ap->method_mod)) {
+ goto err;
+ }
+
+ BN_set_flags(m1, BN_FLG_CONSTTIME);
+
+ if (!BN_sub(m1, m1, r0) ||
+ !BN_mul(m1, m1, ap->coeff, ctx) ||
+ !BN_mod(m1, m1, prime, ctx) ||
+ (BN_is_negative(m1) && !BN_add(m1, m1, prime)) ||
+ !BN_mul(m1, m1, ap->r, ctx) ||
+ !BN_add(r0, r0, m1)) {
+ goto err;
+ }
+ }
+
if (rsa->e && rsa->n) {
if (!rsa->meth->bn_mod_exp(vrfy, r0, rsa->e, rsa->n, ctx,
rsa->_method_mod_n)) {
@@ -766,12 +830,20 @@ err:
return ret;
}
-static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
+static int keygen_multiprime(RSA *rsa, int bits, int num_primes,
+ BIGNUM *e_value, BN_GENCB *cb) {
BIGNUM *r0 = NULL, *r1 = NULL, *r2 = NULL, *r3 = NULL, *tmp;
BIGNUM local_r0, local_d, local_p;
BIGNUM *pr0, *d, *p;
- int bitsp, bitsq, ok = -1, n = 0;
+ int prime_bits, ok = -1, n = 0, i, j;
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) {
@@ -782,12 +854,36 @@ static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
r1 = BN_CTX_get(ctx);
r2 = BN_CTX_get(ctx);
r3 = BN_CTX_get(ctx);
- if (r3 == NULL) {
+ if (r0 == NULL || r1 == NULL || r2 == NULL || r3 == NULL) {
goto err;
}
- bitsp = (bits + 1) / 2;
- bitsq = bits - bitsp;
+ 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;
+ }
+ 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 (!rsa->n && ((rsa->n = BN_new()) == NULL)) {
@@ -815,11 +911,14 @@ static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
goto err;
}
- BN_copy(rsa->e, e_value);
+ if (!BN_copy(rsa->e, e_value)) {
+ goto err;
+ }
/* generate p and q */
+ prime_bits = (bits + (num_primes - 1)) / num_primes;
for (;;) {
- if (!BN_generate_prime_ex(rsa->p, bitsp, 0, NULL, NULL, cb) ||
+ if (!BN_generate_prime_ex(rsa->p, prime_bits, 0, NULL, NULL, cb) ||
!BN_sub(r2, rsa->p, BN_value_one()) ||
!BN_gcd(r1, r2, rsa->e, ctx)) {
goto err;
@@ -834,19 +933,20 @@ static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
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, bitsq, 0, NULL, NULL, cb)) {
+ if (!BN_generate_prime_ex(rsa->q, prime_bits, 0, NULL, NULL, cb)) {
goto err;
}
} while ((BN_cmp(rsa->p, rsa->q) == 0) && (++degenerate < 3));
if (degenerate == 3) {
ok = 0; /* we set our own err */
- OPENSSL_PUT_ERROR(RSA, keygen, RSA_R_KEY_SIZE_TOO_SMALL);
+ OPENSSL_PUT_ERROR(RSA, RSA_R_KEY_SIZE_TOO_SMALL);
goto err;
}
if (!BN_sub(r2, rsa->q, BN_value_one()) ||
@@ -860,20 +960,91 @@ static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
goto err;
}
}
- if (!BN_GENCB_call(cb, 3, 1)) {
+
+ if (!BN_GENCB_call(cb, 3, 1) ||
+ !BN_mul(rsa->n, rsa->p, rsa->q, ctx)) {
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) == 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;
rsa->q = tmp;
}
- /* calculate n */
- if (!BN_mul(rsa->n, rsa->p, rsa->q, ctx)) {
- goto err;
- }
-
/* calculate d */
if (!BN_sub(r1, rsa->p, BN_value_one())) {
goto err; /* p-1 */
@@ -884,6 +1055,14 @@ static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
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;
+ }
+ }
pr0 = &local_r0;
BN_with_flags(pr0, r0, BN_FLG_CONSTTIME);
if (!BN_mod_inverse(rsa->d, rsa->e, pr0, ctx)) {
@@ -912,21 +1091,38 @@ static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
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_mod_inverse(ap->coeff, ap->r, ap->prime, ctx)) {
+ goto err;
+ }
+ }
+
ok = 1;
+ rsa->additional_primes = additional_primes;
+ additional_primes = NULL;
err:
if (ok == -1) {
- OPENSSL_PUT_ERROR(RSA, keygen, ERR_LIB_BN);
+ OPENSSL_PUT_ERROR(RSA, ERR_LIB_BN);
ok = 0;
}
if (ctx != NULL) {
BN_CTX_end(ctx);
BN_CTX_free(ctx);
}
-
+ sk_RSA_additional_prime_pop_free(additional_primes,
+ RSA_additional_prime_free);
return ok;
}
+static int keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb) {
+ return keygen_multiprime(rsa, bits, 2 /* num primes */, e_value, cb);
+}
+
const struct rsa_meth_st RSA_default_method = {
{
0 /* references */,
@@ -955,4 +1151,7 @@ const struct rsa_meth_st RSA_default_method = {
RSA_FLAG_CACHE_PUBLIC | RSA_FLAG_CACHE_PRIVATE,
keygen,
+ keygen_multiprime,
+
+ NULL /* supports_digest */,
};