summaryrefslogtreecommitdiff
path: root/nacl/crypto_sign/edwards25519sha512batch/ref/fe25519.c
diff options
context:
space:
mode:
Diffstat (limited to 'nacl/crypto_sign/edwards25519sha512batch/ref/fe25519.c')
-rw-r--r--nacl/crypto_sign/edwards25519sha512batch/ref/fe25519.c345
1 files changed, 345 insertions, 0 deletions
diff --git a/nacl/crypto_sign/edwards25519sha512batch/ref/fe25519.c b/nacl/crypto_sign/edwards25519sha512batch/ref/fe25519.c
new file mode 100644
index 00000000..a9f806d2
--- /dev/null
+++ b/nacl/crypto_sign/edwards25519sha512batch/ref/fe25519.c
@@ -0,0 +1,345 @@
1#include "fe25519.h"
2
3#define WINDOWSIZE 4 /* Should be 1,2, or 4 */
4#define WINDOWMASK ((1<<WINDOWSIZE)-1)
5
6static void reduce_add_sub(fe25519 *r)
7{
8 crypto_uint32 t;
9 int i,rep;
10
11 for(rep=0;rep<4;rep++)
12 {
13 t = r->v[31] >> 7;
14 r->v[31] &= 127;
15 t *= 19;
16 r->v[0] += t;
17 for(i=0;i<31;i++)
18 {
19 t = r->v[i] >> 8;
20 r->v[i+1] += t;
21 r->v[i] &= 255;
22 }
23 }
24}
25
26static void reduce_mul(fe25519 *r)
27{
28 crypto_uint32 t;
29 int i,rep;
30
31 for(rep=0;rep<2;rep++)
32 {
33 t = r->v[31] >> 7;
34 r->v[31] &= 127;
35 t *= 19;
36 r->v[0] += t;
37 for(i=0;i<31;i++)
38 {
39 t = r->v[i] >> 8;
40 r->v[i+1] += t;
41 r->v[i] &= 255;
42 }
43 }
44}
45
46/* reduction modulo 2^255-19 */
47static void freeze(fe25519 *r)
48{
49 int i;
50 unsigned int m = (r->v[31] == 127);
51 for(i=30;i>1;i--)
52 m *= (r->v[i] == 255);
53 m *= (r->v[0] >= 237);
54
55 r->v[31] -= m*127;
56 for(i=30;i>0;i--)
57 r->v[i] -= m*255;
58 r->v[0] -= m*237;
59}
60
61/*freeze input before calling isone*/
62static int isone(const fe25519 *x)
63{
64 int i;
65 int r = (x->v[0] == 1);
66 for(i=1;i<32;i++)
67 r *= (x->v[i] == 0);
68 return r;
69}
70
71/*freeze input before calling iszero*/
72static int iszero(const fe25519 *x)
73{
74 int i;
75 int r = (x->v[0] == 0);
76 for(i=1;i<32;i++)
77 r *= (x->v[i] == 0);
78 return r;
79}
80
81
82static int issquare(const fe25519 *x)
83{
84 unsigned char e[32] = {0xf6,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f}; /* (p-1)/2 */
85 fe25519 t;
86
87 fe25519_pow(&t,x,e);
88 freeze(&t);
89 return isone(&t) || iszero(&t);
90}
91
92void fe25519_unpack(fe25519 *r, const unsigned char x[32])
93{
94 int i;
95 for(i=0;i<32;i++) r->v[i] = x[i];
96 r->v[31] &= 127;
97}
98
99/* Assumes input x being reduced mod 2^255 */
100void fe25519_pack(unsigned char r[32], const fe25519 *x)
101{
102 int i;
103 for(i=0;i<32;i++)
104 r[i] = x->v[i];
105
106 /* freeze byte array */
107 unsigned int m = (r[31] == 127); /* XXX: some compilers might use branches; fix */
108 for(i=30;i>1;i--)
109 m *= (r[i] == 255);
110 m *= (r[0] >= 237);
111 r[31] -= m*127;
112 for(i=30;i>0;i--)
113 r[i] -= m*255;
114 r[0] -= m*237;
115}
116
117void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
118{
119 unsigned char nb = 1-b;
120 int i;
121 for(i=0;i<32;i++) r->v[i] = nb * r->v[i] + b * x->v[i];
122}
123
124unsigned char fe25519_getparity(const fe25519 *x)
125{
126 fe25519 t;
127 int i;
128 for(i=0;i<32;i++) t.v[i] = x->v[i];
129 freeze(&t);
130 return t.v[0] & 1;
131}
132
133void fe25519_setone(fe25519 *r)
134{
135 int i;
136 r->v[0] = 1;
137 for(i=1;i<32;i++) r->v[i]=0;
138}
139
140void fe25519_setzero(fe25519 *r)
141{
142 int i;
143 for(i=0;i<32;i++) r->v[i]=0;
144}
145
146void fe25519_neg(fe25519 *r, const fe25519 *x)
147{
148 fe25519 t;
149 int i;
150 for(i=0;i<32;i++) t.v[i]=x->v[i];
151 fe25519_setzero(r);
152 fe25519_sub(r, r, &t);
153}
154
155void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
156{
157 int i;
158 for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i];
159 reduce_add_sub(r);
160}
161
162void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
163{
164 int i;
165 crypto_uint32 t[32];
166 t[0] = x->v[0] + 0x1da;
167 t[31] = x->v[31] + 0xfe;
168 for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe;
169 for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i];
170 reduce_add_sub(r);
171}
172
173void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
174{
175 int i,j;
176 crypto_uint32 t[63];
177 for(i=0;i<63;i++)t[i] = 0;
178
179 for(i=0;i<32;i++)
180 for(j=0;j<32;j++)
181 t[i+j] += x->v[i] * y->v[j];
182
183 for(i=32;i<63;i++)
184 r->v[i-32] = t[i-32] + 38*t[i];
185 r->v[31] = t[31]; /* result now in r[0]...r[31] */
186
187 reduce_mul(r);
188}
189
190void fe25519_square(fe25519 *r, const fe25519 *x)
191{
192 fe25519_mul(r, x, x);
193}
194
195/*XXX: Make constant time! */
196void fe25519_pow(fe25519 *r, const fe25519 *x, const unsigned char *e)
197{
198 /*
199 fe25519 g;
200 fe25519_setone(&g);
201 int i;
202 unsigned char j;
203 for(i=32;i>0;i--)
204 {
205 for(j=128;j>0;j>>=1)
206 {
207 fe25519_square(&g,&g);
208 if(e[i-1] & j)
209 fe25519_mul(&g,&g,x);
210 }
211 }
212 for(i=0;i<32;i++) r->v[i] = g.v[i];
213 */
214 fe25519 g;
215 fe25519_setone(&g);
216 int i,j,k;
217 fe25519 pre[(1 << WINDOWSIZE)];
218 fe25519 t;
219 unsigned char w;
220
221 // Precomputation
222 fe25519_setone(pre);
223 pre[1] = *x;
224 for(i=2;i<(1<<WINDOWSIZE);i+=2)
225 {
226 fe25519_square(pre+i, pre+i/2);
227 fe25519_mul(pre+i+1, pre+i, pre+1);
228 }
229
230 // Fixed-window scalar multiplication
231 for(i=32;i>0;i--)
232 {
233 for(j=8-WINDOWSIZE;j>=0;j-=WINDOWSIZE)
234 {
235 for(k=0;k<WINDOWSIZE;k++)
236 fe25519_square(&g, &g);
237 // Cache-timing resistant loading of precomputed value:
238 w = (e[i-1]>>j) & WINDOWMASK;
239 t = pre[0];
240 for(k=1;k<(1<<WINDOWSIZE);k++)
241 fe25519_cmov(&t, &pre[k], k==w);
242 fe25519_mul(&g, &g, &t);
243 }
244 }
245 *r = g;
246}
247
248/* Return 0 on success, 1 otherwise */
249int fe25519_sqrt_vartime(fe25519 *r, const fe25519 *x, unsigned char parity)
250{
251 /* See HAC, Alg. 3.37 */
252 if (!issquare(x)) return -1;
253 unsigned char e[32] = {0xfb,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f}; /* (p-1)/4 */
254 unsigned char e2[32] = {0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f}; /* (p+3)/8 */
255 unsigned char e3[32] = {0xfd,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x0f}; /* (p-5)/8 */
256 fe25519 p = {{0}};
257 fe25519 d;
258 int i;
259 fe25519_pow(&d,x,e);
260 freeze(&d);
261 if(isone(&d))
262 fe25519_pow(r,x,e2);
263 else
264 {
265 for(i=0;i<32;i++)
266 d.v[i] = 4*x->v[i];
267 fe25519_pow(&d,&d,e3);
268 for(i=0;i<32;i++)
269 r->v[i] = 2*x->v[i];
270 fe25519_mul(r,r,&d);
271 }
272 freeze(r);
273 if((r->v[0] & 1) != (parity & 1))
274 {
275 fe25519_sub(r,&p,r);
276 }
277 return 0;
278}
279
280void fe25519_invert(fe25519 *r, const fe25519 *x)
281{
282 fe25519 z2;
283 fe25519 z9;
284 fe25519 z11;
285 fe25519 z2_5_0;
286 fe25519 z2_10_0;
287 fe25519 z2_20_0;
288 fe25519 z2_50_0;
289 fe25519 z2_100_0;
290 fe25519 t0;
291 fe25519 t1;
292 int i;
293
294 /* 2 */ fe25519_square(&z2,x);
295 /* 4 */ fe25519_square(&t1,&z2);
296 /* 8 */ fe25519_square(&t0,&t1);
297 /* 9 */ fe25519_mul(&z9,&t0,x);
298 /* 11 */ fe25519_mul(&z11,&z9,&z2);
299 /* 22 */ fe25519_square(&t0,&z11);
300 /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9);
301
302 /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0);
303 /* 2^7 - 2^2 */ fe25519_square(&t1,&t0);
304 /* 2^8 - 2^3 */ fe25519_square(&t0,&t1);
305 /* 2^9 - 2^4 */ fe25519_square(&t1,&t0);
306 /* 2^10 - 2^5 */ fe25519_square(&t0,&t1);
307 /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0);
308
309 /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0);
310 /* 2^12 - 2^2 */ fe25519_square(&t1,&t0);
311 /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
312 /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0);
313
314 /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0);
315 /* 2^22 - 2^2 */ fe25519_square(&t1,&t0);
316 /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
317 /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0);
318
319 /* 2^41 - 2^1 */ fe25519_square(&t1,&t0);
320 /* 2^42 - 2^2 */ fe25519_square(&t0,&t1);
321 /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
322 /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0);
323
324 /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0);
325 /* 2^52 - 2^2 */ fe25519_square(&t1,&t0);
326 /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
327 /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0);
328
329 /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0);
330 /* 2^102 - 2^2 */ fe25519_square(&t0,&t1);
331 /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
332 /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0);
333
334 /* 2^201 - 2^1 */ fe25519_square(&t0,&t1);
335 /* 2^202 - 2^2 */ fe25519_square(&t1,&t0);
336 /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
337 /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0);
338
339 /* 2^251 - 2^1 */ fe25519_square(&t1,&t0);
340 /* 2^252 - 2^2 */ fe25519_square(&t0,&t1);
341 /* 2^253 - 2^3 */ fe25519_square(&t1,&t0);
342 /* 2^254 - 2^4 */ fe25519_square(&t0,&t1);
343 /* 2^255 - 2^5 */ fe25519_square(&t1,&t0);
344 /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11);
345}