提交 71883868 编写于 作者: A Andy Polyakov

bn/bn_{mont|exp}.c: switch to zero-padded intermediate vectors.

Note that exported functions maintain original behaviour, so that
external callers won't observe difference. While internally we can
now perform Montogomery multiplication on fixed-length vectors, fixed
at modulus size. The new functions, bn_to_mont_fixed_top and
bn_mul_mont_fixed_top, are declared in bn_int.h, because one can use
them even outside bn, e.g. in RSA, DSA, ECDSA...
Reviewed-by: NRich Salz <rsalz@openssl.org>
Reviewed-by: NDavid Benjamin <davidben@google.com>
(Merged from https://github.com/openssl/openssl/pull/6662)
上级 305b68f1
...@@ -361,17 +361,17 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, ...@@ -361,17 +361,17 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
ret = 1; ret = 1;
goto err; goto err;
} }
if (!BN_to_montgomery(val[0], aa, mont, ctx)) if (!bn_to_mont_fixed_top(val[0], aa, mont, ctx))
goto err; /* 1 */ goto err; /* 1 */
window = BN_window_bits_for_exponent_size(bits); window = BN_window_bits_for_exponent_size(bits);
if (window > 1) { if (window > 1) {
if (!BN_mod_mul_montgomery(d, val[0], val[0], mont, ctx)) if (!bn_mul_mont_fixed_top(d, val[0], val[0], mont, ctx))
goto err; /* 2 */ goto err; /* 2 */
j = 1 << (window - 1); j = 1 << (window - 1);
for (i = 1; i < j; i++) { for (i = 1; i < j; i++) {
if (((val[i] = BN_CTX_get(ctx)) == NULL) || if (((val[i] = BN_CTX_get(ctx)) == NULL) ||
!BN_mod_mul_montgomery(val[i], val[i - 1], d, mont, ctx)) !bn_mul_mont_fixed_top(val[i], val[i - 1], d, mont, ctx))
goto err; goto err;
} }
} }
...@@ -393,19 +393,15 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, ...@@ -393,19 +393,15 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
for (i = 1; i < j; i++) for (i = 1; i < j; i++)
r->d[i] = (~m->d[i]) & BN_MASK2; r->d[i] = (~m->d[i]) & BN_MASK2;
r->top = j; r->top = j;
/* r->flags |= BN_FLG_FIXED_TOP;
* Upper words will be zero if the corresponding words of 'm' were
* 0xfff[...], so decrement r->top accordingly.
*/
bn_correct_top(r);
} else } else
#endif #endif
if (!BN_to_montgomery(r, BN_value_one(), mont, ctx)) if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx))
goto err; goto err;
for (;;) { for (;;) {
if (BN_is_bit_set(p, wstart) == 0) { if (BN_is_bit_set(p, wstart) == 0) {
if (!start) { if (!start) {
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
goto err; goto err;
} }
if (wstart == 0) if (wstart == 0)
...@@ -436,12 +432,12 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, ...@@ -436,12 +432,12 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/* add the 'bytes above' */ /* add the 'bytes above' */
if (!start) if (!start)
for (i = 0; i < j; i++) { for (i = 0; i < j; i++) {
if (!BN_mod_mul_montgomery(r, r, r, mont, ctx)) if (!bn_mul_mont_fixed_top(r, r, r, mont, ctx))
goto err; goto err;
} }
/* wvalue will be an odd number < 2^window */ /* wvalue will be an odd number < 2^window */
if (!BN_mod_mul_montgomery(r, r, val[wvalue >> 1], mont, ctx)) if (!bn_mul_mont_fixed_top(r, r, val[wvalue >> 1], mont, ctx))
goto err; goto err;
/* move the 'window' down further */ /* move the 'window' down further */
...@@ -451,6 +447,11 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, ...@@ -451,6 +447,11 @@ int BN_mod_exp_mont(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
if (wstart < 0) if (wstart < 0)
break; break;
} }
/*
* Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
* removes padding [if any] and makes return value suitable for public
* API consumer.
*/
#if defined(SPARC_T4_MONT) #if defined(SPARC_T4_MONT)
if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) { if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
j = mont->N.top; /* borrow j */ j = mont->N.top; /* borrow j */
...@@ -575,7 +576,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top, ...@@ -575,7 +576,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBUF(BIGNUM *b, int top,
} }
b->top = top; b->top = top;
bn_correct_top(b); b->flags |= BN_FLG_FIXED_TOP;
return 1; return 1;
} }
...@@ -747,16 +748,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, ...@@ -747,16 +748,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
tmp.top = top; tmp.top = top;
} else } else
#endif #endif
if (!BN_to_montgomery(&tmp, BN_value_one(), mont, ctx)) if (!bn_to_mont_fixed_top(&tmp, BN_value_one(), mont, ctx))
goto err; goto err;
/* prepare a^1 in Montgomery domain */ /* prepare a^1 in Montgomery domain */
if (a->neg || BN_ucmp(a, m) >= 0) { if (a->neg || BN_ucmp(a, m) >= 0) {
if (!BN_nnmod(&am, a, m, ctx)) if (!BN_nnmod(&am, a, m, ctx))
goto err; goto err;
if (!BN_to_montgomery(&am, &am, mont, ctx)) if (!bn_to_mont_fixed_top(&am, &am, mont, ctx))
goto err; goto err;
} else if (!BN_to_montgomery(&am, a, mont, ctx)) } else if (!bn_to_mont_fixed_top(&am, a, mont, ctx))
goto err; goto err;
#if defined(SPARC_T4_MONT) #if defined(SPARC_T4_MONT)
...@@ -1034,14 +1035,14 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, ...@@ -1034,14 +1035,14 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
* performance advantage of sqr over mul). * performance advantage of sqr over mul).
*/ */
if (window > 1) { if (window > 1) {
if (!BN_mod_mul_montgomery(&tmp, &am, &am, mont, ctx)) if (!bn_mul_mont_fixed_top(&tmp, &am, &am, mont, ctx))
goto err; goto err;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2, if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2,
window)) window))
goto err; goto err;
for (i = 3; i < numPowers; i++) { for (i = 3; i < numPowers; i++) {
/* Calculate a^i = a^(i-1) * a */ /* Calculate a^i = a^(i-1) * a */
if (!BN_mod_mul_montgomery(&tmp, &am, &tmp, mont, ctx)) if (!bn_mul_mont_fixed_top(&tmp, &am, &tmp, mont, ctx))
goto err; goto err;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i, if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i,
window)) window))
...@@ -1072,7 +1073,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, ...@@ -1072,7 +1073,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
/* Square the result window-size times */ /* Square the result window-size times */
for (i = 0; i < window; i++) for (i = 0; i < window; i++)
if (!BN_mod_mul_montgomery(&tmp, &tmp, &tmp, mont, ctx)) if (!bn_mul_mont_fixed_top(&tmp, &tmp, &tmp, mont, ctx))
goto err; goto err;
/* /*
...@@ -1095,12 +1096,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p, ...@@ -1095,12 +1096,16 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr, const BIGNUM *a, const BIGNUM *p,
goto err; goto err;
/* Multiply the result into the intermediate result */ /* Multiply the result into the intermediate result */
if (!BN_mod_mul_montgomery(&tmp, &tmp, &am, mont, ctx)) if (!bn_mul_mont_fixed_top(&tmp, &tmp, &am, mont, ctx))
goto err; goto err;
} }
} }
/* Convert the final result from montgomery to standard format */ /*
* Done with zero-padded intermediate BIGNUMs. Final BN_from_montgomery
* removes padding [if any] and makes return value suitable for public
* API consumer.
*/
#if defined(SPARC_T4_MONT) #if defined(SPARC_T4_MONT)
if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) { if (OPENSSL_sparcv9cap_P[0] & (SPARCV9_VIS3 | SPARCV9_PREFER_FPU)) {
am.d[0] = 1; /* borrow am */ am.d[0] = 1; /* borrow am */
......
...@@ -229,7 +229,8 @@ struct bignum_st { ...@@ -229,7 +229,8 @@ struct bignum_st {
/* Used for montgomery multiplication */ /* Used for montgomery multiplication */
struct bn_mont_ctx_st { struct bn_mont_ctx_st {
int ri; /* number of bits in R */ int ri; /* number of bits in R */
BIGNUM RR; /* used to convert to montgomery form */ BIGNUM RR; /* used to convert to montgomery form,
possibly zero-padded */
BIGNUM N; /* The modulus */ BIGNUM N; /* The modulus */
BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 (Ni is only BIGNUM Ni; /* R*(1/R mod N) - N*Ni = 1 (Ni is only
* stored for bignum algorithm) */ * stored for bignum algorithm) */
......
...@@ -20,11 +20,22 @@ ...@@ -20,11 +20,22 @@
#define MONT_WORD /* use the faster word-based algorithm */ #define MONT_WORD /* use the faster word-based algorithm */
#ifdef MONT_WORD #ifdef MONT_WORD
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont); static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont);
#endif #endif
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mont, BN_CTX *ctx) BN_MONT_CTX *mont, BN_CTX *ctx)
{
int ret = bn_mul_mont_fixed_top(r, a, b, mont, ctx);
bn_correct_top(r);
bn_check_top(r);
return ret;
}
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mont, BN_CTX *ctx)
{ {
BIGNUM *tmp; BIGNUM *tmp;
int ret = 0; int ret = 0;
...@@ -37,7 +48,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, ...@@ -37,7 +48,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) { if (bn_mul_mont(r->d, a->d, b->d, mont->N.d, mont->n0, num)) {
r->neg = a->neg ^ b->neg; r->neg = a->neg ^ b->neg;
r->top = num; r->top = num;
bn_correct_top(r); r->flags |= BN_FLG_FIXED_TOP;
return 1; return 1;
} }
} }
...@@ -61,13 +72,12 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, ...@@ -61,13 +72,12 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
} }
/* reduce from aRR to aR */ /* reduce from aRR to aR */
#ifdef MONT_WORD #ifdef MONT_WORD
if (!BN_from_montgomery_word(r, tmp, mont)) if (!bn_from_montgomery_word(r, tmp, mont))
goto err; goto err;
#else #else
if (!BN_from_montgomery(r, tmp, mont, ctx)) if (!BN_from_montgomery(r, tmp, mont, ctx))
goto err; goto err;
#endif #endif
bn_check_top(r);
ret = 1; ret = 1;
err: err:
BN_CTX_end(ctx); BN_CTX_end(ctx);
...@@ -75,7 +85,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b, ...@@ -75,7 +85,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
} }
#ifdef MONT_WORD #ifdef MONT_WORD
static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) static int bn_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
{ {
BIGNUM *n; BIGNUM *n;
BN_ULONG *ap, *np, *rp, n0, v, carry; BN_ULONG *ap, *np, *rp, n0, v, carry;
...@@ -102,6 +112,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) ...@@ -102,6 +112,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
memset(&rp[r->top], 0, sizeof(*rp) * i); memset(&rp[r->top], 0, sizeof(*rp) * i);
r->top = max; r->top = max;
r->flags |= BN_FLG_FIXED_TOP;
n0 = mont->n0[0]; n0 = mont->n0[0];
/* /*
...@@ -120,6 +131,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) ...@@ -120,6 +131,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
if (bn_wexpand(ret, nl) == NULL) if (bn_wexpand(ret, nl) == NULL)
return 0; return 0;
ret->top = nl; ret->top = nl;
ret->flags |= BN_FLG_FIXED_TOP;
ret->neg = r->neg; ret->neg = r->neg;
rp = ret->d; rp = ret->d;
...@@ -140,9 +152,6 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont) ...@@ -140,9 +152,6 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
rp[i] = (carry & ap[i]) | (~carry & rp[i]); rp[i] = (carry & ap[i]) | (~carry & rp[i]);
ap[i] = 0; ap[i] = 0;
} }
bn_correct_top(r);
bn_correct_top(ret);
bn_check_top(ret);
return 1; return 1;
} }
...@@ -156,8 +165,11 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, ...@@ -156,8 +165,11 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
BIGNUM *t; BIGNUM *t;
BN_CTX_start(ctx); BN_CTX_start(ctx);
if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) {
retn = BN_from_montgomery_word(ret, t, mont); retn = bn_from_montgomery_word(ret, t, mont);
bn_correct_top(ret);
bn_check_top(ret);
}
BN_CTX_end(ctx); BN_CTX_end(ctx);
#else /* !MONT_WORD */ #else /* !MONT_WORD */
BIGNUM *t1, *t2; BIGNUM *t1, *t2;
...@@ -195,6 +207,12 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont, ...@@ -195,6 +207,12 @@ int BN_from_montgomery(BIGNUM *ret, const BIGNUM *a, BN_MONT_CTX *mont,
return retn; return retn;
} }
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx)
{
return bn_mul_mont_fixed_top(r, a, &(mont->RR), mont, ctx);
}
BN_MONT_CTX *BN_MONT_CTX_new(void) BN_MONT_CTX *BN_MONT_CTX_new(void)
{ {
BN_MONT_CTX *ret; BN_MONT_CTX *ret;
...@@ -232,7 +250,7 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont) ...@@ -232,7 +250,7 @@ void BN_MONT_CTX_free(BN_MONT_CTX *mont)
int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
{ {
int ret = 0; int i, ret = 0;
BIGNUM *Ri, *R; BIGNUM *Ri, *R;
if (BN_is_zero(mod)) if (BN_is_zero(mod))
...@@ -367,6 +385,11 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx) ...@@ -367,6 +385,11 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx)) if (!BN_mod(&(mont->RR), &(mont->RR), &(mont->N), ctx))
goto err; goto err;
for (i = mont->RR.top, ret = mont->N.top; i < ret; i++)
mont->RR.d[i] = 0;
mont->RR.top = ret;
mont->RR.flags |= BN_FLG_FIXED_TOP;
ret = 1; ret = 1;
err: err:
BN_CTX_end(ctx); BN_CTX_end(ctx);
......
...@@ -60,4 +60,16 @@ void bn_set_static_words(BIGNUM *a, BN_ULONG *words, int size); ...@@ -60,4 +60,16 @@ void bn_set_static_words(BIGNUM *a, BN_ULONG *words, int size);
*/ */
int bn_set_words(BIGNUM *a, BN_ULONG *words, int num_words); int bn_set_words(BIGNUM *a, BN_ULONG *words, int num_words);
/*
* Some BIGNUM functions assume most significant limb to be non-zero, which
* is customarily arranged by bn_correct_top. Output from below functions
* is not processed with bn_correct_top, and for this reason it may not be
* returned out of public API. It may only be passed internally into other
* functions known to support non-minimal or zero-padded BIGNUMs.
*/
int bn_mul_mont_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
BN_MONT_CTX *mont, BN_CTX *ctx);
int bn_to_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx);
#endif #endif
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册