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

📄 mpi.c

📁 Dropbear is an SSH 2 server, designed to be usable in small memory environments. It supports:
💻 C
📖 第 1 页 / 共 5 页
字号:
/* }}} *//* {{{ mp_strerror(ec) *//*  mp_strerror(ec)  Return a string describing the meaning of error code 'ec'.  The  string returned is allocated in static memory, so the caller should  not attempt to modify or free the memory associated with this  string. */const char  *mp_strerror(mp_err ec){  int   aec = (ec < 0) ? -ec : ec;  /* Code values are negative, so the senses of these comparisons     are accurate */  if(ec < MP_LAST_CODE || ec > MP_OKAY) {    return mp_err_string[0];  /* unknown error code */  } else {    return mp_err_string[aec + 1];  }} /* end mp_strerror() *//* }}} *//*========================================================================*//*------------------------------------------------------------------------*//* Static function definitions (internal use only)                        *//* {{{ Memory management *//* {{{ s_mp_grow(mp, min) *//* Make sure there are at least 'min' digits allocated to mp              */mp_err   s_mp_grow(mp_int *mp, mp_size min){  if(min > ALLOC(mp)) {    mp_digit   *tmp;    /* Set min to next nearest default precision block size */    min = ((min + (s_mp_defprec - 1)) / s_mp_defprec) * s_mp_defprec;    if((tmp = s_mp_alloc(min, sizeof(mp_digit))) == NULL)      return MP_MEM;    s_mp_copy(DIGITS(mp), tmp, USED(mp));#if MP_CRYPTO    s_mp_setz(DIGITS(mp), ALLOC(mp));#endif    s_mp_free(DIGITS(mp));    DIGITS(mp) = tmp;    ALLOC(mp) = min;  }  return MP_OKAY;} /* end s_mp_grow() *//* }}} *//* {{{ s_mp_pad(mp, min) *//* Make sure the used size of mp is at least 'min', growing if needed     */mp_err   s_mp_pad(mp_int *mp, mp_size min){  if(min > USED(mp)) {    mp_err  res;    /* Make sure there is room to increase precision  */    if(min > ALLOC(mp) && (res = s_mp_grow(mp, min)) != MP_OKAY)      return res;    /* Increase precision; should already be 0-filled */    USED(mp) = min;  }  return MP_OKAY;} /* end s_mp_pad() *//* }}} *//* {{{ s_mp_setz(dp, count) */#if MP_MACRO == 0/* Set 'count' digits pointed to by dp to be zeroes                       */void s_mp_setz(mp_digit *dp, mp_size count){#if MP_MEMSET == 0  int  ix;  for(ix = 0; ix < count; ix++)    dp[ix] = 0;#else  memset(dp, 0, count * sizeof(mp_digit));#endif} /* end s_mp_setz() */#endif/* }}} *//* {{{ s_mp_copy(sp, dp, count) */#if MP_MACRO == 0/* Copy 'count' digits from sp to dp                                      */void s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count){#if MP_MEMCPY == 0  int  ix;  for(ix = 0; ix < count; ix++)    dp[ix] = sp[ix];#else  memcpy(dp, sp, count * sizeof(mp_digit));#endif} /* end s_mp_copy() */#endif/* }}} *//* {{{ s_mp_alloc(nb, ni) */#if MP_MACRO == 0/* Allocate ni records of nb bytes each, and return a pointer to that     */void    *s_mp_alloc(size_t nb, size_t ni){  return calloc(nb, ni);} /* end s_mp_alloc() */#endif/* }}} *//* {{{ s_mp_free(ptr) */#if MP_MACRO == 0/* Free the memory pointed to by ptr                                      */void     s_mp_free(void *ptr){  if(ptr)    free(ptr);} /* end s_mp_free() */#endif/* }}} *//* {{{ s_mp_clamp(mp) *//* Remove leading zeroes from the given value                             */void     s_mp_clamp(mp_int *mp){  mp_size   du = USED(mp);  mp_digit *zp = DIGITS(mp) + du - 1;  while(du > 1 && !*zp--)    --du;  USED(mp) = du;} /* end s_mp_clamp() *//* }}} *//* {{{ s_mp_exch(a, b) *//* Exchange the data for a and b; (b, a) = (a, b)                         */void     s_mp_exch(mp_int *a, mp_int *b){  mp_int   tmp;  tmp = *a;  *a = *b;  *b = tmp;} /* end s_mp_exch() *//* }}} *//* }}} *//* {{{ Arithmetic helpers *//* {{{ s_mp_lshd(mp, p) *//*    Shift mp leftward by p digits, growing if needed, and zero-filling   the in-shifted digits at the right end.  This is a convenient   alternative to multiplication by powers of the radix */   mp_err   s_mp_lshd(mp_int *mp, mp_size p){  mp_err   res;  mp_size  pos;  mp_digit *dp;  int     ix;  if(p == 0)    return MP_OKAY;  if((res = s_mp_pad(mp, USED(mp) + p)) != MP_OKAY)    return res;  pos = USED(mp) - 1;  dp = DIGITS(mp);  /* Shift all the significant figures over as needed */  for(ix = pos - p; ix >= 0; ix--)     dp[ix + p] = dp[ix];  /* Fill the bottom digits with zeroes */  for(ix = 0; ix < p; ix++)    dp[ix] = 0;  return MP_OKAY;} /* end s_mp_lshd() *//* }}} *//* {{{ s_mp_rshd(mp, p) *//*    Shift mp rightward by p digits.  Maintains the invariant that   digits above the precision are all zero.  Digits shifted off the   end are lost.  Cannot fail. */void     s_mp_rshd(mp_int *mp, mp_size p){  mp_size  ix;  mp_digit *dp;  if(p == 0)    return;  /* Shortcut when all digits are to be shifted off */  if(p >= USED(mp)) {    s_mp_setz(DIGITS(mp), ALLOC(mp));    USED(mp) = 1;    SIGN(mp) = MP_ZPOS;    return;  }  /* Shift all the significant figures over as needed */  dp = DIGITS(mp);  for(ix = p; ix < USED(mp); ix++)    dp[ix - p] = dp[ix];  /* Fill the top digits with zeroes */  ix -= p;  while(ix < USED(mp))    dp[ix++] = 0;  /* Strip off any leading zeroes    */  s_mp_clamp(mp);} /* end s_mp_rshd() *//* }}} *//* {{{ s_mp_div_2(mp) *//* Divide by two -- take advantage of radix properties to do it fast      */void     s_mp_div_2(mp_int *mp){  s_mp_div_2d(mp, 1);} /* end s_mp_div_2() *//* }}} *//* {{{ s_mp_mul_2(mp) */mp_err s_mp_mul_2(mp_int *mp){  int      ix;  mp_digit kin = 0, kout, *dp = DIGITS(mp);  mp_err   res;  /* Shift digits leftward by 1 bit */  for(ix = 0; ix < USED(mp); ix++) {    kout = (dp[ix] >> (DIGIT_BIT - 1)) & 1;    dp[ix] = (dp[ix] << 1) | kin;    kin = kout;  }  /* Deal with rollover from last digit */  if(kin) {    if(ix >= ALLOC(mp)) {      if((res = s_mp_grow(mp, ALLOC(mp) + 1)) != MP_OKAY)	return res;      dp = DIGITS(mp);    }    dp[ix] = kin;    USED(mp) += 1;  }  return MP_OKAY;} /* end s_mp_mul_2() *//* }}} *//* {{{ s_mp_mod_2d(mp, d) *//*  Remainder the integer by 2^d, where d is a number of bits.  This  amounts to a bitwise AND of the value, and does not require the full  division code */void     s_mp_mod_2d(mp_int *mp, mp_digit d){  unsigned int  ndig = (d / DIGIT_BIT), nbit = (d % DIGIT_BIT);  unsigned int  ix;  mp_digit      dmask, *dp = DIGITS(mp);  if(ndig >= USED(mp))    return;  /* Flush all the bits above 2^d in its digit */  dmask = (1 << nbit) - 1;  dp[ndig] &= dmask;  /* Flush all digits above the one with 2^d in it */  for(ix = ndig + 1; ix < USED(mp); ix++)    dp[ix] = 0;  s_mp_clamp(mp);} /* end s_mp_mod_2d() *//* }}} *//* {{{ s_mp_mul_2d(mp, d) *//*  Multiply by the integer 2^d, where d is a number of bits.  This  amounts to a bitwise shift of the value, and does not require the  full multiplication code. */mp_err    s_mp_mul_2d(mp_int *mp, mp_digit d){  mp_err   res;  mp_digit save, next, mask, *dp;  mp_size  used;  int      ix;  if((res = s_mp_lshd(mp, d / DIGIT_BIT)) != MP_OKAY)    return res;  dp = DIGITS(mp); used = USED(mp);  d %= DIGIT_BIT;  mask = (1 << d) - 1;  /* If the shift requires another digit, make sure we've got one to     work with */  if((dp[used - 1] >> (DIGIT_BIT - d)) & mask) {    if((res = s_mp_grow(mp, used + 1)) != MP_OKAY)      return res;    dp = DIGITS(mp);  }  /* Do the shifting... */  save = 0;  for(ix = 0; ix < used; ix++) {    next = (dp[ix] >> (DIGIT_BIT - d)) & mask;    dp[ix] = (dp[ix] << d) | save;    save = next;  }  /* If, at this point, we have a nonzero carryout into the next     digit, we'll increase the size by one digit, and store it...   */  if(save) {    dp[used] = save;    USED(mp) += 1;  }  s_mp_clamp(mp);  return MP_OKAY;} /* end s_mp_mul_2d() *//* }}} *//* {{{ s_mp_div_2d(mp, d) *//*  Divide the integer by 2^d, where d is a number of bits.  This  amounts to a bitwise shift of the value, and does not require the  full division code (used in Barrett reduction, see below) */void     s_mp_div_2d(mp_int *mp, mp_digit d){  int       ix;  mp_digit  save, next, mask, *dp = DIGITS(mp);  s_mp_rshd(mp, d / DIGIT_BIT);  d %= DIGIT_BIT;  mask = (1 << d) - 1;  save = 0;  for(ix = USED(mp) - 1; ix >= 0; ix--) {    next = dp[ix] & mask;    dp[ix] = (dp[ix] >> d) | (save << (DIGIT_BIT - d));    save = next;  }  s_mp_clamp(mp);} /* end s_mp_div_2d() *//* }}} *//* {{{ s_mp_norm(a, b) *//*  s_mp_norm(a, b)  Normalize a and b for division, where b is the divisor.  In order  that we might make good guesses for quotient digits, we want the  leading digit of b to be at least half the radix, which we  accomplish by multiplying a and b by a constant.  This constant is  returned (so that it can be divided back out of the remainder at the  end of the division process).  We multiply by the smallest power of 2 that gives us a leading digit  at least half the radix.  By choosing a power of 2, we simplify the   multiplication and division steps to simple shifts. */mp_digit s_mp_norm(mp_int *a, mp_int *b){  mp_digit  t, d = 0;  t = DIGIT(b, USED(b) - 1);  while(t < (RADIX / 2)) {    t <<= 1;    ++d;  }      if(d != 0) {    s_mp_mul_2d(a, d);    s_mp_mul_2d(b, d);  }  return d;} /* end s_mp_norm() *//* }}} *//* }}} *//* {{{ Primitive digit arithmetic *//* {{{ s_mp_add_d(mp, d) *//* Add d to |mp| in place                                                 */mp_err   s_mp_add_d(mp_int *mp, mp_digit d)    /* unsigned digit addition */{  mp_word   w, k = 0;  mp_size   ix = 1, used = USED(mp);  mp_digit *dp = DIGITS(mp);  w = dp[0] + d;  dp[0] = ACCUM(w);  k = CARRYOUT(w);  while(ix < used && k) {    w = dp[ix] + k;    dp[ix] = ACCUM(w);    k = CARRYOUT(w);    ++ix;  }  if(k != 0) {    mp_err  res;    if((res = s_mp_pad(mp, USED(mp) + 1)) != MP_OKAY)      return res;    DIGIT(mp, ix) = k;  }  return MP_OKAY;} /* end s_mp_add_d() *//* }}} *//* {{{ s_mp_sub_d(mp, d) *//* Subtract d from |mp| in place, assumes |mp| > d                        */mp_err   s_mp_sub_d(mp_int *mp, mp_digit d)    /* unsigned digit subtract */{  mp_word   w, b = 0;  mp_size   ix = 1, used = USED(mp);  mp_digit *dp = DIGITS(mp);  /* Compute initial subtraction    */  w = (RADIX + dp[0]) - d;  b = CARRYOUT(w) ? 0 : 1;  dp[0] = ACCUM(w);  /* Propagate borrows leftward     */  while(b && ix < used) {    w = (RADIX + dp[ix]) - b;    b = CARRYOUT(w) ? 0 : 1;    dp[ix] = ACCUM(w);    ++ix;  }  /* Remove leading zeroes          */  s_mp_clamp(mp);  /* If we have a borrow out, it's a violation of the input invariant */  if(b)    return MP_RANGE;  else    return MP_OKAY;} /* end s_mp_sub_d() *//* }}} *//* {{{ s_mp_mul_d(a, d) *//* Compute a = a * d, single digit multiplication                         */mp_err   s_mp_mul_d(mp_int *a, mp_digit d){  mp_word w, k = 0;  mp_size ix, max;  mp_err  res;  mp_digit *dp = DIGITS(a);  /*    Single-digit multiplication will increase the precision of the    output by at most one digit.  However, we can detect when this    will happen -- if the high-order digit of a, times d, gives a    two-digit result, then the precision of the result will increase;    otherwise it won't.  We use this fact to avoid calling s_mp_pad()    unless absolutely necessary.   */  max = USED(a);  w = dp[max - 1] * d;  if(CARRYOUT(w) != 0) {    if((res = s_mp_pad(a, max + 1)) != MP_OKAY)      return res;    dp = DIGITS(a);  }  for(ix = 0; ix < max; ix++) {    w = (dp[ix] * d) + k;    dp[ix] = ACCUM(w);    k = CARRYOUT(w);  }  /* If there is a precision increase, take care of it here; the above     test guarantees we have enough storage to do this safely.   */  if(k) {    dp[max] = k;     USED(a) = max + 1;  }  s_mp_clamp(a);  return MP_OKAY;  } /* end s_mp_mul_d() *//* }}} *//* {{{ s_mp_div_d(mp, d, r) *//*  s_mp_div_d(mp, d, r)  Compute the quotient mp = mp / d and remainder r = mp mod d, for a  single digit d.  If r is null, the remainder will be discarded. */mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r){  mp_word   w = 0, t;  mp_int    quot;  mp_err    res;  mp_digit *dp = DIGITS(mp), *qp;  int       ix;  if(d == 0)    return MP_RANGE;  /* Make room for the quotient */  if((res = mp_init_size(&quot, USED(mp))) != MP_OKAY)    return res;  USED(&quot) = USED(mp); /* so clamping will work below */  qp = DIGITS(&quot);  /* Divide without subtraction */  for(ix = USED(mp) - 1; ix >= 0; ix--) {    w = (w << DIGIT_BIT) | dp[ix];    if(w >= d) {      t = w / d;      w = w % d;    } else {      t = 0;    }    qp[ix] = t;  }  /* Deliver the remainder, if desired */  if(r)    *r = w;  s_mp_clamp(&quot);  mp_exch(&quot, mp);  mp_clear(&quot);  return MP_OKAY;} /* end s_mp_div_d() *//* }}} *//* }}} *//* {{{ Primitive full arithmetic *//* {{{ s_mp_add(a, b) *//* Compute a = |a| + |b|                                                  */mp_err   s_mp_add(mp_int *a, mp_int *b)        /* magnitude addition      */{  mp_word   w = 0;  mp_digit *pa, *pb;  mp_size   ix

⌨️ 快捷键说明

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