summaryrefslogtreecommitdiff
path: root/fe25519.c
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2013-12-07 11:24:01 +1100
committerDamien Miller <djm@mindrot.org>2013-12-07 11:24:01 +1100
commit5be9d9e3cbd9c66f24745d25bf2e809c1d158ee0 (patch)
treed2086d37436014ea44f0f024396a1a8638640b00 /fe25519.c
parentbcd00abd8451f36142ae2ee10cc657202149201e (diff)
- markus@cvs.openbsd.org 2013/12/06 13:39:49
[authfd.c authfile.c key.c key.h myproposal.h pathnames.h readconf.c] [servconf.c ssh-agent.c ssh-keygen.c ssh-keyscan.1 ssh-keyscan.c] [ssh-keysign.c ssh.c ssh_config.5 sshd.8 sshd.c verify.c ssh-ed25519.c] [sc25519.h sc25519.c hash.c ge25519_base.data ge25519.h ge25519.c] [fe25519.h fe25519.c ed25519.c crypto_api.h blocks.c] support ed25519 keys (hostkeys and user identities) using the public domain ed25519 reference code from SUPERCOP, see http://ed25519.cr.yp.to/software.html feedback, help & ok djm@
Diffstat (limited to 'fe25519.c')
-rw-r--r--fe25519.c331
1 files changed, 331 insertions, 0 deletions
diff --git a/fe25519.c b/fe25519.c
new file mode 100644
index 000000000..d2efa5051
--- /dev/null
+++ b/fe25519.c
@@ -0,0 +1,331 @@
1/* $OpenBSD: */
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
10static 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
18static 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
27static crypto_uint32 times19(crypto_uint32 a)
28{
29 return (a << 4) + (a << 1) + a;
30}
31
32static crypto_uint32 times38(crypto_uint32 a)
33{
34 return (a << 5) + (a << 2) + (a << 1);
35}
36
37static 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
57static 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 */
78void 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
94void 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 */
102void 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
111int 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
123int 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
135void 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
143unsigned char fe25519_getparity(const fe25519 *x)
144{
145 fe25519 t = *x;
146 fe25519_freeze(&t);
147 return t.v[0] & 1;
148}
149
150void 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
157void fe25519_setzero(fe25519 *r)
158{
159 int i;
160 for(i=0;i<32;i++) r->v[i]=0;
161}
162
163void 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
172void 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
179void 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
190void 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
207void fe25519_square(fe25519 *r, const fe25519 *x)
208{
209 fe25519_mul(r, x, x);
210}
211
212void 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
279void 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}