Coverage Report

Created: 2026-01-10 06:13

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/libtorrent/src/ed25519/ge.cpp
Line
Count
Source
1
// ignore warnings in this file
2
#include "libtorrent/aux_/disable_warnings_push.hpp"
3
4
#include "ge.h"
5
#include "precomp_data.h"
6
7
8
/*
9
r = p + q
10
*/
11
12
0
void ge_add(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
13
0
    fe t0;
14
0
    fe_add(r->X, p->Y, p->X);
15
0
    fe_sub(r->Y, p->Y, p->X);
16
0
    fe_mul(r->Z, r->X, q->YplusX);
17
0
    fe_mul(r->Y, r->Y, q->YminusX);
18
0
    fe_mul(r->T, q->T2d, p->T);
19
0
    fe_mul(r->X, p->Z, q->Z);
20
0
    fe_add(t0, r->X, r->X);
21
0
    fe_sub(r->X, r->Z, r->Y);
22
0
    fe_add(r->Y, r->Z, r->Y);
23
0
    fe_add(r->Z, t0, r->T);
24
0
    fe_sub(r->T, t0, r->T);
25
0
}
26
27
28
0
static void slide(signed char *r, const unsigned char *a) {
29
0
    int i;
30
0
    int b;
31
0
    int k;
32
33
0
    for (i = 0; i < 256; ++i) {
34
0
        r[i] = 1 & (a[i >> 3] >> (i & 7));
35
0
    }
36
37
0
    for (i = 0; i < 256; ++i)
38
0
        if (r[i]) {
39
0
            for (b = 1; b <= 6 && i + b < 256; ++b) {
40
0
                if (r[i + b]) {
41
0
                    if (r[i] + (r[i + b] << b) <= 15) {
42
0
                        r[i] += r[i + b] << b;
43
0
                        r[i + b] = 0;
44
0
                    } else if (r[i] - (r[i + b] << b) >= -15) {
45
0
                        r[i] -= r[i + b] << b;
46
47
0
                        for (k = i + b; k < 256; ++k) {
48
0
                            if (!r[k]) {
49
0
                                r[k] = 1;
50
0
                                break;
51
0
                            }
52
53
0
                            r[k] = 0;
54
0
                        }
55
0
                    } else {
56
0
                        break;
57
0
                    }
58
0
                }
59
0
            }
60
0
        }
61
0
}
62
63
/*
64
r = a * A + b * B
65
where a = a[0]+256*a[1]+...+256^31 a[31].
66
and b = b[0]+256*b[1]+...+256^31 b[31].
67
B is the Ed25519 base point (x,4/5) with x positive.
68
*/
69
70
0
void ge_double_scalarmult_vartime(ge_p2 *r, const unsigned char *a, const ge_p3 *A, const unsigned char *b) {
71
0
    signed char aslide[256];
72
0
    signed char bslide[256];
73
0
    ge_cached Ai[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
74
0
    ge_p1p1 t;
75
0
    ge_p3 u;
76
0
    ge_p3 A2;
77
0
    int i;
78
0
    slide(aslide, a);
79
0
    slide(bslide, b);
80
0
    ge_p3_to_cached(&Ai[0], A);
81
0
    ge_p3_dbl(&t, A);
82
0
    ge_p1p1_to_p3(&A2, &t);
83
0
    ge_add(&t, &A2, &Ai[0]);
84
0
    ge_p1p1_to_p3(&u, &t);
85
0
    ge_p3_to_cached(&Ai[1], &u);
86
0
    ge_add(&t, &A2, &Ai[1]);
87
0
    ge_p1p1_to_p3(&u, &t);
88
0
    ge_p3_to_cached(&Ai[2], &u);
89
0
    ge_add(&t, &A2, &Ai[2]);
90
0
    ge_p1p1_to_p3(&u, &t);
91
0
    ge_p3_to_cached(&Ai[3], &u);
92
0
    ge_add(&t, &A2, &Ai[3]);
93
0
    ge_p1p1_to_p3(&u, &t);
94
0
    ge_p3_to_cached(&Ai[4], &u);
95
0
    ge_add(&t, &A2, &Ai[4]);
96
0
    ge_p1p1_to_p3(&u, &t);
97
0
    ge_p3_to_cached(&Ai[5], &u);
98
0
    ge_add(&t, &A2, &Ai[5]);
99
0
    ge_p1p1_to_p3(&u, &t);
100
0
    ge_p3_to_cached(&Ai[6], &u);
101
0
    ge_add(&t, &A2, &Ai[6]);
102
0
    ge_p1p1_to_p3(&u, &t);
103
0
    ge_p3_to_cached(&Ai[7], &u);
104
0
    ge_p2_0(r);
105
106
0
    for (i = 255; i >= 0; --i) {
107
0
        if (aslide[i] || bslide[i]) {
108
0
            break;
109
0
        }
110
0
    }
111
112
0
    for (; i >= 0; --i) {
113
0
        ge_p2_dbl(&t, r);
114
115
0
        if (aslide[i] > 0) {
116
0
            ge_p1p1_to_p3(&u, &t);
117
0
            ge_add(&t, &u, &Ai[aslide[i] / 2]);
118
0
        } else if (aslide[i] < 0) {
119
0
            ge_p1p1_to_p3(&u, &t);
120
0
            ge_sub(&t, &u, &Ai[(-aslide[i]) / 2]);
121
0
        }
122
123
0
        if (bslide[i] > 0) {
124
0
            ge_p1p1_to_p3(&u, &t);
125
0
            ge_madd(&t, &u, &Bi[bslide[i] / 2]);
126
0
        } else if (bslide[i] < 0) {
127
0
            ge_p1p1_to_p3(&u, &t);
128
0
            ge_msub(&t, &u, &Bi[(-bslide[i]) / 2]);
129
0
        }
130
131
0
        ge_p1p1_to_p2(r, &t);
132
0
    }
133
0
}
134
135
136
static const fe d = {
137
    -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
138
};
139
140
static const fe sqrtm1 = {
141
    -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
142
};
143
144
0
int ge_frombytes_negate_vartime(ge_p3 *h, const unsigned char *s) {
145
0
    fe u;
146
0
    fe v;
147
0
    fe v3;
148
0
    fe vxx;
149
0
    fe check;
150
0
    fe_frombytes(h->Y, s);
151
0
    fe_1(h->Z);
152
0
    fe_sq(u, h->Y);
153
0
    fe_mul(v, u, d);
154
0
    fe_sub(u, u, h->Z);     /* u = y^2-1 */
155
0
    fe_add(v, v, h->Z);     /* v = dy^2+1 */
156
0
    fe_sq(v3, v);
157
0
    fe_mul(v3, v3, v);      /* v3 = v^3 */
158
0
    fe_sq(h->X, v3);
159
0
    fe_mul(h->X, h->X, v);
160
0
    fe_mul(h->X, h->X, u);  /* x = uv^7 */
161
0
    fe_pow22523(h->X, h->X); /* x = (uv^7)^((q-5)/8) */
162
0
    fe_mul(h->X, h->X, v3);
163
0
    fe_mul(h->X, h->X, u);  /* x = uv^3(uv^7)^((q-5)/8) */
164
0
    fe_sq(vxx, h->X);
165
0
    fe_mul(vxx, vxx, v);
166
0
    fe_sub(check, vxx, u);  /* vx^2-u */
167
168
0
    if (fe_isnonzero(check)) {
169
0
        fe_add(check, vxx, u); /* vx^2+u */
170
171
0
        if (fe_isnonzero(check)) {
172
0
            return -1;
173
0
        }
174
175
0
        fe_mul(h->X, h->X, sqrtm1);
176
0
    }
177
178
0
    if (fe_isnegative(h->X) == (s[31] >> 7)) {
179
0
        fe_neg(h->X, h->X);
180
0
    }
181
182
0
    fe_mul(h->T, h->X, h->Y);
183
0
    return 0;
184
0
}
185
186
187
/*
188
r = p + q
189
*/
190
191
0
void ge_madd(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
192
0
    fe t0;
193
0
    fe_add(r->X, p->Y, p->X);
194
0
    fe_sub(r->Y, p->Y, p->X);
195
0
    fe_mul(r->Z, r->X, q->yplusx);
196
0
    fe_mul(r->Y, r->Y, q->yminusx);
197
0
    fe_mul(r->T, q->xy2d, p->T);
198
0
    fe_add(t0, p->Z, p->Z);
199
0
    fe_sub(r->X, r->Z, r->Y);
200
0
    fe_add(r->Y, r->Z, r->Y);
201
0
    fe_add(r->Z, t0, r->T);
202
0
    fe_sub(r->T, t0, r->T);
203
0
}
204
205
206
/*
207
r = p - q
208
*/
209
210
0
void ge_msub(ge_p1p1 *r, const ge_p3 *p, const ge_precomp *q) {
211
0
    fe t0;
212
213
0
    fe_add(r->X, p->Y, p->X);
214
0
    fe_sub(r->Y, p->Y, p->X);
215
0
    fe_mul(r->Z, r->X, q->yminusx);
216
0
    fe_mul(r->Y, r->Y, q->yplusx);
217
0
    fe_mul(r->T, q->xy2d, p->T);
218
0
    fe_add(t0, p->Z, p->Z);
219
0
    fe_sub(r->X, r->Z, r->Y);
220
0
    fe_add(r->Y, r->Z, r->Y);
221
0
    fe_sub(r->Z, t0, r->T);
222
0
    fe_add(r->T, t0, r->T);
223
0
}
224
225
226
/*
227
r = p
228
*/
229
230
0
void ge_p1p1_to_p2(ge_p2 *r, const ge_p1p1 *p) {
231
0
    fe_mul(r->X, p->X, p->T);
232
0
    fe_mul(r->Y, p->Y, p->Z);
233
0
    fe_mul(r->Z, p->Z, p->T);
234
0
}
235
236
237
238
/*
239
r = p
240
*/
241
242
0
void ge_p1p1_to_p3(ge_p3 *r, const ge_p1p1 *p) {
243
0
    fe_mul(r->X, p->X, p->T);
244
0
    fe_mul(r->Y, p->Y, p->Z);
245
0
    fe_mul(r->Z, p->Z, p->T);
246
0
    fe_mul(r->T, p->X, p->Y);
247
0
}
248
249
250
0
void ge_p2_0(ge_p2 *h) {
251
0
    fe_0(h->X);
252
0
    fe_1(h->Y);
253
0
    fe_1(h->Z);
254
0
}
255
256
257
258
/*
259
r = 2 * p
260
*/
261
262
0
void ge_p2_dbl(ge_p1p1 *r, const ge_p2 *p) {
263
0
    fe t0;
264
265
0
    fe_sq(r->X, p->X);
266
0
    fe_sq(r->Z, p->Y);
267
0
    fe_sq2(r->T, p->Z);
268
0
    fe_add(r->Y, p->X, p->Y);
269
0
    fe_sq(t0, r->Y);
270
0
    fe_add(r->Y, r->Z, r->X);
271
0
    fe_sub(r->Z, r->Z, r->X);
272
0
    fe_sub(r->X, t0, r->Y);
273
0
    fe_sub(r->T, r->T, r->Z);
274
0
}
275
276
277
0
void ge_p3_0(ge_p3 *h) {
278
0
    fe_0(h->X);
279
0
    fe_1(h->Y);
280
0
    fe_1(h->Z);
281
0
    fe_0(h->T);
282
0
}
283
284
285
/*
286
r = 2 * p
287
*/
288
289
0
void ge_p3_dbl(ge_p1p1 *r, const ge_p3 *p) {
290
0
    ge_p2 q;
291
0
    ge_p3_to_p2(&q, p);
292
0
    ge_p2_dbl(r, &q);
293
0
}
294
295
296
297
/*
298
r = p
299
*/
300
301
static const fe d2 = {
302
    -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199
303
};
304
305
0
void ge_p3_to_cached(ge_cached *r, const ge_p3 *p) {
306
0
    fe_add(r->YplusX, p->Y, p->X);
307
0
    fe_sub(r->YminusX, p->Y, p->X);
308
0
    fe_copy(r->Z, p->Z);
309
0
    fe_mul(r->T2d, p->T, d2);
310
0
}
311
312
313
/*
314
r = p
315
*/
316
317
0
void ge_p3_to_p2(ge_p2 *r, const ge_p3 *p) {
318
0
    fe_copy(r->X, p->X);
319
0
    fe_copy(r->Y, p->Y);
320
0
    fe_copy(r->Z, p->Z);
321
0
}
322
323
324
0
void ge_p3_tobytes(unsigned char *s, const ge_p3 *h) {
325
0
    fe recip;
326
0
    fe x;
327
0
    fe y;
328
0
    fe_invert(recip, h->Z);
329
0
    fe_mul(x, h->X, recip);
330
0
    fe_mul(y, h->Y, recip);
331
0
    fe_tobytes(s, y);
332
0
    s[31] ^= fe_isnegative(x) << 7;
333
0
}
334
335
336
0
static unsigned char equal(signed char b, signed char c) {
337
0
    unsigned char ub = b;
338
0
    unsigned char uc = c;
339
0
    unsigned char x = ub ^ uc; /* 0: yes; 1..255: no */
340
0
    u64 y = x; /* 0: yes; 1..255: no */
341
0
    y -= 1; /* large: yes; 0..254: no */
342
0
    y >>= 63; /* 1: yes; 0: no */
343
0
    return (unsigned char) y;
344
0
}
345
346
0
static unsigned char negative(signed char b) {
347
0
    u64 x = b; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
348
0
    x >>= 63; /* 1: yes; 0: no */
349
0
    return (unsigned char) x;
350
0
}
351
352
0
static void cmov(ge_precomp *t, const ge_precomp *u, unsigned char b) {
353
0
    fe_cmov(t->yplusx, u->yplusx, b);
354
0
    fe_cmov(t->yminusx, u->yminusx, b);
355
0
    fe_cmov(t->xy2d, u->xy2d, b);
356
0
}
357
358
359
0
static void select(ge_precomp *t, int pos, signed char b) {
360
0
    typedef signed char schar;
361
0
    typedef unsigned char uchar;
362
0
    ge_precomp minust;
363
0
    unsigned char const bnegative = negative(b);
364
0
    unsigned char const babs = b - schar(uchar((-bnegative) & b) << 1);
365
0
    fe_1(t->yplusx);
366
0
    fe_1(t->yminusx);
367
0
    fe_0(t->xy2d);
368
0
    cmov(t, &base[pos][0], equal(babs, 1));
369
0
    cmov(t, &base[pos][1], equal(babs, 2));
370
0
    cmov(t, &base[pos][2], equal(babs, 3));
371
0
    cmov(t, &base[pos][3], equal(babs, 4));
372
0
    cmov(t, &base[pos][4], equal(babs, 5));
373
0
    cmov(t, &base[pos][5], equal(babs, 6));
374
0
    cmov(t, &base[pos][6], equal(babs, 7));
375
0
    cmov(t, &base[pos][7], equal(babs, 8));
376
0
    fe_copy(minust.yplusx, t->yminusx);
377
0
    fe_copy(minust.yminusx, t->yplusx);
378
0
    fe_neg(minust.xy2d, t->xy2d);
379
0
    cmov(t, &minust, bnegative);
380
0
}
381
382
/*
383
h = a * B
384
where a = a[0]+256*a[1]+...+256^31 a[31]
385
B is the Ed25519 base point (x,4/5) with x positive.
386
387
Preconditions:
388
  a[31] <= 127
389
*/
390
391
0
void ge_scalarmult_base(ge_p3 *h, const unsigned char *a) {
392
0
    signed char e[64];
393
0
    signed char carry;
394
0
    ge_p1p1 r;
395
0
    ge_p2 s;
396
0
    ge_precomp t;
397
0
    int i;
398
399
0
    for (i = 0; i < 32; ++i) {
400
0
        e[2 * i + 0] = (a[i] >> 0) & 15;
401
0
        e[2 * i + 1] = (a[i] >> 4) & 15;
402
0
    }
403
404
    /* each e[i] is between 0 and 15 */
405
    /* e[63] is between 0 and 7 */
406
0
    carry = 0;
407
408
0
    for (i = 0; i < 63; ++i) {
409
0
        e[i] += carry;
410
0
        carry = e[i] + 8;
411
0
        carry >>= 4;
412
0
        e[i] -= carry << 4;
413
0
    }
414
415
0
    e[63] += carry;
416
    /* each e[i] is between -8 and 8 */
417
0
    ge_p3_0(h);
418
419
0
    for (i = 1; i < 64; i += 2) {
420
0
        select(&t, i / 2, e[i]);
421
0
        ge_madd(&r, h, &t);
422
0
        ge_p1p1_to_p3(h, &r);
423
0
    }
424
425
0
    ge_p3_dbl(&r, h);
426
0
    ge_p1p1_to_p2(&s, &r);
427
0
    ge_p2_dbl(&r, &s);
428
0
    ge_p1p1_to_p2(&s, &r);
429
0
    ge_p2_dbl(&r, &s);
430
0
    ge_p1p1_to_p2(&s, &r);
431
0
    ge_p2_dbl(&r, &s);
432
0
    ge_p1p1_to_p3(h, &r);
433
434
0
    for (i = 0; i < 64; i += 2) {
435
0
        select(&t, i / 2, e[i]);
436
0
        ge_madd(&r, h, &t);
437
0
        ge_p1p1_to_p3(h, &r);
438
0
    }
439
0
}
440
441
442
/*
443
r = p - q
444
*/
445
446
0
void ge_sub(ge_p1p1 *r, const ge_p3 *p, const ge_cached *q) {
447
0
    fe t0;
448
    
449
0
    fe_add(r->X, p->Y, p->X);
450
0
    fe_sub(r->Y, p->Y, p->X);
451
0
    fe_mul(r->Z, r->X, q->YminusX);
452
0
    fe_mul(r->Y, r->Y, q->YplusX);
453
0
    fe_mul(r->T, q->T2d, p->T);
454
0
    fe_mul(r->X, p->Z, q->Z);
455
0
    fe_add(t0, r->X, r->X);
456
0
    fe_sub(r->X, r->Z, r->Y);
457
0
    fe_add(r->Y, r->Z, r->Y);
458
0
    fe_sub(r->Z, t0, r->T);
459
0
    fe_add(r->T, t0, r->T);
460
0
}
461
462
463
0
void ge_tobytes(unsigned char *s, const ge_p2 *h) {
464
0
    fe recip;
465
0
    fe x;
466
0
    fe y;
467
0
    fe_invert(recip, h->Z);
468
0
    fe_mul(x, h->X, recip);
469
0
    fe_mul(y, h->Y, recip);
470
0
    fe_tobytes(s, y);
471
0
    s[31] ^= fe_isnegative(x) << 7;
472
0
}