X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fbn%2Fbn.h;h=5f16fbad00c326470304dddab99f8e8d2b4d6fca;hp=44ba175247b0bd2ea181ce0e22001de1e6aa7d47;hb=5734bebe05949bf1e7b94dcf225d297389347bb2;hpb=c465e7941ec785f2ce53638b351a21d6a49fe1a0 diff --git a/crypto/bn/bn.h b/crypto/bn/bn.h index 44ba175247..5f16fbad00 100644 --- a/crypto/bn/bn.h +++ b/crypto/bn/bn.h @@ -252,27 +252,6 @@ typedef struct bignum_st 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; @@ -611,7 +590,87 @@ 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. + */ + +/* #define BN_DEBUG_RAND */ + +#ifdef BN_DEBUG + +/* We only need assert() when debugging */ +#include + +#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) \ @@ -619,6 +678,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);