]> Git Repo - secp256k1.git/blame - src/ecmult_impl.h
Split up ecmult and ecmult_gen entirely
[secp256k1.git] / src / ecmult_impl.h
CommitLineData
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 */
32void 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
39void 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
68typedef 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 74static const secp256k1_ecmult_consts_t *secp256k1_ecmult_consts = NULL;
b1483f87
PW
75
76static 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
100static 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 */
116static 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
149void 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
This page took 0.062252 seconds and 4 git commands to generate.