The Big Number library. #include "bn.h" when using this library. This big number library was written for use in implementing the RSA and DH public key encryption algorithms. As such, features such as negative numbers have not been extensively tested but they should work as expected. This library uses dynamic memory allocation for storing its data structures and so there are no limit on the size of the numbers manipulated by these routines but there is always the requirement to check return codes from functions just in case a memory allocation error has occurred. The basic object in this library is a BIGNUM. It is used to hold a single large integer. This type should be considered opaque and fields should not be modified or accessed directly. typedef struct bignum_st { int top; /* Index of last used d. */ BN_ULONG *d; /* Pointer to an array of 'BITS2' bit chunks. */ int max; /* Size of the d array. */ int neg; } BIGNUM; The big number is stored in a malloced array of BN_ULONG's. A BN_ULONG can be either 16, 32 or 64 bits in size, depending on the 'number of bits' specified in bn.h. The 'd' field is this array. 'max' is the size of the 'd' array that has been allocated. 'top' is the 'last' entry being used, so for a value of 4, bn.d[0]=4 and bn.top=1. 'neg' is 1 if the number is negative. When a BIGNUM is '0', the 'd' field can be NULL and top == 0. Various routines in this library require the use of 'temporary' BIGNUM variables during their execution. Due to the use of dynamic memory allocation to create BIGNUMs being rather expensive when used in conjunction with repeated subroutine calls, the BN_CTX structure is used. This structure contains BN_CTX BIGNUMs. BN_CTX is the maximum number of temporary BIGNUMs any publicly exported function will use. #define BN_CTX 12 typedef struct bignum_ctx { int tos; /* top of stack */ BIGNUM *bn[BN_CTX]; /* The variables */ } BN_CTX; The functions that follow have been grouped according to function. Most arithmetic functions return a result in the first argument, sometimes this first argument can also be an input parameter, sometimes it cannot. These restrictions are documented. extern BIGNUM *BN_value_one; There is one variable defined by this library, a BIGNUM which contains the number 1. This variable is useful for use in comparisons and assignment. Get Size functions. int BN_num_bits(BIGNUM *a); This function returns the size of 'a' in bits. int BN_num_bytes(BIGNUM *a); This function (macro) returns the size of 'a' in bytes. For conversion of BIGNUMs to byte streams, this is the number of bytes the output string will occupy. If the output byte format specifies that the 'top' bit indicates if the number is signed, so an extra '0' byte is required if the top bit on a positive number is being written, it is upto the application to make this adjustment. Like I said at the start, I don't really support negative numbers :-). Creation/Destruction routines. BIGNUM *BN_new(); Return a new BIGNUM object. The number initially has a value of 0. If there is an error, NULL is returned. void BN_free(BIGNUM *a); Free()s a BIGNUM. void BN_clear(BIGNUM *a); Sets 'a' to a value of 0 and also zeros all unused allocated memory. This function is used to clear a variable of 'sensitive' data that was held in it. void BN_clear_free(BIGNUM *a); This function zeros the memory used by 'a' and then free()'s it. This function should be used to BN_free() BIGNUMS that have held sensitive numeric values like RSA private key values. Both this function and BN_clear tend to only be used by RSA and DH routines. BN_CTX *BN_CTX_new(void); Returns a new BN_CTX. NULL on error. void BN_CTX_free(BN_CTX *c); Free a BN_CTX structure. The BIGNUMs in 'c' are BN_clear_free()ed. BIGNUM *bn_expand(BIGNUM *b, int bits); This is an internal function that should not normally be used. It ensures that 'b' has enough room for a 'bits' bit 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_copy(BIGNUM *to, BIGNUM *from); The 'from' is copied into 'to'. NULL is returned if there is an error, otherwise 'to' is returned. BIGNUM *BN_dup(BIGNUM *a); A new BIGNUM is created and returned containing the value of 'a'. NULL is returned on error. Comparison and Test Functions. int BN_is_zero(BIGNUM *a) Return 1 if 'a' is zero, else 0. int BN_is_one(a) Return 1 is 'a' is one, else 0. int BN_is_word(a,w) Return 1 if 'a' == w, else 0. 'w' is a BN_ULONG. int BN_cmp(BIGNUM *a, BIGNUM *b); Return -1 if 'a' is less than 'b', 0 if 'a' and 'b' are the same and 1 is 'a' is greater than 'b'. This is a signed comparison. int BN_ucmp(BIGNUM *a, BIGNUM *b); This function is the same as BN_cmp except that the comparison ignores the sign of the numbers. Arithmetic Functions For all of these functions, 0 is returned if there is an error and 1 is returned for success. The return value should always be checked. eg. if (!BN_add(r,a,b)) goto err; Unless explicitly mentioned, the 'return' value can be one of the 'parameters' to the function. int BN_add(BIGNUM *r, BIGNUM *a, BIGNUM *b); Add 'a' and 'b' and return the result in 'r'. This is r=a+b. int BN_sub(BIGNUM *r, BIGNUM *a, BIGNUM *b); Subtract 'a' from 'b' and put the result in 'r'. This is r=a-b. int BN_lshift(BIGNUM *r, BIGNUM *a, int n); Shift 'a' left by 'n' bits. This is r=a*(2^n). int BN_lshift1(BIGNUM *r, BIGNUM *a); Shift 'a' left by 1 bit. This form is more efficient than BN_lshift(r,a,1). This is r=a*2. int BN_rshift(BIGNUM *r, BIGNUM *a, int n); Shift 'a' right by 'n' bits. This is r=int(a/(2^n)). int BN_rshift1(BIGNUM *r, BIGNUM *a); Shift 'a' right by 1 bit. This form is more efficient than BN_rshift(r,a,1). This is r=int(a/2). int BN_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b); Multiply a by b and return the result in 'r'. 'r' must not be either 'a' or 'b'. It has to be a different BIGNUM. This is r=a*b. int BN_sqr(BIGNUM *r, BIGNUM *a, BN_CTX *ctx); Multiply a by a and return the result in 'r'. 'r' must not be 'a'. This function is alot faster than BN_mul(r,a,a). This is r=a*a. int BN_div(BIGNUM *dv, BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx); Divide 'm' by 'd' and return the result in 'dv' and the remainder in 'rem'. Either of 'dv' or 'rem' can be NULL in which case that value is not returned. 'ctx' needs to be passed as a source of temporary BIGNUM variables. This is dv=int(m/d), rem=m%d. int BN_mod(BIGNUM *rem, BIGNUM *m, BIGNUM *d, BN_CTX *ctx); Find the remainder of 'm' divided by 'd' and return it in 'rem'. 'ctx' holds the temporary BIGNUMs required by this function. This function is more efficient than BN_div(NULL,rem,m,d,ctx); This is rem=m%d. int BN_mod_mul(BIGNUM *r, BIGNUM *a, BIGNUM *b, BIGNUM *m,BN_CTX *ctx); Multiply 'a' by 'b' and return the remainder when divided by 'm'. 'ctx' holds the temporary BIGNUMs required by this function. This is r=(a*b)%m. int BN_mod_exp(BIGNUM *r, BIGNUM *a, BIGNUM *p, BIGNUM *m,BN_CTX *ctx); Raise 'a' to the 'p' power and return the remainder when divided by 'm'. 'ctx' holds the temporary BIGNUMs required by this function. This is r=(a^p)%m. int BN_reciprocal(BIGNUM *r, BIGNUM *m, BN_CTX *ctx); Return the reciprocal of 'm'. 'ctx' holds the temporary variables required. This function returns -1 on error, otherwise it returns the number of bits 'r' is shifted left to make 'r' into an integer. This number of bits shifted is required in BN_mod_mul_reciprocal(). This is r=(1/m)<<(BN_num_bits(m)+1). int BN_mod_mul_reciprocal(BIGNUM *r, BIGNUM *x, BIGNUM *y, BIGNUM *m, BIGNUM *i, int nb, BN_CTX *ctx); This function is used to perform an efficient BN_mod_mul() operation. If one is going to repeatedly perform BN_mod_mul() with the same modulus is worth calculating the reciprocal of the modulus and then using this function. This operation uses the fact that a/b == a*r where r is the reciprocal of b. On modern computers multiplication is very fast and big number division is very slow. 'x' is multiplied by 'y' and then divided by 'm' and the remainder is returned. 'i' is the reciprocal of 'm' and 'nb' is the number of bits as returned from BN_reciprocal(). Normal usage is as follows. bn=BN_reciprocal(i,m); for (...) { BN_mod_mul_reciprocal(r,x,y,m,i,bn,ctx); } This is r=(x*y)%m. Internally it is approximately r=(x*y)-m*(x*y/m) or r=(x*y)-m*((x*y*i) >> bn) This function is used in BN_mod_exp() and BN_is_prime(). Assignment Operations int BN_one(BIGNUM *a) Set 'a' to hold the value one. This is a=1. int BN_zero(BIGNUM *a) Set 'a' to hold the value zero. This is a=0. int BN_set_word(BIGNUM *a, unsigned long w); Set 'a' to hold the value of 'w'. 'w' is an unsigned long. This is a=w. unsigned long BN_get_word(BIGNUM *a); Returns 'a' in an unsigned long. Not remarkably, often 'a' will be biger than a word, in which case 0xffffffffL is returned. Word Operations These functions are much more efficient that the normal bignum arithmetic operations. BN_ULONG BN_mod_word(BIGNUM *a, unsigned long w); Return the remainder of 'a' divided by 'w'. This is return(a%w). int BN_add_word(BIGNUM *a, unsigned long w); Add 'w' to 'a'. This function does not take the sign of 'a' into account. This is a+=w; Bit operations. int BN_is_bit_set(BIGNUM *a, int n); This function return 1 if bit 'n' is set in 'a' else 0. int BN_set_bit(BIGNUM *a, int n); This function sets bit 'n' to 1 in 'a'. This is a&= ~(1<