symm/sha3.[ch]: Add support for SHA3 and related functions based on Keccak.
[catacomb] / symm / sha3.h
diff --git a/symm/sha3.h b/symm/sha3.h
new file mode 100644 (file)
index 0000000..bc0a4fc
--- /dev/null
@@ -0,0 +1,469 @@
+/* -*-c-*-
+ *
+ * The SHA3 algorithm family
+ *
+ * (c) 2017 Straylight/Edgeware
+ */
+
+/*----- Licensing notice --------------------------------------------------*
+ *
+ * This file is part of Catacomb.
+ *
+ * Catacomb is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Library General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * Catacomb is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public
+ * License along with Catacomb; if not, write to the Free
+ * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+ * MA 02111-1307, USA.
+ */
+
+#ifndef CATACOMB_SHA3_H
+#define CATACOMB_SHA3_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Notes on the SHA3 algorithm family --------------------------------*
+ *
+ * The winner of the SHA3 competition was Keccak, designed by Guido Bertoni,
+ * Joan Daemen, MichaĆ«l Peeters, and Gilles Van Assche.  The algorithm uses
+ * their `sponge construction', based on a fixed attempt to instantiate an
+ * `ideal permutation'.  The construction is rather versatile, and NIST has
+ * standardized a number of algorithms based on it.
+ *
+ * The basic offerings are the drop-in replacements for the SHA2 family.
+ * These are slower than is ideal, because of the decision to provide O(2^n)
+ * resistance to second-preimage attacks for the n-bit hash function, which
+ * means that, effectively, the capacity parameter is set unnecessarily
+ * large.  (There was a major fuss when NIST tried to change this in a draft
+ * of te standard.)  All of the obvious hash modes, e.g., HMAC, MGF, can be
+ * applied to the SHA3 hash functions, though I can't really recommend this:
+ * there's almost certainly a better way of doing whatever it is.
+ *
+ * Other members of the family are: SHAKE and cSHAKE, `extendable-output
+ * funnctions' which can be used directly in place of MGFs; and KMAC, a
+ * message authentication code with arbitrary-length key, message, and tag,
+ * which can therefore be used as a key-derivation function.  The cSHAKE
+ * construction, on which KMAC is based, introduces a personalization string
+ * which can be used for domain separation.
+ */
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_KECCAK1600_H
+#  include "keccak1600.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+#  include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_GHASH_H
+#  include "ghash.h"
+#endif
+
+#ifndef CATACOMB_GMAC_H
+#  include "gmac.h"
+#endif
+
+#ifndef CATACOMB_GRAND_H
+#  include "grand.h"
+#endif
+
+/*----- The SHA3 hash function family -------------------------------------*/
+
+typedef struct sha3_ctx {
+  keccak1600_state s;
+  unsigned r, w, n;
+  octet buf[200];
+} sha3_ctx;
+#define sha3_224_ctx sha3_ctx
+#define sha3_256_ctx sha3_ctx
+#define sha3_384_ctx sha3_ctx
+#define sha3_512_ctx sha3_ctx
+
+#define SHA3_224_HASHSZ 28
+#define SHA3_256_HASHSZ 32
+#define SHA3_384_HASHSZ 48
+#define SHA3_512_HASHSZ 64
+
+#define SHA3_224_BUFSZ 144
+#define SHA3_256_BUFSZ 136
+#define SHA3_384_BUFSZ 104
+#define SHA3_512_BUFSZ 72
+
+#define SHA3_STATESZ (sizeof(sha3_ctx))
+#define SHA3_224_STATESZ SHA3_STATESZ
+#define SHA3_256_STATESZ SHA3_STATESZ
+#define SHA3_384_STATESZ SHA3_STATESZ
+#define SHA3_512_STATESZ SHA3_STATESZ
+
+/* --- @sha3_{224,256,384,512}_init@ --- *
+ *
+ * Arguments:  @sha3_ctx *ctx@ = pointer to context block to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a SHA3 hashing context for use.
+ */
+
+extern void sha3_224_init(sha3_ctx */*ctx*/);
+extern void sha3_256_init(sha3_ctx */*ctx*/);
+extern void sha3_384_init(sha3_ctx */*ctx*/);
+extern void sha3_512_init(sha3_ctx */*ctx*/);
+
+/* --- @sha3_hash@ --- *
+ *
+ * Arguments:  @sha3_ctx *ctx@ = pointer to context bock
+ *             @const void *p@ = pointer to data to hash
+ *             @size_t sz@ = size of buffer to hash
+ *
+ * Returns:    ---
+ *
+ * Use:                Hashes a buffer of data.  The buffer may be of any size and
+ *             alignment.
+ */
+
+#define sha3_224_hash sha3_hash
+#define sha3_256_hash sha3_hash
+#define sha3_384_hash sha3_hash
+#define sha3_512_hash sha3_hash
+
+extern void sha3_hash(sha3_ctx */*ctx*/, const void */*p*/, size_t /*sz*/);
+
+/* --- @sha3_done@ --- *
+ *
+ * Arguments:  @sha3_ctx *ctx@ = pointer to context block
+ *             @void *hash@ = pointer to output buffer
+ *
+ * Returns:    ---
+ *
+ * Use:                Returns the hash of the data read so far.
+ */
+
+#define sha3_224_done sha3_done
+#define sha3_256_done sha3_done
+#define sha3_384_done sha3_done
+#define sha3_512_done sha3_done
+
+extern void sha3_done(sha3_ctx */*ctx*/, void */*hash*/);
+
+/* --- @sha3_{224,256,384,512}_set@ --- *
+ *
+ * Arguments:  @sha3_ctx *ctx@ = pointer to context block
+ *             @const void *buf@ = pointer to state buffer
+ *             @unsigned long count@ = current count of bytes processed
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a context block from a given state.  This is
+ *             something of a kludge for the benefit of HMAC, but there are
+ *             better ways to use SHA3 as a MAC.
+ *
+ *             Furthermore, the @count@ argument is expected to be zero or
+ *             be the output of @sha3_state@ below.  Doing anything else
+ *             won't work properly.
+ */
+
+extern void sha3_224_set(sha3_ctx */*ctx*/,
+                        const void */*buf*/, unsigned long /*count*/);
+extern void sha3_256_set(sha3_ctx */*ctx*/,
+                        const void */*buf*/, unsigned long /*count*/);
+extern void sha3_384_set(sha3_ctx */*ctx*/,
+                        const void */*buf*/, unsigned long /*count*/);
+extern void sha3_512_set(sha3_ctx */*ctx*/,
+                        const void */*buf*/, unsigned long /*count*/);
+
+/* --- @sha3_state@ --- *
+ *
+ * Arguments:  @sha3_ctx *ctx@ = pointer to context block
+ *             @void *state@ = pointer to buffer for current state
+ *
+ * Returns:    A value which is meaningful to @sha3_..._set@.
+ *
+ * Use:                Returns the current state of the hash function such that it
+ *             can be passed to @sha3_..._set@.
+ */
+
+#define sha3_224_state sha3_state
+#define sha3_256_state sha3_state
+#define sha3_384_state sha3_state
+#define sha3_512_state sha3_state
+
+extern unsigned long sha3_state(sha3_ctx */*ctx*/, void */*state*/);
+
+/* --- Generic hash interface --- */
+
+extern const gchash sha3_224, sha3_256, sha3_384, sha3_512;
+
+/*----- The cSHAKE XOF algorithm ------------------------------------------*/
+
+typedef struct shake_ctx {
+  sha3_ctx h;
+  unsigned st, op;
+} shake_ctx;
+#define shake128_ctx shake_ctx
+#define shake256_ctx shake_ctx
+
+#define SHAKE128_KEYSZ 16
+#define SHAKE256_KEYSZ 32
+
+#define SHAKE128_HASHSZ 32             /* Somewhat arbitrary... */
+#define SHAKE256_HASHSZ 64
+
+extern const octet shake128_keysz[], shake256_keysz[];
+
+/* --- @cshake{128,256}_init@ --- *
+ *
+ * Arguments:  @shake_ctx *ctx@ = pointer to context to initialize
+ *             @const void *func@ = NIST-allocated function name
+ *             @size_t fsz@ = length of function name
+ *             @const void *perso@ = user personalization string
+ *             @size_t psz@ = length of personalization string
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a cSHAKE context.  The context is initially in
+ *             the `absorbing' state: feed it data with @shake_hash@.
+ */
+
+extern void cshake128_init(shake_ctx */*ctx*/,
+                          const void */*func*/, size_t /*fsz*/,
+                          const void */*perso*/, size_t /*psz*/);
+
+extern void cshake256_init(shake_ctx */*ctx*/,
+                          const void */*func*/, size_t /*fsz*/,
+                          const void */*perso*/, size_t /*psz*/);
+
+/* --- @shake{128,256}_init@ --- *
+ *
+ * Arguments:  @sha3_ctx *ctx@ = pointer to context to initialize
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a SHAKE context.  The context is initially in
+ *             the `absorbing' state: feed it data with @shake_hash@.
+ */
+
+extern void shake128_init(shake_ctx */*ctx*/);
+extern void shake256_init(shake_ctx */*ctx*/);
+
+/* --- @shake_hash@ --- *
+ *
+ * Arguments:  @shake_ctx *ctx@ = context to update
+ *             @const void *p@ = input buffer
+ *             @size_t sz@ = size of input
+ *
+ * Returns:    ---
+ *
+ * Use:                Feeds input data into a SHAKE context.  The context must be
+ *             in `absorbing' state.
+ */
+
+extern void shake_hash(shake_ctx */*ctx*/, const void */*p*/, size_t /*sz*/);
+
+/* --- @shake_xof@ --- *
+ *
+ * Arguments:  @shake_ctx *ctx@ = context to update
+ *
+ * Returns:    ---
+ *
+ * Use:                Switches the context into `squeezing' state.  Use @shake_get@
+ *             or @shake_mask@ to extract data.
+ */
+
+extern void shake_xof(shake_ctx */*ctx*/);
+
+/* --- @shake_get@ --- *
+ *
+ * Arguments:  @shake_ctx *ctx@ = context to update
+ *             @void *p@ = output buffer
+ *             @size_t sz@ = size of output
+ *
+ * Returns:    ---
+ *
+ * Use:                Extracts output from a SHAKE context.  The context must be
+ *             in `squeezing' state.
+ */
+
+extern void shake_get(shake_ctx */*ctx*/, void */*p*/, size_t /*sz*/);
+
+/* --- @shake_mask@ --- *
+ *
+ * Arguments:  @shake_ctx *ctx@ = context to update
+ *             @const void *src@ = pointer to source data, or null
+ *             @void *dest@ = output buffer
+ *             @size_t sz@ = size of output
+ *
+ * Returns:    ---
+ *
+ * Use:                Mask the @src@ data by XORing it with output from the SHAKE
+ *             context, writing the result to @dest@.  The @src@ and @dest
+ *             buffers may be equal but must not otherwise overlap.  The
+ *             context must be in `squeezing' state.
+ */
+
+extern void shake_mask(shake_ctx */*ctx*/,
+                      const void */*src*/, void */*dest*/, size_t /*sz*/);
+
+/* --- @shake_done@ --- *
+ *
+ * Arguments:  @shake_ctx *ctx@ = context to update
+ *             @void *h@ = where to write the hash
+ *             @size_t hsz@ = size of the hash to make
+ *
+ * Returns:    ---
+ *
+ * Use:                Switches the context into `squeezing' state.  Use @shake_get@
+ *             or @shake_mask@ to extract data.
+ */
+
+extern void shake_done(shake_ctx */*ctx*/, void */*h*/, size_t /*hsz*/);
+
+/* --- @shake{128,256}_rand@ --- *
+ *
+ * Arguments:  @const void *k@ = pointer to seed material
+ *             @size_t sz@ = size of the seed
+ *
+ * Returns:    A pseudorandom generator with the given seed.
+ */
+
+extern grand *shake128_rand(const void */*k*/, size_t /*sz*/);
+extern grand *shake256_rand(const void */*k*/, size_t /*sz*/);
+
+/* --- @cshake{128,256}_rand@ --- *
+ *
+ * Arguments:  @const void *func@ = function name
+ *             @size_t fsz@ = length of function name
+ *             @const void *perso@ = personalization string
+ *             @size_t psz@ = length of personalization string
+ *             @const void *k@ = pointer to seed material
+ *             @size_t sz@ = size of the seed
+ *
+ * Returns:    A pseudorandom generator with the given seed.
+ *
+ * Use:                Note that with null @func@ and @perso@ strings, this is
+ *             equivalent to @shake128_rand@ or @shake256_rand@.
+ */
+
+extern grand *cshake128_rand(const void */*func*/, size_t /*fsz*/,
+                            const void */*perso*/, size_t /*psz*/,
+                            const void */*k*/, size_t /*sz*/);
+
+extern grand *cshake256_rand(const void */*func*/, size_t /*fsz*/,
+                            const void */*perso*/, size_t /*psz*/,
+                            const void */*k*/, size_t /*sz*/);
+
+/* --- Generic cipher interface --- */
+
+extern const gccipher shake128_xof, shake256_xof;
+extern const gchash shake128, shake256;
+
+/*----- The KMAC variable-length PRF --------------------------------------*/
+
+typedef shake_ctx kmac_ctx;
+
+#define KMAC128_KEYSZ SHAKE128_KEYSZ
+#define KMAC256_KEYSZ SHAKE256_KEYSZ
+
+#define KMAC128_TAGSZ 16
+#define KMAC256_TAGSZ 32
+
+#define kmac128_keysz shake128_keysz
+#define kmac256_keysz shake256_keysz
+
+/* --- @kmac{128,256}_init@ --- *
+ *
+ * Arguments:  @kmac_ctx *ctx@ = pointer to context to fill in
+ *             @const void *perso@ = personalization string, or null
+ *             @size_t psz@ = length of personalization string
+ *             @const void *k@ = pointer to key material
+ *             @size_t sz@ = size of key material
+ *
+ * Returns:    ---
+ *
+ * Use:                Sets up a KMAC context.  Set @tsz@ to zero for a flexible-
+ *             length tag, which can be read using @kmac_get@.  Use
+ *             @kmac_hash@ to feed in the input message.
+ */
+
+extern void kmac128_init(kmac_ctx */*ctx*/,
+                        const void */*perso*/, size_t /*psz*/,
+                        const void */*k*/, size_t /*sz*/);
+extern void kmac256_init(kmac_ctx */*ctx*/,
+                        const void */*perso*/, size_t /*psz*/,
+                        const void */*k*/, size_t /*sz*/);
+
+/* --- @kmac_xof@ --- *
+ *
+ * Arguments:  @kmac_ctx *ctx@ = pointer to context
+ *
+ * Returns:    ---
+ *
+ * Use:                Marks the end of the message to be processed.  The output can
+ *             be read using @kmac_get@.
+ */
+
+void kmac_xof(kmac_ctx */*ctx*/);
+
+/* --- @kmac_done@ --- *
+ *
+ * Arguments:  @kmac_ctx *ctx@ = pointer to context
+ *             @void *h@ = where to put the tag
+ *             @size_t hsz@ = size of tag to produce
+ *
+ * Returns:    ---
+ *
+ * Use:                Marks the end of the message to be processed and returns a
+ *             tag.  Note that the tag value is dependent on the output
+ *             size.
+ */
+
+void kmac_done(kmac_ctx */*ctx*/, void */*h*/, size_t /*hsz*/);
+
+/* --- Convenience aliases --- */
+
+#define kmac_hash shake_hash
+#define kmac_get shake_get
+#define kmac_mask shake_mask
+
+/* --- @kmac{128,256}_rand@ --- *
+ *
+ * Arguments:  @const void *perso@ = personalization string, or null
+ *             @size_t psz@ = length of personalization string
+ *             @const void *k@ = pointer to seed material
+ *             @size_t sz@ = size of the seed
+ *
+ * Returns:    A pseudorandom generator with the given key.
+ *
+ * Use:                The generator processes an empty message by default, but this
+ *             can be changed by seeding it.
+ */
+
+extern grand *kmac128_rand(const void */*perso*/, size_t /*psz*/,
+                          const void */*k*/, size_t /*sz*/);
+extern grand *kmac256_rand(const void */*perso*/, size_t /*psz*/,
+                          const void */*k*/, size_t /*sz*/);
+
+/* --- Generic MAC interface --- */
+
+extern const gcmac kmac128, kmac256;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif