aboutsummaryrefslogtreecommitdiff
path: root/src/util/tweetnacl-gnunet.c
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2019-11-26 18:26:54 +0100
committerFlorian Dold <florian.dold@gmail.com>2019-11-26 18:29:56 +0100
commitbc340979c19807c76baedc7da98778178b9bcc4a (patch)
treec7e0e017a441ea5bc13d9e165417c5156e390c9b /src/util/tweetnacl-gnunet.c
parentc36c37830eb909fe73357383136cf8b2405d9633 (diff)
downloadgnunet-bc340979c19807c76baedc7da98778178b9bcc4a.tar.gz
gnunet-bc340979c19807c76baedc7da98778178b9bcc4a.zip
use Curve25519 for ECDH and tweetnacl where we can
This leads to some performance improvements and makes it easier to write software that interoperates with GNUnet / GNU Taler. It also avoids using the rather inconvenient libgcrypt APIs. We still need to keep libgcrypt though, as we need it for RSA, ECDSA and some other primitives. This change is still behind a #define NEW_CRYPTO, as it is a breaking change for both EdDSA (removing the superfluous additional hash) and for ECDHE (using Curve25519 instead of Ed25519).
Diffstat (limited to 'src/util/tweetnacl-gnunet.c')
-rw-r--r--src/util/tweetnacl-gnunet.c530
1 files changed, 530 insertions, 0 deletions
diff --git a/src/util/tweetnacl-gnunet.c b/src/util/tweetnacl-gnunet.c
new file mode 100644
index 000000000..b0d87c2fe
--- /dev/null
+++ b/src/util/tweetnacl-gnunet.c
@@ -0,0 +1,530 @@
1/*
2 This file has been placed in the public domain.
3
4 Based on TweetNaCl version 20140427
5
6 Originally obtained from:
7 https://tweetnacl.cr.yp.to/20140427/tweetnacl.h
8*/
9
10#include "platform.h"
11#include "gnunet_crypto_lib.h"
12#include "tweetnacl-gnunet.h"
13#define FOR(i,n) for (i = 0; i < n; ++i)
14#define sv static void
15
16typedef uint8_t u8;
17typedef uint32_t u32;
18typedef uint64_t u64;
19typedef int64_t i64;
20typedef i64 gf[16];
21
22static void randombytes (u8 *data,u64 len)
23{
24 GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, data, len);
25}
26
27static const u8 _9[32] = {9};
28static const gf
29 gf0,
30 gf1 = {1},
31 _121665 = {0xDB41,1},
32 D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898,
33 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
34 D2 = {0xf159, 0x26b2, 0x9b94, 0xebd6, 0xb156, 0x8283, 0x149a, 0x00e0, 0xd130,
35 0xeef3, 0x80f2, 0x198e, 0xfce7, 0x56df, 0xd9dc, 0x2406},
36 X = {0xd51a, 0x8f25, 0x2d60, 0xc956, 0xa7b2, 0x9525, 0xc760, 0x692c, 0xdc5c,
37 0xfdd6, 0xe231, 0xc0a4, 0x53fe, 0xcd6e, 0x36d3, 0x2169},
38 Y = {0x6658, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666,
39 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666, 0x6666},
40 I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7,
41 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
42
43static int vn (const u8 *x,const u8 *y,int n)
44{
45 u32 i,d = 0;
46 FOR (i,n) d |= x[i] ^ y[i];
47 return (1 & ((d - 1) >> 8)) - 1;
48}
49
50int crypto_verify_16 (const u8 *x,const u8 *y)
51{
52 return vn (x,y,16);
53}
54
55int crypto_verify_32 (const u8 *x,const u8 *y)
56{
57 return vn (x,y,32);
58}
59
60sv set25519 (gf r, const gf a)
61{
62 int i;
63 FOR (i,16) r[i] = a[i];
64}
65
66sv car25519 (gf o)
67{
68 int i;
69 i64 c;
70 FOR (i,16) {
71 o[i] += (1LL << 16);
72 c = o[i] >> 16;
73 o[(i + 1) * (i<15)] += c - 1 + 37 * (c - 1) * (i==15);
74 o[i] -= c << 16;
75 }
76}
77
78sv sel25519 (gf p,gf q,int b)
79{
80 i64 t,i,c = ~(b - 1);
81 FOR (i,16) {
82 t = c & (p[i] ^ q[i]);
83 p[i] ^= t;
84 q[i] ^= t;
85 }
86}
87
88sv pack25519 (u8 *o,const gf n)
89{
90 int i,j,b;
91 gf m,t;
92 FOR (i,16) t[i] = n[i];
93 car25519 (t);
94 car25519 (t);
95 car25519 (t);
96 FOR (j,2) {
97 m[0] = t[0] - 0xffed;
98 for (i = 1; i<15; i++) {
99 m[i] = t[i] - 0xffff - ((m[i - 1] >> 16) & 1);
100 m[i - 1] &= 0xffff;
101 }
102 m[15] = t[15] - 0x7fff - ((m[14] >> 16) & 1);
103 b = (m[15] >> 16) & 1;
104 m[14] &= 0xffff;
105 sel25519 (t,m,1 - b);
106 }
107 FOR (i,16) {
108 o[2 * i] = t[i] & 0xff;
109 o[2 * i + 1] = t[i] >> 8;
110 }
111}
112
113static int neq25519 (const gf a, const gf b)
114{
115 u8 c[32],d[32];
116 pack25519 (c,a);
117 pack25519 (d,b);
118 return crypto_verify_32 (c,d);
119}
120
121static u8 par25519 (const gf a)
122{
123 u8 d[32];
124 pack25519 (d,a);
125 return d[0] & 1;
126}
127
128sv unpack25519 (gf o, const u8 *n)
129{
130 int i;
131 FOR (i,16) o[i] = n[2 * i] + ((i64) n[2 * i + 1] << 8);
132 o[15] &= 0x7fff;
133}
134
135sv A (gf o,const gf a,const gf b)
136{
137 int i;
138 FOR (i,16) o[i] = a[i] + b[i];
139}
140
141sv Z (gf o,const gf a,const gf b)
142{
143 int i;
144 FOR (i,16) o[i] = a[i] - b[i];
145}
146
147sv M (gf o,const gf a,const gf b)
148{
149 i64 i,j,t[31];
150 FOR (i,31) t[i] = 0;
151 FOR (i,16) FOR (j,16) t[i + j] += a[i] * b[j];
152 FOR (i,15) t[i] += 38 * t[i + 16];
153 FOR (i,16) o[i] = t[i];
154 car25519 (o);
155 car25519 (o);
156}
157
158sv S (gf o,const gf a)
159{
160 M (o,a,a);
161}
162
163sv inv25519 (gf o,const gf i)
164{
165 gf c;
166 int a;
167 FOR (a,16) c[a] = i[a];
168 for (a = 253; a>=0; a--) {
169 S (c,c);
170 if ((a!=2)&&(a!=4))
171 M (c,c,i);
172 }
173 FOR (a,16) o[a] = c[a];
174}
175
176sv pow2523 (gf o,const gf i)
177{
178 gf c;
179 int a;
180 FOR (a,16) c[a] = i[a];
181 for (a = 250; a>=0; a--) {
182 S (c,c);
183 if (a!=1)
184 M (c,c,i);
185 }
186 FOR (a,16) o[a] = c[a];
187}
188
189int crypto_scalarmult (u8 *q,const u8 *n,const u8 *p)
190{
191 u8 z[32];
192 i64 x[80],r,i;
193 gf a,b,c,d,e,f;
194 FOR (i,31) z[i] = n[i];
195 z[31] = (n[31] & 127) | 64;
196 z[0] &= 248;
197 unpack25519 (x,p);
198 FOR (i,16) {
199 b[i] = x[i];
200 d[i] = a[i] = c[i] = 0;
201 }
202 a[0] = d[0] = 1;
203 for (i = 254; i>=0; --i) {
204 r = (z[i >> 3] >> (i & 7)) & 1;
205 sel25519 (a,b,r);
206 sel25519 (c,d,r);
207 A (e,a,c);
208 Z (a,a,c);
209 A (c,b,d);
210 Z (b,b,d);
211 S (d,e);
212 S (f,a);
213 M (a,c,a);
214 M (c,b,e);
215 A (e,a,c);
216 Z (a,a,c);
217 S (b,a);
218 Z (c,d,f);
219 M (a,c,_121665);
220 A (a,a,d);
221 M (c,c,a);
222 M (a,d,f);
223 M (d,b,x);
224 S (b,e);
225 sel25519 (a,b,r);
226 sel25519 (c,d,r);
227 }
228 FOR (i,16) {
229 x[i + 16] = a[i];
230 x[i + 32] = c[i];
231 x[i + 48] = b[i];
232 x[i + 64] = d[i];
233 }
234 inv25519 (x + 32,x + 32);
235 M (x + 16,x + 16,x + 32);
236 pack25519 (q,x + 16);
237 return 0;
238}
239
240int crypto_scalarmult_base (u8 *q,const u8 *n)
241{
242 return crypto_scalarmult (q,n,_9);
243}
244
245int crypto_box_keypair (u8 *y,u8 *x)
246{
247 randombytes (x,32);
248 return crypto_scalarmult_base (y,x);
249}
250
251int crypto_hash (u8 *out,const u8 *m,u64 n)
252{
253 struct GNUNET_HashCode *hc = (void *) out;
254 GNUNET_CRYPTO_hash (m, n, hc);
255 return 0;
256}
257
258sv add (gf p[4],gf q[4])
259{
260 gf a,b,c,d,t,e,f,g,h;
261
262 Z (a, p[1], p[0]);
263 Z (t, q[1], q[0]);
264 M (a, a, t);
265 A (b, p[0], p[1]);
266 A (t, q[0], q[1]);
267 M (b, b, t);
268 M (c, p[3], q[3]);
269 M (c, c, D2);
270 M (d, p[2], q[2]);
271 A (d, d, d);
272 Z (e, b, a);
273 Z (f, d, c);
274 A (g, d, c);
275 A (h, b, a);
276
277 M (p[0], e, f);
278 M (p[1], h, g);
279 M (p[2], g, f);
280 M (p[3], e, h);
281}
282
283sv cswap (gf p[4],gf q[4],u8 b)
284{
285 int i;
286 FOR (i,4)
287 sel25519 (p[i],q[i],b);
288}
289
290sv pack (u8 *r,gf p[4])
291{
292 gf tx, ty, zi;
293 inv25519 (zi, p[2]);
294 M (tx, p[0], zi);
295 M (ty, p[1], zi);
296 pack25519 (r, ty);
297 r[31] ^= par25519 (tx) << 7;
298}
299
300sv scalarmult (gf p[4],gf q[4],const u8 *s)
301{
302 int i;
303 set25519 (p[0],gf0);
304 set25519 (p[1],gf1);
305 set25519 (p[2],gf1);
306 set25519 (p[3],gf0);
307 for (i = 255; i >= 0; --i) {
308 u8 b = (s[i / 8] >> (i & 7)) & 1;
309 cswap (p,q,b);
310 add (q,p);
311 add (p,p);
312 cswap (p,q,b);
313 }
314}
315
316sv scalarbase (gf p[4],const u8 *s)
317{
318 gf q[4];
319 set25519 (q[0],X);
320 set25519 (q[1],Y);
321 set25519 (q[2],gf1);
322 M (q[3],X,Y);
323 scalarmult (p,q,s);
324}
325
326static const u64 L[32] = {0xed, 0xd3, 0xf5, 0x5c, 0x1a, 0x63, 0x12, 0x58, 0xd6,
327 0x9c, 0xf7, 0xa2, 0xde, 0xf9, 0xde, 0x14, 0, 0, 0, 0,
328 0, 0, 0, 0, 0, 0, 0, 0,
329 0, 0, 0, 0x10};
330
331sv modL (u8 *r,i64 x[64])
332{
333 i64 carry,i,j;
334 for (i = 63; i >= 32; --i) {
335 carry = 0;
336 for (j = i - 32; j < i - 12; ++j) {
337 x[j] += carry - 16 * x[i] * L[j - (i - 32)];
338 carry = (x[j] + 128) >> 8;
339 x[j] -= carry << 8;
340 }
341 x[j] += carry;
342 x[i] = 0;
343 }
344 carry = 0;
345 FOR (j,32) {
346 x[j] += carry - (x[31] >> 4) * L[j];
347 carry = x[j] >> 8;
348 x[j] &= 255;
349 }
350 FOR (j,32) x[j] -= carry * L[j];
351 FOR (i,32) {
352 x[i + 1] += x[i] >> 8;
353 r[i] = x[i] & 255;
354 }
355}
356
357sv reduce (u8 *r)
358{
359 i64 x[64],i;
360 FOR (i,64) x[i] = (u64) r[i];
361 FOR (i,64) r[i] = 0;
362 modL (r,x);
363}
364
365static int unpackneg (gf r[4],const u8 p[32])
366{
367 gf t, chk, num, den, den2, den4, den6;
368 set25519 (r[2],gf1);
369 unpack25519 (r[1],p);
370 S (num,r[1]);
371 M (den,num,D);
372 Z (num,num,r[2]);
373 A (den,r[2],den);
374
375 S (den2,den);
376 S (den4,den2);
377 M (den6,den4,den2);
378 M (t,den6,num);
379 M (t,t,den);
380
381 pow2523 (t,t);
382 M (t,t,num);
383 M (t,t,den);
384 M (t,t,den);
385 M (r[0],t,den);
386
387 S (chk,r[0]);
388 M (chk,chk,den);
389 if (neq25519 (chk, num))
390 M (r[0],r[0],I);
391
392 S (chk,r[0]);
393 M (chk,chk,den);
394 if (neq25519 (chk, num))
395 return -1;
396
397 if (par25519 (r[0]) == (p[31] >> 7))
398 Z (r[0],gf0,r[0]);
399
400 M (r[3],r[0],r[1]);
401 return 0;
402}
403
404/* The following functions have been added for GNUnet */
405
406void
407crypto_sign_pk_from_seed (u8 *pk, const u8 *seed)
408{
409 u8 d[64];
410 gf p[4];
411
412 crypto_hash (d, seed, 32);
413 d[0] &= 248;
414 d[31] &= 127;
415 d[31] |= 64;
416
417 scalarbase (p,d);
418 pack (pk,p);
419}
420
421void
422crypto_sign_sk_from_seed (u8 *sk, const u8 *seed)
423{
424 u8 d[64];
425 gf p[4];
426 u8 pk[32];
427 int i;
428
429 crypto_hash (d, seed, 32);
430 d[0] &= 248;
431 d[31] &= 127;
432 d[31] |= 64;
433
434 scalarbase (p,d);
435 pack (pk,p);
436
437 FOR (i,32) sk[i] = seed[i];
438 FOR (i,32) sk[32 + i] = pk[i];
439}
440
441
442int
443crypto_sign_ed25519_pk_to_curve25519 (u8 *x25519_pk, const u8 *ed25519_pk)
444{
445 gf ge_a[4];
446 gf x;
447 gf one_minus_y;
448
449 if (0 != unpackneg (ge_a, ed25519_pk))
450 return -1;
451
452 set25519 (one_minus_y, gf1);
453 Z (one_minus_y, one_minus_y, ge_a[1]);
454
455 set25519 (x, gf1);
456 A (x, x, ge_a[1]);
457
458 inv25519 (one_minus_y, one_minus_y);
459 M (x, x, one_minus_y);
460 pack25519 (x25519_pk, x);
461
462 return 0;
463}
464
465
466int crypto_sign_detached_verify (const u8 *sig,const u8 *m,u64 n,const u8 *pk)
467{
468 struct GNUNET_HashContext *hc;
469 u8 t[32],h[64];
470 gf p[4],q[4];
471
472 if (unpackneg (q,pk))
473 return -1;
474
475 hc = GNUNET_CRYPTO_hash_context_start ();
476 GNUNET_CRYPTO_hash_context_read (hc, sig, 32);
477 GNUNET_CRYPTO_hash_context_read (hc, pk, 32);
478 GNUNET_CRYPTO_hash_context_read (hc, m, n);
479 GNUNET_CRYPTO_hash_context_finish (hc, (void *) h);
480
481 reduce (h);
482 scalarmult (p,q,h);
483
484 scalarbase (q,sig+32);
485 add (p,q);
486 pack (t,p);
487
488 if (crypto_verify_32 (sig, t))
489 return -1;
490 return 0;
491}
492
493
494int
495crypto_sign_detached (u8 *sig,const u8 *m,u64 n,const u8 *sk)
496{
497 struct GNUNET_HashContext *hc;
498 u8 d[64],h[64],r[64];
499 i64 i,j,x[64];
500 gf p[4];
501
502 crypto_hash (d, sk, 32);
503 d[0] &= 248;
504 d[31] &= 127;
505 d[31] |= 64;
506
507 hc = GNUNET_CRYPTO_hash_context_start ();
508 GNUNET_CRYPTO_hash_context_read (hc, d + 32, 32);
509 GNUNET_CRYPTO_hash_context_read (hc, m, n);
510 GNUNET_CRYPTO_hash_context_finish (hc, (void *) r);
511
512 reduce (r);
513 scalarbase (p,r);
514 pack (sig,p);
515
516 hc = GNUNET_CRYPTO_hash_context_start ();
517 GNUNET_CRYPTO_hash_context_read (hc, sig, 32);
518 GNUNET_CRYPTO_hash_context_read (hc, sk + 32, 32);
519 GNUNET_CRYPTO_hash_context_read (hc, m, n);
520 GNUNET_CRYPTO_hash_context_finish (hc, (void *) h);
521
522 reduce (h);
523
524 FOR (i,64) x[i] = 0;
525 FOR (i,32) x[i] = (u64) r[i];
526 FOR (i,32) FOR (j,32) x[i + j] += h[i] * (u64) d[j];
527 modL (sig + 32,x);
528
529 return 0;
530}