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:
parent
4792110b2b
commit
4edca0b308
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user