comparison curve25519.c @ 1659:d32bcb5c557d

Add Ed25519 support (#91) * Add support for Ed25519 as a public key type Ed25519 is a elliptic curve signature scheme that offers better security than ECDSA and DSA and good performance. It may be used for both user and host keys. OpenSSH key import and fuzzer are not supported yet. Initially inspired by Peter Szabo. * Add curve25519 and ed25519 fuzzers * Add import and export of Ed25519 keys
author Vladislav Grishenko <themiron@users.noreply.github.com>
date Wed, 11 Mar 2020 21:09:45 +0500
parents
children 41a0ff8d5a89
comparison
equal deleted inserted replaced
1658:7402218141d4 1659:d32bcb5c557d
1 /*
2 * Dropbear - a SSH2 server
3 *
4 * Copyright (c) 2002,2003 Matt Johnston
5 * All rights reserved.
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE. */
24
25 #include "includes.h"
26 #include "dbrandom.h"
27 #include "curve25519.h"
28
29 #if DROPBEAR_CURVE25519 || DROPBEAR_ED25519
30
31 /* Modified TweetNaCl version 20140427, a self-contained public-domain C library.
32 * https://tweetnacl.cr.yp.to/ */
33
34 #define FOR(i,n) for (i = 0;i < n;++i)
35 #define sv static void
36
37 typedef unsigned char u8;
38 typedef unsigned long u32;
39 typedef unsigned long long u64;
40 typedef long long i64;
41 typedef i64 gf[16];
42
43 #if DROPBEAR_CURVE25519
44 static const gf
45 _121665 = {0xDB41,1};
46 #endif /* DROPBEAR_CURVE25519 */
47 #if DROPBEAR_ED25519
48 static const gf
49 gf0,
50 gf1 = {1},
51 D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130, 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
52 X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c, 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
53 Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666};
54 #if DROPBEAR_SIGNKEY_VERIFY
55 static const gf
56 D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
57 I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
58 #endif /* DROPBEAR_SIGNKEY_VERIFY */
59 #endif /* DROPBEAR_ED25519 */
60
61 #if DROPBEAR_ED25519
62 #if DROPBEAR_SIGNKEY_VERIFY
63 static int vn(const u8 *x,const u8 *y,u32 n)
64 {
65 u32 i,d = 0;
66 FOR(i,n) d |= x[i]^y[i];
67 return (1 & ((d - 1) >> 8)) - 1;
68 }
69
70 static int crypto_verify_32(const u8 *x,const u8 *y)
71 {
72 return vn(x,y,32);
73 }
74 #endif /* DROPBEAR_SIGNKEY_VERIFY */
75
76 sv set25519(gf r, const gf a)
77 {
78 int i;
79 FOR(i,16) r[i]=a[i];
80 }
81 #endif /* DROPBEAR_ED25519 */
82
83 sv car25519(gf o)
84 {
85 int i;
86 i64 c;
87 FOR(i,16) {
88 o[i]+=(1LL<<16);
89 c=o[i]>>16;
90 o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
91 o[i]-=c<<16;
92 }
93 }
94
95 sv sel25519(gf p,gf q,int b)
96 {
97 i64 t,i,c=~(b-1);
98 FOR(i,16) {
99 t= c&(p[i]^q[i]);
100 p[i]^=t;
101 q[i]^=t;
102 }
103 }
104
105 sv pack25519(u8 *o,const gf n)
106 {
107 int i,j,b;
108 gf m,t;
109 FOR(i,16) t[i]=n[i];
110 car25519(t);
111 car25519(t);
112 car25519(t);
113 FOR(j,2) {
114 m[0]=t[0]-0xffed;
115 for(i=1;i<15;i++) {
116 m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
117 m[i-1]&=0xffff;
118 }
119 m[15]=t[15]-0x7fff-((m[14]>>16)&1);
120 b=(m[15]>>16)&1;
121 m[14]&=0xffff;
122 sel25519(t,m,1-b);
123 }
124 FOR(i,16) {
125 o[2*i]=t[i]&0xff;
126 o[2*i+1]=t[i]>>8;
127 }
128 }
129
130 #if DROPBEAR_ED25519
131 #if DROPBEAR_SIGNKEY_VERIFY
132 static int neq25519(const gf a, const gf b)
133 {
134 u8 c[32],d[32];
135 pack25519(c,a);
136 pack25519(d,b);
137 return crypto_verify_32(c,d);
138 }
139 #endif /* DROPBEAR_SIGNKEY_VERIFY */
140
141 static u8 par25519(const gf a)
142 {
143 u8 d[32];
144 pack25519(d,a);
145 return d[0]&1;
146 }
147 #endif /* DROPBEAR_ED25519 */
148
149 sv unpack25519(gf o, const u8 *n)
150 {
151 int i;
152 FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
153 o[15]&=0x7fff;
154 }
155
156 sv A(gf o,const gf a,const gf b)
157 {
158 int i;
159 FOR(i,16) o[i]=a[i]+b[i];
160 }
161
162 sv Z(gf o,const gf a,const gf b)
163 {
164 int i;
165 FOR(i,16) o[i]=a[i]-b[i];
166 }
167
168 sv M(gf o,const gf a,const gf b)
169 {
170 i64 i,j,t[31];
171 FOR(i,31) t[i]=0;
172 FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
173 FOR(i,15) t[i]+=38*t[i+16];
174 FOR(i,16) o[i]=t[i];
175 car25519(o);
176 car25519(o);
177 }
178
179 sv S(gf o,const gf a)
180 {
181 M(o,a,a);
182 }
183
184 sv inv25519(gf o,const gf i)
185 {
186 gf c;
187 int a;
188 FOR(a,16) c[a]=i[a];
189 for(a=253;a>=0;a--) {
190 S(c,c);
191 if(a!=2&&a!=4) M(c,c,i);
192 }
193 FOR(a,16) o[a]=c[a];
194 }
195
196 #if DROPBEAR_ED25519 && DROPBEAR_SIGNKEY_VERIFY
197 sv pow2523(gf o,const gf i)
198 {
199 gf c;
200 int a;
201 FOR(a,16) c[a]=i[a];
202 for(a=250;a>=0;a--) {
203 S(c,c);
204 if(a!=1) M(c,c,i);
205 }
206 FOR(a,16) o[a]=c[a];
207 }
208 #endif /* DROPBEAR_ED25519 && DROPBEAR_SIGNKEY_VERIFY */
209
210 #if DROPBEAR_CURVE25519
211 int dropbear_curve25519_scalarmult(u8 *q,const u8 *n,const u8 *p)
212 {
213 u8 z[32];
214 i64 x[80],r,i;
215 gf a,b,c,d,e,f;
216 FOR(i,31) z[i]=n[i];
217 z[31]=(n[31]&127)|64;
218 z[0]&=248;
219 unpack25519(x,p);
220 FOR(i,16) {
221 b[i]=x[i];
222 d[i]=a[i]=c[i]=0;
223 }
224 a[0]=d[0]=1;
225 for(i=254;i>=0;--i) {
226 r=(z[i>>3]>>(i&7))&1;
227 sel25519(a,b,r);
228 sel25519(c,d,r);
229 A(e,a,c);
230 Z(a,a,c);
231 A(c,b,d);
232 Z(b,b,d);
233 S(d,e);
234 S(f,a);
235 M(a,c,a);
236 M(c,b,e);
237 A(e,a,c);
238 Z(a,a,c);
239 S(b,a);
240 Z(c,d,f);
241 M(a,c,_121665);
242 A(a,a,d);
243 M(c,c,a);
244 M(a,d,f);
245 M(d,b,x);
246 S(b,e);
247 sel25519(a,b,r);
248 sel25519(c,d,r);
249 }
250 FOR(i,16) {
251 x[i+16]=a[i];
252 x[i+32]=c[i];
253 x[i+48]=b[i];
254 x[i+64]=d[i];
255 }
256 inv25519(x+32,x+32);
257 M(x+16,x+16,x+32);
258 pack25519(q,x+16);
259 return 0;
260 }
261 #endif /* DROPBEAR_CURVE25519 */
262
263 #if DROPBEAR_ED25519
264 static int crypto_hash(u8 *out,const u8 *m,u64 n)
265 {
266 hash_state hs;
267
268 sha512_init(&hs);
269 sha512_process(&hs, m, n);
270 return sha512_done(&hs, out);
271 }
272
273 sv add(gf p[4],gf q[4])
274 {
275 gf a,b,c,d,t,e,f,g,h;
276
277 Z(a, p[1], p[0]);
278 Z(t, q[1], q[0]);
279 M(a, a, t);
280 A(b, p[0], p[1]);
281 A(t, q[0], q[1]);
282 M(b, b, t);
283 M(c, p[3], q[3]);
284 M(c, c, D2);
285 M(d, p[2], q[2]);
286 A(d, d, d);
287 Z(e, b, a);
288 Z(f, d, c);
289 A(g, d, c);
290 A(h, b, a);
291
292 M(p[0], e, f);
293 M(p[1], h, g);
294 M(p[2], g, f);
295 M(p[3], e, h);
296 }
297
298 sv cswap(gf p[4],gf q[4],u8 b)
299 {
300 int i;
301 FOR(i,4)
302 sel25519(p[i],q[i],b);
303 }
304
305 sv pack(u8 *r,gf p[4])
306 {
307 gf tx, ty, zi;
308 inv25519(zi, p[2]);
309 M(tx, p[0], zi);
310 M(ty, p[1], zi);
311 pack25519(r, ty);
312 r[31] ^= par25519(tx) << 7;
313 }
314
315 sv scalarmult(gf p[4],gf q[4],const u8 *s)
316 {
317 int i;
318 set25519(p[0],gf0);
319 set25519(p[1],gf1);
320 set25519(p[2],gf1);
321 set25519(p[3],gf0);
322 for (i = 255;i >= 0;--i) {
323 u8 b = (s[i/8]>>(i&7))&1;
324 cswap(p,q,b);
325 add(q,p);
326 add(p,p);
327 cswap(p,q,b);
328 }
329 }
330
331 sv scalarbase(gf p[4],const u8 *s)
332 {
333 gf q[4];
334 set25519(q[0],X);
335 set25519(q[1],Y);
336 set25519(q[2],gf1);
337 M(q[3],X,Y);
338 scalarmult(p,q,s);
339 }
340
341 int dropbear_ed25519_make_key(u8 *pk,u8 *sk)
342 {
343 u8 d[64];
344 gf p[4];
345
346 genrandom(sk, 32);
347
348 crypto_hash(d, sk, 32);
349 d[0] &= 248;
350 d[31] &= 127;
351 d[31] |= 64;
352
353 scalarbase(p,d);
354 pack(pk,p);
355
356 return 0;
357 }
358
359 static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6, 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0x10};
360
361 sv modL(u8 *r,i64 x[64])
362 {
363 i64 carry,i,j;
364 for (i = 63;i >= 32;--i) {
365 carry = 0;
366 for (j = i - 32;j < i - 12;++j) {
367 x[j] += carry - 16 * x[i] * L[j - (i - 32)];
368 carry = (x[j] + 128) >> 8;
369 x[j] -= carry << 8;
370 }
371 x[j] += carry;
372 x[i] = 0;
373 }
374 carry = 0;
375 FOR(j,32) {
376 x[j] += carry - (x[31] >> 4) * L[j];
377 carry = x[j] >> 8;
378 x[j] &= 255;
379 }
380 FOR(j,32) x[j] -= carry * L[j];
381 FOR(i,32) {
382 x[i+1] += x[i] >> 8;
383 r[i] = x[i] & 255;
384 }
385 }
386
387 sv reduce(u8 *r)
388 {
389 i64 x[64],i;
390 FOR(i,64) x[i] = (u64) r[i];
391 FOR(i,64) r[i] = 0;
392 modL(r,x);
393 }
394
395 int dropbear_ed25519_sign(const u8 *m,u32 mlen,u8 *s,u32 *slen,const u8 *sk, const u8 *pk)
396 {
397 hash_state hs;
398 u8 d[64],h[64],r[64];
399 i64 x[64];
400 gf p[4];
401 u32 i,j;
402
403 crypto_hash(d, sk, 32);
404 d[0] &= 248;
405 d[31] &= 127;
406 d[31] |= 64;
407
408 *slen = 64;
409
410 sha512_init(&hs);
411 sha512_process(&hs,d + 32,32);
412 sha512_process(&hs,m,mlen);
413 sha512_done(&hs,r);
414 reduce(r);
415 scalarbase(p,r);
416 pack(s,p);
417
418 sha512_init(&hs);
419 sha512_process(&hs,s,32);
420 sha512_process(&hs,pk,32);
421 sha512_process(&hs,m,mlen);
422 sha512_done(&hs,h);
423 reduce(h);
424
425 FOR(i,64) x[i] = 0;
426 FOR(i,32) x[i] = (u64) r[i];
427 FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
428 modL(s + 32,x);
429
430 return 0;
431 }
432
433 #if DROPBEAR_SIGNKEY_VERIFY
434 static int unpackneg(gf r[4],const u8 p[32])
435 {
436 gf t, chk, num, den, den2, den4, den6;
437 set25519(r[2],gf1);
438 unpack25519(r[1],p);
439 S(num,r[1]);
440 M(den,num,D);
441 Z(num,num,r[2]);
442 A(den,r[2],den);
443
444 S(den2,den);
445 S(den4,den2);
446 M(den6,den4,den2);
447 M(t,den6,num);
448 M(t,t,den);
449
450 pow2523(t,t);
451 M(t,t,num);
452 M(t,t,den);
453 M(t,t,den);
454 M(r[0],t,den);
455
456 S(chk,r[0]);
457 M(chk,chk,den);
458 if (neq25519(chk, num)) M(r[0],r[0],I);
459
460 S(chk,r[0]);
461 M(chk,chk,den);
462 if (neq25519(chk, num)) return -1;
463
464 if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
465
466 M(r[3],r[0],r[1]);
467 return 0;
468 }
469
470 int dropbear_ed25519_verify(const u8 *m,u32 mlen,const u8 *s,u32 slen,const u8 *pk)
471 {
472 hash_state hs;
473 u8 t[32],h[64];
474 gf p[4],q[4];
475
476 if (slen < 64) return -1;
477
478 if (unpackneg(q,pk)) return -1;
479
480 sha512_init(&hs);
481 sha512_process(&hs,s,32);
482 sha512_process(&hs,pk,32);
483 sha512_process(&hs,m,mlen);
484 sha512_done(&hs,h);
485
486 reduce(h);
487 scalarmult(p,q,h);
488
489 scalarbase(q,s + 32);
490 add(p,q);
491 pack(t,p);
492
493 if (crypto_verify_32(s, t))
494 return -1;
495
496 return 0;
497 }
498 #endif /* DROPBEAR_SIGNKEY_VERIFY */
499
500 #endif /* DROPBEAR_ED25519 */
501
502 #endif /* DROPBEAR_CURVE25519 || DROPBEAR_ED25519 */