Require the public exponent to be available in RSA blinding.
Require the public exponent to be available unless
|RSA_FLAG_NO_BLINDING| is set on the key. Also, document this.
If the public exponent |e| is not available, then we could compute it
from |p|, |q|, and |d|. However, there's no reasonable situation in
which we'd have |p| or |q| but not |e|; either we have all the CRT
parameters, or we have (e, d, n), or we have only (d, n). The
calculation to compute |e| exposes the private key to risk of side
channel attacks.
Also, it was particularly wasteful to compute |e| for each
|BN_BLINDING| created, instead of just once before the first
|BN_BLINDING| was created.
|BN_BLINDING| now no longer needs to contain a duplicate copy of |e|,
so it is now more space-efficient.
Note that the condition |b->e != NULL| in |bn_blinding_update| was
always true since commit cbf56a5683
.
Change-Id: Ic2fd6980e0d359dcd53772a7c31bdd0267e316b4
Reviewed-on: https://boringssl-review.googlesource.com/7594
Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
d035730ac7
commit
86361a3910
@ -108,7 +108,6 @@
|
|||||||
|
|
||||||
#include <openssl/rsa.h>
|
#include <openssl/rsa.h>
|
||||||
|
|
||||||
#include <assert.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include <openssl/bn.h>
|
#include <openssl/bn.h>
|
||||||
@ -123,18 +122,13 @@
|
|||||||
struct bn_blinding_st {
|
struct bn_blinding_st {
|
||||||
BIGNUM *A; /* The base blinding factor, Montgomery-encoded. */
|
BIGNUM *A; /* The base blinding factor, Montgomery-encoded. */
|
||||||
BIGNUM *Ai; /* The inverse of the blinding factor, Montgomery-encoded. */
|
BIGNUM *Ai; /* The inverse of the blinding factor, Montgomery-encoded. */
|
||||||
BIGNUM *e;
|
|
||||||
unsigned counter;
|
unsigned counter;
|
||||||
};
|
};
|
||||||
|
|
||||||
static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
|
static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
|
||||||
const BIGNUM *q, BN_CTX *ctx);
|
const BN_MONT_CTX *mont, BN_CTX *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);
|
|
||||||
|
|
||||||
|
BN_BLINDING *BN_BLINDING_new(void) {
|
||||||
BN_BLINDING *ret = OPENSSL_malloc(sizeof(BN_BLINDING));
|
BN_BLINDING *ret = OPENSSL_malloc(sizeof(BN_BLINDING));
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
|
OPENSSL_PUT_ERROR(RSA, ERR_R_MALLOC_FAILURE);
|
||||||
@ -152,19 +146,6 @@ BN_BLINDING *BN_BLINDING_new(const RSA *rsa, BN_CTX *ctx) {
|
|||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rsa->e != NULL) {
|
|
||||||
ret->e = BN_dup(rsa->e);
|
|
||||||
if (ret->e == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
ret->e = rsa_get_public_exp(rsa->d, rsa->p, rsa->q, ctx);
|
|
||||||
if (ret->e == NULL) {
|
|
||||||
OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* The blinding values need to be created before this blinding can be used. */
|
/* The blinding values need to be created before this blinding can be used. */
|
||||||
ret->counter = BN_BLINDING_COUNTER - 1;
|
ret->counter = BN_BLINDING_COUNTER - 1;
|
||||||
|
|
||||||
@ -182,15 +163,14 @@ void BN_BLINDING_free(BN_BLINDING *r) {
|
|||||||
|
|
||||||
BN_free(r->A);
|
BN_free(r->A);
|
||||||
BN_free(r->Ai);
|
BN_free(r->Ai);
|
||||||
BN_free(r->e);
|
|
||||||
OPENSSL_free(r);
|
OPENSSL_free(r);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bn_blinding_update(BN_BLINDING *b, const BN_MONT_CTX *mont,
|
static int bn_blinding_update(BN_BLINDING *b, const BIGNUM *e,
|
||||||
BN_CTX *ctx) {
|
const BN_MONT_CTX *mont, BN_CTX *ctx) {
|
||||||
if (++b->counter == BN_BLINDING_COUNTER) {
|
if (++b->counter == BN_BLINDING_COUNTER) {
|
||||||
/* re-create blinding parameters */
|
/* re-create blinding parameters */
|
||||||
if (!bn_blinding_create_param(b, mont, ctx)) {
|
if (!bn_blinding_create_param(b, e, mont, ctx)) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
b->counter = 0;
|
b->counter = 0;
|
||||||
@ -213,12 +193,12 @@ err:
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BN_MONT_CTX *mont,
|
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
|
||||||
BN_CTX *ctx) {
|
const BN_MONT_CTX *mont, BN_CTX *ctx) {
|
||||||
/* |n| is not Montgomery-encoded and |b->A| is. |BN_mod_mul_montgomery|
|
/* |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.
|
* cancels one Montgomery factor, so the resulting value of |n| is unencoded.
|
||||||
*/
|
*/
|
||||||
if (!bn_blinding_update(b, mont, ctx) ||
|
if (!bn_blinding_update(b, e, mont, ctx) ||
|
||||||
!BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) {
|
!BN_mod_mul_montgomery(n, n, b->A, mont, ctx)) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -234,8 +214,8 @@ int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont,
|
|||||||
return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx);
|
return BN_mod_mul_montgomery(n, n, b->Ai, mont, ctx);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int bn_blinding_create_param(BN_BLINDING *b, const BN_MONT_CTX *mont,
|
static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
|
||||||
BN_CTX *ctx) {
|
const BN_MONT_CTX *mont, BN_CTX *ctx) {
|
||||||
BIGNUM mont_N_consttime;
|
BIGNUM mont_N_consttime;
|
||||||
BN_init(&mont_N_consttime);
|
BN_init(&mont_N_consttime);
|
||||||
BN_with_flags(&mont_N_consttime, &mont->N, BN_FLG_CONSTTIME);
|
BN_with_flags(&mont_N_consttime, &mont->N, BN_FLG_CONSTTIME);
|
||||||
@ -273,7 +253,7 @@ static int bn_blinding_create_param(BN_BLINDING *b, const BN_MONT_CTX *mont,
|
|||||||
}
|
}
|
||||||
} while (1);
|
} while (1);
|
||||||
|
|
||||||
if (!BN_mod_exp_mont(b->A, b->A, b->e, &mont->N, ctx, mont)) {
|
if (!BN_mod_exp_mont(b->A, b->A, e, &mont->N, ctx, mont)) {
|
||||||
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@ -285,36 +265,3 @@ static int bn_blinding_create_param(BN_BLINDING *b, const BN_MONT_CTX *mont,
|
|||||||
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static BIGNUM *rsa_get_public_exp(const BIGNUM *d, const BIGNUM *p,
|
|
||||||
const BIGNUM *q, BN_CTX *ctx) {
|
|
||||||
BIGNUM *ret = NULL, *r0, *r1, *r2;
|
|
||||||
|
|
||||||
if (d == NULL || p == NULL || q == NULL) {
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
|
|
||||||
BN_CTX_start(ctx);
|
|
||||||
r0 = BN_CTX_get(ctx);
|
|
||||||
r1 = BN_CTX_get(ctx);
|
|
||||||
r2 = BN_CTX_get(ctx);
|
|
||||||
if (r2 == NULL) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!BN_sub(r1, p, BN_value_one())) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (!BN_sub(r2, q, BN_value_one())) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
if (!BN_mul(r0, r1, r2, ctx)) {
|
|
||||||
goto err;
|
|
||||||
}
|
|
||||||
|
|
||||||
ret = BN_mod_inverse(NULL, d, r0, ctx);
|
|
||||||
|
|
||||||
err:
|
|
||||||
BN_CTX_end(ctx);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
@ -87,10 +87,10 @@ int rsa_default_keygen(RSA *rsa, int bits, BIGNUM *e_value, BN_GENCB *cb);
|
|||||||
#define RSA_PKCS1_PADDING_SIZE 11
|
#define RSA_PKCS1_PADDING_SIZE 11
|
||||||
|
|
||||||
|
|
||||||
BN_BLINDING *BN_BLINDING_new(const RSA *rsa, BN_CTX *ctx);
|
BN_BLINDING *BN_BLINDING_new(void);
|
||||||
void BN_BLINDING_free(BN_BLINDING *b);
|
void BN_BLINDING_free(BN_BLINDING *b);
|
||||||
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BN_MONT_CTX *mont_ctx,
|
int BN_BLINDING_convert(BIGNUM *n, BN_BLINDING *b, const BIGNUM *e,
|
||||||
BN_CTX *ctx);
|
const BN_MONT_CTX *mont_ctx, BN_CTX *ctx);
|
||||||
int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx,
|
int BN_BLINDING_invert(BIGNUM *n, const BN_BLINDING *b, BN_MONT_CTX *mont_ctx,
|
||||||
BN_CTX *ctx);
|
BN_CTX *ctx);
|
||||||
|
|
||||||
|
@ -244,7 +244,7 @@ static BN_BLINDING *rsa_blinding_get(RSA *rsa, unsigned *index_used,
|
|||||||
* the arrays by one and use the newly created element. */
|
* the arrays by one and use the newly created element. */
|
||||||
|
|
||||||
CRYPTO_MUTEX_unlock(&rsa->lock);
|
CRYPTO_MUTEX_unlock(&rsa->lock);
|
||||||
ret = BN_BLINDING_new(rsa, ctx);
|
ret = BN_BLINDING_new();
|
||||||
if (ret == NULL) {
|
if (ret == NULL) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
@ -557,6 +557,13 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
|
if (!(rsa->flags & RSA_FLAG_NO_BLINDING)) {
|
||||||
|
/* Keys without public exponents must have blinding explicitly disabled to
|
||||||
|
* be used. */
|
||||||
|
if (rsa->e == NULL) {
|
||||||
|
OPENSSL_PUT_ERROR(RSA, RSA_R_NO_PUBLIC_EXPONENT);
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
|
if (!BN_MONT_CTX_set_locked(&rsa->mont_n, &rsa->lock, rsa->n, ctx)) {
|
||||||
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
||||||
goto err;
|
goto err;
|
||||||
@ -567,7 +574,7 @@ int rsa_default_private_transform(RSA *rsa, uint8_t *out, const uint8_t *in,
|
|||||||
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (!BN_BLINDING_convert(f, blinding, rsa->mont_n, ctx)) {
|
if (!BN_BLINDING_convert(f, blinding, rsa->e, rsa->mont_n, ctx)) {
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -416,7 +416,11 @@ OPENSSL_EXPORT void *RSA_get_ex_data(const RSA *r, int idx);
|
|||||||
/* Deprecated and ignored. */
|
/* Deprecated and ignored. */
|
||||||
#define RSA_FLAG_CACHE_PRIVATE 4
|
#define RSA_FLAG_CACHE_PRIVATE 4
|
||||||
|
|
||||||
/* RSA_FLAG_NO_BLINDING disables blinding of private operations. */
|
/* RSA_FLAG_NO_BLINDING disables blinding of private operations, which is a
|
||||||
|
* dangerous thing to do. It is deprecated and may be ignored in the future.
|
||||||
|
*
|
||||||
|
* This flag must be used if a key without the public exponent |e| is used for
|
||||||
|
* private key operations; avoid using such keys whenever possible. */
|
||||||
#define RSA_FLAG_NO_BLINDING 8
|
#define RSA_FLAG_NO_BLINDING 8
|
||||||
|
|
||||||
/* RSA_FLAG_EXT_PKEY is deprecated and ignored. */
|
/* RSA_FLAG_EXT_PKEY is deprecated and ignored. */
|
||||||
|
Loading…
Reference in New Issue
Block a user