GCC Code Coverage Report


Directory: ./
File: src/modules/ellswift/main_impl.h
Date: 2023-04-24 14:08:55
Exec Total Coverage
Lines: 211 212 99.5%
Functions: 11 11 100.0%
Branches: 58 74 78.4%

Line Branch Exec Source
1 /***********************************************************************
2 * Copyright (c) 2022 Pieter Wuille *
3 * Distributed under the MIT software license, see the accompanying *
4 * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
5 ***********************************************************************/
6
7 #ifndef SECP256K1_MODULE_ELLSWIFT_MAIN_H
8 #define SECP256K1_MODULE_ELLSWIFT_MAIN_H
9
10 #include "../../../include/secp256k1.h"
11 #include "../../../include/secp256k1_ellswift.h"
12 #include "../../hash.h"
13
14 /** c1 = (sqrt(-3)-1)/2 */
15 static const secp256k1_fe secp256k1_ellswift_c1 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa40);
16 /** c2 = (-sqrt(-3)-1)/2 = -(c1+1) */
17 static const secp256k1_fe secp256k1_ellswift_c2 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ee);
18 /** c3 = (-sqrt(-3)+1)/2 = -c1 = c2+1 */
19 static const secp256k1_fe secp256k1_ellswift_c3 = SECP256K1_FE_CONST(0x7ae96a2b, 0x657c0710, 0x6e64479e, 0xac3434e9, 0x9cf04975, 0x12f58995, 0xc1396c28, 0x719501ef);
20 /** c4 = (sqrt(-3)+1)/2 = -c2 = c1+1 */
21 static const secp256k1_fe secp256k1_ellswift_c4 = SECP256K1_FE_CONST(0x851695d4, 0x9a83f8ef, 0x919bb861, 0x53cbcb16, 0x630fb68a, 0xed0a766a, 0x3ec693d6, 0x8e6afa41);
22
23 /** Decode ElligatorSwift encoding (u, t) to a fraction xn/xd representing a curve X coordinate. */
24 243374 static void secp256k1_ellswift_xswiftec_frac_var(secp256k1_fe *xn, secp256k1_fe *xd, const secp256k1_fe *u, const secp256k1_fe *t) {
25 /* The implemented algorithm is the following (all operations in GF(p)):
26 *
27 * - c0 = sqrt(-3) = 0xa2d2ba93507f1df233770c2a797962cc61f6d15da14ecd47d8d27ae1cd5f852
28 * - If u=0, set u=1.
29 * - If t=0, set t=1.
30 * - If u^3+7+t^2 = 0, set t=2*t.
31 * - Let X=(u^3+7-t^2)/(2*t)
32 * - Let Y=(X+t)/(c0*u)
33 * - If x3=u+4*Y^2 is a valid x coordinate, return x3.
34 * - If x2=(-X/Y-u)/2 is a valid x coordinare, return x2.
35 * - Return x1=(X/Y-u)/2 (which is now guaranteed to be a valid x coordinate).
36 *
37 * Introducing s=t^2, g=u^3+7, and simplifying x1=-(x2+u) we get:
38 *
39 * - ...
40 * - Let s=t^2
41 * - Let g=u^3+7
42 * - If g+s=0, set t=2*t, s=4*s
43 * - Let X=(g-s)/(2*t)
44 * - Let Y=(X+t)/(c0*u) = (g+s)/(2*c0*t*u)
45 * - If x3=u+4*Y^2 is a valid x coordinate, return x3.
46 * - If x2=(-X/Y-u)/2 is a valid x coordinate, return it.
47 * - Return x1=-(x2+u).
48 *
49 * Now substitute Y^2 = -(g+s)^2/(12*s*u^2) and X/Y = c0*u*(g-s)/(g+s)
50 *
51 * - ...
52 * - If g+s=0, set s=4*s
53 * - If x3=u-(g+s)^2/(3*s*u^2) is a valid x coordinate, return it.
54 * - If x2=(-c0*u*(g-s)/(g+s)-u)/2 is a valid x coordinate, return it.
55 * - Return x1=(c0*u*(g-s)/(g+s)-u)/2.
56 *
57 * Simplifying x2 using 2 additional constants:
58 *
59 * - c1 = (c0-1)/2 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40
60 * - c2 = (-c0-1)/2 = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee
61 * - ...
62 * - If x2=u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it.
63 * - ...
64 *
65 * Writing x3 as a fraction:
66 *
67 * - ...
68 * - If x3=(3*s*u^3-(g+s)^2)/(3*s*u^2)
69 * - ...
70
71 * Overall, we get:
72 *
73 * - c1 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40
74 * - c2 = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee
75 * - If u=0, set u=1.
76 * - If t=0, set s=1, else set s=t^2
77 * - Let g=u^3+7
78 * - If g+s=0, set s=4*s
79 * - If x3=(3*s*u^3-(g+s)^2)/(3*s*u^2) is a valid x coordinate, return it.
80 * - If x2=u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it.
81 * - Return x1=-(x2+u)
82 */
83 secp256k1_fe u1, s, g, p, d, n, l;
84 243374 u1 = *u;
85
2/2
✓ Branch 1 taken 36 times.
✓ Branch 2 taken 243338 times.
243374 if (EXPECT(secp256k1_fe_normalizes_to_zero_var(&u1), 0)) u1 = secp256k1_fe_one;
86 243374 secp256k1_fe_sqr(&s, t);
87
2/2
✓ Branch 1 taken 30 times.
✓ Branch 2 taken 243344 times.
243374 if (EXPECT(secp256k1_fe_normalizes_to_zero_var(t), 0)) s = secp256k1_fe_one;
88 243374 secp256k1_fe_sqr(&l, &u1); /* l = u^2 */
89 243374 secp256k1_fe_mul(&g, &l, &u1); /* g = u^3 */
90 243374 secp256k1_fe_add_int(&g, SECP256K1_B); /* g = u^3 + 7 */
91 243374 p = g; /* p = g */
92 243374 secp256k1_fe_add(&p, &s); /* p = g+s */
93
2/2
✓ Branch 1 taken 14 times.
✓ Branch 2 taken 243360 times.
243374 if (EXPECT(secp256k1_fe_normalizes_to_zero_var(&p), 0)) {
94 14 secp256k1_fe_mul_int(&s, 4); /* s = 4*s */
95 /* recompute p = g+s */
96 14 p = g; /* p = g */
97 14 secp256k1_fe_add(&p, &s); /* p = g+s */
98 }
99 243374 secp256k1_fe_mul(&d, &s, &l); /* d = s*u^2 */
100 243374 secp256k1_fe_mul_int(&d, 3); /* d = 3*s*u^2 */
101 243374 secp256k1_fe_sqr(&l, &p); /* l = (g+s)^2 */
102 243374 secp256k1_fe_negate(&l, &l, 1); /* l = -(g+s)^2 */
103 243374 secp256k1_fe_mul(&n, &d, &u1); /* n = 3*s*u^3 */
104 243374 secp256k1_fe_add(&n, &l); /* n = 3*s*u^3-(g+s)^2 */
105
2/2
✓ Branch 1 taken 122141 times.
✓ Branch 2 taken 121233 times.
243374 if (secp256k1_ge_x_frac_on_curve_var(&n, &d)) {
106 /* Return n/d = (3*s*u^3-(g+s)^2)/(3*s*u^2) */
107 122141 *xn = n;
108 122141 *xd = d;
109 182935 return;
110 }
111 121233 *xd = p;
112 121233 secp256k1_fe_mul(&l, &secp256k1_ellswift_c1, &s); /* l = c1*s */
113 121233 secp256k1_fe_mul(&n, &secp256k1_ellswift_c2, &g); /* n = c2*g */
114 121233 secp256k1_fe_add(&n, &l); /* n = c1*s+c2*g */
115 121233 secp256k1_fe_mul(&n, &n, &u1); /* n = u*(c1*s+c2*g) */
116 /* Possible optimization: in the invocation below, d^2 = (g+s)^2 is computed,
117 * which we already have computed above. This could be deduplicated. */
118
2/2
✓ Branch 1 taken 60794 times.
✓ Branch 2 taken 60439 times.
121233 if (secp256k1_ge_x_frac_on_curve_var(&n, &p)) {
119 /* Return n/p = u*(c1*s+c2*g)/(g+s) */
120 60794 *xn = n;
121 60794 return;
122 }
123 60439 secp256k1_fe_mul(&l, &p, &u1); /* l = u*(g+s) */
124 60439 secp256k1_fe_add(&n, &l); /* n = u*(c1*s+c2*g)+u*g*s */
125 60439 secp256k1_fe_negate(xn, &n, 2); /* n = -u*(c1*s+c2*g)+u*g*s */
126 #ifdef VERIFY
127 VERIFY_CHECK(secp256k1_ge_x_frac_on_curve_var(xn, &p));
128 #endif
129 /* Return n/p = -(u*(c1*s+c2*g)/(g+s)+u) */
130 }
131
132 /** Decode ElligatorSwift encoding (u, t) to X coordinate. */
133 140974 static void secp256k1_ellswift_xswiftec_var(secp256k1_fe *x, const secp256k1_fe *u, const secp256k1_fe *t) {
134 secp256k1_fe xn, xd;
135 140974 secp256k1_ellswift_xswiftec_frac_var(&xn, &xd, u, t);
136 140974 secp256k1_fe_inv_var(&xd, &xd);
137 140974 secp256k1_fe_mul(x, &xn, &xd);
138 140974 }
139
140 /** Decode ElligatorSwift encoding (u, t) to point P. */
141 140876 static void secp256k1_ellswift_swiftec_var(secp256k1_ge *p, const secp256k1_fe *u, const secp256k1_fe *t) {
142 secp256k1_fe x;
143 140876 secp256k1_ellswift_xswiftec_var(&x, u, t);
144 140876 secp256k1_ge_set_xo_var(p, &x, secp256k1_fe_is_odd(t));
145 140876 }
146
147 /* Try to complete an ElligatorSwift encoding (u, t) for X coordinate x, given u and x.
148 *
149 * There may be up to 8 distinct t values such that (u, t) decodes back to x, but also
150 * fewer, or none at all. Each such partial inverse can be accessed individually using a
151 * distinct input argument c (in range 0-7), and some or all of these may return failure.
152 * The following guarantees exist:
153 * - Given (x, u), no two distinct c values give the same successful result t.
154 * - Every successful result maps back to x through secp256k1_ellswift_xswiftec_var.
155 * - Given (x, u), all t values that map back to x can be reached by combining the
156 * successful results from this function over all c values, with the exception of:
157 * - this function cannot be called with u=0
158 * - no result with t=0 will be returned
159 * - no result for which u^3 + t^2 + 7 = 0 will be returned.
160 */
161 461012 static int secp256k1_ellswift_xswiftec_inv_var(secp256k1_fe *t, const secp256k1_fe *x_in, const secp256k1_fe *u_in, int c) {
162 /* The implemented algorithm is this (all arithmetic, except involving c, is mod p):
163 *
164 * - If (c & 2) = 0:
165 * - If (-x-u) is a valid X coordinate, fail.
166 * - Let s=-(u^3+7)/(u^2+u*x+x^2).
167 * - If s is not square, fail.
168 * - Let v=x.
169 * - If (c & 2) = 2:
170 * - Let s=x-u.
171 * - If s=0, fail.
172 * - If s is not square, fail.
173 * - Let r=sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist.
174 * - If (c & 1) = 1 and r = 0, fail.
175 * - Let v=(r/s-u)/2.
176 * - Let w=sqrt(s).
177 * - If (c & 5) = 0: return -w*(c3*u + v)
178 * - If (c & 5) = 1: return w*(c4*u + v)
179 * - If (c & 5) = 4: return w*(c3*u + v)
180 * - If (c & 5) = 5: return -w*(c4*u + v)
181 */
182 461012 secp256k1_fe x = *x_in, u = *u_in, u2, g, v, s, m, r, q;
183
184 /* Normalize. */
185 461012 secp256k1_fe_normalize_weak(&x);
186 461012 secp256k1_fe_normalize_weak(&u);
187
188
2/2
✓ Branch 0 taken 230177 times.
✓ Branch 1 taken 230835 times.
461012 if (!(c & 2)) {
189 /* If -u-x is a valid X coordinate, fail. */
190 230177 m = x; /* m = x */
191 230177 secp256k1_fe_add(&m, &u); /* m = u+x */
192 230177 secp256k1_fe_negate(&m, &m, 2); /* m = -u-x */
193
2/2
✓ Branch 1 taken 115058 times.
✓ Branch 2 taken 115119 times.
230177 if (secp256k1_ge_x_on_curve_var(&m)) return 0; /* test if -u-x on curve */
194
195 /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [first part] */
196 115119 secp256k1_fe_sqr(&s, &m); /* s = (u+x)^2 */
197 115119 secp256k1_fe_negate(&s, &s, 1); /* s= -(u+x)^2 */
198 115119 secp256k1_fe_mul(&m, &u, &x); /* m = u*x */
199 115119 secp256k1_fe_add(&s, &m); /* s = -(u^2 + u*x + x^2) */
200
201 /* If s is not square, fail. We have not fully computed s yet, but s is square iff
202 * -(u^3+7)*(u^2+u*x+x^2) is square. */
203 115119 secp256k1_fe_sqr(&g, &u); /* g = u^2 */
204 115119 secp256k1_fe_mul(&g, &g, &u); /* g = u^3 */
205 115119 secp256k1_fe_add_int(&g, SECP256K1_B); /* g = u^3+7 */
206 115119 secp256k1_fe_mul(&m, &s, &g); /* m = -(u^3 + 7)*(u^2 + u*x + x^2) */
207
2/2
✓ Branch 1 taken 57486 times.
✓ Branch 2 taken 57633 times.
115119 if (!secp256k1_fe_is_square_var(&m)) return 0;
208
209 /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [second part] */
210 57633 secp256k1_fe_inv_var(&s, &s); /* s = -1/(u^2 + u*x + x^2) */
211 57633 secp256k1_fe_mul(&s, &s, &g); /* s = -(u^3 + 7)/(u^2 + u*x + x^2) */
212
213 /* Let v = x. */
214 57633 v = x;
215 } else {
216 /* Let s = x-u. */
217 230835 secp256k1_fe_negate(&m, &u, 1); /* m = -u */
218 230835 s = m; /* s = -u */
219 230835 secp256k1_fe_add(&s, &x); /* s = x-u */
220
221 /* If s=0, fail. */
222
2/2
✓ Branch 1 taken 8 times.
✓ Branch 2 taken 230827 times.
230835 if (secp256k1_fe_normalizes_to_zero_var(&s)) return 0;
223
224 /* If s is not square, fail. */
225
2/2
✓ Branch 1 taken 115560 times.
✓ Branch 2 taken 115267 times.
230827 if (!secp256k1_fe_is_square_var(&s)) return 0;
226
227 /* Let r = sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist. */
228 115267 secp256k1_fe_sqr(&u2, &u); /* u2 = u^2 */
229 115267 secp256k1_fe_mul(&g, &u2, &u); /* g = u^3 */
230 115267 secp256k1_fe_add_int(&g, SECP256K1_B); /* g = u^3+7 */
231 115267 secp256k1_fe_normalize_weak(&g);
232 115267 secp256k1_fe_mul_int(&g, 4); /* g = 4*(u^3+7) */
233 115267 secp256k1_fe_mul_int(&u2, 3); /* u2 = 3*u^2 */
234 115267 secp256k1_fe_mul(&q, &s, &u2); /* q = 3*s*u^2 */
235 115267 secp256k1_fe_add(&q, &g); /* q = 4*(u^3+7)+3*s*u^2 */
236 115267 secp256k1_fe_mul(&q, &q, &s); /* q = s*(4*(u^3+7)+3*u^2*s) */
237 115267 secp256k1_fe_negate(&q, &q, 1); /* q = -s*(4*(u^3+7)+3*u^2*s) */
238
2/2
✓ Branch 1 taken 57596 times.
✓ Branch 2 taken 57671 times.
115267 if (!secp256k1_fe_is_square_var(&q)) return 0;
239 57671 secp256k1_fe_sqrt(&r, &q); /* r = sqrt(-s*(4*(u^3+7)+3*u^2*s)) */
240
241 /* If (c & 1) = 1 and r = 0, fail. */
242
4/4
✓ Branch 0 taken 29060 times.
✓ Branch 1 taken 28611 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 29054 times.
57671 if ((c & 1) && secp256k1_fe_normalizes_to_zero_var(&r)) return 0;
243
244 /* Let v=(r/s-u)/2. */
245 57665 secp256k1_fe_inv_var(&v, &s); /* v=1/s */
246 57665 secp256k1_fe_mul(&v, &v, &r); /* v=r/s */
247 57665 secp256k1_fe_add(&v, &m); /* v=r/s-u */
248 57665 secp256k1_fe_half(&v); /* v=(r/s-u)/2 */
249 }
250
251 /* Let w=sqrt(s). */
252 115298 secp256k1_fe_sqrt(&m, &s); /* m = sqrt(s) = w */
253
254 /* Return logic. */
255
4/4
✓ Branch 0 taken 86715 times.
✓ Branch 1 taken 28583 times.
✓ Branch 2 taken 28824 times.
✓ Branch 3 taken 57891 times.
115298 if ((c & 5) == 0 || (c & 5) == 5) {
256 57407 secp256k1_fe_negate(&m, &m, 1); /* m = -w */
257 }
258 /* Now m = {w if c&5=0 or c&5=5; -w otherwise}. */
259
2/2
✓ Branch 0 taken 57877 times.
✓ Branch 1 taken 57421 times.
115298 secp256k1_fe_mul(&u, &u, c&1 ? &secp256k1_ellswift_c4 : &secp256k1_ellswift_c3);
260 /* u = {c4 if c&1=1; c3 otherwise}*u */
261 115298 secp256k1_fe_add(&u, &v); /* u = {c4 if c&1=1; c3 otherwise}*u + v */
262 115298 secp256k1_fe_mul(t, &m, &u);
263 115298 return 1;
264 }
265
266 /** Find an ElligatorSwift encoding (u, t) for X coordinate x.
267 *
268 * hasher is a SHA256 object which a incrementing 4-byte counter is added to to
269 * generate randomness for the rejection sampling in this function. Its size plus
270 * 4 (for the counter) plus 9 (for the SHA256 padding) must be a multiple of 64
271 * for efficiency reasons.
272 */
273 115200 static void secp256k1_ellswift_xelligatorswift_var(secp256k1_fe *u, secp256k1_fe *t, const secp256k1_fe *x, const secp256k1_sha256 *hasher) {
274 /* Pool of 3-bit branch values. */
275 unsigned char branch_hash[32];
276 /* Number of 3-bit values in branch_hash left. */
277 115200 int branches_left = 0;
278 /* Field elements u and branch values are extracted from
279 * SHA256(hasher || cnt) for consecutive values of cnt. cnt==0
280 * is first used to populate a pool of 64 4-bit branch values. The 64 cnt
281 * values that follow are used to generate field elements u. cnt==65 (and
282 * multiples thereof) are used to repopulate the pool and start over, if
283 * that were ever necessary. */
284 115200 uint32_t cnt = 0;
285 VERIFY_CHECK((hasher->bytes + 4 + 9) % 64 == 0);
286 345556 while (1) {
287 int branch;
288 /* If the pool of branch values is empty, populate it. */
289
2/2
✓ Branch 0 taken 115200 times.
✓ Branch 1 taken 345556 times.
460756 if (branches_left == 0) {
290 115200 secp256k1_sha256 hash = *hasher;
291 unsigned char buf4[4];
292 115200 buf4[0] = cnt;
293 115200 buf4[1] = cnt >> 8;
294 115200 buf4[2] = cnt >> 16;
295 115200 buf4[3] = cnt >> 24;
296 115200 ++cnt;
297 115200 secp256k1_sha256_write(&hash, buf4, 4);
298 115200 secp256k1_sha256_finalize(&hash, branch_hash);
299 115200 branches_left = 64;
300 }
301 /* Take a 3-bit branch value from the branch pool (top bit is discarded). */
302 460756 --branches_left;
303 460756 branch = (branch_hash[branches_left >> 1] >> ((branches_left & 1) << 2)) & 7;
304 /* Compute a new u value by hashing. */
305 {
306 460756 secp256k1_sha256 hash = *hasher;
307 unsigned char buf4[4];
308 unsigned char u32[32];
309 460756 buf4[0] = cnt;
310 460756 buf4[1] = cnt >> 8;
311 460756 buf4[2] = cnt >> 16;
312 460756 buf4[3] = cnt >> 24;
313 460756 ++cnt;
314 460756 secp256k1_sha256_write(&hash, buf4, 4);
315 460756 secp256k1_sha256_finalize(&hash, u32);
316
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 460756 times.
460756 if (!secp256k1_fe_set_b32(u, u32)) continue;
317
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 460756 times.
460756 if (secp256k1_fe_is_zero(u)) continue;
318 }
319 /* Find a remainder t, and return it if found. */
320
2/2
✓ Branch 1 taken 115200 times.
✓ Branch 2 taken 345556 times.
460756 if (secp256k1_ellswift_xswiftec_inv_var(t, x, u, branch)) {
321 115200 secp256k1_fe_normalize_var(t);
322 115200 break;
323 }
324 }
325 115200 }
326
327 /** Find an ElligatorSwift encoding (u, t) for point P. */
328 115200 static void secp256k1_ellswift_elligatorswift_var(secp256k1_fe *u, secp256k1_fe *t, const secp256k1_ge *p, const secp256k1_sha256 *hasher) {
329 115200 secp256k1_ellswift_xelligatorswift_var(u, t, &p->x, hasher);
330
2/2
✓ Branch 2 taken 57597 times.
✓ Branch 3 taken 57603 times.
115200 if (secp256k1_fe_is_odd(t) != secp256k1_fe_is_odd(&p->y)) {
331 57597 secp256k1_fe_negate(t, t, 1);
332 57597 secp256k1_fe_normalize_var(t);
333 }
334 115200 }
335
336 64000 int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64, const secp256k1_pubkey *pubkey, const unsigned char *rnd32) {
337 secp256k1_ge p;
338 VERIFY_CHECK(ctx != NULL);
339
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64000 times.
64000 ARG_CHECK(ell64 != NULL);
340
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64000 times.
64000 ARG_CHECK(pubkey != NULL);
341
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 64000 times.
64000 ARG_CHECK(rnd32 != NULL);
342
343
1/2
✓ Branch 1 taken 64000 times.
✗ Branch 2 not taken.
64000 if (secp256k1_pubkey_load(ctx, &p, pubkey)) {
344 static const unsigned char PREFIX[128 - 9 - 4 - 32 - 33] = "secp256k1_ellswift_encode";
345 secp256k1_fe u, t;
346 unsigned char p33[33];
347 secp256k1_sha256 hash;
348
349 /* Set up hasher state */
350 64000 secp256k1_sha256_initialize(&hash);
351 64000 secp256k1_sha256_write(&hash, PREFIX, sizeof(PREFIX));
352 64000 secp256k1_sha256_write(&hash, rnd32, 32);
353 64000 secp256k1_fe_get_b32(p33, &p.x);
354 64000 p33[32] = secp256k1_fe_is_odd(&p.y);
355 64000 secp256k1_sha256_write(&hash, p33, sizeof(p33));
356 VERIFY_CHECK(hash.bytes == 128 - 9 - 4);
357
358 /* Compute ElligatorSwift encoding and construct output. */
359 64000 secp256k1_ellswift_elligatorswift_var(&u, &t, &p, &hash);
360 64000 secp256k1_fe_get_b32(ell64, &u);
361 64000 secp256k1_fe_get_b32(ell64 + 32, &t);
362 64000 return 1;
363 }
364 /* Only returned in case the provided pubkey is invalid. */
365 return 0;
366 }
367
368 51200 int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *rnd32) {
369 secp256k1_ge p;
370 secp256k1_fe u, t;
371 secp256k1_sha256 hash;
372 secp256k1_scalar seckey_scalar;
373 static const unsigned char PREFIX[32] = "secp256k1_ellswift_create";
374 static const unsigned char ZERO[32] = {0};
375 51200 int ret = 0;
376
377 /* Sanity check inputs. */
378 VERIFY_CHECK(ctx != NULL);
379
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51200 times.
51200 ARG_CHECK(ell64 != NULL);
380 51200 memset(ell64, 0, 64);
381
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 51200 times.
51200 ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
382
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 51200 times.
51200 ARG_CHECK(seckey32 != NULL);
383
384 /* Compute (affine) public key */
385 51200 ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey32);
386 51200 secp256k1_declassify(ctx, &p, sizeof(p)); /* not constant time in produced pubkey */
387 51200 secp256k1_fe_normalize_var(&p.x);
388 51200 secp256k1_fe_normalize_var(&p.y);
389
390 /* Set up hasher state */
391 51200 secp256k1_sha256_initialize(&hash);
392 51200 secp256k1_sha256_write(&hash, PREFIX, sizeof(PREFIX));
393 51200 secp256k1_sha256_write(&hash, seckey32, 32);
394
1/2
✓ Branch 0 taken 51200 times.
✗ Branch 1 not taken.
51200 secp256k1_sha256_write(&hash, rnd32 ? rnd32 : ZERO, 32);
395 51200 secp256k1_sha256_write(&hash, ZERO, 32 - 9 - 4);
396 51200 secp256k1_declassify(ctx, &hash, sizeof(hash)); /* hasher gets to declassify private key */
397
398 /* Compute ElligatorSwift encoding and construct output. */
399 51200 secp256k1_ellswift_elligatorswift_var(&u, &t, &p, &hash);
400 51200 secp256k1_fe_get_b32(ell64, &u);
401 51200 secp256k1_fe_get_b32(ell64 + 32, &t);
402
403 51200 secp256k1_memczero(ell64, 64, !ret);
404 51200 secp256k1_scalar_clear(&seckey_scalar);
405
406 51200 return ret;
407 }
408
409 140876 int secp256k1_ellswift_decode(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *ell64) {
410 secp256k1_fe u, t;
411 secp256k1_ge p;
412 VERIFY_CHECK(ctx != NULL);
413
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140876 times.
140876 ARG_CHECK(pubkey != NULL);
414
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 140876 times.
140876 ARG_CHECK(ell64 != NULL);
415
416 140876 secp256k1_fe_set_b32(&u, ell64);
417 140876 secp256k1_fe_normalize_var(&u);
418 140876 secp256k1_fe_set_b32(&t, ell64 + 32);
419 140876 secp256k1_fe_normalize_var(&t);
420 140876 secp256k1_ellswift_swiftec_var(&p, &u, &t);
421 140876 secp256k1_pubkey_save(pubkey, &p);
422 140876 return 1;
423 }
424
425 51200 static int ellswift_xdh_hash_function_sha256(unsigned char *output, const unsigned char *x32, const unsigned char *ours64, const unsigned char *theirs64, void *data) {
426 secp256k1_sha256 sha;
427
428 (void)data;
429
430 51200 secp256k1_sha256_initialize(&sha);
431
2/2
✓ Branch 1 taken 25714 times.
✓ Branch 2 taken 25486 times.
51200 if (secp256k1_memcmp_var(ours64, theirs64, 64) <= 0) {
432 25714 secp256k1_sha256_write(&sha, ours64, 64);
433 25714 secp256k1_sha256_write(&sha, theirs64, 64);
434 } else {
435 25486 secp256k1_sha256_write(&sha, theirs64, 64);
436 25486 secp256k1_sha256_write(&sha, ours64, 64);
437 }
438 51200 secp256k1_sha256_write(&sha, x32, 32);
439 51200 secp256k1_sha256_finalize(&sha, output);
440
441 51200 return 1;
442 }
443
444 const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_sha256 = ellswift_xdh_hash_function_sha256;
445 const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_default = ellswift_xdh_hash_function_sha256;
446
447 102400 int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, const unsigned char *theirs64, const unsigned char *ours64, const unsigned char *seckey32, secp256k1_ellswift_xdh_hash_function hashfp, void *data) {
448 102400 int ret = 0;
449 int overflow;
450 secp256k1_scalar s;
451 secp256k1_fe xn, xd, px, u, t;
452 unsigned char sx[32];
453
454 VERIFY_CHECK(ctx != NULL);
455
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102400 times.
102400 ARG_CHECK(output != NULL);
456
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102400 times.
102400 ARG_CHECK(theirs64 != NULL);
457
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102400 times.
102400 ARG_CHECK(ours64 != NULL);
458
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 102400 times.
102400 ARG_CHECK(seckey32 != NULL);
459
460
2/2
✓ Branch 0 taken 51200 times.
✓ Branch 1 taken 51200 times.
102400 if (hashfp == NULL) {
461 51200 hashfp = secp256k1_ellswift_xdh_hash_function_default;
462 }
463
464 /* Load remote public key (as fraction). */
465 102400 secp256k1_fe_set_b32(&u, theirs64);
466 102400 secp256k1_fe_normalize_var(&u);
467 102400 secp256k1_fe_set_b32(&t, theirs64 + 32);
468 102400 secp256k1_fe_normalize_var(&t);
469 102400 secp256k1_ellswift_xswiftec_frac_var(&xn, &xd, &u, &t);
470
471 /* Load private key (using one if invalid). */
472 102400 secp256k1_scalar_set_b32(&s, seckey32, &overflow);
473 102400 overflow = secp256k1_scalar_is_zero(&s);
474 102400 secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
475
476 /* Compute shared X coordinate. */
477 102400 secp256k1_ecmult_const_xonly(&px, &xn, &xd, &s, 256, 1);
478 102400 secp256k1_fe_normalize(&px);
479 102400 secp256k1_fe_get_b32(sx, &px);
480
481 /* Invoke hasher */
482 102400 ret = hashfp(output, sx, ours64, theirs64, data);
483
484 102400 memset(sx, 0, 32);
485 102400 secp256k1_fe_clear(&px);
486 102400 secp256k1_scalar_clear(&s);
487
488 102400 return !!ret & !overflow;
489 }
490
491 #endif
492