Fix unused variable warning
[openssl.git] / crypto / bn / bn_lcl.h
index ccfe7bc40a2cbd77a8025b9a7182bdfb48779a47..260f67b348ee8a1a4928dfb8467810572c3a6627 100644 (file)
 #ifndef HEADER_BN_LCL_H
 #define HEADER_BN_LCL_H
 
-#include <openssl/bn.h>
+#include "internal/bn_int.h"
 
 #ifdef  __cplusplus
 extern "C" {
 #endif
 
+/* Bignum consistency macros
+ * There is one "API" macro, bn_fix_top(), for stripping leading zeroes from
+ * bignum data after direct manipulations on the data. There is also an
+ * "internal" macro, bn_check_top(), for verifying that there are no leading
+ * zeroes. Unfortunately, some auditing is required due to the fact that
+ * bn_fix_top() has become an overabused duct-tape because bignum data is
+ * occasionally passed around in an inconsistent state. So the following
+ * changes have been made to sort this out;
+ * - bn_fix_top()s implementation has been moved to bn_correct_top()
+ * - if BN_DEBUG isn't defined, bn_fix_top() maps to bn_correct_top(), and
+ *   bn_check_top() is as before.
+ * - if BN_DEBUG *is* defined;
+ *   - bn_check_top() tries to pollute unused words even if the bignum 'top' is
+ *     consistent. (ed: only if BN_DEBUG_RAND is defined)
+ *   - bn_fix_top() maps to bn_check_top() rather than "fixing" anything.
+ * The idea is to have debug builds flag up inconsistent bignums when they
+ * occur. If that occurs in a bn_fix_top(), we examine the code in question; if
+ * the use of bn_fix_top() was appropriate (ie. it follows directly after code
+ * that manipulates the bignum) it is converted to bn_correct_top(), and if it
+ * was not appropriate, we convert it permanently to bn_check_top() and track
+ * down the cause of the bug. Eventually, no internal code should be using the
+ * bn_fix_top() macro. External applications and libraries should try this with
+ * their own code too, both in terms of building against the openssl headers
+ * with BN_DEBUG defined *and* linking with a version of OpenSSL built with it
+ * defined. This not only improves external code, it provides more test
+ * coverage for openssl's own code.
+ */
+
+#ifdef BN_DEBUG
+
+/* We only need assert() when debugging */
+#include <assert.h>
+
+#ifdef BN_DEBUG_RAND
+/* To avoid "make update" cvs wars due to BN_DEBUG, use some tricks */
+#ifndef RAND_pseudo_bytes
+int RAND_pseudo_bytes(unsigned char *buf,int num);
+#define BN_DEBUG_TRIX
+#endif
+#define bn_pollute(a) \
+       do { \
+               const BIGNUM *_bnum1 = (a); \
+               if(_bnum1->top < _bnum1->dmax) { \
+                       unsigned char _tmp_char; \
+                       /* We cast away const without the compiler knowing, any \
+                        * *genuinely* constant variables that aren't mutable \
+                        * wouldn't be constructed with top!=dmax. */ \
+                       BN_ULONG *_not_const; \
+                       memcpy(&_not_const, &_bnum1->d, sizeof(BN_ULONG*)); \
+                       RAND_pseudo_bytes(&_tmp_char, 1); \
+                       memset((unsigned char *)(_not_const + _bnum1->top), _tmp_char, \
+                               (_bnum1->dmax - _bnum1->top) * sizeof(BN_ULONG)); \
+               } \
+       } while(0)
+#ifdef BN_DEBUG_TRIX
+#undef RAND_pseudo_bytes
+#endif
+#else
+#define bn_pollute(a)
+#endif
+#define bn_check_top(a) \
+       do { \
+               const BIGNUM *_bnum2 = (a); \
+               if (_bnum2 != NULL) { \
+                       assert((_bnum2->top == 0) || \
+                               (_bnum2->d[_bnum2->top - 1] != 0)); \
+                       bn_pollute(_bnum2); \
+               } \
+       } while(0)
+
+#define bn_fix_top(a)          bn_check_top(a)
+
+#define bn_check_size(bn, bits) bn_wcheck_size(bn, ((bits+BN_BITS2-1))/BN_BITS2)
+#define bn_wcheck_size(bn, words) \
+       do { \
+               const BIGNUM *_bnum2 = (bn); \
+               assert((words) <= (_bnum2)->dmax && (words) >= (_bnum2)->top); \
+               /* avoid unused variable warning with NDEBUG */ \
+               (void)(_bnum2); \
+       } while(0)
+
+#else /* !BN_DEBUG */
+
+#define bn_pollute(a)
+#define bn_check_top(a)
+#define bn_fix_top(a)          bn_correct_top(a)
+#define bn_check_size(bn, bits)
+#define bn_wcheck_size(bn, words)
+
+#endif
+
+
+BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+BN_ULONG bn_mul_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);
+void     bn_sqr_words(BN_ULONG *rp, const BN_ULONG *ap, int num);
+BN_ULONG bn_div_words(BN_ULONG h, BN_ULONG l, BN_ULONG d);
+BN_ULONG bn_add_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
+BN_ULONG bn_sub_words(BN_ULONG *rp, const BN_ULONG *ap, const BN_ULONG *bp,int num);
+
+
+struct bignum_st
+       {
+       BN_ULONG *d;    /* Pointer to an array of 'BN_BITS2' bit chunks. */
+       int top;        /* Index of last used d +1. */
+       /* The next are internal book keeping for bn_expand. */
+       int dmax;       /* Size of the d array. */
+       int neg;        /* one if the number is negative */
+       int flags;
+       };
+
+/* Used for montgomery multiplication */
+struct bn_mont_ctx_st
+       {
+       int ri;        /* number of bits in R */
+       BIGNUM RR;     /* used to convert to montgomery form */
+       BIGNUM N;      /* The modulus */
+       BIGNUM Ni;     /* R*(1/R mod N) - N*Ni = 1
+                       * (Ni is only stored for bignum algorithm) */
+       BN_ULONG n0[2];/* least significant word(s) of Ni;
+                         (type changed with 0.9.9, was "BN_ULONG n0;" before) */
+       int flags;
+       };
+
+/* Used for reciprocal division/mod functions
+ * It cannot be shared between threads
+ */
+struct bn_recp_ctx_st
+       {
+       BIGNUM N;       /* the divisor */
+       BIGNUM Nr;      /* the reciprocal */
+       int num_bits;
+       int shift;
+       int flags;
+       };
+
+/* Used for slow "generation" functions. */
+struct bn_gencb_st
+       {
+       unsigned int ver;       /* To handle binary (in)compatibility */
+       void *arg;              /* callback-specific data */
+       union
+               {
+               /* if(ver==1) - handles old style callbacks */
+               void (*cb_1)(int, int, void *);
+               /* if(ver==2) - new callback style */
+               int (*cb_2)(int, int, BN_GENCB *);
+               } cb;
+       };
+
 
 /*
  * BN_window_bits_for_exponent_size -- macro for sliding window mod_exp functions
@@ -163,6 +312,45 @@ extern "C" {
 
 
 
+/* BN_mod_exp_mont_conttime is based on the assumption that the
+ * L1 data cache line width of the target processor is at least
+ * the following value.
+ */
+#define MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH     ( 64 )
+#define MOD_EXP_CTIME_MIN_CACHE_LINE_MASK      (MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH - 1)
+
+/* Window sizes optimized for fixed window size modular exponentiation
+ * algorithm (BN_mod_exp_mont_consttime).
+ *
+ * To achieve the security goals of BN_mode_exp_mont_consttime, the
+ * maximum size of the window must not exceed
+ * log_2(MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH). 
+ *
+ * Window size thresholds are defined for cache line sizes of 32 and 64,
+ * cache line sizes where log_2(32)=5 and log_2(64)=6 respectively. A
+ * window size of 7 should only be used on processors that have a 128
+ * byte or greater cache line size.
+ */
+#if MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 64
+
+#  define BN_window_bits_for_ctime_exponent_size(b) \
+               ((b) > 937 ? 6 : \
+                (b) > 306 ? 5 : \
+                (b) >  89 ? 4 : \
+                (b) >  22 ? 3 : 1)
+#  define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE   (6)
+
+#elif MOD_EXP_CTIME_MIN_CACHE_LINE_WIDTH == 32
+
+#  define BN_window_bits_for_ctime_exponent_size(b) \
+               ((b) > 306 ? 5 : \
+                (b) >  89 ? 4 : \
+                (b) >  22 ? 3 : 1)
+#  define BN_MAX_WINDOW_BITS_FOR_CTIME_EXPONENT_SIZE   (5)
+
+#endif
+
+
 /* Pentium pro 16,16,16,32,64 */
 /* Alpha       16,16,16,16.64 */
 #define BN_MULL_SIZE_NORMAL                    (16) /* 32 */
@@ -171,7 +359,25 @@ extern "C" {
 #define BN_MUL_LOW_RECURSIVE_SIZE_NORMAL       (32) /* 32 */
 #define BN_MONT_CTX_SET_SIZE_WORD              (64) /* 32 */
 
-#if !defined(NO_ASM) && !defined(NO_INLINE_ASM) && !defined(PEDANTIC)
+/* 2011-02-22 SMS.
+ * In various places, a size_t variable or a type cast to size_t was
+ * used to perform integer-only operations on pointers.  This failed on
+ * VMS with 64-bit pointers (CC /POINTER_SIZE = 64) because size_t is
+ * still only 32 bits.  What's needed in these cases is an integer type
+ * with the same size as a pointer, which size_t is not certain to be.
+ * The only fix here is VMS-specific.
+ */
+#if defined(OPENSSL_SYS_VMS)
+# if __INITIAL_POINTER_SIZE == 64
+#  define PTR_SIZE_INT long long
+# else /* __INITIAL_POINTER_SIZE == 64 */
+#  define PTR_SIZE_INT int
+# endif /* __INITIAL_POINTER_SIZE == 64 [else] */
+#elif !defined(PTR_SIZE_INT) /* defined(OPENSSL_SYS_VMS) */
+# define PTR_SIZE_INT size_t
+#endif /* defined(OPENSSL_SYS_VMS) [else] */
+
+#if !defined(OPENSSL_NO_ASM) && !defined(OPENSSL_NO_INLINE_ASM) && !defined(PEDANTIC)
 /*
  * BN_UMULT_HIGH section.
  *
@@ -199,7 +405,7 @@ extern "C" {
 #  if defined(__DECC)
 #   include <c_asm.h>
 #   define BN_UMULT_HIGH(a,b)  (BN_ULONG)asm("umulh %a0,%a1,%v0",(a),(b))
-#  elif defined(__GNUC__)
+#  elif defined(__GNUC__) && __GNUC__>=2
 #   define BN_UMULT_HIGH(a,b)  ({      \
        register BN_ULONG ret;          \
        asm ("umulh     %1,%2,%0"       \
@@ -208,7 +414,7 @@ extern "C" {
        ret;                    })
 #  endif       /* compiler */
 # elif defined(_ARCH_PPC) && defined(__64BIT__) && defined(SIXTY_FOUR_BIT_LONG)
-#  if defined(__GNUC__)
+#  if defined(__GNUC__) && __GNUC__>=2
 #   define BN_UMULT_HIGH(a,b)  ({      \
        register BN_ULONG ret;          \
        asm ("mulhdu    %0,%1,%2"       \
@@ -216,8 +422,62 @@ extern "C" {
             : "r"(a), "r"(b));         \
        ret;                    })
 #  endif       /* compiler */
+# elif (defined(__x86_64) || defined(__x86_64__)) && \
+       (defined(SIXTY_FOUR_BIT_LONG) || defined(SIXTY_FOUR_BIT))
+#  if defined(__GNUC__) && __GNUC__>=2
+#   define BN_UMULT_HIGH(a,b)  ({      \
+       register BN_ULONG ret,discard;  \
+       asm ("mulq      %3"             \
+            : "=a"(discard),"=d"(ret)  \
+            : "a"(a), "g"(b)           \
+            : "cc");                   \
+       ret;                    })
+#   define BN_UMULT_LOHI(low,high,a,b) \
+       asm ("mulq      %3"             \
+               : "=a"(low),"=d"(high)  \
+               : "a"(a),"g"(b)         \
+               : "cc");
+#  endif
+# elif (defined(_M_AMD64) || defined(_M_X64)) && defined(SIXTY_FOUR_BIT)
+#  if defined(_MSC_VER) && _MSC_VER>=1400
+    unsigned __int64 __umulh   (unsigned __int64 a,unsigned __int64 b);
+    unsigned __int64 _umul128  (unsigned __int64 a,unsigned __int64 b,
+                                unsigned __int64 *h);
+#   pragma intrinsic(__umulh,_umul128)
+#   define BN_UMULT_HIGH(a,b)          __umulh((a),(b))
+#   define BN_UMULT_LOHI(low,high,a,b) ((low)=_umul128((a),(b),&(high)))
+#  endif
+# elif defined(__mips) && (defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG))
+#  if defined(__GNUC__) && __GNUC__>=2
+#   if __GNUC__>=4 && __GNUC_MINOR__>=4 /* "h" constraint is no more since 4.4 */
+#     define BN_UMULT_HIGH(a,b)                 (((__uint128_t)(a)*(b))>>64)
+#     define BN_UMULT_LOHI(low,high,a,b) ({    \
+       __uint128_t ret=(__uint128_t)(a)*(b);   \
+       (high)=ret>>64; (low)=ret;       })
+#   else
+#     define BN_UMULT_HIGH(a,b)        ({      \
+       register BN_ULONG ret;          \
+       asm ("dmultu    %1,%2"          \
+            : "=h"(ret)                \
+            : "r"(a), "r"(b) : "l");   \
+       ret;                    })
+#     define BN_UMULT_LOHI(low,high,a,b)\
+       asm ("dmultu    %2,%3"          \
+            : "=l"(low),"=h"(high)     \
+            : "r"(a), "r"(b));
+#    endif
+#  endif
+# elif defined(__aarch64__) && defined(SIXTY_FOUR_BIT_LONG)
+#  if defined(__GNUC__) && __GNUC__>=2
+#   define BN_UMULT_HIGH(a,b)  ({      \
+       register BN_ULONG ret;          \
+       asm ("umulh     %0,%1,%2"       \
+            : "=r"(ret)                \
+            : "r"(a), "r"(b));         \
+       ret;                    })
+#  endif
 # endif                /* cpu */
-#endif         /* NO_ASM */
+#endif         /* OPENSSL_NO_ASM */
 
 /*************************************************************
  * Using the long long type
@@ -225,44 +485,17 @@ extern "C" {
 #define Lw(t)    (((BN_ULONG)(t))&BN_MASK2)
 #define Hw(t)    (((BN_ULONG)((t)>>BN_BITS2))&BN_MASK2)
 
-/* This is used for internal error checking and is not normally used */
-#ifdef BN_DEBUG
-# include <assert.h>
-# define bn_check_top(a) assert ((a)->top >= 0 && (a)->top <= (a)->dmax);
-#else
-# define bn_check_top(a)
-#endif
-
-/* This macro is to add extra stuff for development checking */
-#ifdef BN_DEBUG
-#define        bn_set_max(r) ((r)->max=(r)->top,BN_set_flags((r),BN_FLG_STATIC_DATA))
-#else
-#define        bn_set_max(r)
-#endif
-
-/* These macros are used to 'take' a section of a bignum for read only use */
-#define bn_set_low(r,a,n) \
-       { \
-       (r)->top=((a)->top > (n))?(n):(a)->top; \
-       (r)->d=(a)->d; \
-       (r)->neg=(a)->neg; \
-       (r)->flags|=BN_FLG_STATIC_DATA; \
-       bn_set_max(r); \
-       }
-
-#define bn_set_high(r,a,n) \
+#ifdef BN_DEBUG_RAND
+#define bn_clear_top2max(a) \
        { \
-       if ((a)->top > (n)) \
-               { \
-               (r)->top=(a)->top-n; \
-               (r)->d= &((a)->d[n]); \
-               } \
-       else \
-               (r)->top=0; \
-       (r)->neg=(a)->neg; \
-       (r)->flags|=BN_FLG_STATIC_DATA; \
-       bn_set_max(r); \
+       int      ind = (a)->dmax - (a)->top; \
+       BN_ULONG *ftl = &(a)->d[(a)->top-1]; \
+       for (; ind != 0; ind--) \
+               *(++ftl) = 0x0; \
        }
+#else
+#define bn_clear_top2max(a)
+#endif
 
 #ifdef BN_LLONG
 #define mul_add(r,a,w,c) { \
@@ -286,6 +519,33 @@ extern "C" {
        (r1)=Hw(t); \
        }
 
+#elif defined(BN_UMULT_LOHI)
+#define mul_add(r,a,w,c) {             \
+       BN_ULONG high,low,ret,tmp=(a);  \
+       ret =  (r);                     \
+       BN_UMULT_LOHI(low,high,w,tmp);  \
+       ret += (c);                     \
+       (c) =  (ret<(c))?1:0;           \
+       (c) += high;                    \
+       ret += low;                     \
+       (c) += (ret<low)?1:0;           \
+       (r) =  ret;                     \
+       }
+
+#define mul(r,a,w,c)   {               \
+       BN_ULONG high,low,ret,ta=(a);   \
+       BN_UMULT_LOHI(low,high,w,ta);   \
+       ret =  low + (c);               \
+       (c) =  high;                    \
+       (c) += (ret<low)?1:0;           \
+       (r) =  ret;                     \
+       }
+
+#define sqr(r0,r1,a)   {               \
+       BN_ULONG tmp=(a);               \
+       BN_UMULT_LOHI(r0,r1,tmp,tmp);   \
+       }
+
 #elif defined(BN_UMULT_HIGH)
 #define mul_add(r,a,w,c) {             \
        BN_ULONG high,low,ret,tmp=(a);  \
@@ -323,7 +583,7 @@ extern "C" {
 
 #define LBITS(a)       ((a)&BN_MASK2l)
 #define HBITS(a)       (((a)>>BN_BITS4)&BN_MASK2l)
-#define        L2HBITS(a)      ((BN_ULONG)((a)&BN_MASK2l)<<BN_BITS4)
+#define        L2HBITS(a)      (((a)<<BN_BITS4)&BN_MASK2)
 
 #define LLBITS(a)      ((a)&BN_MASKl)
 #define LHBITS(a)      (((a)>>BN_BITS2)&BN_MASKl)
@@ -339,7 +599,7 @@ extern "C" {
        lt=(bl)*(lt); \
        m1=(bl)*(ht); \
        ht =(bh)*(ht); \
-       m=(m+m1)&BN_MASK2; if (m < m1) ht+=L2HBITS(1L); \
+       m=(m+m1)&BN_MASK2; if (m < m1) ht+=L2HBITS((BN_ULONG)1); \
        ht+=HBITS(m); \
        m1=L2HBITS(m); \
        lt=(lt+m1)&BN_MASK2; if (lt < m1) ht++; \
@@ -395,6 +655,10 @@ extern "C" {
        }
 #endif /* !BN_LLONG */
 
+void BN_init(BIGNUM *a);
+void BN_RECP_CTX_init(BN_RECP_CTX *recp);
+void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
+
 void bn_mul_normal(BN_ULONG *r,BN_ULONG *a,int na,BN_ULONG *b,int nb);
 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);
@@ -402,15 +666,31 @@ void bn_sqr_normal(BN_ULONG *r, const BN_ULONG *a, int n, BN_ULONG *tmp);
 void bn_sqr_comba8(BN_ULONG *r,const BN_ULONG *a);
 void bn_sqr_comba4(BN_ULONG *r,const BN_ULONG *a);
 int bn_cmp_words(const BN_ULONG *a,const BN_ULONG *b,int n);
-void bn_mul_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,BN_ULONG *t);
+int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b,
+       int cl, int dl);
+void bn_mul_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,
+       int dna,int dnb,BN_ULONG *t);
 void bn_mul_part_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,
-       int tn, int n,BN_ULONG *t);
+       int n,int tna,int tnb,BN_ULONG *t);
 void bn_sqr_recursive(BN_ULONG *r,const BN_ULONG *a, int n2, BN_ULONG *t);
 void bn_mul_low_normal(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b, int n);
 void bn_mul_low_recursive(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,int n2,
        BN_ULONG *t);
 void bn_mul_high(BN_ULONG *r,BN_ULONG *a,BN_ULONG *b,BN_ULONG *l,int n2,
        BN_ULONG *t);
+BN_ULONG bn_add_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
+       int cl, int dl);
+BN_ULONG bn_sub_part_words(BN_ULONG *r, const BN_ULONG *a, const BN_ULONG *b,
+       int cl, int dl);
+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);
+
+BIGNUM *int_bn_mod_inverse(BIGNUM *in,
+       const BIGNUM *a, const BIGNUM *n, BN_CTX *ctx, int *noinv);
+
+int bn_probable_prime_dh(BIGNUM *rnd, int bits,
+       const BIGNUM *add, const BIGNUM *rem, BN_CTX *ctx);
+int bn_probable_prime_dh_retry(BIGNUM *rnd, int bits, BN_CTX *ctx);
+int bn_probable_prime_dh_coprime(BIGNUM *rnd, int bits, BN_CTX *ctx);
 
 #ifdef  __cplusplus
 }