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