symm/gcm.h, symm/gcm-def.h: Implement the GCM authenticated encryption mode.
[catacomb] / symm / gcm.h
diff --git a/symm/gcm.h b/symm/gcm.h
new file mode 100644 (file)
index 0000000..d3e6d03
--- /dev/null
@@ -0,0 +1,308 @@
+/* -*-c-*-
+ *
+ * The GCM authenticated encryption mode
+ *
+ * (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 GCM ------------------------------------------------------*
+ *
+ * The name is short for `Galois Counter Mode'.  GCM was designed in 2005 by
+ * David McGrew and John Viega as a fast, patent-free authenticated
+ * encryption scheme; and it's specified by NIST in SP800-38D.  It combines
+ * counter-mode encryption with a Carter--Wegman authenticator based on a
+ * polynomial hash over %$\gf{2^{128}}%, so it needs only one blockcipher
+ * application per message block, together with a multiplication by a
+ * constant in the finite field.  GCM is essentially the winner in the
+ * authenticated-encryption-mode competition, to the extent that Intel and
+ * ARM both added instructions to their architectures to accelerate it.
+ *
+ * GCM allows arbitrary-sized nonces, though it's happiest if the nonce is 32
+ * bits shorter than the block size, leaving a fixed-size block counter in
+ * the low 32 bits.  It permits header data to be processed independently of
+ * the message, though doing this requires some slightly fiddly algebra and
+ * most implementations don't allow callers to take advantage of this.
+ *
+ * One downside is that the field multiplication is inefficient in software.
+ * Back in 2005 it was assumed that implementors would use large tables, but
+ * that leaks the authentication secret through the processor cache.  This
+ * implementation runs in constant time, but the penalty is that, without
+ * dedicated processor support, it's much slower than an extra blockcipher
+ * application would have been.
+ *
+ * Another downside is that, while GCM came with a security proof, it was
+ * subtly incorrect in a few ways which mean that its concrete security is
+ * significantly less than one would expect.
+ *
+ * If interoperability isn't a concern, then OCB3 is probably a better
+ * choice; if the OCB patent situation is also worrying, then EAX is likely
+ * preferable.
+ */
+
+#ifndef CATACOMB_GCM_H
+#define CATACOMB_GCM_H
+
+#ifdef __cplusplus
+  extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stddef.h>
+
+#include <mLib/bits.h>
+#include <mLib/buf.h>
+
+#ifndef CATACOMB_GAEAD_H
+#  include "gaead.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @GCM_DECL@ --- *
+ *
+ * Arguments:  @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use:                Creates declarations for GCM authenticated-encryption mode.
+ */
+
+#define GCM_DECL(PRE, pre)                                             \
+                                                                       \
+typedef struct pre##_gcmkey {                                          \
+  pre##_ctx ctx;                       /* Block cipher key */          \
+  uint32 ktab[32*PRE##_BLKSZ*PRE##_BLKSZ]; /* Multiplication table */  \
+} pre##_gcmkey;                                                                \
+                                                                       \
+typedef struct pre##_gcmaadctx {                                       \
+  pre##_gcmkey k;                      /* Underlying key */            \
+  uint32 a[PRE##_BLKSZ/4];             /* GHASH accumulator */         \
+  octet b[PRE##_BLKSZ];                        /* Input buffer */              \
+  unsigned off;                                /* Length of stuff in buffer */ \
+  unsigned long len;                   /* Number of blocks so far */   \
+} pre##_gcmaadctx;                                                     \
+                                                                       \
+typedef struct pre##_gcmctx {                                          \
+  /* The buffer is split into two portions.  The first N octets hold a \
+   * chunk of ciphertext, which will be fed into the OMAC calculation; \
+   * the remaining BLKSZ - N octets hold E_K(C), which is the XOR mask \
+   * to apply to the plaintext or ciphertext.                          \
+   */                                                                  \
+  pre##_gcmkey k;                      /* Underlying key */            \
+  uint32 c[PRE##_BLKSZ/4];             /* Current counter value */     \
+  uint32 c0[PRE##_BLKSZ/4];            /* Initial counter */           \
+  uint32 a[PRE##_BLKSZ];               /* GHASH accumulator */         \
+  octet b[PRE##_BLKSZ];                        /* Ciphertext/mask buffer */    \
+  unsigned off;                                /* Crossover point in buffer */ \
+  unsigned long len;                   /* Number of blocks so far */   \
+} pre##_gcmctx;                                                                \
+                                                                       \
+extern const octet pre##_gcmnoncesz[], pre##_gcmtagsz[];               \
+                                                                       \
+/* --- @pre_gcmsetkey@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_gcmkey *key@ = pointer to key block to fill in     \
+ *             @const void *k@ = pointer to key material               \
+ *             @size_t ksz@ = size of key material                     \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes an GCM key block.                           \
+ */                                                                    \
+                                                                       \
+extern void pre##_gcmsetkey(pre##_gcmkey */*key*/,                     \
+                           const void */*k*/, size_t /*ksz*/);         \
+                                                                       \
+/* --- @pre_gcmaadinit@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_gcmaadctx *aad@ = pointer to AAD context           \
+ *             @const pre_gcmkey *key@ = pointer to key block          \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initializes an GCM AAD (`additional authenticated       \
+ *             data') context associated with a given key.  AAD        \
+ *             contexts can be copied and/or reused, saving time if    \
+ *             the AAD for a number of messages has a common prefix.   \
+ *                                                                     \
+ *             The @key@ doesn't need to be kept around, though        \
+ *             usually there'll at least be another copy in some GCM   \
+ *             operation context because the AAD on its own isn't much \
+ *             good.                                                   \
+ */                                                                    \
+                                                                       \
+extern void pre##_gcmaadinit(pre##_gcmaadctx */*aad*/,                 \
+                            const pre##_gcmkey */*key*/);              \
+                                                                       \
+/* --- @pre_gcmaadhash@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_gcmaadctx *aad@ = pointer to AAD context           \
+ *             @const void *p@ = pointer to AAD material               \
+ *             @size_t sz@ = length of AAD material                    \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Feeds AAD into the context.                             \
+ */                                                                    \
+                                                                       \
+extern void pre##_gcmaadhash(pre##_gcmaadctx */*aad*/,                 \
+                            const void */*p*/, size_t /*sz*/);         \
+                                                                       \
+/* --- @pre_gcminit@ --- *                                             \
+ *                                                                     \
+ * Arguments:  @pre_gcmctx *ctx@ = pointer to GCM context              \
+ *             @const pre_gcmkey *key@ = pointer to key block          \
+ *             @const void *n@ = pointer to nonce                      \
+ *             @size_t nsz@ = size of nonce                            \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Initialize an GCM operation context with a given key.   \
+ *                                                                     \
+ *             The original key needn't be kept around any more.       \
+ */                                                                    \
+                                                                       \
+extern void pre##_gcminit(pre##_gcmctx */*ctx*/,                       \
+                         const pre##_gcmkey */*k*/,                    \
+                         const void */*n*/, size_t /*nsz*/);           \
+                                                                       \
+/* --- @pre_gcmreinit@ --- *                                           \
+ *                                                                     \
+ * Arguments:  @pre_gcmctx *ctx@ = pointer to GCM context              \
+ *             @const void *n@ = pointer to nonce                      \
+ *             @size_t nsz@ = size of nonce                            \
+ *                                                                     \
+ * Returns:    ---                                                     \
+ *                                                                     \
+ * Use:                Reinitialize an GCM operation context, changing the     \
+ *             nonce.                                                  \
+ */                                                                    \
+                                                                       \
+extern void pre##_gcmreinit(pre##_gcmctx */*ctx*/,                     \
+                           const void */*n*/, size_t /*nsz*/);         \
+                                                                       \
+/* --- @pre_gcmencrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_gcmctx *ctx@ = pointer to GCM operation context    \
+ *             @const void *src@ = pointer to plaintext message chunk  \
+ *             @size_t sz@ = size of the plaintext                     \
+ *             @buf *dst@ = a buffer to write the ciphertext to        \
+ *                                                                     \
+ * Returns:    Zero on success; @-1@ on failure.                       \
+ *                                                                     \
+ * Use:                Encrypts a chunk of a plaintext message, writing a      \
+ *             chunk of ciphertext to the output buffer and updating   \
+ *             the operation state.                                    \
+ *                                                                     \
+ *             For GCM, we always write a ciphertext chunk the same    \
+ *             size as the plaintext.  The messing about with @buf@    \
+ *             objects makes the interface consistent with other AEAD  \
+ *             schemes which can't do this.                            \
+ */                                                                    \
+                                                                       \
+extern int pre##_gcmencrypt(pre##_gcmctx */*ctx*/,                     \
+                           const void */*src*/, size_t /*sz*/,         \
+                           buf */*dst*/);                              \
+                                                                       \
+/* --- @pre_gcmdecrypt@ --- *                                          \
+ *                                                                     \
+ * Arguments:  @pre_gcmctx *ctx@ = pointer to GCM operation context    \
+ *             @const void *src@ = pointer to ciphertext message chunk \
+ *             @size_t sz@ = size of the ciphertext                    \
+ *             @buf *dst@ = a buffer to write the plaintext to         \
+ *                                                                     \
+ * Returns:    Zero on success; @-1@ on failure.                       \
+ *                                                                     \
+ * Use:                Decrypts a chunk of a ciphertext message, writing a     \
+ *             chunk of plaintext to the output buffer and updating    \
+ *             the operation state.                                    \
+ *                                                                     \
+ *             For GCM, we always write a plaintext chunk the same     \
+ *             size as the ciphertext.  The messing about with @buf@   \
+ *             objects makes the interface consistent with other AEAD  \
+ *             schemes which can't do this.                            \
+ */                                                                    \
+                                                                       \
+extern int pre##_gcmdecrypt(pre##_gcmctx */*ctx*/,                     \
+                           const void */*src*/, size_t /*sz*/,         \
+                           buf */*dst*/);                              \
+                                                                       \
+/* --- @pre_gcmencryptdone@ --- *                                      \
+ *                                                                     \
+ * Arguments:  @pre_gcmctx *ctx@ = pointer to an GCM context           \
+ *             @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
+ *                     null                                            \
+ *             @buf *dst@ = buffer for remaining ciphertext            \
+ *             @void *tag@ = where to write the tag                    \
+ *             @size_t tsz@ = length of tag to store                   \
+ *                                                                     \
+ * Returns:    Zero on success; @-1@ on failure.                       \
+ *                                                                     \
+ * Use:                Completes an GCM encryption operation.  The @aad@       \
+ *             pointer may be null if there is no additional           \
+ *             authenticated data.  GCM doesn't buffer ciphertext, but \
+ *             the output buffer is provided anyway for consistency    \
+ *             with other AEAD schemes which don't have this property; \
+ *             the function will fail if the output buffer is broken.  \
+ */                                                                    \
+                                                                       \
+extern int pre##_gcmencryptdone(pre##_gcmctx */*ctx*/,                 \
+                               const pre##_gcmaadctx */*aad*/,         \
+                               buf */*dst*/,                           \
+                               void */*tag*/, size_t /*tsz*/);         \
+                                                                       \
+/* --- @pre_gcmdecryptdone@ --- *                                      \
+ *                                                                     \
+ * Arguments:  @pre_gcmctx *ctx@ = pointer to an GCM context           \
+ *             @const pre_gcmaadctx *aad@ = pointer to AAD context, or \
+ *                     null                                            \
+ *             @buf *dst@ = buffer for remaining plaintext             \
+ *             @const void *tag@ = tag to verify                       \
+ *             @size_t tsz@ = length of tag                            \
+ *                                                                     \
+ * Returns:    @+1@ for complete success; @0@ if tag verification      \
+ *             failed; @-1@ for other kinds of errors.                 \
+ *                                                                     \
+ * Use:                Completes an GCM decryption operation.  The @aad@       \
+ *             pointer may be null if there is no additional           \
+ *             authenticated data.  GCM doesn't buffer plaintext, but  \
+ *             the output buffer is provided anyway for consistency    \
+ *             with other AEAD schemes which don't have this property; \
+ *             the function will fail if the output buffer is broken.  \
+ */                                                                    \
+                                                                       \
+extern int pre##_gcmdecryptdone(pre##_gcmctx */*ctx*/,                 \
+                               const pre##_gcmaadctx */*aad*/,         \
+                               buf */*dst*/,                           \
+                               const void */*tag*/, size_t /*tsz*/);   \
+                                                                       \
+/* --- Generic AEAD interface --- */                                   \
+                                                                       \
+extern const gcaead pre##_gcm;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+  }
+#endif
+
+#endif