3 * The SHA3 algorithm family
5 * (c) 2017 Straylight/Edgeware
8 /*----- Licensing notice --------------------------------------------------*
10 * This file is part of Catacomb.
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.
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.
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,
28 /*----- Header files ------------------------------------------------------*/
35 #include "ghash-def.h"
38 /*----- General utilities -------------------------------------------------*/
40 static void absorb(sha3_ctx *ctx, const octet *p, unsigned r)
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);
50 static void step(sha3_ctx *ctx) { keccak1600_p(&ctx->s, &ctx->s, 24); }
52 static void pad(sha3_ctx *ctx, unsigned lo, unsigned hi)
54 size_t spare = ctx->r - ctx->n;
57 ctx->buf[ctx->n] = lo | hi;
59 ctx->buf[ctx->n] = lo;
60 ctx->buf[ctx->r - 1] = hi;
61 memset(ctx->buf + ctx->n + 1, 0, spare - 2);
63 absorb(ctx, ctx->buf, ctx->r/8);
66 static void squeeze(sha3_ctx *ctx, octet *p, unsigned r)
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); */
82 enum { ST_ABSORB, ST_SQUEEZE, ST_DEAD };
84 /*----- The SHA3 algorithms -----------------------------------------------*/
86 /* --- @sha3_{224,256,384,512}_init@ --- *
88 * Arguments: @sha3_ctx *ctx@ = pointer to context block to initialize
92 * Use: Initializes a SHA3 hashing context for use.
95 static void init_sha3(sha3_ctx *ctx, unsigned w)
97 keccak1600_init(&ctx->s);
98 ctx->w = w/8; ctx->r = (1600 - 2*w)/8; ctx->n = 0;
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); }
106 /* --- @sha3_hash@ --- *
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
114 * Use: Hashes a buffer of data. The buffer may be of any size and
118 void sha3_hash(sha3_ctx *ctx, const void *p, size_t sz)
121 size_t spare = ctx->r - ctx->n;
124 memcpy(ctx->buf + ctx->n, q, sz);
129 memcpy(ctx->buf + ctx->n, q, spare);
130 absorb(ctx, ctx->buf, ctx->r/8);
132 q += spare; sz -= spare;
134 while (sz >= ctx->r) {
135 absorb(ctx, q, ctx->r/8);
137 q += ctx->r; sz -= ctx->r;
139 if (sz) memcpy(ctx->buf, q, sz);
143 /* --- @sha3_done@ --- *
145 * Arguments: @sha3_ctx *ctx@ = pointer to context block
146 * @void *hash@ = pointer to output buffer
150 * Use: Returns the hash of the data read so far.
153 void sha3_done(sha3_ctx *ctx, void *hash)
155 pad(ctx, OP_SHA3, 0x80);
159 squeeze(ctx, hash, ctx->w/8);
161 squeeze(ctx, ctx->buf, (ctx->w + 7)/8);
162 memcpy(hash, ctx->buf, ctx->w);
166 /* --- @sha3_{224,256,384,512}_set@ --- *
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
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.
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.
183 static void set(sha3_ctx *ctx, const void *buf,
184 unsigned long count, unsigned w)
187 memcpy(ctx, buf, sizeof(*ctx));
189 static const char *prefix = "Catacomb SHA3 NMAC kludge";
191 sha3_hash(ctx, prefix, sizeof(prefix));
192 sha3_hash(ctx, buf, SHA3_STATESZ);
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); }
205 /* --- @sha3_state@ --- *
207 * Arguments: @sha3_ctx *ctx@ = pointer to context block
208 * @void *state@ = pointer to buffer for current state
210 * Returns: A value which is meaningful to @sha3_..._set@.
212 * Use: Returns the current state of the hash function such that it
213 * can be passed to @sha3_..._set@.
216 unsigned long sha3_state(sha3_ctx *ctx, void *state)
217 { memcpy(state, ctx, sizeof(*ctx)); return (1); }
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")
226 /*----- The cSHAKE XOF algorithm ------------------------------------------*/
228 static void leftenc_sz(shake_ctx *ctx, size_t n)
234 SET64(t, ((n&~MASK32) >> 16) >> 16, n&MASK32);
235 STORE64_B_(b + 1, t);
236 for (i = 1; i < 8 && !b[i]; i++);
238 shake_hash(ctx, b + i, 9 - i);
241 static void rightenc_sz(shake_ctx *ctx, size_t n)
247 SET64(t, ((n&~MASK32) >> 16) >> 16, n&MASK32);
249 for (i = 0; i < 7 && !b[i]; i++);
251 shake_hash(ctx, b + i, 9 - i);
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); }
257 static void bytepad_before(shake_ctx *ctx)
258 { leftenc_sz(ctx, ctx->h.r); }
260 static void bytepad_after(shake_ctx *ctx)
265 pad = 8 - ctx->h.n%8;
266 memset(ctx->h.buf + ctx->h.n, 0, pad);
270 absorb(&ctx->h, ctx->h.buf, ctx->h.n/8);
271 step(&ctx->h); ctx->h.n = 0;
276 shake128_keysz[] = { KSZ_ANY, SHAKE128_KEYSZ },
277 shake256_keysz[] = { KSZ_ANY, SHAKE256_KEYSZ };
279 /* --- @cshake{128,256}_init@ --- *
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
289 * Use: Initializes a cSHAKE context. The context is initially in
290 * the `absorbing' state: feed it data with @shake_hash@.
293 static void init_shake(shake_ctx *ctx, unsigned c0,
294 const void *func, size_t fsz,
295 const void *perso, size_t psz)
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;
303 stringenc(ctx, func, fsz);
304 stringenc(ctx, perso, psz);
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); }
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); }
320 /* --- @shake{128,256}_init@ --- *
322 * Arguments: @sha3_ctx *ctx@ = pointer to context to initialize
326 * Use: Initializes a SHAKE context. The context is initially in
327 * the `absorbing' state: feed it data with @shake_hash@.
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); }
333 /* --- @shake_hash@ --- *
335 * Arguments: @shake_ctx *ctx@ = context to update
336 * @const void *p@ = input buffer
337 * @size_t sz@ = size of input
341 * Use: Feeds input data into a SHAKE context. The context must be
342 * in `absorbing' state.
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); }
348 /* --- @shake_xof@ --- *
350 * Arguments: @shake_ctx *ctx@ = context to update
354 * Use: Switches the context into `squeezing' state. Use @shake_get@
355 * or @shake_mask@ to extract data.
358 void shake_xof(shake_ctx *ctx)
360 assert(ctx->st == ST_ABSORB);
361 pad(&ctx->h, ctx->op, 0x80);
362 ctx->st = ST_SQUEEZE;
366 /* --- @shake_get@ --- *
368 * Arguments: @shake_ctx *ctx@ = context to update
369 * @void *p@ = output buffer
370 * @size_t sz@ = size of output
374 * Use: Extracts output from a SHAKE context. The context must be
375 * in `squeezing' state.
378 void shake_get(shake_ctx *ctx, void *p, size_t sz)
381 size_t left = ctx->h.r - ctx->h.n;
383 assert(ctx->st == ST_SQUEEZE);
385 memcpy(q, ctx->h.buf + ctx->h.n, sz);
390 memcpy(q, ctx->h.buf + ctx->h.n, left);
391 q += left; sz -= left;
393 while (sz >= ctx->h.r) {
395 squeeze(&ctx->h, q, ctx->h.r/8);
396 q += ctx->h.r; sz -= ctx->h.r;
402 squeeze(&ctx->h, ctx->h.buf, ctx->h.r/8);
403 memcpy(q, ctx->h.buf, sz);
408 /* --- @shake_mask@ --- *
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
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.
423 void shake_mask(shake_ctx *ctx, const void *src, void *dest, size_t sz)
425 const octet *p = src, *pp, *l;
427 size_t left = ctx->h.r - ctx->h.n;
429 if (!src) { shake_get(ctx, dest, sz); return; }
431 assert(ctx->st == ST_SQUEEZE);
433 pp = ctx->h.buf + ctx->h.n; l = q + sz;
434 while (q < l) *q++ = *p++ ^ *pp++;
439 pp = ctx->h.buf + ctx->h.n; l = q + left;
440 while (q < l) *q++ = *p++ ^ *pp++;
443 while (sz >= ctx->h.r) {
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++;
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++;
461 /* --- @shake_done@ --- *
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
469 * Use: Switches the context into `squeezing' state. Use @shake_get@
470 * or @shake_mask@ to extract data.
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; }
476 /* --- Hash interface --- */
478 typedef struct shake_ghctx {
481 octet hb[SHAKE256_HASHSZ];
484 static const ghash_ops shake128_ghops, shake256_ghops;
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); }
489 static octet *shake_ghdone(ghash *h, void *buf)
491 shake_ghctx *cc = (shake_ghctx *)h;
492 if (!buf) buf = cc->hb;
493 shake_done(&cc->c, buf, h->ops->c->hashsz);
497 static void shake_ghdestroy(ghash *h)
498 { shake_ghctx *cc = (shake_ghctx *)h; BURN(cc); S_DESTROY(cc); }
500 static ghash *shake_ghcopy(ghash *h)
502 shake_ghctx *cc = (shake_ghctx *)h;
503 shake_ghctx *hc = S_CREATE(shake_ghctx);
508 static ghash *shake128_ghinit(void)
510 shake_ghctx *cc = S_CREATE(shake_ghctx);
511 cc->h.ops = &shake128_ghops;
512 shake128_init(&cc->c);
516 static ghash *shake256_ghinit(void)
518 shake_ghctx *cc = S_CREATE(shake_ghctx);
519 cc->h.ops = &shake256_ghops;
520 shake256_init(&cc->c);
525 shake128 = { "shake128", SHAKE128_HASHSZ, shake128_ghinit, 168 },
526 shake256 = { "shake256", SHAKE256_HASHSZ, shake256_ghinit, 136 };
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 };
534 /* --- Cipher interface --- */
536 typedef struct shake_gcctx {
541 static const gcipher_ops shake128_gcops, shake256_gcops;
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); }
546 static void shake_gcdestroy(gcipher *c)
547 { shake_gcctx *cc = (shake_gcctx *)c; BURN(*cc); S_DESTROY(cc); }
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 };
555 static gcipher *shake128_gcinit(const void *k, size_t sz)
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);
563 static gcipher *shake256_gcinit(const void *k, size_t sz)
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);
572 shake128_xof = { "shake128-xof", shake128_keysz, 0, shake128_gcinit },
573 shake256_xof = { "shake256-xof", shake256_keysz, 0, shake256_gcinit };
575 /* --- Random generator interface --- */
577 typedef struct shake_grctx {
582 static int shake_grmisc(grand *r, unsigned op, ...)
586 case GRAND_CHECK: rc = 0; break;
587 default: GRAND_BADOP; break;
592 static void shake_grdestroy(grand *r)
593 { shake_grctx *cc = (shake_grctx *)r; BURN(cc); S_DESTROY(cc); }
595 static octet shake_grbyte(grand *r)
597 shake_grctx *cc = (shake_grctx *)r;
599 shake_get(&cc->c, &o, 1);
603 static uint32 shake_grword(grand *r)
605 shake_grctx *cc = (shake_grctx *)r;
607 shake_get(&cc->c, &b, 4);
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); }
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,
619 shake256_grops = { "shake256", GRAND_CRYPTO, 0,
620 shake_grmisc, shake_grdestroy, shake_grword,
621 shake_grbyte, shake_grword, grand_defaultrange,
623 cshake128_grops = { "cshake128", GRAND_CRYPTO, 0,
624 shake_grmisc, shake_grdestroy, shake_grword,
625 shake_grbyte, shake_grword, grand_defaultrange,
627 cshake256_grops = { "cshake256", GRAND_CRYPTO, 0,
628 shake_grmisc, shake_grdestroy, shake_grword,
629 shake_grbyte, shake_grword, grand_defaultrange,
632 /* --- @shake{128,256}_rand@ --- *
634 * Arguments: @const void *k@ = pointer to seed material
635 * @size_t sz@ = size of the seed
637 * Returns: A pseudorandom generator with the given seed.
640 grand *shake128_rand(const void *k, size_t sz)
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);
648 grand *shake256_rand(const void *k, size_t sz)
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);
656 /* --- @cshake{128,256}_rand@ --- *
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
665 * Returns: A pseudorandom generator with the given seed.
668 grand *cshake128_rand(const void *func, size_t fsz,
669 const void *perso, size_t psz,
670 const void *k, size_t sz)
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);
679 grand *cshake256_rand(const void *func, size_t fsz,
680 const void *perso, size_t psz,
681 const void *k, size_t sz)
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);
690 /*----- The KMAC variable-length PRF --------------------------------------*/
692 typedef shake_ctx kmac_ctx;
694 /* --- @kmac{128,256}_init@ --- *
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
704 * Use: Sets up a KMAC context. Use @kmac_hash@ to feed in the input
708 static void init_kmac(kmac_ctx *ctx,
709 unsigned c0, const void *perso, size_t psz,
710 const void *k, size_t sz)
712 init_shake(ctx, c0, "KMAC", 4, perso, psz);
713 bytepad_before(ctx); stringenc(ctx, k, sz); bytepad_after(ctx);
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); }
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); }
724 /* --- @kmac_xof@ --- *
726 * Arguments: @kmac_ctx *ctx@ = pointer to context
730 * Use: Marks the end of the message to be processed. The output can
731 * be read using @kmac_get@.
734 void kmac_xof(kmac_ctx *ctx)
735 { rightenc_sz(ctx, 0); shake_xof(ctx); }
737 /* --- @kmac_done@ --- *
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
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
750 void kmac_done(kmac_ctx *ctx, void *h, size_t hsz)
751 { rightenc_sz(ctx, 8*hsz); shake_done(ctx, h, hsz); }
753 /* --- MAC interface --- */
755 typedef struct kmac_ghctx {
758 octet hb[KMAC256_TAGSZ];
761 typedef struct kmac_gmctx {
764 const ghash_ops *hops;
767 static const ghash_ops kmac128_ghops, kmac256_ghops;
768 static const gmac_ops kmac128_gmops, kmac256_gmops;
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); }
773 static octet *kmac_ghdone(ghash *h, void *buf)
775 kmac_ghctx *cc = (kmac_ghctx *)h;
776 if (!buf) buf = cc->hb;
777 kmac_done(&cc->c, buf, cc->h.ops->c->hashsz);
781 static void kmac_ghdestroy(ghash *h)
782 { kmac_ghctx *cc = (kmac_ghctx *)h; BURN(cc); S_DESTROY(cc); }
784 static ghash *kmac_ghcopy(ghash *h)
786 kmac_ghctx *cc = (kmac_ghctx *)h;
787 kmac_ghctx *hc = S_CREATE(kmac_ghctx);
792 static ghash *kmac_ghinit(void)
793 { assert(((void)"Attempt to instantiate an unkeyed MAC", 0)); return (0); }
795 static ghash *kmac_gminit(gmac *m)
797 kmac_gmctx *cc = (kmac_gmctx *)m;
798 kmac_ghctx *hc = S_CREATE(kmac_ghctx);
799 hc->h.ops = cc->hops;
804 static void kmac_gmdestroy(gmac *m)
805 { kmac_gmctx *cc = (kmac_gmctx *)m; BURN(cc); S_DESTROY(cc); }
807 static gmac *kmac128_gmkey(const void *k, size_t sz)
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);
815 static gmac *kmac256_gmkey(const void *k, size_t sz)
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);
824 kmac128_ghcls = { "kmac128", KMAC128_TAGSZ, kmac_ghinit, 168 },
825 kmac256_ghcls = { "kmac256", KMAC256_TAGSZ, kmac_ghinit, 136 };
828 kmac128 = { "kmac128", KMAC128_TAGSZ, kmac128_keysz, kmac128_gmkey },
829 kmac256 = { "kmac256", KMAC256_TAGSZ, kmac256_keysz, kmac256_gmkey };
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 };
837 static const gmac_ops
838 kmac128_gmops = { &kmac128, kmac_gminit, kmac_gmdestroy },
839 kmac256_gmops = { &kmac256, kmac_gminit, kmac_gmdestroy };
841 /* --- Random generator XOF interface --- */
843 typedef struct kmac_grctx {
848 static int kmac_grmisc(grand *r, unsigned op, ...)
850 kmac_grctx *cc = (kmac_grctx *)r;
863 op = va_arg(ap, unsigned);
865 case GRAND_SEEDINT: case GRAND_SEEDUINT32:
866 case GRAND_SEEDBLOCK: case GRAND_SEEDRAND:
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;
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);
883 kmac_hash(&cc->c, p, sz);
886 default: GRAND_BADOP; break;
891 static void kmac_grdestroy(grand *r)
892 { kmac_grctx *cc = (kmac_grctx *)r; BURN(cc); S_DESTROY(cc); }
894 static octet kmac_grbyte(grand *r)
896 kmac_grctx *cc = (kmac_grctx *)r;
898 kmac_get(&cc->c, &o, 1);
902 static uint32 kmac_grword(grand *r)
904 kmac_grctx *cc = (kmac_grctx *)r;
906 kmac_get(&cc->c, &b, 4);
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); }
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,
918 kmac256_grops = { "kmac256", GRAND_CRYPTO, 0,
919 kmac_grmisc, kmac_grdestroy, kmac_grword,
920 kmac_grbyte, kmac_grword, grand_defaultrange,
923 /* --- @kmac{128,256}_rand@ --- *
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
930 * Returns: A pseudorandom generator with the given key.
932 * Use: The generator processes an empty message by default, but this
933 * can be changed by seeding it.
936 grand *kmac128_rand(const void *perso, size_t psz, const void *k, size_t sz)
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);
945 grand *kmac256_rand(const void *perso, size_t psz, const void *k, size_t sz)
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);
954 /*----- Test rig ----------------------------------------------------------*/
960 #include <mLib/report.h>
961 #include <mLib/testrig.h>
965 static int vrf_sha3_mct(void (*initfn)(sha3_ctx *),
966 int n, dstr *in, dstr *out)
973 if (in->len != out->len) die(1, "inconsistent lengths");
974 dstr_ensure(&d, out->len); d.len = out->len;
975 memcpy(d.buf, in->buf, in->len);
976 for (i = 0; i < n; i++) {
978 sha3_hash(&ctx, d.buf, d.len);
979 sha3_done(&ctx, d.buf);
982 if (memcmp(d.buf, out->buf, out->len) != 0) {
984 printf("\nfail\n\tsteps = %d\n\tinput = ", n);
985 type_hex.dump(in, stdout);
986 printf("\n\texpected = ");
987 type_hex.dump(out, stdout);
988 fputs("\n\tcomputed = ", stdout);
989 type_hex.dump(&d, stdout);
997 #define VRF_MCT(PRE, pre, name) \
998 static int vrf_##pre##_mct(dstr *v) \
999 { return (vrf_sha3_mct(pre##_init, *(int *)v[0].buf, &v[1], &v[2])); }
1003 static int vrf_shaky(void (*initfn)(shake_ctx *,
1004 const void *, size_t,
1005 const void *, size_t),
1006 dstr *func, dstr *perso,
1007 dstr *m, dstr *want)
1016 static const int szs[] = { 1, 7, 192, -1, 0 };
1018 dstr_ensure(&d, want->len); d.len = want->len;
1019 for (ip = szs; *ip; ip++) {
1021 func ? func->buf : 0, func ? func->len : 0,
1022 perso ? perso->buf : 0, perso ? perso->len : 0);
1023 p = (octet *)m->buf; sz = m->len;
1024 i = (*ip == -1 || *ip > sz) ? sz : *ip;
1027 shake_hash(&ctx, p, i);
1032 p = (octet *)d.buf; sz = d.len;
1033 i = (*ip == -1 || *ip > sz) ? sz : *ip;
1036 shake_get(&ctx, p, i);
1040 if (memcmp(d.buf, want->buf, want->len) != 0) {
1042 printf("\nfail (get):\n\tstep = %i\n\tinput = ", *ip);
1043 type_hex.dump(m, stdout);
1044 if (func) printf("\n\tfunction = `%s'", func->buf);
1045 if (perso) printf("\n\tperso = `%s'", perso->buf);
1046 printf("\n\texpected = ");
1047 type_hex.dump(want, stdout);
1048 fputs("\n\tcomputed = ", stdout);
1049 type_hex.dump(&d, stdout);
1054 func ? func->buf : 0, func ? func->len : 0,
1055 perso ? perso->buf : 0, perso ? perso->len : 0);
1056 p = (octet *)m->buf; sz = m->len;
1057 i = (*ip == -1 || *ip > sz) ? sz : *ip;
1060 shake_hash(&ctx, p, i);
1065 memset(d.buf, 0, d.len);
1066 p = (octet *)d.buf; sz = d.len;
1067 i = (*ip == -1 || *ip > sz) ? sz : *ip;
1070 shake_mask(&ctx, p, p, i);
1074 if (memcmp(d.buf, want->buf, want->len) != 0) {
1076 printf("\nfail (mask):\n\tstep = %i\n\tinput = ", *ip);
1077 type_hex.dump(m, stdout);
1078 if (func) printf("\n\tfunction = `%s'", func->buf);
1079 if (perso) printf("\n\tperso = `%s'", perso->buf);
1080 printf("\n\texpected = ");
1081 type_hex.dump(want, stdout);
1082 fputs("\n\tcomputed = ", stdout);
1083 type_hex.dump(&d, stdout);
1092 static int vrf_cshake128(dstr *v)
1094 return (vrf_shaky(cshake128_init, &v[0], &v[1], &v[2], &v[3]));
1097 static int vrf_cshake256(dstr *v)
1099 return (vrf_shaky(cshake256_init, &v[0], &v[1], &v[2], &v[3]));
1102 static void shake128_init_adaptor(shake_ctx *ctx,
1103 const void *func, size_t fsz,
1104 const void *perso, size_t psz)
1105 { assert(!fsz); assert(!psz); shake128_init(ctx);}
1107 static void shake256_init_adaptor(shake_ctx *ctx,
1108 const void *func, size_t fsz,
1109 const void *perso, size_t psz)
1110 { assert(!fsz); assert(!psz); shake256_init(ctx);}
1112 static int vrf_shake128(dstr *v)
1113 { return (vrf_shaky(shake128_init_adaptor, 0, 0, &v[0], &v[1])); }
1115 static int vrf_shake256(dstr *v)
1116 { return (vrf_shaky(shake256_init_adaptor, 0, 0, &v[0], &v[1])); }
1118 static int vrf_kmac(void (*initfn)(kmac_ctx *, const void *, size_t,
1119 const void *, size_t),
1120 dstr *perso, int tsz,
1121 dstr *k, dstr *m, dstr *want)
1127 if (tsz && tsz != want->len) die(1, "inconsistent tag length request");
1128 dstr_ensure(&d, want->len); d.len = want->len;
1129 initfn(&ctx, perso->buf, perso->len, k->buf, k->len);
1130 kmac_hash(&ctx, m->buf, m->len);
1131 if (tsz) kmac_done(&ctx, d.buf, tsz);
1132 else { kmac_xof(&ctx); kmac_get(&ctx, d.buf, d.len); }
1134 if (memcmp(d.buf, want->buf, want->len) != 0) {
1137 printf("\n\tperso = `%s'", perso->buf);
1138 printf("\n\ttag size = %d", tsz);
1139 printf("\n\tkey = "); type_hex.dump(k, stdout);
1140 printf("\n\tinput = "); type_hex.dump(m, stdout);
1141 printf("\n\texpected = "); type_hex.dump(want, stdout);
1142 fputs("\n\tcomputed = ", stdout); type_hex.dump(&d, stdout);
1150 static int vrf_kmac128(dstr *v)
1152 return (vrf_kmac(kmac128_init, &v[0], *(int *)v[1].buf,
1153 &v[2], &v[3], &v[4]));
1156 static int vrf_kmac256(dstr *v)
1158 return (vrf_kmac(kmac256_init, &v[0], *(int *)v[1].buf,
1159 &v[2], &v[3], &v[4]));
1162 static const test_chunk defs[] = {
1163 HASHES(HASH_TESTDEFSX)
1164 #define VRF_MCTDEF(PRE, pre, name) \
1165 { name "-mct", vrf_##pre##_mct, \
1166 { &type_int, &type_hex, &type_hex, 0 } },
1169 { "shake128", vrf_shake128, { &type_hex, &type_hex, 0 } },
1170 { "shake256", vrf_shake256, { &type_hex, &type_hex, 0 } },
1171 { "cshake128", vrf_cshake128,
1172 { &type_string, &type_string, &type_hex, &type_hex, 0 } },
1173 { "cshake256", vrf_cshake256,
1174 { &type_string, &type_string, &type_hex, &type_hex, 0 } },
1175 { "kmac128", vrf_kmac128,
1176 { &type_string, &type_int, &type_hex, &type_hex, &type_hex, 0 } },
1177 { "kmac256", vrf_kmac256,
1178 { &type_string, &type_int, &type_hex, &type_hex, &type_hex, 0 } },
1182 int main(int argc, char *argv[])
1184 test_run(argc, argv, defs, SRCDIR"/t/sha3");
1190 /*----- That's all, folks -------------------------------------------------*/