]> Git Repo - secp256k1.git/blame - src/field_impl.h
Implement endomorphism optimization for secp256k1_ecmult_const
[secp256k1.git] / src / field_impl.h
CommitLineData
71712b27
GM
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 **********************************************************************/
0a433ea2 6
7a4b7691
PW
7#ifndef _SECP256K1_FIELD_IMPL_H_
8#define _SECP256K1_FIELD_IMPL_H_
9
78cd96b1
CF
10#if defined HAVE_CONFIG_H
11#include "libsecp256k1-config.h"
12#endif
13
1c7fa133
PW
14#include "util.h"
15
7277fd76 16#if defined(USE_FIELD_10X26)
11ab5622 17#include "field_10x26_impl.h"
f0c89aad 18#elif defined(USE_FIELD_5X52)
11ab5622 19#include "field_5x52_impl.h"
f0c89aad
PW
20#else
21#error "Please select field implementation"
ea165f47 22#endif
fba1d58d 23
d7174edf
PW
24SECP256K1_INLINE static int secp256k1_fe_equal_var(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
25 secp256k1_fe_t na;
26 secp256k1_fe_negate(&na, a, 1);
27 secp256k1_fe_add(&na, b);
49ee0dbe 28 return secp256k1_fe_normalizes_to_zero_var(&na);
d7174edf
PW
29}
30
39bd94d8 31static int secp256k1_fe_sqrt_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
25b35c7e
GM
32 secp256k1_fe_t x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
33 int j;
f8ccd9be 34
71712b27
GM
35 /** The binary representation of (p + 1)/4 has 3 blocks of 1s, with lengths in
36 * { 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
37 * 1, [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
38 */
f8ccd9be 39
f8ccd9be
PD
40 secp256k1_fe_sqr(&x2, a);
41 secp256k1_fe_mul(&x2, &x2, a);
42
f8ccd9be
PD
43 secp256k1_fe_sqr(&x3, &x2);
44 secp256k1_fe_mul(&x3, &x3, a);
45
25b35c7e 46 x6 = x3;
26320197
GM
47 for (j=0; j<3; j++) {
48 secp256k1_fe_sqr(&x6, &x6);
49 }
f8ccd9be
PD
50 secp256k1_fe_mul(&x6, &x6, &x3);
51
25b35c7e 52 x9 = x6;
26320197
GM
53 for (j=0; j<3; j++) {
54 secp256k1_fe_sqr(&x9, &x9);
55 }
f8ccd9be
PD
56 secp256k1_fe_mul(&x9, &x9, &x3);
57
25b35c7e 58 x11 = x9;
26320197
GM
59 for (j=0; j<2; j++) {
60 secp256k1_fe_sqr(&x11, &x11);
61 }
f8ccd9be
PD
62 secp256k1_fe_mul(&x11, &x11, &x2);
63
25b35c7e 64 x22 = x11;
26320197
GM
65 for (j=0; j<11; j++) {
66 secp256k1_fe_sqr(&x22, &x22);
67 }
f8ccd9be
PD
68 secp256k1_fe_mul(&x22, &x22, &x11);
69
25b35c7e 70 x44 = x22;
26320197
GM
71 for (j=0; j<22; j++) {
72 secp256k1_fe_sqr(&x44, &x44);
73 }
f8ccd9be
PD
74 secp256k1_fe_mul(&x44, &x44, &x22);
75
25b35c7e 76 x88 = x44;
26320197
GM
77 for (j=0; j<44; j++) {
78 secp256k1_fe_sqr(&x88, &x88);
79 }
f8ccd9be
PD
80 secp256k1_fe_mul(&x88, &x88, &x44);
81
25b35c7e 82 x176 = x88;
26320197
GM
83 for (j=0; j<88; j++) {
84 secp256k1_fe_sqr(&x176, &x176);
85 }
f8ccd9be
PD
86 secp256k1_fe_mul(&x176, &x176, &x88);
87
25b35c7e 88 x220 = x176;
26320197
GM
89 for (j=0; j<44; j++) {
90 secp256k1_fe_sqr(&x220, &x220);
91 }
f8ccd9be
PD
92 secp256k1_fe_mul(&x220, &x220, &x44);
93
25b35c7e 94 x223 = x220;
26320197
GM
95 for (j=0; j<3; j++) {
96 secp256k1_fe_sqr(&x223, &x223);
97 }
f8ccd9be
PD
98 secp256k1_fe_mul(&x223, &x223, &x3);
99
71712b27 100 /* The final result is then assembled using a sliding window over the blocks. */
f8ccd9be 101
25b35c7e 102 t1 = x223;
26320197
GM
103 for (j=0; j<23; j++) {
104 secp256k1_fe_sqr(&t1, &t1);
105 }
f8ccd9be 106 secp256k1_fe_mul(&t1, &t1, &x22);
26320197
GM
107 for (j=0; j<6; j++) {
108 secp256k1_fe_sqr(&t1, &t1);
109 }
f8ccd9be
PD
110 secp256k1_fe_mul(&t1, &t1, &x2);
111 secp256k1_fe_sqr(&t1, &t1);
112 secp256k1_fe_sqr(r, &t1);
09ca4f32 113
71712b27 114 /* Check that a square root was actually calculated */
09ca4f32
PD
115
116 secp256k1_fe_sqr(&t1, r);
70ae0d28 117 return secp256k1_fe_equal_var(&t1, a);
4adf6b2a 118}
5a437b06 119
a4a43d75 120static void secp256k1_fe_inv(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
25b35c7e
GM
121 secp256k1_fe_t x2, x3, x6, x9, x11, x22, x44, x88, x176, x220, x223, t1;
122 int j;
f8ccd9be 123
71712b27
GM
124 /** The binary representation of (p - 2) has 5 blocks of 1s, with lengths in
125 * { 1, 2, 22, 223 }. Use an addition chain to calculate 2^n - 1 for each block:
126 * [1], [2], 3, 6, 9, 11, [22], 44, 88, 176, 220, [223]
127 */
f8ccd9be 128
f8ccd9be
PD
129 secp256k1_fe_sqr(&x2, a);
130 secp256k1_fe_mul(&x2, &x2, a);
131
f8ccd9be
PD
132 secp256k1_fe_sqr(&x3, &x2);
133 secp256k1_fe_mul(&x3, &x3, a);
134
25b35c7e 135 x6 = x3;
26320197
GM
136 for (j=0; j<3; j++) {
137 secp256k1_fe_sqr(&x6, &x6);
138 }
f8ccd9be
PD
139 secp256k1_fe_mul(&x6, &x6, &x3);
140
25b35c7e 141 x9 = x6;
26320197
GM
142 for (j=0; j<3; j++) {
143 secp256k1_fe_sqr(&x9, &x9);
144 }
f8ccd9be
PD
145 secp256k1_fe_mul(&x9, &x9, &x3);
146
25b35c7e 147 x11 = x9;
26320197
GM
148 for (j=0; j<2; j++) {
149 secp256k1_fe_sqr(&x11, &x11);
150 }
f8ccd9be
PD
151 secp256k1_fe_mul(&x11, &x11, &x2);
152
25b35c7e 153 x22 = x11;
26320197
GM
154 for (j=0; j<11; j++) {
155 secp256k1_fe_sqr(&x22, &x22);
156 }
f8ccd9be
PD
157 secp256k1_fe_mul(&x22, &x22, &x11);
158
25b35c7e 159 x44 = x22;
26320197
GM
160 for (j=0; j<22; j++) {
161 secp256k1_fe_sqr(&x44, &x44);
162 }
f8ccd9be
PD
163 secp256k1_fe_mul(&x44, &x44, &x22);
164
25b35c7e 165 x88 = x44;
26320197
GM
166 for (j=0; j<44; j++) {
167 secp256k1_fe_sqr(&x88, &x88);
168 }
f8ccd9be
PD
169 secp256k1_fe_mul(&x88, &x88, &x44);
170
25b35c7e 171 x176 = x88;
26320197
GM
172 for (j=0; j<88; j++) {
173 secp256k1_fe_sqr(&x176, &x176);
174 }
f8ccd9be
PD
175 secp256k1_fe_mul(&x176, &x176, &x88);
176
25b35c7e 177 x220 = x176;
26320197
GM
178 for (j=0; j<44; j++) {
179 secp256k1_fe_sqr(&x220, &x220);
180 }
f8ccd9be
PD
181 secp256k1_fe_mul(&x220, &x220, &x44);
182
25b35c7e 183 x223 = x220;
26320197
GM
184 for (j=0; j<3; j++) {
185 secp256k1_fe_sqr(&x223, &x223);
186 }
f8ccd9be
PD
187 secp256k1_fe_mul(&x223, &x223, &x3);
188
71712b27 189 /* The final result is then assembled using a sliding window over the blocks. */
f8ccd9be 190
25b35c7e 191 t1 = x223;
26320197
GM
192 for (j=0; j<23; j++) {
193 secp256k1_fe_sqr(&t1, &t1);
194 }
f8ccd9be 195 secp256k1_fe_mul(&t1, &t1, &x22);
26320197
GM
196 for (j=0; j<5; j++) {
197 secp256k1_fe_sqr(&t1, &t1);
198 }
f8ccd9be 199 secp256k1_fe_mul(&t1, &t1, a);
26320197
GM
200 for (j=0; j<3; j++) {
201 secp256k1_fe_sqr(&t1, &t1);
202 }
f8ccd9be 203 secp256k1_fe_mul(&t1, &t1, &x2);
26320197
GM
204 for (j=0; j<2; j++) {
205 secp256k1_fe_sqr(&t1, &t1);
206 }
be82e92f 207 secp256k1_fe_mul(r, a, &t1);
5a437b06
PW
208}
209
a4a43d75 210static void secp256k1_fe_inv_var(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
2d938092 211#if defined(USE_FIELD_INV_BUILTIN)
910d0de4 212 secp256k1_fe_inv(r, a);
f0c89aad 213#elif defined(USE_FIELD_INV_NUM)
d9543c90 214 secp256k1_num_t n, m;
36b305a8
PW
215 static const secp256k1_fe_t negone = SECP256K1_FE_CONST(
216 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF,
217 0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFE, 0xFFFFFC2E
218 );
6efd6e77 219 /* secp256k1 field prime, value p defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */
4732d260
PW
220 static const unsigned char prime[32] = {
221 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
222 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
223 0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
224 0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFC,0x2F
225 };
910d0de4
PW
226 unsigned char b[32];
227 secp256k1_fe_t c = *a;
39bd94d8 228 secp256k1_fe_normalize_var(&c);
910d0de4 229 secp256k1_fe_get_b32(b, &c);
910d0de4 230 secp256k1_num_set_bin(&n, b, 32);
4732d260
PW
231 secp256k1_num_set_bin(&m, prime, 32);
232 secp256k1_num_mod_inverse(&n, &n, &m);
910d0de4 233 secp256k1_num_get_bin(b, 32, &n);
d907ebc0 234 VERIFY_CHECK(secp256k1_fe_set_b32(r, b));
36b305a8
PW
235 /* Verify the result is the (unique) valid inverse using non-GMP code. */
236 secp256k1_fe_mul(&c, &c, r);
237 secp256k1_fe_add(&c, &negone);
238 CHECK(secp256k1_fe_normalizes_to_zero_var(&c));
f0c89aad
PW
239#else
240#error "Please select field inverse implementation"
910d0de4 241#endif
5a437b06 242}
ff29b855 243
3627437d 244static void secp256k1_fe_inv_all_var(size_t len, secp256k1_fe_t *r, const secp256k1_fe_t *a) {
25b35c7e
GM
245 secp256k1_fe_t u;
246 size_t i;
26320197 247 if (len < 1) {
f16be77f 248 return;
26320197 249 }
f16be77f 250
1c7fa133 251 VERIFY_CHECK((r + len <= a) || (a + len <= r));
f16be77f
PD
252
253 r[0] = a[0];
254
25b35c7e 255 i = 0;
f16be77f
PD
256 while (++i < len) {
257 secp256k1_fe_mul(&r[i], &r[i - 1], &a[i]);
258 }
259
25b35c7e 260 secp256k1_fe_inv_var(&u, &r[--i]);
f16be77f
PD
261
262 while (i > 0) {
263 int j = i--;
264 secp256k1_fe_mul(&r[j], &r[i], &u);
265 secp256k1_fe_mul(&u, &u, &a[j]);
266 }
267
268 r[0] = u;
269}
270
7a4b7691 271#endif
This page took 0.068596 seconds and 4 git commands to generate.