int flags;
} BIGNUM;
+/* Declaring static BIGNUMs as constant is tricky in C; the 'd' data can't be
+ * pre-declared const without having to cast away the const when declaring the
+ * BIGNUM. We use this alternative type for declaring const BIGNUMs. See
+ * bn_nist.c for examples. */
+typedef struct bignum_c_st
+ {
+ const BN_ULONG *d;
+ int top;
+ int dmax;
+ int neg;
+ int flags;
+ } BIGNUM_C;
+#ifdef BN_DEBUG
+/* Use a function to do this so that we can type-check the pointer we're
+ * casting */
+const BIGNUM *BIGNUM_CONST(const BIGNUM_C *bn);
+#else
+/* Use a macro instead */
+#define BIGNUM_CONST(bn) ((const BIGNUM *)bn)
+#endif
+
/* Used for temp variables (declaration hidden in bn_lcl.h) */
typedef struct bignum_ctx BN_CTX;
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 */
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 */
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);
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.
+ */
+#define bn_correct_top(a) \
{ \
BN_ULONG *ftl; \
if ((a)->top > 0) \
} \
}
+/* #define BN_DEBUG_RAND */
+
+#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_check_top(a) \
+ do { \
+ const BIGNUM *_tbignum = (a); \
+ assert((_tbignum->top == 0) || \
+ (_tbignum->d[_tbignum->top - 1] != 0)); \
+ if(_tbignum->top < _tbignum->dmax) { \
+ /* 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, &_tbignum->d, sizeof(BN_ULONG*)); \
+ RAND_pseudo_bytes((unsigned char *)(_not_const + _tbignum->top), \
+ (_tbignum->dmax - _tbignum->top) * sizeof(BN_ULONG)); \
+ } \
+ } while(0)
+#ifdef BN_DEBUG_TRIX
+#undef RAND_pseudo_bytes
+#endif
+#else /* !BN_DEBUG_RAND */
+#define bn_check_top(a) \
+ do { \
+ const BIGNUM *_tbignum = (a); \
+ assert((_tbignum->top == 0) || \
+ (_tbignum->d[_tbignum->top - 1] != 0)); \
+ } while(0)
+#endif
+
+#define bn_fix_top(a) bn_check_top(a)
+
+#else /* !BN_DEBUG */
+
+#define bn_check_top(a)
+#define bn_fix_top(a) bn_correct_top(a)
+
+#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);