X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fbn%2Fbn_lib.c;h=b499292884ad6b51f9744a4ac1d27880be2f0d5d;hp=af8ec34a496328609c8bfa41e497399014a85585;hb=657a9195983badf9f0a45d32bd8199bab27f0e01;hpb=0dba0613ea50e36fb23e327dbbf835475d00beab diff --git a/crypto/bn/bn_lib.c b/crypto/bn/bn_lib.c index af8ec34a49..b499292884 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" @@ -90,28 +91,28 @@ void BN_set_params(int mult, int high, int low, int mont) { if (mult >= 0) { - if (mult > (sizeof(int)*8)-1) + if (mult > (int)(sizeof(int)*8)-1) mult=sizeof(int)*8-1; bn_limit_bits=mult; bn_limit_num=1<= 0) { - if (high > (sizeof(int)*8)-1) + if (high > (int)(sizeof(int)*8)-1) high=sizeof(int)*8-1; bn_limit_bits_high=high; bn_limit_num_high=1<= 0) { - if (low > (sizeof(int)*8)-1) + if (low > (int)(sizeof(int)*8)-1) low=sizeof(int)*8-1; bn_limit_bits_low=low; bn_limit_num_low=1<= 0) { - if (mont > (sizeof(int)*8)-1) + if (mont > (int)(sizeof(int)*8)-1) mont=sizeof(int)*8-1; bn_limit_bits_mont=mont; bn_limit_num_mont=1<d != NULL) { - memset(a->d,0,a->dmax*sizeof(a->d[0])); + OPENSSL_cleanse(a->d,a->dmax*sizeof(a->d[0])); if (!(BN_get_flags(a,BN_FLG_STATIC_DATA))) OPENSSL_free(a->d); } i=BN_get_flags(a,BN_FLG_MALLOCED); - memset(a,0,sizeof(BIGNUM)); + OPENSSL_cleanse(a,sizeof(BIGNUM)); if (i) OPENSSL_free(a); } @@ -285,6 +286,7 @@ void BN_free(BIGNUM *a) void BN_init(BIGNUM *a) { memset(a,0,sizeof(BIGNUM)); + bn_check_top(a); } BIGNUM *BN_new(void) @@ -301,6 +303,7 @@ BIGNUM *BN_new(void) ret->neg=0; ret->dmax=0; ret->d=NULL; + bn_check_top(ret); return(ret); } @@ -312,6 +315,12 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) 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)) { @@ -356,17 +365,6 @@ static BN_ULONG *bn_expand_internal(const BIGNUM *b, int words) } } - /* 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) - { - A[0]=0; A[1]=0; A[2]=0; A[3]=0; - A[4]=0; A[5]=0; A[6]=0; A[7]=0; - } - for (i=(words - b->top)&7; i>0; i--,A++) - A[0]=0; #else memset(A,0,sizeof(BN_ULONG)*(words+1)); memcpy(A,b->d,sizeof(b->d[0])*b->top); @@ -390,6 +388,12 @@ BIGNUM *bn_dup_expand(const BIGNUM *b, int words) { BIGNUM *r = NULL; + /* This function does not work if + * words <= b->dmax && top < words + * because BN_dup() does not preserve 'dmax'! + * (But bn_dup_expand() is not used anywhere yet.) + */ + if (words > b->dmax) { BN_ULONG *a = bn_expand_internal(b, words); @@ -418,16 +422,21 @@ BIGNUM *bn_dup_expand(const BIGNUM *b, int words) r = BN_dup(b); } + bn_check_top(r); return r; } /* This is an internal function that should not be used in applications. - * It ensures that 'b' has enough room for a 'words' word number number. + * It ensures that 'b' has enough room for a 'words' word number + * and initialises any unused part of b->d with leading zeros. * It is mostly used by the various BIGNUM routines. If there is an error, * NULL is returned. If not, 'b' is returned. */ BIGNUM *bn_expand2(BIGNUM *b, int words) { + BN_ULONG *A; + int i; + if (words > b->dmax) { BN_ULONG *a = bn_expand_internal(b, words); @@ -442,6 +451,21 @@ BIGNUM *bn_expand2(BIGNUM *b, int words) else b = NULL; } + + /* NB: bn_wexpand() calls this only if the BIGNUM really has to grow */ + if ((b != NULL) && (b->top < b->dmax)) + { + A = &(b->d[b->top]); + for (i=(b->dmax - b->top)>>3; i>0; i--,A+=8) + { + A[0]=0; A[1]=0; A[2]=0; A[3]=0; + A[4]=0; A[5]=0; A[6]=0; A[7]=0; + } + for (i=(b->dmax - b->top)&7; i>0; i--,A++) + A[0]=0; + assert(A == &(b->d[b->dmax])); + } + else if(b) bn_check_top(b); return b; } @@ -459,6 +483,7 @@ BIGNUM *BN_dup(const BIGNUM *a) /* now r == t || r == NULL */ if (r == NULL) BN_free(t); + bn_check_top(r); return r; } @@ -498,6 +523,53 @@ BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b) if ((a->top == 0) && (a->d != NULL)) a->d[0]=0; a->neg=b->neg; + bn_check_top(a); + return(a); + } + +BIGNUM *BN_ncopy(BIGNUM *a, const BIGNUM *b, size_t n) + { + int i, min; + BN_ULONG *A; + const BN_ULONG *B; + + bn_check_top(b); + + if (a == b) + return a; + + min = (b->top < (int)n)? b->top: (int)n; + + if (!min) + { + BN_zero(a); + return a; + } + + if (bn_wexpand(a, min) == NULL) + return NULL; + + A=a->d; + B=b->d; + for (i=min>>2; i>0; i--, A+=4, B+=4) + { + BN_ULONG a0,a1,a2,a3; + a0=B[0]; a1=B[1]; a2=B[2]; a3=B[3]; + A[0]=a0; A[1]=a1; A[2]=a2; A[3]=a3; + } + switch (min&3) + { + case 3: A[2]=B[2]; + case 2: A[1]=B[1]; + case 1: A[0]=B[0]; + case 0: ; + } + a->top = min; + + a->neg = b->neg; + bn_correct_top(a); + + bn_check_top(a); return(a); } @@ -507,6 +579,9 @@ void BN_swap(BIGNUM *a, BIGNUM *b) BN_ULONG *tmp_d; int tmp_top, tmp_dmax, tmp_neg; + bn_check_top(a); + bn_check_top(b); + flags_old_a = a->flags; flags_old_b = b->flags; @@ -527,11 +602,14 @@ void BN_swap(BIGNUM *a, BIGNUM *b) 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); + bn_check_top(a); + bn_check_top(b); } void BN_clear(BIGNUM *a) { + bn_check_top(a); if (a->d != NULL) memset(a->d,0,a->dmax*sizeof(a->d[0])); a->top=0; @@ -544,7 +622,7 @@ BN_ULONG BN_get_word(const BIGNUM *a) BN_ULONG ret=0; n=BN_num_bytes(a); - if (n > sizeof(BN_ULONG)) + if (n > (int)sizeof(BN_ULONG)) return(BN_MASK2); for (i=a->top-1; i>=0; i--) { @@ -562,7 +640,8 @@ BN_ULONG BN_get_word(const BIGNUM *a) int BN_set_word(BIGNUM *a, BN_ULONG w) { int i,n; - if (bn_expand(a,sizeof(BN_ULONG)*8) == NULL) return(0); + bn_check_top(a); + if (bn_expand(a,(int)sizeof(BN_ULONG)*8) == NULL) return(0); n=sizeof(BN_ULONG)/BN_BYTES; a->neg=0; @@ -583,6 +662,7 @@ int BN_set_word(BIGNUM *a, BN_ULONG w) a->d[i]=(BN_ULONG)w&BN_MASK2; if (a->d[i] != 0) a->top=i+1; } + bn_check_top(a); return(1); } @@ -594,6 +674,7 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) if (ret == NULL) ret=BN_new(); if (ret == NULL) return(NULL); + bn_check_top(ret); l=0; n=len; if (n == 0) @@ -619,7 +700,7 @@ BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret) } /* need to call this due to clear byte at top if avoiding * having the top bit set (-ve number) */ - bn_fix_top(ret); + bn_correct_top(ret); return(ret); } @@ -629,6 +710,7 @@ int BN_bn2bin(const BIGNUM *a, unsigned char *to) int n,i; BN_ULONG l; + bn_check_top(a); n=i=BN_num_bytes(a); while (i-- > 0) { @@ -705,6 +787,9 @@ int BN_set_bit(BIGNUM *a, int n) { int i,j,k; + if (n < 0) + return 0; + i=n/BN_BITS2; j=n%BN_BITS2; if (a->top <= i) @@ -716,6 +801,7 @@ int BN_set_bit(BIGNUM *a, int n) } a->d[i]|=(((BN_ULONG)1)<top <= i) return(0); a->d[i]&=(~(((BN_ULONG)1)<= a->top) return(0); @@ -757,7 +849,7 @@ int BN_mask_bits(BIGNUM *a, int n) a->top=w+1; a->d[w]&= ~(BN_MASK2<