📄 bn_lib.c
字号:
r->top = b->top;
r->dmax = words;
r->neg = b->neg;
r->d = a;
}
else
{
/* r == NULL, BN_new failure */
OPENSSL_free(a);
}
}
/* If a == NULL, there was an error in allocation in
bn_expand_internal(), and NULL should be returned */
}
else
{
r = BN_dup(b);
}
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 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)
{
if (words > b->dmax)
{
BN_ULONG *a = bn_expand_internal(b, words);
if (a)
{
if (b->d)
OPENSSL_free(b->d);
b->d=a;
b->dmax=words;
}
else
b = NULL;
}
return b;
}
BIGNUM *BN_dup(const BIGNUM *a)
{
BIGNUM *r, *t;
if (a == NULL) return NULL;
bn_check_top(a);
t = BN_new();
if (t == NULL) return(NULL);
r = BN_copy(t, a);
/* now r == t || r == NULL */
if (r == NULL)
BN_free(t);
return r;
}
BIGNUM *BN_copy(BIGNUM *a, const BIGNUM *b)
{
int i;
BN_ULONG *A;
const BN_ULONG *B;
bn_check_top(b);
if (a == b) return(a);
if (bn_wexpand(a,b->top) == NULL) return(NULL);
#if 1
A=a->d;
B=b->d;
for (i=b->top>>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 (b->top&3)
{
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_expand_internal */
}
#else
memcpy(a->d,b->d,sizeof(b->d[0])*b->top);
#endif
/* memset(&(a->d[b->top]),0,sizeof(a->d[0])*(a->max-b->top));*/
a->top=b->top;
if ((a->top == 0) && (a->d != NULL))
a->d[0]=0;
a->neg=b->neg;
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)
memset(a->d,0,a->dmax*sizeof(a->d[0]));
a->top=0;
a->neg=0;
}
BN_ULONG BN_get_word(const BIGNUM *a)
{
int i,n;
BN_ULONG ret=0;
n=BN_num_bytes(a);
if (n > sizeof(BN_ULONG))
return(BN_MASK2);
for (i=a->top-1; i>=0; i--)
{
#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */
ret<<=BN_BITS4; /* stops the compiler complaining */
ret<<=BN_BITS4;
#else
ret=0;
#endif
ret|=a->d[i];
}
return(ret);
}
int BN_set_word(BIGNUM *a, BN_ULONG w)
{
int i,n;
if (bn_expand(a,sizeof(BN_ULONG)*8) == NULL) return(0);
n=sizeof(BN_ULONG)/BN_BYTES;
a->neg=0;
a->top=0;
a->d[0]=(BN_ULONG)w&BN_MASK2;
if (a->d[0] != 0) a->top=1;
for (i=1; i<n; i++)
{
/* the following is done instead of
* w>>=BN_BITS2 so compilers don't complain
* on builds where sizeof(long) == BN_TYPES */
#ifndef SIXTY_FOUR_BIT /* the data item > unsigned long */
w>>=BN_BITS4;
w>>=BN_BITS4;
#else
w=0;
#endif
a->d[i]=(BN_ULONG)w&BN_MASK2;
if (a->d[i] != 0) a->top=i+1;
}
return(1);
}
BIGNUM *BN_bin2bn(const unsigned char *s, int len, BIGNUM *ret)
{
unsigned int i,m;
unsigned int n;
BN_ULONG l;
if (ret == NULL) ret=BN_new();
if (ret == NULL) return(NULL);
l=0;
n=len;
if (n == 0)
{
ret->top=0;
return(ret);
}
if (bn_expand(ret,(int)(n+2)*8) == NULL)
return(NULL);
i=((n-1)/BN_BYTES)+1;
m=((n-1)%(BN_BYTES));
ret->top=i;
ret->neg=0;
while (n-- > 0)
{
l=(l<<8L)| *(s++);
if (m-- == 0)
{
ret->d[--i]=l;
l=0;
m=BN_BYTES-1;
}
}
/* need to call this due to clear byte at top if avoiding
* having the top bit set (-ve number) */
bn_fix_top(ret);
return(ret);
}
/* ignore negative */
int BN_bn2bin(const BIGNUM *a, unsigned char *to)
{
int n,i;
BN_ULONG l;
n=i=BN_num_bytes(a);
while (i-- > 0)
{
l=a->d[i/BN_BYTES];
*(to++)=(unsigned char)(l>>(8*(i%BN_BYTES)))&0xff;
}
return(n);
}
int BN_ucmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
BN_ULONG t1,t2,*ap,*bp;
bn_check_top(a);
bn_check_top(b);
i=a->top-b->top;
if (i != 0) return(i);
ap=a->d;
bp=b->d;
for (i=a->top-1; i>=0; i--)
{
t1= ap[i];
t2= bp[i];
if (t1 != t2)
return(t1 > t2?1:-1);
}
return(0);
}
int BN_cmp(const BIGNUM *a, const BIGNUM *b)
{
int i;
int gt,lt;
BN_ULONG t1,t2;
if ((a == NULL) || (b == NULL))
{
if (a != NULL)
return(-1);
else if (b != NULL)
return(1);
else
return(0);
}
bn_check_top(a);
bn_check_top(b);
if (a->neg != b->neg)
{
if (a->neg)
return(-1);
else return(1);
}
if (a->neg == 0)
{ gt=1; lt= -1; }
else { gt= -1; lt=1; }
if (a->top > b->top) return(gt);
if (a->top < b->top) return(lt);
for (i=a->top-1; i>=0; i--)
{
t1=a->d[i];
t2=b->d[i];
if (t1 > t2) return(gt);
if (t1 < t2) return(lt);
}
return(0);
}
int BN_set_bit(BIGNUM *a, int n)
{
int i,j,k;
i=n/BN_BITS2;
j=n%BN_BITS2;
if (a->top <= i)
{
if (bn_wexpand(a,i+1) == NULL) return(0);
for(k=a->top; k<i+1; k++)
a->d[k]=0;
a->top=i+1;
}
a->d[i]|=(((BN_ULONG)1)<<j);
return(1);
}
int BN_clear_bit(BIGNUM *a, int n)
{
int i,j;
i=n/BN_BITS2;
j=n%BN_BITS2;
if (a->top <= i) return(0);
a->d[i]&=(~(((BN_ULONG)1)<<j));
bn_fix_top(a);
return(1);
}
int BN_is_bit_set(const BIGNUM *a, int n)
{
int i,j;
if (n < 0) return(0);
i=n/BN_BITS2;
j=n%BN_BITS2;
if (a->top <= i) return(0);
return((a->d[i]&(((BN_ULONG)1)<<j))?1:0);
}
int BN_mask_bits(BIGNUM *a, int n)
{
int b,w;
w=n/BN_BITS2;
b=n%BN_BITS2;
if (w >= a->top) return(0);
if (b == 0)
a->top=w;
else
{
a->top=w+1;
a->d[w]&= ~(BN_MASK2<<b);
}
bn_fix_top(a);
return(1);
}
int bn_cmp_words(const BN_ULONG *a, const BN_ULONG *b, int n)
{
int i;
BN_ULONG aa,bb;
aa=a[n-1];
bb=b[n-1];
if (aa != bb) return((aa > bb)?1:-1);
for (i=n-2; i>=0; i--)
{
aa=a[i];
bb=b[i];
if (aa != bb) return((aa > bb)?1:-1);
}
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);
}
int BN_high_bit(BIGNUM *a)
{
int i;
BN_ULONG l;
i=BN_num_bytes(a);
if(!i) return(0);
i--;
l=a->d[i/BN_BYTES];
return((l>>(8*(i%BN_BYTES)))&0x80?1:0);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -