665 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
			
		
		
	
	
			665 lines
		
	
	
		
			14 KiB
		
	
	
	
		
			C
		
	
	
/*
 | 
						|
 | 
						|
Big number library - arithmetic on multiple-precision unsigned integers.
 | 
						|
 | 
						|
This library is an implementation of arithmetic on arbitrarily large integers.
 | 
						|
 | 
						|
The difference between this and other implementations, is that the data structure
 | 
						|
has optimal memory utilization (i.e. a 1024 bit integer takes up 128 bytes RAM),
 | 
						|
and all memory is allocated statically: no dynamic allocation for better or worse.
 | 
						|
 | 
						|
Primary goals are correctness, clarity of code and clean, portable implementation.
 | 
						|
Secondary goal is a memory footprint small enough to make it suitable for use in
 | 
						|
embedded applications.
 | 
						|
 | 
						|
 | 
						|
The current state is correct functionality and adequate performance.
 | 
						|
There may well be room for performance-optimizations and improvements.
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
#include <stdio.h>
 | 
						|
#include <stdbool.h>
 | 
						|
#include <assert.h>
 | 
						|
#include "bn.h"
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Functions for shifting number in-place. */
 | 
						|
static void _lshift_one_bit(struct bn* a);
 | 
						|
static void _rshift_one_bit(struct bn* a);
 | 
						|
static void _lshift_word(struct bn* a, int nwords);
 | 
						|
static void _rshift_word(struct bn* a, int nwords);
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Public / Exported functions. */
 | 
						|
void bignum_init(struct bn* n)
 | 
						|
{
 | 
						|
  require(n, "n is null");
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    n->array[i] = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_from_int(struct bn* n, DTYPE_TMP i)
 | 
						|
{
 | 
						|
  require(n, "n is null");
 | 
						|
 | 
						|
  bignum_init(n);
 | 
						|
 | 
						|
  /* Endianness issue if machine is not little-endian? */
 | 
						|
#ifdef WORD_SIZE
 | 
						|
 #if (WORD_SIZE == 1)
 | 
						|
  n->array[0] = (i & 0x000000ff);
 | 
						|
  n->array[1] = (i & 0x0000ff00) >> 8;
 | 
						|
  n->array[2] = (i & 0x00ff0000) >> 16;
 | 
						|
  n->array[3] = (i & 0xff000000) >> 24;
 | 
						|
 #elif (WORD_SIZE == 2)
 | 
						|
  n->array[0] = (i & 0x0000ffff);
 | 
						|
  n->array[1] = (i & 0xffff0000) >> 16;
 | 
						|
 #elif (WORD_SIZE == 4)
 | 
						|
  n->array[0] = i;
 | 
						|
  DTYPE_TMP num_32 = 32;
 | 
						|
  DTYPE_TMP tmp = i >> num_32; /* bit-shift with U64 operands to force 64-bit results */
 | 
						|
  n->array[1] = tmp;
 | 
						|
 #endif
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int bignum_to_int(struct bn* n)
 | 
						|
{
 | 
						|
  require(n, "n is null");
 | 
						|
 | 
						|
  int ret = 0;
 | 
						|
 | 
						|
  /* Endianness issue if machine is not little-endian? */
 | 
						|
#if (WORD_SIZE == 1)
 | 
						|
  ret += n->array[0];
 | 
						|
  ret += n->array[1] << 8;
 | 
						|
  ret += n->array[2] << 16;
 | 
						|
  ret += n->array[3] << 24;  
 | 
						|
#elif (WORD_SIZE == 2)
 | 
						|
  ret += n->array[0];
 | 
						|
  ret += n->array[1] << 16;
 | 
						|
#elif (WORD_SIZE == 4)
 | 
						|
  ret += n->array[0];
 | 
						|
#endif
 | 
						|
 | 
						|
  return ret;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_from_string(struct bn* n, char* str, int nbytes)
 | 
						|
{
 | 
						|
  require(n, "n is null");
 | 
						|
  require(str, "str is null");
 | 
						|
  require(nbytes > 0, "nbytes must be positive");
 | 
						|
  require((nbytes & 1) == 0, "string format must be in hex -> equal number of bytes");
 | 
						|
 | 
						|
  bignum_init(n);
 | 
						|
 | 
						|
  DTYPE tmp;                        /* DTYPE is defined in bn.h - uint{8,16,32,64}_t */
 | 
						|
  int i = nbytes - (2 * WORD_SIZE); /* index into string */
 | 
						|
  int j = 0;                        /* index into array */
 | 
						|
 | 
						|
  /* reading last hex-byte "MSB" from string first -> big endian */
 | 
						|
  /* MSB ~= most significant byte / block ? :) */
 | 
						|
  while (i >= 0)
 | 
						|
  {
 | 
						|
    tmp = 0;
 | 
						|
    sscanf(&str[i], SSCANF_FORMAT_STR, &tmp);
 | 
						|
    n->array[j] = tmp;
 | 
						|
    i -= (2 * WORD_SIZE); /* step WORD_SIZE hex-byte(s) back in the string. */
 | 
						|
    j += 1;               /* step one element forward in the array. */
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_to_string(struct bn* n, char* str, int nbytes)
 | 
						|
{
 | 
						|
  require(n, "n is null");
 | 
						|
  require(str, "str is null");
 | 
						|
  require(nbytes > 0, "nbytes must be positive");
 | 
						|
  require((nbytes & 1) == 0, "string format must be in hex -> equal number of bytes");
 | 
						|
 | 
						|
  int j = BN_ARRAY_SIZE - 1; /* index into array - reading "MSB" first -> big-endian */
 | 
						|
  int i = 0;                 /* index into string representation. */
 | 
						|
 | 
						|
  /* reading last array-element "MSB" first -> big endian */
 | 
						|
  while ((j >= 0) && (nbytes > (i + 1)))
 | 
						|
  {
 | 
						|
    sprintf(&str[i], SPRINTF_FORMAT_STR, n->array[j]);
 | 
						|
    i += (2 * WORD_SIZE); /* step WORD_SIZE hex-byte(s) forward in the string. */
 | 
						|
    j -= 1;               /* step one element back in the array. */
 | 
						|
  }
 | 
						|
 | 
						|
  /* Count leading zeros: */
 | 
						|
  j = 0;
 | 
						|
  while (str[j] == '0')
 | 
						|
  {
 | 
						|
    j += 1;
 | 
						|
  }
 | 
						|
 
 | 
						|
  /* Move string j places ahead, effectively skipping leading zeros */ 
 | 
						|
  for (i = 0; i < (nbytes - j); ++i)
 | 
						|
  {
 | 
						|
    str[i] = str[i + j];
 | 
						|
  }
 | 
						|
 | 
						|
  /* Zero-terminate string */
 | 
						|
  str[i] = 0;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_dec(struct bn* n)
 | 
						|
{
 | 
						|
  require(n, "n is null");
 | 
						|
 | 
						|
  DTYPE tmp; /* copy of n */
 | 
						|
  DTYPE res;
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    tmp = n->array[i];
 | 
						|
    res = tmp - 1;
 | 
						|
    n->array[i] = res;
 | 
						|
 | 
						|
    if (!(res > tmp))
 | 
						|
    {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_inc(struct bn* n)
 | 
						|
{
 | 
						|
  require(n, "n is null");
 | 
						|
 | 
						|
  DTYPE res;
 | 
						|
  DTYPE_TMP tmp; /* copy of n */
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    tmp = n->array[i];
 | 
						|
    res = tmp + 1;
 | 
						|
    n->array[i] = res;
 | 
						|
 | 
						|
    if (res > tmp)
 | 
						|
    {
 | 
						|
      break;
 | 
						|
    }
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_add(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  DTYPE_TMP tmp;
 | 
						|
  int carry = 0;
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    tmp = (DTYPE_TMP)a->array[i] + b->array[i] + carry;
 | 
						|
    carry = (tmp > MAX_VAL);
 | 
						|
    c->array[i] = (tmp & MAX_VAL);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_sub(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  DTYPE_TMP res;
 | 
						|
  DTYPE_TMP tmp1;
 | 
						|
  DTYPE_TMP tmp2;
 | 
						|
  int borrow = 0;
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    tmp1 = (DTYPE_TMP)a->array[i] + (MAX_VAL + 1); /* + number_base */
 | 
						|
    tmp2 = (DTYPE_TMP)b->array[i] + borrow;;
 | 
						|
    res = (tmp1 - tmp2);
 | 
						|
    c->array[i] = (DTYPE)(res & MAX_VAL); /* "modulo number_base" == "% (number_base - 1)" if number_base is 2^N */
 | 
						|
    borrow = (res <= MAX_VAL);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_mul(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  struct bn row;
 | 
						|
  struct bn tmp;
 | 
						|
  int i, j;
 | 
						|
 | 
						|
  bignum_init(c);
 | 
						|
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    bignum_init(&row);
 | 
						|
 | 
						|
    for (j = 0; j < BN_ARRAY_SIZE; ++j)
 | 
						|
    {
 | 
						|
      if (i + j < BN_ARRAY_SIZE)
 | 
						|
      {
 | 
						|
        bignum_init(&tmp);
 | 
						|
        DTYPE_TMP intermediate = ((DTYPE_TMP)a->array[i] * (DTYPE_TMP)b->array[j]);
 | 
						|
        bignum_from_int(&tmp, intermediate);
 | 
						|
        _lshift_word(&tmp, i + j);
 | 
						|
        bignum_add(&tmp, &row, &row);
 | 
						|
      }
 | 
						|
    }
 | 
						|
    bignum_add(c, &row, c);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_div(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  struct bn current;
 | 
						|
  struct bn denom;
 | 
						|
  struct bn tmp;
 | 
						|
 | 
						|
  bignum_from_int(¤t, 1);               // int current = 1;
 | 
						|
  bignum_assign(&denom, b);                   // denom = b
 | 
						|
  bignum_assign(&tmp, a);                     // tmp   = a
 | 
						|
 | 
						|
  const DTYPE_TMP half_max = 1 + (DTYPE_TMP)(MAX_VAL / 2);
 | 
						|
  bool overflow = false;
 | 
						|
  while (bignum_cmp(&denom, a) != LARGER)     // while (denom <= a) {
 | 
						|
  {
 | 
						|
    if (denom.array[BN_ARRAY_SIZE - 1] >= half_max)
 | 
						|
    {
 | 
						|
      overflow = true;
 | 
						|
      break;
 | 
						|
    }
 | 
						|
    _lshift_one_bit(¤t);                //   current <<= 1;
 | 
						|
    _lshift_one_bit(&denom);                  //   denom <<= 1;
 | 
						|
  }
 | 
						|
  if (!overflow)
 | 
						|
  {
 | 
						|
    _rshift_one_bit(&denom);                  // denom >>= 1;
 | 
						|
    _rshift_one_bit(¤t);                // current >>= 1;
 | 
						|
  }
 | 
						|
  bignum_init(c);                             // int answer = 0;
 | 
						|
 | 
						|
  while (!bignum_is_zero(¤t))           // while (current != 0)
 | 
						|
  {
 | 
						|
    if (bignum_cmp(&tmp, &denom) != SMALLER)  //   if (dividend >= denom)
 | 
						|
    {
 | 
						|
      bignum_sub(&tmp, &denom, &tmp);         //     dividend -= denom;
 | 
						|
      bignum_or(c, ¤t, c);              //     answer |= current;
 | 
						|
    }
 | 
						|
    _rshift_one_bit(¤t);                //   current >>= 1;
 | 
						|
    _rshift_one_bit(&denom);                  //   denom >>= 1;
 | 
						|
  }                                           // return answer;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_lshift(struct bn* a, struct bn* b, int nbits)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(nbits >= 0, "no negative shifts");
 | 
						|
 | 
						|
  bignum_assign(b, a);
 | 
						|
  /* Handle shift in multiples of word-size */
 | 
						|
  const int nbits_pr_word = (WORD_SIZE * 8);
 | 
						|
  int nwords = nbits / nbits_pr_word;
 | 
						|
  if (nwords != 0)
 | 
						|
  {
 | 
						|
    _lshift_word(b, nwords);
 | 
						|
    nbits -= (nwords * nbits_pr_word);
 | 
						|
  }
 | 
						|
 | 
						|
  if (nbits != 0)
 | 
						|
  {
 | 
						|
    int i;
 | 
						|
    for (i = (BN_ARRAY_SIZE - 1); i > 0; --i)
 | 
						|
    {
 | 
						|
      b->array[i] = (b->array[i] << nbits) | (b->array[i - 1] >> ((8 * WORD_SIZE) - nbits));
 | 
						|
    }
 | 
						|
    b->array[i] <<= nbits;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_rshift(struct bn* a, struct bn* b, int nbits)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(nbits >= 0, "no negative shifts");
 | 
						|
  
 | 
						|
  bignum_assign(b, a);
 | 
						|
  /* Handle shift in multiples of word-size */
 | 
						|
  const int nbits_pr_word = (WORD_SIZE * 8);
 | 
						|
  int nwords = nbits / nbits_pr_word;
 | 
						|
  if (nwords != 0)
 | 
						|
  {
 | 
						|
    _rshift_word(b, nwords);
 | 
						|
    nbits -= (nwords * nbits_pr_word);
 | 
						|
  }
 | 
						|
 | 
						|
  if (nbits != 0)
 | 
						|
  {
 | 
						|
    int i;
 | 
						|
    for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i)
 | 
						|
    {
 | 
						|
      b->array[i] = (b->array[i] >> nbits) | (b->array[i + 1] << ((8 * WORD_SIZE) - nbits));
 | 
						|
    }
 | 
						|
    b->array[i] >>= nbits;
 | 
						|
  }
 | 
						|
  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_mod(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  /*
 | 
						|
    Take divmod and throw away div part
 | 
						|
  */
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  struct bn tmp;
 | 
						|
 | 
						|
  bignum_divmod(a,b,&tmp,c);
 | 
						|
}
 | 
						|
 | 
						|
void bignum_divmod(struct bn* a, struct bn* b, struct bn* c, struct bn* d)
 | 
						|
{
 | 
						|
  /*
 | 
						|
    Puts a%b in d
 | 
						|
    and a/b in c
 | 
						|
 | 
						|
    mod(a,b) = a - ((a / b) * b)
 | 
						|
 | 
						|
    example:
 | 
						|
      mod(8, 3) = 8 - ((8 / 3) * 3) = 2
 | 
						|
  */
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  struct bn tmp;
 | 
						|
 | 
						|
  /* c = (a / b) */
 | 
						|
  bignum_div(a, b, c);
 | 
						|
 | 
						|
  /* tmp = (c * b) */
 | 
						|
  bignum_mul(c, b, &tmp);
 | 
						|
 | 
						|
  /* c = a - tmp */
 | 
						|
  bignum_sub(a, &tmp, d);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_and(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    c->array[i] = (a->array[i] & b->array[i]);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_or(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    c->array[i] = (a->array[i] | b->array[i]);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_xor(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    c->array[i] = (a->array[i] ^ b->array[i]);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int bignum_cmp(struct bn* a, struct bn* b)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
 | 
						|
  int i = BN_ARRAY_SIZE;
 | 
						|
  do
 | 
						|
  {
 | 
						|
    i -= 1; /* Decrement first, to start with last array element */
 | 
						|
    if (a->array[i] > b->array[i])
 | 
						|
    {
 | 
						|
      return LARGER;
 | 
						|
    }
 | 
						|
    else if (a->array[i] < b->array[i])
 | 
						|
    {
 | 
						|
      return SMALLER;
 | 
						|
    }
 | 
						|
  }
 | 
						|
  while (i != 0);
 | 
						|
 | 
						|
  return EQUAL;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
int bignum_is_zero(struct bn* n)
 | 
						|
{
 | 
						|
  require(n, "n is null");
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    if (n->array[i])
 | 
						|
    {
 | 
						|
      return 0;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_pow(struct bn* a, struct bn* b, struct bn* c)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
  require(c, "c is null");
 | 
						|
 | 
						|
  struct bn tmp;
 | 
						|
 | 
						|
  bignum_init(c);
 | 
						|
 | 
						|
  if (bignum_cmp(b, c) == EQUAL)
 | 
						|
  {
 | 
						|
    /* Return 1 when exponent is 0 -- n^0 = 1 */
 | 
						|
    bignum_inc(c);
 | 
						|
  }
 | 
						|
  else
 | 
						|
  {
 | 
						|
    struct bn bcopy;
 | 
						|
    bignum_assign(&bcopy, b);
 | 
						|
 | 
						|
    /* Copy a -> tmp */
 | 
						|
    bignum_assign(&tmp, a);
 | 
						|
 | 
						|
    bignum_dec(&bcopy);
 | 
						|
 
 | 
						|
    /* Begin summing products: */
 | 
						|
    while (!bignum_is_zero(&bcopy))
 | 
						|
    {
 | 
						|
 | 
						|
      /* c = tmp * tmp */
 | 
						|
      bignum_mul(&tmp, a, c);
 | 
						|
      /* Decrement b by one */
 | 
						|
      bignum_dec(&bcopy);
 | 
						|
 | 
						|
      bignum_assign(&tmp, c);
 | 
						|
    }
 | 
						|
 | 
						|
    /* c = tmp */
 | 
						|
    bignum_assign(c, &tmp);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
void bignum_isqrt(struct bn *a, struct bn* b)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(b, "b is null");
 | 
						|
 | 
						|
  struct bn low, high, mid, tmp;
 | 
						|
 | 
						|
  bignum_init(&low);
 | 
						|
  bignum_assign(&high, a);
 | 
						|
  bignum_rshift(&high, &mid, 1);
 | 
						|
  bignum_inc(&mid);
 | 
						|
 | 
						|
  while (bignum_cmp(&high, &low) > 0) 
 | 
						|
  {
 | 
						|
    bignum_mul(&mid, &mid, &tmp);
 | 
						|
    if (bignum_cmp(&tmp, a) > 0) 
 | 
						|
    {
 | 
						|
      bignum_assign(&high, &mid);
 | 
						|
      bignum_dec(&high);
 | 
						|
    }
 | 
						|
    else 
 | 
						|
    {
 | 
						|
      bignum_assign(&low, &mid);
 | 
						|
    }
 | 
						|
    bignum_sub(&high,&low,&mid);
 | 
						|
    _rshift_one_bit(&mid);
 | 
						|
    bignum_add(&low,&mid,&mid);
 | 
						|
    bignum_inc(&mid);
 | 
						|
  }
 | 
						|
  bignum_assign(b,&low);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
void bignum_assign(struct bn* dst, struct bn* src)
 | 
						|
{
 | 
						|
  require(dst, "dst is null");
 | 
						|
  require(src, "src is null");
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    dst->array[i] = src->array[i];
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/* Private / Static functions. */
 | 
						|
static void _rshift_word(struct bn* a, int nwords)
 | 
						|
{
 | 
						|
  /* Naive method: */
 | 
						|
  require(a, "a is null");
 | 
						|
  require(nwords >= 0, "no negative shifts");
 | 
						|
 | 
						|
  int i;
 | 
						|
  if (nwords >= BN_ARRAY_SIZE)
 | 
						|
  {
 | 
						|
    for (i = 0; i < BN_ARRAY_SIZE; ++i)
 | 
						|
    {
 | 
						|
      a->array[i] = 0;
 | 
						|
    }
 | 
						|
    return;
 | 
						|
  }
 | 
						|
 | 
						|
  for (i = 0; i < BN_ARRAY_SIZE - nwords; ++i)
 | 
						|
  {
 | 
						|
    a->array[i] = a->array[i + nwords];
 | 
						|
  }
 | 
						|
  for (; i < BN_ARRAY_SIZE; ++i)
 | 
						|
  {
 | 
						|
    a->array[i] = 0;
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void _lshift_word(struct bn* a, int nwords)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
  require(nwords >= 0, "no negative shifts");
 | 
						|
 | 
						|
  int i;
 | 
						|
  /* Shift whole words */
 | 
						|
  for (i = (BN_ARRAY_SIZE - 1); i >= nwords; --i)
 | 
						|
  {
 | 
						|
    a->array[i] = a->array[i - nwords];
 | 
						|
  }
 | 
						|
  /* Zero pad shifted words. */
 | 
						|
  for (; i >= 0; --i)
 | 
						|
  {
 | 
						|
    a->array[i] = 0;
 | 
						|
  }  
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void _lshift_one_bit(struct bn* a)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = (BN_ARRAY_SIZE - 1); i > 0; --i)
 | 
						|
  {
 | 
						|
    a->array[i] = (a->array[i] << 1) | (a->array[i - 1] >> ((8 * WORD_SIZE) - 1));
 | 
						|
  }
 | 
						|
  a->array[0] <<= 1;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
static void _rshift_one_bit(struct bn* a)
 | 
						|
{
 | 
						|
  require(a, "a is null");
 | 
						|
 | 
						|
  int i;
 | 
						|
  for (i = 0; i < (BN_ARRAY_SIZE - 1); ++i)
 | 
						|
  {
 | 
						|
    a->array[i] = (a->array[i] >> 1) | (a->array[i + 1] << ((8 * WORD_SIZE) - 1));
 | 
						|
  }
 | 
						|
  a->array[BN_ARRAY_SIZE - 1] >>= 1;
 | 
						|
}
 | 
						|
 | 
						|
 |