1 #define WINDOWSIZE 1 /* Should be 1,2, or 4 */
2 #define WINDOWMASK ((1<<WINDOWSIZE)-1)
6 static crypto_uint32
equal(crypto_uint32 a
,crypto_uint32 b
) /* 16-bit inputs */
8 crypto_uint32 x
= a
^ b
; /* 0: yes; 1..65535: no */
9 x
-= 1; /* 4294967295: yes; 0..65534: no */
10 x
>>= 31; /* 1: yes; 0: no */
14 static crypto_uint32
ge(crypto_uint32 a
,crypto_uint32 b
) /* 16-bit inputs */
17 x
-= (unsigned int) b
; /* 0..65535: yes; 4294901761..4294967295: no */
18 x
>>= 31; /* 0: yes; 1: no */
19 x
^= 1; /* 1: yes; 0: no */
23 static crypto_uint32
times19(crypto_uint32 a
)
25 return (a
<< 4) + (a
<< 1) + a
;
28 static crypto_uint32
times38(crypto_uint32 a
)
30 return (a
<< 5) + (a
<< 2) + (a
<< 1);
33 static void reduce_add_sub(fe25519
*r
)
38 for(rep
=0;rep
<4;rep
++)
53 static void reduce_mul(fe25519
*r
)
58 for(rep
=0;rep
<2;rep
++)
73 /* reduction modulo 2^255-19 */
74 void fe25519_freeze(fe25519
*r
)
77 crypto_uint32 m
= equal(r
->v
[31],127);
79 m
&= equal(r
->v
[i
],255);
90 void fe25519_unpack(fe25519
*r
, const unsigned char x
[32])
93 for(i
=0;i
<32;i
++) r
->v
[i
] = x
[i
];
97 /* Assumes input x being reduced below 2^255 */
98 void fe25519_pack(unsigned char r
[32], const fe25519
*x
)
107 int fe25519_iszero(const fe25519
*x
)
112 int r
= equal(t
.v
[0],0);
114 r
&= equal(t
.v
[i
],0);
118 int fe25519_iseq_vartime(const fe25519
*x
, const fe25519
*y
)
126 if(t1
.v
[i
] != t2
.v
[i
]) return 0;
130 void fe25519_cmov(fe25519
*r
, const fe25519
*x
, unsigned char b
)
133 crypto_uint32 mask
= b
;
135 for(i
=0;i
<32;i
++) r
->v
[i
] ^= mask
& (x
->v
[i
] ^ r
->v
[i
]);
138 unsigned char fe25519_getparity(const fe25519
*x
)
145 void fe25519_setone(fe25519
*r
)
149 for(i
=1;i
<32;i
++) r
->v
[i
]=0;
152 void fe25519_setzero(fe25519
*r
)
155 for(i
=0;i
<32;i
++) r
->v
[i
]=0;
158 void fe25519_neg(fe25519
*r
, const fe25519
*x
)
162 for(i
=0;i
<32;i
++) t
.v
[i
]=x
->v
[i
];
164 fe25519_sub(r
, r
, &t
);
167 void fe25519_add(fe25519
*r
, const fe25519
*x
, const fe25519
*y
)
170 for(i
=0;i
<32;i
++) r
->v
[i
] = x
->v
[i
] + y
->v
[i
];
174 void fe25519_sub(fe25519
*r
, const fe25519
*x
, const fe25519
*y
)
178 t
[0] = x
->v
[0] + 0x1da;
179 t
[31] = x
->v
[31] + 0xfe;
180 for(i
=1;i
<31;i
++) t
[i
] = x
->v
[i
] + 0x1fe;
181 for(i
=0;i
<32;i
++) r
->v
[i
] = t
[i
] - y
->v
[i
];
185 void fe25519_mul(fe25519
*r
, const fe25519
*x
, const fe25519
*y
)
189 for(i
=0;i
<63;i
++)t
[i
] = 0;
193 t
[i
+j
] += x
->v
[i
] * y
->v
[j
];
196 r
->v
[i
-32] = t
[i
-32] + times38(t
[i
]);
197 r
->v
[31] = t
[31]; /* result now in r[0]...r[31] */
202 void fe25519_square(fe25519
*r
, const fe25519
*x
)
204 fe25519_mul(r
, x
, x
);
207 void fe25519_invert(fe25519
*r
, const fe25519
*x
)
221 /* 2 */ fe25519_square(&z2
,x
);
222 /* 4 */ fe25519_square(&t1
,&z2
);
223 /* 8 */ fe25519_square(&t0
,&t1
);
224 /* 9 */ fe25519_mul(&z9
,&t0
,x
);
225 /* 11 */ fe25519_mul(&z11
,&z9
,&z2
);
226 /* 22 */ fe25519_square(&t0
,&z11
);
227 /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0
,&t0
,&z9
);
229 /* 2^6 - 2^1 */ fe25519_square(&t0
,&z2_5_0
);
230 /* 2^7 - 2^2 */ fe25519_square(&t1
,&t0
);
231 /* 2^8 - 2^3 */ fe25519_square(&t0
,&t1
);
232 /* 2^9 - 2^4 */ fe25519_square(&t1
,&t0
);
233 /* 2^10 - 2^5 */ fe25519_square(&t0
,&t1
);
234 /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0
,&t0
,&z2_5_0
);
236 /* 2^11 - 2^1 */ fe25519_square(&t0
,&z2_10_0
);
237 /* 2^12 - 2^2 */ fe25519_square(&t1
,&t0
);
238 /* 2^20 - 2^10 */ for (i
= 2;i
< 10;i
+= 2) { fe25519_square(&t0
,&t1
); fe25519_square(&t1
,&t0
); }
239 /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0
,&t1
,&z2_10_0
);
241 /* 2^21 - 2^1 */ fe25519_square(&t0
,&z2_20_0
);
242 /* 2^22 - 2^2 */ fe25519_square(&t1
,&t0
);
243 /* 2^40 - 2^20 */ for (i
= 2;i
< 20;i
+= 2) { fe25519_square(&t0
,&t1
); fe25519_square(&t1
,&t0
); }
244 /* 2^40 - 2^0 */ fe25519_mul(&t0
,&t1
,&z2_20_0
);
246 /* 2^41 - 2^1 */ fe25519_square(&t1
,&t0
);
247 /* 2^42 - 2^2 */ fe25519_square(&t0
,&t1
);
248 /* 2^50 - 2^10 */ for (i
= 2;i
< 10;i
+= 2) { fe25519_square(&t1
,&t0
); fe25519_square(&t0
,&t1
); }
249 /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0
,&t0
,&z2_10_0
);
251 /* 2^51 - 2^1 */ fe25519_square(&t0
,&z2_50_0
);
252 /* 2^52 - 2^2 */ fe25519_square(&t1
,&t0
);
253 /* 2^100 - 2^50 */ for (i
= 2;i
< 50;i
+= 2) { fe25519_square(&t0
,&t1
); fe25519_square(&t1
,&t0
); }
254 /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0
,&t1
,&z2_50_0
);
256 /* 2^101 - 2^1 */ fe25519_square(&t1
,&z2_100_0
);
257 /* 2^102 - 2^2 */ fe25519_square(&t0
,&t1
);
258 /* 2^200 - 2^100 */ for (i
= 2;i
< 100;i
+= 2) { fe25519_square(&t1
,&t0
); fe25519_square(&t0
,&t1
); }
259 /* 2^200 - 2^0 */ fe25519_mul(&t1
,&t0
,&z2_100_0
);
261 /* 2^201 - 2^1 */ fe25519_square(&t0
,&t1
);
262 /* 2^202 - 2^2 */ fe25519_square(&t1
,&t0
);
263 /* 2^250 - 2^50 */ for (i
= 2;i
< 50;i
+= 2) { fe25519_square(&t0
,&t1
); fe25519_square(&t1
,&t0
); }
264 /* 2^250 - 2^0 */ fe25519_mul(&t0
,&t1
,&z2_50_0
);
266 /* 2^251 - 2^1 */ fe25519_square(&t1
,&t0
);
267 /* 2^252 - 2^2 */ fe25519_square(&t0
,&t1
);
268 /* 2^253 - 2^3 */ fe25519_square(&t1
,&t0
);
269 /* 2^254 - 2^4 */ fe25519_square(&t0
,&t1
);
270 /* 2^255 - 2^5 */ fe25519_square(&t1
,&t0
);
271 /* 2^255 - 21 */ fe25519_mul(r
,&t1
,&z11
);
274 void fe25519_pow2523(fe25519
*r
, const fe25519
*x
)
287 /* 2 */ fe25519_square(&z2
,x
);
288 /* 4 */ fe25519_square(&t
,&z2
);
289 /* 8 */ fe25519_square(&t
,&t
);
290 /* 9 */ fe25519_mul(&z9
,&t
,x
);
291 /* 11 */ fe25519_mul(&z11
,&z9
,&z2
);
292 /* 22 */ fe25519_square(&t
,&z11
);
293 /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0
,&t
,&z9
);
295 /* 2^6 - 2^1 */ fe25519_square(&t
,&z2_5_0
);
296 /* 2^10 - 2^5 */ for (i
= 1;i
< 5;i
++) { fe25519_square(&t
,&t
); }
297 /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0
,&t
,&z2_5_0
);
299 /* 2^11 - 2^1 */ fe25519_square(&t
,&z2_10_0
);
300 /* 2^20 - 2^10 */ for (i
= 1;i
< 10;i
++) { fe25519_square(&t
,&t
); }
301 /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0
,&t
,&z2_10_0
);
303 /* 2^21 - 2^1 */ fe25519_square(&t
,&z2_20_0
);
304 /* 2^40 - 2^20 */ for (i
= 1;i
< 20;i
++) { fe25519_square(&t
,&t
); }
305 /* 2^40 - 2^0 */ fe25519_mul(&t
,&t
,&z2_20_0
);
307 /* 2^41 - 2^1 */ fe25519_square(&t
,&t
);
308 /* 2^50 - 2^10 */ for (i
= 1;i
< 10;i
++) { fe25519_square(&t
,&t
); }
309 /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0
,&t
,&z2_10_0
);
311 /* 2^51 - 2^1 */ fe25519_square(&t
,&z2_50_0
);
312 /* 2^100 - 2^50 */ for (i
= 1;i
< 50;i
++) { fe25519_square(&t
,&t
); }
313 /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0
,&t
,&z2_50_0
);
315 /* 2^101 - 2^1 */ fe25519_square(&t
,&z2_100_0
);
316 /* 2^200 - 2^100 */ for (i
= 1;i
< 100;i
++) { fe25519_square(&t
,&t
); }
317 /* 2^200 - 2^0 */ fe25519_mul(&t
,&t
,&z2_100_0
);
319 /* 2^201 - 2^1 */ fe25519_square(&t
,&t
);
320 /* 2^250 - 2^50 */ for (i
= 1;i
< 50;i
++) { fe25519_square(&t
,&t
); }
321 /* 2^250 - 2^0 */ fe25519_mul(&t
,&t
,&z2_50_0
);
323 /* 2^251 - 2^1 */ fe25519_square(&t
,&t
);
324 /* 2^252 - 2^2 */ fe25519_square(&t
,&t
);
325 /* 2^252 - 3 */ fe25519_mul(r
,&t
,x
);