Update source files to handle new FIPS_lock() location. Add FIPS_lock()
[openssl.git] / crypto / bn / bn_mont.c
index 594d95940fdf86d99eaae4c7d4bc51712694e842..ba659cfd1d51719bcb7d53c0dbdbb182828f9c0e 100644 (file)
  * sections 3.8 and 4.2 in http://security.ece.orst.edu/koc/papers/r01rsasw.pdf
  */
 
+#define OPENSSL_FIPSAPI
+
 #include <stdio.h>
 #include "cryptlib.h"
 #include "bn_lcl.h"
 
+#ifdef OPENSSL_FIPS
+#include <openssl/fips.h>
+#endif
+
 #define MONT_WORD /* use the faster word-based algorithm */
 
 #ifdef MONT_WORD
@@ -243,7 +249,7 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
 
        /* mont->ri will be a multiple of the word size and below code
         * is kind of BN_rshift(ret,r,mont->ri) equivalent */
-       if (r->top < ri)
+       if (r->top <= ri)
                {
                ret->top=0;
                return(1);
@@ -259,29 +265,29 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
 
        rp=ret->d;
        ap=&(r->d[ri]);
-       nrp=ap;
 
-       /* This 'if' denotes violation of 2*M<r^(n-1) boundary condition
-        * formulated by C.D.Walter in "Montgomery exponentiation needs
-        * no final subtractions." Incurred branch can disclose only
-        * information about modulus length, which is not really secret. */
-       if ((mont->N.d[ri-1]>>(BN_BITS2-2))!=0)
-               {
-               size_t m1,m2;
-
-               v=bn_sub_words(rp,ap,mont->N.d,ri);
-               /* if (al==ri && !v) || al>ri)  nrp=rp; */
-               /* in other words if subtraction result is real, then
-                * trick unconditional memcpy below to make "refresh"
-                * instead of real copy. */
-               m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);   /* al<ri */
-               m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);   /* al>ri */
-               m1=~(m1|m2);            /* (al==ri) */
-               m1&=~(0-(size_t)v);     /* (al==ri && !v) */
-               m1|=m2;                 /* (al==ri && !v) || al>ri */
-               nrp=(BN_ULONG *)(((size_t)rp&m1)|((size_t)ap&~m1));
-               }
+       {
+       size_t m1,m2;
+
+       v=bn_sub_words(rp,ap,np,ri);
+       /* this ----------------^^ works even in al<ri case
+        * thanks to zealous zeroing of top of the vector in the
+        * beginning. */
+
+       /* if (al==ri && !v) || al>ri) nrp=rp; else nrp=ap; */
+       /* in other words if subtraction result is real, then
+        * trick unconditional memcpy below to perform in-place
+        * "refresh" instead of actual copy. */
+       m1=0-(size_t)(((al-ri)>>(sizeof(al)*8-1))&1);   /* al<ri */
+       m2=0-(size_t)(((ri-al)>>(sizeof(al)*8-1))&1);   /* al>ri */
+       m1|=m2;                 /* (al!=ri) */
+       m1|=(0-(size_t)v);      /* (al!=ri || v) */
+       m1&=~m2;                /* (al!=ri || v) && !al>ri */
+       nrp=(BN_ULONG *)(((size_t)rp&~m1)|((size_t)ap&m1));
+       }
 
+       /* 'i<ri' is chosen to eliminate dependency on input data, even
+        * though it results in redundant copy in al<ri case. */
        for (i=0,ri-=4; i<ri; i+=4)
                {
                BN_ULONG t1,t2,t3,t4;
@@ -297,6 +303,8 @@ static int BN_from_montgomery_word(BIGNUM *ret, BIGNUM *r, BN_MONT_CTX *mont)
                }
        for (ri+=4; i<ri; i++)
                rp[i]=nrp[i], ap[i]=0;
+       bn_correct_top(r);
+       bn_correct_top(ret);
 #else
        if (bn_wexpand(ret,al) == NULL) return(0);
        ret->top=al;
@@ -392,6 +400,7 @@ void BN_MONT_CTX_init(BN_MONT_CTX *ctx)
        BN_init(&(ctx->RR));
        BN_init(&(ctx->N));
        BN_init(&(ctx->Ni));
+       ctx->n0[0] = ctx->n0[1] = 0;
        ctx->flags=0;
        }
 
@@ -423,6 +432,7 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
                BIGNUM tmod;
                BN_ULONG buf[2];
 
+               BN_init(&tmod);
                tmod.d=buf;
                tmod.dmax=2;
                tmod.neg=0;
@@ -430,6 +440,11 @@ int BN_MONT_CTX_set(BN_MONT_CTX *mont, const BIGNUM *mod, BN_CTX *ctx)
                mont->ri=(BN_num_bits(mod)+(BN_BITS2-1))/BN_BITS2*BN_BITS2;
 
 #if defined(OPENSSL_BN_ASM_MONT) && (BN_BITS2<=32)
+               /* Only certain BN_BITS2<=32 platforms actually make use of
+                * n0[1], and we could use the #else case (with a shorter R
+                * value) for the others.  However, currently only the assembler
+                * files do know which is which. */
+
                BN_zero(R);
                if (!(BN_set_bit(R,2*BN_BITS2))) goto err;