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