]>
Commit | Line | Data |
---|---|---|
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 |
24 | SECP256K1_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 | 31 | static 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 | 120 | static 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 | 210 | static 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 | 244 | static 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 |