summaryrefslogtreecommitdiff
path: root/src/tweetnacl.c
diff options
context:
space:
mode:
authorSebastien Blot2017-09-20 10:11:01 +0200
committerSebastien Blot2017-09-20 10:11:01 +0200
commit868f96c759b6650d88ff9f4fbc5c048302134248 (patch)
treec0de0af318bf77a8959164ef11aeeeb2b7bab294 /src/tweetnacl.c
Initial import
Diffstat (limited to 'src/tweetnacl.c')
-rw-r--r--src/tweetnacl.c842
1 files changed, 842 insertions, 0 deletions
diff --git a/src/tweetnacl.c b/src/tweetnacl.c
new file mode 100644
index 0000000..937e879
--- /dev/null
+++ b/src/tweetnacl.c
@@ -0,0 +1,842 @@
1#include "tweetnacl.h"
2#define FOR(i,n) for (i = 0;i < n;++i)
3#define sv static void
4
5typedef unsigned char u8;
6typedef unsigned long u32;
7typedef unsigned long long u64;
8typedef long long i64;
9typedef i64 gf[16];
10
11
12/* it's really stupid that there isn't a syscall for this */
13
14static int fd = -1;
15
16void randombytes(unsigned char *x,unsigned long long xlen)
17{
18 int i;
19
20 if (fd == -1) {
21 for (;;) {
22 fd = open("/dev/urandom",O_RDONLY);
23 if (fd != -1) break;
24 sleep(1);
25 }
26 }
27
28 while (xlen > 0) {
29 if (xlen < 1048576) i = xlen; else i = 1048576;
30
31 i = read(fd,x,i);
32 if (i < 1) {
33 sleep(1);
34 continue;
35 }
36
37 x += i;
38 xlen -= i;
39 }
40}
41
42
43static const u8
44 _0[16],
45 _9[32] = {9};
46static const gf
47 gf0,
48 gf1 = {1},
49 _121665 = {0xDB41,1},
50 D = {0x78a3, 0x1359, 0x4dca, 0x75eb, 0xd8ab, 0x4141, 0x0a4d, 0x0070, 0xe898, 0x7779, 0x4079, 0x8cc7, 0xfe73, 0x2b6f, 0x6cee, 0x5203},
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 I = {0xa0b0, 0x4a0e, 0x1b27, 0xc4ee, 0xe478, 0xad2f, 0x1806, 0x2f43, 0xd7a7, 0x3dfb, 0x0099, 0x2b4d, 0xdf0b, 0x4fc1, 0x2480, 0x2b83};
55
56static u32 L32(u32 x,int c) { return (x << c) | ((x&0xffffffff) >> (32 - c)); }
57
58static u32 ld32(const u8 *x)
59{
60 u32 u = x[3];
61 u = (u<<8)|x[2];
62 u = (u<<8)|x[1];
63 return (u<<8)|x[0];
64}
65
66static u64 dl64(const u8 *x)
67{
68 u64 i,u=0;
69 FOR(i,8) u=(u<<8)|x[i];
70 return u;
71}
72
73sv st32(u8 *x,u32 u)
74{
75 int i;
76 FOR(i,4) { x[i] = u; u >>= 8; }
77}
78
79sv ts64(u8 *x,u64 u)
80{
81 int i;
82 for (i = 7;i >= 0;--i) { x[i] = u; u >>= 8; }
83}
84
85static int vn(const u8 *x,const u8 *y,int n)
86{
87 int i = 0;
88 u32 d = 0;
89 FOR(i,n) d |= x[i]^y[i];
90 return (1 & ((d - 1) >> 8)) - 1;
91}
92
93int crypto_verify_16(const u8 *x,const u8 *y)
94{
95 return vn(x,y,16);
96}
97
98int crypto_verify_32(const u8 *x,const u8 *y)
99{
100 return vn(x,y,32);
101}
102
103sv core(u8 *out,const u8 *in,const u8 *k,const u8 *c,int h)
104{
105 u32 w[16],x[16],y[16],t[4];
106 int i,j,m;
107
108 FOR(i,4) {
109 x[5*i] = ld32(c+4*i);
110 x[1+i] = ld32(k+4*i);
111 x[6+i] = ld32(in+4*i);
112 x[11+i] = ld32(k+16+4*i);
113 }
114
115 FOR(i,16) y[i] = x[i];
116
117 FOR(i,20) {
118 FOR(j,4) {
119 FOR(m,4) t[m] = x[(5*j+4*m)%16];
120 t[1] ^= L32(t[0]+t[3], 7);
121 t[2] ^= L32(t[1]+t[0], 9);
122 t[3] ^= L32(t[2]+t[1],13);
123 t[0] ^= L32(t[3]+t[2],18);
124 FOR(m,4) w[4*j+(j+m)%4] = t[m];
125 }
126 FOR(m,16) x[m] = w[m];
127 }
128
129 if (h) {
130 FOR(i,16) x[i] += y[i];
131 FOR(i,4) {
132 x[5*i] -= ld32(c+4*i);
133 x[6+i] -= ld32(in+4*i);
134 }
135 FOR(i,4) {
136 st32(out+4*i,x[5*i]);
137 st32(out+16+4*i,x[6+i]);
138 }
139 } else
140 FOR(i,16) st32(out + 4 * i,x[i] + y[i]);
141}
142
143int crypto_core_salsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
144{
145 core(out,in,k,c,0);
146 return 0;
147}
148
149int crypto_core_hsalsa20(u8 *out,const u8 *in,const u8 *k,const u8 *c)
150{
151 core(out,in,k,c,1);
152 return 0;
153}
154
155static const u8 sigma[16] = "expand 32-byte k";
156
157int crypto_stream_salsa20_xor(u8 *c,const u8 *m,u64 b,const u8 *n,const u8 *k)
158{
159 u8 z[16],x[64];
160 u32 u,i;
161 if (!b) return 0;
162 FOR(i,16) z[i] = 0;
163 FOR(i,8) z[i] = n[i];
164 while (b >= 64) {
165 crypto_core_salsa20(x,z,k,sigma);
166 FOR(i,64) c[i] = (m?m[i]:0) ^ x[i];
167 u = 1;
168 for (i = 8;i < 16;++i) {
169 u += (u32) z[i];
170 z[i] = u;
171 u >>= 8;
172 }
173 b -= 64;
174 c += 64;
175 if (m) m += 64;
176 }
177 if (b) {
178 crypto_core_salsa20(x,z,k,sigma);
179 FOR(i,b) c[i] = (m?m[i]:0) ^ x[i];
180 }
181 return 0;
182}
183
184int crypto_stream_salsa20(u8 *c,u64 d,const u8 *n,const u8 *k)
185{
186 return crypto_stream_salsa20_xor(c,0,d,n,k);
187}
188
189int crypto_stream(u8 *c,u64 d,const u8 *n,const u8 *k)
190{
191 u8 s[32];
192 crypto_core_hsalsa20(s,n,k,sigma);
193 return crypto_stream_salsa20(c,d,n+16,s);
194}
195
196int crypto_stream_xor(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
197{
198 u8 s[32];
199 crypto_core_hsalsa20(s,n,k,sigma);
200 return crypto_stream_salsa20_xor(c,m,d,n+16,s);
201}
202
203sv add1305(u32 *h,const u32 *c)
204{
205 u32 j,u = 0;
206 FOR(j,17) {
207 u += h[j] + c[j];
208 h[j] = u & 255;
209 u >>= 8;
210 }
211}
212
213static const u32 minusp[17] = {
214 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 252
215} ;
216
217int crypto_onetimeauth(u8 *out,const u8 *m,u64 n,const u8 *k)
218{
219 u32 s,i,j,u,x[17],r[17],h[17],c[17],g[17];
220
221 FOR(j,17) r[j]=h[j]=0;
222 FOR(j,16) r[j]=k[j];
223 r[3]&=15;
224 r[4]&=252;
225 r[7]&=15;
226 r[8]&=252;
227 r[11]&=15;
228 r[12]&=252;
229 r[15]&=15;
230
231 while (n > 0) {
232 FOR(j,17) c[j] = 0;
233 for (j = 0;(j < 16) && (j < n);++j) c[j] = m[j];
234 c[j] = 1;
235 m += j; n -= j;
236 add1305(h,c);
237 FOR(i,17) {
238 x[i] = 0;
239 FOR(j,17) x[i] += h[j] * ((j <= i) ? r[i - j] : 320 * r[i + 17 - j]);
240 }
241 FOR(i,17) h[i] = x[i];
242 u = 0;
243 FOR(j,16) {
244 u += h[j];
245 h[j] = u & 255;
246 u >>= 8;
247 }
248 u += h[16]; h[16] = u & 3;
249 u = 5 * (u >> 2);
250 FOR(j,16) {
251 u += h[j];
252 h[j] = u & 255;
253 u >>= 8;
254 }
255 u += h[16]; h[16] = u;
256 }
257
258 FOR(j,17) g[j] = h[j];
259 add1305(h,minusp);
260 s = -(h[16] >> 7);
261 FOR(j,17) h[j] ^= s & (g[j] ^ h[j]);
262
263 FOR(j,16) c[j] = k[j + 16];
264 c[16] = 0;
265 add1305(h,c);
266 FOR(j,16) out[j] = h[j];
267 return 0;
268}
269
270int crypto_onetimeauth_verify(const u8 *h,const u8 *m,u64 n,const u8 *k)
271{
272 u8 x[16];
273 crypto_onetimeauth(x,m,n,k);
274 return crypto_verify_16(h,x);
275}
276
277int crypto_secretbox(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
278{
279 int i;
280 if (d < 32) return -1;
281 crypto_stream_xor(c,m,d,n,k);
282 crypto_onetimeauth(c + 16,c + 32,d - 32,c);
283 FOR(i,16) c[i] = 0;
284 return 0;
285}
286
287int crypto_secretbox_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
288{
289 int i;
290 u8 x[32];
291 if (d < 32) return -1;
292 crypto_stream(x,32,n,k);
293 if (crypto_onetimeauth_verify(c + 16,c + 32,d - 32,x) != 0) return -1;
294 crypto_stream_xor(m,c,d,n,k);
295 FOR(i,32) m[i] = 0;
296 return 0;
297}
298
299sv set25519(gf r, const gf a)
300{
301 int i;
302 FOR(i,16) r[i]=a[i];
303}
304
305sv car25519(gf o)
306{
307 int i;
308 i64 c;
309 FOR(i,16) {
310 o[i]+=(1LL<<16);
311 c=o[i]>>16;
312 o[(i+1)*(i<15)]+=c-1+37*(c-1)*(i==15);
313 o[i]-=c<<16;
314 }
315}
316
317sv sel25519(gf p,gf q,int b)
318{
319 i64 t,i,c=~(b-1);
320 FOR(i,16) {
321 t= c&(p[i]^q[i]);
322 p[i]^=t;
323 q[i]^=t;
324 }
325}
326
327sv pack25519(u8 *o,const gf n)
328{
329 int i,j,b;
330 gf m,t;
331 FOR(i,16) t[i]=n[i];
332 car25519(t);
333 car25519(t);
334 car25519(t);
335 FOR(j,2) {
336 m[0]=t[0]-0xffed;
337 for(i=1;i<15;i++) {
338 m[i]=t[i]-0xffff-((m[i-1]>>16)&1);
339 m[i-1]&=0xffff;
340 }
341 m[15]=t[15]-0x7fff-((m[14]>>16)&1);
342 b=(m[15]>>16)&1;
343 m[14]&=0xffff;
344 sel25519(t,m,1-b);
345 }
346 FOR(i,16) {
347 o[2*i]=t[i]&0xff;
348 o[2*i+1]=t[i]>>8;
349 }
350}
351
352static int neq25519(const gf a, const gf b)
353{
354 u8 c[32],d[32];
355 pack25519(c,a);
356 pack25519(d,b);
357 return crypto_verify_32(c,d);
358}
359
360static u8 par25519(const gf a)
361{
362 u8 d[32];
363 pack25519(d,a);
364 return d[0]&1;
365}
366
367sv unpack25519(gf o, const u8 *n)
368{
369 int i;
370 FOR(i,16) o[i]=n[2*i]+((i64)n[2*i+1]<<8);
371 o[15]&=0x7fff;
372}
373
374sv A(gf o,const gf a,const gf b)
375{
376 int i;
377 FOR(i,16) o[i]=a[i]+b[i];
378}
379
380sv Z(gf o,const gf a,const gf b)
381{
382 int i;
383 FOR(i,16) o[i]=a[i]-b[i];
384}
385
386sv M(gf o,const gf a,const gf b)
387{
388 i64 i,j,t[31];
389 FOR(i,31) t[i]=0;
390 FOR(i,16) FOR(j,16) t[i+j]+=a[i]*b[j];
391 FOR(i,15) t[i]+=38*t[i+16];
392 FOR(i,16) o[i]=t[i];
393 car25519(o);
394 car25519(o);
395}
396
397sv S(gf o,const gf a)
398{
399 M(o,a,a);
400}
401
402sv inv25519(gf o,const gf i)
403{
404 gf c;
405 int a;
406 FOR(a,16) c[a]=i[a];
407 for(a=253;a>=0;a--) {
408 S(c,c);
409 if(a!=2&&a!=4) M(c,c,i);
410 }
411 FOR(a,16) o[a]=c[a];
412}
413
414sv pow2523(gf o,const gf i)
415{
416 gf c;
417 int a;
418 FOR(a,16) c[a]=i[a];
419 for(a=250;a>=0;a--) {
420 S(c,c);
421 if(a!=1) M(c,c,i);
422 }
423 FOR(a,16) o[a]=c[a];
424}
425
426int crypto_scalarmult(u8 *q,const u8 *n,const u8 *p)
427{
428 u8 z[32];
429 i64 x[80],r,i;
430 gf a,b,c,d,e,f;
431 FOR(i,31) z[i]=n[i];
432 z[31]=(n[31]&127)|64;
433 z[0]&=248;
434 unpack25519(x,p);
435 FOR(i,16) {
436 b[i]=x[i];
437 d[i]=a[i]=c[i]=0;
438 }
439 a[0]=d[0]=1;
440 for(i=254;i>=0;--i) {
441 r=(z[i>>3]>>(i&7))&1;
442 sel25519(a,b,r);
443 sel25519(c,d,r);
444 A(e,a,c);
445 Z(a,a,c);
446 A(c,b,d);
447 Z(b,b,d);
448 S(d,e);
449 S(f,a);
450 M(a,c,a);
451 M(c,b,e);
452 A(e,a,c);
453 Z(a,a,c);
454 S(b,a);
455 Z(c,d,f);
456 M(a,c,_121665);
457 A(a,a,d);
458 M(c,c,a);
459 M(a,d,f);
460 M(d,b,x);
461 S(b,e);
462 sel25519(a,b,r);
463 sel25519(c,d,r);
464 }
465 FOR(i,16) {
466 x[i+16]=a[i];
467 x[i+32]=c[i];
468 x[i+48]=b[i];
469 x[i+64]=d[i];
470 }
471 inv25519(x+32,x+32);
472 M(x+16,x+16,x+32);
473 pack25519(q,x+16);
474 return 0;
475}
476
477int crypto_scalarmult_base(u8 *q,const u8 *n)
478{
479 return crypto_scalarmult(q,n,_9);
480}
481
482int crypto_box_keypair(u8 *y,u8 *x)
483{
484 randombytes(x,32);
485 return crypto_scalarmult_base(y,x);
486}
487
488int crypto_box_beforenm(u8 *k,const u8 *y,const u8 *x)
489{
490 u8 s[32];
491 crypto_scalarmult(s,x,y);
492 return crypto_core_hsalsa20(k,_0,s,sigma);
493}
494
495int crypto_box_afternm(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *k)
496{
497 return crypto_secretbox(c,m,d,n,k);
498}
499
500int crypto_box_open_afternm(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *k)
501{
502 return crypto_secretbox_open(m,c,d,n,k);
503}
504
505int crypto_box(u8 *c,const u8 *m,u64 d,const u8 *n,const u8 *y,const u8 *x)
506{
507 u8 k[32];
508 crypto_box_beforenm(k,y,x);
509 return crypto_box_afternm(c,m,d,n,k);
510}
511
512int crypto_box_open(u8 *m,const u8 *c,u64 d,const u8 *n,const u8 *y,const u8 *x)
513{
514 u8 k[32];
515 crypto_box_beforenm(k,y,x);
516 return crypto_box_open_afternm(m,c,d,n,k);
517}
518
519static u64 R(u64 x,int c) { return (x >> c) | (x << (64 - c)); }
520static u64 Ch(u64 x,u64 y,u64 z) { return (x & y) ^ (~x & z); }
521static u64 Maj(u64 x,u64 y,u64 z) { return (x & y) ^ (x & z) ^ (y & z); }
522static u64 Sigma0(u64 x) { return R(x,28) ^ R(x,34) ^ R(x,39); }
523static u64 Sigma1(u64 x) { return R(x,14) ^ R(x,18) ^ R(x,41); }
524static u64 sigma0(u64 x) { return R(x, 1) ^ R(x, 8) ^ (x >> 7); }
525static u64 sigma1(u64 x) { return R(x,19) ^ R(x,61) ^ (x >> 6); }
526
527static const u64 K[80] =
528{
529 0x428a2f98d728ae22ULL, 0x7137449123ef65cdULL, 0xb5c0fbcfec4d3b2fULL, 0xe9b5dba58189dbbcULL,
530 0x3956c25bf348b538ULL, 0x59f111f1b605d019ULL, 0x923f82a4af194f9bULL, 0xab1c5ed5da6d8118ULL,
531 0xd807aa98a3030242ULL, 0x12835b0145706fbeULL, 0x243185be4ee4b28cULL, 0x550c7dc3d5ffb4e2ULL,
532 0x72be5d74f27b896fULL, 0x80deb1fe3b1696b1ULL, 0x9bdc06a725c71235ULL, 0xc19bf174cf692694ULL,
533 0xe49b69c19ef14ad2ULL, 0xefbe4786384f25e3ULL, 0x0fc19dc68b8cd5b5ULL, 0x240ca1cc77ac9c65ULL,
534 0x2de92c6f592b0275ULL, 0x4a7484aa6ea6e483ULL, 0x5cb0a9dcbd41fbd4ULL, 0x76f988da831153b5ULL,
535 0x983e5152ee66dfabULL, 0xa831c66d2db43210ULL, 0xb00327c898fb213fULL, 0xbf597fc7beef0ee4ULL,
536 0xc6e00bf33da88fc2ULL, 0xd5a79147930aa725ULL, 0x06ca6351e003826fULL, 0x142929670a0e6e70ULL,
537 0x27b70a8546d22ffcULL, 0x2e1b21385c26c926ULL, 0x4d2c6dfc5ac42aedULL, 0x53380d139d95b3dfULL,
538 0x650a73548baf63deULL, 0x766a0abb3c77b2a8ULL, 0x81c2c92e47edaee6ULL, 0x92722c851482353bULL,
539 0xa2bfe8a14cf10364ULL, 0xa81a664bbc423001ULL, 0xc24b8b70d0f89791ULL, 0xc76c51a30654be30ULL,
540 0xd192e819d6ef5218ULL, 0xd69906245565a910ULL, 0xf40e35855771202aULL, 0x106aa07032bbd1b8ULL,
541 0x19a4c116b8d2d0c8ULL, 0x1e376c085141ab53ULL, 0x2748774cdf8eeb99ULL, 0x34b0bcb5e19b48a8ULL,
542 0x391c0cb3c5c95a63ULL, 0x4ed8aa4ae3418acbULL, 0x5b9cca4f7763e373ULL, 0x682e6ff3d6b2b8a3ULL,
543 0x748f82ee5defb2fcULL, 0x78a5636f43172f60ULL, 0x84c87814a1f0ab72ULL, 0x8cc702081a6439ecULL,
544 0x90befffa23631e28ULL, 0xa4506cebde82bde9ULL, 0xbef9a3f7b2c67915ULL, 0xc67178f2e372532bULL,
545 0xca273eceea26619cULL, 0xd186b8c721c0c207ULL, 0xeada7dd6cde0eb1eULL, 0xf57d4f7fee6ed178ULL,
546 0x06f067aa72176fbaULL, 0x0a637dc5a2c898a6ULL, 0x113f9804bef90daeULL, 0x1b710b35131c471bULL,
547 0x28db77f523047d84ULL, 0x32caab7b40c72493ULL, 0x3c9ebe0a15c9bebcULL, 0x431d67c49c100d4cULL,
548 0x4cc5d4becb3e42b6ULL, 0x597f299cfc657e2aULL, 0x5fcb6fab3ad6faecULL, 0x6c44198c4a475817ULL
549};
550
551int crypto_hashblocks(u8 *x,const u8 *m,u64 n)
552{
553 u64 z[8],b[8],a[8],w[16],t;
554 int i,j;
555
556 FOR(i,8) z[i] = a[i] = dl64(x + 8 * i);
557
558 while (n >= 128) {
559 FOR(i,16) w[i] = dl64(m + 8 * i);
560
561 FOR(i,80) {
562 FOR(j,8) b[j] = a[j];
563 t = a[7] + Sigma1(a[4]) + Ch(a[4],a[5],a[6]) + K[i] + w[i%16];
564 b[7] = t + Sigma0(a[0]) + Maj(a[0],a[1],a[2]);
565 b[3] += t;
566 FOR(j,8) a[(j+1)%8] = b[j];
567 if (i%16 == 15)
568 FOR(j,16)
569 w[j] += w[(j+9)%16] + sigma0(w[(j+1)%16]) + sigma1(w[(j+14)%16]);
570 }
571
572 FOR(i,8) { a[i] += z[i]; z[i] = a[i]; }
573
574 m += 128;
575 n -= 128;
576 }
577
578 FOR(i,8) ts64(x+8*i,z[i]);
579
580 return n;
581}
582
583static const u8 iv[64] = {
584 0x6a,0x09,0xe6,0x67,0xf3,0xbc,0xc9,0x08,
585 0xbb,0x67,0xae,0x85,0x84,0xca,0xa7,0x3b,
586 0x3c,0x6e,0xf3,0x72,0xfe,0x94,0xf8,0x2b,
587 0xa5,0x4f,0xf5,0x3a,0x5f,0x1d,0x36,0xf1,
588 0x51,0x0e,0x52,0x7f,0xad,0xe6,0x82,0xd1,
589 0x9b,0x05,0x68,0x8c,0x2b,0x3e,0x6c,0x1f,
590 0x1f,0x83,0xd9,0xab,0xfb,0x41,0xbd,0x6b,
591 0x5b,0xe0,0xcd,0x19,0x13,0x7e,0x21,0x79
592} ;
593
594int crypto_hash(u8 *out,const u8 *m,u64 n)
595{
596 u8 h[64],x[256];
597 u64 i,b = n;
598
599 FOR(i,64) h[i] = iv[i];
600
601 crypto_hashblocks(h,m,n);
602 m += n;
603 n &= 127;
604 m -= n;
605
606 FOR(i,256) x[i] = 0;
607 FOR(i,n) x[i] = m[i];
608 x[n] = 128;
609
610 n = 256-128*(n<112);
611 x[n-9] = b >> 61;
612 ts64(x+n-8,b<<3);
613 crypto_hashblocks(h,x,n);
614
615 FOR(i,64) out[i] = h[i];
616
617 return 0;
618}
619
620sv add(gf p[4],gf q[4])
621{
622 gf a,b,c,d,t,e,f,g,h;
623
624 Z(a, p[1], p[0]);
625 Z(t, q[1], q[0]);
626 M(a, a, t);
627 A(b, p[0], p[1]);
628 A(t, q[0], q[1]);
629 M(b, b, t);
630 M(c, p[3], q[3]);
631 M(c, c, D2);
632 M(d, p[2], q[2]);
633 A(d, d, d);
634 Z(e, b, a);
635 Z(f, d, c);
636 A(g, d, c);
637 A(h, b, a);
638
639 M(p[0], e, f);
640 M(p[1], h, g);
641 M(p[2], g, f);
642 M(p[3], e, h);
643}
644
645sv cswap(gf p[4],gf q[4],u8 b)
646{
647 int i;
648 FOR(i,4)
649 sel25519(p[i],q[i],b);
650}
651
652sv pack(u8 *r,gf p[4])
653{
654 gf tx, ty, zi;
655 inv25519(zi, p[2]);
656 M(tx, p[0], zi);
657 M(ty, p[1], zi);
658 pack25519(r, ty);
659 r[31] ^= par25519(tx) << 7;
660}
661
662sv scalarmult(gf p[4],gf q[4],const u8 *s)
663{
664 int i;
665 set25519(p[0],gf0);
666 set25519(p[1],gf1);
667 set25519(p[2],gf1);
668 set25519(p[3],gf0);
669 for (i = 255;i >= 0;--i) {
670 u8 b = (s[i/8]>>(i&7))&1;
671 cswap(p,q,b);
672 add(q,p);
673 add(p,p);
674 cswap(p,q,b);
675 }
676}
677
678sv scalarbase(gf p[4],const u8 *s)
679{
680 gf q[4];
681 set25519(q[0],X);
682 set25519(q[1],Y);
683 set25519(q[2],gf1);
684 M(q[3],X,Y);
685 scalarmult(p,q,s);
686}
687
688int crypto_sign_keypair(u8 *pk, u8 *sk)
689{
690 u8 d[64];
691 gf p[4];
692 int i;
693
694 randombytes(sk, 32);
695 crypto_hash(d, sk, 32);
696 d[0] &= 248;
697 d[31] &= 127;
698 d[31] |= 64;
699
700 scalarbase(p,d);
701 pack(pk,p);
702
703 FOR(i,32) sk[32 + i] = pk[i];
704 return 0;
705}
706
707static 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};
708
709sv modL(u8 *r,i64 x[64])
710{
711 i64 carry,i,j;
712 for (i = 63;i >= 32;--i) {
713 carry = 0;
714 for (j = i - 32;j < i - 12;++j) {
715 x[j] += carry - 16 * x[i] * L[j - (i - 32)];
716 carry = (x[j] + 128) >> 8;
717 x[j] -= carry << 8;
718 }
719 x[j] += carry;
720 x[i] = 0;
721 }
722 carry = 0;
723 FOR(j,32) {
724 x[j] += carry - (x[31] >> 4) * L[j];
725 carry = x[j] >> 8;
726 x[j] &= 255;
727 }
728 FOR(j,32) x[j] -= carry * L[j];
729 FOR(i,32) {
730 x[i+1] += x[i] >> 8;
731 r[i] = x[i] & 255;
732 }
733}
734
735sv reduce(u8 *r)
736{
737 i64 x[64],i;
738 FOR(i,64) x[i] = (u64) r[i];
739 FOR(i,64) r[i] = 0;
740 modL(r,x);
741}
742
743int crypto_sign(u8 *sm,u64 *smlen,const u8 *m,u64 n,const u8 *sk)
744{
745 u8 d[64],h[64],r[64];
746 u64 i;
747 i64 j,x[64];
748 gf p[4];
749
750 crypto_hash(d, sk, 32);
751 d[0] &= 248;
752 d[31] &= 127;
753 d[31] |= 64;
754
755 *smlen = n+64;
756 FOR(i,n) sm[64 + i] = m[i];
757 FOR(i,32) sm[32 + i] = d[32 + i];
758
759 crypto_hash(r, sm+32, n+32);
760 reduce(r);
761 scalarbase(p,r);
762 pack(sm,p);
763
764 FOR(i,32) sm[i+32] = sk[i+32];
765 crypto_hash(h,sm,n + 64);
766 reduce(h);
767
768 FOR(i,64) x[i] = 0;
769 FOR(i,32) x[i] = (u64) r[i];
770 FOR(i,32) FOR(j,32) x[i+j] += h[i] * (u64) d[j];
771 modL(sm + 32,x);
772
773 return 0;
774}
775
776static int unpackneg(gf r[4],const u8 p[32])
777{
778 gf t, chk, num, den, den2, den4, den6;
779 set25519(r[2],gf1);
780 unpack25519(r[1],p);
781 S(num,r[1]);
782 M(den,num,D);
783 Z(num,num,r[2]);
784 A(den,r[2],den);
785
786 S(den2,den);
787 S(den4,den2);
788 M(den6,den4,den2);
789 M(t,den6,num);
790 M(t,t,den);
791
792 pow2523(t,t);
793 M(t,t,num);
794 M(t,t,den);
795 M(t,t,den);
796 M(r[0],t,den);
797
798 S(chk,r[0]);
799 M(chk,chk,den);
800 if (neq25519(chk, num)) M(r[0],r[0],I);
801
802 S(chk,r[0]);
803 M(chk,chk,den);
804 if (neq25519(chk, num)) return -1;
805
806 if (par25519(r[0]) == (p[31]>>7)) Z(r[0],gf0,r[0]);
807
808 M(r[3],r[0],r[1]);
809 return 0;
810}
811
812int crypto_sign_open(u8 *m,u64 *mlen,const u8 *sm,u64 n,const u8 *pk)
813{
814 u64 i;
815 u8 t[32],h[64];
816 gf p[4],q[4];
817
818 *mlen = -1;
819 if (n < 64) return -1;
820
821 if (unpackneg(q,pk)) return -1;
822
823 FOR(i,n) m[i] = sm[i];
824 FOR(i,32) m[i+32] = pk[i];
825 crypto_hash(h,m,n);
826 reduce(h);
827 scalarmult(p,q,h);
828
829 scalarbase(q,sm + 32);
830 add(p,q);
831 pack(t,p);
832
833 n -= 64;
834 if (crypto_verify_32(sm, t)) {
835 FOR(i,n) m[i] = 0;
836 return -1;
837 }
838
839 FOR(i,n) m[i] = sm[i + 64];
840 *mlen = n;
841 return 0;
842}