Coverage Report

Created: 2025-09-25 19:17

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/root/bitcoin/src/secp256k1/src/modules/ellswift/main_impl.h
Line
Count
Source
1
/***********************************************************************
2
 * Distributed under the MIT software license, see the accompanying    *
3
 * file COPYING or https://www.opensource.org/licenses/mit-license.php.*
4
 ***********************************************************************/
5
6
#ifndef SECP256K1_MODULE_ELLSWIFT_MAIN_H
7
#define SECP256K1_MODULE_ELLSWIFT_MAIN_H
8
9
#include "../../../include/secp256k1.h"
10
#include "../../../include/secp256k1_ellswift.h"
11
#include "../../eckey.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
0
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
     * - Let 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 it.
34
     * - If x2 = (-X/Y-u)/2 is a valid x coordinate, return it.
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
     * - Let c0 = ...
40
     * - If u = 0, set u = 1.
41
     * - If t = 0, set t = 1.
42
     * - Let s = t^2
43
     * - Let g = u^3+7
44
     * - If g+s = 0, set t = 2*t, s = 4*s
45
     * - Let X = (g-s)/(2*t).
46
     * - Let Y = (X+t)/(c0*u) = (g+s)/(2*c0*t*u).
47
     * - If x3 = u+4*Y^2 is a valid x coordinate, return it.
48
     * - If x2 = (-X/Y-u)/2 is a valid x coordinate, return it.
49
     * - Return x1 = -(x2+u).
50
     *
51
     * Now substitute Y^2 = -(g+s)^2/(12*s*u^2) and X/Y = c0*u*(g-s)/(g+s). This
52
     * means X and Y do not need to be evaluated explicitly anymore.
53
     *
54
     * - ...
55
     * - If g+s = 0, set s = 4*s.
56
     * - If x3 = u-(g+s)^2/(3*s*u^2) is a valid x coordinate, return it.
57
     * - If x2 = (-c0*u*(g-s)/(g+s)-u)/2 is a valid x coordinate, return it.
58
     * - Return x1 = -(x2+u).
59
     *
60
     * Simplifying x2 using 2 additional constants:
61
     *
62
     * - Let c1 = (c0-1)/2 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40.
63
     * - Let c2 = (-c0-1)/2 = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee.
64
     * - ...
65
     * - If x2 = u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it.
66
     * - ...
67
     *
68
     * Writing x3 as a fraction:
69
     *
70
     * - ...
71
     * - If x3 = (3*s*u^3-(g+s)^2)/(3*s*u^2) ...
72
     * - ...
73
74
     * Overall, we get:
75
     *
76
     * - Let c1 = 0x851695d49a83f8ef919bb86153cbcb16630fb68aed0a766a3ec693d68e6afa40.
77
     * - Let c2 = 0x7ae96a2b657c07106e64479eac3434e99cf0497512f58995c1396c28719501ee.
78
     * - If u = 0, set u = 1.
79
     * - If t = 0, set s = 1, else set s = t^2.
80
     * - Let g = u^3+7.
81
     * - If g+s = 0, set s = 4*s.
82
     * - If x3 = (3*s*u^3-(g+s)^2)/(3*s*u^2) is a valid x coordinate, return it.
83
     * - If x2 = u*(c1*s+c2*g)/(g+s) is a valid x coordinate, return it.
84
     * - Return x1 = -(x2+u).
85
     */
86
0
    secp256k1_fe u1, s, g, p, d, n, l;
87
0
    u1 = *u;
88
0
    if (EXPECT(secp256k1_fe_normalizes_to_zero_var(&u1), 0)) u1 = secp256k1_fe_one;
89
0
    secp256k1_fe_sqr(&s, t);
90
0
    if (EXPECT(secp256k1_fe_normalizes_to_zero_var(t), 0)) s = secp256k1_fe_one;
91
0
    secp256k1_fe_sqr(&l, &u1);                                   /* l = u^2 */
92
0
    secp256k1_fe_mul(&g, &l, &u1);                               /* g = u^3 */
93
0
    secp256k1_fe_add_int(&g, SECP256K1_B);                       /* g = u^3 + 7 */
94
0
    p = g;                                                       /* p = g */
95
0
    secp256k1_fe_add(&p, &s);                                    /* p = g+s */
96
0
    if (EXPECT(secp256k1_fe_normalizes_to_zero_var(&p), 0)) {
97
0
        secp256k1_fe_mul_int(&s, 4);
98
        /* Recompute p = g+s */
99
0
        p = g;                                                   /* p = g */
100
0
        secp256k1_fe_add(&p, &s);                                /* p = g+s */
101
0
    }
102
0
    secp256k1_fe_mul(&d, &s, &l);                                /* d = s*u^2 */
103
0
    secp256k1_fe_mul_int(&d, 3);                                 /* d = 3*s*u^2 */
104
0
    secp256k1_fe_sqr(&l, &p);                                    /* l = (g+s)^2 */
105
0
    secp256k1_fe_negate(&l, &l, 1);                              /* l = -(g+s)^2 */
106
0
    secp256k1_fe_mul(&n, &d, &u1);                               /* n = 3*s*u^3 */
107
0
    secp256k1_fe_add(&n, &l);                                    /* n = 3*s*u^3-(g+s)^2 */
108
0
    if (secp256k1_ge_x_frac_on_curve_var(&n, &d)) {
109
        /* Return x3 = n/d = (3*s*u^3-(g+s)^2)/(3*s*u^2) */
110
0
        *xn = n;
111
0
        *xd = d;
112
0
        return;
113
0
    }
114
0
    *xd = p;
115
0
    secp256k1_fe_mul(&l, &secp256k1_ellswift_c1, &s);            /* l = c1*s */
116
0
    secp256k1_fe_mul(&n, &secp256k1_ellswift_c2, &g);            /* n = c2*g */
117
0
    secp256k1_fe_add(&n, &l);                                    /* n = c1*s+c2*g */
118
0
    secp256k1_fe_mul(&n, &n, &u1);                               /* n = u*(c1*s+c2*g) */
119
    /* Possible optimization: in the invocation below, p^2 = (g+s)^2 is computed,
120
     * which we already have computed above. This could be deduplicated. */
121
0
    if (secp256k1_ge_x_frac_on_curve_var(&n, &p)) {
122
        /* Return x2 = n/p = u*(c1*s+c2*g)/(g+s) */
123
0
        *xn = n;
124
0
        return;
125
0
    }
126
0
    secp256k1_fe_mul(&l, &p, &u1);                               /* l = u*(g+s) */
127
0
    secp256k1_fe_add(&n, &l);                                    /* n = u*(c1*s+c2*g)+u*(g+s) */
128
0
    secp256k1_fe_negate(xn, &n, 2);                              /* n = -u*(c1*s+c2*g)-u*(g+s) */
129
130
0
    VERIFY_CHECK(secp256k1_ge_x_frac_on_curve_var(xn, &p));
131
    /* Return x3 = n/p = -(u*(c1*s+c2*g)/(g+s)+u) */
132
0
}
133
134
/** Decode ElligatorSwift encoding (u, t) to X coordinate. */
135
0
static void secp256k1_ellswift_xswiftec_var(secp256k1_fe *x, const secp256k1_fe *u, const secp256k1_fe *t) {
136
0
    secp256k1_fe xn, xd;
137
0
    secp256k1_ellswift_xswiftec_frac_var(&xn, &xd, u, t);
138
0
    secp256k1_fe_inv_var(&xd, &xd);
139
0
    secp256k1_fe_mul(x, &xn, &xd);
140
0
}
141
142
/** Decode ElligatorSwift encoding (u, t) to point P. */
143
0
static void secp256k1_ellswift_swiftec_var(secp256k1_ge *p, const secp256k1_fe *u, const secp256k1_fe *t) {
144
0
    secp256k1_fe x;
145
0
    secp256k1_ellswift_xswiftec_var(&x, u, t);
146
0
    secp256k1_ge_set_xo_var(p, &x, secp256k1_fe_is_odd(t));
147
0
}
148
149
/* Try to complete an ElligatorSwift encoding (u, t) for X coordinate x, given u and x.
150
 *
151
 * There may be up to 8 distinct t values such that (u, t) decodes back to x, but also
152
 * fewer, or none at all. Each such partial inverse can be accessed individually using a
153
 * distinct input argument c (in range 0-7), and some or all of these may return failure.
154
 * The following guarantees exist:
155
 * - Given (x, u), no two distinct c values give the same successful result t.
156
 * - Every successful result maps back to x through secp256k1_ellswift_xswiftec_var.
157
 * - Given (x, u), all t values that map back to x can be reached by combining the
158
 *   successful results from this function over all c values, with the exception of:
159
 *   - this function cannot be called with u=0
160
 *   - no result with t=0 will be returned
161
 *   - no result for which u^3 + t^2 + 7 = 0 will be returned.
162
 *
163
 * The rather unusual encoding of bits in c (a large "if" based on the middle bit, and then
164
 * using the low and high bits to pick signs of square roots) is to match the paper's
165
 * encoding more closely: c=0 through c=3 match branches 1..4 in the paper, while c=4 through
166
 * c=7 are copies of those with an additional negation of sqrt(w).
167
 */
168
0
static int secp256k1_ellswift_xswiftec_inv_var(secp256k1_fe *t, const secp256k1_fe *x_in, const secp256k1_fe *u_in, int c) {
169
    /* The implemented algorithm is this (all arithmetic, except involving c, is mod p):
170
     *
171
     * - If (c & 2) = 0:
172
     *   - If (-x-u) is a valid X coordinate, fail.
173
     *   - Let s=-(u^3+7)/(u^2+u*x+x^2).
174
     *   - If s is not square, fail.
175
     *   - Let v=x.
176
     * - If (c & 2) = 2:
177
     *   - Let s=x-u.
178
     *   - If s is not square, fail.
179
     *   - Let r=sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist.
180
     *   - If (c & 1) = 1 and r = 0, fail.
181
     *   - If s=0, fail.
182
     *   - Let v=(r/s-u)/2.
183
     * - Let w=sqrt(s).
184
     * - If (c & 5) = 0: return -w*(c3*u + v).
185
     * - If (c & 5) = 1: return  w*(c4*u + v).
186
     * - If (c & 5) = 4: return  w*(c3*u + v).
187
     * - If (c & 5) = 5: return -w*(c4*u + v).
188
     */
189
0
    secp256k1_fe x = *x_in, u = *u_in, g, v, s, m, r, q;
190
0
    int ret;
191
192
0
    secp256k1_fe_normalize_weak(&x);
193
0
    secp256k1_fe_normalize_weak(&u);
194
195
0
    VERIFY_CHECK(c >= 0 && c < 8);
196
0
    VERIFY_CHECK(secp256k1_ge_x_on_curve_var(&x));
197
198
0
    if (!(c & 2)) {
199
        /* c is in {0, 1, 4, 5}. In this case we look for an inverse under the x1 (if c=0 or
200
         * c=4) formula, or x2 (if c=1 or c=5) formula. */
201
202
        /* If -u-x is a valid X coordinate, fail. This would yield an encoding that roundtrips
203
         * back under the x3 formula instead (which has priority over x1 and x2, so the decoding
204
         * would not match x). */
205
0
        m = x;                                          /* m = x */
206
0
        secp256k1_fe_add(&m, &u);                       /* m = u+x */
207
0
        secp256k1_fe_negate(&m, &m, 2);                 /* m = -u-x */
208
        /* Test if (-u-x) is a valid X coordinate. If so, fail. */
209
0
        if (secp256k1_ge_x_on_curve_var(&m)) return 0;
210
211
        /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [first part] */
212
0
        secp256k1_fe_sqr(&s, &m);                       /* s = (u+x)^2 */
213
0
        secp256k1_fe_negate(&s, &s, 1);                 /* s = -(u+x)^2 */
214
0
        secp256k1_fe_mul(&m, &u, &x);                   /* m = u*x */
215
0
        secp256k1_fe_add(&s, &m);                       /* s = -(u^2 + u*x + x^2) */
216
217
        /* Note that at this point, s = 0 is impossible. If it were the case:
218
         *             s = -(u^2 + u*x + x^2) = 0
219
         * =>                 u^2 + u*x + x^2 = 0
220
         * =>   (u + 2*x) * (u^2 + u*x + x^2) = 0
221
         * => 2*x^3 + 3*x^2*u + 3*x*u^2 + u^3 = 0
222
         * =>                 (x + u)^3 + x^3 = 0
223
         * =>                             x^3 = -(x + u)^3
224
         * =>                         x^3 + B = (-u - x)^3 + B
225
         *
226
         * However, we know x^3 + B is square (because x is on the curve) and
227
         * that (-u-x)^3 + B is not square (the secp256k1_ge_x_on_curve_var(&m)
228
         * test above would have failed). This is a contradiction, and thus the
229
         * assumption s=0 is false. */
230
0
        VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(&s));
231
232
        /* If s is not square, fail. We have not fully computed s yet, but s is square iff
233
         * -(u^3+7)*(u^2+u*x+x^2) is square (because a/b is square iff a*b is square and b is
234
         * nonzero). */
235
0
        secp256k1_fe_sqr(&g, &u);                       /* g = u^2 */
236
0
        secp256k1_fe_mul(&g, &g, &u);                   /* g = u^3 */
237
0
        secp256k1_fe_add_int(&g, SECP256K1_B);          /* g = u^3+7 */
238
0
        secp256k1_fe_mul(&m, &s, &g);                   /* m = -(u^3 + 7)*(u^2 + u*x + x^2) */
239
0
        if (!secp256k1_fe_is_square_var(&m)) return 0;
240
241
        /* Let s = -(u^3 + 7)/(u^2 + u*x + x^2) [second part] */
242
0
        secp256k1_fe_inv_var(&s, &s);                   /* s = -1/(u^2 + u*x + x^2) [no div by 0] */
243
0
        secp256k1_fe_mul(&s, &s, &g);                   /* s = -(u^3 + 7)/(u^2 + u*x + x^2) */
244
245
        /* Let v = x. */
246
0
        v = x;
247
0
    } else {
248
        /* c is in {2, 3, 6, 7}. In this case we look for an inverse under the x3 formula. */
249
250
        /* Let s = x-u. */
251
0
        secp256k1_fe_negate(&m, &u, 1);                 /* m = -u */
252
0
        s = m;                                          /* s = -u */
253
0
        secp256k1_fe_add(&s, &x);                       /* s = x-u */
254
255
        /* If s is not square, fail. */
256
0
        if (!secp256k1_fe_is_square_var(&s)) return 0;
257
258
        /* Let r = sqrt(-s*(4*(u^3+7)+3*u^2*s)); fail if it doesn't exist. */
259
0
        secp256k1_fe_sqr(&g, &u);                       /* g = u^2 */
260
0
        secp256k1_fe_mul(&q, &s, &g);                   /* q = s*u^2 */
261
0
        secp256k1_fe_mul_int(&q, 3);                    /* q = 3*s*u^2 */
262
0
        secp256k1_fe_mul(&g, &g, &u);                   /* g = u^3 */
263
0
        secp256k1_fe_mul_int(&g, 4);                    /* g = 4*u^3 */
264
0
        secp256k1_fe_add_int(&g, 4 * SECP256K1_B);      /* g = 4*(u^3+7) */
265
0
        secp256k1_fe_add(&q, &g);                       /* q = 4*(u^3+7)+3*s*u^2 */
266
0
        secp256k1_fe_mul(&q, &q, &s);                   /* q = s*(4*(u^3+7)+3*u^2*s) */
267
0
        secp256k1_fe_negate(&q, &q, 1);                 /* q = -s*(4*(u^3+7)+3*u^2*s) */
268
0
        if (!secp256k1_fe_is_square_var(&q)) return 0;
269
0
        ret = secp256k1_fe_sqrt(&r, &q);                /* r = sqrt(-s*(4*(u^3+7)+3*u^2*s)) */
270
#ifdef VERIFY
271
        VERIFY_CHECK(ret);
272
#else
273
0
        (void)ret;
274
0
#endif
275
276
        /* If (c & 1) = 1 and r = 0, fail. */
277
0
        if (EXPECT((c & 1) && secp256k1_fe_normalizes_to_zero_var(&r), 0)) return 0;
278
279
        /* If s = 0, fail. */
280
0
        if (EXPECT(secp256k1_fe_normalizes_to_zero_var(&s), 0)) return 0;
281
282
        /* Let v = (r/s-u)/2. */
283
0
        secp256k1_fe_inv_var(&v, &s);                   /* v = 1/s [no div by 0] */
284
0
        secp256k1_fe_mul(&v, &v, &r);                   /* v = r/s */
285
0
        secp256k1_fe_add(&v, &m);                       /* v = r/s-u */
286
0
        secp256k1_fe_half(&v);                          /* v = (r/s-u)/2 */
287
0
    }
288
289
    /* Let w = sqrt(s). */
290
0
    ret = secp256k1_fe_sqrt(&m, &s);                    /* m = sqrt(s) = w */
291
0
    VERIFY_CHECK(ret);
292
293
    /* Return logic. */
294
0
    if ((c & 5) == 0 || (c & 5) == 5) {
295
0
        secp256k1_fe_negate(&m, &m, 1);                 /* m = -w */
296
0
    }
297
    /* Now m = {-w if c&5=0 or c&5=5; w otherwise}. */
298
0
    secp256k1_fe_mul(&u, &u, c&1 ? &secp256k1_ellswift_c4 : &secp256k1_ellswift_c3);
299
    /* u = {c4 if c&1=1; c3 otherwise}*u */
300
0
    secp256k1_fe_add(&u, &v);                           /* u = {c4 if c&1=1; c3 otherwise}*u + v */
301
0
    secp256k1_fe_mul(t, &m, &u);
302
0
    return 1;
303
0
}
304
305
/** Use SHA256 as a PRNG, returning SHA256(hasher || cnt).
306
 *
307
 * hasher is a SHA256 object to which an incrementing 4-byte counter is written to generate randomness.
308
 * Writing 13 bytes (4 bytes for counter, plus 9 bytes for the SHA256 padding) cannot cross a
309
 * 64-byte block size boundary (to make sure it only triggers a single SHA256 compression). */
310
0
static void secp256k1_ellswift_prng(unsigned char* out32, const secp256k1_sha256 *hasher, uint32_t cnt) {
311
0
    secp256k1_sha256 hash = *hasher;
312
0
    unsigned char buf4[4];
313
#ifdef VERIFY
314
    size_t blocks = hash.bytes >> 6;
315
#endif
316
0
    buf4[0] = cnt;
317
0
    buf4[1] = cnt >> 8;
318
0
    buf4[2] = cnt >> 16;
319
0
    buf4[3] = cnt >> 24;
320
0
    secp256k1_sha256_write(&hash, buf4, 4);
321
0
    secp256k1_sha256_finalize(&hash, out32);
322
323
    /* Writing and finalizing together should trigger exactly one SHA256 compression. */
324
0
    VERIFY_CHECK(((hash.bytes) >> 6) == (blocks + 1));
325
0
}
326
327
/** Find an ElligatorSwift encoding (u, t) for X coordinate x, and random Y coordinate.
328
 *
329
 * u32 is the 32-byte big endian encoding of u; t is the output field element t that still
330
 * needs encoding.
331
 *
332
 * hasher is a hasher in the secp256k1_ellswift_prng sense, with the same restrictions. */
333
0
static void secp256k1_ellswift_xelligatorswift_var(unsigned char *u32, secp256k1_fe *t, const secp256k1_fe *x, const secp256k1_sha256 *hasher) {
334
    /* Pool of 3-bit branch values. */
335
0
    unsigned char branch_hash[32];
336
    /* Number of 3-bit values in branch_hash left. */
337
0
    int branches_left = 0;
338
    /* Field elements u and branch values are extracted from RNG based on hasher for consecutive
339
     * values of cnt. cnt==0 is first used to populate a pool of 64 4-bit branch values. The 64
340
     * cnt values that follow are used to generate field elements u. cnt==65 (and multiples
341
     * thereof) are used to repopulate the pool and start over, if that were ever necessary.
342
     * On average, 4 iterations are needed. */
343
0
    uint32_t cnt = 0;
344
0
    while (1) {
345
0
        int branch;
346
0
        secp256k1_fe u;
347
        /* If the pool of branch values is empty, populate it. */
348
0
        if (branches_left == 0) {
349
0
            secp256k1_ellswift_prng(branch_hash, hasher, cnt++);
350
0
            branches_left = 64;
351
0
        }
352
        /* Take a 3-bit branch value from the branch pool (top bit is discarded). */
353
0
        --branches_left;
354
0
        branch = (branch_hash[branches_left >> 1] >> ((branches_left & 1) << 2)) & 7;
355
        /* Compute a new u value by hashing. */
356
0
        secp256k1_ellswift_prng(u32, hasher, cnt++);
357
        /* overflow is not a problem (we prefer uniform u32 over uniform u). */
358
0
        secp256k1_fe_set_b32_mod(&u, u32);
359
        /* Since u is the output of a hash, it should practically never be 0. We could apply the
360
         * u=0 to u=1 correction here too to deal with that case still, but it's such a low
361
         * probability event that we do not bother. */
362
0
        VERIFY_CHECK(!secp256k1_fe_normalizes_to_zero_var(&u));
363
364
        /* Find a remainder t, and return it if found. */
365
0
        if (EXPECT(secp256k1_ellswift_xswiftec_inv_var(t, x, &u, branch), 0)) break;
366
0
    }
367
0
}
368
369
/** Find an ElligatorSwift encoding (u, t) for point P.
370
 *
371
 * This is similar secp256k1_ellswift_xelligatorswift_var, except it takes a full group element p
372
 * as input, and returns an encoding that matches the provided Y coordinate rather than a random
373
 * one.
374
 */
375
0
static void secp256k1_ellswift_elligatorswift_var(unsigned char *u32, secp256k1_fe *t, const secp256k1_ge *p, const secp256k1_sha256 *hasher) {
376
0
    secp256k1_ellswift_xelligatorswift_var(u32, t, &p->x, hasher);
377
0
    secp256k1_fe_normalize_var(t);
378
0
    if (secp256k1_fe_is_odd(t) != secp256k1_fe_is_odd(&p->y)) {
379
0
        secp256k1_fe_negate(t, t, 1);
380
0
        secp256k1_fe_normalize_var(t);
381
0
    }
382
0
}
383
384
/** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_encode". */
385
0
static void secp256k1_ellswift_sha256_init_encode(secp256k1_sha256* hash) {
386
0
    secp256k1_sha256_initialize(hash);
387
0
    hash->s[0] = 0xd1a6524bul;
388
0
    hash->s[1] = 0x028594b3ul;
389
0
    hash->s[2] = 0x96e42f4eul;
390
0
    hash->s[3] = 0x1037a177ul;
391
0
    hash->s[4] = 0x1b8fcb8bul;
392
0
    hash->s[5] = 0x56023885ul;
393
0
    hash->s[6] = 0x2560ede1ul;
394
0
    hash->s[7] = 0xd626b715ul;
395
396
0
    hash->bytes = 64;
397
0
}
398
399
0
int secp256k1_ellswift_encode(const secp256k1_context *ctx, unsigned char *ell64, const secp256k1_pubkey *pubkey, const unsigned char *rnd32) {
400
0
    secp256k1_ge p;
401
0
    VERIFY_CHECK(ctx != NULL);
402
0
    ARG_CHECK(ell64 != NULL);
403
0
    ARG_CHECK(pubkey != NULL);
404
0
    ARG_CHECK(rnd32 != NULL);
405
406
0
    if (secp256k1_pubkey_load(ctx, &p, pubkey)) {
407
0
        secp256k1_fe t;
408
0
        unsigned char p64[64] = {0};
409
0
        size_t ser_size;
410
0
        int ser_ret;
411
0
        secp256k1_sha256 hash;
412
413
        /* Set up hasher state; the used RNG is H(pubkey || "\x00"*31 || rnd32 || cnt++), using
414
         * BIP340 tagged hash with tag "secp256k1_ellswift_encode". */
415
0
        secp256k1_ellswift_sha256_init_encode(&hash);
416
0
        ser_ret = secp256k1_eckey_pubkey_serialize(&p, p64, &ser_size, 1);
417
#ifdef VERIFY
418
        VERIFY_CHECK(ser_ret && ser_size == 33);
419
#else
420
0
        (void)ser_ret;
421
0
#endif
422
0
        secp256k1_sha256_write(&hash, p64, sizeof(p64));
423
0
        secp256k1_sha256_write(&hash, rnd32, 32);
424
425
        /* Compute ElligatorSwift encoding and construct output. */
426
0
        secp256k1_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */
427
0
        secp256k1_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */
428
0
        return 1;
429
0
    }
430
    /* Only reached in case the provided pubkey is invalid. */
431
0
    memset(ell64, 0, 64);
432
0
    return 0;
433
0
}
434
435
/** Set hash state to the BIP340 tagged hash midstate for "secp256k1_ellswift_create". */
436
0
static void secp256k1_ellswift_sha256_init_create(secp256k1_sha256* hash) {
437
0
    secp256k1_sha256_initialize(hash);
438
0
    hash->s[0] = 0xd29e1bf5ul;
439
0
    hash->s[1] = 0xf7025f42ul;
440
0
    hash->s[2] = 0x9b024773ul;
441
0
    hash->s[3] = 0x094cb7d5ul;
442
0
    hash->s[4] = 0xe59ed789ul;
443
0
    hash->s[5] = 0x03bc9786ul;
444
0
    hash->s[6] = 0x68335b35ul;
445
0
    hash->s[7] = 0x4e363b53ul;
446
447
0
    hash->bytes = 64;
448
0
}
449
450
0
int secp256k1_ellswift_create(const secp256k1_context *ctx, unsigned char *ell64, const unsigned char *seckey32, const unsigned char *auxrnd32) {
451
0
    secp256k1_ge p;
452
0
    secp256k1_fe t;
453
0
    secp256k1_sha256 hash;
454
0
    secp256k1_scalar seckey_scalar;
455
0
    int ret;
456
0
    static const unsigned char zero32[32] = {0};
457
458
    /* Sanity check inputs. */
459
0
    VERIFY_CHECK(ctx != NULL);
460
0
    ARG_CHECK(ell64 != NULL);
461
0
    memset(ell64, 0, 64);
462
0
    ARG_CHECK(secp256k1_ecmult_gen_context_is_built(&ctx->ecmult_gen_ctx));
463
0
    ARG_CHECK(seckey32 != NULL);
464
465
    /* Compute (affine) public key */
466
0
    ret = secp256k1_ec_pubkey_create_helper(&ctx->ecmult_gen_ctx, &seckey_scalar, &p, seckey32);
467
0
    secp256k1_declassify(ctx, &p, sizeof(p)); /* not constant time in produced pubkey */
468
0
    secp256k1_fe_normalize_var(&p.x);
469
0
    secp256k1_fe_normalize_var(&p.y);
470
471
    /* Set up hasher state. The used RNG is H(privkey || "\x00"*32 [|| auxrnd32] || cnt++),
472
     * using BIP340 tagged hash with tag "secp256k1_ellswift_create". */
473
0
    secp256k1_ellswift_sha256_init_create(&hash);
474
0
    secp256k1_sha256_write(&hash, seckey32, 32);
475
0
    secp256k1_sha256_write(&hash, zero32, sizeof(zero32));
476
0
    secp256k1_declassify(ctx, &hash, sizeof(hash)); /* private key is hashed now */
477
0
    if (auxrnd32) secp256k1_sha256_write(&hash, auxrnd32, 32);
478
479
    /* Compute ElligatorSwift encoding and construct output. */
480
0
    secp256k1_ellswift_elligatorswift_var(ell64, &t, &p, &hash); /* puts u in ell64[0..32] */
481
0
    secp256k1_fe_get_b32(ell64 + 32, &t); /* puts t in ell64[32..64] */
482
483
0
    secp256k1_memczero(ell64, 64, !ret);
484
0
    secp256k1_scalar_clear(&seckey_scalar);
485
486
0
    return ret;
487
0
}
488
489
0
int secp256k1_ellswift_decode(const secp256k1_context *ctx, secp256k1_pubkey *pubkey, const unsigned char *ell64) {
490
0
    secp256k1_fe u, t;
491
0
    secp256k1_ge p;
492
0
    VERIFY_CHECK(ctx != NULL);
493
0
    ARG_CHECK(pubkey != NULL);
494
0
    ARG_CHECK(ell64 != NULL);
495
496
0
    secp256k1_fe_set_b32_mod(&u, ell64);
497
0
    secp256k1_fe_set_b32_mod(&t, ell64 + 32);
498
0
    secp256k1_fe_normalize_var(&t);
499
0
    secp256k1_ellswift_swiftec_var(&p, &u, &t);
500
0
    secp256k1_pubkey_save(pubkey, &p);
501
0
    return 1;
502
0
}
503
504
0
static int ellswift_xdh_hash_function_prefix(unsigned char *output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) {
505
0
    secp256k1_sha256 sha;
506
507
0
    secp256k1_sha256_initialize(&sha);
508
0
    secp256k1_sha256_write(&sha, data, 64);
509
0
    secp256k1_sha256_write(&sha, ell_a64, 64);
510
0
    secp256k1_sha256_write(&sha, ell_b64, 64);
511
0
    secp256k1_sha256_write(&sha, x32, 32);
512
0
    secp256k1_sha256_finalize(&sha, output);
513
0
    secp256k1_sha256_clear(&sha);
514
515
0
    return 1;
516
0
}
517
518
/** Set hash state to the BIP340 tagged hash midstate for "bip324_ellswift_xonly_ecdh". */
519
0
static void secp256k1_ellswift_sha256_init_bip324(secp256k1_sha256* hash) {
520
0
    secp256k1_sha256_initialize(hash);
521
0
    hash->s[0] = 0x8c12d730ul;
522
0
    hash->s[1] = 0x827bd392ul;
523
0
    hash->s[2] = 0x9e4fb2eeul;
524
0
    hash->s[3] = 0x207b373eul;
525
0
    hash->s[4] = 0x2292bd7aul;
526
0
    hash->s[5] = 0xaa5441bcul;
527
0
    hash->s[6] = 0x15c3779ful;
528
0
    hash->s[7] = 0xcfb52549ul;
529
530
0
    hash->bytes = 64;
531
0
}
532
533
0
static int ellswift_xdh_hash_function_bip324(unsigned char* output, const unsigned char *x32, const unsigned char *ell_a64, const unsigned char *ell_b64, void *data) {
534
0
    secp256k1_sha256 sha;
535
536
0
    (void)data;
537
538
0
    secp256k1_ellswift_sha256_init_bip324(&sha);
539
0
    secp256k1_sha256_write(&sha, ell_a64, 64);
540
0
    secp256k1_sha256_write(&sha, ell_b64, 64);
541
0
    secp256k1_sha256_write(&sha, x32, 32);
542
0
    secp256k1_sha256_finalize(&sha, output);
543
0
    secp256k1_sha256_clear(&sha);
544
545
0
    return 1;
546
0
}
547
548
const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_prefix = ellswift_xdh_hash_function_prefix;
549
const secp256k1_ellswift_xdh_hash_function secp256k1_ellswift_xdh_hash_function_bip324 = ellswift_xdh_hash_function_bip324;
550
551
0
int secp256k1_ellswift_xdh(const secp256k1_context *ctx, unsigned char *output, const unsigned char *ell_a64, const unsigned char *ell_b64, const unsigned char *seckey32, int party, secp256k1_ellswift_xdh_hash_function hashfp, void *data) {
552
0
    int ret = 0;
553
0
    int overflow;
554
0
    secp256k1_scalar s;
555
0
    secp256k1_fe xn, xd, px, u, t;
556
0
    unsigned char sx[32];
557
0
    const unsigned char* theirs64;
558
559
0
    VERIFY_CHECK(ctx != NULL);
560
0
    ARG_CHECK(output != NULL);
561
0
    ARG_CHECK(ell_a64 != NULL);
562
0
    ARG_CHECK(ell_b64 != NULL);
563
0
    ARG_CHECK(seckey32 != NULL);
564
0
    ARG_CHECK(hashfp != NULL);
565
566
    /* Load remote public key (as fraction). */
567
0
    theirs64 = party ? ell_a64 : ell_b64;
568
0
    secp256k1_fe_set_b32_mod(&u, theirs64);
569
0
    secp256k1_fe_set_b32_mod(&t, theirs64 + 32);
570
0
    secp256k1_ellswift_xswiftec_frac_var(&xn, &xd, &u, &t);
571
572
    /* Load private key (using one if invalid). */
573
0
    secp256k1_scalar_set_b32(&s, seckey32, &overflow);
574
0
    overflow = secp256k1_scalar_is_zero(&s);
575
0
    secp256k1_scalar_cmov(&s, &secp256k1_scalar_one, overflow);
576
577
    /* Compute shared X coordinate. */
578
0
    secp256k1_ecmult_const_xonly(&px, &xn, &xd, &s, 1);
579
0
    secp256k1_fe_normalize(&px);
580
0
    secp256k1_fe_get_b32(sx, &px);
581
582
    /* Invoke hasher */
583
0
    ret = hashfp(output, sx, ell_a64, ell_b64, data);
584
585
0
    secp256k1_memclear(sx, sizeof(sx));
586
0
    secp256k1_fe_clear(&px);
587
0
    secp256k1_scalar_clear(&s);
588
589
0
    return !!ret & !overflow;
590
0
}
591
592
#endif