Add additional DigestInfo checks.
[openssl.git] / crypto / bn / bn_asm.c
index 52af96d36b4ec98a36ee42b9ef80c16a6ea72d3a..c43c91cc09f485fa615eddc61ddb81d20e792bf4 100644 (file)
@@ -75,6 +75,7 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
        assert(num >= 0);
        if (num <= 0) return(c1);
 
+#ifndef OPENSSL_SMALL_FOOTPRINT
        while (num&~3)
                {
                mul_add(rp[0],ap[0],w,c1);
@@ -83,11 +84,11 @@ BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
                mul_add(rp[3],ap[3],w,c1);
                ap+=4; 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;
+               mul_add(rp[0],ap[0],w,c1);
+               ap++; rp++; num--;
                }
        
        return(c1);
@@ -100,6 +101,7 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
        assert(num >= 0);
        if (num <= 0) return(c1);
 
+#ifndef OPENSSL_SMALL_FOOTPRINT
        while (num&~3)
                {
                mul(rp[0],ap[0],w,c1);
@@ -108,11 +110,11 @@ BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w)
                mul(rp[3],ap[3],w,c1);
                ap+=4; 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);
+               mul(rp[0],ap[0],w,c1);
+               ap++; rp++; num--;
                }
        return(c1);
        } 
@@ -121,6 +123,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]);
@@ -129,11 +133,11 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
                sqr(r[6],r[7],a[3]);
                a+=4; 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]);
+               sqr(r[0],r[1],a[0]);
+               a++; r+=2; n--;
                }
        }
 
@@ -150,18 +154,20 @@ BN_ULONG bn_mul_add_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_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;
+               ap+=4; rp+=4; num-=4;
+               }
+#endif
+       while (num)
+               {
+               mul_add(rp[0],ap[0],bl,bh,c);
+               ap++; rp++; num--;
                }
        return(c);
        } 
@@ -177,18 +183,20 @@ 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;
+               ap+=4; rp+=4; num-=4;
+               }
+#endif
+       while (num)
+               {
+               mul(rp[0],ap[0],bl,bh,carry);
+               ap++; rp++; num--;
                }
        return(carry);
        } 
@@ -197,22 +205,21 @@ void bn_sqr_words(BN_ULONG *r, const BN_ULONG *a, int n)
         {
        assert(n >= 0);
        if (n <= 0) return;
-       for (;;)
+
+#ifndef OPENSSL_SMALL_FOOTPRINT
+       while (n&~3)
                {
                sqr64(r[0],r[1],a[0]);
-               if (--n == 0) break;
-
                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;
+               a+=4; r+=8; n-=4;
+               }
+#endif
+       while (n)
+               {
+               sqr64(r[0],r[1],a[0]);
+               a++; r+=2; n--;
                }
        }
 
@@ -303,31 +310,30 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
        assert(n >= 0);
        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;
+               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);
        }
@@ -340,7 +346,8 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
        if (n <= 0) return((BN_ULONG)0);
 
        c=0;
-       for (;;)
+#ifndef OPENSSL_SMALL_FOOTPRINT
+       while (n&~3)
                {
                t=a[0];
                t=(t+c)&BN_MASK2;
@@ -348,35 +355,36 @@ BN_ULONG bn_add_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
                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;
+               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);
        }
@@ -390,36 +398,35 @@ BN_ULONG bn_sub_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b, int n)
        assert(n >= 0);
        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;
+               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
@@ -821,33 +828,67 @@ void bn_sqr_comba4(BN_ULONG *r, const BN_ULONG *a)
        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 does give 40%
- * faster rsa1024 private key operations and 10% faster rsa4096 ones,
- * while on AMD64 it improves rsa1024 sign only by 10%, but *worsens*
- * rsa4096 sign by 15%. Once again, it's a reference implementation,
- * one to be used as start-point for platform-specific assembler.
+ * 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.
  */
-void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,BN_ULONG n0, int num)
+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;
+       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));
 
-       tp[num]   = bn_mul_words(tp,ap,num,bp[0]);
+       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 = bn_mul_add_words(tp,ap,num,bp[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);
@@ -883,19 +924,24 @@ void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_
                if (tp[num]!=0 || c0==0)
                        {
                        for(i=0;i<num+2;i++)    vp[i] = 0;
-                       return;
+                       return 1;
                        }
                }
        for(i=0;i<num;i++)      rp[i] = tp[i],  vp[i] = 0;
        vp[num]   = 0;
        vp[num+1] = 0;
+       return 1;
        }
-
-void bn_sqr_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *np,BN_ULONG n0, int num)
-       {
-       bn_mul_mont(rp,ap,ap,np,n0,num);
-       }
+#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 */
 
@@ -934,10 +980,12 @@ 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
-void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_ULONG *np,BN_ULONG n0, int num)
+#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;
+       BN_ULONG c0,c1,*tp,n0=*n0p;
        volatile BN_ULONG *vp;
        int i=0,j;
 
@@ -948,12 +996,12 @@ void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_
        for(i=0;i<num;i++)
                {
                c0         = bn_mul_add_words(tp,ap,num,bp[i]);
-               c1         = tp[num] + c0;
+               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;
+               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];
@@ -965,18 +1013,18 @@ void bn_mul_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp, const BN_
                if (tp[num]!=0 || c0==0)
                        {
                        for(i=0;i<num+2;i++)    vp[i] = 0;
-                       return;
+                       return 1;
                        }
                }
        for(i=0;i<num;i++)      rp[i] = tp[i],  vp[i] = 0;
        vp[num]   = 0;
        vp[num+1] = 0;
+       return 1;
        }
-
-void bn_sqr_mont(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *np,BN_ULONG n0, int num)
-       {
-       bn_mul_mont(rp,ap,ap,np,n0,num);
-       }
+#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 */