Deprecate |BN_mod_exp_mont_word| and simplify its implementation.
|BN_mod_exp_mont_word| is only useful when the base is a single word in length and timing side channel protection of the exponent is not needed. That's never the case in real life. Keep the function in the API, but removes its single-word-base optimized implementation with a call to |BN_mod_exp_mont|. Change-Id: Ic25f6d4f187210b681c6ee6b87038b64a5744958 Reviewed-on: https://boringssl-review.googlesource.com/7731 Reviewed-by: David Benjamin <davidben@google.com>
This commit is contained in:
parent
376a0fed24
commit
e31d103a0a
@ -606,11 +606,6 @@ int BN_mod_exp(BIGNUM *r, const BIGNUM *a, const BIGNUM *p, const BIGNUM *m,
|
||||
* has been integrated into OpenSSL.) */
|
||||
|
||||
if (BN_is_odd(m)) {
|
||||
if (a->top == 1 && !a->neg && BN_get_flags(p, BN_FLG_CONSTTIME) == 0) {
|
||||
BN_ULONG A = a->d[0];
|
||||
return BN_mod_exp_mont_word(r, A, p, m, ctx, NULL);
|
||||
}
|
||||
|
||||
return BN_mod_exp_mont(r, a, p, m, ctx, NULL);
|
||||
}
|
||||
|
||||
@ -1234,151 +1229,21 @@ err:
|
||||
int BN_mod_exp_mont_word(BIGNUM *rr, BN_ULONG a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont) {
|
||||
BN_MONT_CTX *new_mont = NULL;
|
||||
int b, bits, ret = 0;
|
||||
int r_is_one;
|
||||
BN_ULONG w, next_w;
|
||||
BIGNUM *d, *r, *t;
|
||||
BIGNUM *swap_tmp;
|
||||
#define BN_MOD_MUL_WORD(r, w, m) \
|
||||
(BN_mul_word(r, (w)) && \
|
||||
(/* BN_ucmp(r, (m)) < 0 ? 1 :*/ \
|
||||
(BN_mod(t, r, m, ctx) && (swap_tmp = r, r = t, t = swap_tmp, 1))))
|
||||
/* BN_MOD_MUL_WORD is only used with 'w' large, so the BN_ucmp test is
|
||||
* probably more overhead than always using BN_mod (which uses BN_copy if a
|
||||
* similar test returns true). We can use BN_mod and do not need BN_nnmod
|
||||
* because our accumulator is never negative (the result of BN_mod does not
|
||||
* depend on the sign of the modulus). */
|
||||
#define BN_TO_MONTGOMERY_WORD(r, w, mont) \
|
||||
(BN_set_word(r, (w)) && BN_to_montgomery(r, r, (mont), ctx))
|
||||
BIGNUM a_bignum;
|
||||
BN_init(&a_bignum);
|
||||
|
||||
if (BN_get_flags(p, BN_FLG_CONSTTIME) != 0) {
|
||||
/* BN_FLG_CONSTTIME only supported by BN_mod_exp_mont() */
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_SHOULD_NOT_HAVE_BEEN_CALLED);
|
||||
return 0;
|
||||
}
|
||||
int ret = 0;
|
||||
|
||||
if (!BN_is_odd(m)) {
|
||||
OPENSSL_PUT_ERROR(BN, BN_R_CALLED_WITH_EVEN_MODULUS);
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (m->top == 1) {
|
||||
a %= m->d[0]; /* make sure that 'a' is reduced */
|
||||
}
|
||||
|
||||
bits = BN_num_bits(p);
|
||||
if (bits == 0) {
|
||||
/* x**0 mod 1 is still zero. */
|
||||
if (BN_is_one(m)) {
|
||||
BN_zero(rr);
|
||||
return 1;
|
||||
}
|
||||
return BN_one(rr);
|
||||
}
|
||||
if (a == 0) {
|
||||
BN_zero(rr);
|
||||
return 1;
|
||||
}
|
||||
|
||||
BN_CTX_start(ctx);
|
||||
d = BN_CTX_get(ctx);
|
||||
r = BN_CTX_get(ctx);
|
||||
t = BN_CTX_get(ctx);
|
||||
if (d == NULL || r == NULL || t == NULL) {
|
||||
if (!BN_set_word(&a_bignum, a)) {
|
||||
OPENSSL_PUT_ERROR(BN, ERR_R_INTERNAL_ERROR);
|
||||
goto err;
|
||||
}
|
||||
|
||||
/* Allocate a montgomery context if it was not supplied by the caller. */
|
||||
if (mont == NULL) {
|
||||
new_mont = BN_MONT_CTX_new();
|
||||
if (new_mont == NULL || !BN_MONT_CTX_set(new_mont, m, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
mont = new_mont;
|
||||
}
|
||||
|
||||
r_is_one = 1; /* except for Montgomery factor */
|
||||
|
||||
/* bits-1 >= 0 */
|
||||
|
||||
/* The result is accumulated in the product r*w. */
|
||||
w = a; /* bit 'bits-1' of 'p' is always set */
|
||||
for (b = bits - 2; b >= 0; b--) {
|
||||
/* First, square r*w. */
|
||||
next_w = w * w;
|
||||
if ((next_w / w) != w) {
|
||||
/* overflow */
|
||||
if (r_is_one) {
|
||||
if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
|
||||
goto err;
|
||||
}
|
||||
r_is_one = 0;
|
||||
} else {
|
||||
if (!BN_MOD_MUL_WORD(r, w, m)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
next_w = 1;
|
||||
}
|
||||
|
||||
w = next_w;
|
||||
if (!r_is_one) {
|
||||
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
|
||||
/* Second, multiply r*w by 'a' if exponent bit is set. */
|
||||
if (BN_is_bit_set(p, b)) {
|
||||
next_w = w * a;
|
||||
if ((next_w / a) != w) {
|
||||
/* overflow */
|
||||
if (r_is_one) {
|
||||
if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
|
||||
goto err;
|
||||
}
|
||||
r_is_one = 0;
|
||||
} else {
|
||||
if (!BN_MOD_MUL_WORD(r, w, m)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
next_w = a;
|
||||
}
|
||||
w = next_w;
|
||||
}
|
||||
}
|
||||
|
||||
/* Finally, set r:=r*w. */
|
||||
if (w != 1) {
|
||||
if (r_is_one) {
|
||||
if (!BN_TO_MONTGOMERY_WORD(r, w, mont)) {
|
||||
goto err;
|
||||
}
|
||||
r_is_one = 0;
|
||||
} else {
|
||||
if (!BN_MOD_MUL_WORD(r, w, m)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (r_is_one) {
|
||||
/* can happen only if a == 1*/
|
||||
if (!BN_one(rr)) {
|
||||
goto err;
|
||||
}
|
||||
} else {
|
||||
if (!BN_from_montgomery(rr, r, mont, ctx)) {
|
||||
goto err;
|
||||
}
|
||||
}
|
||||
ret = 1;
|
||||
ret = BN_mod_exp_mont(rr, &a_bignum, p, m, ctx, mont);
|
||||
|
||||
err:
|
||||
BN_MONT_CTX_free(new_mont);
|
||||
BN_CTX_end(ctx);
|
||||
BN_free(&a_bignum);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -802,9 +802,6 @@ OPENSSL_EXPORT int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a,
|
||||
BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont);
|
||||
|
||||
OPENSSL_EXPORT int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont);
|
||||
OPENSSL_EXPORT int BN_mod_exp2_mont(BIGNUM *r, const BIGNUM *a1,
|
||||
const BIGNUM *p1, const BIGNUM *a2,
|
||||
const BIGNUM *p2, const BIGNUM *m,
|
||||
@ -829,6 +826,13 @@ OPENSSL_EXPORT size_t BN_bn2mpi(const BIGNUM *in, uint8_t *out);
|
||||
* is updated. */
|
||||
OPENSSL_EXPORT BIGNUM *BN_mpi2bn(const uint8_t *in, size_t len, BIGNUM *out);
|
||||
|
||||
/* BN_mod_exp_mont_word is like |BN_mod_exp_mont| except that the base |a| is
|
||||
* given as a |BN_ULONG| instead of a |BIGNUM *|. It returns one on success
|
||||
* or zero otherwise. */
|
||||
OPENSSL_EXPORT int BN_mod_exp_mont_word(BIGNUM *r, BN_ULONG a, const BIGNUM *p,
|
||||
const BIGNUM *m, BN_CTX *ctx,
|
||||
const BN_MONT_CTX *mont);
|
||||
|
||||
|
||||
/* Private functions */
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user