summaryrefslogtreecommitdiff
path: root/Cryptlib/OpenSSL/crypto/bn/bn_asm.c
diff options
context:
space:
mode:
Diffstat (limited to 'Cryptlib/OpenSSL/crypto/bn/bn_asm.c')
-rw-r--r--Cryptlib/OpenSSL/crypto/bn/bn_asm.c607
1 files changed, 390 insertions, 217 deletions
diff --git a/Cryptlib/OpenSSL/crypto/bn/bn_asm.c b/Cryptlib/OpenSSL/crypto/bn/bn_asm.c
index 92e9539c..03a33cff 100644
--- a/Cryptlib/OpenSSL/crypto/bn/bn_asm.c
+++ b/Cryptlib/OpenSSL/crypto/bn/bn_asm.c
@@ -77,6 +77,7 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
if (num <= 0)
return (c1);
+# ifndef OPENSSL_SMALL_FOOTPRINT
while (num & ~3) {
mul_add(rp[0], ap[0], w, c1);
mul_add(rp[1], ap[1], w, c1);
@@ -86,15 +87,12 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
rp += 4;
num -= 4;
}
- if (num) {
+# endif
+ while (num) {
mul_add(rp[0], ap[0], w, c1);
- if (--num == 0)
- return c1;
- mul_add(rp[1], ap[1], w, c1);
- if (--num == 0)
- return c1;
- mul_add(rp[2], ap[2], w, c1);
- return c1;
+ ap++;
+ rp++;
+ num--;
}
return (c1);
@@ -108,6 +106,7 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
if (num <= 0)
return (c1);
+# ifndef OPENSSL_SMALL_FOOTPRINT
while (num & ~3) {
mul(rp[0], ap[0], w, c1);
mul(rp[1], ap[1], w, c1);
@@ -117,14 +116,12 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
rp += 4;
num -= 4;
}
- if (num) {
+# endif
+ while (num) {
mul(rp[0], ap[0], w, c1);
- if (--num == 0)
- return c1;
- mul(rp[1], ap[1], w, c1);
- if (--num == 0)
- return c1;
- mul(rp[2], ap[2], w, c1);
+ ap++;
+ rp++;
+ num--;
}
return (c1);
}
@@ -134,6 +131,8 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
assert(n >= 0);
if (n <= 0)
return;
+
+# ifndef OPENSSL_SMALL_FOOTPRINT
while (n & ~3) {
sqr(r[0], r[1], a[0]);
sqr(r[2], r[3], a[1]);
@@ -143,14 +142,12 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
r += 8;
n -= 4;
}
- if (n) {
+# endif
+ while (n) {
sqr(r[0], r[1], a[0]);
- if (--n == 0)
- return;
- sqr(r[2], r[3], a[1]);
- if (--n == 0)
- return;
- sqr(r[4], r[5], a[2]);
+ a++;
+ r += 2;
+ n--;
}
}
@@ -170,21 +167,22 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num,
bl = LBITS(w);
bh = HBITS(w);
- for (;;) {
+# ifndef OPENSSL_SMALL_FOOTPRINT
+ while (num & ~3) {
mul_add(rp[0], ap[0], bl, bh, c);
- if (--num == 0)
- break;
mul_add(rp[1], ap[1], bl, bh, c);
- if (--num == 0)
- break;
mul_add(rp[2], ap[2], bl, bh, c);
- if (--num == 0)
- break;
mul_add(rp[3], ap[3], bl, bh, c);
- if (--num == 0)
- break;
ap += 4;
rp += 4;
+ num -= 4;
+ }
+# endif
+ while (num) {
+ mul_add(rp[0], ap[0], bl, bh, c);
+ ap++;
+ rp++;
+ num--;
}
return (c);
}
@@ -201,21 +199,22 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
bl = LBITS(w);
bh = HBITS(w);
- for (;;) {
+# ifndef OPENSSL_SMALL_FOOTPRINT
+ while (num & ~3) {
mul(rp[0], ap[0], bl, bh, carry);
- if (--num == 0)
- break;
mul(rp[1], ap[1], bl, bh, carry);
- if (--num == 0)
- break;
mul(rp[2], ap[2], bl, bh, carry);
- if (--num == 0)
- break;
mul(rp[3], ap[3], bl, bh, carry);
- if (--num == 0)
- break;
ap += 4;
rp += 4;
+ num -= 4;
+ }
+# endif
+ while (num) {
+ mul(rp[0], ap[0], bl, bh, carry);
+ ap++;
+ rp++;
+ num--;
}
return (carry);
}
@@ -225,25 +224,23 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
assert(n >= 0);
if (n <= 0)
return;
- for (;;) {
- sqr64(r[0], r[1], a[0]);
- if (--n == 0)
- break;
+# ifndef OPENSSL_SMALL_FOOTPRINT
+ while (n & ~3) {
+ sqr64(r[0], r[1], a[0]);
sqr64(r[2], r[3], a[1]);
- if (--n == 0)
- break;
-
sqr64(r[4], r[5], a[2]);
- if (--n == 0)
- break;
-
sqr64(r[6], r[7], a[3]);
- if (--n == 0)
- break;
-
a += 4;
r += 8;
+ n -= 4;
+ }
+# endif
+ while (n) {
+ sqr64(r[0], r[1], a[0]);
+ a++;
+ r += 2;
+ n--;
}
}
@@ -335,34 +332,34 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
if (n <= 0)
return ((BN_ULONG)0);
- for (;;) {
+# ifndef OPENSSL_SMALL_FOOTPRINT
+ while (n & ~3) {
ll += (BN_ULLONG) a[0] + b[0];
r[0] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
- if (--n <= 0)
- break;
-
ll += (BN_ULLONG) a[1] + b[1];
r[1] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
- if (--n <= 0)
- break;
-
ll += (BN_ULLONG) a[2] + b[2];
r[2] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
- if (--n <= 0)
- break;
-
ll += (BN_ULLONG) a[3] + b[3];
r[3] = (BN_ULONG)ll & BN_MASK2;
ll >>= BN_BITS2;
- if (--n <= 0)
- break;
-
a += 4;
b += 4;
r += 4;
+ n -= 4;
+ }
+# endif
+ while (n) {
+ ll += (BN_ULLONG) a[0] + b[0];
+ r[0] = (BN_ULONG)ll & BN_MASK2;
+ ll >>= BN_BITS2;
+ a++;
+ b++;
+ r++;
+ n--;
}
return ((BN_ULONG)ll);
}
@@ -377,46 +374,49 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
return ((BN_ULONG)0);
c = 0;
- for (;;) {
+# ifndef OPENSSL_SMALL_FOOTPRINT
+ while (n & ~3) {
t = a[0];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[0]) & BN_MASK2;
c += (l < t);
r[0] = l;
- if (--n <= 0)
- break;
-
t = a[1];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[1]) & BN_MASK2;
c += (l < t);
r[1] = l;
- if (--n <= 0)
- break;
-
t = a[2];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[2]) & BN_MASK2;
c += (l < t);
r[2] = l;
- if (--n <= 0)
- break;
-
t = a[3];
t = (t + c) & BN_MASK2;
c = (t < c);
l = (t + b[3]) & BN_MASK2;
c += (l < t);
r[3] = l;
- if (--n <= 0)
- break;
-
a += 4;
b += 4;
r += 4;
+ n -= 4;
+ }
+# endif
+ while (n) {
+ t = a[0];
+ t = (t + c) & BN_MASK2;
+ c = (t < c);
+ l = (t + b[0]) & BN_MASK2;
+ c += (l < t);
+ r[0] = l;
+ a++;
+ b++;
+ r++;
+ n--;
}
return ((BN_ULONG)c);
}
@@ -432,47 +432,49 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
if (n <= 0)
return ((BN_ULONG)0);
- for (;;) {
+#ifndef OPENSSL_SMALL_FOOTPRINT
+ while (n & ~3) {
t1 = a[0];
t2 = b[0];
r[0] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
- if (--n <= 0)
- break;
-
t1 = a[1];
t2 = b[1];
r[1] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
- if (--n <= 0)
- break;
-
t1 = a[2];
t2 = b[2];
r[2] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
- if (--n <= 0)
- break;
-
t1 = a[3];
t2 = b[3];
r[3] = (t1 - t2 - c) & BN_MASK2;
if (t1 != t2)
c = (t1 < t2);
- if (--n <= 0)
- break;
-
a += 4;
b += 4;
r += 4;
+ n -= 4;
+ }
+#endif
+ while (n) {
+ t1 = a[0];
+ t2 = b[0];
+ r[0] = (t1 - t2 - c) & BN_MASK2;
+ if (t1 != t2)
+ c = (t1 < t2);
+ a++;
+ b++;
+ r++;
+ n--;
}
return (c);
}
-#ifdef BN_MUL_COMBA
+#if defined(BN_MUL_COMBA) && !defined(OPENSSL_SMALL_FOOTPRINT)
# undef bn_mul_comba8
# undef bn_mul_comba4
@@ -487,121 +489,144 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
* c=(c2,c1,c0)
*/
+# ifdef BN_LLONG
/*
- * Keep in mind that carrying into high part of multiplication result
- * can not overflow, because it cannot be all-ones.
+ * Keep in mind that additions to multiplication result can not
+ * overflow, because its high half cannot be all-ones.
*/
-# ifdef BN_LLONG
-# define mul_add_c(a,b,c0,c1,c2) \
- t=(BN_ULLONG)a*b; \
- t1=(BN_ULONG)Lw(t); \
- t2=(BN_ULONG)Hw(t); \
- c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
- c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
-
-# define mul_add_c2(a,b,c0,c1,c2) \
- t=(BN_ULLONG)a*b; \
- tt=(t+t)&BN_MASK; \
- if (tt < t) c2++; \
- t1=(BN_ULONG)Lw(tt); \
- t2=(BN_ULONG)Hw(tt); \
- c0=(c0+t1)&BN_MASK2; \
- if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \
- c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
-
-# define sqr_add_c(a,i,c0,c1,c2) \
- t=(BN_ULLONG)a[i]*a[i]; \
- t1=(BN_ULONG)Lw(t); \
- t2=(BN_ULONG)Hw(t); \
- c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
- c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+# define mul_add_c(a,b,c0,c1,c2) do { \
+ BN_ULONG hi; \
+ BN_ULLONG t = (BN_ULLONG)(a)*(b); \
+ t += c0; /* no carry */ \
+ c0 = (BN_ULONG)Lw(t); \
+ hi = (BN_ULONG)Hw(t); \
+ c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ } while(0)
+
+# define mul_add_c2(a,b,c0,c1,c2) do { \
+ BN_ULONG hi; \
+ BN_ULLONG t = (BN_ULLONG)(a)*(b); \
+ BN_ULLONG tt = t+c0; /* no carry */ \
+ c0 = (BN_ULONG)Lw(tt); \
+ hi = (BN_ULONG)Hw(tt); \
+ c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ t += c0; /* no carry */ \
+ c0 = (BN_ULONG)Lw(t); \
+ hi = (BN_ULONG)Hw(t); \
+ c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ } while(0)
+
+# define sqr_add_c(a,i,c0,c1,c2) do { \
+ BN_ULONG hi; \
+ BN_ULLONG t = (BN_ULLONG)a[i]*a[i]; \
+ t += c0; /* no carry */ \
+ c0 = (BN_ULONG)Lw(t); \
+ hi = (BN_ULONG)Hw(t); \
+ c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ } while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
# elif defined(BN_UMULT_LOHI)
-
-# define mul_add_c(a,b,c0,c1,c2) { \
- BN_ULONG ta=(a),tb=(b); \
- BN_UMULT_LOHI(t1,t2,ta,tb); \
- c0 += t1; t2 += (c0<t1)?1:0; \
- c1 += t2; c2 += (c1<t2)?1:0; \
- }
-
-# define mul_add_c2(a,b,c0,c1,c2) { \
- BN_ULONG ta=(a),tb=(b),t0; \
- BN_UMULT_LOHI(t0,t1,ta,tb); \
- c0 += t0; t2 = t1+((c0<t0)?1:0);\
- c1 += t2; c2 += (c1<t2)?1:0; \
- c0 += t0; t1 += (c0<t0)?1:0; \
- c1 += t1; c2 += (c1<t1)?1:0; \
- }
-
-# define sqr_add_c(a,i,c0,c1,c2) { \
- BN_ULONG ta=(a)[i]; \
- BN_UMULT_LOHI(t1,t2,ta,ta); \
- c0 += t1; t2 += (c0<t1)?1:0; \
- c1 += t2; c2 += (c1<t2)?1:0; \
- }
+/*
+ * Keep in mind that additions to hi can not overflow, because
+ * the high word of a multiplication result cannot be all-ones.
+ */
+# define mul_add_c(a,b,c0,c1,c2) do { \
+ BN_ULONG ta = (a), tb = (b); \
+ BN_ULONG lo, hi; \
+ BN_UMULT_LOHI(lo,hi,ta,tb); \
+ c0 += lo; hi += (c0<lo)?1:0; \
+ c1 += hi; c2 += (c1<hi)?1:0; \
+ } while(0)
+
+# define mul_add_c2(a,b,c0,c1,c2) do { \
+ BN_ULONG ta = (a), tb = (b); \
+ BN_ULONG lo, hi, tt; \
+ BN_UMULT_LOHI(lo,hi,ta,tb); \
+ c0 += lo; tt = hi+((c0<lo)?1:0); \
+ c1 += tt; c2 += (c1<tt)?1:0; \
+ c0 += lo; hi += (c0<lo)?1:0; \
+ c1 += hi; c2 += (c1<hi)?1:0; \
+ } while(0)
+
+# define sqr_add_c(a,i,c0,c1,c2) do { \
+ BN_ULONG ta = (a)[i]; \
+ BN_ULONG lo, hi; \
+ BN_UMULT_LOHI(lo,hi,ta,ta); \
+ c0 += lo; hi += (c0<lo)?1:0; \
+ c1 += hi; c2 += (c1<hi)?1:0; \
+ } while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
# elif defined(BN_UMULT_HIGH)
-
-# define mul_add_c(a,b,c0,c1,c2) { \
- BN_ULONG ta=(a),tb=(b); \
- t1 = ta * tb; \
- t2 = BN_UMULT_HIGH(ta,tb); \
- c0 += t1; t2 += (c0<t1)?1:0; \
- c1 += t2; c2 += (c1<t2)?1:0; \
- }
-
-# define mul_add_c2(a,b,c0,c1,c2) { \
- BN_ULONG ta=(a),tb=(b),t0; \
- t1 = BN_UMULT_HIGH(ta,tb); \
- t0 = ta * tb; \
- c0 += t0; t2 = t1+((c0<t0)?1:0);\
- c1 += t2; c2 += (c1<t2)?1:0; \
- c0 += t0; t1 += (c0<t0)?1:0; \
- c1 += t1; c2 += (c1<t1)?1:0; \
- }
-
-# define sqr_add_c(a,i,c0,c1,c2) { \
- BN_ULONG ta=(a)[i]; \
- t1 = ta * ta; \
- t2 = BN_UMULT_HIGH(ta,ta); \
- c0 += t1; t2 += (c0<t1)?1:0; \
- c1 += t2; c2 += (c1<t2)?1:0; \
- }
+/*
+ * Keep in mind that additions to hi can not overflow, because
+ * the high word of a multiplication result cannot be all-ones.
+ */
+# define mul_add_c(a,b,c0,c1,c2) do { \
+ BN_ULONG ta = (a), tb = (b); \
+ BN_ULONG lo = ta * tb; \
+ BN_ULONG hi = BN_UMULT_HIGH(ta,tb); \
+ c0 += lo; hi += (c0<lo)?1:0; \
+ c1 += hi; c2 += (c1<hi)?1:0; \
+ } while(0)
+
+# define mul_add_c2(a,b,c0,c1,c2) do { \
+ BN_ULONG ta = (a), tb = (b), tt; \
+ BN_ULONG lo = ta * tb; \
+ BN_ULONG hi = BN_UMULT_HIGH(ta,tb); \
+ c0 += lo; tt = hi + ((c0<lo)?1:0); \
+ c1 += tt; c2 += (c1<tt)?1:0; \
+ c0 += lo; hi += (c0<lo)?1:0; \
+ c1 += hi; c2 += (c1<hi)?1:0; \
+ } while(0)
+
+# define sqr_add_c(a,i,c0,c1,c2) do { \
+ BN_ULONG ta = (a)[i]; \
+ BN_ULONG lo = ta * ta; \
+ BN_ULONG hi = BN_UMULT_HIGH(ta,ta); \
+ c0 += lo; hi += (c0<lo)?1:0; \
+ c1 += hi; c2 += (c1<hi)?1:0; \
+ } while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
# else /* !BN_LLONG */
-# define mul_add_c(a,b,c0,c1,c2) \
- t1=LBITS(a); t2=HBITS(a); \
- bl=LBITS(b); bh=HBITS(b); \
- mul64(t1,t2,bl,bh); \
- c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
- c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
-
-# define mul_add_c2(a,b,c0,c1,c2) \
- t1=LBITS(a); t2=HBITS(a); \
- bl=LBITS(b); bh=HBITS(b); \
- mul64(t1,t2,bl,bh); \
- if (t2 & BN_TBIT) c2++; \
- t2=(t2+t2)&BN_MASK2; \
- if (t1 & BN_TBIT) t2++; \
- t1=(t1+t1)&BN_MASK2; \
- c0=(c0+t1)&BN_MASK2; \
- if ((c0 < t1) && (((++t2)&BN_MASK2) == 0)) c2++; \
- c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
-
-# define sqr_add_c(a,i,c0,c1,c2) \
- sqr64(t1,t2,(a)[i]); \
- c0=(c0+t1)&BN_MASK2; if ((c0) < t1) t2++; \
- c1=(c1+t2)&BN_MASK2; if ((c1) < t2) c2++;
+/*
+ * Keep in mind that additions to hi can not overflow, because
+ * the high word of a multiplication result cannot be all-ones.
+ */
+# define mul_add_c(a,b,c0,c1,c2) do { \
+ BN_ULONG lo = LBITS(a), hi = HBITS(a); \
+ BN_ULONG bl = LBITS(b), bh = HBITS(b); \
+ mul64(lo,hi,bl,bh); \
+ c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
+ c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ } while(0)
+
+# define mul_add_c2(a,b,c0,c1,c2) do { \
+ BN_ULONG tt; \
+ BN_ULONG lo = LBITS(a), hi = HBITS(a); \
+ BN_ULONG bl = LBITS(b), bh = HBITS(b); \
+ mul64(lo,hi,bl,bh); \
+ tt = hi; \
+ c0 = (c0+lo)&BN_MASK2; if (c0<lo) tt++; \
+ c1 = (c1+tt)&BN_MASK2; if (c1<tt) c2++; \
+ c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
+ c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ } while(0)
+
+# define sqr_add_c(a,i,c0,c1,c2) do { \
+ BN_ULONG lo, hi; \
+ sqr64(lo,hi,(a)[i]); \
+ c0 = (c0+lo)&BN_MASK2; if (c0<lo) hi++; \
+ c1 = (c1+hi)&BN_MASK2; if (c1<hi) c2++; \
+ } while(0)
# define sqr_add_c2(a,i,j,c0,c1,c2) \
mul_add_c2((a)[i],(a)[j],c0,c1,c2)
@@ -609,12 +634,6 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
-# ifdef BN_LLONG
- BN_ULLONG t;
-# else
- BN_ULONG bl, bh;
-# endif
- BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -718,12 +737,6 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
{
-# ifdef BN_LLONG
- BN_ULLONG t;
-# else
- BN_ULONG bl, bh;
-# endif
- BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -763,12 +776,6 @@ void bn_mul_comba4(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
{
-# ifdef BN_LLONG
- BN_ULLONG t, tt;
-# else
- BN_ULONG bl, bh;
-# endif
- BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -844,12 +851,6 @@ void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
{
-# ifdef BN_LLONG
- BN_ULLONG t, tt;
-# else
- BN_ULONG bl, bh;
-# endif
- BN_ULONG t1, t2;
BN_ULONG c1, c2, c3;
c1 = 0;
@@ -880,18 +881,138 @@ void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
r[6] = c1;
r[7] = c2;
}
+
+# ifdef OPENSSL_NO_ASM
+# ifdef OPENSSL_BN_ASM_MONT
+# include <alloca.h>
+/*
+ * This is essentially reference implementation, which may or may not
+ * result in performance improvement. E.g. on IA-32 this routine was
+ * observed to give 40% faster rsa1024 private key operations and 10%
+ * faster rsa4096 ones, while on AMD64 it improves rsa1024 sign only
+ * by 10% and *worsens* rsa4096 sign by 15%. Once again, it's a
+ * reference implementation, one to be used as starting point for
+ * platform-specific assembler. Mentioned numbers apply to compiler
+ * generated code compiled with and without -DOPENSSL_BN_ASM_MONT and
+ * can vary not only from platform to platform, but even for compiler
+ * versions. Assembler vs. assembler improvement coefficients can
+ * [and are known to] differ and are to be documented elsewhere.
+ */
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0p, int num)
+{
+ BN_ULONG c0, c1, ml, *tp, n0;
+# ifdef mul64
+ BN_ULONG mh;
+# endif
+ volatile BN_ULONG *vp;
+ int i = 0, j;
+
+# if 0 /* template for platform-specific
+ * implementation */
+ if (ap == bp)
+ return bn_sqr_mont(rp, ap, np, n0p, num);
+# endif
+ vp = tp = alloca((num + 2) * sizeof(BN_ULONG));
+
+ n0 = *n0p;
+
+ c0 = 0;
+ ml = bp[0];
+# ifdef mul64
+ mh = HBITS(ml);
+ ml = LBITS(ml);
+ for (j = 0; j < num; ++j)
+ mul(tp[j], ap[j], ml, mh, c0);
+# else
+ for (j = 0; j < num; ++j)
+ mul(tp[j], ap[j], ml, c0);
+# endif
+
+ tp[num] = c0;
+ tp[num + 1] = 0;
+ goto enter;
+
+ for (i = 0; i < num; i++) {
+ c0 = 0;
+ ml = bp[i];
+# ifdef mul64
+ mh = HBITS(ml);
+ ml = LBITS(ml);
+ for (j = 0; j < num; ++j)
+ mul_add(tp[j], ap[j], ml, mh, c0);
+# else
+ for (j = 0; j < num; ++j)
+ mul_add(tp[j], ap[j], ml, c0);
+# endif
+ c1 = (tp[num] + c0) & BN_MASK2;
+ tp[num] = c1;
+ tp[num + 1] = (c1 < c0 ? 1 : 0);
+ enter:
+ c1 = tp[0];
+ ml = (c1 * n0) & BN_MASK2;
+ c0 = 0;
+# ifdef mul64
+ mh = HBITS(ml);
+ ml = LBITS(ml);
+ mul_add(c1, np[0], ml, mh, c0);
+# else
+ mul_add(c1, ml, np[0], c0);
+# endif
+ for (j = 1; j < num; j++) {
+ c1 = tp[j];
+# ifdef mul64
+ mul_add(c1, np[j], ml, mh, c0);
+# else
+ mul_add(c1, ml, np[j], c0);
+# endif
+ tp[j - 1] = c1 & BN_MASK2;
+ }
+ c1 = (tp[num] + c0) & BN_MASK2;
+ tp[num - 1] = c1;
+ tp[num] = tp[num + 1] + (c1 < c0 ? 1 : 0);
+ }
+
+ if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {
+ c0 = bn_sub_words(rp, tp, np, num);
+ if (tp[num] != 0 || c0 == 0) {
+ for (i = 0; i < num + 2; i++)
+ vp[i] = 0;
+ return 1;
+ }
+ }
+ for (i = 0; i < num; i++)
+ rp[i] = tp[i], vp[i] = 0;
+ vp[num] = 0;
+ vp[num + 1] = 0;
+ return 1;
+}
+# else
+/*
+ * Return value of 0 indicates that multiplication/convolution was not
+ * performed to signal the caller to fall down to alternative/original
+ * code-path.
+ */
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num)
+{
+ return 0;
+}
+# endif /* OPENSSL_BN_ASM_MONT */
+# endif
+
#else /* !BN_MUL_COMBA */
/* hmm... is it faster just to do a multiply? */
# undef bn_sqr_comba4
-void bn_sqr_comba4(BN_ULONG *r, BN_ULONG *a)
+void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG t[8];
bn_sqr_normal(r, a, 4, t);
}
# undef bn_sqr_comba8
-void bn_sqr_comba8(BN_ULONG *r, BN_ULONG *a)
+void bn_sqr_comba8(BN_ULONG *r, const BN_ULONG *a)
{
BN_ULONG t[16];
bn_sqr_normal(r, a, 8, t);
@@ -917,4 +1038,56 @@ void bn_mul_comba8(BN_ULONG *r, BN_ULONG *a, BN_ULONG *b)
r[15] = bn_mul_add_words(&(r[7]), a, 8, b[7]);
}
+# ifdef OPENSSL_NO_ASM
+# ifdef OPENSSL_BN_ASM_MONT
+# include <alloca.h>
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0p, int num)
+{
+ BN_ULONG c0, c1, *tp, n0 = *n0p;
+ volatile BN_ULONG *vp;
+ int i = 0, j;
+
+ vp = tp = alloca((num + 2) * sizeof(BN_ULONG));
+
+ for (i = 0; i <= num; i++)
+ tp[i] = 0;
+
+ for (i = 0; i < num; i++) {
+ c0 = bn_mul_add_words(tp, ap, num, bp[i]);
+ c1 = (tp[num] + c0) & BN_MASK2;
+ tp[num] = c1;
+ tp[num + 1] = (c1 < c0 ? 1 : 0);
+
+ c0 = bn_mul_add_words(tp, np, num, tp[0] * n0);
+ c1 = (tp[num] + c0) & BN_MASK2;
+ tp[num] = c1;
+ tp[num + 1] += (c1 < c0 ? 1 : 0);
+ for (j = 0; j <= num; j++)
+ tp[j] = tp[j + 1];
+ }
+
+ if (tp[num] != 0 || tp[num - 1] >= np[num - 1]) {
+ c0 = bn_sub_words(rp, tp, np, num);
+ if (tp[num] != 0 || c0 == 0) {
+ for (i = 0; i < num + 2; i++)
+ vp[i] = 0;
+ return 1;
+ }
+ }
+ for (i = 0; i < num; i++)
+ rp[i] = tp[i], vp[i] = 0;
+ vp[num] = 0;
+ vp[num + 1] = 0;
+ return 1;
+}
+# else
+int bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,
+ const BN_ULONG *np, const BN_ULONG *n0, int num)
+{
+ return 0;
+}
+# endif /* OPENSSL_BN_ASM_MONT */
+# endif
+
#endif /* !BN_MUL_COMBA */