Convert RSA blinding to use Montgomery multiplication.
|BN_mod_mul_montgomery| has better constant-time behavior (usually) than |BN_mod_mul| and |BN_mod_sqr| and on platforms where we have assembly language optimizations (when |OPENSSL_BN_ASM_MONT| is set in crypto/bn/montgomery.c) it is faster. While doing so, reorder and rename the |BN_MONT_CTX| parameters of the blinding functions to match the order normally used in Montgomery math functions. As a bonus, remove a redundant copy of the RSA public modulus from the |BN_BLINDING| structure, which reduces memory usage. Change-Id: I70597e40246429c7964947a1dc46d0d81c7530ef Reviewed-on: https://boringssl-review.googlesource.com/7524 Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
feaa57d13d
commit
3426d10119
@ -121,17 +121,16 @@
|
||||
#define BN_BLINDING_COUNTER 32
|
||||
|
||||
struct bn_blinding_st {
|
||||
BIGNUM *A;
|
||||
BIGNUM *Ai;
|
||||
BIGNUM *A; /* The base blinding factor, Montgomery-encoded. */
|
||||
BIGNUM *Ai; /* The inverse of the blinding factor, Montgomery-encoded. */
|
||||
BIGNUM *e;
|
||||
BIGNUM *mod;
|
||||
unsigned counter;
|
||||
};
|
||||
|
||||
static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
|
||||
const BIGNUM *q, BN_CTX *ctx);
|
||||
static int bn_blinding_create_param(BN_BLINDING *b, BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont_ctx);
|
||||
static int bn_blinding_create_param(BN_BLINDING *b, const BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx);
|
||||
|
||||
BN_BLINDING *BN_BLINDING_new(const RSA *rsa, BN_CTX *ctx) {
|
||||
assert(ctx != NULL);
|
||||
@ -166,13 +165,6 @@ BN_BLINDING *BN_BLINDING_new(const RSA *rsa, BN_CTX *ctx) {
|
||||
}
|
||||
}
|
||||
|
||||
/* save a copy of mod in the BN_BLINDING structure */
|
||||
ret->mod = BN_dup(rsa->n);
|
||||
if (ret->mod == NULL) {
|
||||
goto err;
|
||||
}
|
||||
BN_set_flags(ret->mod, BN_FLG_CONSTTIME);
|
||||
|
||||
/* The blinding values need to be created before this blinding can be used. */
|
||||
ret->counter = BN_BLINDING_COUNTER - 1;
|
||||
|
||||
@ -191,23 +183,20 @@ void BN_BLINDING_free(BN_BLINDING *r) {
|
||||
BN_free(r->A);
|
||||
BN_free(r->Ai);
|
||||
BN_free(r->e);
|
||||
BN_free(r->mod);
|
||||
OPENSSL_free(r);
|
||||
}
|
||||
|
||||
static int bn_blinding_update(BN_BLINDING *b, BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont_ctx) {
|
||||
static int bn_blinding_update(BN_BLINDING *b, const BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx) {
|
||||
if (++b->counter == BN_BLINDING_COUNTER) {
|
||||
/* re-create blinding parameters */
|
||||
if (!bn_blinding_create_param(b, ctx, mont_ctx)) {
|
||||
if (!bn_blinding_create_param(b, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
b->counter = 0;
|
||||
} else {
|
||||
if (!BN_mod_mul(b->A, b->A, b->A, b->mod, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
if (!BN_mod_mul(b->Ai, b->Ai, b->Ai, b->mod, ctx)) {
|
||||
if (!BN_mod_mul_montgomery(b->A, b->A, b->A, mont, ctx) ||
|
||||
!BN_mod_mul_montgomery(b->Ai, b->Ai, b->Ai, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@ -224,32 +213,43 @@ err:
|
||||
return 0;
|
||||
}
|
||||
|
||||
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont_ctx) {
|
||||
if (!bn_blinding_update(b, ctx, mont_ctx) ||
|
||||
!BN_mod_mul(n, n, b->A, b->mod, ctx)) {
|
||||
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx) {
|
||||
/* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
|
||||
* cancels one Montgomery factor, so the resulting value of |n| is unencoded.
|
||||
*/
|
||||
if (!bn_blinding_update(b, mont, ctx) ||
|
||||
!BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_CTX *ctx) {
|
||||
return BN_mod_mul(n, n, b->Ai, b->mod, ctx);
|
||||
int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx) {
|
||||
/* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
|
||||
* cancels one Montgomery factor, so the resulting value of |n| is unencoded.
|
||||
*/
|
||||
return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx);
|
||||
}
|
||||
|
||||
static int bn_blinding_create_param(BN_BLINDING *b, BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont_ctx) {
|
||||
static int bn_blinding_create_param(BN_BLINDING *b, const BN_MONT_CTX *mont,
|
||||
BN_CTX *ctx) {
|
||||
BIGNUM mont_N_consttime;
|
||||
BN_init(&mont_N_consttime);
|
||||
BN_with_flags(&mont_N_consttime, &mont->N, BN_FLG_CONSTTIME);
|
||||
int retry_counter = 32;
|
||||
|
||||
do {
|
||||
if (!BN_rand_range(b->A, b->mod)) {
|
||||
if (!BN_rand_range(b->A, &mont->N)) {
|
||||
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int no_inverse;
|
||||
if (BN_mod_inverse_ex(b->Ai, &no_inverse, b->A, b->mod, ctx) == NULL) {
|
||||
if (BN_mod_inverse_ex(b->Ai, &no_inverse, b->A, &mont_N_consttime, ctx) ==
|
||||
NULL) {
|
||||
/* this should almost never happen for good RSA keys */
|
||||
if (no_inverse) {
|
||||
if (retry_counter-- == 0) {
|
||||
@ -266,7 +266,13 @@ static int bn_blinding_create_param(BN_BLINDING *b, BN_CTX *ctx,
|
||||
}
|
||||
} while (1);
|
||||
|
||||
if (!BN_mod_exp_mont(b->A, b->A, b->e, b->mod, ctx, mont_ctx)) {
|
||||
if (!BN_mod_exp_mont(b->A, b->A, b->e, &mont->N, ctx, mont)) {
|
||||
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!BN_to_montgomery(b->A, b->A, mont, ctx) ||
|
||||
!BN_to_montgomery(b->Ai, b->Ai, mont, ctx)) {
|
||||
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
||||
return 0;
|
||||
}
|
||||
|
@ -92,9 +92,10 @@ int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb);
|
||||
|
||||
BN_BLINDING *BN_BLINDING_new(const RSA *rsa, BN_CTX *ctx);
|
||||
void BN_BLINDING_free(BN_BLINDING *b);
|
||||
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont_ctx);
|
||||
int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_CTX *ctx);
|
||||
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BN_MONT_CTX *mont_ctx,
|
||||
BN_CTX *ctx);
|
||||
int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx,
|
||||
BN_CTX *ctx);
|
||||
|
||||
|
||||
int RSA_padding_add_PKCS1_type_1(uint8_t *to, unsigned to_len,
|
||||
|
@ -213,6 +213,7 @@ err:
|
||||
* |*index_used| and must be passed to |rsa_blinding_release| when finished. */
|
||||
static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
|
||||
BN_CTX *ctx) {
|
||||
assert(ctx != NULL);
|
||||
assert(rsa->mont_n != NULL);
|
||||
|
||||
BN_BLINDING *ret = NULL;
|
||||
@ -562,7 +563,7 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
|
||||
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
if (!BN_BLINDING_convert(f, blinding, ctx, rsa->mont_n)) {
|
||||
if (!BN_BLINDING_convert(f, blinding, rsa->mont_n, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
@ -588,7 +589,7 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
|
||||
}
|
||||
|
||||
if (blinding) {
|
||||
if (!BN_BLINDING_invert(result, blinding, ctx)) {
|
||||
if (!BN_BLINDING_invert(result, blinding, rsa->mont_n, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user