github.com/ethereumproject/go-ethereum@v5.5.2+incompatible/crypto/secp256k1/libsecp256k1/src/num_gmp_impl.h (about)

     1  /**********************************************************************
     2   * Copyright (c) 2013, 2014 Pieter Wuille                             *
     3   * Distributed under the MIT software license, see the accompanying   *
     4   * file COPYING or http://www.opensource.org/licenses/mit-license.php.*
     5   **********************************************************************/
     6  
     7  #ifndef _SECP256K1_NUM_REPR_IMPL_H_
     8  #define _SECP256K1_NUM_REPR_IMPL_H_
     9  
    10  #include <string.h>
    11  #include <stdlib.h>
    12  #include <gmp.h>
    13  
    14  #include "util.h"
    15  #include "num.h"
    16  
    17  #ifdef VERIFY
    18  static void secp256k1_num_sanity(const secp256k1_num *a) {
    19      VERIFY_CHECK(a->limbs == 1 || (a->limbs > 1 && a->data[a->limbs-1] != 0));
    20  }
    21  #else
    22  #define secp256k1_num_sanity(a) do { } while(0)
    23  #endif
    24  
    25  static void secp256k1_num_copy(secp256k1_num *r, const secp256k1_num *a) {
    26      *r = *a;
    27  }
    28  
    29  static void secp256k1_num_get_bin(unsigned char *r, unsigned int rlen, const secp256k1_num *a) {
    30      unsigned char tmp[65];
    31      int len = 0;
    32      int shift = 0;
    33      if (a->limbs>1 || a->data[0] != 0) {
    34          len = mpn_get_str(tmp, 256, (mp_limb_t*)a->data, a->limbs);
    35      }
    36      while (shift < len && tmp[shift] == 0) shift++;
    37      VERIFY_CHECK(len-shift <= (int)rlen);
    38      memset(r, 0, rlen - len + shift);
    39      if (len > shift) {
    40          memcpy(r + rlen - len + shift, tmp + shift, len - shift);
    41      }
    42      memset(tmp, 0, sizeof(tmp));
    43  }
    44  
    45  static void secp256k1_num_set_bin(secp256k1_num *r, const unsigned char *a, unsigned int alen) {
    46      int len;
    47      VERIFY_CHECK(alen > 0);
    48      VERIFY_CHECK(alen <= 64);
    49      len = mpn_set_str(r->data, a, alen, 256);
    50      if (len == 0) {
    51          r->data[0] = 0;
    52          len = 1;
    53      }
    54      VERIFY_CHECK(len <= NUM_LIMBS*2);
    55      r->limbs = len;
    56      r->neg = 0;
    57      while (r->limbs > 1 && r->data[r->limbs-1]==0) {
    58          r->limbs--;
    59      }
    60  }
    61  
    62  static void secp256k1_num_add_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
    63      mp_limb_t c = mpn_add(r->data, a->data, a->limbs, b->data, b->limbs);
    64      r->limbs = a->limbs;
    65      if (c != 0) {
    66          VERIFY_CHECK(r->limbs < 2*NUM_LIMBS);
    67          r->data[r->limbs++] = c;
    68      }
    69  }
    70  
    71  static void secp256k1_num_sub_abs(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
    72      mp_limb_t c = mpn_sub(r->data, a->data, a->limbs, b->data, b->limbs);
    73      VERIFY_CHECK(c == 0);
    74      r->limbs = a->limbs;
    75      while (r->limbs > 1 && r->data[r->limbs-1]==0) {
    76          r->limbs--;
    77      }
    78  }
    79  
    80  static void secp256k1_num_mod(secp256k1_num *r, const secp256k1_num *m) {
    81      secp256k1_num_sanity(r);
    82      secp256k1_num_sanity(m);
    83  
    84      if (r->limbs >= m->limbs) {
    85          mp_limb_t t[2*NUM_LIMBS];
    86          mpn_tdiv_qr(t, r->data, 0, r->data, r->limbs, m->data, m->limbs);
    87          memset(t, 0, sizeof(t));
    88          r->limbs = m->limbs;
    89          while (r->limbs > 1 && r->data[r->limbs-1]==0) {
    90              r->limbs--;
    91          }
    92      }
    93  
    94      if (r->neg && (r->limbs > 1 || r->data[0] != 0)) {
    95          secp256k1_num_sub_abs(r, m, r);
    96          r->neg = 0;
    97      }
    98  }
    99  
   100  static void secp256k1_num_mod_inverse(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *m) {
   101      int i;
   102      mp_limb_t g[NUM_LIMBS+1];
   103      mp_limb_t u[NUM_LIMBS+1];
   104      mp_limb_t v[NUM_LIMBS+1];
   105      mp_size_t sn;
   106      mp_size_t gn;
   107      secp256k1_num_sanity(a);
   108      secp256k1_num_sanity(m);
   109  
   110      /** mpn_gcdext computes: (G,S) = gcdext(U,V), where
   111       *  * G = gcd(U,V)
   112       *  * G = U*S + V*T
   113       *  * U has equal or more limbs than V, and V has no padding
   114       *  If we set U to be (a padded version of) a, and V = m:
   115       *    G = a*S + m*T
   116       *    G = a*S mod m
   117       *  Assuming G=1:
   118       *    S = 1/a mod m
   119       */
   120      VERIFY_CHECK(m->limbs <= NUM_LIMBS);
   121      VERIFY_CHECK(m->data[m->limbs-1] != 0);
   122      for (i = 0; i < m->limbs; i++) {
   123          u[i] = (i < a->limbs) ? a->data[i] : 0;
   124          v[i] = m->data[i];
   125      }
   126      sn = NUM_LIMBS+1;
   127      gn = mpn_gcdext(g, r->data, &sn, u, m->limbs, v, m->limbs);
   128      VERIFY_CHECK(gn == 1);
   129      VERIFY_CHECK(g[0] == 1);
   130      r->neg = a->neg ^ m->neg;
   131      if (sn < 0) {
   132          mpn_sub(r->data, m->data, m->limbs, r->data, -sn);
   133          r->limbs = m->limbs;
   134          while (r->limbs > 1 && r->data[r->limbs-1]==0) {
   135              r->limbs--;
   136          }
   137      } else {
   138          r->limbs = sn;
   139      }
   140      memset(g, 0, sizeof(g));
   141      memset(u, 0, sizeof(u));
   142      memset(v, 0, sizeof(v));
   143  }
   144  
   145  static int secp256k1_num_is_zero(const secp256k1_num *a) {
   146      return (a->limbs == 1 && a->data[0] == 0);
   147  }
   148  
   149  static int secp256k1_num_is_neg(const secp256k1_num *a) {
   150      return (a->limbs > 1 || a->data[0] != 0) && a->neg;
   151  }
   152  
   153  static int secp256k1_num_cmp(const secp256k1_num *a, const secp256k1_num *b) {
   154      if (a->limbs > b->limbs) {
   155          return 1;
   156      }
   157      if (a->limbs < b->limbs) {
   158          return -1;
   159      }
   160      return mpn_cmp(a->data, b->data, a->limbs);
   161  }
   162  
   163  static int secp256k1_num_eq(const secp256k1_num *a, const secp256k1_num *b) {
   164      if (a->limbs > b->limbs) {
   165          return 0;
   166      }
   167      if (a->limbs < b->limbs) {
   168          return 0;
   169      }
   170      if ((a->neg && !secp256k1_num_is_zero(a)) != (b->neg && !secp256k1_num_is_zero(b))) {
   171          return 0;
   172      }
   173      return mpn_cmp(a->data, b->data, a->limbs) == 0;
   174  }
   175  
   176  static void secp256k1_num_subadd(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b, int bneg) {
   177      if (!(b->neg ^ bneg ^ a->neg)) { /* a and b have the same sign */
   178          r->neg = a->neg;
   179          if (a->limbs >= b->limbs) {
   180              secp256k1_num_add_abs(r, a, b);
   181          } else {
   182              secp256k1_num_add_abs(r, b, a);
   183          }
   184      } else {
   185          if (secp256k1_num_cmp(a, b) > 0) {
   186              r->neg = a->neg;
   187              secp256k1_num_sub_abs(r, a, b);
   188          } else {
   189              r->neg = b->neg ^ bneg;
   190              secp256k1_num_sub_abs(r, b, a);
   191          }
   192      }
   193  }
   194  
   195  static void secp256k1_num_add(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
   196      secp256k1_num_sanity(a);
   197      secp256k1_num_sanity(b);
   198      secp256k1_num_subadd(r, a, b, 0);
   199  }
   200  
   201  static void secp256k1_num_sub(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
   202      secp256k1_num_sanity(a);
   203      secp256k1_num_sanity(b);
   204      secp256k1_num_subadd(r, a, b, 1);
   205  }
   206  
   207  static void secp256k1_num_mul(secp256k1_num *r, const secp256k1_num *a, const secp256k1_num *b) {
   208      mp_limb_t tmp[2*NUM_LIMBS+1];
   209      secp256k1_num_sanity(a);
   210      secp256k1_num_sanity(b);
   211  
   212      VERIFY_CHECK(a->limbs + b->limbs <= 2*NUM_LIMBS+1);
   213      if ((a->limbs==1 && a->data[0]==0) || (b->limbs==1 && b->data[0]==0)) {
   214          r->limbs = 1;
   215          r->neg = 0;
   216          r->data[0] = 0;
   217          return;
   218      }
   219      if (a->limbs >= b->limbs) {
   220          mpn_mul(tmp, a->data, a->limbs, b->data, b->limbs);
   221      } else {
   222          mpn_mul(tmp, b->data, b->limbs, a->data, a->limbs);
   223      }
   224      r->limbs = a->limbs + b->limbs;
   225      if (r->limbs > 1 && tmp[r->limbs - 1]==0) {
   226          r->limbs--;
   227      }
   228      VERIFY_CHECK(r->limbs <= 2*NUM_LIMBS);
   229      mpn_copyi(r->data, tmp, r->limbs);
   230      r->neg = a->neg ^ b->neg;
   231      memset(tmp, 0, sizeof(tmp));
   232  }
   233  
   234  static void secp256k1_num_shift(secp256k1_num *r, int bits) {
   235      if (bits % GMP_NUMB_BITS) {
   236          /* Shift within limbs. */
   237          mpn_rshift(r->data, r->data, r->limbs, bits % GMP_NUMB_BITS);
   238      }
   239      if (bits >= GMP_NUMB_BITS) {
   240          int i;
   241          /* Shift full limbs. */
   242          for (i = 0; i < r->limbs; i++) {
   243              int index = i + (bits / GMP_NUMB_BITS);
   244              if (index < r->limbs && index < 2*NUM_LIMBS) {
   245                  r->data[i] = r->data[index];
   246              } else {
   247                  r->data[i] = 0;
   248              }
   249          }
   250      }
   251      while (r->limbs>1 && r->data[r->limbs-1]==0) {
   252          r->limbs--;
   253      }
   254  }
   255  
   256  static void secp256k1_num_negate(secp256k1_num *r) {
   257      r->neg ^= 1;
   258  }
   259  
   260  #endif