]>
Commit | Line | Data |
---|---|---|
949c1ebb PW |
1 | // Copyright (c) 2013-2014 Pieter Wuille |
2 | // Distributed under the MIT software license, see the accompanying | |
0a433ea2 PW |
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 | |
04e34d18 | 72 | } secp256k1_ecmult_consts_t; |
65a79b30 | 73 | |
f491cd35 | 74 | static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL; |
b1483f87 PW |
75 | |
76 | static void secp256k1_ecmult_start(void) { | |
77 | if (secp256k1_ecmult_consts != NULL) | |
78 | return; | |
79 | ||
c259a7cb | 80 | // Allocate the precomputation table. |
b1483f87 | 81 | secp256k1_ecmult_consts_t *ret = (secp256k1_ecmult_consts_t*)malloc(sizeof(secp256k1_ecmult_consts_t)); |
b1483f87 PW |
82 | |
83 | // get the generator | |
84 | const secp256k1_ge_t *g = &secp256k1_ge_consts->g; | |
f16be77f | 85 | secp256k1_gej_t gj; secp256k1_gej_set_ge(&gj, g); |
b1483f87 PW |
86 | |
87 | // calculate 2^128*generator | |
f16be77f | 88 | secp256k1_gej_t g_128j = gj; |
b1483f87 PW |
89 | for (int i=0; i<128; i++) |
90 | secp256k1_gej_double(&g_128j, &g_128j); | |
b1483f87 PW |
91 | |
92 | // precompute the tables with odd multiples | |
f16be77f PD |
93 | secp256k1_ecmult_table_precomp_ge(ret->pre_g, &gj, WINDOW_G); |
94 | secp256k1_ecmult_table_precomp_ge(ret->pre_g_128, &g_128j, WINDOW_G); | |
c259a7cb PW |
95 | |
96 | // Set the global pointer to the precomputation table. | |
97 | secp256k1_ecmult_consts = ret; | |
04e34d18 PW |
98 | } |
99 | ||
b1483f87 PW |
100 | static void secp256k1_ecmult_stop(void) { |
101 | if (secp256k1_ecmult_consts == NULL) | |
102 | return; | |
607884fc | 103 | |
f491cd35 | 104 | secp256k1_ecmult_consts_t *c = (secp256k1_ecmult_consts_t*)secp256k1_ecmult_consts; |
b1483f87 | 105 | secp256k1_ecmult_consts = NULL; |
c259a7cb | 106 | free(c); |
b1483f87 | 107 | } |
607884fc | 108 | |
b1483f87 PW |
109 | /** Convert a number to WNAF notation. The number becomes represented by sum(2^i * wnaf[i], i=0..bits), |
110 | * with the following guarantees: | |
111 | * - each wnaf[i] is either 0, or an odd integer between -(1<<(w-1) - 1) and (1<<(w-1) - 1) | |
112 | * - two non-zero entries in wnaf are separated by at least w-1 zeroes. | |
113 | * - the index of the highest non-zero entry in wnaf (=return value-1) is at most bits, where | |
114 | * bits is the number of bits necessary to represent the absolute value of the input. | |
115 | */ | |
116 | static int secp256k1_ecmult_wnaf(int *wnaf, const secp256k1_num_t *a, int w) { | |
117 | int ret = 0; | |
118 | int zeroes = 0; | |
119 | secp256k1_num_t x; | |
120 | secp256k1_num_init(&x); | |
121 | secp256k1_num_copy(&x, a); | |
122 | int sign = 1; | |
123 | if (secp256k1_num_is_neg(&x)) { | |
124 | sign = -1; | |
125 | secp256k1_num_negate(&x); | |
607884fc | 126 | } |
b1483f87 PW |
127 | while (!secp256k1_num_is_zero(&x)) { |
128 | while (!secp256k1_num_is_odd(&x)) { | |
129 | zeroes++; | |
130 | secp256k1_num_shift(&x, 1); | |
607884fc | 131 | } |
b1483f87 PW |
132 | int word = secp256k1_num_shift(&x, w); |
133 | while (zeroes) { | |
134 | wnaf[ret++] = 0; | |
135 | zeroes--; | |
607884fc | 136 | } |
b1483f87 PW |
137 | if (word & (1 << (w-1))) { |
138 | secp256k1_num_inc(&x); | |
139 | wnaf[ret++] = sign * (word - (1 << w)); | |
140 | } else { | |
141 | wnaf[ret++] = sign * word; | |
0a07e62f | 142 | } |
b1483f87 | 143 | zeroes = w-1; |
607884fc | 144 | } |
b1483f87 PW |
145 | secp256k1_num_free(&x); |
146 | return ret; | |
607884fc PW |
147 | } |
148 | ||
b1483f87 PW |
149 | void static secp256k1_ecmult(secp256k1_gej_t *r, const secp256k1_gej_t *a, const secp256k1_num_t *na, const secp256k1_num_t *ng) { |
150 | const secp256k1_ecmult_consts_t *c = secp256k1_ecmult_consts; | |
151 | ||
399c03f2 | 152 | #ifdef USE_ENDOMORPHISM |
b1483f87 | 153 | secp256k1_num_t na_1, na_lam; |
b1483f87 PW |
154 | secp256k1_num_init(&na_1); |
155 | secp256k1_num_init(&na_lam); | |
b1483f87 PW |
156 | // split na into na_1 and na_lam (where na = na_1 + na_lam*lambda, and na_1 and na_lam are ~128 bit) |
157 | secp256k1_gej_split_exp(&na_1, &na_lam, na); | |
b1483f87 | 158 | |
399c03f2 | 159 | // build wnaf representation for na_1 and na_lam. |
b1483f87 PW |
160 | int wnaf_na_1[129]; int bits_na_1 = secp256k1_ecmult_wnaf(wnaf_na_1, &na_1, WINDOW_A); |
161 | int wnaf_na_lam[129]; int bits_na_lam = secp256k1_ecmult_wnaf(wnaf_na_lam, &na_lam, WINDOW_A); | |
399c03f2 PW |
162 | int bits = bits_na_1; |
163 | if (bits_na_lam > bits) bits = bits_na_lam; | |
399c03f2 PW |
164 | #else |
165 | // build wnaf representation for na. | |
166 | int wnaf_na[257]; int bits_na = secp256k1_ecmult_wnaf(wnaf_na, na, WINDOW_A); | |
167 | int bits = bits_na; | |
168 | #endif | |
b1483f87 | 169 | |
399c03f2 PW |
170 | // calculate odd multiples of a |
171 | secp256k1_gej_t pre_a[ECMULT_TABLE_SIZE(WINDOW_A)]; | |
172 | secp256k1_ecmult_table_precomp_gej(pre_a, a, WINDOW_A); | |
173 | ||
d7fd4d0f PD |
174 | #ifdef USE_ENDOMORPHISM |
175 | secp256k1_gej_t pre_a_lam[ECMULT_TABLE_SIZE(WINDOW_A)]; | |
176 | for (int i=0; i<ECMULT_TABLE_SIZE(WINDOW_A); i++) | |
177 | secp256k1_gej_mul_lambda(&pre_a_lam[i], &pre_a[i]); | |
178 | #endif | |
179 | ||
399c03f2 PW |
180 | // Splitted G factors. |
181 | secp256k1_num_t ng_1, ng_128; | |
182 | secp256k1_num_init(&ng_1); | |
183 | secp256k1_num_init(&ng_128); | |
184 | ||
185 | // 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) | |
186 | secp256k1_num_split(&ng_1, &ng_128, ng, 128); | |
187 | ||
188 | // Build wnaf representation for ng_1 and ng_128 | |
189 | int wnaf_ng_1[129]; int bits_ng_1 = secp256k1_ecmult_wnaf(wnaf_ng_1, &ng_1, WINDOW_G); | |
190 | int wnaf_ng_128[129]; int bits_ng_128 = secp256k1_ecmult_wnaf(wnaf_ng_128, &ng_128, WINDOW_G); | |
eb0be8ee PW |
191 | if (bits_ng_1 > bits) bits = bits_ng_1; |
192 | if (bits_ng_128 > bits) bits = bits_ng_128; | |
b1483f87 PW |
193 | |
194 | secp256k1_gej_set_infinity(r); | |
f11ff5be PW |
195 | secp256k1_gej_t tmpj; |
196 | secp256k1_ge_t tmpa; | |
607884fc | 197 | |
b1483f87 PW |
198 | for (int i=bits-1; i>=0; i--) { |
199 | secp256k1_gej_double(r, r); | |
200 | int n; | |
399c03f2 | 201 | #ifdef USE_ENDOMORPHISM |
b1483f87 | 202 | if (i < bits_na_1 && (n = wnaf_na_1[i])) { |
399c03f2 | 203 | ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); |
b1483f87 | 204 | secp256k1_gej_add(r, r, &tmpj); |
607884fc | 205 | } |
b1483f87 PW |
206 | if (i < bits_na_lam && (n = wnaf_na_lam[i])) { |
207 | ECMULT_TABLE_GET_GEJ(&tmpj, pre_a_lam, n, WINDOW_A); | |
208 | secp256k1_gej_add(r, r, &tmpj); | |
607884fc | 209 | } |
399c03f2 PW |
210 | #else |
211 | if (i < bits_na && (n = wnaf_na[i])) { | |
212 | ECMULT_TABLE_GET_GEJ(&tmpj, pre_a, n, WINDOW_A); | |
213 | secp256k1_gej_add(r, r, &tmpj); | |
214 | } | |
215 | #endif | |
b1483f87 PW |
216 | if (i < bits_ng_1 && (n = wnaf_ng_1[i])) { |
217 | ECMULT_TABLE_GET_GE(&tmpa, c->pre_g, n, WINDOW_G); | |
218 | secp256k1_gej_add_ge(r, r, &tmpa); | |
607884fc | 219 | } |
b1483f87 PW |
220 | if (i < bits_ng_128 && (n = wnaf_ng_128[i])) { |
221 | ECMULT_TABLE_GET_GE(&tmpa, c->pre_g_128, n, WINDOW_G); | |
222 | secp256k1_gej_add_ge(r, r, &tmpa); | |
607884fc PW |
223 | } |
224 | } | |
4adf6b2a | 225 | |
399c03f2 | 226 | #ifdef USE_ENDOMORPHISM |
b1483f87 PW |
227 | secp256k1_num_free(&na_1); |
228 | secp256k1_num_free(&na_lam); | |
399c03f2 | 229 | #endif |
b1483f87 PW |
230 | secp256k1_num_free(&ng_1); |
231 | secp256k1_num_free(&ng_128); | |
607884fc | 232 | } |
7a4b7691 PW |
233 | |
234 | #endif |