]> Git Repo - secp256k1.git/blame - src/field_10x26_impl.h
Add scalar splitting functions
[secp256k1.git] / src / field_10x26_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_REPR_IMPL_H_
8#define _SECP256K1_FIELD_REPR_IMPL_H_
9
3231676b 10#include <stdio.h>
3231676b 11#include <string.h>
1c7fa133 12#include "util.h"
11ab5622
PW
13#include "num.h"
14#include "field.h"
3231676b 15
a4a43d75
GM
16static void secp256k1_fe_inner_start(void) {}
17static void secp256k1_fe_inner_stop(void) {}
6baf08df 18
7d681ac6 19#ifdef VERIFY
a4a43d75 20static void secp256k1_fe_verify(const secp256k1_fe_t *a) {
7d681ac6
PD
21 const uint32_t *d = a->n;
22 int m = a->normalized ? 1 : 2 * a->magnitude, r = 1;
23 r &= (d[0] <= 0x3FFFFFFUL * m);
24 r &= (d[1] <= 0x3FFFFFFUL * m);
25 r &= (d[2] <= 0x3FFFFFFUL * m);
26 r &= (d[3] <= 0x3FFFFFFUL * m);
27 r &= (d[4] <= 0x3FFFFFFUL * m);
28 r &= (d[5] <= 0x3FFFFFFUL * m);
29 r &= (d[6] <= 0x3FFFFFFUL * m);
30 r &= (d[7] <= 0x3FFFFFFUL * m);
31 r &= (d[8] <= 0x3FFFFFFUL * m);
32 r &= (d[9] <= 0x03FFFFFUL * m);
33 r &= (a->magnitude >= 0);
34 if (a->normalized) {
35 r &= (a->magnitude <= 1);
36 if (r && (d[9] == 0x03FFFFFUL)) {
37 uint32_t mid = d[8] & d[7] & d[6] & d[5] & d[4] & d[3] & d[2];
38 if (mid == 0x3FFFFFFUL) {
39 r &= ((d[1] + 0x40UL + ((d[0] + 0x3D1UL) >> 26)) <= 0x3FFFFFFUL);
40 }
41 }
42 }
43 VERIFY_CHECK(r == 1);
44}
45#else
2cad067a
GM
46static void secp256k1_fe_verify(const secp256k1_fe_t *a) {
47 (void)a;
48}
7d681ac6
PD
49#endif
50
a4a43d75 51static void secp256k1_fe_normalize(secp256k1_fe_t *r) {
42822baa
PD
52 uint32_t t0 = r->n[0], t1 = r->n[1], t2 = r->n[2], t3 = r->n[3], t4 = r->n[4],
53 t5 = r->n[5], t6 = r->n[6], t7 = r->n[7], t8 = r->n[8], t9 = r->n[9];
54
71712b27 55 /* Reduce t9 at the start so there will be at most a single carry from the first pass */
42822baa
PD
56 uint32_t x = t9 >> 22; t9 &= 0x03FFFFFUL;
57 uint32_t m;
58
71712b27 59 /* The first pass ensures the magnitude is 1, ... */
42822baa
PD
60 t0 += x * 0x3D1UL; t1 += (x << 6);
61 t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL;
62 t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL;
63 t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL; m = t2;
64 t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL; m &= t3;
65 t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL; m &= t4;
66 t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL; m &= t5;
67 t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL; m &= t6;
68 t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL; m &= t7;
69 t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL; m &= t8;
70
71712b27 71 /* ... except for a possible carry at bit 22 of t9 (i.e. bit 256 of the field element) */
1c7fa133 72 VERIFY_CHECK(t9 >> 23 == 0);
42822baa 73
71712b27 74 /* At most a single final reduction is needed; check if the value is >= the field characteristic */
7d681ac6
PD
75 x = (t9 >> 22) | ((t9 == 0x03FFFFFUL) & (m == 0x3FFFFFFUL)
76 & ((t1 + 0x40UL + ((t0 + 0x3D1UL) >> 26)) > 0x3FFFFFFUL));
42822baa 77
71712b27 78 /* Apply the final reduction (for constant-time behaviour, we do it always) */
42822baa
PD
79 t0 += x * 0x3D1UL; t1 += (x << 6);
80 t1 += (t0 >> 26); t0 &= 0x3FFFFFFUL;
81 t2 += (t1 >> 26); t1 &= 0x3FFFFFFUL;
82 t3 += (t2 >> 26); t2 &= 0x3FFFFFFUL;
83 t4 += (t3 >> 26); t3 &= 0x3FFFFFFUL;
84 t5 += (t4 >> 26); t4 &= 0x3FFFFFFUL;
85 t6 += (t5 >> 26); t5 &= 0x3FFFFFFUL;
86 t7 += (t6 >> 26); t6 &= 0x3FFFFFFUL;
87 t8 += (t7 >> 26); t7 &= 0x3FFFFFFUL;
88 t9 += (t8 >> 26); t8 &= 0x3FFFFFFUL;
89
71712b27 90 /* If t9 didn't carry to bit 22 already, then it should have after any final reduction */
1c7fa133 91 VERIFY_CHECK(t9 >> 22 == x);
42822baa 92
71712b27 93 /* Mask off the possible multiple of 2^256 from the final reduction */
42822baa
PD
94 t9 &= 0x03FFFFFUL;
95
96 r->n[0] = t0; r->n[1] = t1; r->n[2] = t2; r->n[3] = t3; r->n[4] = t4;
3231676b 97 r->n[5] = t5; r->n[6] = t6; r->n[7] = t7; r->n[8] = t8; r->n[9] = t9;
3231676b
PW
98
99#ifdef VERIFY
100 r->magnitude = 1;
101 r->normalized = 1;
7d681ac6 102 secp256k1_fe_verify(r);
3231676b
PW
103#endif
104}
105
a4a43d75 106SECP256K1_INLINE static void secp256k1_fe_set_int(secp256k1_fe_t *r, int a) {
3231676b
PW
107 r->n[0] = a;
108 r->n[1] = r->n[2] = r->n[3] = r->n[4] = r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
109#ifdef VERIFY
110 r->magnitude = 1;
111 r->normalized = 1;
7d681ac6 112 secp256k1_fe_verify(r);
3231676b
PW
113#endif
114}
115
a4a43d75 116SECP256K1_INLINE static int secp256k1_fe_is_zero(const secp256k1_fe_t *a) {
3231676b 117#ifdef VERIFY
1c7fa133 118 VERIFY_CHECK(a->normalized);
7d681ac6 119 secp256k1_fe_verify(a);
3231676b 120#endif
137e77af
PD
121 const uint32_t *t = a->n;
122 return (t[0] | t[1] | t[2] | t[3] | t[4] | t[5] | t[6] | t[7] | t[8] | t[9]) == 0;
3231676b
PW
123}
124
a4a43d75 125SECP256K1_INLINE static int secp256k1_fe_is_odd(const secp256k1_fe_t *a) {
3231676b 126#ifdef VERIFY
1c7fa133 127 VERIFY_CHECK(a->normalized);
7d681ac6 128 secp256k1_fe_verify(a);
3231676b
PW
129#endif
130 return a->n[0] & 1;
131}
132
a4a43d75 133SECP256K1_INLINE static void secp256k1_fe_clear(secp256k1_fe_t *a) {
2f6c8019 134#ifdef VERIFY
2f6c8019 135 a->magnitude = 0;
7d681ac6 136 a->normalized = 1;
2f6c8019
GM
137#endif
138 for (int i=0; i<10; i++) {
139 a->n[i] = 0;
140 }
141}
142
a4a43d75 143SECP256K1_INLINE static int secp256k1_fe_equal(const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
3231676b 144#ifdef VERIFY
1c7fa133
PW
145 VERIFY_CHECK(a->normalized);
146 VERIFY_CHECK(b->normalized);
7d681ac6
PD
147 secp256k1_fe_verify(a);
148 secp256k1_fe_verify(b);
3231676b 149#endif
137e77af
PD
150 const uint32_t *t = a->n, *u = b->n;
151 return ((t[0]^u[0]) | (t[1]^u[1]) | (t[2]^u[2]) | (t[3]^u[3]) | (t[4]^u[4])
152 | (t[5]^u[5]) | (t[6]^u[6]) | (t[7]^u[7]) | (t[8]^u[8]) | (t[9]^u[9])) == 0;
3231676b
PW
153}
154
d907ebc0 155static int secp256k1_fe_set_b32(secp256k1_fe_t *r, const unsigned char *a) {
3231676b
PW
156 r->n[0] = r->n[1] = r->n[2] = r->n[3] = r->n[4] = 0;
157 r->n[5] = r->n[6] = r->n[7] = r->n[8] = r->n[9] = 0;
158 for (int i=0; i<32; i++) {
159 for (int j=0; j<4; j++) {
160 int limb = (8*i+2*j)/26;
161 int shift = (8*i+2*j)%26;
162 r->n[limb] |= (uint32_t)((a[31-i] >> (2*j)) & 0x3) << shift;
163 }
164 }
d907ebc0
PW
165 if (r->n[9] == 0x3FFFFFUL && (r->n[8] & r->n[7] & r->n[6] & r->n[5] & r->n[4] & r->n[3] & r->n[2]) == 0x3FFFFFFUL && (r->n[1] + 0x40UL + ((r->n[0] + 0x3D1UL) >> 26)) > 0x3FFFFFFUL) {
166 return 0;
167 }
3231676b
PW
168#ifdef VERIFY
169 r->magnitude = 1;
170 r->normalized = 1;
7d681ac6 171 secp256k1_fe_verify(r);
3231676b 172#endif
d907ebc0 173 return 1;
3231676b
PW
174}
175
784e62f3 176/** Convert a field element to a 32-byte big endian value. Requires the input to be normalized */
a4a43d75 177static void secp256k1_fe_get_b32(unsigned char *r, const secp256k1_fe_t *a) {
3231676b 178#ifdef VERIFY
1c7fa133 179 VERIFY_CHECK(a->normalized);
7d681ac6 180 secp256k1_fe_verify(a);
3231676b
PW
181#endif
182 for (int i=0; i<32; i++) {
183 int c = 0;
184 for (int j=0; j<4; j++) {
185 int limb = (8*i+2*j)/26;
186 int shift = (8*i+2*j)%26;
187 c |= ((a->n[limb] >> shift) & 0x3) << (2 * j);
188 }
189 r[31-i] = c;
190 }
191}
192
a4a43d75 193SECP256K1_INLINE static void secp256k1_fe_negate(secp256k1_fe_t *r, const secp256k1_fe_t *a, int m) {
3231676b 194#ifdef VERIFY
1c7fa133 195 VERIFY_CHECK(a->magnitude <= m);
7d681ac6 196 secp256k1_fe_verify(a);
3231676b 197#endif
7a8e385d
PW
198 r->n[0] = 0x3FFFC2FUL * 2 * (m + 1) - a->n[0];
199 r->n[1] = 0x3FFFFBFUL * 2 * (m + 1) - a->n[1];
200 r->n[2] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[2];
201 r->n[3] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[3];
202 r->n[4] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[4];
203 r->n[5] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[5];
204 r->n[6] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[6];
205 r->n[7] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[7];
206 r->n[8] = 0x3FFFFFFUL * 2 * (m + 1) - a->n[8];
207 r->n[9] = 0x03FFFFFUL * 2 * (m + 1) - a->n[9];
3231676b 208#ifdef VERIFY
7d681ac6 209 r->magnitude = m + 1;
3231676b 210 r->normalized = 0;
7d681ac6 211 secp256k1_fe_verify(r);
3231676b 212#endif
7d681ac6
PD
213}
214
a4a43d75 215SECP256K1_INLINE static void secp256k1_fe_mul_int(secp256k1_fe_t *r, int a) {
3231676b
PW
216 r->n[0] *= a;
217 r->n[1] *= a;
218 r->n[2] *= a;
219 r->n[3] *= a;
220 r->n[4] *= a;
221 r->n[5] *= a;
222 r->n[6] *= a;
223 r->n[7] *= a;
224 r->n[8] *= a;
225 r->n[9] *= a;
7d681ac6
PD
226#ifdef VERIFY
227 r->magnitude *= a;
228 r->normalized = 0;
229 secp256k1_fe_verify(r);
230#endif
3231676b
PW
231}
232
a4a43d75 233SECP256K1_INLINE static void secp256k1_fe_add(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
3231676b 234#ifdef VERIFY
7d681ac6 235 secp256k1_fe_verify(a);
3231676b
PW
236#endif
237 r->n[0] += a->n[0];
238 r->n[1] += a->n[1];
239 r->n[2] += a->n[2];
240 r->n[3] += a->n[3];
241 r->n[4] += a->n[4];
242 r->n[5] += a->n[5];
243 r->n[6] += a->n[6];
244 r->n[7] += a->n[7];
245 r->n[8] += a->n[8];
246 r->n[9] += a->n[9];
7d681ac6
PD
247#ifdef VERIFY
248 r->magnitude += a->magnitude;
249 r->normalized = 0;
250 secp256k1_fe_verify(r);
251#endif
3231676b
PW
252}
253
f8cce956
PW
254#ifdef VERIFY
255#define VERIFY_BITS(x, n) VERIFY_CHECK(((x) >> (n)) == 0)
256#else
257#define VERIFY_BITS(x, n) do { } while(0)
258#endif
259
a4a43d75 260SECP256K1_INLINE static void secp256k1_fe_mul_inner(const uint32_t *a, const uint32_t *b, uint32_t *r) {
f8cce956
PW
261 VERIFY_BITS(a[0], 30);
262 VERIFY_BITS(a[1], 30);
263 VERIFY_BITS(a[2], 30);
264 VERIFY_BITS(a[3], 30);
265 VERIFY_BITS(a[4], 30);
266 VERIFY_BITS(a[5], 30);
267 VERIFY_BITS(a[6], 30);
268 VERIFY_BITS(a[7], 30);
269 VERIFY_BITS(a[8], 30);
270 VERIFY_BITS(a[9], 26);
271 VERIFY_BITS(b[0], 30);
272 VERIFY_BITS(b[1], 30);
273 VERIFY_BITS(b[2], 30);
274 VERIFY_BITS(b[3], 30);
275 VERIFY_BITS(b[4], 30);
276 VERIFY_BITS(b[5], 30);
277 VERIFY_BITS(b[6], 30);
278 VERIFY_BITS(b[7], 30);
279 VERIFY_BITS(b[8], 30);
280 VERIFY_BITS(b[9], 26);
5dd421ba
PD
281
282 const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL;
71712b27
GM
283 /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n.
284 * px is a shorthand for sum(a[i]*b[x-i], i=0..x).
285 * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0].
286 */
5dd421ba
PD
287
288 uint64_t c, d;
289
290 d = (uint64_t)a[0] * b[9]
291 + (uint64_t)a[1] * b[8]
292 + (uint64_t)a[2] * b[7]
293 + (uint64_t)a[3] * b[6]
294 + (uint64_t)a[4] * b[5]
295 + (uint64_t)a[5] * b[4]
296 + (uint64_t)a[6] * b[3]
297 + (uint64_t)a[7] * b[2]
298 + (uint64_t)a[8] * b[1]
299 + (uint64_t)a[9] * b[0];
71712b27
GM
300 /* VERIFY_BITS(d, 64); */
301 /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
5dd421ba 302 uint32_t t9 = d & M; d >>= 26;
f8cce956
PW
303 VERIFY_BITS(t9, 26);
304 VERIFY_BITS(d, 38);
71712b27 305 /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
5dd421ba
PD
306
307 c = (uint64_t)a[0] * b[0];
f8cce956 308 VERIFY_BITS(c, 60);
71712b27 309 /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */
5dd421ba
PD
310 d += (uint64_t)a[1] * b[9]
311 + (uint64_t)a[2] * b[8]
312 + (uint64_t)a[3] * b[7]
313 + (uint64_t)a[4] * b[6]
314 + (uint64_t)a[5] * b[5]
315 + (uint64_t)a[6] * b[4]
316 + (uint64_t)a[7] * b[3]
317 + (uint64_t)a[8] * b[2]
318 + (uint64_t)a[9] * b[1];
f8cce956 319 VERIFY_BITS(d, 63);
71712b27 320 /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
5dd421ba 321 uint64_t u0 = d & M; d >>= 26; c += u0 * R0;
f8cce956
PW
322 VERIFY_BITS(u0, 26);
323 VERIFY_BITS(d, 37);
324 VERIFY_BITS(c, 61);
71712b27 325 /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
5dd421ba 326 uint32_t t0 = c & M; c >>= 26; c += u0 * R1;
f8cce956
PW
327 VERIFY_BITS(t0, 26);
328 VERIFY_BITS(c, 37);
71712b27
GM
329 /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
330 /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
5dd421ba
PD
331
332 c += (uint64_t)a[0] * b[1]
333 + (uint64_t)a[1] * b[0];
f8cce956 334 VERIFY_BITS(c, 62);
71712b27 335 /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */
5dd421ba
PD
336 d += (uint64_t)a[2] * b[9]
337 + (uint64_t)a[3] * b[8]
338 + (uint64_t)a[4] * b[7]
339 + (uint64_t)a[5] * b[6]
340 + (uint64_t)a[6] * b[5]
341 + (uint64_t)a[7] * b[4]
342 + (uint64_t)a[8] * b[3]
343 + (uint64_t)a[9] * b[2];
f8cce956 344 VERIFY_BITS(d, 63);
71712b27 345 /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
5dd421ba 346 uint64_t u1 = d & M; d >>= 26; c += u1 * R0;
f8cce956
PW
347 VERIFY_BITS(u1, 26);
348 VERIFY_BITS(d, 37);
349 VERIFY_BITS(c, 63);
71712b27 350 /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
5dd421ba 351 uint32_t t1 = c & M; c >>= 26; c += u1 * R1;
f8cce956
PW
352 VERIFY_BITS(t1, 26);
353 VERIFY_BITS(c, 38);
71712b27
GM
354 /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
355 /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
5dd421ba
PD
356
357 c += (uint64_t)a[0] * b[2]
358 + (uint64_t)a[1] * b[1]
359 + (uint64_t)a[2] * b[0];
f8cce956 360 VERIFY_BITS(c, 62);
71712b27 361 /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
5dd421ba
PD
362 d += (uint64_t)a[3] * b[9]
363 + (uint64_t)a[4] * b[8]
364 + (uint64_t)a[5] * b[7]
365 + (uint64_t)a[6] * b[6]
366 + (uint64_t)a[7] * b[5]
367 + (uint64_t)a[8] * b[4]
368 + (uint64_t)a[9] * b[3];
f8cce956 369 VERIFY_BITS(d, 63);
71712b27 370 /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
5dd421ba 371 uint64_t u2 = d & M; d >>= 26; c += u2 * R0;
f8cce956
PW
372 VERIFY_BITS(u2, 26);
373 VERIFY_BITS(d, 37);
374 VERIFY_BITS(c, 63);
71712b27 375 /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
5dd421ba 376 uint32_t t2 = c & M; c >>= 26; c += u2 * R1;
f8cce956
PW
377 VERIFY_BITS(t2, 26);
378 VERIFY_BITS(c, 38);
71712b27
GM
379 /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
380 /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
5dd421ba
PD
381
382 c += (uint64_t)a[0] * b[3]
383 + (uint64_t)a[1] * b[2]
384 + (uint64_t)a[2] * b[1]
385 + (uint64_t)a[3] * b[0];
f8cce956 386 VERIFY_BITS(c, 63);
71712b27 387 /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
5dd421ba
PD
388 d += (uint64_t)a[4] * b[9]
389 + (uint64_t)a[5] * b[8]
390 + (uint64_t)a[6] * b[7]
391 + (uint64_t)a[7] * b[6]
392 + (uint64_t)a[8] * b[5]
393 + (uint64_t)a[9] * b[4];
f8cce956 394 VERIFY_BITS(d, 63);
71712b27 395 /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
5dd421ba 396 uint64_t u3 = d & M; d >>= 26; c += u3 * R0;
f8cce956
PW
397 VERIFY_BITS(u3, 26);
398 VERIFY_BITS(d, 37);
71712b27
GM
399 /* VERIFY_BITS(c, 64); */
400 /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
5dd421ba 401 uint32_t t3 = c & M; c >>= 26; c += u3 * R1;
f8cce956
PW
402 VERIFY_BITS(t3, 26);
403 VERIFY_BITS(c, 39);
71712b27
GM
404 /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
405 /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
5dd421ba
PD
406
407 c += (uint64_t)a[0] * b[4]
408 + (uint64_t)a[1] * b[3]
409 + (uint64_t)a[2] * b[2]
410 + (uint64_t)a[3] * b[1]
411 + (uint64_t)a[4] * b[0];
f8cce956 412 VERIFY_BITS(c, 63);
71712b27 413 /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
5dd421ba
PD
414 d += (uint64_t)a[5] * b[9]
415 + (uint64_t)a[6] * b[8]
416 + (uint64_t)a[7] * b[7]
417 + (uint64_t)a[8] * b[6]
418 + (uint64_t)a[9] * b[5];
f8cce956 419 VERIFY_BITS(d, 62);
71712b27 420 /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
5dd421ba 421 uint64_t u4 = d & M; d >>= 26; c += u4 * R0;
f8cce956
PW
422 VERIFY_BITS(u4, 26);
423 VERIFY_BITS(d, 36);
71712b27
GM
424 /* VERIFY_BITS(c, 64); */
425 /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
5dd421ba 426 uint32_t t4 = c & M; c >>= 26; c += u4 * R1;
f8cce956
PW
427 VERIFY_BITS(t4, 26);
428 VERIFY_BITS(c, 39);
71712b27
GM
429 /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
430 /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
5dd421ba
PD
431
432 c += (uint64_t)a[0] * b[5]
433 + (uint64_t)a[1] * b[4]
434 + (uint64_t)a[2] * b[3]
435 + (uint64_t)a[3] * b[2]
436 + (uint64_t)a[4] * b[1]
437 + (uint64_t)a[5] * b[0];
f8cce956 438 VERIFY_BITS(c, 63);
71712b27 439 /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
440 d += (uint64_t)a[6] * b[9]
441 + (uint64_t)a[7] * b[8]
442 + (uint64_t)a[8] * b[7]
443 + (uint64_t)a[9] * b[6];
f8cce956 444 VERIFY_BITS(d, 62);
71712b27 445 /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
5dd421ba 446 uint64_t u5 = d & M; d >>= 26; c += u5 * R0;
f8cce956
PW
447 VERIFY_BITS(u5, 26);
448 VERIFY_BITS(d, 36);
71712b27
GM
449 /* VERIFY_BITS(c, 64); */
450 /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
5dd421ba 451 uint32_t t5 = c & M; c >>= 26; c += u5 * R1;
f8cce956
PW
452 VERIFY_BITS(t5, 26);
453 VERIFY_BITS(c, 39);
71712b27
GM
454 /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
455 /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
456
457 c += (uint64_t)a[0] * b[6]
458 + (uint64_t)a[1] * b[5]
459 + (uint64_t)a[2] * b[4]
460 + (uint64_t)a[3] * b[3]
461 + (uint64_t)a[4] * b[2]
462 + (uint64_t)a[5] * b[1]
463 + (uint64_t)a[6] * b[0];
f8cce956 464 VERIFY_BITS(c, 63);
71712b27 465 /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
466 d += (uint64_t)a[7] * b[9]
467 + (uint64_t)a[8] * b[8]
468 + (uint64_t)a[9] * b[7];
f8cce956 469 VERIFY_BITS(d, 61);
71712b27 470 /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 471 uint64_t u6 = d & M; d >>= 26; c += u6 * R0;
f8cce956
PW
472 VERIFY_BITS(u6, 26);
473 VERIFY_BITS(d, 35);
71712b27
GM
474 /* VERIFY_BITS(c, 64); */
475 /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 476 uint32_t t6 = c & M; c >>= 26; c += u6 * R1;
f8cce956
PW
477 VERIFY_BITS(t6, 26);
478 VERIFY_BITS(c, 39);
71712b27
GM
479 /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
480 /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
481
482 c += (uint64_t)a[0] * b[7]
483 + (uint64_t)a[1] * b[6]
484 + (uint64_t)a[2] * b[5]
485 + (uint64_t)a[3] * b[4]
486 + (uint64_t)a[4] * b[3]
487 + (uint64_t)a[5] * b[2]
488 + (uint64_t)a[6] * b[1]
489 + (uint64_t)a[7] * b[0];
71712b27 490 /* VERIFY_BITS(c, 64); */
f8cce956 491 VERIFY_CHECK(c <= 0x8000007C00000007ULL);
71712b27 492 /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
493 d += (uint64_t)a[8] * b[9]
494 + (uint64_t)a[9] * b[8];
f8cce956 495 VERIFY_BITS(d, 58);
71712b27 496 /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 497 uint64_t u7 = d & M; d >>= 26; c += u7 * R0;
f8cce956
PW
498 VERIFY_BITS(u7, 26);
499 VERIFY_BITS(d, 32);
71712b27 500 /* VERIFY_BITS(c, 64); */
f8cce956 501 VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL);
71712b27 502 /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 503 uint32_t t7 = c & M; c >>= 26; c += u7 * R1;
f8cce956
PW
504 VERIFY_BITS(t7, 26);
505 VERIFY_BITS(c, 38);
71712b27
GM
506 /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
507 /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
508
509 c += (uint64_t)a[0] * b[8]
510 + (uint64_t)a[1] * b[7]
511 + (uint64_t)a[2] * b[6]
512 + (uint64_t)a[3] * b[5]
513 + (uint64_t)a[4] * b[4]
514 + (uint64_t)a[5] * b[3]
515 + (uint64_t)a[6] * b[2]
516 + (uint64_t)a[7] * b[1]
517 + (uint64_t)a[8] * b[0];
71712b27 518 /* VERIFY_BITS(c, 64); */
f8cce956 519 VERIFY_CHECK(c <= 0x9000007B80000008ULL);
71712b27 520 /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 521 d += (uint64_t)a[9] * b[9];
f8cce956 522 VERIFY_BITS(d, 57);
71712b27 523 /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 524 uint64_t u8 = d & M; d >>= 26; c += u8 * R0;
f8cce956
PW
525 VERIFY_BITS(u8, 26);
526 VERIFY_BITS(d, 31);
71712b27 527 /* VERIFY_BITS(c, 64); */
f8cce956 528 VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL);
71712b27 529 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
530
531 r[3] = t3;
f8cce956 532 VERIFY_BITS(r[3], 26);
71712b27 533 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 534 r[4] = t4;
f8cce956 535 VERIFY_BITS(r[4], 26);
71712b27 536 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 537 r[5] = t5;
f8cce956 538 VERIFY_BITS(r[5], 26);
71712b27 539 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 540 r[6] = t6;
f8cce956 541 VERIFY_BITS(r[6], 26);
71712b27 542 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 543 r[7] = t7;
f8cce956 544 VERIFY_BITS(r[7], 26);
71712b27 545 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
546
547 r[8] = c & M; c >>= 26; c += u8 * R1;
f8cce956
PW
548 VERIFY_BITS(r[8], 26);
549 VERIFY_BITS(c, 39);
71712b27
GM
550 /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
551 /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 552 c += d * R0 + t9;
f8cce956 553 VERIFY_BITS(c, 45);
71712b27 554 /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 555 r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4);
f8cce956
PW
556 VERIFY_BITS(r[9], 22);
557 VERIFY_BITS(c, 46);
71712b27
GM
558 /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
559 /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
560 /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
561
562 d = c * (R0 >> 4) + t0;
f8cce956 563 VERIFY_BITS(d, 56);
71712b27 564 /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 565 r[0] = d & M; d >>= 26;
f8cce956
PW
566 VERIFY_BITS(r[0], 26);
567 VERIFY_BITS(d, 30);
71712b27 568 /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 569 d += c * (R1 >> 4) + t1;
f8cce956
PW
570 VERIFY_BITS(d, 53);
571 VERIFY_CHECK(d <= 0x10000003FFFFBFULL);
71712b27
GM
572 /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
573 /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 574 r[1] = d & M; d >>= 26;
f8cce956
PW
575 VERIFY_BITS(r[1], 26);
576 VERIFY_BITS(d, 27);
577 VERIFY_CHECK(d <= 0x4000000ULL);
71712b27 578 /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 579 d += t2;
f8cce956 580 VERIFY_BITS(d, 27);
71712b27 581 /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 582 r[2] = d;
f8cce956 583 VERIFY_BITS(r[2], 27);
71712b27 584 /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
3231676b
PW
585}
586
a4a43d75 587SECP256K1_INLINE static void secp256k1_fe_sqr_inner(const uint32_t *a, uint32_t *r) {
f8cce956
PW
588 VERIFY_BITS(a[0], 30);
589 VERIFY_BITS(a[1], 30);
590 VERIFY_BITS(a[2], 30);
591 VERIFY_BITS(a[3], 30);
592 VERIFY_BITS(a[4], 30);
593 VERIFY_BITS(a[5], 30);
594 VERIFY_BITS(a[6], 30);
595 VERIFY_BITS(a[7], 30);
596 VERIFY_BITS(a[8], 30);
597 VERIFY_BITS(a[9], 26);
5dd421ba
PD
598
599 const uint32_t M = 0x3FFFFFFUL, R0 = 0x3D10UL, R1 = 0x400UL;
71712b27
GM
600 /** [... a b c] is a shorthand for ... + a<<52 + b<<26 + c<<0 mod n.
601 * px is a shorthand for sum(a[i]*a[x-i], i=0..x).
602 * Note that [x 0 0 0 0 0 0 0 0 0 0] = [x*R1 x*R0].
603 */
5dd421ba
PD
604
605 uint64_t c, d;
606
607 d = (uint64_t)(a[0]*2) * a[9]
608 + (uint64_t)(a[1]*2) * a[8]
609 + (uint64_t)(a[2]*2) * a[7]
610 + (uint64_t)(a[3]*2) * a[6]
611 + (uint64_t)(a[4]*2) * a[5];
71712b27
GM
612 /* VERIFY_BITS(d, 64); */
613 /* [d 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
5dd421ba 614 uint32_t t9 = d & M; d >>= 26;
f8cce956
PW
615 VERIFY_BITS(t9, 26);
616 VERIFY_BITS(d, 38);
71712b27 617 /* [d t9 0 0 0 0 0 0 0 0 0] = [p9 0 0 0 0 0 0 0 0 0] */
5dd421ba
PD
618
619 c = (uint64_t)a[0] * a[0];
f8cce956 620 VERIFY_BITS(c, 60);
71712b27 621 /* [d t9 0 0 0 0 0 0 0 0 c] = [p9 0 0 0 0 0 0 0 0 p0] */
5dd421ba
PD
622 d += (uint64_t)(a[1]*2) * a[9]
623 + (uint64_t)(a[2]*2) * a[8]
624 + (uint64_t)(a[3]*2) * a[7]
625 + (uint64_t)(a[4]*2) * a[6]
626 + (uint64_t)a[5] * a[5];
f8cce956 627 VERIFY_BITS(d, 63);
71712b27 628 /* [d t9 0 0 0 0 0 0 0 0 c] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
5dd421ba 629 uint64_t u0 = d & M; d >>= 26; c += u0 * R0;
f8cce956
PW
630 VERIFY_BITS(u0, 26);
631 VERIFY_BITS(d, 37);
632 VERIFY_BITS(c, 61);
71712b27 633 /* [d u0 t9 0 0 0 0 0 0 0 0 c-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
5dd421ba 634 uint32_t t0 = c & M; c >>= 26; c += u0 * R1;
f8cce956
PW
635 VERIFY_BITS(t0, 26);
636 VERIFY_BITS(c, 37);
71712b27
GM
637 /* [d u0 t9 0 0 0 0 0 0 0 c-u0*R1 t0-u0*R0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
638 /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 0 p0] */
5dd421ba
PD
639
640 c += (uint64_t)(a[0]*2) * a[1];
f8cce956 641 VERIFY_BITS(c, 62);
71712b27 642 /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p10 p9 0 0 0 0 0 0 0 p1 p0] */
5dd421ba
PD
643 d += (uint64_t)(a[2]*2) * a[9]
644 + (uint64_t)(a[3]*2) * a[8]
645 + (uint64_t)(a[4]*2) * a[7]
646 + (uint64_t)(a[5]*2) * a[6];
f8cce956 647 VERIFY_BITS(d, 63);
71712b27 648 /* [d 0 t9 0 0 0 0 0 0 0 c t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
5dd421ba 649 uint64_t u1 = d & M; d >>= 26; c += u1 * R0;
f8cce956
PW
650 VERIFY_BITS(u1, 26);
651 VERIFY_BITS(d, 37);
652 VERIFY_BITS(c, 63);
71712b27 653 /* [d u1 0 t9 0 0 0 0 0 0 0 c-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
5dd421ba 654 uint32_t t1 = c & M; c >>= 26; c += u1 * R1;
f8cce956
PW
655 VERIFY_BITS(t1, 26);
656 VERIFY_BITS(c, 38);
71712b27
GM
657 /* [d u1 0 t9 0 0 0 0 0 0 c-u1*R1 t1-u1*R0 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
658 /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 0 p1 p0] */
5dd421ba
PD
659
660 c += (uint64_t)(a[0]*2) * a[2]
661 + (uint64_t)a[1] * a[1];
f8cce956 662 VERIFY_BITS(c, 62);
71712b27 663 /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
5dd421ba
PD
664 d += (uint64_t)(a[3]*2) * a[9]
665 + (uint64_t)(a[4]*2) * a[8]
666 + (uint64_t)(a[5]*2) * a[7]
667 + (uint64_t)a[6] * a[6];
f8cce956 668 VERIFY_BITS(d, 63);
71712b27 669 /* [d 0 0 t9 0 0 0 0 0 0 c t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
5dd421ba 670 uint64_t u2 = d & M; d >>= 26; c += u2 * R0;
f8cce956
PW
671 VERIFY_BITS(u2, 26);
672 VERIFY_BITS(d, 37);
673 VERIFY_BITS(c, 63);
71712b27 674 /* [d u2 0 0 t9 0 0 0 0 0 0 c-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
5dd421ba 675 uint32_t t2 = c & M; c >>= 26; c += u2 * R1;
f8cce956
PW
676 VERIFY_BITS(t2, 26);
677 VERIFY_BITS(c, 38);
71712b27
GM
678 /* [d u2 0 0 t9 0 0 0 0 0 c-u2*R1 t2-u2*R0 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
679 /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 0 p2 p1 p0] */
5dd421ba
PD
680
681 c += (uint64_t)(a[0]*2) * a[3]
682 + (uint64_t)(a[1]*2) * a[2];
f8cce956 683 VERIFY_BITS(c, 63);
71712b27 684 /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
5dd421ba
PD
685 d += (uint64_t)(a[4]*2) * a[9]
686 + (uint64_t)(a[5]*2) * a[8]
687 + (uint64_t)(a[6]*2) * a[7];
f8cce956 688 VERIFY_BITS(d, 63);
71712b27 689 /* [d 0 0 0 t9 0 0 0 0 0 c t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
5dd421ba 690 uint64_t u3 = d & M; d >>= 26; c += u3 * R0;
f8cce956
PW
691 VERIFY_BITS(u3, 26);
692 VERIFY_BITS(d, 37);
71712b27
GM
693 /* VERIFY_BITS(c, 64); */
694 /* [d u3 0 0 0 t9 0 0 0 0 0 c-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
5dd421ba 695 uint32_t t3 = c & M; c >>= 26; c += u3 * R1;
f8cce956
PW
696 VERIFY_BITS(t3, 26);
697 VERIFY_BITS(c, 39);
71712b27
GM
698 /* [d u3 0 0 0 t9 0 0 0 0 c-u3*R1 t3-u3*R0 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
699 /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 0 p3 p2 p1 p0] */
5dd421ba
PD
700
701 c += (uint64_t)(a[0]*2) * a[4]
702 + (uint64_t)(a[1]*2) * a[3]
703 + (uint64_t)a[2] * a[2];
f8cce956 704 VERIFY_BITS(c, 63);
71712b27 705 /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
5dd421ba
PD
706 d += (uint64_t)(a[5]*2) * a[9]
707 + (uint64_t)(a[6]*2) * a[8]
708 + (uint64_t)a[7] * a[7];
f8cce956 709 VERIFY_BITS(d, 62);
71712b27 710 /* [d 0 0 0 0 t9 0 0 0 0 c t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
5dd421ba 711 uint64_t u4 = d & M; d >>= 26; c += u4 * R0;
f8cce956
PW
712 VERIFY_BITS(u4, 26);
713 VERIFY_BITS(d, 36);
71712b27
GM
714 /* VERIFY_BITS(c, 64); */
715 /* [d u4 0 0 0 0 t9 0 0 0 0 c-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
5dd421ba 716 uint32_t t4 = c & M; c >>= 26; c += u4 * R1;
f8cce956
PW
717 VERIFY_BITS(t4, 26);
718 VERIFY_BITS(c, 39);
71712b27
GM
719 /* [d u4 0 0 0 0 t9 0 0 0 c-u4*R1 t4-u4*R0 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
720 /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 0 p4 p3 p2 p1 p0] */
5dd421ba
PD
721
722 c += (uint64_t)(a[0]*2) * a[5]
723 + (uint64_t)(a[1]*2) * a[4]
724 + (uint64_t)(a[2]*2) * a[3];
f8cce956 725 VERIFY_BITS(c, 63);
71712b27 726 /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
727 d += (uint64_t)(a[6]*2) * a[9]
728 + (uint64_t)(a[7]*2) * a[8];
f8cce956 729 VERIFY_BITS(d, 62);
71712b27 730 /* [d 0 0 0 0 0 t9 0 0 0 c t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
5dd421ba 731 uint64_t u5 = d & M; d >>= 26; c += u5 * R0;
f8cce956
PW
732 VERIFY_BITS(u5, 26);
733 VERIFY_BITS(d, 36);
71712b27
GM
734 /* VERIFY_BITS(c, 64); */
735 /* [d u5 0 0 0 0 0 t9 0 0 0 c-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
5dd421ba 736 uint32_t t5 = c & M; c >>= 26; c += u5 * R1;
f8cce956
PW
737 VERIFY_BITS(t5, 26);
738 VERIFY_BITS(c, 39);
71712b27
GM
739 /* [d u5 0 0 0 0 0 t9 0 0 c-u5*R1 t5-u5*R0 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
740 /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 0 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
741
742 c += (uint64_t)(a[0]*2) * a[6]
743 + (uint64_t)(a[1]*2) * a[5]
744 + (uint64_t)(a[2]*2) * a[4]
745 + (uint64_t)a[3] * a[3];
f8cce956 746 VERIFY_BITS(c, 63);
71712b27 747 /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
748 d += (uint64_t)(a[7]*2) * a[9]
749 + (uint64_t)a[8] * a[8];
f8cce956 750 VERIFY_BITS(d, 61);
71712b27 751 /* [d 0 0 0 0 0 0 t9 0 0 c t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 752 uint64_t u6 = d & M; d >>= 26; c += u6 * R0;
f8cce956
PW
753 VERIFY_BITS(u6, 26);
754 VERIFY_BITS(d, 35);
71712b27
GM
755 /* VERIFY_BITS(c, 64); */
756 /* [d u6 0 0 0 0 0 0 t9 0 0 c-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 757 uint32_t t6 = c & M; c >>= 26; c += u6 * R1;
f8cce956
PW
758 VERIFY_BITS(t6, 26);
759 VERIFY_BITS(c, 39);
71712b27
GM
760 /* [d u6 0 0 0 0 0 0 t9 0 c-u6*R1 t6-u6*R0 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
761 /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 0 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
762
763 c += (uint64_t)(a[0]*2) * a[7]
764 + (uint64_t)(a[1]*2) * a[6]
765 + (uint64_t)(a[2]*2) * a[5]
766 + (uint64_t)(a[3]*2) * a[4];
71712b27 767 /* VERIFY_BITS(c, 64); */
f8cce956 768 VERIFY_CHECK(c <= 0x8000007C00000007ULL);
71712b27 769 /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 770 d += (uint64_t)(a[8]*2) * a[9];
f8cce956 771 VERIFY_BITS(d, 58);
71712b27 772 /* [d 0 0 0 0 0 0 0 t9 0 c t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 773 uint64_t u7 = d & M; d >>= 26; c += u7 * R0;
f8cce956
PW
774 VERIFY_BITS(u7, 26);
775 VERIFY_BITS(d, 32);
71712b27 776 /* VERIFY_BITS(c, 64); */
f8cce956 777 VERIFY_CHECK(c <= 0x800001703FFFC2F7ULL);
71712b27 778 /* [d u7 0 0 0 0 0 0 0 t9 0 c-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 779 uint32_t t7 = c & M; c >>= 26; c += u7 * R1;
f8cce956
PW
780 VERIFY_BITS(t7, 26);
781 VERIFY_BITS(c, 38);
71712b27
GM
782 /* [d u7 0 0 0 0 0 0 0 t9 c-u7*R1 t7-u7*R0 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
783 /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 0 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
784
785 c += (uint64_t)(a[0]*2) * a[8]
786 + (uint64_t)(a[1]*2) * a[7]
787 + (uint64_t)(a[2]*2) * a[6]
788 + (uint64_t)(a[3]*2) * a[5]
789 + (uint64_t)a[4] * a[4];
71712b27 790 /* VERIFY_BITS(c, 64); */
f8cce956 791 VERIFY_CHECK(c <= 0x9000007B80000008ULL);
71712b27 792 /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 793 d += (uint64_t)a[9] * a[9];
f8cce956 794 VERIFY_BITS(d, 57);
71712b27 795 /* [d 0 0 0 0 0 0 0 0 t9 c t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 796 uint64_t u8 = d & M; d >>= 26; c += u8 * R0;
f8cce956
PW
797 VERIFY_BITS(u8, 26);
798 VERIFY_BITS(d, 31);
71712b27 799 /* VERIFY_BITS(c, 64); */
f8cce956 800 VERIFY_CHECK(c <= 0x9000016FBFFFC2F8ULL);
71712b27 801 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 t3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
802
803 r[3] = t3;
f8cce956 804 VERIFY_BITS(r[3], 26);
71712b27 805 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 t4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 806 r[4] = t4;
f8cce956 807 VERIFY_BITS(r[4], 26);
71712b27 808 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 t5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 809 r[5] = t5;
f8cce956 810 VERIFY_BITS(r[5], 26);
71712b27 811 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 t6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 812 r[6] = t6;
f8cce956 813 VERIFY_BITS(r[6], 26);
71712b27 814 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 t7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 815 r[7] = t7;
f8cce956 816 VERIFY_BITS(r[7], 26);
71712b27 817 /* [d u8 0 0 0 0 0 0 0 0 t9 c-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
818
819 r[8] = c & M; c >>= 26; c += u8 * R1;
f8cce956
PW
820 VERIFY_BITS(r[8], 26);
821 VERIFY_BITS(c, 39);
71712b27
GM
822 /* [d u8 0 0 0 0 0 0 0 0 t9+c-u8*R1 r8-u8*R0 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
823 /* [d 0 0 0 0 0 0 0 0 0 t9+c r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 824 c += d * R0 + t9;
f8cce956 825 VERIFY_BITS(c, 45);
71712b27 826 /* [d 0 0 0 0 0 0 0 0 0 c-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 827 r[9] = c & (M >> 4); c >>= 22; c += d * (R1 << 4);
f8cce956
PW
828 VERIFY_BITS(r[9], 22);
829 VERIFY_BITS(c, 46);
71712b27
GM
830 /* [d 0 0 0 0 0 0 0 0 r9+((c-d*R1<<4)<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
831 /* [d 0 0 0 0 0 0 0 -d*R1 r9+(c<<22)-d*R0 r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
832 /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 t0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba
PD
833
834 d = c * (R0 >> 4) + t0;
f8cce956 835 VERIFY_BITS(d, 56);
71712b27 836 /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1 d-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 837 r[0] = d & M; d >>= 26;
f8cce956
PW
838 VERIFY_BITS(r[0], 26);
839 VERIFY_BITS(d, 30);
71712b27 840 /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 t1+d r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 841 d += c * (R1 >> 4) + t1;
f8cce956
PW
842 VERIFY_BITS(d, 53);
843 VERIFY_CHECK(d <= 0x10000003FFFFBFULL);
71712b27
GM
844 /* [r9+(c<<22) r8 r7 r6 r5 r4 r3 t2 d-c*R1>>4 r0-c*R0>>4] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
845 /* [r9 r8 r7 r6 r5 r4 r3 t2 d r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 846 r[1] = d & M; d >>= 26;
f8cce956
PW
847 VERIFY_BITS(r[1], 26);
848 VERIFY_BITS(d, 27);
849 VERIFY_CHECK(d <= 0x4000000ULL);
71712b27 850 /* [r9 r8 r7 r6 r5 r4 r3 t2+d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 851 d += t2;
f8cce956 852 VERIFY_BITS(d, 27);
71712b27 853 /* [r9 r8 r7 r6 r5 r4 r3 d r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
5dd421ba 854 r[2] = d;
f8cce956 855 VERIFY_BITS(r[2], 27);
71712b27 856 /* [r9 r8 r7 r6 r5 r4 r3 r2 r1 r0] = [p18 p17 p16 p15 p14 p13 p12 p11 p10 p9 p8 p7 p6 p5 p4 p3 p2 p1 p0] */
3231676b
PW
857}
858
859
a4a43d75 860static void secp256k1_fe_mul(secp256k1_fe_t *r, const secp256k1_fe_t *a, const secp256k1_fe_t *b) {
3231676b 861#ifdef VERIFY
1c7fa133
PW
862 VERIFY_CHECK(a->magnitude <= 8);
863 VERIFY_CHECK(b->magnitude <= 8);
7d681ac6
PD
864 secp256k1_fe_verify(a);
865 secp256k1_fe_verify(b);
866#endif
867 secp256k1_fe_mul_inner(a->n, b->n, r->n);
868#ifdef VERIFY
3231676b
PW
869 r->magnitude = 1;
870 r->normalized = 0;
7d681ac6 871 secp256k1_fe_verify(r);
3231676b 872#endif
3231676b
PW
873}
874
a4a43d75 875static void secp256k1_fe_sqr(secp256k1_fe_t *r, const secp256k1_fe_t *a) {
3231676b 876#ifdef VERIFY
1c7fa133 877 VERIFY_CHECK(a->magnitude <= 8);
7d681ac6
PD
878 secp256k1_fe_verify(a);
879#endif
880 secp256k1_fe_sqr_inner(a->n, r->n);
881#ifdef VERIFY
3231676b
PW
882 r->magnitude = 1;
883 r->normalized = 0;
7d681ac6 884 secp256k1_fe_verify(r);
3231676b 885#endif
3231676b 886}
7a4b7691
PW
887
888#endif
This page took 0.143963 seconds and 4 git commands to generate.