--- /dev/null
+/* -*-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