File openssl-bn_mul_mont_fixed_top.patch of Package openssl.14115
From 71883868ea5b33416ae8283bcc38dd2d97e5006b Mon Sep 17 00:00:00 2001
From: Andy Polyakov <appro@openssl.org>
Date: Fri, 6 Jul 2018 15:13:15 +0200
Subject: [PATCH] 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: Rich Salz <rsalz@openssl.org>
Reviewed-by: David Benjamin <davidben@google.com>
(Merged from https://github.com/openssl/openssl/pull/6662)
---
crypto/bn/bn_exp.c | 47 ++++++++++++++++++--------------
crypto/bn/bn_lcl.h | 3 +-
crypto/bn/bn_mont.c | 45 ++++++++++++++++++++++--------
crypto/bn_int.h | 12 ++++++++
4 files changed, 74 insertions(+), 33 deletions(-)
Index: openssl-1.0.1i/crypto/bn/bn_exp.c
===================================================================
--- openssl-1.0.1i.orig/crypto/bn/bn_exp.c
+++ openssl-1.0.1i/crypto/bn/bn_exp.c
@@ -445,18 +445,19 @@ int BN_mod_exp_mont(BIGNUM *rr, const BI
ret = 1;
goto err;
}
- if (!BN_to_montgomery(val[0],aa,mont,ctx)) goto err; /* 1 */
+ if (!bn_to_mont_fixed_top(val[0], aa, mont, ctx))
+ goto err; /* 1 */
window = BN_window_bits_for_exponent_size(bits);
if (window > 1)
{
- if (!BN_mod_mul_montgomery(d,val[0],val[0],mont,ctx)) goto err; /* 2 */
+ if (!bn_mul_mont_fixed_top(d, val[0], val[0], mont, ctx))
+ goto err; /* 2 */
j=1<<(window-1);
for (i=1; i<j; i++)
{
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;
}
}
@@ -468,14 +469,15 @@ int BN_mod_exp_mont(BIGNUM *rr, const BI
wstart=bits-1; /* The top bit of the window */
wend=0; /* The bottom bit of the window */
- if (!BN_to_montgomery(r,BN_value_one(),mont,ctx)) goto err;
+ if (!bn_to_mont_fixed_top(r, BN_value_one(), mont, ctx))
+ goto err;
for (;;)
{
if (BN_is_bit_set(p,wstart) == 0)
{
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;
}
if (wstart == 0) break;
@@ -506,12 +508,12 @@ int BN_mod_exp_mont(BIGNUM *rr, const BI
if (!start)
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;
}
/* 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;
/* move the 'window' down further */
@@ -617,7 +619,7 @@ static int MOD_EXP_CTIME_COPY_FROM_PREBU
}
b->top = top;
- bn_correct_top(b);
+ b->flags |= BN_FLG_FIXED_TOP;
return 1;
}
@@ -713,7 +715,8 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
/* prepare a^0 in Montgomery domain */
#if 1
- if (!BN_to_montgomery(&tmp,BN_value_one(),mont,ctx)) goto err;
+ if (!bn_to_mont_fixed_top(&tmp, BN_value_one(), mont, ctx))
+ goto err;
#else
tmp.d[0] = (0-m->d[0])&BN_MASK2; /* 2^(top*BN_BITS2) - m */
for (i=1;i<top;i++)
@@ -725,9 +728,9 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
if (a->neg || BN_ucmp(a,m) >= 0)
{
if (!BN_mod(&am,a,m,ctx)) goto err;
- if (!BN_to_montgomery(&am,&am,mont,ctx)) goto err;
+ if (!bn_to_mont_fixed_top(&am, &am, mont, ctx)) goto err;
}
- else if (!BN_to_montgomery(&am,a,mont,ctx)) goto err;
+ else if (!bn_to_mont_fixed_top(&am,a,mont,ctx)) goto err;
#if defined(OPENSSL_BN_ASM_MONT5)
/* This optimization uses ideas from http://eprint.iacr.org/2011/239,
@@ -833,13 +836,13 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
*/
if (window > 1)
{
- if (!BN_mod_mul_montgomery(&tmp,&am,&am,mont,ctx)) goto err;
+ if (!bn_mul_mont_fixed_top(&tmp,&am,&am,mont,ctx)) goto err;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, 2,
window)) goto err;
for (i=3; i<numPowers; i++)
{
/* 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;
if (!MOD_EXP_CTIME_COPY_TO_PREBUF(&tmp, top, powerbuf, i,
window)) goto err;
@@ -867,7 +870,7 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
while (bits > 0) {
/* Square the result window-size times */
for (i = 0; i < window; i++)
- if (!BN_mod_mul_montgomery(&tmp,&tmp,&tmp,mont,ctx)) goto err;
+ if (!bn_mul_mont_fixed_top(&tmp,&tmp,&tmp,mont,ctx)) goto err;
/*
* Get a window's worth of bits from the exponent
@@ -886,11 +889,15 @@ int BN_mod_exp_mont_consttime(BIGNUM *rr
window)) goto err;
/* Multiply the result into the intermediate result */
- if (!BN_mod_mul_montgomery(&tmp,&tmp,&am,mont,ctx)) goto err;
+ if (!bn_mul_mont_fixed_top(&tmp,&tmp,&am,mont,ctx)) 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 (!BN_from_montgomery(rr,&tmp,mont,ctx)) goto err;
ret=1;
err:
Index: openssl-1.0.1i/crypto/bn/bn_mont.c
===================================================================
--- openssl-1.0.1i.orig/crypto/bn/bn_mont.c
+++ openssl-1.0.1i/crypto/bn/bn_mont.c
@@ -123,12 +123,21 @@
#define MONT_WORD /* use the faster word-based algorithm */
#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
int BN_mod_mul_montgomery(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
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;
int ret=0;
#if defined(OPENSSL_BN_ASM_MONT) && defined(MONT_WORD)
@@ -141,7 +150,7 @@ int BN_mod_mul_montgomery(BIGNUM *r, con
{
r->neg = a->neg^b->neg;
r->top = num;
- bn_correct_top(r);
+ r->flags |= BN_FLG_FIXED_TOP;
return(1);
}
}
@@ -161,11 +170,10 @@ int BN_mod_mul_montgomery(BIGNUM *r, con
}
/* reduce from aRR to aR */
#ifdef MONT_WORD
- if (!BN_from_montgomery_word(r,tmp,mont)) goto err;
+ if (!bn_from_montgomery_word(r,tmp,mont)) goto err;
#else
if (!BN_from_montgomery(r,tmp,mont,ctx)) goto err;
#endif
- bn_check_top(r);
ret=1;
err:
BN_CTX_end(ctx);
@@ -173,7 +181,7 @@ err:
}
#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;
BN_ULONG *ap,*np,*rp,n0,v,carry;
@@ -198,6 +206,7 @@ static int BN_from_montgomery_word(BIGNU
}
r->top=max;
+ r->flags |= BN_FLG_FIXED_TOP;
n0=mont->n0[0];
#ifdef BN_COUNT
@@ -229,6 +238,7 @@ static int BN_from_montgomery_word(BIGNU
if (bn_wexpand(ret,nl) == NULL) return(0);
ret->top=nl;
+ ret->flags |= BN_FLG_FIXED_TOP;
ret->neg=r->neg;
rp=ret->d;
@@ -294,8 +304,11 @@ int bn_from_mont_fixed_top(BIGNUM *ret,
BIGNUM *t;
BN_CTX_start(ctx);
- if ((t = BN_CTX_get(ctx)) && BN_copy(t,a))
- retn = BN_from_montgomery_word(ret,t,mont);
+ if ((t = BN_CTX_get(ctx)) && BN_copy(t, a)) {
+ retn = bn_from_montgomery_word(ret, t, mont);
+ bn_correct_top(ret);
+ bn_check_top(ret);
+ }
BN_CTX_end(ctx);
#else /* !MONT_WORD */
BIGNUM *t1,*t2;
@@ -327,6 +340,12 @@ int bn_from_mont_fixed_top(BIGNUM *ret,
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 *ret;
@@ -363,7 +382,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 ret = 0;
+ int i, ret = 0;
BIGNUM *Ri,*R;
BN_CTX_start(ctx);
@@ -465,6 +484,11 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, c
if (!BN_set_bit(&(mont->RR),mont->ri*2)) goto err;
if (!BN_mod(&(mont->RR),&(mont->RR),&(mont->N),ctx)) 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;
err:
BN_CTX_end(ctx);
Index: openssl-1.0.1i/crypto/bn/bn.h
===================================================================
--- openssl-1.0.1i.orig/crypto/bn/bn.h
+++ openssl-1.0.1i/crypto/bn/bn.h
@@ -330,7 +330,8 @@ struct bignum_st
struct bn_mont_ctx_st
{
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 Ni; /* R*(1/R mod N) - N*Ni = 1
* (Ni is only stored for bignum algorithm) */
@@ -581,6 +582,12 @@ int BN_mod_mul_montgomery(BIGNUM *r,cons
int BN_from_montgomery(BIGNUM *r,const BIGNUM *a,
BN_MONT_CTX *mont, BN_CTX *ctx);
int bn_bn2binpad(const BIGNUM *a, unsigned char *to, int tolen);
+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);
+int bn_mod_add_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,
+ const BIGNUM *m);
int bn_from_mont_fixed_top(BIGNUM *r, const BIGNUM *a, BN_MONT_CTX *mont,
BN_CTX *ctx);
int bn_mod_sub_fixed_top(BIGNUM *r, const BIGNUM *a, const BIGNUM *b,