aboutsummaryrefslogtreecommitdiff
path: root/src/util/tweetnacl-gnunet.c
diff options
context:
space:
mode:
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}