1 /* $OpenBSD: fe25519.c,v 1.3 2013/12/09 11:03:45 markus Exp $ */
4 * Public Domain, Authors: Daniel J. Bernstein, Niels Duif, Tanja Lange,
5 * Peter Schwabe, Bo-Yin Yang.
6 * Copied from supercop-20130419/crypto_sign/ed25519/ref/fe25519.c
11 #define WINDOWSIZE 1 /* Should be 1,2, or 4 */
12 #define WINDOWMASK ((1<<WINDOWSIZE)-1)
16 static crypto_uint32
equal(crypto_uint32 a
,crypto_uint32 b
) /* 16-bit inputs */
18 crypto_uint32 x
= a
^ b
; /* 0: yes; 1..65535: no */
19 x
-= 1; /* 4294967295: yes; 0..65534: no */
20 x
>>= 31; /* 1: yes; 0: no */
24 static crypto_uint32
ge(crypto_uint32 a
,crypto_uint32 b
) /* 16-bit inputs */
27 x
-= (unsigned int) b
; /* 0..65535: yes; 4294901761..4294967295: no */
28 x
>>= 31; /* 0: yes; 1: no */
29 x
^= 1; /* 1: yes; 0: no */
33 static crypto_uint32
times19(crypto_uint32 a
)
35 return (a
<< 4) + (a
<< 1) + a
;
38 static crypto_uint32
times38(crypto_uint32 a
)
40 return (a
<< 5) + (a
<< 2) + (a
<< 1);
43 static void reduce_add_sub(fe25519
*r
)
48 for(rep
=0;rep
<4;rep
++)
63 static void reduce_mul(fe25519
*r
)
68 for(rep
=0;rep
<2;rep
++)
83 /* reduction modulo 2^255-19 */
84 void fe25519_freeze(fe25519
*r
)
87 crypto_uint32 m
= equal(r
->v
[31],127);
89 m
&= equal(r
->v
[i
],255);
100 void fe25519_unpack(fe25519
*r
, const unsigned char x
[32])
103 for(i
=0;i
<32;i
++) r
->v
[i
] = x
[i
];
107 /* Assumes input x being reduced below 2^255 */
108 void fe25519_pack(unsigned char r
[32], const fe25519
*x
)
117 int fe25519_iszero(const fe25519
*x
)
125 r
&= equal(t
.v
[i
],0);
129 int fe25519_iseq_vartime(const fe25519
*x
, const fe25519
*y
)
137 if(t1
.v
[i
] != t2
.v
[i
]) return 0;
141 void fe25519_cmov(fe25519
*r
, const fe25519
*x
, unsigned char b
)
144 crypto_uint32 mask
= b
;
146 for(i
=0;i
<32;i
++) r
->v
[i
] ^= mask
& (x
->v
[i
] ^ r
->v
[i
]);
149 unsigned char fe25519_getparity(const fe25519
*x
)
156 void fe25519_setone(fe25519
*r
)
160 for(i
=1;i
<32;i
++) r
->v
[i
]=0;
163 void fe25519_setzero(fe25519
*r
)
166 for(i
=0;i
<32;i
++) r
->v
[i
]=0;
169 void fe25519_neg(fe25519
*r
, const fe25519
*x
)
173 for(i
=0;i
<32;i
++) t
.v
[i
]=x
->v
[i
];
175 fe25519_sub(r
, r
, &t
);
178 void fe25519_add(fe25519
*r
, const fe25519
*x
, const fe25519
*y
)
181 for(i
=0;i
<32;i
++) r
->v
[i
] = x
->v
[i
] + y
->v
[i
];
185 void fe25519_sub(fe25519
*r
, const fe25519
*x
, const fe25519
*y
)
189 t
[0] = x
->v
[0] + 0x1da;
190 t
[31] = x
->v
[31] + 0xfe;
191 for(i
=1;i
<31;i
++) t
[i
] = x
->v
[i
] + 0x1fe;
192 for(i
=0;i
<32;i
++) r
->v
[i
] = t
[i
] - y
->v
[i
];
196 void fe25519_mul(fe25519
*r
, const fe25519
*x
, const fe25519
*y
)
200 for(i
=0;i
<63;i
++)t
[i
] = 0;
204 t
[i
+j
] += x
->v
[i
] * y
->v
[j
];
207 r
->v
[i
-32] = t
[i
-32] + times38(t
[i
]);
208 r
->v
[31] = t
[31]; /* result now in r[0]...r[31] */
213 void fe25519_square(fe25519
*r
, const fe25519
*x
)
215 fe25519_mul(r
, x
, x
);
218 void fe25519_invert(fe25519
*r
, const fe25519
*x
)
232 /* 2 */ fe25519_square(&z2
,x
);
233 /* 4 */ fe25519_square(&t1
,&z2
);
234 /* 8 */ fe25519_square(&t0
,&t1
);
235 /* 9 */ fe25519_mul(&z9
,&t0
,x
);
236 /* 11 */ fe25519_mul(&z11
,&z9
,&z2
);
237 /* 22 */ fe25519_square(&t0
,&z11
);
238 /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0
,&t0
,&z9
);
240 /* 2^6 - 2^1 */ fe25519_square(&t0
,&z2_5_0
);
241 /* 2^7 - 2^2 */ fe25519_square(&t1
,&t0
);
242 /* 2^8 - 2^3 */ fe25519_square(&t0
,&t1
);
243 /* 2^9 - 2^4 */ fe25519_square(&t1
,&t0
);
244 /* 2^10 - 2^5 */ fe25519_square(&t0
,&t1
);
245 /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0
,&t0
,&z2_5_0
);
247 /* 2^11 - 2^1 */ fe25519_square(&t0
,&z2_10_0
);
248 /* 2^12 - 2^2 */ fe25519_square(&t1
,&t0
);
249 /* 2^20 - 2^10 */ for (i
= 2;i
< 10;i
+= 2) { fe25519_square(&t0
,&t1
); fe25519_square(&t1
,&t0
); }
250 /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0
,&t1
,&z2_10_0
);
252 /* 2^21 - 2^1 */ fe25519_square(&t0
,&z2_20_0
);
253 /* 2^22 - 2^2 */ fe25519_square(&t1
,&t0
);
254 /* 2^40 - 2^20 */ for (i
= 2;i
< 20;i
+= 2) { fe25519_square(&t0
,&t1
); fe25519_square(&t1
,&t0
); }
255 /* 2^40 - 2^0 */ fe25519_mul(&t0
,&t1
,&z2_20_0
);
257 /* 2^41 - 2^1 */ fe25519_square(&t1
,&t0
);
258 /* 2^42 - 2^2 */ fe25519_square(&t0
,&t1
);
259 /* 2^50 - 2^10 */ for (i
= 2;i
< 10;i
+= 2) { fe25519_square(&t1
,&t0
); fe25519_square(&t0
,&t1
); }
260 /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0
,&t0
,&z2_10_0
);
262 /* 2^51 - 2^1 */ fe25519_square(&t0
,&z2_50_0
);
263 /* 2^52 - 2^2 */ fe25519_square(&t1
,&t0
);
264 /* 2^100 - 2^50 */ for (i
= 2;i
< 50;i
+= 2) { fe25519_square(&t0
,&t1
); fe25519_square(&t1
,&t0
); }
265 /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0
,&t1
,&z2_50_0
);
267 /* 2^101 - 2^1 */ fe25519_square(&t1
,&z2_100_0
);
268 /* 2^102 - 2^2 */ fe25519_square(&t0
,&t1
);
269 /* 2^200 - 2^100 */ for (i
= 2;i
< 100;i
+= 2) { fe25519_square(&t1
,&t0
); fe25519_square(&t0
,&t1
); }
270 /* 2^200 - 2^0 */ fe25519_mul(&t1
,&t0
,&z2_100_0
);
272 /* 2^201 - 2^1 */ fe25519_square(&t0
,&t1
);
273 /* 2^202 - 2^2 */ fe25519_square(&t1
,&t0
);
274 /* 2^250 - 2^50 */ for (i
= 2;i
< 50;i
+= 2) { fe25519_square(&t0
,&t1
); fe25519_square(&t1
,&t0
); }
275 /* 2^250 - 2^0 */ fe25519_mul(&t0
,&t1
,&z2_50_0
);
277 /* 2^251 - 2^1 */ fe25519_square(&t1
,&t0
);
278 /* 2^252 - 2^2 */ fe25519_square(&t0
,&t1
);
279 /* 2^253 - 2^3 */ fe25519_square(&t1
,&t0
);
280 /* 2^254 - 2^4 */ fe25519_square(&t0
,&t1
);
281 /* 2^255 - 2^5 */ fe25519_square(&t1
,&t0
);
282 /* 2^255 - 21 */ fe25519_mul(r
,&t1
,&z11
);
285 void fe25519_pow2523(fe25519
*r
, const fe25519
*x
)
298 /* 2 */ fe25519_square(&z2
,x
);
299 /* 4 */ fe25519_square(&t
,&z2
);
300 /* 8 */ fe25519_square(&t
,&t
);
301 /* 9 */ fe25519_mul(&z9
,&t
,x
);
302 /* 11 */ fe25519_mul(&z11
,&z9
,&z2
);
303 /* 22 */ fe25519_square(&t
,&z11
);
304 /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0
,&t
,&z9
);
306 /* 2^6 - 2^1 */ fe25519_square(&t
,&z2_5_0
);
307 /* 2^10 - 2^5 */ for (i
= 1;i
< 5;i
++) { fe25519_square(&t
,&t
); }
308 /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0
,&t
,&z2_5_0
);
310 /* 2^11 - 2^1 */ fe25519_square(&t
,&z2_10_0
);
311 /* 2^20 - 2^10 */ for (i
= 1;i
< 10;i
++) { fe25519_square(&t
,&t
); }
312 /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0
,&t
,&z2_10_0
);
314 /* 2^21 - 2^1 */ fe25519_square(&t
,&z2_20_0
);
315 /* 2^40 - 2^20 */ for (i
= 1;i
< 20;i
++) { fe25519_square(&t
,&t
); }
316 /* 2^40 - 2^0 */ fe25519_mul(&t
,&t
,&z2_20_0
);
318 /* 2^41 - 2^1 */ fe25519_square(&t
,&t
);
319 /* 2^50 - 2^10 */ for (i
= 1;i
< 10;i
++) { fe25519_square(&t
,&t
); }
320 /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0
,&t
,&z2_10_0
);
322 /* 2^51 - 2^1 */ fe25519_square(&t
,&z2_50_0
);
323 /* 2^100 - 2^50 */ for (i
= 1;i
< 50;i
++) { fe25519_square(&t
,&t
); }
324 /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0
,&t
,&z2_50_0
);
326 /* 2^101 - 2^1 */ fe25519_square(&t
,&z2_100_0
);
327 /* 2^200 - 2^100 */ for (i
= 1;i
< 100;i
++) { fe25519_square(&t
,&t
); }
328 /* 2^200 - 2^0 */ fe25519_mul(&t
,&t
,&z2_100_0
);
330 /* 2^201 - 2^1 */ fe25519_square(&t
,&t
);
331 /* 2^250 - 2^50 */ for (i
= 1;i
< 50;i
++) { fe25519_square(&t
,&t
); }
332 /* 2^250 - 2^0 */ fe25519_mul(&t
,&t
,&z2_50_0
);
334 /* 2^251 - 2^1 */ fe25519_square(&t
,&t
);
335 /* 2^252 - 2^2 */ fe25519_square(&t
,&t
);
336 /* 2^252 - 3 */ fe25519_mul(r
,&t
,x
);