progs/perftest.c: Use from Glibc syscall numbers.
[catacomb] / symm / sha3.c
1 /* -*-c-*-
2 *
3 * The SHA3 algorithm family
4 *
5 * (c) 2017 Straylight/Edgeware
6 */
7
8 /*----- Licensing notice --------------------------------------------------*
9 *
10 * This file is part of Catacomb.
11 *
12 * Catacomb is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU Library General Public License as
14 * published by the Free Software Foundation; either version 2 of the
15 * License, or (at your option) any later version.
16 *
17 * Catacomb is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU Library General Public License for more details.
21 *
22 * You should have received a copy of the GNU Library General Public
23 * License along with Catacomb; if not, write to the Free
24 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25 * MA 02111-1307, USA.
26 */
27
28 /*----- Header files ------------------------------------------------------*/
29
30 #include <assert.h>
31 #include <stdarg.h>
32 #include <string.h>
33
34 #include "hash.h"
35 #include "ghash-def.h"
36 #include "sha3.h"
37
38 /*----- General utilities -------------------------------------------------*/
39
40 static void absorb(sha3_ctx *ctx, const octet *p, unsigned r)
41 {
42 kludge64 t[25];
43 unsigned i;
44
45 /* memdump("absorb", p, 8*r, 0); */
46 for (i = 0; i < r; i++) { LOAD64_L_(t[i], p); p += 8; }
47 keccak1600_mix(&ctx->s, t, r);
48 }
49
50 static void step(sha3_ctx *ctx) { keccak1600_p(&ctx->s, &ctx->s, 24); }
51
52 static void pad(sha3_ctx *ctx, unsigned lo, unsigned hi)
53 {
54 size_t spare = ctx->r - ctx->n;
55
56 if (spare == 1)
57 ctx->buf[ctx->n] = lo | hi;
58 else {
59 ctx->buf[ctx->n] = lo;
60 ctx->buf[ctx->r - 1] = hi;
61 memset(ctx->buf + ctx->n + 1, 0, spare - 2);
62 }
63 absorb(ctx, ctx->buf, ctx->r/8);
64 }
65
66 static void squeeze(sha3_ctx *ctx, octet *p, unsigned r)
67 {
68 kludge64 t[25];
69 unsigned i;
70
71 keccak1600_extract(&ctx->s, t, r);
72 for (i = 0; i < r; i++) { STORE64_L_(p, t[i]); p += 8; }
73 /* memdump("squeeze", p - 8*r, 8*r, 0); */
74 }
75
76 enum {
77 OP_CSHAKE = 0x04,
78 OP_SHA3 = 0x06,
79 OP_SHAKE = 0x1f
80 };
81
82 enum { ST_ABSORB, ST_SQUEEZE, ST_DEAD };
83
84 /*----- The SHA3 algorithms -----------------------------------------------*/
85
86 /* --- @sha3_{224,256,384,512}_init@ --- *
87 *
88 * Arguments: @sha3_ctx *ctx@ = pointer to context block to initialize
89 *
90 * Returns: ---
91 *
92 * Use: Initializes a SHA3 hashing context for use.
93 */
94
95 static void init_sha3(sha3_ctx *ctx, unsigned w)
96 {
97 keccak1600_init(&ctx->s);
98 ctx->w = w/8; ctx->r = (1600 - 2*w)/8; ctx->n = 0;
99 }
100
101 void sha3_224_init(sha3_ctx *ctx) { init_sha3(ctx, 224); }
102 void sha3_256_init(sha3_ctx *ctx) { init_sha3(ctx, 256); }
103 void sha3_384_init(sha3_ctx *ctx) { init_sha3(ctx, 384); }
104 void sha3_512_init(sha3_ctx *ctx) { init_sha3(ctx, 512); }
105
106 /* --- @sha3_hash@ --- *
107 *
108 * Arguments: @sha3_ctx *ctx@ = pointer to context bock
109 * @const void *p@ = pointer to data to hash
110 * @size_t sz@ = size of buffer to hash
111 *
112 * Returns: ---
113 *
114 * Use: Hashes a buffer of data. The buffer may be of any size and
115 * alignment.
116 */
117
118 void sha3_hash(sha3_ctx *ctx, const void *p, size_t sz)
119 {
120 const octet *q = p;
121 size_t spare = ctx->r - ctx->n;
122
123 if (sz < spare) {
124 memcpy(ctx->buf + ctx->n, q, sz);
125 ctx->n += sz;
126 return;
127 }
128 if (ctx->n) {
129 memcpy(ctx->buf + ctx->n, q, spare);
130 absorb(ctx, ctx->buf, ctx->r/8);
131 step(ctx);
132 q += spare; sz -= spare;
133 }
134 while (sz >= ctx->r) {
135 absorb(ctx, q, ctx->r/8);
136 step(ctx);
137 q += ctx->r; sz -= ctx->r;
138 }
139 if (sz) memcpy(ctx->buf, q, sz);
140 ctx->n = sz;
141 }
142
143 /* --- @sha3_done@ --- *
144 *
145 * Arguments: @sha3_ctx *ctx@ = pointer to context block
146 * @void *hash@ = pointer to output buffer
147 *
148 * Returns: ---
149 *
150 * Use: Returns the hash of the data read so far.
151 */
152
153 void sha3_done(sha3_ctx *ctx, void *hash)
154 {
155 pad(ctx, OP_SHA3, 0x80);
156 step(ctx);
157
158 if (ctx->w%8 == 0)
159 squeeze(ctx, hash, ctx->w/8);
160 else {
161 squeeze(ctx, ctx->buf, (ctx->w + 7)/8);
162 memcpy(hash, ctx->buf, ctx->w);
163 }
164 }
165
166 /* --- @sha3_{224,256,384,512}_set@ --- *
167 *
168 * Arguments: @sha3_ctx *ctx@ = pointer to context block
169 * @const void *buf@ = pointer to state buffer
170 * @unsigned long count@ = current count of bytes processed
171 *
172 * Returns: ---
173 *
174 * Use: Initializes a context block from a given state. This is
175 * something of a kludge for the benefit of HMAC, but there are
176 * better ways to use SHA3 as a MAC.
177 *
178 * Furthermore, the @count@ argument is expected to be zero or
179 * be the output of @sha3_state@ below. Doing anything else
180 * won't work properly.
181 */
182
183 static void set(sha3_ctx *ctx, const void *buf,
184 unsigned long count, unsigned w)
185 {
186 if (count)
187 memcpy(ctx, buf, sizeof(*ctx));
188 else {
189 static const char *prefix = "Catacomb SHA3 NMAC kludge";
190 init_sha3(ctx, w);
191 sha3_hash(ctx, prefix, sizeof(prefix));
192 sha3_hash(ctx, buf, SHA3_STATESZ);
193 }
194 }
195
196 void sha3_224_set(sha3_ctx *ctx, const void *buf, unsigned long count)
197 { set(ctx, buf, count, 224); }
198 void sha3_256_set(sha3_ctx *ctx, const void *buf, unsigned long count)
199 { set(ctx, buf, count, 256); }
200 void sha3_384_set(sha3_ctx *ctx, const void *buf, unsigned long count)
201 { set(ctx, buf, count, 384); }
202 void sha3_512_set(sha3_ctx *ctx, const void *buf, unsigned long count)
203 { set(ctx, buf, count, 512); }
204
205 /* --- @sha3_state@ --- *
206 *
207 * Arguments: @sha3_ctx *ctx@ = pointer to context block
208 * @void *state@ = pointer to buffer for current state
209 *
210 * Returns: A value which is meaningful to @sha3_..._set@.
211 *
212 * Use: Returns the current state of the hash function such that it
213 * can be passed to @sha3_..._set@.
214 */
215
216 unsigned long sha3_state(sha3_ctx *ctx, void *state)
217 { memcpy(state, ctx, sizeof(*ctx)); return (1); }
218
219 #define HASHES(_) \
220 _(SHA3_224, sha3_224, "sha3-224") \
221 _(SHA3_256, sha3_256, "sha3-256") \
222 _(SHA3_384, sha3_384, "sha3-384") \
223 _(SHA3_512, sha3_512, "sha3-512")
224 HASHES(GHASH_DEFX)
225
226 /*----- The cSHAKE XOF algorithm ------------------------------------------*/
227
228 static void leftenc_sz(shake_ctx *ctx, size_t n)
229 {
230 kludge64 t;
231 octet b[9];
232 unsigned i;
233
234 SET64(t, ((n&~(size_t)MASK32) >> 16) >> 16, n&MASK32);
235 STORE64_B_(b + 1, t);
236 for (i = 1; i < 8 && !b[i]; i++);
237 i--; b[i] = 8 - i;
238 shake_hash(ctx, b + i, 9 - i);
239 }
240
241 static void rightenc_sz(shake_ctx *ctx, size_t n)
242 {
243 kludge64 t;
244 octet b[9];
245 unsigned i;
246
247 SET64(t, ((n&~(size_t)MASK32) >> 16) >> 16, n&MASK32);
248 STORE64_B_(b, t);
249 for (i = 0; i < 7 && !b[i]; i++);
250 b[8] = 8 - i;
251 shake_hash(ctx, b + i, 9 - i);
252 }
253
254 static void stringenc(shake_ctx *ctx, const void *p, size_t sz)
255 { leftenc_sz(ctx, 8*sz); if (sz) shake_hash(ctx, p, sz); }
256
257 static void bytepad_before(shake_ctx *ctx)
258 { leftenc_sz(ctx, ctx->h.r); }
259
260 static void bytepad_after(shake_ctx *ctx)
261 {
262 unsigned pad;
263
264 if (ctx->h.n%8) {
265 pad = 8 - ctx->h.n%8;
266 memset(ctx->h.buf + ctx->h.n, 0, pad);
267 ctx->h.n += pad;
268 }
269 if (ctx->h.n) {
270 absorb(&ctx->h, ctx->h.buf, ctx->h.n/8);
271 step(&ctx->h); ctx->h.n = 0;
272 }
273 }
274
275 const octet
276 shake128_keysz[] = { KSZ_ANY, SHAKE128_KEYSZ },
277 shake256_keysz[] = { KSZ_ANY, SHAKE256_KEYSZ };
278
279 /* --- @cshake{128,256}_init@ --- *
280 *
281 * Arguments: @shake_ctx *ctx@ = pointer to context to initialize
282 * @const void *func@ = NIST-allocated function name
283 * @size_t fsz@ = length of function name
284 * @const void *perso@ = user personalization string
285 * @size_t psz@ = length of personalization string
286 *
287 * Returns: ---
288 *
289 * Use: Initializes a cSHAKE context. The context is initially in
290 * the `absorbing' state: feed it data with @shake_hash@.
291 */
292
293 static void init_shake(shake_ctx *ctx, unsigned c0,
294 const void *func, size_t fsz,
295 const void *perso, size_t psz)
296 {
297 keccak1600_init(&ctx->h.s); ctx->st = ST_ABSORB;
298 ctx->h.r = (1600 - 2*c0)/8; ctx->h.w = 0; ctx->h.n = 0;
299 if (!fsz && !psz)
300 ctx->op = OP_SHAKE;
301 else {
302 bytepad_before(ctx);
303 stringenc(ctx, func, fsz);
304 stringenc(ctx, perso, psz);
305 bytepad_after(ctx);
306 ctx->op = OP_CSHAKE;
307 }
308 }
309
310 void cshake128_init(shake_ctx *ctx,
311 const void *func, size_t fsz,
312 const void *perso, size_t psz)
313 { init_shake(ctx, 128, func, fsz, perso, psz); }
314
315 void cshake256_init(shake_ctx *ctx,
316 const void *func, size_t fsz,
317 const void *perso, size_t psz)
318 { init_shake(ctx, 256, func, fsz, perso, psz); }
319
320 /* --- @shake{128,256}_init@ --- *
321 *
322 * Arguments: @sha3_ctx *ctx@ = pointer to context to initialize
323 *
324 * Returns: ---
325 *
326 * Use: Initializes a SHAKE context. The context is initially in
327 * the `absorbing' state: feed it data with @shake_hash@.
328 */
329
330 void shake128_init(shake_ctx *ctx) { init_shake(ctx, 128, 0, 0, 0, 0); }
331 void shake256_init(shake_ctx *ctx) { init_shake(ctx, 256, 0, 0, 0, 0); }
332
333 /* --- @shake_hash@ --- *
334 *
335 * Arguments: @shake_ctx *ctx@ = context to update
336 * @const void *p@ = input buffer
337 * @size_t sz@ = size of input
338 *
339 * Returns: ---
340 *
341 * Use: Feeds input data into a SHAKE context. The context must be
342 * in `absorbing' state.
343 */
344
345 void shake_hash(shake_ctx *ctx, const void *p, size_t sz)
346 { assert(ctx->st == ST_ABSORB); sha3_hash(&ctx->h, p, sz); }
347
348 /* --- @shake_xof@ --- *
349 *
350 * Arguments: @shake_ctx *ctx@ = context to update
351 *
352 * Returns: ---
353 *
354 * Use: Switches the context into `squeezing' state. Use @shake_get@
355 * or @shake_mask@ to extract data.
356 */
357
358 void shake_xof(shake_ctx *ctx)
359 {
360 assert(ctx->st == ST_ABSORB);
361 pad(&ctx->h, ctx->op, 0x80);
362 ctx->st = ST_SQUEEZE;
363 ctx->h.n = ctx->h.r;
364 }
365
366 /* --- @shake_get@ --- *
367 *
368 * Arguments: @shake_ctx *ctx@ = context to update
369 * @void *p@ = output buffer
370 * @size_t sz@ = size of output
371 *
372 * Returns: ---
373 *
374 * Use: Extracts output from a SHAKE context. The context must be
375 * in `squeezing' state.
376 */
377
378 void shake_get(shake_ctx *ctx, void *p, size_t sz)
379 {
380 octet *q = p;
381 size_t left = ctx->h.r - ctx->h.n;
382
383 assert(ctx->st == ST_SQUEEZE);
384 if (left >= sz) {
385 memcpy(q, ctx->h.buf + ctx->h.n, sz);
386 ctx->h.n += sz;
387 return;
388 }
389 if (left) {
390 memcpy(q, ctx->h.buf + ctx->h.n, left);
391 q += left; sz -= left;
392 }
393 while (sz >= ctx->h.r) {
394 step(&ctx->h);
395 squeeze(&ctx->h, q, ctx->h.r/8);
396 q += ctx->h.r; sz -= ctx->h.r;
397 }
398 if (!sz)
399 ctx->h.n = ctx->h.r;
400 else {
401 step(&ctx->h);
402 squeeze(&ctx->h, ctx->h.buf, ctx->h.r/8);
403 memcpy(q, ctx->h.buf, sz);
404 ctx->h.n = sz;
405 }
406 }
407
408 /* --- @shake_mask@ --- *
409 *
410 * Arguments: @shake_ctx *ctx@ = context to update
411 * @const void *src@ = pointer to source data, or null
412 * @void *dest@ = output buffer
413 * @size_t sz@ = size of output
414 *
415 * Returns: ---
416 *
417 * Use: Mask the @src@ data by XORing it with output from the SHAKE
418 * context, writing the result to @dest@. The @src@ and @dest
419 * buffers may be equal but must not otherwise overlap. The
420 * context must be in `squeezing' state.
421 */
422
423 void shake_mask(shake_ctx *ctx, const void *src, void *dest, size_t sz)
424 {
425 const octet *p = src, *pp, *l;
426 octet *q = dest;
427 size_t left = ctx->h.r - ctx->h.n;
428
429 if (!src) { shake_get(ctx, dest, sz); return; }
430
431 assert(ctx->st == ST_SQUEEZE);
432 if (left >= sz) {
433 pp = ctx->h.buf + ctx->h.n; l = q + sz;
434 while (q < l) *q++ = *p++ ^ *pp++;
435 ctx->h.n += sz;
436 return;
437 }
438 if (left) {
439 pp = ctx->h.buf + ctx->h.n; l = q + left;
440 while (q < l) *q++ = *p++ ^ *pp++;
441 sz -= left;
442 }
443 while (sz >= ctx->h.r) {
444 step(&ctx->h);
445 squeeze(&ctx->h, ctx->h.buf, ctx->h.r/8);
446 pp = ctx->h.buf; l = pp + ctx->h.r;
447 while (pp < l) *q++ = *p++ ^ *pp++;
448 sz -= ctx->h.r;
449 }
450 if (!sz)
451 ctx->h.n = ctx->h.r;
452 else {
453 step(&ctx->h);
454 squeeze(&ctx->h, ctx->h.buf, ctx->h.r/8);
455 pp = ctx->h.buf; l = q + sz;
456 while (q < l) *q++ = *p++ ^ *pp++;
457 ctx->h.n = sz;
458 }
459 }
460
461 /* --- @shake_done@ --- *
462 *
463 * Arguments: @shake_ctx *ctx@ = context to update
464 * @void *h@ = where to write the hash
465 * @size_t hsz@ = size of the hash to make
466 *
467 * Returns: ---
468 *
469 * Use: Switches the context into `squeezing' state. Use @shake_get@
470 * or @shake_mask@ to extract data.
471 */
472
473 void shake_done(shake_ctx *ctx, void *h, size_t hsz)
474 { shake_xof(ctx); shake_get(ctx, h, hsz); ctx->st = ST_DEAD; }
475
476 /* --- Hash interface --- */
477
478 typedef struct shake_ghctx {
479 ghash h;
480 shake_ctx c;
481 octet hb[SHAKE256_HASHSZ];
482 } shake_ghctx;
483
484 static const ghash_ops shake128_ghops, shake256_ghops;
485
486 static void shake_ghhash(ghash *h, const void *p, size_t sz)
487 { shake_ghctx *cc = (shake_ghctx *)h; shake_hash(&cc->c, p, sz); }
488
489 static octet *shake_ghdone(ghash *h, void *buf)
490 {
491 shake_ghctx *cc = (shake_ghctx *)h;
492 if (!buf) buf = cc->hb;
493 shake_done(&cc->c, buf, h->ops->c->hashsz);
494 return (buf);
495 }
496
497 static void shake_ghdestroy(ghash *h)
498 { shake_ghctx *cc = (shake_ghctx *)h; BURN(cc); S_DESTROY(cc); }
499
500 static ghash *shake_ghcopy(ghash *h)
501 {
502 shake_ghctx *cc = (shake_ghctx *)h;
503 shake_ghctx *hc = S_CREATE(shake_ghctx);
504 *hc = *cc;
505 return (&hc->h);
506 }
507
508 static ghash *shake128_ghinit(void)
509 {
510 shake_ghctx *cc = S_CREATE(shake_ghctx);
511 cc->h.ops = &shake128_ghops;
512 shake128_init(&cc->c);
513 return (&cc->h);
514 }
515
516 static ghash *shake256_ghinit(void)
517 {
518 shake_ghctx *cc = S_CREATE(shake_ghctx);
519 cc->h.ops = &shake256_ghops;
520 shake256_init(&cc->c);
521 return (&cc->h);
522 }
523
524 const gchash
525 shake128 = { "shake128", SHAKE128_HASHSZ, shake128_ghinit, 168 },
526 shake256 = { "shake256", SHAKE256_HASHSZ, shake256_ghinit, 136 };
527
528 static const ghash_ops
529 shake128_ghops = { &shake128, shake_ghhash, shake_ghdone,
530 shake_ghdestroy, shake_ghcopy },
531 shake256_ghops = { &shake256, shake_ghhash, shake_ghdone,
532 shake_ghdestroy, shake_ghcopy };
533
534 /* --- Cipher interface --- */
535
536 typedef struct shake_gcctx {
537 gcipher gc;
538 shake_ctx c;
539 } shake_gcctx;
540
541 static const gcipher_ops shake128_gcops, shake256_gcops;
542
543 static void shake_gcencdec(gcipher *c, const void *s, void *d, size_t sz)
544 { shake_gcctx *cc = (shake_gcctx *)c; shake_mask(&cc->c, s, d, sz); }
545
546 static void shake_gcdestroy(gcipher *c)
547 { shake_gcctx *cc = (shake_gcctx *)c; BURN(*cc); S_DESTROY(cc); }
548
549 static const gcipher_ops
550 shake128_gcops = { &shake128_xof, shake_gcencdec, shake_gcencdec,
551 shake_gcdestroy, 0, 0 },
552 shake256_gcops = { &shake256_xof, shake_gcencdec, shake_gcencdec,
553 shake_gcdestroy, 0, 0 };
554
555 static gcipher *shake128_gcinit(const void *k, size_t sz)
556 {
557 shake_gcctx *cc = S_CREATE(shake_gcctx);
558 cc->gc.ops = &shake128_gcops;
559 shake128_init(&cc->c); shake_hash(&cc->c, k, sz); shake_xof(&cc->c);
560 return (&cc->gc);
561 }
562
563 static gcipher *shake256_gcinit(const void *k, size_t sz)
564 {
565 shake_gcctx *cc = S_CREATE(shake_gcctx);
566 cc->gc.ops = &shake256_gcops;
567 shake256_init(&cc->c); shake_hash(&cc->c, k, sz); shake_xof(&cc->c);
568 return (&cc->gc);
569 }
570
571 const gccipher
572 shake128_xof = { "shake128-xof", shake128_keysz, 0, shake128_gcinit },
573 shake256_xof = { "shake256-xof", shake256_keysz, 0, shake256_gcinit };
574
575 /* --- Random generator interface --- */
576
577 typedef struct shake_grctx {
578 grand gr;
579 shake_ctx c;
580 } shake_grctx;
581
582 static int shake_grmisc(grand *r, unsigned op, ...)
583 {
584 int rc = 0;
585 switch (op) {
586 case GRAND_CHECK: rc = 0; break;
587 default: GRAND_BADOP; break;
588 }
589 return (rc);
590 }
591
592 static void shake_grdestroy(grand *r)
593 { shake_grctx *cc = (shake_grctx *)r; BURN(cc); S_DESTROY(cc); }
594
595 static octet shake_grbyte(grand *r)
596 {
597 shake_grctx *cc = (shake_grctx *)r;
598 octet o;
599 shake_get(&cc->c, &o, 1);
600 return (o);
601 }
602
603 static uint32 shake_grword(grand *r)
604 {
605 shake_grctx *cc = (shake_grctx *)r;
606 octet b[4];
607 shake_get(&cc->c, &b, 4);
608 return (LOAD32(b));
609 }
610
611 static void shake_grfill(grand *r, void *p, size_t sz)
612 { shake_grctx *cc = (shake_grctx *)r; shake_get(&cc->c, p, sz); }
613
614 static const grand_ops
615 shake128_grops = { "shake128", GRAND_CRYPTO, 0,
616 shake_grmisc, shake_grdestroy, shake_grword,
617 shake_grbyte, shake_grword, grand_defaultrange,
618 shake_grfill },
619 shake256_grops = { "shake256", GRAND_CRYPTO, 0,
620 shake_grmisc, shake_grdestroy, shake_grword,
621 shake_grbyte, shake_grword, grand_defaultrange,
622 shake_grfill },
623 cshake128_grops = { "cshake128", GRAND_CRYPTO, 0,
624 shake_grmisc, shake_grdestroy, shake_grword,
625 shake_grbyte, shake_grword, grand_defaultrange,
626 shake_grfill },
627 cshake256_grops = { "cshake256", GRAND_CRYPTO, 0,
628 shake_grmisc, shake_grdestroy, shake_grword,
629 shake_grbyte, shake_grword, grand_defaultrange,
630 shake_grfill };
631
632 /* --- @shake{128,256}_rand@ --- *
633 *
634 * Arguments: @const void *k@ = pointer to seed material
635 * @size_t sz@ = size of the seed
636 *
637 * Returns: A pseudorandom generator with the given seed.
638 */
639
640 grand *shake128_rand(const void *k, size_t sz)
641 {
642 shake_grctx *cc = S_CREATE(shake_grctx);
643 cc->gr.ops = &shake128_grops;
644 shake128_init(&cc->c); shake_hash(&cc->c, k, sz); shake_xof(&cc->c);
645 return (&cc->gr);
646 }
647
648 grand *shake256_rand(const void *k, size_t sz)
649 {
650 shake_grctx *cc = S_CREATE(shake_grctx);
651 cc->gr.ops = &shake256_grops;
652 shake256_init(&cc->c); shake_hash(&cc->c, k, sz); shake_xof(&cc->c);
653 return (&cc->gr);
654 }
655
656 /* --- @cshake{128,256}_rand@ --- *
657 *
658 * Arguments: @const void *func@ = function name
659 * @size_t fsz@ = length of function name
660 * @const void *perso@ = personalization string
661 * @size_t psz@ = length of personalization string
662 * @const void *k@ = pointer to seed material
663 * @size_t sz@ = size of the seed
664 *
665 * Returns: A pseudorandom generator with the given seed.
666 */
667
668 grand *cshake128_rand(const void *func, size_t fsz,
669 const void *perso, size_t psz,
670 const void *k, size_t sz)
671 {
672 shake_grctx *cc = S_CREATE(shake_grctx);
673 cc->gr.ops = &cshake128_grops;
674 cshake128_init(&cc->c, func, fsz, perso, psz);
675 shake_hash(&cc->c, k, sz); shake_xof(&cc->c);
676 return (&cc->gr);
677 }
678
679 grand *cshake256_rand(const void *func, size_t fsz,
680 const void *perso, size_t psz,
681 const void *k, size_t sz)
682 {
683 shake_grctx *cc = S_CREATE(shake_grctx);
684 cc->gr.ops = &cshake256_grops;
685 cshake256_init(&cc->c, func, fsz, perso, psz);
686 shake_hash(&cc->c, k, sz); shake_xof(&cc->c);
687 return (&cc->gr);
688 }
689
690 /*----- The KMAC variable-length PRF --------------------------------------*/
691
692 typedef shake_ctx kmac_ctx;
693
694 /* --- @kmac{128,256}_init@ --- *
695 *
696 * Arguments: @kmac_ctx *ctx@ = pointer to context to fill in
697 * @const char *perso@ = personalization string, or null
698 * @size_t psz@ = length of personalization string
699 * @const void *k@ = pointer to key material
700 * @size_t sz@ = size of key material
701 *
702 * Returns: ---
703 *
704 * Use: Sets up a KMAC context. Use @kmac_hash@ to feed in the input
705 * message.
706 */
707
708 static void init_kmac(kmac_ctx *ctx,
709 unsigned c0, const void *perso, size_t psz,
710 const void *k, size_t sz)
711 {
712 init_shake(ctx, c0, "KMAC", 4, perso, psz);
713 bytepad_before(ctx); stringenc(ctx, k, sz); bytepad_after(ctx);
714 }
715
716 void kmac128_init(kmac_ctx *ctx, const void *perso, size_t psz,
717 const void *k, size_t sz)
718 { init_kmac(ctx, 128, perso, psz, k, sz); }
719
720 void kmac256_init(kmac_ctx *ctx, const void *perso, size_t psz,
721 const void *k, size_t sz)
722 { init_kmac(ctx, 256, perso, psz, k, sz); }
723
724 /* --- @kmac_xof@ --- *
725 *
726 * Arguments: @kmac_ctx *ctx@ = pointer to context
727 *
728 * Returns: ---
729 *
730 * Use: Marks the end of the message to be processed. The output can
731 * be read using @kmac_get@.
732 */
733
734 void kmac_xof(kmac_ctx *ctx)
735 { rightenc_sz(ctx, 0); shake_xof(ctx); }
736
737 /* --- @kmac_done@ --- *
738 *
739 * Arguments: @kmac_ctx *ctx@ = pointer to context
740 * @void *h@ = where to put the tag
741 * @size_t hsz@ = size of tag to produce
742 *
743 * Returns: ---
744 *
745 * Use: Marks the end of the message to be processed and returns a
746 * tag. Note that the tag value is dependent on the output
747 * size.
748 */
749
750 void kmac_done(kmac_ctx *ctx, void *h, size_t hsz)
751 { rightenc_sz(ctx, 8*hsz); shake_done(ctx, h, hsz); }
752
753 /* --- MAC interface --- */
754
755 typedef struct kmac_ghctx {
756 ghash h;
757 kmac_ctx c;
758 octet hb[KMAC256_TAGSZ];
759 } kmac_ghctx;
760
761 typedef struct kmac_gmctx {
762 gmac m;
763 kmac_ctx c;
764 const ghash_ops *hops;
765 } kmac_gmctx;
766
767 static const ghash_ops kmac128_ghops, kmac256_ghops;
768 static const gmac_ops kmac128_gmops, kmac256_gmops;
769
770 static void kmac_ghhash(ghash *h, const void *p, size_t sz)
771 { kmac_ghctx *cc = (kmac_ghctx *)h; kmac_hash(&cc->c, p, sz); }
772
773 static octet *kmac_ghdone(ghash *h, void *buf)
774 {
775 kmac_ghctx *cc = (kmac_ghctx *)h;
776 if (!buf) buf = cc->hb;
777 kmac_done(&cc->c, buf, cc->h.ops->c->hashsz);
778 return (buf);
779 }
780
781 static void kmac_ghdestroy(ghash *h)
782 { kmac_ghctx *cc = (kmac_ghctx *)h; BURN(cc); S_DESTROY(cc); }
783
784 static ghash *kmac_ghcopy(ghash *h)
785 {
786 kmac_ghctx *cc = (kmac_ghctx *)h;
787 kmac_ghctx *hc = S_CREATE(kmac_ghctx);
788 *hc = *cc;
789 return (&hc->h);
790 }
791
792 static ghash *kmac_ghinit(void)
793 { assert(((void)"Attempt to instantiate an unkeyed MAC", 0)); return (0); }
794
795 static ghash *kmac_gminit(gmac *m)
796 {
797 kmac_gmctx *cc = (kmac_gmctx *)m;
798 kmac_ghctx *hc = S_CREATE(kmac_ghctx);
799 hc->h.ops = cc->hops;
800 hc->c = cc->c;
801 return (&hc->h);
802 }
803
804 static void kmac_gmdestroy(gmac *m)
805 { kmac_gmctx *cc = (kmac_gmctx *)m; BURN(cc); S_DESTROY(cc); }
806
807 static gmac *kmac128_gmkey(const void *k, size_t sz)
808 {
809 kmac_gmctx *cc = S_CREATE(kmac_gmctx);
810 cc->m.ops = &kmac128_gmops; cc->hops = &kmac128_ghops;
811 kmac128_init(&cc->c, 0, 0, k, sz);
812 return (&cc->m);
813 }
814
815 static gmac *kmac256_gmkey(const void *k, size_t sz)
816 {
817 kmac_gmctx *cc = S_CREATE(kmac_gmctx);
818 cc->m.ops = &kmac256_gmops; cc->hops = &kmac256_ghops;
819 kmac256_init(&cc->c, 0, 0, k, sz);
820 return (&cc->m);
821 }
822
823 static const gchash
824 kmac128_ghcls = { "kmac128", KMAC128_TAGSZ, kmac_ghinit, 168 },
825 kmac256_ghcls = { "kmac256", KMAC256_TAGSZ, kmac_ghinit, 136 };
826
827 const gcmac
828 kmac128 = { "kmac128", KMAC128_TAGSZ, kmac128_keysz, kmac128_gmkey },
829 kmac256 = { "kmac256", KMAC256_TAGSZ, kmac256_keysz, kmac256_gmkey };
830
831 static const ghash_ops
832 kmac128_ghops = { &kmac128_ghcls, kmac_ghhash, kmac_ghdone,
833 kmac_ghdestroy, kmac_ghcopy },
834 kmac256_ghops = { &kmac256_ghcls, kmac_ghhash, kmac_ghdone,
835 kmac_ghdestroy, kmac_ghcopy };
836
837 static const gmac_ops
838 kmac128_gmops = { &kmac128, kmac_gminit, kmac_gmdestroy },
839 kmac256_gmops = { &kmac256, kmac_gminit, kmac_gmdestroy };
840
841 /* --- Random generator XOF interface --- */
842
843 typedef struct kmac_grctx {
844 grand gr;
845 kmac_ctx k, c;
846 } kmac_grctx;
847
848 static int kmac_grmisc(grand *r, unsigned op, ...)
849 {
850 kmac_grctx *cc = (kmac_grctx *)r;
851 int rc = 0;
852 octet buf[64];
853 va_list ap;
854 int i;
855 uint32 u;
856 grand *rr;
857 const void *p;
858 size_t sz;
859
860 va_start(ap, op);
861 switch (op) {
862 case GRAND_CHECK:
863 op = va_arg(ap, unsigned);
864 switch (op) {
865 case GRAND_SEEDINT: case GRAND_SEEDUINT32:
866 case GRAND_SEEDBLOCK: case GRAND_SEEDRAND:
867 rc = 1; break;
868 default:
869 rc = 0; break;
870 }
871 break;
872 case GRAND_SEEDINT:
873 i = va_arg(ap, int); STORE32_L(buf, i); p = buf; sz = 4; goto seed;
874 case GRAND_SEEDUINT32:
875 u = va_arg(ap, uint32); STORE32_L(buf, u); p = buf; sz = 4; goto seed;
876 case GRAND_SEEDRAND:
877 rr = va_arg(ap, grand *);
878 p = buf; sz = (200 - cc->c.h.r)/2; GR_FILL(rr, buf, sz); goto seed;
879 case GRAND_SEEDBLOCK:
880 p = va_arg(ap, const void *); sz = va_arg(ap, size_t);
881 seed:
882 cc->c = cc->k;
883 kmac_hash(&cc->c, p, sz);
884 kmac_xof(&cc->c);
885 break;
886 default: GRAND_BADOP; break;
887 }
888 return (rc);
889 }
890
891 static void kmac_grdestroy(grand *r)
892 { kmac_grctx *cc = (kmac_grctx *)r; BURN(cc); S_DESTROY(cc); }
893
894 static octet kmac_grbyte(grand *r)
895 {
896 kmac_grctx *cc = (kmac_grctx *)r;
897 octet o;
898 kmac_get(&cc->c, &o, 1);
899 return (o);
900 }
901
902 static uint32 kmac_grword(grand *r)
903 {
904 kmac_grctx *cc = (kmac_grctx *)r;
905 octet b[4];
906 kmac_get(&cc->c, &b, 4);
907 return (LOAD32(b));
908 }
909
910 static void kmac_grfill(grand *r, void *p, size_t sz)
911 { kmac_grctx *cc = (kmac_grctx *)r; kmac_get(&cc->c, p, sz); }
912
913 static const grand_ops
914 kmac128_grops = { "kmac128", GRAND_CRYPTO, 0,
915 kmac_grmisc, kmac_grdestroy, kmac_grword,
916 kmac_grbyte, kmac_grword, grand_defaultrange,
917 kmac_grfill },
918 kmac256_grops = { "kmac256", GRAND_CRYPTO, 0,
919 kmac_grmisc, kmac_grdestroy, kmac_grword,
920 kmac_grbyte, kmac_grword, grand_defaultrange,
921 kmac_grfill };
922
923 /* --- @kmac{128,256}_rand@ --- *
924 *
925 * Arguments: @const void *perso@ = personalization string, or null
926 * @size_t psz@ = length of personalization string
927 * @const void *k@ = pointer to seed material
928 * @size_t sz@ = size of the seed
929 *
930 * Returns: A pseudorandom generator with the given key.
931 *
932 * Use: The generator processes an empty message by default, but this
933 * can be changed by seeding it.
934 */
935
936 grand *kmac128_rand(const void *perso, size_t psz, const void *k, size_t sz)
937 {
938 kmac_grctx *cc = S_CREATE(kmac_grctx);
939 cc->gr.ops = &kmac128_grops;
940 kmac128_init(&cc->k, perso, psz, k, sz);
941 cc->c = cc->k; kmac_xof(&cc->c);
942 return (&cc->gr);
943 }
944
945 grand *kmac256_rand(const void *perso, size_t psz, const void *k, size_t sz)
946 {
947 kmac_grctx *cc = S_CREATE(kmac_grctx);
948 cc->gr.ops = &kmac256_grops;
949 kmac256_init(&cc->k, perso, psz, k, sz);
950 cc->c = cc->k; kmac_xof(&cc->c);
951 return (&cc->gr);
952 }
953
954 /*----- Test rig ----------------------------------------------------------*/
955
956 #ifdef TEST_RIG
957
958 #include <stdio.h>
959
960 #include <mLib/macros.h>
961 #include <mLib/report.h>
962 #include <mLib/testrig.h>
963
964 HASHES(HASH_VERIFYX)
965
966 static int vrf_sha3_mct(void (*initfn)(sha3_ctx *),
967 int n, dstr *in, dstr *out)
968 {
969 sha3_ctx ctx;
970 dstr d = DSTR_INIT;
971 int ok = 1;
972 int i;
973
974 if (in->len != out->len) die(1, "inconsistent lengths");
975 dstr_ensure(&d, out->len); d.len = out->len;
976 memcpy(d.buf, in->buf, in->len);
977 for (i = 0; i < n; i++) {
978 initfn(&ctx);
979 sha3_hash(&ctx, d.buf, d.len);
980 sha3_done(&ctx, d.buf);
981 }
982
983 if (MEMCMP(d.buf, !=, out->buf, out->len)) {
984 ok = 0;
985 printf("\nfail\n\tsteps = %d\n\tinput = ", n);
986 type_hex.dump(in, stdout);
987 printf("\n\texpected = ");
988 type_hex.dump(out, stdout);
989 fputs("\n\tcomputed = ", stdout);
990 type_hex.dump(&d, stdout);
991 putchar('\n');
992 }
993
994 dstr_destroy(&d);
995 return (ok);
996 }
997
998 #define VRF_MCT(PRE, pre, name) \
999 static int vrf_##pre##_mct(dstr *v) \
1000 { return (vrf_sha3_mct(pre##_init, *(int *)v[0].buf, &v[1], &v[2])); }
1001 HASHES(VRF_MCT)
1002 #undef VRF_MCT
1003
1004 static int vrf_shaky(void (*initfn)(shake_ctx *,
1005 const void *, size_t,
1006 const void *, size_t),
1007 dstr *func, dstr *perso,
1008 dstr *m, dstr *want)
1009 {
1010 shake_ctx ctx;
1011 dstr d = DSTR_INIT;
1012 int ok = 1;
1013 int i;
1014 const int *ip;
1015 size_t sz;
1016 octet *p;
1017 static const int szs[] = { 1, 7, 192, -1, 0 };
1018
1019 dstr_ensure(&d, want->len); d.len = want->len;
1020 for (ip = szs; *ip; ip++) {
1021 initfn(&ctx,
1022 func ? func->buf : 0, func ? func->len : 0,
1023 perso ? perso->buf : 0, perso ? perso->len : 0);
1024 p = (octet *)m->buf; sz = m->len;
1025 i = (*ip == -1 || *ip > sz) ? sz : *ip;
1026 while (sz) {
1027 if (i > sz) i = sz;
1028 shake_hash(&ctx, p, i);
1029 p += i; sz -= i;
1030 }
1031 shake_xof(&ctx);
1032
1033 p = (octet *)d.buf; sz = d.len;
1034 i = (*ip == -1 || *ip > sz) ? sz : *ip;
1035 while (sz) {
1036 if (i > sz) i = sz;
1037 shake_get(&ctx, p, i);
1038 p += i; sz -= i;
1039 }
1040
1041 if (MEMCMP(d.buf, !=, want->buf, want->len)) {
1042 ok = 0;
1043 printf("\nfail (get):\n\tstep = %i\n\tinput = ", *ip);
1044 type_hex.dump(m, stdout);
1045 if (func) printf("\n\tfunction = `%s'", func->buf);
1046 if (perso) printf("\n\tperso = `%s'", perso->buf);
1047 printf("\n\texpected = ");
1048 type_hex.dump(want, stdout);
1049 fputs("\n\tcomputed = ", stdout);
1050 type_hex.dump(&d, stdout);
1051 putchar('\n');
1052 }
1053
1054 initfn(&ctx,
1055 func ? func->buf : 0, func ? func->len : 0,
1056 perso ? perso->buf : 0, perso ? perso->len : 0);
1057 p = (octet *)m->buf; sz = m->len;
1058 i = (*ip == -1 || *ip > sz) ? sz : *ip;
1059 while (sz) {
1060 if (i > sz) i = sz;
1061 shake_hash(&ctx, p, i);
1062 p += i; sz -= i;
1063 }
1064 shake_xof(&ctx);
1065
1066 memset(d.buf, 0, d.len);
1067 p = (octet *)d.buf; sz = d.len;
1068 i = (*ip == -1 || *ip > sz) ? sz : *ip;
1069 while (sz) {
1070 if (i > sz) i = sz;
1071 shake_mask(&ctx, p, p, i);
1072 p += i; sz -= i;
1073 }
1074
1075 if (MEMCMP(d.buf, !=, want->buf, want->len)) {
1076 ok = 0;
1077 printf("\nfail (mask):\n\tstep = %i\n\tinput = ", *ip);
1078 type_hex.dump(m, stdout);
1079 if (func) printf("\n\tfunction = `%s'", func->buf);
1080 if (perso) printf("\n\tperso = `%s'", perso->buf);
1081 printf("\n\texpected = ");
1082 type_hex.dump(want, stdout);
1083 fputs("\n\tcomputed = ", stdout);
1084 type_hex.dump(&d, stdout);
1085 putchar('\n');
1086 }
1087 }
1088
1089 dstr_destroy(&d);
1090 return (ok);
1091 }
1092
1093 static int vrf_cshake128(dstr *v)
1094 {
1095 return (vrf_shaky(cshake128_init, &v[0], &v[1], &v[2], &v[3]));
1096 }
1097
1098 static int vrf_cshake256(dstr *v)
1099 {
1100 return (vrf_shaky(cshake256_init, &v[0], &v[1], &v[2], &v[3]));
1101 }
1102
1103 static void shake128_init_adaptor(shake_ctx *ctx,
1104 const void *func, size_t fsz,
1105 const void *perso, size_t psz)
1106 { assert(!fsz); assert(!psz); shake128_init(ctx);}
1107
1108 static void shake256_init_adaptor(shake_ctx *ctx,
1109 const void *func, size_t fsz,
1110 const void *perso, size_t psz)
1111 { assert(!fsz); assert(!psz); shake256_init(ctx);}
1112
1113 static int vrf_shake128(dstr *v)
1114 { return (vrf_shaky(shake128_init_adaptor, 0, 0, &v[0], &v[1])); }
1115
1116 static int vrf_shake256(dstr *v)
1117 { return (vrf_shaky(shake256_init_adaptor, 0, 0, &v[0], &v[1])); }
1118
1119 static int vrf_kmac(void (*initfn)(kmac_ctx *, const void *, size_t,
1120 const void *, size_t),
1121 dstr *perso, int tsz,
1122 dstr *k, dstr *m, dstr *want)
1123 {
1124 kmac_ctx ctx;
1125 dstr d = DSTR_INIT;
1126 int ok = 1;
1127
1128 if (tsz && tsz != want->len) die(1, "inconsistent tag length request");
1129 dstr_ensure(&d, want->len); d.len = want->len;
1130 initfn(&ctx, perso->buf, perso->len, k->buf, k->len);
1131 kmac_hash(&ctx, m->buf, m->len);
1132 if (tsz) kmac_done(&ctx, d.buf, tsz);
1133 else { kmac_xof(&ctx); kmac_get(&ctx, d.buf, d.len); }
1134
1135 if (MEMCMP(d.buf, !=, want->buf, want->len)) {
1136 ok = 0;
1137 printf("\nfail");
1138 printf("\n\tperso = `%s'", perso->buf);
1139 printf("\n\ttag size = %d", tsz);
1140 printf("\n\tkey = "); type_hex.dump(k, stdout);
1141 printf("\n\tinput = "); type_hex.dump(m, stdout);
1142 printf("\n\texpected = "); type_hex.dump(want, stdout);
1143 fputs("\n\tcomputed = ", stdout); type_hex.dump(&d, stdout);
1144 putchar('\n');
1145 }
1146
1147 dstr_destroy(&d);
1148 return (ok);
1149 }
1150
1151 static int vrf_kmac128(dstr *v)
1152 {
1153 return (vrf_kmac(kmac128_init, &v[0], *(int *)v[1].buf,
1154 &v[2], &v[3], &v[4]));
1155 }
1156
1157 static int vrf_kmac256(dstr *v)
1158 {
1159 return (vrf_kmac(kmac256_init, &v[0], *(int *)v[1].buf,
1160 &v[2], &v[3], &v[4]));
1161 }
1162
1163 static const test_chunk defs[] = {
1164 HASHES(HASH_TESTDEFSX)
1165 #define VRF_MCTDEF(PRE, pre, name) \
1166 { name "-mct", vrf_##pre##_mct, \
1167 { &type_int, &type_hex, &type_hex, 0 } },
1168 HASHES(VRF_MCTDEF)
1169 #undef VRF_MCTDEF
1170 { "shake128", vrf_shake128, { &type_hex, &type_hex, 0 } },
1171 { "shake256", vrf_shake256, { &type_hex, &type_hex, 0 } },
1172 { "cshake128", vrf_cshake128,
1173 { &type_string, &type_string, &type_hex, &type_hex, 0 } },
1174 { "cshake256", vrf_cshake256,
1175 { &type_string, &type_string, &type_hex, &type_hex, 0 } },
1176 { "kmac128", vrf_kmac128,
1177 { &type_string, &type_int, &type_hex, &type_hex, &type_hex, 0 } },
1178 { "kmac256", vrf_kmac256,
1179 { &type_string, &type_int, &type_hex, &type_hex, &type_hex, 0 } },
1180 { 0, 0, { 0 } }
1181 };
1182
1183 int main(int argc, char *argv[])
1184 {
1185 test_run(argc, argv, defs, SRCDIR"/t/sha3");
1186 return (0);
1187 }
1188
1189 #endif
1190
1191 /*----- That's all, folks -------------------------------------------------*/