2 #include "precomp_data.h"
9 void ge_add(ge_p1p1
*r
, const ge_p3
*p
, const ge_cached
*q
) {
11 fe_add(r
->X
, p
->Y
, p
->X
);
12 fe_sub(r
->Y
, p
->Y
, p
->X
);
13 fe_mul(r
->Z
, r
->X
, q
->YplusX
);
14 fe_mul(r
->Y
, r
->Y
, q
->YminusX
);
15 fe_mul(r
->T
, q
->T2d
, p
->T
);
16 fe_mul(r
->X
, p
->Z
, q
->Z
);
17 fe_add(t0
, r
->X
, r
->X
);
18 fe_sub(r
->X
, r
->Z
, r
->Y
);
19 fe_add(r
->Y
, r
->Z
, r
->Y
);
20 fe_add(r
->Z
, t0
, r
->T
);
21 fe_sub(r
->T
, t0
, r
->T
);
25 static void slide(signed char *r
, const unsigned char *a
) {
30 for (i
= 0; i
< 256; ++i
) {
31 r
[i
] = 1 & (a
[i
>> 3] >> (i
& 7));
34 for (i
= 0; i
< 256; ++i
)
36 for (b
= 1; b
<= 6 && i
+ b
< 256; ++b
) {
38 if (r
[i
] + (r
[i
+ b
] << b
) <= 15) {
39 r
[i
] += r
[i
+ b
] << b
;
41 } else if (r
[i
] - (r
[i
+ b
] << b
) >= -15) {
42 r
[i
] -= r
[i
+ b
] << b
;
44 for (k
= i
+ b
; k
< 256; ++k
) {
62 where a = a[0]+256*a[1]+...+256^31 a[31].
63 and b = b[0]+256*b[1]+...+256^31 b[31].
64 B is the Ed25519 base point (x,4/5) with x positive.
67 void ge_double_scalarmult_vartime(ge_p2
*r
, const unsigned char *a
, const ge_p3
*A
, const unsigned char *b
) {
68 signed char aslide
[256];
69 signed char bslide
[256];
70 ge_cached Ai
[8]; /* A,3A,5A,7A,9A,11A,13A,15A */
77 ge_p3_to_cached(&Ai
[0], A
);
79 ge_p1p1_to_p3(&A2
, &t
);
80 ge_add(&t
, &A2
, &Ai
[0]);
81 ge_p1p1_to_p3(&u
, &t
);
82 ge_p3_to_cached(&Ai
[1], &u
);
83 ge_add(&t
, &A2
, &Ai
[1]);
84 ge_p1p1_to_p3(&u
, &t
);
85 ge_p3_to_cached(&Ai
[2], &u
);
86 ge_add(&t
, &A2
, &Ai
[2]);
87 ge_p1p1_to_p3(&u
, &t
);
88 ge_p3_to_cached(&Ai
[3], &u
);
89 ge_add(&t
, &A2
, &Ai
[3]);
90 ge_p1p1_to_p3(&u
, &t
);
91 ge_p3_to_cached(&Ai
[4], &u
);
92 ge_add(&t
, &A2
, &Ai
[4]);
93 ge_p1p1_to_p3(&u
, &t
);
94 ge_p3_to_cached(&Ai
[5], &u
);
95 ge_add(&t
, &A2
, &Ai
[5]);
96 ge_p1p1_to_p3(&u
, &t
);
97 ge_p3_to_cached(&Ai
[6], &u
);
98 ge_add(&t
, &A2
, &Ai
[6]);
99 ge_p1p1_to_p3(&u
, &t
);
100 ge_p3_to_cached(&Ai
[7], &u
);
103 for (i
= 255; i
>= 0; --i
) {
104 if (aslide
[i
] || bslide
[i
]) {
109 for (; i
>= 0; --i
) {
113 ge_p1p1_to_p3(&u
, &t
);
114 ge_add(&t
, &u
, &Ai
[aslide
[i
] / 2]);
115 } else if (aslide
[i
] < 0) {
116 ge_p1p1_to_p3(&u
, &t
);
117 ge_sub(&t
, &u
, &Ai
[(-aslide
[i
]) / 2]);
121 ge_p1p1_to_p3(&u
, &t
);
122 ge_madd(&t
, &u
, &Bi
[bslide
[i
] / 2]);
123 } else if (bslide
[i
] < 0) {
124 ge_p1p1_to_p3(&u
, &t
);
125 ge_msub(&t
, &u
, &Bi
[(-bslide
[i
]) / 2]);
128 ge_p1p1_to_p2(r
, &t
);
133 static const fe d
= {
134 -10913610, 13857413, -15372611, 6949391, 114729, -8787816, -6275908, -3247719, -18696448, -12055116
137 static const fe sqrtm1
= {
138 -32595792, -7943725, 9377950, 3500415, 12389472, -272473, -25146209, -2005654, 326686, 11406482
141 int ge_frombytes_negate_vartime(ge_p3
*h
, const unsigned char *s
) {
147 fe_frombytes(h
->Y
, s
);
151 fe_sub(u
, u
, h
->Z
); /* u = y^2-1 */
152 fe_add(v
, v
, h
->Z
); /* v = dy^2+1 */
154 fe_mul(v3
, v3
, v
); /* v3 = v^3 */
156 fe_mul(h
->X
, h
->X
, v
);
157 fe_mul(h
->X
, h
->X
, u
); /* x = uv^7 */
158 fe_pow22523(h
->X
, h
->X
); /* x = (uv^7)^((q-5)/8) */
159 fe_mul(h
->X
, h
->X
, v3
);
160 fe_mul(h
->X
, h
->X
, u
); /* x = uv^3(uv^7)^((q-5)/8) */
163 fe_sub(check
, vxx
, u
); /* vx^2-u */
165 if (fe_isnonzero(check
)) {
166 fe_add(check
, vxx
, u
); /* vx^2+u */
168 if (fe_isnonzero(check
)) {
172 fe_mul(h
->X
, h
->X
, sqrtm1
);
175 if (fe_isnegative(h
->X
) == (s
[31] >> 7)) {
179 fe_mul(h
->T
, h
->X
, h
->Y
);
188 void ge_madd(ge_p1p1
*r
, const ge_p3
*p
, const ge_precomp
*q
) {
190 fe_add(r
->X
, p
->Y
, p
->X
);
191 fe_sub(r
->Y
, p
->Y
, p
->X
);
192 fe_mul(r
->Z
, r
->X
, q
->yplusx
);
193 fe_mul(r
->Y
, r
->Y
, q
->yminusx
);
194 fe_mul(r
->T
, q
->xy2d
, p
->T
);
195 fe_add(t0
, p
->Z
, p
->Z
);
196 fe_sub(r
->X
, r
->Z
, r
->Y
);
197 fe_add(r
->Y
, r
->Z
, r
->Y
);
198 fe_add(r
->Z
, t0
, r
->T
);
199 fe_sub(r
->T
, t0
, r
->T
);
207 void ge_msub(ge_p1p1
*r
, const ge_p3
*p
, const ge_precomp
*q
) {
210 fe_add(r
->X
, p
->Y
, p
->X
);
211 fe_sub(r
->Y
, p
->Y
, p
->X
);
212 fe_mul(r
->Z
, r
->X
, q
->yminusx
);
213 fe_mul(r
->Y
, r
->Y
, q
->yplusx
);
214 fe_mul(r
->T
, q
->xy2d
, p
->T
);
215 fe_add(t0
, p
->Z
, p
->Z
);
216 fe_sub(r
->X
, r
->Z
, r
->Y
);
217 fe_add(r
->Y
, r
->Z
, r
->Y
);
218 fe_sub(r
->Z
, t0
, r
->T
);
219 fe_add(r
->T
, t0
, r
->T
);
227 void ge_p1p1_to_p2(ge_p2
*r
, const ge_p1p1
*p
) {
228 fe_mul(r
->X
, p
->X
, p
->T
);
229 fe_mul(r
->Y
, p
->Y
, p
->Z
);
230 fe_mul(r
->Z
, p
->Z
, p
->T
);
239 void ge_p1p1_to_p3(ge_p3
*r
, const ge_p1p1
*p
) {
240 fe_mul(r
->X
, p
->X
, p
->T
);
241 fe_mul(r
->Y
, p
->Y
, p
->Z
);
242 fe_mul(r
->Z
, p
->Z
, p
->T
);
243 fe_mul(r
->T
, p
->X
, p
->Y
);
247 void ge_p2_0(ge_p2
*h
) {
259 void ge_p2_dbl(ge_p1p1
*r
, const ge_p2
*p
) {
265 fe_add(r
->Y
, p
->X
, p
->Y
);
267 fe_add(r
->Y
, r
->Z
, r
->X
);
268 fe_sub(r
->Z
, r
->Z
, r
->X
);
269 fe_sub(r
->X
, t0
, r
->Y
);
270 fe_sub(r
->T
, r
->T
, r
->Z
);
274 void ge_p3_0(ge_p3
*h
) {
286 void ge_p3_dbl(ge_p1p1
*r
, const ge_p3
*p
) {
298 static const fe d2
= {
299 -21827239, -5839606, -30745221, 13898782, 229458, 15978800, -12551817, -6495438, 29715968, 9444199
302 void ge_p3_to_cached(ge_cached
*r
, const ge_p3
*p
) {
303 fe_add(r
->YplusX
, p
->Y
, p
->X
);
304 fe_sub(r
->YminusX
, p
->Y
, p
->X
);
306 fe_mul(r
->T2d
, p
->T
, d2
);
314 void ge_p3_to_p2(ge_p2
*r
, const ge_p3
*p
) {
321 void ge_p3_tobytes(unsigned char *s
, const ge_p3
*h
) {
325 fe_invert(recip
, h
->Z
);
326 fe_mul(x
, h
->X
, recip
);
327 fe_mul(y
, h
->Y
, recip
);
329 s
[31] ^= fe_isnegative(x
) << 7;
333 static unsigned char equal(signed char b
, signed char c
) {
334 unsigned char ub
= b
;
335 unsigned char uc
= c
;
336 unsigned char x
= ub
^ uc
; /* 0: yes; 1..255: no */
337 uint64_t y
= x
; /* 0: yes; 1..255: no */
338 y
-= 1; /* large: yes; 0..254: no */
339 y
>>= 63; /* 1: yes; 0: no */
340 return (unsigned char) y
;
343 static unsigned char negative(signed char b
) {
344 uint64_t x
= b
; /* 18446744073709551361..18446744073709551615: yes; 0..255: no */
345 x
>>= 63; /* 1: yes; 0: no */
346 return (unsigned char) x
;
349 static void cmov(ge_precomp
*t
, ge_precomp
*u
, unsigned char b
) {
350 fe_cmov(t
->yplusx
, u
->yplusx
, b
);
351 fe_cmov(t
->yminusx
, u
->yminusx
, b
);
352 fe_cmov(t
->xy2d
, u
->xy2d
, b
);
356 static void select(ge_precomp
*t
, int pos
, signed char b
) {
358 unsigned char bnegative
= negative(b
);
359 unsigned char babs
= b
- (((-bnegative
) & b
) << 1);
363 cmov(t
, &base
[pos
][0], equal(babs
, 1));
364 cmov(t
, &base
[pos
][1], equal(babs
, 2));
365 cmov(t
, &base
[pos
][2], equal(babs
, 3));
366 cmov(t
, &base
[pos
][3], equal(babs
, 4));
367 cmov(t
, &base
[pos
][4], equal(babs
, 5));
368 cmov(t
, &base
[pos
][5], equal(babs
, 6));
369 cmov(t
, &base
[pos
][6], equal(babs
, 7));
370 cmov(t
, &base
[pos
][7], equal(babs
, 8));
371 fe_copy(minust
.yplusx
, t
->yminusx
);
372 fe_copy(minust
.yminusx
, t
->yplusx
);
373 fe_neg(minust
.xy2d
, t
->xy2d
);
374 cmov(t
, &minust
, bnegative
);
379 where a = a[0]+256*a[1]+...+256^31 a[31]
380 B is the Ed25519 base point (x,4/5) with x positive.
386 void ge_scalarmult_base(ge_p3
*h
, const unsigned char *a
) {
394 for (i
= 0; i
< 32; ++i
) {
395 e
[2 * i
+ 0] = (a
[i
] >> 0) & 15;
396 e
[2 * i
+ 1] = (a
[i
] >> 4) & 15;
399 /* each e[i] is between 0 and 15 */
400 /* e[63] is between 0 and 7 */
403 for (i
= 0; i
< 63; ++i
) {
411 /* each e[i] is between -8 and 8 */
414 for (i
= 1; i
< 64; i
+= 2) {
415 select(&t
, i
/ 2, e
[i
]);
417 ge_p1p1_to_p3(h
, &r
);
421 ge_p1p1_to_p2(&s
, &r
);
423 ge_p1p1_to_p2(&s
, &r
);
425 ge_p1p1_to_p2(&s
, &r
);
427 ge_p1p1_to_p3(h
, &r
);
429 for (i
= 0; i
< 64; i
+= 2) {
430 select(&t
, i
/ 2, e
[i
]);
432 ge_p1p1_to_p3(h
, &r
);
441 void ge_sub(ge_p1p1
*r
, const ge_p3
*p
, const ge_cached
*q
) {
444 fe_add(r
->X
, p
->Y
, p
->X
);
445 fe_sub(r
->Y
, p
->Y
, p
->X
);
446 fe_mul(r
->Z
, r
->X
, q
->YminusX
);
447 fe_mul(r
->Y
, r
->Y
, q
->YplusX
);
448 fe_mul(r
->T
, q
->T2d
, p
->T
);
449 fe_mul(r
->X
, p
->Z
, q
->Z
);
450 fe_add(t0
, r
->X
, r
->X
);
451 fe_sub(r
->X
, r
->Z
, r
->Y
);
452 fe_add(r
->Y
, r
->Z
, r
->Y
);
453 fe_sub(r
->Z
, t0
, r
->T
);
454 fe_add(r
->T
, t0
, r
->T
);
458 void ge_tobytes(unsigned char *s
, const ge_p2
*h
) {
462 fe_invert(recip
, h
->Z
);
463 fe_mul(x
, h
->X
, recip
);
464 fe_mul(y
, h
->Y
, recip
);
466 s
[31] ^= fe_isnegative(x
) << 7;