symm/strobe.c: Implement Hamburg's STROBE framework.
[catacomb] / symm / strobe.h
diff --git a/symm/strobe.h b/symm/strobe.h
new file mode 100644 (file)
index 0000000..c53fc39
--- /dev/null
@@ -0,0 +1,233 @@
+/* -*-c-*-
+ *
+ * The STROBE protocol framework
+ *
+ * (c) 2018 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.
+ */
+
+/*----- Notes on the STROBE framework -------------------------------------*
+ *
+ * Mike Hamburg's STROBE framework is an attempt to do pretty much all the
+ * obvious parts of symmetric cryptography using a single primitive: the
+ * Keccak-p[1600, 24] sponge function which underlies the SHA3.  This works
+ * excellently on tiny devices, because it's possible to implement
+ * Keccak-p[1600, 24] with a very small amount of code, and STROBE requires
+ * minimal additional state beyond the 200-byte Keccak-p[1600, n] state,
+ * which can be updated more-or-less in place.
+ *
+ * STROBE is stateful.  The idea is that the two parties' STROBE states
+ * should evolve in lockstep with each other.  This will obviously go wrong
+ * if messages cross over, or are reordered or duplicated.
+ *
+ * The model for a single STROBE-based endpoint consists of the application,
+ * and a transport for communicating with a peer.  All data gets mixed into
+ * the STROBE state.  Some operations mix input data with a keystream
+ * generated by the sponge function (used in duplexing mode), which can then
+ * be used to encrypt and authenticate messages.
+ */
+
+#ifndef CATACOMB_STROBE_H
+#define CATACOMB_STROBE_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_KECCAK1600_H
+#  include "keccak1600.h"
+#endif
+
+/*----- Data structures ---------------------------------------------------*/
+
+#define STRBF_I 0x01                   /* inbound */
+#define STRBF_A 0x02                   /* application */
+#define STRBF_C 0x04                   /* cipher */
+#define STRBF_T 0x08                   /* transport */
+#define STRBF_M 0x10                   /* metadata */
+#define STRBF_K 0x20                   /* key-tree (not implemented) */
+#define STRBF_VALIDMASK 0x1f           /* valid bits */
+#define STRBF_OPMASK 0xff              /* observable operation bits */
+
+typedef struct strobe_ctx {
+  keccak1600_state k;
+  octet buf[200];
+  unsigned f, r, n0, n;
+#define STRBF_I0 0x0001                        /* initiator/responder role */
+#define STRBF_INIT 0x0100              /* initiator/responder role set? */
+#define STRBF_STMASK 0x01ff            /* mask for persistent state bits */
+#define STRBF_ACTIVE 0x0200            /* operation in progress */
+#define STRBF_WANTIN 0x0400            /* expect input buffer */
+#define STRBF_WANTOUT 0x0800           /* expect output buffer */
+#define STRBF_VRFOUT 0x1000            /* verify that output is nonzero */
+#define STRBF_NZERO 0x2000             /* nonzero output from update */
+#define STRBF_MIXOUT 0x4000            /* mix output into state */
+#define STRBF_CRYPTO 0x8000            /* mix sponge state into output */
+} strobe_ctx;
+
+#define STROBE_KEY               (STRBF_A | STRBF_C)
+#define STROBE_AD                (STRBF_A)
+#define STROBE_PRF     (STRBF_I | STRBF_A | STRBF_C)
+#define STROBE_CLROUT            (STRBF_A |           STRBF_T)
+#define STROBE_CLRIN   (STRBF_I | STRBF_A |           STRBF_T)
+#define STROBE_ENCOUT            (STRBF_A | STRBF_C | STRBF_T)
+#define STROBE_ENCIN   (STRBF_I | STRBF_A | STRBF_C | STRBF_T)
+#define STROBE_MACOUT                      (STRBF_C | STRBF_T)
+#define STROBE_MACIN   (STRBF_I |           STRBF_C | STRBF_T)
+#define STROBE_RATCHET                     (STRBF_C)
+
+#define STROBE_ROLEMASK        (STRBF_I0 | STRBF_INIT)
+#define STRBRL_UNDCD   (0)                     /* undecided */
+#define STRBRL_INIT               (STRBF_INIT) /* initiator */
+#define STRBRL_RESP    (STRBF_I0 | STRBF_INIT) /* responder */
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @strobe_init@ --- *
+ *
+ * Arguments:  @strobe_ctx *ctx@ = pointer to context block to initialize
+ *             @unsigned lambda@ = security parameter, in bits (must be a
+ *                     multiple of 32)
+ *
+ * Returns:    ---
+ *
+ * Use:                Initialize a STROBE context for use.
+ */
+
+extern void strobe_init(strobe_ctx */*ctx*/, unsigned /*lambda*/);
+
+/* --- @strobe_begin@ --- *
+ *
+ * Arguments:  @strobe_ctx *ctx@ = pointer to context block
+ *             @unsigned op@ = bitmask of flags
+ *
+ * Returns:    ---
+ *
+ * Use:                Begin a STROBE operation.  The flags determine the behaviour
+ *             of the @strobe_process@ and @strobe_done@ functions.
+ *
+ *               * The @I@ bit determines the primary direction of data
+ *                 movement.  If it's clear, data comes from the application
+ *                 into STROBE.  If it's set, data comes from STROBE towards
+ *                 the application.
+ *
+ *               * The @C@ bit activates cryptographic processing.  If it's
+ *                 clear, then the input and output data would be equal, so
+ *                 @dest@ must be null.  If it's set, then input data is
+ *                 XORed with the keystream on its way to the output.
+ *
+ *               * The @A@ bit determines whether the application is
+ *                 engaged.  If it's set, then the input or output buffer
+ *                 (according to whether @I@ is clear or set, respectively)
+ *                 holds the application data.  If it's clear, and @I@ is
+ *                 clear, then zero bytes are fed in; if @I@ is set, then
+ *                 the output is compared with zero, and @strobe_done@
+ *                 reports the outcome of this comparison.
+ *
+ *               * The @T@ bit determines whether the transport is engaged.
+ *                 If it's set, then the input or output buffer (according
+ *                 to whether @I@ is set or clear, respectively) holds
+ *                 transport data.  If it's clear, and @I@ is set, then zero
+ *                 bytes are fed in; if @I@ is clear, then the output is
+ *                 discarded.
+ *
+ *               * The @M@ bit marks the data as metadata, but has no other
+ *                 effect.
+ */
+
+extern void strobe_begin(strobe_ctx */*ctx*/, unsigned /*op*/);
+
+/* --- @strobe_process@ --- *
+ *
+ * Arguments:  @strobe_ctx *ctx@ = pointer to context block
+ *             @const void *src@ = pointer to input data, or null
+ *             @void *dest@ = pointer to output data, or null
+ *             @size_t sz@ = common buffer length
+ *
+ * Returns:    ---
+ *
+ * Use:                Process data through the active STROBE operation.  The exact
+ *             behaviour depends on the flags passed to @strobe_begin@; see
+ *             that function for details.  If @src@ is null, then the
+ *             behaviour is as if the input consists of @sz@ zero bytes.  If
+ *             @dest@ in null, then the output is discarded.
+ */
+
+extern void strobe_process(strobe_ctx */*ctx*/, const void */*src*/,
+                          void */*dest*/, size_t /*sz*/);
+
+/* --- @strobe_done@ --- *
+ *
+ * Arguments:  @strobe_ctx *ctx@ = pointer to context block
+ *
+ * Returns:    Zero on success; @-1@ on verification failure (if @I@ and @T@
+ *                     are set and @A@ is clear)
+ *
+ * Use:                Concludes a STROBE operation, returning the result.
+ */
+
+extern int strobe_done(strobe_ctx */*ctx*/);
+
+/* --- @strobe_key@, @strobe_ad@, @strobe_@prf@, @strobe_clrout@,
+ *     @strobe_clrin@, @strobe_encout@, @strobe_encin@, @strobe_macout@,
+ *     @strobe_macin@, @strobe_ratchet@ --- *
+ *
+ * Arguments:  @strobe_ctx *ctx@ = pointer to context block
+ *
+ * Returns:    @strobe_macin@ returns zero on success, or @-1@ on
+ *                     verification failure
+ *
+ * Use:                Perform a STROBE operation on a single buffer.
+ */
+
+extern void strobe_key(strobe_ctx */*ctx*/, unsigned /*f*/,
+                      const void */*k*/, size_t /*sz*/);
+extern void strobe_ad(strobe_ctx */*ctx*/, unsigned /*f*/,
+                     const void */*h*/, size_t /*sz*/);
+extern void strobe_prf(strobe_ctx */*ctx*/, unsigned /*f*/,
+                      void */*t*/, size_t /*sz*/);
+extern void strobe_clrout(strobe_ctx */*ctx*/, unsigned /*f*/,
+                         const void */*m*/, size_t /*sz*/);
+extern void strobe_clrin(strobe_ctx */*ctx*/, unsigned /*f*/,
+                        const void */*m*/, size_t /*sz*/);
+extern void strobe_encout(strobe_ctx */*ctx*/, unsigned /*f*/,
+                         const void */*m*/, void */*c*/, size_t /*sz*/);
+extern void strobe_encin(strobe_ctx */*ctx*/, unsigned /*f*/,
+                        const void */*c*/, void */*m*/, size_t /*sz*/);
+extern void strobe_macout(strobe_ctx */*ctx*/, unsigned /*f*/,
+                         void */*t*/, size_t /*sz*/);
+extern int strobe_macin(strobe_ctx */*ctx*/, unsigned /*f*/,
+                       const void */*t*/, size_t /*sz*/);
+extern void strobe_ratchet(strobe_ctx */*ctx*/, unsigned /*f*/,
+                          size_t /*sz*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif