]>
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 | ||
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 |
16 | static void secp256k1_fe_inner_start(void) {} |
17 | static void secp256k1_fe_inner_stop(void) {} | |
6baf08df | 18 | |
7d681ac6 | 19 | #ifdef VERIFY |
a4a43d75 | 20 | static 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 |
46 | static void secp256k1_fe_verify(const secp256k1_fe_t *a) { |
47 | (void)a; | |
48 | } | |
7d681ac6 PD |
49 | #endif |
50 | ||
a4a43d75 | 51 | static 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 | 106 | SECP256K1_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 | 116 | SECP256K1_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 | 125 | SECP256K1_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 | 133 | SECP256K1_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 | 143 | SECP256K1_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 | 155 | static 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 | 177 | static 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 | 193 | SECP256K1_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 | 215 | SECP256K1_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 | 233 | SECP256K1_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 | 260 | SECP256K1_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 | 587 | SECP256K1_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 | 860 | static 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 | 875 | static 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 |