3 #define WINDOWSIZE 4 /* Should be 1,2, or 4 */
4 #define WINDOWMASK ((1<<WINDOWSIZE)-1)
6 static void reduce_add_sub(fe25519 *r)
11 for(rep=0;rep<4;rep++)
26 static void reduce_mul(fe25519 *r)
31 for(rep=0;rep<2;rep++)
46 /* reduction modulo 2^255-19 */
47 static void freeze(fe25519 *r)
50 unsigned int m = (r->v[31] == 127);
52 m *= (r->v[i] == 255);
53 m *= (r->v[0] >= 237);
61 /*freeze input before calling isone*/
62 static int isone(const fe25519 *x)
65 int r = (x->v[0] == 1);
71 /*freeze input before calling iszero*/
72 static int iszero(const fe25519 *x)
75 int r = (x->v[0] == 0);
82 static int issquare(const fe25519 *x)
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 */
89 return isone(&t) || iszero(&t);
92 void fe25519_unpack(fe25519 *r, const unsigned char x[32])
95 for(i=0;i<32;i++) r->v[i] = x[i];
99 /* Assumes input x being reduced mod 2^255 */
100 void fe25519_pack(unsigned char r[32], const fe25519 *x)
107 /* freeze byte array */
108 m = (r[31] == 127); /* XXX: some compilers might use branches; fix */
118 void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
120 unsigned char nb = 1-b;
122 for(i=0;i<32;i++) r->v[i] = nb * r->v[i] + b * x->v[i];
125 unsigned char fe25519_getparity(const fe25519 *x)
129 for(i=0;i<32;i++) t.v[i] = x->v[i];
134 void fe25519_setone(fe25519 *r)
138 for(i=1;i<32;i++) r->v[i]=0;
141 void fe25519_setzero(fe25519 *r)
144 for(i=0;i<32;i++) r->v[i]=0;
147 void fe25519_neg(fe25519 *r, const fe25519 *x)
151 for(i=0;i<32;i++) t.v[i]=x->v[i];
153 fe25519_sub(r, r, &t);
156 void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
159 for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i];
163 void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
167 t[0] = x->v[0] + 0x1da;
168 t[31] = x->v[31] + 0xfe;
169 for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe;
170 for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i];
174 void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
178 for(i=0;i<63;i++)t[i] = 0;
182 t[i+j] += x->v[i] * y->v[j];
185 r->v[i-32] = t[i-32] + 38*t[i];
186 r->v[31] = t[31]; /* result now in r[0]...r[31] */
191 void fe25519_square(fe25519 *r, const fe25519 *x)
193 fe25519_mul(r, x, x);
196 /*XXX: Make constant time! */
197 void fe25519_pow(fe25519 *r, const fe25519 *x, const unsigned char *e)
208 fe25519_square(&g,&g);
210 fe25519_mul(&g,&g,x);
213 for(i=0;i<32;i++) r->v[i] = g.v[i];
219 fe25519 pre[(1 << WINDOWSIZE)];
226 for(i=2;i<(1<<WINDOWSIZE);i+=2)
228 fe25519_square(pre+i, pre+i/2);
229 fe25519_mul(pre+i+1, pre+i, pre+1);
232 // Fixed-window scalar multiplication
235 for(j=8-WINDOWSIZE;j>=0;j-=WINDOWSIZE)
237 for(k=0;k<WINDOWSIZE;k++)
238 fe25519_square(&g, &g);
239 // Cache-timing resistant loading of precomputed value:
240 w = (e[i-1]>>j) & WINDOWMASK;
242 for(k=1;k<(1<<WINDOWSIZE);k++)
243 fe25519_cmov(&t, &pre[k], k==w);
244 fe25519_mul(&g, &g, &t);
250 /* Return 0 on success, 1 otherwise */
251 int fe25519_sqrt_vartime(fe25519 *r, const fe25519 *x, unsigned char parity)
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 */
260 /* See HAC, Alg. 3.37 */
261 if (!issquare(x)) return -1;
270 fe25519_pow(&d,&d,e3);
276 if((r->v[0] & 1) != (parity & 1))
283 void fe25519_invert(fe25519 *r, const fe25519 *x)
297 /* 2 */ fe25519_square(&z2,x);
298 /* 4 */ fe25519_square(&t1,&z2);
299 /* 8 */ fe25519_square(&t0,&t1);
300 /* 9 */ fe25519_mul(&z9,&t0,x);
301 /* 11 */ fe25519_mul(&z11,&z9,&z2);
302 /* 22 */ fe25519_square(&t0,&z11);
303 /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9);
305 /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0);
306 /* 2^7 - 2^2 */ fe25519_square(&t1,&t0);
307 /* 2^8 - 2^3 */ fe25519_square(&t0,&t1);
308 /* 2^9 - 2^4 */ fe25519_square(&t1,&t0);
309 /* 2^10 - 2^5 */ fe25519_square(&t0,&t1);
310 /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0);
312 /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0);
313 /* 2^12 - 2^2 */ fe25519_square(&t1,&t0);
314 /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
315 /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0);
317 /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0);
318 /* 2^22 - 2^2 */ fe25519_square(&t1,&t0);
319 /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
320 /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0);
322 /* 2^41 - 2^1 */ fe25519_square(&t1,&t0);
323 /* 2^42 - 2^2 */ fe25519_square(&t0,&t1);
324 /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
325 /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0);
327 /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0);
328 /* 2^52 - 2^2 */ fe25519_square(&t1,&t0);
329 /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
330 /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0);
332 /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0);
333 /* 2^102 - 2^2 */ fe25519_square(&t0,&t1);
334 /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
335 /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0);
337 /* 2^201 - 2^1 */ fe25519_square(&t0,&t1);
338 /* 2^202 - 2^2 */ fe25519_square(&t1,&t0);
339 /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
340 /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0);
342 /* 2^251 - 2^1 */ fe25519_square(&t1,&t0);
343 /* 2^252 - 2^2 */ fe25519_square(&t0,&t1);
344 /* 2^253 - 2^3 */ fe25519_square(&t1,&t0);
345 /* 2^254 - 2^4 */ fe25519_square(&t0,&t1);
346 /* 2^255 - 2^5 */ fe25519_square(&t1,&t0);
347 /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11);