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