]>
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 | |
abe2d3e8 DR |
7 | #ifndef SECP256K1_FIELD_REPR_IMPL_H |
8 | #define SECP256K1_FIELD_REPR_IMPL_H | |
7a4b7691 | 9 | |
78cd96b1 CF |
10 | #if defined HAVE_CONFIG_H |
11 | #include "libsecp256k1-config.h" | |
12 | #endif | |
13 | ||
1c7fa133 | 14 | #include "util.h" |
11ab5622 | 15 | #include "field.h" |
e6d142a8 | 16 | |
1ba4a60a | 17 | #if defined(USE_ASM_X86_64) |
11ab5622 | 18 | #include "field_5x52_asm_impl.h" |
f0c89aad | 19 | #else |
1ba4a60a | 20 | #include "field_5x52_int128_impl.h" |
e6d142a8 PW |
21 | #endif |
22 | ||
e6d142a8 PW |
23 | /** Implements arithmetic modulo FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFF FFFFFFFE FFFFFC2F, |
24 | * represented as 5 uint64_t's in base 2^52. The values are allowed to contain >52 each. In particular, | |
25 | * each FieldElem has a 'magnitude' associated with it. Internally, a magnitude M means each element | |
26 | * is at most M*(2^53-1), except the most significant one, which is limited to M*(2^49-1). All operations | |
27 | * accept any input with magnitude at most M, and have different rules for propagating magnitude to their | |
28 | * output. | |
29 | */ | |
30 | ||
59447da3 | 31 | #ifdef VERIFY |
dd891e0e | 32 | static void secp256k1_fe_verify(const secp256k1_fe *a) { |
59447da3 | 33 | const uint64_t *d = a->n; |
21f81a84 | 34 | int m = a->normalized ? 1 : 2 * a->magnitude, r = 1; |
6efd6e77 | 35 | /* secp256k1 'p' value defined in "Standards for Efficient Cryptography" (SEC2) 2.7.1. */ |
59447da3 PD |
36 | r &= (d[0] <= 0xFFFFFFFFFFFFFULL * m); |
37 | r &= (d[1] <= 0xFFFFFFFFFFFFFULL * m); | |
38 | r &= (d[2] <= 0xFFFFFFFFFFFFFULL * m); | |
39 | r &= (d[3] <= 0xFFFFFFFFFFFFFULL * m); | |
40 | r &= (d[4] <= 0x0FFFFFFFFFFFFULL * m); | |
7d681ac6 | 41 | r &= (a->magnitude >= 0); |
7688e341 | 42 | r &= (a->magnitude <= 2048); |
59447da3 | 43 | if (a->normalized) { |
7d681ac6 | 44 | r &= (a->magnitude <= 1); |
59447da3 PD |
45 | if (r && (d[4] == 0x0FFFFFFFFFFFFULL) && ((d[3] & d[2] & d[1]) == 0xFFFFFFFFFFFFFULL)) { |
46 | r &= (d[0] < 0xFFFFEFFFFFC2FULL); | |
47 | } | |
48 | } | |
1c7fa133 | 49 | VERIFY_CHECK(r == 1); |
59447da3 PD |
50 | } |
51 | #endif | |
52 | ||
dd891e0e | 53 | static void secp256k1_fe_normalize(secp256k1_fe *r) { |
90377077 PD |
54 | uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; |
55 | ||
71712b27 | 56 | /* Reduce t4 at the start so there will be at most a single carry from the first pass */ |
42822baa | 57 | uint64_t m; |
25b35c7e | 58 | uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; |
90377077 | 59 | |
71712b27 | 60 | /* The first pass ensures the magnitude is 1, ... */ |
90377077 PD |
61 | t0 += x * 0x1000003D1ULL; |
62 | t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; | |
42822baa PD |
63 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; |
64 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; | |
65 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; | |
90377077 | 66 | |
71712b27 | 67 | /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ |
1c7fa133 | 68 | VERIFY_CHECK(t4 >> 49 == 0); |
90377077 | 69 | |
71712b27 | 70 | /* At most a single final reduction is needed; check if the value is >= the field characteristic */ |
42822baa | 71 | x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) |
90377077 PD |
72 | & (t0 >= 0xFFFFEFFFFFC2FULL)); |
73 | ||
71712b27 | 74 | /* Apply the final reduction (for constant-time behaviour, we do it always) */ |
90377077 PD |
75 | t0 += x * 0x1000003D1ULL; |
76 | t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; | |
77 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; | |
78 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; | |
79 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; | |
80 | ||
71712b27 | 81 | /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ |
1c7fa133 | 82 | VERIFY_CHECK(t4 >> 48 == x); |
90377077 | 83 | |
71712b27 | 84 | /* Mask off the possible multiple of 2^256 from the final reduction */ |
90377077 PD |
85 | t4 &= 0x0FFFFFFFFFFFFULL; |
86 | ||
910d0de4 PW |
87 | r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; |
88 | ||
89 | #ifdef VERIFY | |
90 | r->magnitude = 1; | |
91 | r->normalized = 1; | |
21f81a84 | 92 | secp256k1_fe_verify(r); |
910d0de4 PW |
93 | #endif |
94 | } | |
e6d142a8 | 95 | |
dd891e0e | 96 | static void secp256k1_fe_normalize_weak(secp256k1_fe *r) { |
0295f0a3 PW |
97 | uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; |
98 | ||
99 | /* Reduce t4 at the start so there will be at most a single carry from the first pass */ | |
100 | uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; | |
101 | ||
102 | /* The first pass ensures the magnitude is 1, ... */ | |
103 | t0 += x * 0x1000003D1ULL; | |
104 | t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; | |
105 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; | |
106 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; | |
107 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; | |
108 | ||
109 | /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ | |
110 | VERIFY_CHECK(t4 >> 49 == 0); | |
111 | ||
112 | r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; | |
113 | ||
114 | #ifdef VERIFY | |
115 | r->magnitude = 1; | |
116 | secp256k1_fe_verify(r); | |
117 | #endif | |
118 | } | |
119 | ||
dd891e0e | 120 | static void secp256k1_fe_normalize_var(secp256k1_fe *r) { |
39bd94d8 PW |
121 | uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; |
122 | ||
123 | /* Reduce t4 at the start so there will be at most a single carry from the first pass */ | |
39bd94d8 | 124 | uint64_t m; |
25b35c7e | 125 | uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; |
39bd94d8 PW |
126 | |
127 | /* The first pass ensures the magnitude is 1, ... */ | |
128 | t0 += x * 0x1000003D1ULL; | |
129 | t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; | |
130 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; m = t1; | |
131 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; m &= t2; | |
132 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; m &= t3; | |
133 | ||
134 | /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ | |
135 | VERIFY_CHECK(t4 >> 49 == 0); | |
136 | ||
137 | /* At most a single final reduction is needed; check if the value is >= the field characteristic */ | |
138 | x = (t4 >> 48) | ((t4 == 0x0FFFFFFFFFFFFULL) & (m == 0xFFFFFFFFFFFFFULL) | |
139 | & (t0 >= 0xFFFFEFFFFFC2FULL)); | |
140 | ||
141 | if (x) { | |
142 | t0 += 0x1000003D1ULL; | |
143 | t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; | |
144 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; | |
145 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; | |
146 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; | |
147 | ||
148 | /* If t4 didn't carry to bit 48 already, then it should have after any final reduction */ | |
149 | VERIFY_CHECK(t4 >> 48 == x); | |
150 | ||
151 | /* Mask off the possible multiple of 2^256 from the final reduction */ | |
152 | t4 &= 0x0FFFFFFFFFFFFULL; | |
153 | } | |
154 | ||
155 | r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4; | |
156 | ||
157 | #ifdef VERIFY | |
158 | r->magnitude = 1; | |
159 | r->normalized = 1; | |
160 | secp256k1_fe_verify(r); | |
161 | #endif | |
162 | } | |
163 | ||
dd891e0e | 164 | static int secp256k1_fe_normalizes_to_zero(secp256k1_fe *r) { |
eed599dd PD |
165 | uint64_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4]; |
166 | ||
eed599dd PD |
167 | /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ |
168 | uint64_t z0, z1; | |
169 | ||
25b35c7e GM |
170 | /* Reduce t4 at the start so there will be at most a single carry from the first pass */ |
171 | uint64_t x = t4 >> 48; t4 &= 0x0FFFFFFFFFFFFULL; | |
172 | ||
eed599dd PD |
173 | /* The first pass ensures the magnitude is 1, ... */ |
174 | t0 += x * 0x1000003D1ULL; | |
175 | t1 += (t0 >> 52); t0 &= 0xFFFFFFFFFFFFFULL; z0 = t0; z1 = t0 ^ 0x1000003D0ULL; | |
176 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; | |
177 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; | |
178 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; | |
179 | z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; | |
49ee0dbe PD |
180 | |
181 | /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ | |
182 | VERIFY_CHECK(t4 >> 49 == 0); | |
183 | ||
184 | return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); | |
185 | } | |
186 | ||
dd891e0e | 187 | static int secp256k1_fe_normalizes_to_zero_var(secp256k1_fe *r) { |
25b35c7e GM |
188 | uint64_t t0, t1, t2, t3, t4; |
189 | uint64_t z0, z1; | |
190 | uint64_t x; | |
191 | ||
192 | t0 = r->n[0]; | |
193 | t4 = r->n[4]; | |
49ee0dbe PD |
194 | |
195 | /* Reduce t4 at the start so there will be at most a single carry from the first pass */ | |
25b35c7e | 196 | x = t4 >> 48; |
49ee0dbe PD |
197 | |
198 | /* The first pass ensures the magnitude is 1, ... */ | |
199 | t0 += x * 0x1000003D1ULL; | |
200 | ||
201 | /* z0 tracks a possible raw value of 0, z1 tracks a possible raw value of P */ | |
25b35c7e GM |
202 | z0 = t0 & 0xFFFFFFFFFFFFFULL; |
203 | z1 = z0 ^ 0x1000003D0ULL; | |
49ee0dbe PD |
204 | |
205 | /* Fast return path should catch the majority of cases */ | |
26320197 | 206 | if ((z0 != 0ULL) & (z1 != 0xFFFFFFFFFFFFFULL)) { |
49ee0dbe | 207 | return 0; |
26320197 | 208 | } |
49ee0dbe | 209 | |
25b35c7e GM |
210 | t1 = r->n[1]; |
211 | t2 = r->n[2]; | |
212 | t3 = r->n[3]; | |
213 | ||
49ee0dbe PD |
214 | t4 &= 0x0FFFFFFFFFFFFULL; |
215 | ||
263dcbca | 216 | t1 += (t0 >> 52); |
49ee0dbe PD |
217 | t2 += (t1 >> 52); t1 &= 0xFFFFFFFFFFFFFULL; z0 |= t1; z1 &= t1; |
218 | t3 += (t2 >> 52); t2 &= 0xFFFFFFFFFFFFFULL; z0 |= t2; z1 &= t2; | |
219 | t4 += (t3 >> 52); t3 &= 0xFFFFFFFFFFFFFULL; z0 |= t3; z1 &= t3; | |
220 | z0 |= t4; z1 &= t4 ^ 0xF000000000000ULL; | |
eed599dd PD |
221 | |
222 | /* ... except for a possible carry at bit 48 of t4 (i.e. bit 256 of the field element) */ | |
223 | VERIFY_CHECK(t4 >> 49 == 0); | |
224 | ||
225 | return (z0 == 0) | (z1 == 0xFFFFFFFFFFFFFULL); | |
226 | } | |
227 | ||
dd891e0e | 228 | SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe *r, int a) { |
910d0de4 PW |
229 | r->n[0] = a; |
230 | r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0; | |
231 | #ifdef VERIFY | |
232 | r->magnitude = 1; | |
233 | r->normalized = 1; | |
21f81a84 | 234 | secp256k1_fe_verify(r); |
e6d142a8 PW |
235 | #endif |
236 | } | |
237 | ||
dd891e0e | 238 | SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe *a) { |
25b35c7e | 239 | const uint64_t *t = a->n; |
910d0de4 | 240 | #ifdef VERIFY |
1c7fa133 | 241 | VERIFY_CHECK(a->normalized); |
21f81a84 | 242 | secp256k1_fe_verify(a); |
e6d142a8 | 243 | #endif |
137e77af | 244 | return (t[0] | t[1] | t[2] | t[3] | t[4]) == 0; |
e6d142a8 PW |
245 | } |
246 | ||
dd891e0e | 247 | SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe *a) { |
910d0de4 | 248 | #ifdef VERIFY |
1c7fa133 | 249 | VERIFY_CHECK(a->normalized); |
21f81a84 | 250 | secp256k1_fe_verify(a); |
e6d142a8 | 251 | #endif |
910d0de4 | 252 | return a->n[0] & 1; |
e6d142a8 PW |
253 | } |
254 | ||
dd891e0e | 255 | SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe *a) { |
25b35c7e | 256 | int i; |
2f6c8019 GM |
257 | #ifdef VERIFY |
258 | a->magnitude = 0; | |
7d681ac6 | 259 | a->normalized = 1; |
2f6c8019 | 260 | #endif |
25b35c7e | 261 | for (i=0; i<5; i++) { |
2f6c8019 GM |
262 | a->n[i] = 0; |
263 | } | |
264 | } | |
265 | ||
dd891e0e | 266 | static int secp256k1_fe_cmp_var(const secp256k1_fe *a, const secp256k1_fe *b) { |
25b35c7e | 267 | int i; |
f24041d6 PW |
268 | #ifdef VERIFY |
269 | VERIFY_CHECK(a->normalized); | |
270 | VERIFY_CHECK(b->normalized); | |
271 | secp256k1_fe_verify(a); | |
272 | secp256k1_fe_verify(b); | |
273 | #endif | |
25b35c7e | 274 | for (i = 4; i >= 0; i--) { |
26320197 GM |
275 | if (a->n[i] > b->n[i]) { |
276 | return 1; | |
277 | } | |
278 | if (a->n[i] < b->n[i]) { | |
279 | return -1; | |
280 | } | |
f24041d6 PW |
281 | } |
282 | return 0; | |
283 | } | |
284 | ||
dd891e0e | 285 | static int secp256k1_fe_set_b32(secp256k1_fe *r, const unsigned char *a) { |
34a67c77 | 286 | int ret; |
aa849908 C |
287 | r->n[0] = (uint64_t)a[31] |
288 | | ((uint64_t)a[30] << 8) | |
289 | | ((uint64_t)a[29] << 16) | |
290 | | ((uint64_t)a[28] << 24) | |
291 | | ((uint64_t)a[27] << 32) | |
292 | | ((uint64_t)a[26] << 40) | |
293 | | ((uint64_t)(a[25] & 0xF) << 48); | |
294 | r->n[1] = (uint64_t)((a[25] >> 4) & 0xF) | |
295 | | ((uint64_t)a[24] << 4) | |
296 | | ((uint64_t)a[23] << 12) | |
297 | | ((uint64_t)a[22] << 20) | |
298 | | ((uint64_t)a[21] << 28) | |
299 | | ((uint64_t)a[20] << 36) | |
300 | | ((uint64_t)a[19] << 44); | |
301 | r->n[2] = (uint64_t)a[18] | |
302 | | ((uint64_t)a[17] << 8) | |
303 | | ((uint64_t)a[16] << 16) | |
304 | | ((uint64_t)a[15] << 24) | |
305 | | ((uint64_t)a[14] << 32) | |
306 | | ((uint64_t)a[13] << 40) | |
307 | | ((uint64_t)(a[12] & 0xF) << 48); | |
308 | r->n[3] = (uint64_t)((a[12] >> 4) & 0xF) | |
309 | | ((uint64_t)a[11] << 4) | |
310 | | ((uint64_t)a[10] << 12) | |
311 | | ((uint64_t)a[9] << 20) | |
312 | | ((uint64_t)a[8] << 28) | |
313 | | ((uint64_t)a[7] << 36) | |
314 | | ((uint64_t)a[6] << 44); | |
315 | r->n[4] = (uint64_t)a[5] | |
316 | | ((uint64_t)a[4] << 8) | |
317 | | ((uint64_t)a[3] << 16) | |
318 | | ((uint64_t)a[2] << 24) | |
319 | | ((uint64_t)a[1] << 32) | |
320 | | ((uint64_t)a[0] << 40); | |
34a67c77 | 321 | ret = !((r->n[4] == 0x0FFFFFFFFFFFFULL) & ((r->n[3] & r->n[2] & r->n[1]) == 0xFFFFFFFFFFFFFULL) & (r->n[0] >= 0xFFFFEFFFFFC2FULL)); |
910d0de4 PW |
322 | #ifdef VERIFY |
323 | r->magnitude = 1; | |
34a67c77 GM |
324 | if (ret) { |
325 | r->normalized = 1; | |
326 | secp256k1_fe_verify(r); | |
327 | } else { | |
328 | r->normalized = 0; | |
329 | } | |
910d0de4 | 330 | #endif |
34a67c77 | 331 | return ret; |
e6d142a8 PW |
332 | } |
333 | ||
910d0de4 | 334 | /** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */ |
dd891e0e | 335 | static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe *a) { |
910d0de4 | 336 | #ifdef VERIFY |
1c7fa133 | 337 | VERIFY_CHECK(a->normalized); |
21f81a84 | 338 | secp256k1_fe_verify(a); |
910d0de4 | 339 | #endif |
aa849908 C |
340 | r[0] = (a->n[4] >> 40) & 0xFF; |
341 | r[1] = (a->n[4] >> 32) & 0xFF; | |
342 | r[2] = (a->n[4] >> 24) & 0xFF; | |
343 | r[3] = (a->n[4] >> 16) & 0xFF; | |
344 | r[4] = (a->n[4] >> 8) & 0xFF; | |
345 | r[5] = a->n[4] & 0xFF; | |
346 | r[6] = (a->n[3] >> 44) & 0xFF; | |
347 | r[7] = (a->n[3] >> 36) & 0xFF; | |
348 | r[8] = (a->n[3] >> 28) & 0xFF; | |
349 | r[9] = (a->n[3] >> 20) & 0xFF; | |
350 | r[10] = (a->n[3] >> 12) & 0xFF; | |
351 | r[11] = (a->n[3] >> 4) & 0xFF; | |
352 | r[12] = ((a->n[2] >> 48) & 0xF) | ((a->n[3] & 0xF) << 4); | |
353 | r[13] = (a->n[2] >> 40) & 0xFF; | |
354 | r[14] = (a->n[2] >> 32) & 0xFF; | |
355 | r[15] = (a->n[2] >> 24) & 0xFF; | |
356 | r[16] = (a->n[2] >> 16) & 0xFF; | |
357 | r[17] = (a->n[2] >> 8) & 0xFF; | |
358 | r[18] = a->n[2] & 0xFF; | |
359 | r[19] = (a->n[1] >> 44) & 0xFF; | |
360 | r[20] = (a->n[1] >> 36) & 0xFF; | |
361 | r[21] = (a->n[1] >> 28) & 0xFF; | |
362 | r[22] = (a->n[1] >> 20) & 0xFF; | |
363 | r[23] = (a->n[1] >> 12) & 0xFF; | |
364 | r[24] = (a->n[1] >> 4) & 0xFF; | |
365 | r[25] = ((a->n[0] >> 48) & 0xF) | ((a->n[1] & 0xF) << 4); | |
366 | r[26] = (a->n[0] >> 40) & 0xFF; | |
367 | r[27] = (a->n[0] >> 32) & 0xFF; | |
368 | r[28] = (a->n[0] >> 24) & 0xFF; | |
369 | r[29] = (a->n[0] >> 16) & 0xFF; | |
370 | r[30] = (a->n[0] >> 8) & 0xFF; | |
371 | r[31] = a->n[0] & 0xFF; | |
e6d142a8 PW |
372 | } |
373 | ||
dd891e0e | 374 | SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe *r, const secp256k1_fe *a, int m) { |
910d0de4 | 375 | #ifdef VERIFY |
1c7fa133 | 376 | VERIFY_CHECK(a->magnitude <= m); |
21f81a84 | 377 | secp256k1_fe_verify(a); |
e6d142a8 | 378 | #endif |
7a8e385d PW |
379 | r->n[0] = 0xFFFFEFFFFFC2FULL * 2 * (m + 1) - a->n[0]; |
380 | r->n[1] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[1]; | |
381 | r->n[2] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[2]; | |
382 | r->n[3] = 0xFFFFFFFFFFFFFULL * 2 * (m + 1) - a->n[3]; | |
383 | r->n[4] = 0x0FFFFFFFFFFFFULL * 2 * (m + 1) - a->n[4]; | |
910d0de4 | 384 | #ifdef VERIFY |
21f81a84 | 385 | r->magnitude = m + 1; |
eb0be8ee | 386 | r->normalized = 0; |
21f81a84 | 387 | secp256k1_fe_verify(r); |
e6d142a8 | 388 | #endif |
21f81a84 PW |
389 | } |
390 | ||
dd891e0e | 391 | SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe *r, int a) { |
910d0de4 PW |
392 | r->n[0] *= a; |
393 | r->n[1] *= a; | |
394 | r->n[2] *= a; | |
395 | r->n[3] *= a; | |
396 | r->n[4] *= a; | |
910d0de4 | 397 | #ifdef VERIFY |
21f81a84 | 398 | r->magnitude *= a; |
910d0de4 | 399 | r->normalized = 0; |
21f81a84 | 400 | secp256k1_fe_verify(r); |
e6d142a8 | 401 | #endif |
21f81a84 PW |
402 | } |
403 | ||
dd891e0e | 404 | SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe *r, const secp256k1_fe *a) { |
7d681ac6 PD |
405 | #ifdef VERIFY |
406 | secp256k1_fe_verify(a); | |
407 | #endif | |
910d0de4 PW |
408 | r->n[0] += a->n[0]; |
409 | r->n[1] += a->n[1]; | |
410 | r->n[2] += a->n[2]; | |
411 | r->n[3] += a->n[3]; | |
412 | r->n[4] += a->n[4]; | |
21f81a84 PW |
413 | #ifdef VERIFY |
414 | r->magnitude += a->magnitude; | |
415 | r->normalized = 0; | |
416 | secp256k1_fe_verify(r); | |
21f81a84 | 417 | #endif |
e6d142a8 PW |
418 | } |
419 | ||
dd891e0e | 420 | static void secp256k1_fe_mul(secp256k1_fe *r, const secp256k1_fe *a, const secp256k1_fe * SECP256K1_RESTRICT b) { |
910d0de4 | 421 | #ifdef VERIFY |
1c7fa133 PW |
422 | VERIFY_CHECK(a->magnitude <= 8); |
423 | VERIFY_CHECK(b->magnitude <= 8); | |
21f81a84 PW |
424 | secp256k1_fe_verify(a); |
425 | secp256k1_fe_verify(b); | |
be82e92f | 426 | VERIFY_CHECK(r != b); |
4efb3f8d | 427 | VERIFY_CHECK(a != b); |
21f81a84 | 428 | #endif |
b2c9681c | 429 | secp256k1_fe_mul_inner(r->n, a->n, b->n); |
21f81a84 | 430 | #ifdef VERIFY |
910d0de4 PW |
431 | r->magnitude = 1; |
432 | r->normalized = 0; | |
21f81a84 | 433 | secp256k1_fe_verify(r); |
e6d142a8 PW |
434 | #endif |
435 | } | |
436 | ||
dd891e0e | 437 | static void secp256k1_fe_sqr(secp256k1_fe *r, const secp256k1_fe *a) { |
910d0de4 | 438 | #ifdef VERIFY |
1c7fa133 | 439 | VERIFY_CHECK(a->magnitude <= 8); |
7d681ac6 | 440 | secp256k1_fe_verify(a); |
21f81a84 | 441 | #endif |
b2c9681c | 442 | secp256k1_fe_sqr_inner(r->n, a->n); |
21f81a84 | 443 | #ifdef VERIFY |
fba1d58d PW |
444 | r->magnitude = 1; |
445 | r->normalized = 0; | |
7d681ac6 | 446 | secp256k1_fe_verify(r); |
e6d142a8 PW |
447 | #endif |
448 | } | |
7a4b7691 | 449 | |
dd891e0e | 450 | static SECP256K1_INLINE void secp256k1_fe_cmov(secp256k1_fe *r, const secp256k1_fe *a, int flag) { |
bb0ea50d | 451 | uint64_t mask0, mask1; |
f79a7adc | 452 | VG_CHECK_VERIFY(r->n, sizeof(r->n)); |
bb0ea50d GM |
453 | mask0 = flag + ~((uint64_t)0); |
454 | mask1 = ~mask0; | |
455 | r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); | |
456 | r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); | |
457 | r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); | |
458 | r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); | |
459 | r->n[4] = (r->n[4] & mask0) | (a->n[4] & mask1); | |
460 | #ifdef VERIFY | |
34a67c77 | 461 | if (flag) { |
a0601cd7 | 462 | r->magnitude = a->magnitude; |
34a67c77 | 463 | r->normalized = a->normalized; |
a0601cd7 | 464 | } |
bb0ea50d GM |
465 | #endif |
466 | } | |
467 | ||
dd891e0e | 468 | static SECP256K1_INLINE void secp256k1_fe_storage_cmov(secp256k1_fe_storage *r, const secp256k1_fe_storage *a, int flag) { |
27bc1311 | 469 | uint64_t mask0, mask1; |
f79a7adc | 470 | VG_CHECK_VERIFY(r->n, sizeof(r->n)); |
27bc1311 GM |
471 | mask0 = flag + ~((uint64_t)0); |
472 | mask1 = ~mask0; | |
ff889f7d PW |
473 | r->n[0] = (r->n[0] & mask0) | (a->n[0] & mask1); |
474 | r->n[1] = (r->n[1] & mask0) | (a->n[1] & mask1); | |
475 | r->n[2] = (r->n[2] & mask0) | (a->n[2] & mask1); | |
476 | r->n[3] = (r->n[3] & mask0) | (a->n[3] & mask1); | |
477 | } | |
478 | ||
dd891e0e | 479 | static void secp256k1_fe_to_storage(secp256k1_fe_storage *r, const secp256k1_fe *a) { |
ff889f7d PW |
480 | #ifdef VERIFY |
481 | VERIFY_CHECK(a->normalized); | |
482 | #endif | |
483 | r->n[0] = a->n[0] | a->n[1] << 52; | |
484 | r->n[1] = a->n[1] >> 12 | a->n[2] << 40; | |
485 | r->n[2] = a->n[2] >> 24 | a->n[3] << 28; | |
486 | r->n[3] = a->n[3] >> 36 | a->n[4] << 16; | |
487 | } | |
488 | ||
dd891e0e | 489 | static SECP256K1_INLINE void secp256k1_fe_from_storage(secp256k1_fe *r, const secp256k1_fe_storage *a) { |
ff889f7d PW |
490 | r->n[0] = a->n[0] & 0xFFFFFFFFFFFFFULL; |
491 | r->n[1] = a->n[0] >> 52 | ((a->n[1] << 12) & 0xFFFFFFFFFFFFFULL); | |
492 | r->n[2] = a->n[1] >> 40 | ((a->n[2] << 24) & 0xFFFFFFFFFFFFFULL); | |
493 | r->n[3] = a->n[2] >> 28 | ((a->n[3] << 36) & 0xFFFFFFFFFFFFFULL); | |
494 | r->n[4] = a->n[3] >> 16; | |
495 | #ifdef VERIFY | |
496 | r->magnitude = 1; | |
497 | r->normalized = 1; | |
498 | #endif | |
499 | } | |
500 | ||
abe2d3e8 | 501 | #endif /* SECP256K1_FIELD_REPR_IMPL_H */ |