X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fbn%2Fbn_lib.c;h=e37b85bfc549c63631c08041e1939e290ce27e1c;hp=130a9e2db401468e83ef2747031a4056defeb1f6;hb=35ed8cb8b6655606c2be31d44be942f6724ba405;hpb=cbd48ba626845170ee2b70774e881a4b50a7369d diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index 130a9e2db4..e37b85bfc5 100644 --- a/crypto/bn/bn_lib.c +++ b/crypto/bn/bn_lib.c @@ -62,6 +62,7 @@ #endif #include +#include #include #include "cryptlib.h" #include "bn_lcl.h" @@ -306,22 +307,28 @@ BIGNUM *BN_new(void) /* This is used both by bn_expand2() and bn_dup_expand() */ /* The caller MUST check that words > b->dmax before calling this */ -static BN_ULONG *internal_bn_expand(const BIGNUM *b, int words) +static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) { BN_ULONG *A,*a = NULL; const BN_ULONG *B; int i; + if (words > (INT_MAX/(4*BN_BITS2))) + { + BNerr(BN_F_BN_EXPAND_INTERNAL,BN_R_BIGNUM_TOO_LONG); + return NULL; + } + bn_check_top(b); if (BN_get_flags(b,BN_FLG_STATIC_DATA)) { - BNerr(BN_F_BN_EXPAND2,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); + BNerr(BN_F_BN_EXPAND_INTERNAL,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA); return(NULL); } a=A=(BN_ULONG *)OPENSSL_malloc(sizeof(BN_ULONG)*(words+1)); if (A == NULL) { - BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE); + BNerr(BN_F_BN_EXPAND_INTERNAL,ERR_R_MALLOC_FAILURE); return(NULL); } #if 1 @@ -329,70 +336,6 @@ static BN_ULONG *internal_bn_expand(const BIGNUM *b, int words) /* Check if the previous number needs to be copied */ if (B != NULL) { -#if 0 - /* This lot is an unrolled loop to copy b->top - * BN_ULONGs from B to A - */ -/* - * I have nothing against unrolling but it's usually done for - * several reasons, namely: - * - minimize percentage of decision making code, i.e. branches; - * - avoid cache trashing; - * - make it possible to schedule loads earlier; - * Now let's examine the code below. The cornerstone of C is - * "programmer is always right" and that's what we love it for:-) - * For this very reason C compilers have to be paranoid when it - * comes to data aliasing and assume the worst. Yeah, but what - * does it mean in real life? This means that loop body below will - * be compiled to sequence of loads immediately followed by stores - * as compiler assumes the worst, something in A==B+1 style. As a - * result CPU pipeline is going to starve for incoming data. Secondly - * if A and B happen to share same cache line such code is going to - * cause severe cache trashing. Both factors have severe impact on - * performance of modern CPUs and this is the reason why this - * particular piece of code is #ifdefed away and replaced by more - * "friendly" version found in #else section below. This comment - * also applies to BN_copy function. - * - * - */ - for (i=b->top&(~7); i>0; i-=8) - { - A[0]=B[0]; A[1]=B[1]; A[2]=B[2]; A[3]=B[3]; - A[4]=B[4]; A[5]=B[5]; A[6]=B[6]; A[7]=B[7]; - A+=8; - B+=8; - } - switch (b->top&7) - { - case 7: - A[6]=B[6]; - case 6: - A[5]=B[5]; - case 5: - A[4]=B[4]; - case 4: - A[3]=B[3]; - case 3: - A[2]=B[2]; - case 2: - A[1]=B[1]; - case 1: - A[0]=B[0]; - case 0: - /* I need the 'case 0' entry for utrix cc. - * If the optimizer is turned on, it does the - * switch table by doing - * a=top&7 - * a--; - * goto jump_table[a]; - * If top is 0, this makes us jump to 0xffffffc - * which is rather bad :-(. - * eric 23-Apr-1998 - */ - ; - } -#else for (i=b->top>>2; i>0; i--,A+=4,B+=4) { /* @@ -413,12 +356,15 @@ static BN_ULONG *internal_bn_expand(const BIGNUM *b, int words) case 3: A[2]=B[2]; case 2: A[1]=B[1]; case 1: A[0]=B[0]; - case 0: ; /* ultrix cc workaround, see above */ + case 0: /* workaround for ultrix cc: without 'case 0', the optimizer does + * the switch table by doing a=top&3; a--; goto jump_table[a]; + * which fails for top== 0 */ + ; } -#endif } /* Now need to zero any data between b->top and b->max */ + /* XXX Why? */ A= &(a[b->top]); for (i=(words - b->top)>>3; i>0; i--,A+=8) @@ -453,7 +399,7 @@ BIGNUM *bn_dup_expand(const BIGNUM *b, int words) if (words > b->dmax) { - BN_ULONG *a = internal_bn_expand(b, words); + BN_ULONG *a = bn_expand_internal(b, words); if (a) { @@ -472,7 +418,7 @@ BIGNUM *bn_dup_expand(const BIGNUM *b, int words) } } /* If a == NULL, there was an error in allocation in - internal_bn_expand(), and NULL should be returned */ + bn_expand_internal(), and NULL should be returned */ } else { @@ -491,11 +437,12 @@ BIGNUM *bn_expand2(BIGNUM *b, int words) { if (words > b->dmax) { - BN_ULONG *a = internal_bn_expand(b, words); + BN_ULONG *a = bn_expand_internal(b, words); if (a) { - OPENSSL_free(b->d); + if (b->d) + OPENSSL_free(b->d); b->d=a; b->dmax=words; } @@ -547,7 +494,7 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) case 3: A[2]=B[2]; case 2: A[1]=B[1]; case 1: A[0]=B[0]; - case 0: ; /* ultrix cc workaround, see comments in bn_expand2 */ + case 0: ; /* ultrix cc workaround, see comments in bn_expand_internal */ } #else memcpy(a->d,b->d,sizeof(b->d[0])*b->top); @@ -561,6 +508,35 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) return(a); } +void BN_swap(BIGNUM *a, BIGNUM *b) + { + int flags_old_a, flags_old_b; + BN_ULONG *tmp_d; + int tmp_top, tmp_dmax, tmp_neg; + + flags_old_a = a->flags; + flags_old_b = b->flags; + + tmp_d = a->d; + tmp_top = a->top; + tmp_dmax = a->dmax; + tmp_neg = a->neg; + + a->d = b->d; + a->top = b->top; + a->dmax = b->dmax; + a->neg = b->neg; + + b->d = tmp_d; + b->top = tmp_top; + b->dmax = tmp_dmax; + b->neg = tmp_neg; + + a->flags = (flags_old_a & BN_FLG_MALLOCED) | (flags_old_b & BN_FLG_STATIC_DATA); + b->flags = (flags_old_b & BN_FLG_MALLOCED) | (flags_old_a & BN_FLG_STATIC_DATA); + } + + void BN_clear(BIGNUM *a) { if (a->d != NULL) @@ -617,7 +593,6 @@ int BN_set_word(BIGNUM *a, BN_ULONG w) return(1); } -/* ignore negative */ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) { unsigned int i,m; @@ -638,6 +613,7 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) i=((n-1)/BN_BYTES)+1; m=((n-1)%(BN_BYTES)); ret->top=i; + ret->neg=0; while (n-- > 0) { l=(l<<8L)| *(s++); @@ -809,3 +785,34 @@ int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n) return(0); } +/* Here follows a specialised variants of bn_cmp_words(). It has the + property of performing the operation on arrays of different sizes. + The sizes of those arrays is expressed through cl, which is the + common length ( basicall, min(len(a),len(b)) ), and dl, which is the + delta between the two lengths, calculated as len(a)-len(b). + All lengths are the number of BN_ULONGs... */ + +int bn_cmp_part_words(const BN_ULONG *a, const BN_ULONG *b, + int cl, int dl) + { + int n,i; + n = cl-1; + + if (dl < 0) + { + for (i=dl; i<0; i++) + { + if (b[n-i] != 0) + return -1; /* a < b */ + } + } + if (dl > 0) + { + for (i=dl; i>0; i--) + { + if (a[n+i] != 0) + return 1; /* a > b */ + } + } + return bn_cmp_words(a,b,cl); + }