symm/: Implement Daniel Bernstein's `Poly1305' message authentication code.
[catacomb] / symm / poly1305.h
diff --git a/symm/poly1305.h b/symm/poly1305.h
new file mode 100644 (file)
index 0000000..bcc81c2
--- /dev/null
@@ -0,0 +1,225 @@
+/* -*-c-*-
+ *
+ * Poly1305 message authentication code
+ *
+ * (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.
+ */
+
+/*----- Notes on Poly1305 -------------------------------------------------*
+ *
+ * The Poly1305 message authentication code was designed by Daniel Bernstein
+ * in 2004.  It's a heavily performance-engineered Carter--Wegman MAC, based
+ * on polynomial evaluation in %$\F = \mathrm{GF}(2^{130} - 5)$%.  Some of
+ * the performance engineering is out-of-date, being there to support
+ * implementation techniques which are no longer relevant, but it still runs
+ * very quickly.
+ *
+ * The key %$r$% is an element of %$\F$%.  Messages are encoded as a sequence
+ * %$m_0, m_1, \ldots, m_{n-1}$% of of elements of %$\F$%.  A raw hash is
+ * calculated as %$h_0 = \sum_{0\le i<n} m_0 r^{n-i}$%.  Finally, the raw
+ * hash is masked for output by adding to its canonical representative a mask
+ * value %$s$% modulo %$2^{128}$% and encoding the result as an octet string.
+ *
+ * As originally presented, Poly1305 generated the output mask by encrypting
+ * a nonce using AES.  This has since been separated from the design, so that
+ * Poly1305 stands on its own.  Poly1305 is highly key-agile, and most modern
+ * uses simply generate a fresh pseudorandom key and mask for each message.
+ * Note that both key and mask must be (at least) pseudorandom.
+ */
+
+#ifndef CATACOMB_POLY1305_H
+#define CATACOMB_POLY1305_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <mLib/bits.h>
+
+#ifndef CATACOMB_KEYSZ_H
+#  include "keysz.h"
+#endif
+
+/*----- Constants ---------------------------------------------------------*/
+
+extern const octet poly1305_keysz[];
+
+#define POLY1305_BLKSZ 16u
+#define POLY1305_KEYSZ 16u
+#define POLY1305_MASKSZ 16u
+
+/*----- Data structures ---------------------------------------------------*/
+
+typedef struct poly1305_key {
+  union {
+    struct { uint32 r0, r1, r2, r3, r4, rr1, rr2, rr3, rr4; } p26;
+    struct { uint16 r[12]; } p11;
+  } u;
+} poly1305_key;
+
+typedef struct poly1305_ctx {
+  poly1305_key k;
+  union {
+    struct { uint32 s0, s1, s2, s3, s4; uint32 h[5]; } p26;
+    struct { uint16 s[12], h[12]; } p11;
+  } u;
+  unsigned long count;
+  unsigned nbuf;
+  octet buf[16];
+} poly1305_ctx;
+
+/*----- Functions provided ------------------------------------------------*/
+
+/* --- @poly1305_keyinit@ --- *
+ *
+ * Arguments:  @poly1305_key *key@ = key structure to fill in
+ *             @const void *k@ = pointer to key material
+ *             @size_t ksz@ = length of key (must be @POLY1305_KEYSZ == 16@)
+ *
+ * Returns:    ---
+ *
+ * Use:                Records a Poly1305 key and performs (minimal)
+ *             precomputations.
+ */
+
+extern void poly1305_keyinit(poly1305_key */*key*/,
+                            const void */*k*/, size_t /*sz*/);
+
+/* --- @poly1305_macinit@ --- *
+ *
+ * Arguments:  @poly1305_ctx *ctx@ = MAC context to fill in
+ *             @const poly1305_key *key@ = pointer to key structure to use
+ *             @const void *iv@ = pointer to mask string
+ *
+ * Returns:    ---
+ *
+ * Use:                Initializes a MAC context for use.  The key can be discarded
+ *             at any time.
+ *
+ *             It is permitted for @iv@ to be null, though it is not then
+ *             possible to complete the MAC computation on @ctx@.  The
+ *             resulting context may still be useful, e.g., as an operand to
+ *             @poly1305_concat@.
+ */
+
+extern void poly1305_macinit(poly1305_ctx */*ctx*/,
+                            const poly1305_key */*key*/,
+                            const void */*iv*/);
+
+/* --- @poly1305_copy@ --- *
+ *
+ * Arguments:  @poly1305_ctx *to@ = destination context
+ *             @const poly1305_ctx *from@ = source context
+ *
+ * Returns:    ---
+ *
+ * Use:                Duplicates a Poly1305 MAC context.  The destination need not
+ *             have been initialized.  Both contexts can be used
+ *             independently afterwards.
+ */
+
+extern void poly1305_copy(poly1305_ctx */*to*/,
+                         const poly1305_ctx */*from*/);
+
+/* --- @poly1305_hash@ --- *
+ *
+ * Arguments:  @poly1305_ctx *ctx@ = MAC context to update
+ *             @const void *p@ = pointer to message data
+ *             @size_t sz@ = length of message data
+ *
+ * Returns:    ---
+ *
+ * Use:                Processes a chunk of message.  The message pieces may have
+ *             arbitrary lengths, and may be empty.
+ */
+
+extern void poly1305_hash(poly1305_ctx */*ctx*/,
+                         const void */*p*/, size_t /*sz*/);
+
+/* --- @poly1305_flush@ --- *
+ *
+ * Arguments:  @poly1305_ctx *ctx@ = MAC context to flush
+ *
+ * Returns:    ---
+ *
+ * Use:                Forces any buffered message data in the context to be
+ *             processed.  This has no effect if the message processed so
+ *             far is a whole number of blocks.  Flushing is performed
+ *             automatically by @poly1305_done@, but it may be necessary to
+ *             force it by hand when using @poly1305_concat@.
+ *
+ *             Flushing a partial block has an observable effect on the
+ *             computation: the resulting state is (with high probability)
+ *             dissimilar to any state reachable with a message which is a
+ *             whole number of blocks long.
+ */
+
+extern void poly1305_flush(poly1305_ctx */*ctx*/);
+
+/* --- @poly1305_concat@ --- *
+ *
+ * Arguments:  @poly1305_ctx *ctx@ = destination context
+ *             @const poly1305_ctx *prefix, *suffix@ = two operand contexts
+ *
+ * Returns:    ---
+ *
+ * Use:                The two operand contexts @prefix@ and @suffix@ represent
+ *             processing of two messages %$m$% and %$m'$%; the effect is to
+ *             set @ctx@ to the state corresponding to their concatenation
+ *             %$m \cat m'$%.
+ *
+ *             All three contexts must have been initialized using the same
+ *             key value (though not necessarily from the same key
+ *             structure).  The mask values associated with the input
+ *             contexts are irrelevant.  The @prefix@ message %$m$% must be
+ *             a whole number of blocks long: this can be arranged by
+ *             flushing the context.  The @suffix@ message need not be a
+ *             whole number of blocks long.  All of the contexts remain
+ *             operational and can be used independently afterwards.
+ */
+
+extern void poly1305_concat(poly1305_ctx */*ctx*/,
+                           const poly1305_ctx */*prefix*/,
+                           const poly1305_ctx */*suffix*/);
+
+/* --- @poly1305_done@ --- *
+ *
+ * Arguments:  @poly1305_ctx *ctx@ = MAC context to finish
+ *             @void *h@ = buffer to write the tag to
+ *
+ * Returns:    ---
+ *
+ * Use:                Completes a Poly1305 MAC tag computation.
+ */
+
+extern void poly1305_done(poly1305_ctx */*ctx*/, void */*h*/);
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif