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

📄 mpi.c

📁 Dropbear is an SSH 2 server, designed to be usable in small memory environments. It supports:
💻 C
📖 第 1 页 / 共 5 页
字号:
    d >>= 1;    if((res = s_mp_sqr(&x)) != MP_OKAY)      goto CLEANUP;  }    if(mp_iseven(b))    SIGN(&s) = SIGN(a);  res = mp_copy(&s, c);CLEANUP:  mp_clear(&x);X:  mp_clear(&s);  return res;} /* end mp_expt() *//* }}} *//* {{{ mp_2expt(a, k) *//* Compute a = 2^k */mp_err mp_2expt(mp_int *a, mp_digit k){  ARGCHK(a != NULL, MP_BADARG);  return s_mp_2expt(a, k);} /* end mp_2expt() *//* }}} *//* {{{ mp_mod(a, m, c) *//*  mp_mod(a, m, c)  Compute c = a (mod m).  Result will always be 0 <= c < m. */mp_err mp_mod(mp_int *a, mp_int *m, mp_int *c){  mp_err  res;  int     mag;  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);  if(SIGN(m) == MP_NEG)    return MP_RANGE;  /*     If |a| > m, we need to divide to get the remainder and take the     absolute value.       If |a| < m, we don't need to do any division, just copy and adjust     the sign (if a is negative).     If |a| == m, we can simply set the result to zero.     This order is intended to minimize the average path length of the     comparison chain on common workloads -- the most frequent cases are     that |a| != m, so we do those first.   */  if((mag = s_mp_cmp(a, m)) > 0) {    if((res = mp_div(a, m, NULL, c)) != MP_OKAY)      return res;        if(SIGN(c) == MP_NEG) {      if((res = mp_add(c, m, c)) != MP_OKAY)	return res;    }  } else if(mag < 0) {    if((res = mp_copy(a, c)) != MP_OKAY)      return res;    if(mp_cmp_z(a) < 0) {      if((res = mp_add(c, m, c)) != MP_OKAY)	return res;    }      } else {    mp_zero(c);  }  return MP_OKAY;} /* end mp_mod() *//* }}} *//* {{{ mp_mod_d(a, d, c) *//*  mp_mod_d(a, d, c)  Compute c = a (mod d).  Result will always be 0 <= c < d */mp_err mp_mod_d(mp_int *a, mp_digit d, mp_digit *c){  mp_err   res;  mp_digit rem;  ARGCHK(a != NULL && c != NULL, MP_BADARG);  if(s_mp_cmp_d(a, d) > 0) {    if((res = mp_div_d(a, d, NULL, &rem)) != MP_OKAY)      return res;  } else {    if(SIGN(a) == MP_NEG)      rem = d - DIGIT(a, 0);    else      rem = DIGIT(a, 0);  }  if(c)    *c = rem;  return MP_OKAY;} /* end mp_mod_d() *//* }}} *//* {{{ mp_sqrt(a, b) *//*  mp_sqrt(a, b)  Compute the integer square root of a, and store the result in b.  Uses an integer-arithmetic version of Newton's iterative linear  approximation technique to determine this value; the result has the  following two properties:     b^2 <= a     (b+1)^2 >= a  It is a range error to pass a negative value. */mp_err mp_sqrt(mp_int *a, mp_int *b){  mp_int   x, t;  mp_err   res;  ARGCHK(a != NULL && b != NULL, MP_BADARG);  /* Cannot take square root of a negative value */  if(SIGN(a) == MP_NEG)    return MP_RANGE;  /* Special cases for zero and one, trivial     */  if(mp_cmp_d(a, 0) == MP_EQ || mp_cmp_d(a, 1) == MP_EQ)     return mp_copy(a, b);      /* Initialize the temporaries we'll use below  */  if((res = mp_init_size(&t, USED(a))) != MP_OKAY)    return res;  /* Compute an initial guess for the iteration as a itself */  if((res = mp_init_copy(&x, a)) != MP_OKAY)    goto X;s_mp_rshd(&x, (USED(&x)/2)+1);mp_add_d(&x, 1, &x);  for(;;) {    /* t = (x * x) - a */    mp_copy(&x, &t);      /* can't fail, t is big enough for original x */    if((res = mp_sqr(&t, &t)) != MP_OKAY ||       (res = mp_sub(&t, a, &t)) != MP_OKAY)      goto CLEANUP;    /* t = t / 2x       */    s_mp_mul_2(&x);    if((res = mp_div(&t, &x, &t, NULL)) != MP_OKAY)      goto CLEANUP;    s_mp_div_2(&x);    /* Terminate the loop, if the quotient is zero */    if(mp_cmp_z(&t) == MP_EQ)      break;    /* x = x - t       */    if((res = mp_sub(&x, &t, &x)) != MP_OKAY)      goto CLEANUP;  }  /* Copy result to output parameter */  mp_sub_d(&x, 1, &x);  s_mp_exch(&x, b); CLEANUP:  mp_clear(&x); X:  mp_clear(&t);   return res;} /* end mp_sqrt() *//* }}} *//* }}} *//*------------------------------------------------------------------------*//* {{{ Modular arithmetic */#if MP_MODARITH/* {{{ mp_addmod(a, b, m, c) *//*  mp_addmod(a, b, m, c)  Compute c = (a + b) mod m */mp_err mp_addmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);  if((res = mp_add(a, b, c)) != MP_OKAY)    return res;  if((res = mp_mod(c, m, c)) != MP_OKAY)    return res;  return MP_OKAY;}/* }}} *//* {{{ mp_submod(a, b, m, c) *//*  mp_submod(a, b, m, c)  Compute c = (a - b) mod m */mp_err mp_submod(mp_int *a, mp_int *b, mp_int *m, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);  if((res = mp_sub(a, b, c)) != MP_OKAY)    return res;  if((res = mp_mod(c, m, c)) != MP_OKAY)    return res;  return MP_OKAY;}/* }}} *//* {{{ mp_mulmod(a, b, m, c) *//*  mp_mulmod(a, b, m, c)  Compute c = (a * b) mod m */mp_err mp_mulmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && b != NULL && m != NULL && c != NULL, MP_BADARG);  if((res = mp_mul(a, b, c)) != MP_OKAY)    return res;  if((res = mp_mod(c, m, c)) != MP_OKAY)    return res;  return MP_OKAY;}/* }}} *//* {{{ mp_sqrmod(a, m, c) */#if MP_SQUAREmp_err mp_sqrmod(mp_int *a, mp_int *m, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && m != NULL && c != NULL, MP_BADARG);  if((res = mp_sqr(a, c)) != MP_OKAY)    return res;  if((res = mp_mod(c, m, c)) != MP_OKAY)    return res;  return MP_OKAY;} /* end mp_sqrmod() */#endif/* }}} *//* {{{ mp_exptmod(a, b, m, c) *//*  mp_exptmod(a, b, m, c)  Compute c = (a ** b) mod m.  Uses a standard square-and-multiply  method with modular reductions at each step. (This is basically the  same code as mp_expt(), except for the addition of the reductions)    The modular reductions are done using Barrett's algorithm (see  s_mp_reduce() below for details) */mp_err mp_exptmod(mp_int *a, mp_int *b, mp_int *m, mp_int *c){  mp_int   s, x, mu;  mp_err   res;  mp_digit d, *db = DIGITS(b);  mp_size  ub = USED(b);  int      dig, bit;  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);  if(mp_cmp_z(b) < 0 || mp_cmp_z(m) <= 0)    return MP_RANGE;  if((res = mp_init(&s)) != MP_OKAY)    return res;  if((res = mp_init_copy(&x, a)) != MP_OKAY)    goto X;  if((res = mp_mod(&x, m, &x)) != MP_OKAY ||     (res = mp_init(&mu)) != MP_OKAY)    goto MU;  mp_set(&s, 1);  /* mu = b^2k / m */  s_mp_add_d(&mu, 1);   s_mp_lshd(&mu, 2 * USED(m));  if((res = mp_div(&mu, m, &mu, NULL)) != MP_OKAY)    goto CLEANUP;  /* Loop over digits of b in ascending order, except highest order */  for(dig = 0; dig < (ub - 1); dig++) {    d = *db++;    /* Loop over the bits of the lower-order digits */    for(bit = 0; bit < DIGIT_BIT; bit++) {      if(d & 1) {	if((res = s_mp_mul(&s, &x)) != MP_OKAY)	  goto CLEANUP;	if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)	  goto CLEANUP;      }      d >>= 1;      if((res = s_mp_sqr(&x)) != MP_OKAY)	goto CLEANUP;      if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)	goto CLEANUP;    }  }  /* Now do the last digit... */  d = *db;  while(d) {    if(d & 1) {      if((res = s_mp_mul(&s, &x)) != MP_OKAY)	goto CLEANUP;      if((res = s_mp_reduce(&s, m, &mu)) != MP_OKAY)	goto CLEANUP;    }    d >>= 1;    if((res = s_mp_sqr(&x)) != MP_OKAY)      goto CLEANUP;    if((res = s_mp_reduce(&x, m, &mu)) != MP_OKAY)      goto CLEANUP;  }  s_mp_exch(&s, c); CLEANUP:  mp_clear(&mu); MU:  mp_clear(&x); X:  mp_clear(&s);  return res;} /* end mp_exptmod() *//* }}} *//* {{{ mp_exptmod_d(a, d, m, c) */mp_err mp_exptmod_d(mp_int *a, mp_digit d, mp_int *m, mp_int *c){  mp_int   s, x;  mp_err   res;  ARGCHK(a != NULL && c != NULL, MP_BADARG);  if((res = mp_init(&s)) != MP_OKAY)    return res;  if((res = mp_init_copy(&x, a)) != MP_OKAY)    goto X;  mp_set(&s, 1);  while(d != 0) {    if(d & 1) {      if((res = s_mp_mul(&s, &x)) != MP_OKAY ||	 (res = mp_mod(&s, m, &s)) != MP_OKAY)	goto CLEANUP;    }    d /= 2;    if((res = s_mp_sqr(&x)) != MP_OKAY ||       (res = mp_mod(&x, m, &x)) != MP_OKAY)      goto CLEANUP;  }  s_mp_exch(&s, c);CLEANUP:  mp_clear(&x);X:  mp_clear(&s);  return res;} /* end mp_exptmod_d() *//* }}} */#endif /* if MP_MODARITH *//* }}} *//*------------------------------------------------------------------------*//* {{{ Comparison functions *//* {{{ mp_cmp_z(a) *//*  mp_cmp_z(a)  Compare a <=> 0.  Returns <0 if a<0, 0 if a=0, >0 if a>0. */int    mp_cmp_z(mp_int *a){  if(SIGN(a) == MP_NEG)    return MP_LT;  else if(USED(a) == 1 && DIGIT(a, 0) == 0)    return MP_EQ;  else    return MP_GT;} /* end mp_cmp_z() *//* }}} *//* {{{ mp_cmp_d(a, d) *//*  mp_cmp_d(a, d)  Compare a <=> d.  Returns <0 if a<d, 0 if a=d, >0 if a>d */int    mp_cmp_d(mp_int *a, mp_digit d){  ARGCHK(a != NULL, MP_EQ);  if(SIGN(a) == MP_NEG)    return MP_LT;  return s_mp_cmp_d(a, d);} /* end mp_cmp_d() *//* }}} *//* {{{ mp_cmp(a, b) */int    mp_cmp(mp_int *a, mp_int *b){  ARGCHK(a != NULL && b != NULL, MP_EQ);  if(SIGN(a) == SIGN(b)) {    int  mag;    if((mag = s_mp_cmp(a, b)) == MP_EQ)      return MP_EQ;    if(SIGN(a) == MP_ZPOS)      return mag;    else      return -mag;  } else if(SIGN(a) == MP_ZPOS) {    return MP_GT;  } else {    return MP_LT;  }} /* end mp_cmp() *//* }}} *//* {{{ mp_cmp_mag(a, b) *//*  mp_cmp_mag(a, b)  Compares |a| <=> |b|, and returns an appropriate comparison result */int    mp_cmp_mag(mp_int *a, mp_int *b){  ARGCHK(a != NULL && b != NULL, MP_EQ);  return s_mp_cmp(a, b);} /* end mp_cmp_mag() *//* }}} *//* {{{ mp_cmp_int(a, z) *//*  This just converts z to an mp_int, and uses the existing comparison  routines.  This is sort of inefficient, but it's not clear to me how  frequently this wil get used anyway.  For small positive constants,  you can always use mp_cmp_d(), and for zero, there is mp_cmp_z(). */int    mp_cmp_int(mp_int *a, long z){  mp_int  tmp;  int     out;  ARGCHK(a != NULL, MP_EQ);    mp_init(&tmp); mp_set_int(&tmp, z);  out = mp_cmp(a, &tmp);  mp_clear(&tmp);  return out;} /* end mp_cmp_int() *//* }}} *//* {{{ mp_isodd(a) *//*  mp_isodd(a)  Returns a true (non-zero) value if a is odd, false (zero) otherwise. */int    mp_isodd(mp_int *a){  ARGCHK(a != NULL, 0);  return (DIGIT(a, 0) & 1);} /* end mp_isodd() *//* }}} *//* {{{ mp_iseven(a) */int    mp_iseven(mp_int *a){  return !mp_isodd(a);} /* end mp_iseven() *//* }}} *//* }}} *//*------------------------------------------------------------------------*//* {{{ Number theoretic functions */#if MP_NUMTH/* {{{ mp_gcd(a, b, c) *//*  Like the old mp_gcd() function, except computes the GCD using the  binary algorithm due to Josef Stein in 1961 (via Knuth). */mp_err mp_gcd(mp_int *a, mp_int *b, mp_int *c){  mp_err   res;  mp_int   u, v, t;  mp_size  k = 0;  ARGCHK(a != NULL && b != NULL && c != NULL, MP_BADARG);  if(mp_cmp_z(a) == MP_EQ && mp_cmp_z(b) == MP_EQ)      return MP_RANGE;  if(mp_cmp_z(a) == MP_EQ) {    return mp_copy(b, c);  } else if(mp_cmp_z(b) == MP_EQ) {    return mp_copy(a, c);  }  if((res = mp_init(&t)) != MP_OKAY)    return res;  if((res = mp_init_copy(&u, a)) != MP_OKAY)    goto U;  if((res = mp_init_copy(&v, b)) != MP_OKAY)    goto V;  SIGN(&u) = MP_ZPOS;  SIGN(&v) = MP_ZPOS;  /* Divide out common factors of 2 until at least 1 of a, b is even */  while(mp_iseven(&u) && mp_iseven(&v)) {    s_mp_div_2(&u);    s_mp_div_2(&v);    ++k;  }  /* Initialize t */  if(mp_isodd(&u)) {    if((res = mp_copy(&v, &t)) != MP_OKAY)      goto CLEANUP;        /* t = -v */    if(SIGN(&v) == MP_ZPOS)      SIGN(&t) = MP_NEG;    else      SIGN(&t) = MP_ZPOS;    

⌨️ 快捷键说明

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