--- /dev/null
+/* -*-c-*-
+ *
+ * The OCB1 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 OCB1 -----------------------------------------------------*
+ *
+ * OCB was designed in 2001 by Phillip Rogaway, with Mihir Bellare and John
+ * Black, as a blockcipher-based authenticated encryption scheme which can
+ * operate on multiple message blocks in parallel and requires only a single
+ * blockcipher application per message block. It refines Charanjit Jutla's
+ * earlier IAPM, which was the first such mode to be proven secure. This
+ * version implements the `OCB.PMAC' mode described by Rogaway in 2002, which
+ * combines the original OCB with PMAC (Rogaway and Black, 2002) into a
+ * single authenticated-encryption with associated-data (AEAD) scheme.
+ *
+ * The patent situation on these efficient authenticated encryption schemes
+ * is fraught. IBM hold two patents on Jutla's pioneering work on `IACBC'
+ * and `IAPM' which can apply (a third was filed at least six years too
+ * late), and Virgil Gligor and Pompiliu Donescu hold patents on their `XECB'
+ * and `XCBC' modes; these may or may not apply to OCB. Rogaway himself
+ * holds US patents on various versions of OCB, but has issued free licences
+ * for free (`open source') software, and for all non-military use. I think
+ * Catacomb's implementation of OCB falls within the scope of the former
+ * licence.
+ *
+ * Confusingly, Rogaway's 2004 paper `Efficient Instantiations of Tweakable
+ * Blockciphers and Refinements to Modes OCB and PMAC' named the new versions
+ * of those modes `OCB1' and `PMAC1'. The 2011 paper by Krovetz and Rogaway,
+ * `The Software Performance of Authenticated-Encryption Modes' renamed the
+ * original 2001 version of OCB as `OCB1', and the 2004 version `OCB2', and
+ * introduced a new `OCB3'. I've decided to follow and extend the 2011
+ * naming, so `OCB1' refers to the 2001 OCB; the 2004 version would be
+ * `OCB2'.
+ *
+ * The OCB specification is clear about how OCB applies to arbitrary block
+ * sizes.
+ *
+ * OCB1 is a fairly well-behaved AEAD mode. It doesn't require
+ * precommentment to any lengths, and allows header data to be processed
+ * independently of any message. On the other hand, it only accepts nonces
+ * the same size as the underlying blockcipher's block size, and it buffers
+ * up to a whole block's worth of data internally, which somewhat complicates
+ * streaming.
+ */
+
+#ifndef CATACOMB_OCB1_H
+#define CATACOMB_OCB1_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
+
+#ifndef CATACOMB_OCB_H
+# include "ocb.h"
+#endif
+
+#ifndef CATACOMB_RSVR_H
+# include "rsvr.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @OCB1_DECL@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates declarations for OCB1 message-authentication mode.
+ */
+
+#define OCB1_STRUCTS(PRE, pre, keyty, aadty) \
+ \
+typedef struct keyty { \
+ pre##_ctx ctx; /* Underlying cipher context */ \
+ uint32 lxinv[PRE##_BLKSZ/4]; /* Final-block mask */ \
+ uint32 lmask[OCB_NCALC][PRE##_BLKSZ/4]; /* Precalculated masks */ \
+} keyty; \
+ \
+typedef struct aadty { \
+ keyty k; /* Processed key material */ \
+ uint32 o[PRE##_BLKSZ/4]; /* Current offset */ \
+ uint32 a[PRE##_BLKSZ/4]; /* Accumulator state */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned long i; /* Block counter */ \
+ unsigned off; /* Offset into buffered data */ \
+} aadty;
+
+#define OCB1_DECL(PRE, pre) \
+ \
+OCB1_STRUCTS(PRE, pre, pre##_ocb1key, pre##_ocb1aadctx) \
+ \
+typedef struct pre##_ocb1ctx { \
+ /* This is the same as @pre_ocb1aadctx@ above, but the two are \
+ * logically distinct and shouldn't be muddled up. \
+ */ \
+ \
+ pre##_ocb1key k; /* Processed key material */ \
+ uint32 o[PRE##_BLKSZ/4]; /* Current offset */ \
+ uint32 a[PRE##_BLKSZ/4]; /* Accumulator state */ \
+ octet b[PRE##_BLKSZ]; /* Input buffer */ \
+ unsigned long i; /* Block counter */ \
+ unsigned off; /* Offset into buffered data */ \
+} pre##_ocb1ctx; \
+ \
+extern const rsvr_policy pre##_ocb1policy; \
+ \
+extern const octet pre##_ocb1noncesz[], pre##_ocb1tagsz[]; \
+ \
+/* --- @pre_ocb1setkey@ --- * \
+ * \
+ * Arguments: @pre_ocb1key *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 OCB1 key block. \
+ */ \
+ \
+extern void pre##_ocb1setkey(pre##_ocb1key */*key*/, \
+ const void */*k*/, size_t /*ksz*/); \
+ \
+/* --- @pre_ocb1aadinit@ --- * \
+ * \
+ * Arguments: @pre_ocb1aadctx *aad@ = pointer to AAD context \
+ * @const pre_ocb1key *key@ = pointer to key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an OCB1 AAD (`additional authenticated \
+ * data') context associated with a given key. AAD \
+ * contexts can be copied and/or reused, saving time if \
+ * the AAD for 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 OCB1 \
+ * operation context because the AAD on its own isn't much \
+ * good. \
+ */ \
+ \
+extern void pre##_ocb1aadinit(pre##_ocb1aadctx */*aad*/, \
+ const pre##_ocb1key */*key*/); \
+ \
+/* --- @pre_ocb1aadhash@ --- * \
+ * \
+ * Arguments: @pre_ocb1aadctx *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##_ocb1aadhash(pre##_ocb1aadctx */*aad*/, \
+ const void */*p*/, size_t /*sz*/); \
+ \
+/* --- @pre_ocb1aadtag@ --- * \
+ * \
+ * Arguments: @const pre_ocb1aadctx *aad@ = pointer to context block \
+ * @uint32 *u@ = where to write the tag \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Finishes processing AAD and produces a tag which can be \
+ * mixed with an OCB1 checksum. This function is exposed \
+ * for internal reasons and is not expected to be \
+ * generally useful. \
+ */ \
+ \
+extern void pre##_ocb1aadtag(const pre##_ocb1aadctx */*aad*/, \
+ uint32 */*t*/); \
+ \
+/* --- @pre_ocb1init@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 context \
+ * @const pre_ocb1key *key@ = pointer to key block \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce length is bad. \
+ * \
+ * Use: Initialize an OCB1 operation context with a given key. \
+ * \
+ * The original key needn't be kept around any more. \
+ */ \
+ \
+extern int pre##_ocb1init(pre##_ocb1ctx */*ctx*/, \
+ const pre##_ocb1key */*k*/, \
+ const void */*n*/, size_t /*nsz*/); \
+ \
+/* --- @pre_ocb1reinit@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 context \
+ * @const void *n@ = pointer to nonce \
+ * @size_t nsz@ = size of nonce \
+ * \
+ * Returns: Zero on success, @-1@ if the nonce length is bad. \
+ * \
+ * Use: Reinitialize an OCB1 operation context, changing the \
+ * nonce. \
+ */ \
+ \
+extern int pre##_ocb1reinit(pre##_ocb1ctx */*ctx*/, \
+ const void */*n*/, size_t /*nsz*/); \
+ \
+/* --- @pre_ocb1encrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 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. \
+ * \
+ * Note that OCB1 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+extern int pre##_ocb1encrypt(pre##_ocb1ctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_ocb1decrypt@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to OCB1 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. \
+ * \
+ * Note that OCB1 delays output if its input is not a \
+ * whole number of blocks. This means that the output \
+ * might be smaller or larger the input by up to the block \
+ * size. \
+ */ \
+ \
+extern int pre##_ocb1decrypt(pre##_ocb1ctx */*ctx*/, \
+ const void */*src*/, size_t /*sz*/, \
+ buf */*dst*/); \
+ \
+/* --- @pre_ocb1encryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
+ * @const pre_ocb1aadctx *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 OCB1 encryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB1 delays output, so this will \
+ * cause any remaining buffered plaintext to be encrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_ocb1encryptdone(pre##_ocb1ctx */*ctx*/, \
+ const pre##_ocb1aadctx */*aad*/, \
+ buf */*dst*/, \
+ void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- @pre_ocb1decryptdone@ --- * \
+ * \
+ * Arguments: @pre_ocb1ctx *ctx@ = pointer to an OCB1 context \
+ * @const pre_ocb1aadctx *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 OCB1 decryption operation. The @aad@ \
+ * pointer may be null if there is no additional \
+ * authenticated data. OCB1 delays output, so this will \
+ * cause any remaining buffered ciphertext to be decrypted \
+ * and written to @dst@. Anyway, the function will fail \
+ * if the output buffer is broken. \
+ */ \
+ \
+extern int pre##_ocb1decryptdone(pre##_ocb1ctx */*ctx*/, \
+ const pre##_ocb1aadctx */*aad*/, \
+ buf */*dst*/, \
+ const void */*tag*/, size_t /*tsz*/); \
+ \
+/* --- Generic AEAD interface --- */ \
+ \
+extern const gcaead pre##_ocb1;
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif