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