diff options
Diffstat (limited to 'src/util/tweetnacl-gnunet.c')
-rw-r--r-- | src/util/tweetnacl-gnunet.c | 530 |
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 | |||
16 | typedef uint8_t u8; | ||
17 | typedef uint32_t u32; | ||
18 | typedef uint64_t u64; | ||
19 | typedef int64_t i64; | ||
20 | typedef i64 gf[16]; | ||
21 | |||
22 | static void randombytes (u8 *data,u64 len) | ||
23 | { | ||
24 | GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE, data, len); | ||
25 | } | ||
26 | |||
27 | static const u8 _9[32] = {9}; | ||
28 | static 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 | |||
43 | static 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 | |||
50 | int crypto_verify_16 (const u8 *x,const u8 *y) | ||
51 | { | ||
52 | return vn (x,y,16); | ||
53 | } | ||
54 | |||
55 | int crypto_verify_32 (const u8 *x,const u8 *y) | ||
56 | { | ||
57 | return vn (x,y,32); | ||
58 | } | ||
59 | |||
60 | sv set25519 (gf r, const gf a) | ||
61 | { | ||
62 | int i; | ||
63 | FOR (i,16) r[i] = a[i]; | ||
64 | } | ||
65 | |||
66 | sv 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 | |||
78 | sv 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 | |||
88 | sv 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 | |||
113 | static 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 | |||
121 | static u8 par25519 (const gf a) | ||
122 | { | ||
123 | u8 d[32]; | ||
124 | pack25519 (d,a); | ||
125 | return d[0] & 1; | ||
126 | } | ||
127 | |||
128 | sv 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 | |||
135 | sv 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 | |||
141 | sv 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 | |||
147 | sv 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 | |||
158 | sv S (gf o,const gf a) | ||
159 | { | ||
160 | M (o,a,a); | ||
161 | } | ||
162 | |||
163 | sv 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 | |||
176 | sv 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 | |||
189 | int 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 | |||
240 | int crypto_scalarmult_base (u8 *q,const u8 *n) | ||
241 | { | ||
242 | return crypto_scalarmult (q,n,_9); | ||
243 | } | ||
244 | |||
245 | int crypto_box_keypair (u8 *y,u8 *x) | ||
246 | { | ||
247 | randombytes (x,32); | ||
248 | return crypto_scalarmult_base (y,x); | ||
249 | } | ||
250 | |||
251 | int 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 | |||
258 | sv 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 | |||
283 | sv 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 | |||
290 | sv 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 | |||
300 | sv 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 | |||
316 | sv 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 | |||
326 | static 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 | |||
331 | sv 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 | |||
357 | sv 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 | |||
365 | static 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 | |||
406 | void | ||
407 | crypto_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 | |||
421 | void | ||
422 | crypto_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 | |||
442 | int | ||
443 | crypto_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 | |||
466 | int 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 | |||
494 | int | ||
495 | crypto_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 | } | ||