⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 libtommath.c

📁 IEEE802.11 a/b/g 客户端应用程序源代码
💻 C
📖 第 1 页 / 共 5 页
字号:
  /* normalize both x and y, ensure that y >= b/2, [b == 2**DIGIT_BIT] */  norm = mp_count_bits(&y) % DIGIT_BIT;  if (norm < (int)(DIGIT_BIT-1)) {     norm = (DIGIT_BIT-1) - norm;     if ((res = mp_mul_2d (&x, norm, &x)) != MP_OKAY) {       goto LBL_Y;     }     if ((res = mp_mul_2d (&y, norm, &y)) != MP_OKAY) {       goto LBL_Y;     }  } else {     norm = 0;  }  /* note hac does 0 based, so if used==5 then its 0,1,2,3,4, e.g. use 4 */  n = x.used - 1;  t = y.used - 1;  /* while (x >= y*b**n-t) do { q[n-t] += 1; x -= y*b**{n-t} } */  if ((res = mp_lshd (&y, n - t)) != MP_OKAY) { /* y = y*b**{n-t} */    goto LBL_Y;  }  while (mp_cmp (&x, &y) != MP_LT) {    ++(q.dp[n - t]);    if ((res = mp_sub (&x, &y, &x)) != MP_OKAY) {      goto LBL_Y;    }  }  /* reset y by shifting it back down */  mp_rshd (&y, n - t);  /* step 3. for i from n down to (t + 1) */  for (i = n; i >= (t + 1); i--) {    if (i > x.used) {      continue;    }    /* step 3.1 if xi == yt then set q{i-t-1} to b-1,      * otherwise set q{i-t-1} to (xi*b + x{i-1})/yt */    if (x.dp[i] == y.dp[t]) {      q.dp[i - t - 1] = ((((mp_digit)1) << DIGIT_BIT) - 1);    } else {      mp_word tmp;      tmp = ((mp_word) x.dp[i]) << ((mp_word) DIGIT_BIT);      tmp |= ((mp_word) x.dp[i - 1]);      tmp /= ((mp_word) y.dp[t]);      if (tmp > (mp_word) MP_MASK)        tmp = MP_MASK;      q.dp[i - t - 1] = (mp_digit) (tmp & (mp_word) (MP_MASK));    }    /* while (q{i-t-1} * (yt * b + y{t-1})) >              xi * b**2 + xi-1 * b + xi-2             do q{i-t-1} -= 1;     */    q.dp[i - t - 1] = (q.dp[i - t - 1] + 1) & MP_MASK;    do {      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1) & MP_MASK;      /* find left hand */      mp_zero (&t1);      t1.dp[0] = (t - 1 < 0) ? 0 : y.dp[t - 1];      t1.dp[1] = y.dp[t];      t1.used = 2;      if ((res = mp_mul_d (&t1, q.dp[i - t - 1], &t1)) != MP_OKAY) {        goto LBL_Y;      }      /* find right hand */      t2.dp[0] = (i - 2 < 0) ? 0 : x.dp[i - 2];      t2.dp[1] = (i - 1 < 0) ? 0 : x.dp[i - 1];      t2.dp[2] = x.dp[i];      t2.used = 3;    } while (mp_cmp_mag(&t1, &t2) == MP_GT);    /* step 3.3 x = x - q{i-t-1} * y * b**{i-t-1} */    if ((res = mp_mul_d (&y, q.dp[i - t - 1], &t1)) != MP_OKAY) {      goto LBL_Y;    }    if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {      goto LBL_Y;    }    if ((res = mp_sub (&x, &t1, &x)) != MP_OKAY) {      goto LBL_Y;    }    /* if x < 0 then { x = x + y*b**{i-t-1}; q{i-t-1} -= 1; } */    if (x.sign == MP_NEG) {      if ((res = mp_copy (&y, &t1)) != MP_OKAY) {        goto LBL_Y;      }      if ((res = mp_lshd (&t1, i - t - 1)) != MP_OKAY) {        goto LBL_Y;      }      if ((res = mp_add (&x, &t1, &x)) != MP_OKAY) {        goto LBL_Y;      }      q.dp[i - t - 1] = (q.dp[i - t - 1] - 1UL) & MP_MASK;    }  }  /* now q is the quotient and x is the remainder    * [which we have to normalize]    */    /* get sign before writing to c */  x.sign = x.used == 0 ? MP_ZPOS : a->sign;  if (c != NULL) {    mp_clamp (&q);    mp_exch (&q, c);    c->sign = neg;  }  if (d != NULL) {    mp_div_2d (&x, norm, &x, NULL);    mp_exch (&x, d);  }  res = MP_OKAY;LBL_Y:mp_clear (&y);LBL_X:mp_clear (&x);LBL_T2:mp_clear (&t2);LBL_T1:mp_clear (&t1);LBL_Q:mp_clear (&q);  return res;}#endif#ifdef MP_LOW_MEM   #define TAB_SIZE 32#else   #define TAB_SIZE 256#endifstatic int s_mp_exptmod (mp_int * G, mp_int * X, mp_int * P, mp_int * Y, int redmode){  mp_int  M[TAB_SIZE], res, mu;  mp_digit buf;  int     err, bitbuf, bitcpy, bitcnt, mode, digidx, x, y, winsize;  int (*redux)(mp_int*,mp_int*,mp_int*);  /* find window size */  x = mp_count_bits (X);  if (x <= 7) {    winsize = 2;  } else if (x <= 36) {    winsize = 3;  } else if (x <= 140) {    winsize = 4;  } else if (x <= 450) {    winsize = 5;  } else if (x <= 1303) {    winsize = 6;  } else if (x <= 3529) {    winsize = 7;  } else {    winsize = 8;  }#ifdef MP_LOW_MEM    if (winsize > 5) {       winsize = 5;    }#endif  /* init M array */  /* init first cell */  if ((err = mp_init(&M[1])) != MP_OKAY) {     return err;   }  /* now init the second half of the array */  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {    if ((err = mp_init(&M[x])) != MP_OKAY) {      for (y = 1<<(winsize-1); y < x; y++) {        mp_clear (&M[y]);      }      mp_clear(&M[1]);      return err;    }  }  /* create mu, used for Barrett reduction */  if ((err = mp_init (&mu)) != MP_OKAY) {    goto LBL_M;  }    if (redmode == 0) {     if ((err = mp_reduce_setup (&mu, P)) != MP_OKAY) {        goto LBL_MU;     }     redux = mp_reduce;  } else {     if ((err = mp_reduce_2k_setup_l (P, &mu)) != MP_OKAY) {        goto LBL_MU;     }     redux = mp_reduce_2k_l;  }      /* create M table   *   * The M table contains powers of the base,    * e.g. M[x] = G**x mod P   *   * The first half of the table is not    * computed though accept for M[0] and M[1]   */  if ((err = mp_mod (G, P, &M[1])) != MP_OKAY) {    goto LBL_MU;  }  /* compute the value at M[1<<(winsize-1)] by squaring    * M[1] (winsize-1) times    */  if ((err = mp_copy (&M[1], &M[1 << (winsize - 1)])) != MP_OKAY) {    goto LBL_MU;  }  for (x = 0; x < (winsize - 1); x++) {    /* square it */    if ((err = mp_sqr (&M[1 << (winsize - 1)],                        &M[1 << (winsize - 1)])) != MP_OKAY) {      goto LBL_MU;    }    /* reduce modulo P */    if ((err = redux (&M[1 << (winsize - 1)], P, &mu)) != MP_OKAY) {      goto LBL_MU;    }  }  /* create upper table, that is M[x] = M[x-1] * M[1] (mod P)   * for x = (2**(winsize - 1) + 1) to (2**winsize - 1)   */  for (x = (1 << (winsize - 1)) + 1; x < (1 << winsize); x++) {    if ((err = mp_mul (&M[x - 1], &M[1], &M[x])) != MP_OKAY) {      goto LBL_MU;    }    if ((err = redux (&M[x], P, &mu)) != MP_OKAY) {      goto LBL_MU;    }  }  /* setup result */  if ((err = mp_init (&res)) != MP_OKAY) {    goto LBL_MU;  }  mp_set (&res, 1);  /* set initial mode and bit cnt */  mode   = 0;  bitcnt = 1;  buf    = 0;  digidx = X->used - 1;  bitcpy = 0;  bitbuf = 0;  for (;;) {    /* grab next digit as required */    if (--bitcnt == 0) {      /* if digidx == -1 we are out of digits */      if (digidx == -1) {        break;      }      /* read next digit and reset the bitcnt */      buf    = X->dp[digidx--];      bitcnt = (int) DIGIT_BIT;    }    /* grab the next msb from the exponent */    y     = (buf >> (mp_digit)(DIGIT_BIT - 1)) & 1;    buf <<= (mp_digit)1;    /* if the bit is zero and mode == 0 then we ignore it     * These represent the leading zero bits before the first 1 bit     * in the exponent.  Technically this opt is not required but it     * does lower the # of trivial squaring/reductions used     */    if (mode == 0 && y == 0) {      continue;    }    /* if the bit is zero and mode == 1 then we square */    if (mode == 1 && y == 0) {      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {        goto LBL_RES;      }      if ((err = redux (&res, P, &mu)) != MP_OKAY) {        goto LBL_RES;      }      continue;    }    /* else we add it to the window */    bitbuf |= (y << (winsize - ++bitcpy));    mode    = 2;    if (bitcpy == winsize) {      /* ok window is filled so square as required and multiply  */      /* square first */      for (x = 0; x < winsize; x++) {        if ((err = mp_sqr (&res, &res)) != MP_OKAY) {          goto LBL_RES;        }        if ((err = redux (&res, P, &mu)) != MP_OKAY) {          goto LBL_RES;        }      }      /* then multiply */      if ((err = mp_mul (&res, &M[bitbuf], &res)) != MP_OKAY) {        goto LBL_RES;      }      if ((err = redux (&res, P, &mu)) != MP_OKAY) {        goto LBL_RES;      }      /* empty window and reset */      bitcpy = 0;      bitbuf = 0;      mode   = 1;    }  }  /* if bits remain then square/multiply */  if (mode == 2 && bitcpy > 0) {    /* square then multiply if the bit is set */    for (x = 0; x < bitcpy; x++) {      if ((err = mp_sqr (&res, &res)) != MP_OKAY) {        goto LBL_RES;      }      if ((err = redux (&res, P, &mu)) != MP_OKAY) {        goto LBL_RES;      }      bitbuf <<= 1;      if ((bitbuf & (1 << winsize)) != 0) {        /* then multiply */        if ((err = mp_mul (&res, &M[1], &res)) != MP_OKAY) {          goto LBL_RES;        }        if ((err = redux (&res, P, &mu)) != MP_OKAY) {          goto LBL_RES;        }      }    }  }  mp_exch (&res, Y);  err = MP_OKAY;LBL_RES:mp_clear (&res);LBL_MU:mp_clear (&mu);LBL_M:  mp_clear(&M[1]);  for (x = 1<<(winsize-1); x < (1 << winsize); x++) {    mp_clear (&M[x]);  }  return err;}/* computes b = a*a */static int mp_sqr (mp_int * a, mp_int * b){  int     res;#ifdef BN_MP_TOOM_SQR_C  /* use Toom-Cook? */  if (a->used >= TOOM_SQR_CUTOFF) {    res = mp_toom_sqr(a, b);  /* Karatsuba? */  } else #endif#ifdef BN_MP_KARATSUBA_SQR_Cif (a->used >= KARATSUBA_SQR_CUTOFF) {    res = mp_karatsuba_sqr (a, b);  } else #endif  {#ifdef BN_FAST_S_MP_SQR_C    /* can we use the fast comba multiplier? */    if ((a->used * 2 + 1) < MP_WARRAY &&          a->used <          (1 << (sizeof(mp_word) * CHAR_BIT - 2*DIGIT_BIT - 1))) {      res = fast_s_mp_sqr (a, b);    } else#endif#ifdef BN_S_MP_SQR_C      res = s_mp_sqr (a, b);#else#error mp_sqr could fail      res = MP_VAL;#endif  }  b->sign = MP_ZPOS;  return res;}/* reduces a modulo n where n is of the form 2**p - d    This differs from reduce_2k since "d" can be larger   than a single digit.*/static int mp_reduce_2k_l(mp_int *a, mp_int *n, mp_int *d){   mp_int q;   int    p, res;      if ((res = mp_init(&q)) != MP_OKAY) {      return res;   }      p = mp_count_bits(n);    top:   /* q = a/2**p, a = a mod 2**p */   if ((res = mp_div_2d(a, p, &q, a)) != MP_OKAY) {      goto ERR;   }      /* q = q * d */   if ((res = mp_mul(&q, d, &q)) != MP_OKAY) {       goto ERR;   }      /* a = a + q */   if ((res = s_mp_add(a, &q, a)) != MP_OKAY) {      goto ERR;   }      if (mp_cmp_mag(a, n) != MP_LT) {      s_mp_sub(a, n, a);      goto top;   }   ERR:   mp_clear(&q);   return res;}/* determines the setup value */static int mp_reduce_2k_setup_l(mp_int *a, mp_int *d){   int    res;   mp_int tmp;      if ((res = mp_init(&tmp)) != MP_OKAY) {      return res;   }      if ((res = mp_2expt(&tmp, mp_count_bits(a))) != MP_OKAY) {      goto ERR;   }      if ((res = s_mp_sub(&tmp, a, d)) != MP_OKAY) {      goto ERR;   }   ERR:   mp_clear(&tmp);   return res;}/* computes a = 2**b  * * Simple algorithm which zeroes the int, grows it then just sets one bit * as required. */static int mp_2expt (mp_int * a, int b){  int     res;  /* zero a as per default */  mp_zero (a);  /* grow a to accomodate the single bit */  if ((res = mp_grow (a, b / DIGIT_BIT + 1)) != MP_OKAY) {    return res;  }  /* set the used count of where the bit will go */  a->used = b / DIGIT_BIT + 1;  /* put the single bit in its place */  a->dp[b / DIGIT_BIT] = ((mp_digit)1) << (b % DIGIT_BIT);  return MP_OKAY;}/* pre-calculate the value required for Barrett reduction * For a given modulus "b" it calulates the value required in "a" */static int mp_reduce_setup (mp_int * a, mp_int * b){  int     res;    if ((res = mp_2expt (a, b->used * 2 * DIGIT_BIT)) != MP_OKAY) {    return res;  }  return mp_div (a, b, a, NULL);}/* reduces x mod m, assumes 0 < x < m**2, mu is  * precomputed via mp_reduce_setup. * From HAC pp.604 Algorithm 14.42 */static int mp_reduce (mp_int * x, mp_int * m, mp_int * mu){  mp_int  q;  int     res, um = m->used;  /* q = x */  if ((res = mp_init_copy (&q, x)) != MP_OKAY) {    return res;  }  /* q1 = x / b**(k-1)  */  mp_rshd (&q, um - 1);           /* according to HAC this optimization is ok */  if (((unsigned long) um) > (((mp_digit)1) << (DIGIT_BIT - 1))) {    if ((res = mp_mul (&q, mu, &q)) != MP_OKAY) {      goto CLEANUP;    }  } else {#ifdef BN_S_MP_MUL_HIGH_DIGS_C    if ((res = s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {      goto CLEANUP;    }#elif defined(BN_FAST_S_MP_MUL_HIGH_DIGS_C)    if ((res = fast_s_mp_mul_high_digs (&q, mu, &q, um)) != MP_OKAY) {      goto CLEANUP;    }#else     { #error mp_reduce would always fail      res = MP_VAL;      goto CLEANUP;    }#endif  }  /* q3 = q2 / b**(k+1) */  mp_rshd (&q, um + 1);           /* x = x mod b**(k+1), quick (no division) */  if ((res = mp_mod_2d (x, DIGIT_BIT * (um + 1), x)) != MP_OKAY) {    goto CLEANUP;  }  /* q = q * m mod b**(k+1), quick (no division) */  if ((res = s_mp_mul_digs (&q, m, &q, um + 1)) != MP_OKAY) {    goto CLEANUP;  }  /* x = x - q */  if ((res = mp_sub (x, &q, x)) != MP_OKAY) {    goto CLEANUP;  }

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -