TwlIPL/build/tools/acsign/bn_lib.c
yosiokat 60f18e5554 新規追加。(まだビルドできない。)
git-svn-id: file:///Users/lillianskinner/Downloads/platinum/twl/TwlIPL/trunk@1 b08762b0-b915-fc4b-9d8c-17b2551a87ff
2007-09-06 05:28:51 +00:00

1080 lines
23 KiB
C

/* $Id$ */
/*
* Copyright (C) 1998-2002 RSA Security Inc. All rights reserved.
*
* This work contains proprietary information of RSA Security.
* Distribution is limited to authorized licensees of RSA
* Security. Any unauthorized reproduction, distribution or
* modification of this work is strictly prohibited.
*
*/
/**
* @file bn_lib.c
* @brief BN library functions
* @todo add dox for undocumented functions
*/
#include "bn_lcl.h"
//#include "err.h"
#include "r_stdiag.h"
#if !(defined(NO_SPLIT) && defined(SPLIT_FILE))
#ifdef NO_SPLIT
#define SPLIT_BN_VALUE_ONE
#define SPLIT_BN_NUM_BITS_WORD
#define SPLIT_BN_NUM_BITS
#define SPLIT_BN_CLEAR_FREE
#define SPLIT_BN_FREE
#define SPLIT_BN_INIT
#define SPLIT_BN_NEW
#define SPLIT_BN_CTX_NEW
#define SPLIT_CTX_INIT
#define SPLIT_BN_CTX_FREE
#define SPLIT_BN_EXPAND2
#define SPLIT_BN_DUP
#define SPLIT_BN_COPY
#define SPLIT_BN_CLEAR
#define SPLIT_BN_GET_WORD
#define SPLIT_BN_SET_WORD
#define SPLIT_BN_BIN2BN
#define SPLIT_BN_BN2BIN
#define SPLIT_BN_UCMP
#define SPLIT_BN_CMP
#define SPLIT_BN_SET_BIT
#define SPLIT_BN_CLEAR_BIT
#define SPLIT_BN_IS_BIT_SET
#define SPLIT_BN_MASK_BITS
#define SPLIT_BN_CMP_WORDS
#endif /* NO_SPLIT */
#ifdef SPLIT_BN_VALUE_ONE
const char *BN_version="Big Number part of RCOM 2.3.0 11-Jun-2002";
BIGNUM *BN_value_one()
{
const static BN_ULONG data_one=1L;
const static BIGNUM const_one={(BN_ULONG *)&data_one,1,1,0};
return((BIGNUM *)&const_one);
}
#endif
/**
* Returns the maximum number of bits required to represent the
* number <tt>l</tt>
* @param l [In] a word (size of word depends on machine)
* @returns number of bits in parameter <tt>l</tt>
*/
#ifdef SPLIT_BN_NUM_BITS_WORD
int BN_num_bits_word(l)
BN_ILONG l;
{
int i;
/*
* This table represents the number of bits required to
* represent a "number", where "number" is indexed from
* 0 into the table. So:
* number 0 = # bits req'd to represent 0 = bits[0] = 0
* number 1 = # bits req'd to represent 1 = bits[1] = 1
* number 2 = # bits req'd to represent 2 = bits[2] = 2
* number 3 = # bits req'd to represent 3 = bits[3] = 2
* number 4 = # bits req'd to represent 4 = bits[4] = 3
* etc.
*
* The small code size table exists to save some space,
* but requires (at most) an extra shift, an extra AND,
* and an extra add.
*/
#ifdef SMALL_CODE_SIZE
const static char bits[16]={
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4
};
#else
const static char bits[256]={
0,1,2,2,3,3,3,3,4,4,4,4,4,4,4,4,
5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,8,
};
#endif
#if defined(SIXTY_FOUR_BIT_LONG)
if (l & 0xffffffff00000000L)
{
if (l & 0xffff000000000000L)
{
if (l & 0xff00000000000000L)
i=56;
else i=48;
}
else
{
if (l & 0x0000ff0000000000L)
i=40;
else i=32;
}
}
else
#else
#ifdef SIXTY_FOUR_BIT
if (l & 0xffffffff00000000LL)
{
if (l & 0xffff000000000000LL)
{
if (l & 0xff00000000000000LL)
i=56;
else i=48;
}
else
{
if (l & 0x0000ff0000000000LL)
i=40;
else i=32;
}
}
else
#endif
#endif
{
#if defined(THIRTY_BIT) || defined(THIRTY_ONE_BIT) || defined(THIRTY_TWO_BIT) || defined(SIXTY_FOUR_BIT) || defined(SIXTY_FOUR_BIT_LONG)
if (l & 0xffff0000L)
{
if (l & 0xff000000L)
i=24;
else i=16;
}
else
#endif
{
if (l & 0xff00L)
i=8;
else
i=0;
}
}
#ifndef SMALL_CODE_SIZE
return(i+bits[l>>i]);
#else
l>>=i;
if (l & 0xf0)
return(bits[l>>4]+i+4);
else
return(bits[l]+i);
#endif
}
#endif
#ifdef SPLIT_BN_NUM_BITS
int BN_num_bits(a)
BIGNUM *a;
{
BN_ULONG l;
int i;
bn_check_top(a);
if (a->top == 0) return(0);
l=a->d[a->top-1];
i=(a->top-1)*BN_BITS2;
#ifdef BN_DEBUG
if (l == 0)
{
#if !defined(NO_FP_API) && !defined(WIN16)
fprintf(stderr,"BAD TOP VALUE\n");
#endif
abort(); /* BN_DEBUG */
/* TODO: need to understand what sort of error can
* be reported for this error
*/
return(0);
}
#endif
return(i+BN_num_bits_word(l));
}
#endif
/**
* Clears and free a BIGNUM
*
* @param a [In] BIGNUM to clear then free
*/
#ifdef SPLIT_BN_CLEAR_FREE
void BN_clear_free(BIGNUM *a)
{
if (a == NULL)
{
return;
}
BN_clear(a);
BN_free(a);
}
#endif
#ifdef SPLIT_BN_FREE
/**
* Frees a BIGNUM
*
* @param a [In] BIGNUM to free
*/
void BN_free(a)
BIGNUM *a;
{
if (a == NULL) return;
if ((a->d != NULL) && !(BN_get_flags(a,BN_FLG_STATIC_DATA)))
Free(a->d);
a->flags|=BN_FLG_FREE; /* REMOVE? */
if (a->flags & BN_FLG_MALLOCED)
Free(a);
}
#endif
#ifdef SPLIT_BN_INIT
#ifdef SMALL_CODE_SIZE
/**
* Zero expands a bignum
*
* @param a [In] BIGNUM to expand
* @param n [In] number of bits to expand to
*
* @pre <i>a</i> is a valid BIGNUM.
*/
void bn_zexpand(a,n)
BIGNUM *a;
int n;
{
if ((a)->top < n)
{
int i;
bn_wexpand((a),n);
if (a->d!=NULL)
{
for (i=(a)->top; i<n; i++)
(a)->d[i]=0;
}
}
}
/**
* Fixes the top value in the BIGNUM to be the count of BN_ULONGs with data.
*
* @param a [In] BIGNUM to free
*
* @pre <i>a</i> is a valid BIGNUM.
*/
void bn_fix_top(a)
BIGNUM *a;
{
BN_ULONG *ftl;
if ((a)->top > 0)
{
for (ftl= &((a)->d[(a)->top-1]); (a)->top > 0; (a)->top--)
if (*(ftl--)) break;
}
}
#endif
/**
* Initializes a BIGNUM
*
* @param a [In] BIGNUM reference
*
* @pre <i>a</i> is a valid BIGNUM.
*/
void BN_init(a)
BIGNUM *a;
{
(void)Memset(a,0,sizeof(BIGNUM));
}
#endif
#ifdef SPLIT_BN_NEW
/**
* Allocates a BIGNUM
*
* @return pointer to allocated BIGNUM
*/
BIGNUM *BN_new()
{
BIGNUM *ret;
if ((ret=(BIGNUM *)Malloc(sizeof(BIGNUM))) == NULL)
{
#ifndef NO_ERR
BNerr(BN_F_BN_NEW,ERR_R_MALLOC_FAILURE);
#endif
return(NULL);
}
ret->flags=BN_FLG_MALLOCED;
ret->top=0;
ret->neg=0;
ret->max=0;
ret->d=NULL;
return(ret);
}
#endif
#ifdef SPLIT_BN_CTX_NEW
/**
* Allocates a BIGNUM context
*
* @return pointer to allocated BIGNUM context
*/
BN_CTX *BN_CTX_new()
{
BN_CTX *ret;
ret=(BN_CTX *)Malloc(sizeof(BN_CTX));
if (ret == NULL)
{
#ifndef NO_ERR
BNerr(BN_F_BN_CTX_NEW,ERR_R_MALLOC_FAILURE);
#endif
return(NULL);
}
BN_CTX_init(ret);
ret->flags=BN_FLG_MALLOCED;
return(ret);
}
#endif
#ifdef SPLIT_CTX_INIT
/**
* Initializes a BIGNUM context
*
* @param a [In] BIGNUM context reference
*
* @pre <i>a</i> is a valid BIGNUM context.
*/
void BN_CTX_init(ctx)
BN_CTX *ctx;
{
(void)Memset(ctx,0,sizeof(BN_CTX));
ctx->tos=0;
ctx->flags=0;
}
#endif
#ifdef SPLIT_BN_CTX_FREE
/**
* Frees a BIGNUM context
*
* @param a [In] BIGNUM context reference
*
* @pre <i>a</i> is a valid BIGNUM context.
*/
void BN_CTX_free(c)
BN_CTX *c;
{
int i;
for (i=0; i<BN_CTX_NUM; i++)
BN_clear_free(&(c->bn[i]));
if (c->flags & BN_FLG_MALLOCED)
Free(c);
}
#endif
#ifdef SPLIT_BN_EXPAND2
BIGNUM *bn_expand2(b, words)
BIGNUM *b;
int words;
{
BN_ULONG *A,*B,*a;
R_DIAG_CHECK_STACK;
bn_check_top(b);
if (words > b->max)
{
bn_check_top(b);
if (BN_get_flags(b,BN_FLG_STATIC_DATA))
{
#ifndef NO_ERR
BNerr(BN_F_BN_EXPAND2,BN_R_EXPAND_ON_STATIC_BIGNUM_DATA);
#endif
return(NULL);
}
a=A=(BN_ULONG *)Malloc(sizeof(BN_ULONG)*(words+1));
if (A == NULL)
{
#ifndef NO_ERR
BNerr(BN_F_BN_EXPAND2,ERR_R_MALLOC_FAILURE);
#endif
return(NULL);
}
/* during development this is a nice way of making sure
* that we are not relying on the top byte being 0 or
* other such things
*/
#ifdef BN_DEBUG
(void)Memset(A,0x5c,sizeof(BN_ULONG)*(words+1));
#endif
B=b->d;
if (B != NULL)
{
#ifndef SMALL_CODE_SIZE
int i;
/* for (i=b->top&(~7); i>0; i-=8) */
/* The above line can induce a SunC compiler bug */
for (i=(b->top>>3); i>0; i--)
{
BN_ULONG T0,T1,T2,T3;
T0=B[0];
T1=B[1];
T2=B[2];
T3=B[3];
A[0]=T0;
A[1]=T1;
A[2]=T2;
A[3]=T3;
T0=B[4];
T1=B[5];
T2=B[6];
T3=B[7];
A[4]=T0;
A[5]=T1;
A[6]=T2;
A[7]=T3;
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 optimiser 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
*/
;
}
#if 0 /* Not needed */
B= &(b->d[b->top]);
j=b->max-8;
for (i=b->top; i<j; i+=8)
{
B[0]=0; B[1]=0; B[2]=0; B[3]=0;
B[4]=0; B[5]=0; B[6]=0; B[7]=0;
B+=8;
}
for (j+=8; i<j; i++)
{
B[0]=0;
B++;
}
#endif
#else
(void)Memcpy(A,B,sizeof(BN_ULONG)*b->top);
#endif
Free(b->d);
}
b->d=a;
b->max=words;
}
return(b);
}
#endif
#ifdef SPLIT_BN_DUP
/**
* Duplicates a BIGNUM
*
* @param a [In] BIGNUM reference
*
* @returns pointer to duplicate BIGNUM of <i>a</i>
*/
BIGNUM *BN_dup(a)
BIGNUM *a;
{
BIGNUM *r;
BIGNUM *ret;
bn_check_top(a);
r=BN_new();
if (r == NULL) return(NULL);
ret = (BIGNUM *)BN_copy(r,a);
if (ret == NULL)
{
BN_free(r);
}
return(ret);
}
#endif
#ifdef SPLIT_BN_COPY
/**
* Copies a BIGNUM to an existing BIGNUM
*
* @param a [In] To BIGNUM reference
* @param b [Out] From BIGNUM reference
*
* @pre Both <i>a</i> and <i>b</i> are valid BIGNUMs
*
* @returns pointer to duplicate BIGNUM of <i>a</i>
*/
BIGNUM *BN_copy(a, b)
BIGNUM *a;
BIGNUM *b;
{
#ifndef SMALL_CODE_SIZE
int i;
BN_ULONG *A,*B;
#endif
bn_check_top(b);
if (a == b) return(a);
if (bn_wexpand(a,b->top) == NULL) return(NULL);
#ifndef SMALL_CODE_SIZE
A=a->d;
B=b->d;
/* for (i=b->top&~0x07; i>0; i-=8) */
/* The above version of this loop has been removed. It appeared
to generate a compiler bug in SunC 4.x and 5.x. I do not believe
that the code was to blame. Compiling with -fast was the problem
since this would loop unroll the loop below another 3 times.
The compiler would generate generate
andcc %o0,-8,%o1 # load ~0x07
ld [%i2],%o3 # load *B
ble .L77000125 # exit loop unless 8 or more
ld [%i1],%o2 # load *A
sub %o1,-7,%o0 #
sdivcc %o0,8,%o0 # when do we clear %y?
bvs,a .L900001510
sethi %hi(0x80000000),%o0
.L900001510:
cmp %o0,3
bl .L77000114 # one loop
ld [%o2],%o0
# three loop code
The loop would then be unrolled 3 times. The problem I believe
I was seeing was that the sdivcc operates is %y:%o0 / 8.
%y is not being cleared, and so occasionally this would
cause problems. The replacement code sequence stops
the compiler generating the sdiv instruction.
*/
for (i=(b->top>>3); i>0; i--)
{
BN_ULONG T0,T1,T2,T3;
T0=B[0];
T1=B[1];
T2=B[2];
T3=B[3];
A[0]=T0;
A[1]=T1;
A[2]=T2;
A[3]=T3;
T0=B[4];
T1=B[5];
T2=B[6];
T3=B[7];
A[4]=T0;
A[5]=T1;
A[6]=T2;
A[7]=T3;
A+=8;
B+=8;
}
switch (b->top&0x07)
{
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 optimiser 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
(void)Memcpy(a->d,b->d,sizeof(b->d[0])*b->top);
#endif
/* (void)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);
}
#endif
#ifdef SPLIT_BN_CLEAR
/**
* Clears a BIGNUM
*
* @param a [In] BIGNUM to clear
*
* @pre <i>a</i> is valid
*/
void BN_clear(a)
BIGNUM *a;
{
if (a->d != NULL)
(void)Memset(a->d,0,a->max*sizeof(a->d[0]));
a->top=0;
a->neg=0;
}
#endif
#ifdef SPLIT_BN_GET_WORD
BN_ULONG BN_get_word(a)
BIGNUM *a;
{
int i,n;
BN_ULONG ret=0;
n=BN_num_bytes(a);
if (n > ((int) 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);
}
#endif
#ifdef SPLIT_BN_SET_WORD
/**
* Set the BIGNUM to the supplied BN_ULONG value.
*
* @param a [In/Out] BIGNUM to be updated
* @param w [In] Value to be set in <i>a</i>
*
* @notes Function will expand <i>a</i> to be an
* array of 8 BN_ULONGs in size.
* @todo Review behaviour of expansion without checking
* of size first.
*/
int BN_set_word(a,w)
BIGNUM *a;
BN_ULONG w;
{
int i,n;
if (bn_expand(a,(int)(sizeof(BN_ULONG)*8)) == NULL) return(0);
#ifdef BN_BYTES
/* This is used when a BN_ULONG is greater in size
* than the BN_BYTES of the array, eg BN_ULONG 64 bits
* and actual a->d array of 32 bits.
*/
n=sizeof(BN_ULONG)/BN_BYTES;
#else
n=1;
#endif
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);
}
#endif
#ifdef BN_BYTES
#ifdef SPLIT_BN_BIN2BN
/* ignore negative */
BIGNUM *BN_bin2bn(s, len, ret)
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;
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);
}
#endif
#ifdef SPLIT_BN_BN2BIN
/* ignore negative */
int BN_bn2bin(a, to)
BIGNUM *a;
unsigned char *to;
{
int n,i;
BN_ULONG l;
bn_check_top(a);
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);
}
#endif
#else
#ifdef SPLIT_BN_BIN2BN
/* ignore negative */
BIGNUM *BN_bin2bn(s, len, ret)
unsigned char *s;
int len;
BIGNUM *ret;
{
int i,w,r,b,j,v;
int n;
BN_ULONG l;
if (ret == NULL) ret=BN_new();
if (ret == NULL) return(NULL);
while (len > 0)
{
if (*s != 0) break;
s++;
len--;
}
n=len*8;
if (bn_expand(ret,n) == NULL)
return(NULL);
for (i=0; i<ret->max; i++)
ret->d[i]=0;
j=0;
for (i=len-1; i>=0; i--)
{
v=((int)s[i])&0xff;
w=j/BN_BITS2;
b=j%BN_BITS2;
r=BN_BITS2-b;
j+=8;
if (r >= 8)
{
ret->d[w]|=(((BN_ULONG)v)<<b);
}
else
{
ret->d[w] =(ret->d[w]|(((BN_ULONG)v)<<b))&BN_MASK2;
ret->d[w+1]=(ret->d[w+1]|(((BN_ULONG)v)>>r));
}
}
ret->top=((n-1)/BN_BITS2)+1;
bn_fix_top(ret);
return(ret);
}
#endif
#ifdef SPLIT_BN_BN2BIN
int BN_bn2bin(a, to)
BIGNUM *a;
unsigned char *to;
{
int num,i,bi,w,b,r,max;
BN_ULONG l,*lp;
bn_check_top(a);
num=bi=BN_num_bytes(a);
lp=a->d;
for (i=0; i<num; i++)
{
w=(i*8)/BN_BITS2;
b=(i*8)%BN_BITS2;
r=BN_BITS2-b;
bi--;
if (r >= 8)
to[bi]=(lp[w]>>b)&0xff;
else
{
to[bi]=(lp[w]>>b);
if (w+1 < a->top)
to[bi]|=lp[w+1]<<r;
}
}
return(num);
}
#endif
#endif
#ifdef SPLIT_BN_UCMP
int BN_ucmp(a, b)
BIGNUM *a;
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);
}
#endif
#ifdef SPLIT_BN_CMP
int BN_cmp(a, b)
BIGNUM *a;
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);
}
#endif
#ifdef SPLIT_BN_SET_BIT
int BN_set_bit(a, n)
BIGNUM *a;
int n;
{
int i,j,k;
bn_check_top(a);
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);
}
#endif
#ifdef SPLIT_BN_CLEAR_BIT
int BN_clear_bit(a, n)
BIGNUM *a;
int n;
{
int i,j;
bn_check_top(a);
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);
}
#endif
#ifdef SPLIT_BN_IS_BIT_SET
int BN_is_bit_set(a, n)
BIGNUM *a;
int n;
{
int i,j;
bn_check_top(a);
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);
}
#endif
#ifdef SPLIT_BN_MASK_BITS
int BN_mask_bits(a,n)
BIGNUM *a;
int n;
{
int b,w;
bn_check_top(a);
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_ULONG)BN_MASK2)<<b);
}
bn_fix_top(a);
return(1);
}
#endif
#ifdef SPLIT_BN_CMP_WORDS
int bn_cmp_words(a,b,n)
BN_ULONG *a,*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);
}
#endif
#endif