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

📄 mpi.c

📁 Dropbear is an SSH 2 server, designed to be usable in small memory environments. It supports:
💻 C
📖 第 1 页 / 共 5 页
字号:
/*    mpi.c    by Michael J. Fromberger <sting@linguist.dartmouth.edu>    Copyright (C) 1998 Michael J. Fromberger, All Rights Reserved    Arbitrary precision integer arithmetic library    $Id: mpi.c,v 1.22 2001/09/14 15:11:20 sting Exp sting $ */#include "mpi.h"#include <stdlib.h>#include <string.h>#include <ctype.h>#if MP_DEBUG#include <stdio.h>#define DIAG(T,V) {fprintf(stderr,T);mp_print(V,stderr);fputc('\n',stderr);}#else#define DIAG(T,V)#endif/*    If MP_LOGTAB is not defined, use the math library to compute the   logarithms on the fly.  Otherwise, use the static table below.   Pick which works best for your system. */#if MP_LOGTAB/* {{{ s_logv_2[] - log table for 2 in various bases *//*  A table of the logs of 2 for various bases (the 0 and 1 entries of  this table are meaningless and should not be referenced).    This table is used to compute output lengths for the mp_toradix()  function.  Since a number n in radix r takes up about log_r(n)  digits, we estimate the output size by taking the least integer  greater than log_r(n), where:  log_r(n) = log_2(n) * log_r(2)  This table, therefore, is a table of log_r(2) for 2 <= r <= 36,  which are the output bases supported.   */#include "logtab.h"/* }}} */#define LOG_V_2(R)  s_logv_2[(R)]#else#include <math.h>#define LOG_V_2(R)  (log(2.0)/log(R))#endif/* Default precision for newly created mp_int's      */static unsigned int s_mp_defprec = MP_DEFPREC;/* {{{ Digit arithmetic macros *//*  When adding and multiplying digits, the results can be larger than  can be contained in an mp_digit.  Thus, an mp_word is used.  These  macros mask off the upper and lower digits of the mp_word (the  mp_word may be more than 2 mp_digits wide, but we only concern  ourselves with the low-order 2 mp_digits)  If your mp_word DOES have more than 2 mp_digits, you need to  uncomment the first line, and comment out the second. *//* #define  CARRYOUT(W)  (((W)>>DIGIT_BIT)&MP_DIGIT_MAX) */#define  CARRYOUT(W)  ((W)>>DIGIT_BIT)#define  ACCUM(W)     ((W)&MP_DIGIT_MAX)/* }}} *//* {{{ Comparison constants */#define  MP_LT       -1#define  MP_EQ        0#define  MP_GT        1/* }}} *//* {{{ Constant strings *//* Constant strings returned by mp_strerror() */static const char *mp_err_string[] = {  "unknown result code",     /* say what?            */  "boolean true",            /* MP_OKAY, MP_YES      */  "boolean false",           /* MP_NO                */  "out of memory",           /* MP_MEM               */  "argument out of range",   /* MP_RANGE             */  "invalid input parameter", /* MP_BADARG            */  "result is undefined"      /* MP_UNDEF             */};/* Value to digit maps for radix conversion   *//* s_dmap_1 - standard digits and letters */static const char *s_dmap_1 =   "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz+/";#if 0/* s_dmap_2 - base64 ordering for digits  */static const char *s_dmap_2 =  "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";#endif/* }}} *//* {{{ Static function declarations *//*    If MP_MACRO is false, these will be defined as actual functions;   otherwise, suitable macro definitions will be used.  This works   around the fact that ANSI C89 doesn't support an 'inline' keyword   (although I hear C9x will ... about bloody time).  At present, the   macro definitions are identical to the function bodies, but they'll   expand in place, instead of generating a function call.   I chose these particular functions to be made into macros because   some profiling showed they are called a lot on a typical workload,   and yet they are primarily housekeeping. */#if MP_MACRO == 0 void     s_mp_setz(mp_digit *dp, mp_size count); /* zero digits           */ void     s_mp_copy(mp_digit *sp, mp_digit *dp, mp_size count); /* copy    */ void    *s_mp_alloc(size_t nb, size_t ni);       /* general allocator     */ void     s_mp_free(void *ptr);                   /* general free function */#else /* Even if these are defined as macros, we need to respect the settings    of the MP_MEMSET and MP_MEMCPY configuration options...  */ #if MP_MEMSET == 0  #define  s_mp_setz(dp, count) \       {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=0;} #else  #define  s_mp_setz(dp, count) memset(dp, 0, (count) * sizeof(mp_digit)) #endif /* MP_MEMSET */ #if MP_MEMCPY == 0  #define  s_mp_copy(sp, dp, count) \       {int ix;for(ix=0;ix<(count);ix++)(dp)[ix]=(sp)[ix];} #else  #define  s_mp_copy(sp, dp, count) memcpy(dp, sp, (count) * sizeof(mp_digit)) #endif /* MP_MEMCPY */ #define  s_mp_alloc(nb, ni)  calloc(nb, ni) #define  s_mp_free(ptr) {if(ptr) free(ptr);}#endif /* MP_MACRO */mp_err   s_mp_grow(mp_int *mp, mp_size min);   /* increase allocated size */mp_err   s_mp_pad(mp_int *mp, mp_size min);    /* left pad with zeroes    */void     s_mp_clamp(mp_int *mp);               /* clip leading zeroes     */void     s_mp_exch(mp_int *a, mp_int *b);      /* swap a and b in place   */mp_err   s_mp_lshd(mp_int *mp, mp_size p);     /* left-shift by p digits  */void     s_mp_rshd(mp_int *mp, mp_size p);     /* right-shift by p digits */void     s_mp_div_2d(mp_int *mp, mp_digit d);  /* divide by 2^d in place  */void     s_mp_mod_2d(mp_int *mp, mp_digit d);  /* modulo 2^d in place     */mp_err   s_mp_mul_2d(mp_int *mp, mp_digit d);  /* multiply by 2^d in place*/void     s_mp_div_2(mp_int *mp);               /* divide by 2 in place    */mp_err   s_mp_mul_2(mp_int *mp);               /* multiply by 2 in place  */mp_digit s_mp_norm(mp_int *a, mp_int *b);      /* normalize for division  */mp_err   s_mp_add_d(mp_int *mp, mp_digit d);   /* unsigned digit addition */mp_err   s_mp_sub_d(mp_int *mp, mp_digit d);   /* unsigned digit subtract */mp_err   s_mp_mul_d(mp_int *mp, mp_digit d);   /* unsigned digit multiply */mp_err   s_mp_div_d(mp_int *mp, mp_digit d, mp_digit *r);		                               /* unsigned digit divide   */mp_err   s_mp_reduce(mp_int *x, mp_int *m, mp_int *mu);                                               /* Barrett reduction       */mp_err   s_mp_add(mp_int *a, mp_int *b);       /* magnitude addition      */mp_err   s_mp_sub(mp_int *a, mp_int *b);       /* magnitude subtract      */mp_err   s_mp_mul(mp_int *a, mp_int *b);       /* magnitude multiply      */#if 0void     s_mp_kmul(mp_digit *a, mp_digit *b, mp_digit *out, mp_size len);                                               /* multiply buffers in place */#endif#if MP_SQUAREmp_err   s_mp_sqr(mp_int *a);                  /* magnitude square        */#else#define  s_mp_sqr(a) s_mp_mul(a, a)#endifmp_err   s_mp_div(mp_int *a, mp_int *b);       /* magnitude divide        */mp_err   s_mp_2expt(mp_int *a, mp_digit k);    /* a = 2^k                 */int      s_mp_cmp(mp_int *a, mp_int *b);       /* magnitude comparison    */int      s_mp_cmp_d(mp_int *a, mp_digit d);    /* magnitude digit compare */int      s_mp_ispow2(mp_int *v);               /* is v a power of 2?      */int      s_mp_ispow2d(mp_digit d);             /* is d a power of 2?      */int      s_mp_tovalue(char ch, int r);          /* convert ch to value    */char     s_mp_todigit(int val, int r, int low); /* convert val to digit   */int      s_mp_outlen(int bits, int r);          /* output length in bytes *//* }}} *//* {{{ Default precision manipulation */unsigned int mp_get_prec(void){  return s_mp_defprec;} /* end mp_get_prec() */void         mp_set_prec(unsigned int prec){  if(prec == 0)    s_mp_defprec = MP_DEFPREC;  else    s_mp_defprec = prec;} /* end mp_set_prec() *//* }}} *//*------------------------------------------------------------------------*//* {{{ mp_init(mp) *//*  mp_init(mp)  Initialize a new zero-valued mp_int.  Returns MP_OKAY if successful,  MP_MEM if memory could not be allocated for the structure. */mp_err mp_init(mp_int *mp){  return mp_init_size(mp, s_mp_defprec);} /* end mp_init() *//* }}} *//* {{{ mp_init_array(mp[], count) */mp_err mp_init_array(mp_int mp[], int count){  mp_err  res;  int     pos;  ARGCHK(mp !=NULL && count > 0, MP_BADARG);  for(pos = 0; pos < count; ++pos) {    if((res = mp_init(&mp[pos])) != MP_OKAY)      goto CLEANUP;  }  return MP_OKAY; CLEANUP:  while(--pos >= 0)     mp_clear(&mp[pos]);  return res;} /* end mp_init_array() *//* }}} *//* {{{ mp_init_size(mp, prec) *//*  mp_init_size(mp, prec)  Initialize a new zero-valued mp_int with at least the given  precision; returns MP_OKAY if successful, or MP_MEM if memory could  not be allocated for the structure. */mp_err mp_init_size(mp_int *mp, mp_size prec){  ARGCHK(mp != NULL && prec > 0, MP_BADARG);  if((DIGITS(mp) = s_mp_alloc(prec, sizeof(mp_digit))) == NULL)    return MP_MEM;  SIGN(mp) = MP_ZPOS;  USED(mp) = 1;  ALLOC(mp) = prec;  return MP_OKAY;} /* end mp_init_size() *//* }}} *//* {{{ mp_init_copy(mp, from) *//*  mp_init_copy(mp, from)  Initialize mp as an exact copy of from.  Returns MP_OKAY if  successful, MP_MEM if memory could not be allocated for the new  structure. */mp_err mp_init_copy(mp_int *mp, mp_int *from){  ARGCHK(mp != NULL && from != NULL, MP_BADARG);  if(mp == from)    return MP_OKAY;  if((DIGITS(mp) = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)    return MP_MEM;  s_mp_copy(DIGITS(from), DIGITS(mp), USED(from));  USED(mp) = USED(from);  ALLOC(mp) = USED(from);  SIGN(mp) = SIGN(from);  return MP_OKAY;} /* end mp_init_copy() *//* }}} *//* {{{ mp_copy(from, to) *//*  mp_copy(from, to)  Copies the mp_int 'from' to the mp_int 'to'.  It is presumed that  'to' has already been initialized (if not, use mp_init_copy()  instead). If 'from' and 'to' are identical, nothing happens. */mp_err mp_copy(mp_int *from, mp_int *to){  ARGCHK(from != NULL && to != NULL, MP_BADARG);  if(from == to)    return MP_OKAY;  { /* copy */    mp_digit   *tmp;    /*      If the allocated buffer in 'to' already has enough space to hold      all the used digits of 'from', we'll re-use it to avoid hitting      the memory allocater more than necessary; otherwise, we'd have      to grow anyway, so we just allocate a hunk and make the copy as      usual     */    if(ALLOC(to) >= USED(from)) {      s_mp_setz(DIGITS(to) + USED(from), ALLOC(to) - USED(from));      s_mp_copy(DIGITS(from), DIGITS(to), USED(from));          } else {      if((tmp = s_mp_alloc(USED(from), sizeof(mp_digit))) == NULL)	return MP_MEM;      s_mp_copy(DIGITS(from), tmp, USED(from));      if(DIGITS(to) != NULL) {#if MP_CRYPTO	s_mp_setz(DIGITS(to), ALLOC(to));#endif	s_mp_free(DIGITS(to));      }      DIGITS(to) = tmp;      ALLOC(to) = USED(from);    }    /* Copy the precision and sign from the original */    USED(to) = USED(from);    SIGN(to) = SIGN(from);  } /* end copy */  return MP_OKAY;} /* end mp_copy() *//* }}} *//* {{{ mp_exch(mp1, mp2) *//*  mp_exch(mp1, mp2)  Exchange mp1 and mp2 without allocating any intermediate memory  (well, unless you count the stack space needed for this call and the  locals it creates...).  This cannot fail. */void mp_exch(mp_int *mp1, mp_int *mp2){#if MP_ARGCHK == 2  assert(mp1 != NULL && mp2 != NULL);#else  if(mp1 == NULL || mp2 == NULL)    return;#endif  s_mp_exch(mp1, mp2);} /* end mp_exch() *//* }}} *//* {{{ mp_clear(mp) *//*  mp_clear(mp)  Release the storage used by an mp_int, and void its fields so that  if someone calls mp_clear() again for the same int later, we won't  get tollchocked. */void   mp_clear(mp_int *mp){  if(mp == NULL)    return;  if(DIGITS(mp) != NULL) {#if MP_CRYPTO    s_mp_setz(DIGITS(mp), ALLOC(mp));#endif    s_mp_free(DIGITS(mp));    DIGITS(mp) = NULL;  }  USED(mp) = 0;  ALLOC(mp) = 0;} /* end mp_clear() *//* }}} *//* {{{ mp_clear_array(mp[], count) */void   mp_clear_array(mp_int mp[], int count){  ARGCHK(mp != NULL && count > 0, MP_BADARG);  while(--count >= 0)     mp_clear(&mp[count]);} /* end mp_clear_array() *//* }}} *//* {{{ mp_zero(mp) *//*  mp_zero(mp)   Set mp to zero.  Does not change the allocated size of the structure,  and therefore cannot fail (except on a bad argument, which we ignore) */void   mp_zero(mp_int *mp){  if(mp == NULL)    return;  s_mp_setz(DIGITS(mp), ALLOC(mp));  USED(mp) = 1;  SIGN(mp) = MP_ZPOS;} /* end mp_zero() *//* }}} *//* {{{ mp_set(mp, d) */void   mp_set(mp_int *mp, mp_digit d){  if(mp == NULL)    return;  mp_zero(mp);  DIGIT(mp, 0) = d;} /* end mp_set() *//* }}} *//* {{{ mp_set_int(mp, z) */mp_err mp_set_int(mp_int *mp, long z){  int            ix;  unsigned long  v = abs(z);  mp_err         res;  ARGCHK(mp != NULL, MP_BADARG);  mp_zero(mp);  if(z == 0)    return MP_OKAY;  /* shortcut for zero */  for(ix = sizeof(long) - 1; ix >= 0; ix--) {    if((res = s_mp_mul_2d(mp, CHAR_BIT)) != MP_OKAY)      return res;    res = s_mp_add_d(mp, 		     (mp_digit)((v >> (ix * CHAR_BIT)) & UCHAR_MAX));    if(res != MP_OKAY)      return res;  }  if(z < 0)    SIGN(mp) = MP_NEG;  return MP_OKAY;} /* end mp_set_int() *//* }}} *//*------------------------------------------------------------------------*//* {{{ Digit arithmetic *//* {{{ mp_add_d(a, d, b) *//*  mp_add_d(a, d, b)  Compute the sum b = a + d, for a single digit d.  Respects the sign of  its primary addend (single digits are unsigned anyway). */mp_err mp_add_d(mp_int *a, mp_digit d, mp_int *b){  mp_err   res = MP_OKAY;  ARGCHK(a != NULL && b != NULL, MP_BADARG);  if((res = mp_copy(a, b)) != MP_OKAY)    return res;  if(SIGN(b) == MP_ZPOS) {    res = s_mp_add_d(b, d);  } else if(s_mp_cmp_d(b, d) >= 0) {    res = s_mp_sub_d(b, d);  } else {    SIGN(b) = MP_ZPOS;    DIGIT(b, 0) = d - DIGIT(b, 0);  }  return res;} /* end mp_add_d() *//* }}} *//* {{{ mp_sub_d(a, d, b) *//*  mp_sub_d(a, d, b)  Compute the difference b = a - d, for a single digit d.  Respects the  sign of its subtrahend (single digits are unsigned anyway). */mp_err mp_sub_d(mp_int *a, mp_digit d, mp_int *b){  mp_err   res;  ARGCHK(a != NULL && b != NULL, MP_BADARG);  if((res = mp_copy(a, b)) != MP_OKAY)    return res;  if(SIGN(b) == MP_NEG) {    if((res = s_mp_add_d(b, d)) != MP_OKAY)      return res;  } else if(s_mp_cmp_d(b, d) >= 0) {    if((res = s_mp_sub_d(b, d)) != MP_OKAY)      return res;  } else {    mp_neg(b, b);    DIGIT(b, 0) = d - DIGIT(b, 0);    SIGN(b) = MP_NEG;  }  if(s_mp_cmp_d(b, 0) == 0)    SIGN(b) = MP_ZPOS;  return MP_OKAY;} /* end mp_sub_d() *//* }}} *//* {{{ mp_mul_d(a, d, b) *//*  mp_mul_d(a, d, b)  Compute the product b = a * d, for a single digit d.  Respects the sign  of its multiplicand (single digits are unsigned anyway) */mp_err mp_mul_d(mp_int *a, mp_digit d, mp_int *b){  mp_err  res;  ARGCHK(a != NULL && b != NULL, MP_BADARG);  if(d == 0) {    mp_zero(b);    return MP_OKAY;  }  if((res = mp_copy(a, b)) != MP_OKAY)    return res;  res = s_mp_mul_d(b, d);  return res;} /* end mp_mul_d() *//* }}} *//* {{{ mp_mul_2(a, c) */mp_err mp_mul_2(mp_int *a, mp_int *c){  mp_err  res;  ARGCHK(a != NULL && c != NULL, MP_BADARG);  if((res = mp_copy(a, c)) != MP_OKAY)    return res;  return s_mp_mul_2(c);} /* end mp_mul_2() *//* }}} *//* {{{ mp_div_d(a, d, q, r) *//*

⌨️ 快捷键说明

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