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