diff --git a/CHANGES b/CHANGES index 131faa9ba6..53e4c93219 100644 --- a/CHANGES +++ b/CHANGES @@ -4,6 +4,10 @@ Changes between 0.9.4 and 0.9.5 [xx XXX 2000] + *) Bug fix for BN_div() when the first words of num and divsor are + equal (it gave wrong results if (rem=(n1-q*d0)&BN_MASK2) < d0). + [Ulf Möller] + *) Add support for various broken PKCS#8 formats, and command line options to produce them. [Steve Henson] diff --git a/crypto/bn/bn_div.c b/crypto/bn/bn_div.c index 3505221a96..31062b7db2 100644 --- a/crypto/bn/bn_div.c +++ b/crypto/bn/bn_div.c @@ -62,7 +62,7 @@ #include "bn_lcl.h" /* The old slow way */ -#if 1 +#if 0 int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, BN_CTX *ctx) { @@ -126,6 +126,32 @@ int BN_div(BIGNUM *dv, BIGNUM *rem, const BIGNUM *m, const BIGNUM *d, #else +#if !defined(NO_ASM) && !defined(PEDANTIC) && !defined(BN_DIV3W) +# if defined(__GNUC__) && __GNUC__>=2 +# if defined(__i386) + /* + * There were two reasons for implementing this template: + * - GNU C generates a call to a function (__udivdi3 to be exact) + * in reply to ((((BN_ULLONG)n0)< + */ +# define bn_div_words(n0,n1,d0) \ + ({ asm volatile ( \ + "divl %4" \ + : "=a"(q), "=d"(rem) \ + : "a"(n1), "d"(n0), "g"(d0) \ + : "cc"); \ + q; \ + }) +# define REMAINDER_IS_ALREADY_CALCULATED +# endif /* __ */ +# endif /* __GNUC__ */ +#endif /* NO_ASM */ + int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX *ctx) { @@ -214,103 +240,72 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, #ifdef BN_DIV3W q=bn_div_3_words(wnump,d1,d0); #else - -#if !defined(NO_ASM) && !defined(PEDANTIC) -# if defined(__GNUC__) && __GNUC__>=2 -# if defined(__i386) - /* - * There were two reasons for implementing this template: - * - GNU C generates a call to a function (__udivdi3 to be exact) - * in reply to ((((BN_ULLONG)n0)< - */ -# define bn_div_words(n0,n1,d0) \ - ({ asm volatile ( \ - "divl %4" \ - : "=a"(q), "=d"(rem) \ - : "a"(n1), "d"(n0), "g"(d0) \ - : "cc"); \ - q; \ - }) -# define REMAINDER_IS_ALREADY_CALCULATED -# endif /* __ */ -# endif /* __GNUC__ */ -#endif /* NO_ASM */ BN_ULONG n0,n1,rem=0; n0=wnump[0]; n1=wnump[-1]; if (n0 == d0) - { q=BN_MASK2; -#ifdef REMAINDER_IS_ALREADY_CALCULATED /* in this case it isn't */ - rem=(n1-q*d0)&BN_MASK2; -#endif - } - else /* n0 < d0 */ + else /* n0 < d0 */ + { +#ifdef BN_LLONG + BN_ULLONG t2; + #if defined(BN_LLONG) && defined(BN_DIV2W) && !defined(bn_div_words) q=(BN_ULONG)(((((BN_ULLONG)n0)<d,sdiv->d,div_n,q); wnum.d--; wnum.top++; tmp->d[div_n]=l0; @@ -341,7 +336,7 @@ int BN_div(BIGNUM *dv, BIGNUM *rm, const BIGNUM *num, const BIGNUM *divisor, BN_CTX_end(ctx); return(1); err: - BN_CX_end(ctx); + BN_CTX_end(ctx); return(0); }