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