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
= &shake128_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 -------------------------------------------------*/