]>
Commit | Line | Data |
---|---|---|
0a433ea2 PW |
1 | // Copyright (c) 2013 Pieter Wuille |
2 | // Distributed under the MIT/X11 software license, see the accompanying | |
3 | // file COPYING or http://www.opensource.org/licenses/mit-license.php. | |
4 | ||
7a4b7691 PW |
5 | #ifndef _SECP256K1_ECMULT_IMPL_H_ |
6 | #define _SECP256K1_ECMULT_IMPL_H_ | |
7 | ||
0592d117 | 8 | #include <assert.h> |
11ab5622 PW |
9 | #include "num.h" |
10 | #include "group.h" | |
11 | #include "ecmult.h" | |
607884fc | 12 | |
eb0be8ee | 13 | // optimal for 128-bit and 256-bit exponents. |
607884fc PW |
14 | #define WINDOW_A 5 |
15 | ||
16 | // larger numbers may result in slightly better performance, at the cost of | |
eb0be8ee | 17 | // exponentially larger precomputed tables. WINDOW_G == 14 results in 640 KiB. |
607884fc PW |
18 | #define WINDOW_G 14 |
19 | ||
b1483f87 PW |
20 | /** Fill a table 'pre' with precomputed odd multiples of a. W determines the size of the table. |
21 | * pre will contains the values [1*a,3*a,5*a,...,(2^(w-1)-1)*a], so it needs place for | |
22 | * 2^(w-2) entries. | |
23 | * | |
24 | * There are two versions of this function: | |
25 | * - secp256k1_ecmult_precomp_wnaf_gej, which operates on group elements in jacobian notation, | |
26 | * fast to precompute, but slower to use in later additions. | |
27 | * - secp256k1_ecmult_precomp_wnaf_ge, which operates on group elements in affine notations, | |
28 | * (much) slower to precompute, but a bit faster to use in later additions. | |
29 | * To compute a*P + b*G, we use the jacobian version for P, and the affine version for G, as | |
30 | * G is constant, so it only needs to be done once in advance. | |
31 | */ | |
32 | void static secp256k1_ecmult_table_precomp_gej(secp256k1_gej_t *pre, const secp256k1_gej_t *a, int w) { | |
33 | pre[0] = *a; | |
34 | secp256k1_gej_t d; secp256k1_gej_double(&d, &pre[0]); | |
35 | for (int i=1; i<(1 << (w-2)); i++) | |
36 | secp256k1_gej_add(&pre[i], &d, &pre[i-1]); | |
37 | } | |
f11ff5be | 38 | |
f16be77f PD |
39 | void static secp256k1_ecmult_table_precomp_ge(secp256k1_ge_t *pre, const secp256k1_gej_t *a, int w) { |
40 | const int table_size = 1 << (w-2); | |
41 | secp256k1_gej_t prej[table_size]; | |
42 | prej[0] = *a; | |
43 | secp256k1_gej_t d; secp256k1_gej_double(&d, a); | |
44 | for (int i=1; i<table_size; i++) { | |
45 | secp256k1_gej_add(&prej[i], &d, &prej[i-1]); | |
f11ff5be | 46 | } |
f16be77f | 47 | secp256k1_ge_set_all_gej(table_size, pre, prej); |
b1483f87 | 48 | } |
f11ff5be | 49 | |
b1483f87 PW |
50 | /** The number of entries a table with precomputed multiples needs to have. */ |
51 | #define ECMULT_TABLE_SIZE(w) (1 << ((w)-2)) | |
52 | ||
53 | /** The following two macro retrieves a particular odd multiple from a table | |
54 | * of precomputed multiples. */ | |
55 | #define ECMULT_TABLE_GET(r,pre,n,w,neg) do { \ | |
1c7fa133 PW |
56 | VERIFY_CHECK(((n) & 1) == 1); \ |
57 | VERIFY_CHECK((n) >= -((1 << ((w)-1)) - 1)); \ | |
58 | VERIFY_CHECK((n) <= ((1 << ((w)-1)) - 1)); \ | |
b1483f87 PW |
59 | if ((n) > 0) \ |
60 | *(r) = (pre)[((n)-1)/2]; \ | |
61 | else \ | |
62 | (neg)((r), &(pre)[(-(n)-1)/2]); \ | |
63 | } while(0) | |
64 | ||
65 | #define ECMULT_TABLE_GET_GEJ(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_gej_neg) | |
66 | #define ECMULT_TABLE_GET_GE(r,pre,n,w) ECMULT_TABLE_GET((r),(pre),(n),(w),secp256k1_ge_neg) | |
67 | ||
68 | typedef struct { | |
65a79b30 | 69 | // For accelerating the computation of a*P + b*G: |
b1483f87 PW |
70 | secp256k1_ge_t pre_g[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of the generator |
71 | secp256k1_ge_t pre_g_128[ECMULT_TABLE_SIZE(WINDOW_G)]; // odd multiples of 2^128*generator | |
65a79b30 PW |
72 | |
73 | // For accelerating the computation of a*G: | |
74 | // To harden against timing attacks, use the following mechanism: | |
75 | // * Break up the multiplicand into groups of 4 bits, called n_0, n_1, n_2, ..., n_63. | |
76 | // * Compute sum((n_i + 1) * 16^i * G, i=0..63). | |
77 | // * Subtract sum(1 * 16^i * G, i=0..63). | |
78 | // For each i, and each of the 16 possible values of n_i, ((n_i + 1) * 16^i * G) is | |
79 | // precomputed (call it prec(i,n_i), as well as -sum(1 * 16^i * G) (called fin). | |
80 | // The formula now becomes sum(prec(i, n_i), i=0..63) + fin. | |
81 | // To make memory access uniform, the bytes of prec(i,n_i) are sliced per value of n_i. | |
82 | unsigned char prec[64][sizeof(secp256k1_ge_t)][16]; // prec[j][k][i] = k'th byte of (16^j * (i+1) * G) | |
b1483f87 PW |
83 | secp256k1_ge_t fin; // -(sum(prec[j][0], j=0..63)) |
84 | } secp256k1_ecmult_consts_t; | |
85 | ||
f491cd35 | 86 | static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL; |
b1483f87 PW |
87 | |
88 | static void secp256k1_ecmult_start(void) { | |
89 | if (secp256k1_ecmult_consts != NULL) | |
90 | return; | |
91 | ||
92 | secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t)); | |
93 | secp256k1_ecmult_consts = ret; | |
94 | ||
95 | // get the generator | |
96 | const secp256k1_ge_t *g = &secp256k1_ge_consts->g; | |
f16be77f | 97 | secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g); |
b1483f87 PW |
98 | |
99 | // calculate 2^128*generator | |
f16be77f | 100 | secp256k1_gej_t g_128j = gj; |
b1483f87 PW |
101 | for (int i=0; i<128; i++) |
102 | secp256k1_gej_double(&g_128j, &g_128j); | |
b1483f87 PW |
103 | |
104 | // precompute the tables with odd multiples | |
f16be77f PD |
105 | secp256k1_ecmult_table_precomp_ge(ret->pre_g, &gj, WINDOW_G); |
106 | secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128j, WINDOW_G); | |
b1483f87 PW |
107 | |
108 | // compute prec and fin | |
f16be77f PD |
109 | secp256k1_gej_t tj[961]; |
110 | int pos = 0; | |
b1483f87 | 111 | secp256k1_gej_t fn; secp256k1_gej_set_infinity(&fn); |
f16be77f PD |
112 | for (int j=0; j<64; j++) { |
113 | secp256k1_gej_add(&fn, &fn, &gj); | |
114 | secp256k1_gej_t adj = gj; | |
115 | for (int i=1; i<16; i++) { | |
116 | secp256k1_gej_add(&gj, &gj, &adj); | |
117 | tj[pos++] = gj; | |
118 | } | |
119 | } | |
1c7fa133 | 120 | VERIFY_CHECK(pos == 960); |
f16be77f PD |
121 | tj[pos] = fn; |
122 | secp256k1_ge_t t[961]; secp256k1_ge_set_all_gej(961, t, tj); | |
123 | pos = 0; | |
124 | const unsigned char *raw = (const unsigned char*)g; | |
b1483f87 | 125 | for (int j=0; j<64; j++) { |
65a79b30 | 126 | for (int k=0; k<sizeof(secp256k1_ge_t); k++) |
f16be77f | 127 | ret->prec[j][k][0] = raw[k]; |
b1483f87 | 128 | for (int i=1; i<16; i++) { |
f16be77f | 129 | raw = (const unsigned char*)(&t[pos++]); |
65a79b30 | 130 | for (int k=0; k<sizeof(secp256k1_ge_t); k++) |
f16be77f | 131 | ret->prec[j][k][i] = raw[k]; |
607884fc PW |
132 | } |
133 | } | |
1c7fa133 | 134 | VERIFY_CHECK(pos == 960); |
f16be77f | 135 | secp256k1_ge_neg(&ret->fin, &t[pos]); |
b1483f87 | 136 | } |
607884fc | 137 | |
b1483f87 PW |
138 | static void secp256k1_ecmult_stop(void) { |
139 | if (secp256k1_ecmult_consts == NULL) | |
140 | return; | |
607884fc | 141 | |
f491cd35 PW |
142 | secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts; |
143 | free(c); | |
b1483f87 PW |
144 | secp256k1_ecmult_consts = NULL; |
145 | } | |
607884fc | 146 | |
b1483f87 PW |
147 | /** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), |
148 | * with the following guarantees: | |
149 | * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) | |
150 | * - two non-zero entries in wnaf are separated by at least w-1 zeroes. | |
151 | * - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where | |
152 | * bits is the number of bits necessary to represent the absolute value of the input. | |
153 | */ | |
154 | static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) { | |
155 | int ret = 0; | |
156 | int zeroes = 0; | |
157 | secp256k1_num_t x; | |
158 | secp256k1_num_init(&x); | |
159 | secp256k1_num_copy(&x, a); | |
160 | int sign = 1; | |
161 | if (secp256k1_num_is_neg(&x)) { | |
162 | sign = -1; | |
163 | secp256k1_num_negate(&x); | |
607884fc | 164 | } |
b1483f87 PW |
165 | while (!secp256k1_num_is_zero(&x)) { |
166 | while (!secp256k1_num_is_odd(&x)) { | |
167 | zeroes++; | |
168 | secp256k1_num_shift(&x, 1); | |
607884fc | 169 | } |
b1483f87 PW |
170 | int word = secp256k1_num_shift(&x, w); |
171 | while (zeroes) { | |
172 | wnaf[ret++] = 0; | |
173 | zeroes--; | |
607884fc | 174 | } |
b1483f87 PW |
175 | if (word & (1 << (w-1))) { |
176 | secp256k1_num_inc(&x); | |
177 | wnaf[ret++] = sign * (word - (1 << w)); | |
178 | } else { | |
179 | wnaf[ret++] = sign * word; | |
0a07e62f | 180 | } |
b1483f87 | 181 | zeroes = w-1; |
607884fc | 182 | } |
b1483f87 PW |
183 | secp256k1_num_free(&x); |
184 | return ret; | |
607884fc PW |
185 | } |
186 | ||
b1483f87 | 187 | void static secp256k1_ecmult_gen(secp256k1_gej_t *r, const secp256k1_num_t *gn) { |
4adf6b2a PW |
188 | secp256k1_num_t n; |
189 | secp256k1_num_init(&n); | |
b1483f87 PW |
190 | secp256k1_num_copy(&n, gn); |
191 | const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; | |
65a79b30 | 192 | secp256k1_gej_set_infinity(r); |
2f6c8019 GM |
193 | secp256k1_ge_t add; |
194 | int bits; | |
65a79b30 | 195 | for (int j=0; j<64; j++) { |
2f6c8019 | 196 | bits = secp256k1_num_shift(&n, 4); |
65a79b30 PW |
197 | for (int k=0; k<sizeof(secp256k1_ge_t); k++) |
198 | ((unsigned char*)(&add))[k] = c->prec[j][k][bits]; | |
199 | secp256k1_gej_add_ge(r, r, &add); | |
200 | } | |
2f6c8019 GM |
201 | bits = 0; |
202 | secp256k1_ge_clear(&add); | |
203 | secp256k1_num_clear(&n); | |
4adf6b2a | 204 | secp256k1_num_free(&n); |
b1483f87 | 205 | secp256k1_gej_add_ge(r, r, &c->fin); |
0a07e62f PW |
206 | } |
207 | ||
b1483f87 PW |
208 | void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) { |
209 | const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; | |
210 | ||
399c03f2 | 211 | #ifdef USE_ENDOMORPHISM |
b1483f87 | 212 | secp256k1_num_t na_1, na_lam; |
b1483f87 PW |
213 | secp256k1_num_init(&na_1); |
214 | secp256k1_num_init(&na_lam); | |
b1483f87 PW |
215 | // split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) |
216 | secp256k1_gej_split_exp(&na_1, &na_lam, na); | |
b1483f87 | 217 | |
399c03f2 | 218 | // build wnaf representation for na_1 and na_lam. |
b1483f87 PW |
219 | int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); |
220 | int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A); | |
399c03f2 PW |
221 | int bits = bits_na_1; |
222 | if (bits_na_lam > bits) bits = bits_na_lam; | |
399c03f2 PW |
223 | #else |
224 | // build wnaf representation for na. | |
225 | int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); | |
226 | int bits = bits_na; | |
227 | #endif | |
b1483f87 | 228 | |
399c03f2 PW |
229 | // calculate odd multiples of a |
230 | secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; | |
231 | secp256k1_ecmult_table_precomp_gej(pre_a, a, WINDOW_A); | |
232 | ||
d7fd4d0f PD |
233 | #ifdef USE_ENDOMORPHISM |
234 | secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; | |
235 | for (int i=0; i<ECMULT_TABLE_SIZE(WINDOW_A); i++) | |
236 | secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]); | |
237 | #endif | |
238 | ||
399c03f2 PW |
239 | // Splitted G factors. |
240 | secp256k1_num_t ng_1, ng_128; | |
241 | secp256k1_num_init(&ng_1); | |
242 | secp256k1_num_init(&ng_128); | |
243 | ||
244 | // split ng into ng_1 and ng_128 (where gn = gn_1 + gn_128*2^128, and gn_1 and gn_128 are ~128 bit) | |
245 | secp256k1_num_split(&ng_1, &ng_128, ng, 128); | |
246 | ||
247 | // Build wnaf representation for ng_1 and ng_128 | |
248 | int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); | |
249 | int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G); | |
eb0be8ee PW |
250 | if (bits_ng_1 > bits) bits = bits_ng_1; |
251 | if (bits_ng_128 > bits) bits = bits_ng_128; | |
b1483f87 PW |
252 | |
253 | secp256k1_gej_set_infinity(r); | |
f11ff5be PW |
254 | secp256k1_gej_t tmpj; |
255 | secp256k1_ge_t tmpa; | |
607884fc | 256 | |
b1483f87 PW |
257 | for (int i=bits-1; i>=0; i--) { |
258 | secp256k1_gej_double(r, r); | |
259 | int n; | |
399c03f2 | 260 | #ifdef USE_ENDOMORPHISM |
b1483f87 | 261 | if (i < bits_na_1 && (n = wnaf_na_1[i])) { |
399c03f2 | 262 | ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); |
b1483f87 | 263 | secp256k1_gej_add(r, r, &tmpj); |
607884fc | 264 | } |
b1483f87 PW |
265 | if (i < bits_na_lam && (n = wnaf_na_lam[i])) { |
266 | ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A); | |
267 | secp256k1_gej_add(r, r, &tmpj); | |
607884fc | 268 | } |
399c03f2 PW |
269 | #else |
270 | if (i < bits_na && (n = wnaf_na[i])) { | |
271 | ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); | |
272 | secp256k1_gej_add(r, r, &tmpj); | |
273 | } | |
274 | #endif | |
b1483f87 PW |
275 | if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { |
276 | ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G); | |
277 | secp256k1_gej_add_ge(r, r, &tmpa); | |
607884fc | 278 | } |
b1483f87 PW |
279 | if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { |
280 | ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G); | |
281 | secp256k1_gej_add_ge(r, r, &tmpa); | |
607884fc PW |
282 | } |
283 | } | |
4adf6b2a | 284 | |
399c03f2 | 285 | #ifdef USE_ENDOMORPHISM |
b1483f87 PW |
286 | secp256k1_num_free(&na_1); |
287 | secp256k1_num_free(&na_lam); | |
399c03f2 | 288 | #endif |
b1483f87 PW |
289 | secp256k1_num_free(&ng_1); |
290 | secp256k1_num_free(&ng_128); | |
607884fc | 291 | } |
7a4b7691 PW |
292 | |
293 | #endif |