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