The efforts to eliminate the dual-representation of zero and to ensure
[openssl.git] / crypto / bn / bn.h
index 403add94b03852dea86545584f7a7f2d39151164..a01f193daaf212b8b16333280e2f465eb73032ec 100644 (file)
 extern "C" {
 #endif
 
+/* These preprocessor symbols control various aspects of the bignum headers and
+ * library code. They're not defined by any "normal" configuration, as they are
+ * intended for development and testing purposes. NB: defining all three can be
+ * useful for debugging application code as well as openssl itself.
+ *
+ * BN_DEBUG - turn on various debugging alterations to the bignum code
+ * BN_DEBUG_RAND - uses random poisoning of unused words to trip up
+ * mismanagement of bignum internals. You must also define BN_DEBUG.
+ * BN_STRICT - disables anything (not already caught by BN_DEBUG) that uses the
+ * old ambiguity over zero representation. At some point, this behaviour should
+ * become standard.
+ */
+/* #define BN_DEBUG */
+/* #define BN_DEBUG_RAND */
+/* #define BN_STRICT */
+
 #ifdef OPENSSL_SYS_VMS
 #undef BN_LLONG /* experimental, so far... */
 #endif
@@ -238,7 +254,9 @@ extern "C" {
 
 #define BN_FLG_MALLOCED                0x01
 #define BN_FLG_STATIC_DATA     0x02
+#ifndef OPENSSL_NO_DEPRECATED
 #define BN_FLG_FREE            0x8000  /* used for debuging */
+#endif
 #define BN_set_flags(b,n)      ((b)->flags|=(n))
 #define BN_get_flags(b,n)      ((b)->flags&(n))
 
@@ -261,6 +279,8 @@ typedef struct bn_blinding_st
        BIGNUM *A;
        BIGNUM *Ai;
        BIGNUM *mod; /* just a reference */
+       unsigned long thread_id; /* added in OpenSSL 0.9.6j and 0.9.7b;
+                                 * used only by crypto/rsa/rsa_eay.c, rsa_lib.c */
        } BN_BLINDING;
 
 /* Used for montgomery multiplication */
@@ -287,6 +307,35 @@ typedef struct bn_recp_ctx_st
        int flags;
        } BN_RECP_CTX;
 
+/* Used for slow "generation" functions. */
+typedef struct bn_gencb_st BN_GENCB;
+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;
+       };
+/* Wrapper function to make using BN_GENCB easier,  */
+int BN_GENCB_call(BN_GENCB *cb, int a, int b);
+/* Macro to populate a BN_GENCB structure with an "old"-style callback */
+#define BN_GENCB_set_old(gencb, callback, cb_arg) { \
+               BN_GENCB *tmp_gencb = (gencb); \
+               tmp_gencb->ver = 1; \
+               tmp_gencb->arg = (cb_arg); \
+               tmp_gencb->cb.cb_1 = (callback); }
+/* Macro to populate a BN_GENCB structure with a "new"-style callback */
+#define BN_GENCB_set(gencb, callback, cb_arg) { \
+               BN_GENCB *tmp_gencb = (gencb); \
+               tmp_gencb->ver = 2; \
+               tmp_gencb->arg = (cb_arg); \
+               tmp_gencb->cb.cb_2 = (callback); }
+
 #define BN_prime_checks 0 /* default: select number of iterations
                             based on the size of the number */
 
@@ -310,16 +359,30 @@ typedef struct bn_recp_ctx_st
 
 #define BN_num_bytes(a)        ((BN_num_bits(a)+7)/8)
 
-/* Note that BN_abs_is_word does not work reliably for w == 0 */
-#define BN_abs_is_word(a,w) (((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w)))
-#define BN_is_zero(a)       (((a)->top == 0) || BN_abs_is_word(a,0))
+/* Note that BN_abs_is_word didn't work reliably for w == 0 until 0.9.8 */
+#define BN_abs_is_word(a,w) ((((a)->top == 1) && ((a)->d[0] == (BN_ULONG)(w))) || \
+                               (((w) == 0) && ((a)->top == 0)))
+#ifdef BN_STRICT
+#define BN_is_zero(a)       ((a)->top == 0)
+#else
+#define BN_is_zero(a)       BN_abs_is_word(a,0)
+#endif
 #define BN_is_one(a)        (BN_abs_is_word((a),1) && !(a)->neg)
-#define BN_is_word(a,w)     ((w) ? BN_abs_is_word((a),(w)) && !(a)->neg : \
-                                   BN_is_zero((a)))
+#define BN_is_word(a,w)     (BN_abs_is_word((a),(w)) && (!(w) || !(a)->neg))
 #define BN_is_odd(a)       (((a)->top > 0) && ((a)->d[0] & 1))
 
 #define BN_one(a)      (BN_set_word((a),1))
+#define BN_zero_ex(a) \
+       do { \
+               BIGNUM *_tmp_bn = (a); \
+               _tmp_bn->top = 0; \
+               _tmp_bn->neg = 0; \
+       } while(0)
+#ifdef OPENSSL_NO_DEPRECATED
+#define BN_zero(a)     BN_zero_ex(a)
+#else
 #define BN_zero(a)     (BN_set_word((a),0))
+#endif
 /* BN_set_sign(BIGNUM *, int) sets the sign of a BIGNUM
  * (0 for a non-negative value, 1 for negative) */
 #define BN_set_sign(a,b) ((a)->neg = (b))
@@ -332,7 +395,9 @@ typedef struct bn_recp_ctx_st
 const BIGNUM *BN_value_one(void);
 char * BN_options(void);
 BN_CTX *BN_CTX_new(void);
+#ifndef OPENSSL_NO_DEPRECATED
 void   BN_CTX_init(BN_CTX *c);
+#endif
 void   BN_CTX_free(BN_CTX *c);
 void   BN_CTX_start(BN_CTX *ctx);
 BIGNUM *BN_CTX_get(BN_CTX *ctx);
@@ -431,6 +496,9 @@ BIGNUM *BN_mod_inverse(BIGNUM *ret,
        const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
 BIGNUM *BN_mod_sqrt(BIGNUM *ret,
        const BIGNUM *a, const BIGNUM *n,BN_CTX *ctx);
+
+/* Deprecated versions */
+#ifndef OPENSSL_NO_DEPRECATED
 BIGNUM *BN_generate_prime(BIGNUM *ret,int bits,int safe,
        const BIGNUM *add, const BIGNUM *rem,
        void (*callback)(int,int,void *),void *cb_arg);
@@ -440,6 +508,14 @@ int        BN_is_prime(const BIGNUM *p,int nchecks,
 int    BN_is_prime_fasttest(const BIGNUM *p,int nchecks,
        void (*callback)(int,int,void *),BN_CTX *ctx,void *cb_arg,
        int do_trial_division);
+#endif /* !defined(OPENSSL_NO_DEPRECATED) */
+
+/* Newer versions */
+int    BN_generate_prime_ex(BIGNUM *ret,int bits,int safe, const BIGNUM *add,
+               const BIGNUM *rem, BN_GENCB *cb);
+int    BN_is_prime_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx, BN_GENCB *cb);
+int    BN_is_prime_fasttest_ex(const BIGNUM *p,int nchecks, BN_CTX *ctx,
+               int do_trial_division, BN_GENCB *cb);
 
 BN_MONT_CTX *BN_MONT_CTX_new(void );
 void BN_MONT_CTX_init(BN_MONT_CTX *ctx);
@@ -546,7 +622,85 @@ const BIGNUM *BN_get0_nist_prime_521(void);
 BIGNUM *bn_expand2(BIGNUM *a, int words);
 BIGNUM *bn_dup_expand(const BIGNUM *a, int words);
 
-#define bn_fix_top(a) \
+/* 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); \
+               assert((_bnum2->top == 0) || \
+                               (_bnum2->d[_bnum2->top - 1] != 0)); \
+               bn_pollute(_bnum2); \
+       } while(0)
+
+#define bn_fix_top(a)          bn_check_top(a)
+
+#else /* !BN_DEBUG */
+
+#define bn_pollute(a)
+#define bn_check_top(a)
+#define bn_fix_top(a)          bn_correct_top(a)
+
+#endif
+
+#define bn_correct_top(a) \
         { \
         BN_ULONG *ftl; \
        if ((a)->top > 0) \
@@ -554,6 +708,7 @@ BIGNUM *bn_dup_expand(const BIGNUM *a, int words);
                for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--) \
                if (*(ftl--)) break; \
                } \
+       bn_pollute(a); \
        }
 
 BN_ULONG bn_mul_add_words(BN_ULONG *rp, const BN_ULONG *ap, int num, BN_ULONG w);