Add BN_rand_range_ex and use internally.

There are many cases where we need |BN_rand_range| but with a minimum
value other than 0. |BN_rand_range_ex| provides that.

Change-Id: I564326c9206bf4e20a37414bdbce16a951c148ce
Reviewed-on: https://boringssl-review.googlesource.com/8921
Reviewed-by: David Benjamin <davidben@google.com>
Commit-Queue: David Benjamin <davidben@google.com>
CQ-Verified: CQ bot account: commit-bot@chromium.org <commit-bot@chromium.org>
This commit is contained in:
Brian Smith 2016-07-25 10:36:58 -10:00 committed by CQ bot account: commit-bot@chromium.org
parent 4792110b2b
commit 4edca0b308
9 changed files with 67 additions and 52 deletions

View File

@ -185,6 +185,17 @@ int BN_abs_is_word(const BIGNUM *bn, BN_ULONG w) {
}
}
int BN_cmp_word(const BIGNUM *a, BN_ULONG b) {
BIGNUM b_bn;
BN_init(&b_bn);
b_bn.d = &b;
b_bn.top = b > 0;
b_bn.dmax = 1;
b_bn.flags = BN_FLG_STATIC_DATA;
return BN_cmp(a, &b_bn);
}
int BN_is_zero(const BIGNUM *bn) {
return bn->top == 0;
}

View File

@ -181,16 +181,17 @@ int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom) {
return BN_rand(rnd, bits, top, bottom);
}
int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive,
const BIGNUM *max_exclusive) {
unsigned n;
unsigned count = 100;
if (range->neg || BN_is_zero(range)) {
if (BN_cmp_word(max_exclusive, min_inclusive) <= 0) {
OPENSSL_PUT_ERROR(BN, BN_R_INVALID_RANGE);
return 0;
}
n = BN_num_bits(range); /* n > 0 */
n = BN_num_bits(max_exclusive); /* n > 0 */
/* BN_is_bit_set(range, n - 1) always holds */
if (n == 1) {
@ -204,7 +205,8 @@ int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
return 0;
}
if (!BN_is_bit_set(range, n - 2) && !BN_is_bit_set(range, n - 3)) {
if (!BN_is_bit_set(max_exclusive, n - 2) &&
!BN_is_bit_set(max_exclusive, n - 3)) {
/* range = 100..._2, so 3*range (= 11..._2) is exactly one bit longer
* than range. This is a common scenario when generating a random value
* modulo an RSA public modulus, e.g. for RSA base blinding. */
@ -216,12 +218,12 @@ int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
/* If r < 3*range, use r := r MOD range (which is either r, r - range, or
* r - 2*range). Otherwise, iterate again. Since 3*range = 11..._2, each
* iteration succeeds with probability >= .75. */
if (BN_cmp(r, range) >= 0) {
if (!BN_sub(r, r, range)) {
if (BN_cmp(r, max_exclusive) >= 0) {
if (!BN_sub(r, r, max_exclusive)) {
return 0;
}
if (BN_cmp(r, range) >= 0) {
if (!BN_sub(r, r, range)) {
if (BN_cmp(r, max_exclusive) >= 0) {
if (!BN_sub(r, r, max_exclusive)) {
return 0;
}
}
@ -232,11 +234,16 @@ int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
return 0;
}
}
} while (BN_cmp(r, range) >= 0);
} while (BN_cmp_word(r, min_inclusive) < 0 ||
BN_cmp(r, max_exclusive) >= 0);
return 1;
}
int BN_rand_range(BIGNUM *r, const BIGNUM *range) {
return BN_rand_range_ex(r, 0, range);
}
int BN_pseudo_rand_range(BIGNUM *r, const BIGNUM *range) {
return BN_rand_range(r, range);
}

View File

@ -275,11 +275,9 @@ int DH_generate_key(DH *dh) {
if (generate_new_key) {
if (dh->q) {
do {
if (!BN_rand_range(priv_key, dh->q)) {
if (!BN_rand_range_ex(priv_key, 2, dh->q)) {
goto err;
}
} while (BN_is_zero(priv_key) || BN_is_one(priv_key));
} else {
/* secret exponent length */
DH_check_standard_parameters(dh);

View File

@ -425,11 +425,9 @@ int DSA_generate_key(DSA *dsa) {
}
}
do {
if (!BN_rand_range(priv_key, dsa->q)) {
if (!BN_rand_range_ex(priv_key, 1, dsa->q)) {
goto err;
}
} while (BN_is_zero(priv_key));
pub_key = dsa->pub_key;
if (pub_key == NULL) {
@ -818,11 +816,9 @@ int DSA_sign_setup(const DSA *dsa, BN_CTX *ctx_in, BIGNUM **out_kinv,
}
/* Get random k */
do {
if (!BN_rand_range(&k, dsa->q)) {
if (!BN_rand_range_ex(&k, 1, dsa->q)) {
goto err;
}
} while (BN_is_zero(&k));
BN_set_flags(&k, BN_FLG_CONSTTIME);

View File

@ -425,11 +425,9 @@ int EC_KEY_generate_key(EC_KEY *eckey) {
}
const BIGNUM *order = EC_GROUP_get0_order(eckey->group);
do {
if (!BN_rand_range(priv_key, order)) {
if (!BN_rand_range_ex(priv_key, 1, order)) {
goto err;
}
} while (BN_is_zero(priv_key));
if (eckey->pub_key == NULL) {
pub_key = EC_POINT_new(eckey->group);

View File

@ -263,20 +263,18 @@ static int ecdsa_sign_setup(EC_KEY *eckey, BN_CTX *ctx_in, BIGNUM **kinvp,
/* If possible, we'll include the private key and message digest in the k
* generation. The |digest| argument is only empty if |ECDSA_sign_setup| is
* being used. */
do {
int ok;
if (digest_len > 0) {
ok = BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey),
digest, digest_len, ctx);
} else {
ok = BN_rand_range(k, order);
}
if (!ok) {
do {
if (!BN_generate_dsa_nonce(k, order, EC_KEY_get0_private_key(eckey),
digest, digest_len, ctx)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
} while (BN_is_zero(k));
} else if (!BN_rand_range_ex(k, 1, order)) {
OPENSSL_PUT_ERROR(ECDSA, ECDSA_R_RANDOM_NUMBER_GENERATION_FAILED);
goto err;
}
/* We do not want timing information to leak the length of k,
* so we compute G*k using an equivalent scalar of fixed

View File

@ -222,7 +222,7 @@ static int bn_blinding_create_param(BN_BLINDING *b, const BIGNUM *e,
int retry_counter = 32;
do {
if (!BN_rand_range(b->A, &mont->N)) {
if (!BN_rand_range_ex(b->A, 1, &mont->N)) {
OPENSSL_PUT_ERROR(RSA, ERR_R_INTERNAL_ERROR);
return 0;
}

View File

@ -436,6 +436,10 @@ OPENSSL_EXPORT int BN_sqrt(BIGNUM *out_sqrt, const BIGNUM *in, BN_CTX *ctx);
* less than, equal to or greater than |b|, respectively. */
OPENSSL_EXPORT int BN_cmp(const BIGNUM *a, const BIGNUM *b);
/* BN_cmp_word is like |BN_cmp| except it takes its second argument as a
* |BN_ULONG| instead of a |BIGNUM|. */
int BN_cmp_word(const BIGNUM *a, BN_ULONG b);
/* BN_ucmp returns a value less than, equal to or greater than zero if the
* absolute value of |a| is less than, equal to or greater than the absolute
* value of |b|, respectively. */
@ -587,10 +591,16 @@ OPENSSL_EXPORT int BN_rand(BIGNUM *rnd, int bits, int top, int bottom);
/* BN_pseudo_rand is an alias for |BN_rand|. */
OPENSSL_EXPORT int BN_pseudo_rand(BIGNUM *rnd, int bits, int top, int bottom);
/* BN_rand_range sets |rnd| to a random value [0..range). It returns one on
* success and zero otherwise. */
/* BN_rand_range is equivalent to |BN_rand_range_ex| with |min_inclusive| set
* to zero and |max_exclusive| set to |range|. */
OPENSSL_EXPORT int BN_rand_range(BIGNUM *rnd, const BIGNUM *range);
/* BN_rand_range_ex sets |rnd| to a random value in
* [min_inclusive..max_exclusive). It returns one on success and zero
* otherwise. */
OPENSSL_EXPORT int BN_rand_range_ex(BIGNUM *r, BN_ULONG min_inclusive,
const BIGNUM *max_exclusive);
/* BN_pseudo_rand_range is an alias for BN_rand_range. */
OPENSSL_EXPORT int BN_pseudo_rand_range(BIGNUM *rnd, const BIGNUM *range);

View File

@ -59,12 +59,9 @@ static int ssl_ec_point_offer(SSL_ECDH_CTX *ctx, CBB *out) {
}
/* Generate a private key. */
const BIGNUM *order = EC_GROUP_get0_order(group);
do {
if (!BN_rand_range(private_key, order)) {
if (!BN_rand_range_ex(private_key, 1, EC_GROUP_get0_order(group))) {
goto err;
}
} while (BN_is_zero(private_key));
/* Compute the corresponding public key and serialize it. */
public_key = EC_POINT_new(group);