Annotation of src/usr.bin/ssh/fe25519.c, Revision 1.3
1.3 ! markus 1: /* $OpenBSD: fe25519.c,v 1.2 2013/12/07 00:26:37 djm Exp $ */
1.1 markus 2:
1.3 ! markus 3: /*
! 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
! 7: */
1.1 markus 8:
9: #define WINDOWSIZE 1 /* Should be 1,2, or 4 */
10: #define WINDOWMASK ((1<<WINDOWSIZE)-1)
11:
12: #include "fe25519.h"
13:
14: static crypto_uint32 equal(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
15: {
16: crypto_uint32 x = a ^ b; /* 0: yes; 1..65535: no */
17: x -= 1; /* 4294967295: yes; 0..65534: no */
18: x >>= 31; /* 1: yes; 0: no */
19: return x;
20: }
21:
22: static crypto_uint32 ge(crypto_uint32 a,crypto_uint32 b) /* 16-bit inputs */
23: {
24: unsigned int x = a;
25: x -= (unsigned int) b; /* 0..65535: yes; 4294901761..4294967295: no */
26: x >>= 31; /* 0: yes; 1: no */
27: x ^= 1; /* 1: yes; 0: no */
28: return x;
29: }
30:
31: static crypto_uint32 times19(crypto_uint32 a)
32: {
33: return (a << 4) + (a << 1) + a;
34: }
35:
36: static crypto_uint32 times38(crypto_uint32 a)
37: {
38: return (a << 5) + (a << 2) + (a << 1);
39: }
40:
41: static void reduce_add_sub(fe25519 *r)
42: {
43: crypto_uint32 t;
44: int i,rep;
45:
46: for(rep=0;rep<4;rep++)
47: {
48: t = r->v[31] >> 7;
49: r->v[31] &= 127;
50: t = times19(t);
51: r->v[0] += t;
52: for(i=0;i<31;i++)
53: {
54: t = r->v[i] >> 8;
55: r->v[i+1] += t;
56: r->v[i] &= 255;
57: }
58: }
59: }
60:
61: static void reduce_mul(fe25519 *r)
62: {
63: crypto_uint32 t;
64: int i,rep;
65:
66: for(rep=0;rep<2;rep++)
67: {
68: t = r->v[31] >> 7;
69: r->v[31] &= 127;
70: t = times19(t);
71: r->v[0] += t;
72: for(i=0;i<31;i++)
73: {
74: t = r->v[i] >> 8;
75: r->v[i+1] += t;
76: r->v[i] &= 255;
77: }
78: }
79: }
80:
81: /* reduction modulo 2^255-19 */
82: void fe25519_freeze(fe25519 *r)
83: {
84: int i;
85: crypto_uint32 m = equal(r->v[31],127);
86: for(i=30;i>0;i--)
87: m &= equal(r->v[i],255);
88: m &= ge(r->v[0],237);
89:
90: m = -m;
91:
92: r->v[31] -= m&127;
93: for(i=30;i>0;i--)
94: r->v[i] -= m&255;
95: r->v[0] -= m&237;
96: }
97:
98: void fe25519_unpack(fe25519 *r, const unsigned char x[32])
99: {
100: int i;
101: for(i=0;i<32;i++) r->v[i] = x[i];
102: r->v[31] &= 127;
103: }
104:
105: /* Assumes input x being reduced below 2^255 */
106: void fe25519_pack(unsigned char r[32], const fe25519 *x)
107: {
108: int i;
109: fe25519 y = *x;
110: fe25519_freeze(&y);
111: for(i=0;i<32;i++)
112: r[i] = y.v[i];
113: }
114:
115: int fe25519_iszero(const fe25519 *x)
116: {
117: int i;
118: int r;
119: fe25519 t = *x;
120: fe25519_freeze(&t);
121: r = equal(t.v[0],0);
122: for(i=1;i<32;i++)
123: r &= equal(t.v[i],0);
124: return r;
125: }
126:
127: int fe25519_iseq_vartime(const fe25519 *x, const fe25519 *y)
128: {
129: int i;
130: fe25519 t1 = *x;
131: fe25519 t2 = *y;
132: fe25519_freeze(&t1);
133: fe25519_freeze(&t2);
134: for(i=0;i<32;i++)
135: if(t1.v[i] != t2.v[i]) return 0;
136: return 1;
137: }
138:
139: void fe25519_cmov(fe25519 *r, const fe25519 *x, unsigned char b)
140: {
141: int i;
142: crypto_uint32 mask = b;
143: mask = -mask;
144: for(i=0;i<32;i++) r->v[i] ^= mask & (x->v[i] ^ r->v[i]);
145: }
146:
147: unsigned char fe25519_getparity(const fe25519 *x)
148: {
149: fe25519 t = *x;
150: fe25519_freeze(&t);
151: return t.v[0] & 1;
152: }
153:
154: void fe25519_setone(fe25519 *r)
155: {
156: int i;
157: r->v[0] = 1;
158: for(i=1;i<32;i++) r->v[i]=0;
159: }
160:
161: void fe25519_setzero(fe25519 *r)
162: {
163: int i;
164: for(i=0;i<32;i++) r->v[i]=0;
165: }
166:
167: void fe25519_neg(fe25519 *r, const fe25519 *x)
168: {
169: fe25519 t;
170: int i;
171: for(i=0;i<32;i++) t.v[i]=x->v[i];
172: fe25519_setzero(r);
173: fe25519_sub(r, r, &t);
174: }
175:
176: void fe25519_add(fe25519 *r, const fe25519 *x, const fe25519 *y)
177: {
178: int i;
179: for(i=0;i<32;i++) r->v[i] = x->v[i] + y->v[i];
180: reduce_add_sub(r);
181: }
182:
183: void fe25519_sub(fe25519 *r, const fe25519 *x, const fe25519 *y)
184: {
185: int i;
186: crypto_uint32 t[32];
187: t[0] = x->v[0] + 0x1da;
188: t[31] = x->v[31] + 0xfe;
189: for(i=1;i<31;i++) t[i] = x->v[i] + 0x1fe;
190: for(i=0;i<32;i++) r->v[i] = t[i] - y->v[i];
191: reduce_add_sub(r);
192: }
193:
194: void fe25519_mul(fe25519 *r, const fe25519 *x, const fe25519 *y)
195: {
196: int i,j;
197: crypto_uint32 t[63];
198: for(i=0;i<63;i++)t[i] = 0;
199:
200: for(i=0;i<32;i++)
201: for(j=0;j<32;j++)
202: t[i+j] += x->v[i] * y->v[j];
203:
204: for(i=32;i<63;i++)
205: r->v[i-32] = t[i-32] + times38(t[i]);
206: r->v[31] = t[31]; /* result now in r[0]...r[31] */
207:
208: reduce_mul(r);
209: }
210:
211: void fe25519_square(fe25519 *r, const fe25519 *x)
212: {
213: fe25519_mul(r, x, x);
214: }
215:
216: void fe25519_invert(fe25519 *r, const fe25519 *x)
217: {
218: fe25519 z2;
219: fe25519 z9;
220: fe25519 z11;
221: fe25519 z2_5_0;
222: fe25519 z2_10_0;
223: fe25519 z2_20_0;
224: fe25519 z2_50_0;
225: fe25519 z2_100_0;
226: fe25519 t0;
227: fe25519 t1;
228: int i;
229:
230: /* 2 */ fe25519_square(&z2,x);
231: /* 4 */ fe25519_square(&t1,&z2);
232: /* 8 */ fe25519_square(&t0,&t1);
233: /* 9 */ fe25519_mul(&z9,&t0,x);
234: /* 11 */ fe25519_mul(&z11,&z9,&z2);
235: /* 22 */ fe25519_square(&t0,&z11);
236: /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t0,&z9);
237:
238: /* 2^6 - 2^1 */ fe25519_square(&t0,&z2_5_0);
239: /* 2^7 - 2^2 */ fe25519_square(&t1,&t0);
240: /* 2^8 - 2^3 */ fe25519_square(&t0,&t1);
241: /* 2^9 - 2^4 */ fe25519_square(&t1,&t0);
242: /* 2^10 - 2^5 */ fe25519_square(&t0,&t1);
243: /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t0,&z2_5_0);
244:
245: /* 2^11 - 2^1 */ fe25519_square(&t0,&z2_10_0);
246: /* 2^12 - 2^2 */ fe25519_square(&t1,&t0);
247: /* 2^20 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
248: /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t1,&z2_10_0);
249:
250: /* 2^21 - 2^1 */ fe25519_square(&t0,&z2_20_0);
251: /* 2^22 - 2^2 */ fe25519_square(&t1,&t0);
252: /* 2^40 - 2^20 */ for (i = 2;i < 20;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
253: /* 2^40 - 2^0 */ fe25519_mul(&t0,&t1,&z2_20_0);
254:
255: /* 2^41 - 2^1 */ fe25519_square(&t1,&t0);
256: /* 2^42 - 2^2 */ fe25519_square(&t0,&t1);
257: /* 2^50 - 2^10 */ for (i = 2;i < 10;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
258: /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t0,&z2_10_0);
259:
260: /* 2^51 - 2^1 */ fe25519_square(&t0,&z2_50_0);
261: /* 2^52 - 2^2 */ fe25519_square(&t1,&t0);
262: /* 2^100 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
263: /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t1,&z2_50_0);
264:
265: /* 2^101 - 2^1 */ fe25519_square(&t1,&z2_100_0);
266: /* 2^102 - 2^2 */ fe25519_square(&t0,&t1);
267: /* 2^200 - 2^100 */ for (i = 2;i < 100;i += 2) { fe25519_square(&t1,&t0); fe25519_square(&t0,&t1); }
268: /* 2^200 - 2^0 */ fe25519_mul(&t1,&t0,&z2_100_0);
269:
270: /* 2^201 - 2^1 */ fe25519_square(&t0,&t1);
271: /* 2^202 - 2^2 */ fe25519_square(&t1,&t0);
272: /* 2^250 - 2^50 */ for (i = 2;i < 50;i += 2) { fe25519_square(&t0,&t1); fe25519_square(&t1,&t0); }
273: /* 2^250 - 2^0 */ fe25519_mul(&t0,&t1,&z2_50_0);
274:
275: /* 2^251 - 2^1 */ fe25519_square(&t1,&t0);
276: /* 2^252 - 2^2 */ fe25519_square(&t0,&t1);
277: /* 2^253 - 2^3 */ fe25519_square(&t1,&t0);
278: /* 2^254 - 2^4 */ fe25519_square(&t0,&t1);
279: /* 2^255 - 2^5 */ fe25519_square(&t1,&t0);
280: /* 2^255 - 21 */ fe25519_mul(r,&t1,&z11);
281: }
282:
283: void fe25519_pow2523(fe25519 *r, const fe25519 *x)
284: {
285: fe25519 z2;
286: fe25519 z9;
287: fe25519 z11;
288: fe25519 z2_5_0;
289: fe25519 z2_10_0;
290: fe25519 z2_20_0;
291: fe25519 z2_50_0;
292: fe25519 z2_100_0;
293: fe25519 t;
294: int i;
295:
296: /* 2 */ fe25519_square(&z2,x);
297: /* 4 */ fe25519_square(&t,&z2);
298: /* 8 */ fe25519_square(&t,&t);
299: /* 9 */ fe25519_mul(&z9,&t,x);
300: /* 11 */ fe25519_mul(&z11,&z9,&z2);
301: /* 22 */ fe25519_square(&t,&z11);
302: /* 2^5 - 2^0 = 31 */ fe25519_mul(&z2_5_0,&t,&z9);
303:
304: /* 2^6 - 2^1 */ fe25519_square(&t,&z2_5_0);
305: /* 2^10 - 2^5 */ for (i = 1;i < 5;i++) { fe25519_square(&t,&t); }
306: /* 2^10 - 2^0 */ fe25519_mul(&z2_10_0,&t,&z2_5_0);
307:
308: /* 2^11 - 2^1 */ fe25519_square(&t,&z2_10_0);
309: /* 2^20 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
310: /* 2^20 - 2^0 */ fe25519_mul(&z2_20_0,&t,&z2_10_0);
311:
312: /* 2^21 - 2^1 */ fe25519_square(&t,&z2_20_0);
313: /* 2^40 - 2^20 */ for (i = 1;i < 20;i++) { fe25519_square(&t,&t); }
314: /* 2^40 - 2^0 */ fe25519_mul(&t,&t,&z2_20_0);
315:
316: /* 2^41 - 2^1 */ fe25519_square(&t,&t);
317: /* 2^50 - 2^10 */ for (i = 1;i < 10;i++) { fe25519_square(&t,&t); }
318: /* 2^50 - 2^0 */ fe25519_mul(&z2_50_0,&t,&z2_10_0);
319:
320: /* 2^51 - 2^1 */ fe25519_square(&t,&z2_50_0);
321: /* 2^100 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
322: /* 2^100 - 2^0 */ fe25519_mul(&z2_100_0,&t,&z2_50_0);
323:
324: /* 2^101 - 2^1 */ fe25519_square(&t,&z2_100_0);
325: /* 2^200 - 2^100 */ for (i = 1;i < 100;i++) { fe25519_square(&t,&t); }
326: /* 2^200 - 2^0 */ fe25519_mul(&t,&t,&z2_100_0);
327:
328: /* 2^201 - 2^1 */ fe25519_square(&t,&t);
329: /* 2^250 - 2^50 */ for (i = 1;i < 50;i++) { fe25519_square(&t,&t); }
330: /* 2^250 - 2^0 */ fe25519_mul(&t,&t,&z2_50_0);
331:
332: /* 2^251 - 2^1 */ fe25519_square(&t,&t);
333: /* 2^252 - 2^2 */ fe25519_square(&t,&t);
334: /* 2^252 - 3 */ fe25519_mul(r,&t,x);
335: }