--- /dev/null
+/* -*-c-*-
+ *
+ * $Id: cbc-def.h,v 1.1 1999/12/10 23:16:39 mdw Exp $
+ *
+ * Definitions for cipher block chaining mode
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: cbc-def.h,v $
+ * Revision 1.1 1999/12/10 23:16:39 mdw
+ * Split mode macros into interface and implementation.
+ *
+ */
+
+#ifndef CATACOMB_CBC_DEF_H
+#define CATACOMB_CBC_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+# include "gcipher.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @CBC_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for CBC stealing mode.
+ */
+
+#define CBC_DEF(PRE, pre) \
+ \
+/* --- @pre_cbcgetiv@ --- * \
+ * \
+ * Arguments: @const pre_cbcctx *ctx@ = pointer to CBC context block \
+ * @void *iv#@ = pointer to output data block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reads the currently set IV. Reading and setting an IV \
+ * is transparent to the CBC encryption or decryption \
+ * process. \
+ */ \
+ \
+void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv) \
+{ \
+ BLKC_STORE(PRE, iv, ctx->iv); \
+} \
+ \
+/* --- @pre_cbcsetiv@ --- * \
+ * \
+ * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
+ * @cnost void *iv@ = pointer to IV to set \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Sets the IV to use for subsequent encryption. \
+ */ \
+ \
+void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv) \
+{ \
+ BLKC_LOAD(PRE, ctx->iv, iv); \
+} \
+ \
+/* --- @pre_cbcsetkey@ --- * \
+ * \
+ * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
+ * @const pre_ctx *k@ = pointer to cipher context \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Sets the CBC context to use a different cipher key. \
+ */ \
+ \
+void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k) \
+{ \
+ ctx->ctx = *k; \
+} \
+ \
+/* --- @pre_cbcinit@ --- * \
+ * \
+ * Arguments: @pre_cbcctx *ctx@ = pointer to cipher context \
+ * @const void *key@ = pointer to the key buffer \
+ * @size_t sz@ = size of the key \
+ * @const void *iv@ = pointer to initialization vector \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a CBC context ready for use. The @iv@ \
+ * argument may be passed as a null pointer to set a zero \
+ * IV. Apart from that, this call is equivalent to calls \
+ * to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@. \
+ */ \
+ \
+void pre##_cbcinit(pre##_cbcctx *ctx, \
+ const void *key, size_t sz, \
+ const void *iv) \
+{ \
+ static octet zero[PRE##_BLKSZ] = { 0 }; \
+ pre##_init(&ctx->ctx, key, sz); \
+ BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero); \
+} \
+ \
+/* --- @pre_cbcencrypt@ --- * \
+ * \
+ * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
+ * @const void *src@ = pointer to source data \
+ * @void *dest@ = pointer to destination data \
+ * @size_t sz@ = size of block to be encrypted \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Encrypts a block with a block cipher in CBC mode, with \
+ * ciphertext stealing and other clever tricks. \
+ * Essentially, data can be encrypted in arbitrary sized \
+ * chunks, although decryption must use the same chunks. \
+ */ \
+ \
+void pre##_cbcencrypt(pre##_cbcctx *ctx, \
+ const void *src, void *dest, \
+ size_t sz) \
+{ \
+ const octet *s = src; \
+ octet *d = dest; \
+ \
+ /* --- Empty blocks are trivial --- */ \
+ \
+ if (!sz) \
+ return; \
+ \
+ /* --- Extra magical case for a short block --- * \
+ * \
+ * Encrypt the IV, then exclusive-or the plaintext with the octets \
+ * of the encrypted IV, shifting ciphertext octets in instead. This \
+ * basically switches over to CFB. \
+ */ \
+ \
+ if (sz < PRE##_BLKSZ) { \
+ octet b[PRE##_BLKSZ]; \
+ unsigned i; \
+ \
+ pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
+ BLKC_STORE(PRE, b, ctx->iv); \
+ for (i = 0; i < sz; i++) \
+ d[i] = b[i] ^ s[i]; \
+ memmove(b, b + sz, PRE##_BLKSZ - sz); \
+ memcpy(b + PRE##_BLKSZ - sz, d, sz); \
+ BLKC_LOAD(PRE, ctx->iv, b); \
+ return; \
+ } \
+ \
+ /* --- Do the main chunk of encryption --- * \
+ * \
+ * This will do the whole lot if it's a whole number of blocks. For \
+ * each block, XOR it with the previous ciphertext in @iv@, encrypt, \
+ * and keep a copy of the ciphertext for the next block. \
+ */ \
+ \
+ while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ BLKC_XLOAD(PRE, ctx->iv, s); \
+ pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
+ BLKC_STORE(PRE, d, ctx->iv); \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ sz -= PRE##_BLKSZ; \
+ } \
+ \
+ /* --- Do the tail-end block and bit-left-over --- * \
+ * \
+ * This isn't very efficient. That shouldn't matter much. \
+ */ \
+ \
+ if (sz) { \
+ octet b[PRE##_BLKSZ]; \
+ unsigned i; \
+ \
+ /* --- Let @sz@ be the size of the partial block --- */ \
+ \
+ sz -= PRE##_BLKSZ; \
+ \
+ /* --- First stage --- * \
+ * \
+ * XOR the complete block with the current IV, and encrypt it. The \
+ * first part of the result is the partial ciphertext block. Don't \
+ * write that out yet, because I've not read the partial plaintext \
+ * block. \
+ */ \
+ \
+ BLKC_XLOAD(PRE, ctx->iv, s); \
+ pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
+ BLKC_STORE(PRE, b, ctx->iv); \
+ \
+ /* --- Second stage --- * \
+ * \
+ * Now XOR in the partial plaintext block, writing out the \
+ * ciphertext as I go. Then encrypt, and write the complete \
+ * ciphertext block. \
+ */ \
+ \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ for (i = 0; i < sz; i++) { \
+ register octet x = b[i]; \
+ b[i] ^= s[i]; \
+ d[i] = x; \
+ } \
+ BLKC_LOAD(PRE, ctx->iv, b); \
+ pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
+ BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv); \
+ } \
+ \
+ /* --- Done --- */ \
+ \
+ return; \
+} \
+ \
+/* --- @pre_cbcdecrypt@ --- * \
+ * \
+ * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
+ * @const void *src@ = pointer to source data \
+ * @void *dest@ = pointer to destination data \
+ * @size_t sz@ = size of block to be encrypted \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Decrypts a block with a block cipher in CBC mode, with \
+ * ciphertext stealing and other clever tricks. \
+ * Essentially, data can be encrypted in arbitrary sized \
+ * chunks, although decryption must use the same chunks. \
+ */ \
+ \
+void pre##_cbcdecrypt(pre##_cbcctx *ctx, \
+ const void *src, void *dest, \
+ size_t sz) \
+{ \
+ const octet *s = src; \
+ octet *d = dest; \
+ \
+ /* --- Empty blocks are trivial --- */ \
+ \
+ if (!sz) \
+ return; \
+ \
+ /* --- Extra magical case for a short block --- * \
+ * \
+ * Encrypt the IV, then exclusive-or the ciphertext with the octets \
+ * of the encrypted IV, shifting ciphertext octets in instead. This \
+ * basically switches over to CFB. \
+ */ \
+ \
+ if (sz < PRE##_BLKSZ) { \
+ octet b[PRE##_BLKSZ], c[PRE##_BLKSZ]; \
+ unsigned i; \
+ \
+ pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv); \
+ BLKC_STORE(PRE, b, ctx->iv); \
+ for (i = 0; i < sz; i++) { \
+ register octet x = s[i]; \
+ d[i] = b[i] ^ x; \
+ c[i] = x; \
+ } \
+ memmove(b, b + sz, PRE##_BLKSZ - sz); \
+ memcpy(b + PRE##_BLKSZ - sz, c, sz); \
+ BLKC_LOAD(PRE, ctx->iv, b); \
+ return; \
+ } \
+ \
+ /* --- Do the main chunk of decryption --- * \
+ * \
+ * This will do the whole lot if it's a whole number of blocks. For \
+ * each block, decrypt, XOR it with the previous ciphertext in @iv@, \
+ * and keep a copy of the ciphertext for the next block. \
+ */ \
+ \
+ while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, niv, s); \
+ pre##_dblk(&ctx->ctx, niv, b); \
+ BLKC_XSTORE(PRE, d, b, ctx->iv); \
+ BLKC_MOVE(PRE, ctx->iv, niv); \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ sz -= PRE##_BLKSZ; \
+ } \
+ \
+ /* --- Do the tail-end block and bit-left-over --- * \
+ * \
+ * This isn't very efficient. That shouldn't matter much. \
+ */ \
+ \
+ if (sz) { \
+ octet b[PRE##_BLKSZ]; \
+ uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4]; \
+ unsigned i; \
+ \
+ /* --- Let @sz@ be the size of the partial block --- */ \
+ \
+ sz -= PRE##_BLKSZ; \
+ \
+ /* --- First stage --- * \
+ * \
+ * Take the complete ciphertext block, and decrypt it. This block \
+ * is carried over for the next encryption operation. \
+ */ \
+ \
+ BLKC_LOAD(PRE, niv, s); \
+ pre##_dblk(&ctx->ctx, niv, bk); \
+ \
+ /* --- Second stage --- * \
+ * \
+ * XORing the first few bytes of this with the partial ciphertext \
+ * block recovers the partial plaintext block. At the same time, \
+ * write the partial ciphertext block's contents in ready for stage \
+ * three. \
+ */ \
+ \
+ BLKC_STORE(PRE, b, bk); \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ for (i = 0; i < sz; i++) { \
+ register octet x = s[i]; \
+ d[i] = b[i] ^ x; \
+ b[i] = x; \
+ } \
+ \
+ /* --- Third stage --- * \
+ * \
+ * Decrypt the block we've got left, and XOR with the initial IV to \
+ * recover the complete plaintext block. \
+ */ \
+ \
+ BLKC_LOAD(PRE, bk, b); \
+ pre##_dblk(&ctx->ctx, bk, bk); \
+ BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv); \
+ BLKC_MOVE(PRE, ctx->iv, niv); \
+ } \
+ \
+ /* --- Done --- */ \
+ \
+ return; \
+} \
+ \
+/* --- Generic cipher interface --- */ \
+ \
+static const gcipher_ops gops; \
+ \
+typedef struct gctx { \
+ gcipher c; \
+ pre##_cbcctx k; \
+} gctx; \
+ \
+static gcipher *ginit(const void *k, size_t sz) \
+{ \
+ gctx *g = CREATE(gctx); \
+ g->c.ops = &gops; \
+ pre##_cbcinit(&g->k, k, sz, 0); \
+ return (&g->c); \
+} \
+ \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_cbcencrypt(&g->k, s, t, sz); \
+} \
+ \
+static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_cbcdecrypt(&g->k, s, t, sz); \
+} \
+ \
+static void gdestroy(gcipher *c) \
+{ \
+ gctx *g = (gctx *)c; \
+ DESTROY(g); \
+} \
+ \
+static void gsetiv(gcipher *c, const void *iv) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_cbcsetiv(&g->k, iv); \
+} \
+ \
+static const gcipher_ops gops = { \
+ &pre##_cbc.b, \
+ gencrypt, gdecrypt, gdestroy, gsetiv, 0 \
+}; \
+ \
+const gccipher pre##_cbc = { \
+ { #pre "-cbc", PRE##_KEYSZ, PRE##_BLKSZ }, \
+ ginit \
+}; \
+ \
+CBC_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @CBC_TEST@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use: Standard test rig for CBC functions.
+ */
+
+#define CBC_TEST(PRE, pre) \
+ \
+/* --- Initial plaintext for the test --- */ \
+ \
+static const octet text[] = TEXT; \
+ \
+/* --- Key and IV to use --- */ \
+ \
+static const octet key[] = KEY; \
+static const octet iv[] = IV; \
+ \
+/* --- Buffers for encryption and decryption output --- */ \
+ \
+static octet ct[sizeof(text)]; \
+static octet pt[sizeof(text)]; \
+ \
+static void hexdump(const octet *p, size_t sz) \
+{ \
+ const octet *q = p + sz; \
+ for (sz = 0; p < q; p++, sz++) { \
+ printf("%02x", *p); \
+ if ((sz + 1) % PRE##_BLKSZ == 0) \
+ putchar(':'); \
+ } \
+} \
+ \
+int main(void) \
+{ \
+ size_t sz = 0, rest; \
+ pre##_cbcctx ctx; \
+ pre##_ctx k; \
+ int status = 0; \
+ int done = 0; \
+ \
+ size_t keysz = PRE##_KEYSZ ? \
+ PRE##_KEYSZ : strlen((const char *)key); \
+ \
+ fputs(#pre "-cbc: ", stdout); \
+ \
+ pre##_init(&k, key, keysz); \
+ pre##_cbcsetkey(&ctx, &k); \
+ \
+ while (sz <= sizeof(text)) { \
+ rest = sizeof(text) - sz; \
+ memcpy(ct, text, sizeof(text)); \
+ pre##_cbcsetiv(&ctx, iv); \
+ pre##_cbcencrypt(&ctx, ct, ct, sz); \
+ pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest); \
+ memcpy(pt, ct, sizeof(text)); \
+ pre##_cbcsetiv(&ctx, iv); \
+ pre##_cbcdecrypt(&ctx, pt, pt, sz); \
+ pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest); \
+ if (memcmp(pt, text, sizeof(text)) == 0) { \
+ done++; \
+ if (sizeof(text) < 40 || done % 8 == 0) \
+ fputc('.', stdout); \
+ if (done % 480 == 0) \
+ fputs("\n\t", stdout); \
+ fflush(stdout); \
+ } else { \
+ printf("\nError (sz = %lu)\n", (unsigned long)sz); \
+ status = 1; \
+ printf("\tplaintext = "); hexdump(text, sz); \
+ printf(", "); hexdump(text + sz, rest); \
+ fputc('\n', stdout); \
+ printf("\tciphertext = "); hexdump(ct, sz); \
+ printf(", "); hexdump(ct + sz, rest); \
+ fputc('\n', stdout); \
+ printf("\trecovered text = "); hexdump(pt, sz); \
+ printf(", "); hexdump(pt + sz, rest); \
+ fputc('\n', stdout); \
+ fputc('\n', stdout); \
+ } \
+ if (sz < 63) \
+ sz++; \
+ else \
+ sz += 9; \
+ } \
+ \
+ fputs(status ? " failed\n" : " ok\n", stdout); \
+ return (status); \
+}
+
+#else
+# define CBC_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
/* -*-c-*-
*
- * $Id: cbc.h,v 1.1 1999/09/03 08:41:11 mdw Exp $
+ * $Id: cbc.h,v 1.2 1999/12/10 23:16:39 mdw Exp $
*
* Ciphertext block chaining for block ciphers
*
/*----- Revision history --------------------------------------------------*
*
* $Log: cbc.h,v $
+ * Revision 1.2 1999/12/10 23:16:39 mdw
+ * Split mode macros into interface and implementation.
+ *
* Revision 1.1 1999/09/03 08:41:11 mdw
* Initial import.
*
*/
-#ifndef CBC_H
-#define CBC_H
+#ifndef CATACOMB_CBC_H
+#define CATACOMB_CBC_H
#ifdef __cplusplus
extern "C" {
/*----- Header files ------------------------------------------------------*/
-#include <string.h>
+#include <stddef.h>
#include <mLib/bits.h>
-#ifndef BLKC_H
-# include "blkc.h"
+#ifndef CATACOMB_GCIPHER_H
+# include "gcipher.h"
#endif
/*----- Macros ------------------------------------------------------------*/
#define CBC_DECL(PRE, pre) \
\
-typedef struct pre ## _cbcctx { \
- pre ## _ctx ctx; /* Underlying cipher context */ \
- uint32 iv[PRE ## _BLKSZ / 4]; /* Previous ciphertext or IV */ \
-} pre ## _cbcctx; \
- \
-extern void pre ## _cbcgetiv(const pre ## _cbcctx */*ctx*/, \
- void */*iv*/); \
- \
-extern void pre ## _cbcsetiv(pre ## _cbcctx */*ctx*/, \
- const void */*iv*/); \
- \
-extern void pre ## _cbcsetkey(pre ## _cbcctx */*ctx*/, \
- const pre ## _ctx */*k*/); \
- \
-extern void pre ## _cbcinit(pre ## _cbcctx */*ctx*/, \
- const void */*key*/, size_t /*sz*/, \
- const void */*iv*/); \
+/* --- Cipher block chaining context --- */ \
\
-extern void pre ## _cbcencrypt(pre ## _cbcctx */*ctx*/, \
- const void */*src*/, void */*dest*/, \
- size_t /*sz*/); \
- \
-extern void pre ## _cbcdecrypt(pre ## _cbcctx */*ctx*/, \
- const void */*src*/, void */*dest*/, \
- size_t /*sz*/); \
-
-/* --- @CBC_DEF@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use: Creates an implementation for CBC stealing mode.
- */
-
-#define CBC_DEF(PRE, pre) \
+typedef struct pre##_cbcctx { \
+ pre##_ctx ctx; /* Underlying cipher context */ \
+ uint32 iv[PRE##_BLKSZ / 4]; /* Previous ciphertext or IV */ \
+} pre##_cbcctx; \
\
/* --- @pre_cbcgetiv@ --- * \
* \
* process. \
*/ \
\
-void pre ## _cbcgetiv(const pre ## _cbcctx *ctx, void *iv) \
-{ \
- BLKC_STORE(PRE, iv, ctx->iv); \
-} \
+extern void pre##_cbcgetiv(const pre##_cbcctx */*ctx*/, \
+ void */*iv*/); \
\
/* --- @pre_cbcsetiv@ --- * \
* \
* Use: Sets the IV to use for subsequent encryption. \
*/ \
\
-void pre ## _cbcsetiv(pre ## _cbcctx *ctx, const void *iv) \
-{ \
- BLKC_LOAD(PRE, ctx->iv, iv); \
-} \
+extern void pre##_cbcsetiv(pre##_cbcctx */*ctx*/, \
+ const void */*iv*/); \
\
/* --- @pre_cbcsetkey@ --- * \
* \
* Use: Sets the CBC context to use a different cipher key. \
*/ \
\
-void pre ## _cbcsetkey(pre ## _cbcctx *ctx, const pre ## _ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+extern void pre##_cbcsetkey(pre##_cbcctx */*ctx*/, \
+ const pre##_ctx */*k*/); \
\
/* --- @pre_cbcinit@ --- * \
* \
* to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@. \
*/ \
\
-void pre ## _cbcinit(pre ## _cbcctx *ctx, \
- const void *key, size_t sz, \
- const void *iv) \
-{ \
- static octet zero[PRE ## _BLKSZ] = { 0 }; \
- pre ## _init(&ctx->ctx, key, sz); \
- BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero); \
-} \
+extern void pre##_cbcinit(pre##_cbcctx */*ctx*/, \
+ const void */*key*/, size_t /*sz*/, \
+ const void */*iv*/); \
\
/* --- @pre_cbcencrypt@ --- * \
* \
* chunks, although decryption must use the same chunks. \
*/ \
\
-void pre ## _cbcencrypt(pre ## _cbcctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
-{ \
- const octet *s = src; \
- octet *d = dest; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- Extra magical case for a short block --- * \
- * \
- * Encrypt the IV, then exclusive-or the plaintext with the octets \
- * of the encrypted IV, shifting ciphertext octets in instead. This \
- * basically switches over to CFB. \
- */ \
- \
- if (sz < PRE ## _BLKSZ) { \
- octet b[PRE ## _BLKSZ]; \
- unsigned i; \
- \
- pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
- for (i = 0; i < sz; i++) \
- d[i] = b[i] ^ s[i]; \
- memmove(b, b + sz, PRE ## _BLKSZ - sz); \
- memcpy(b + PRE ## _BLKSZ - sz, d, sz); \
- BLKC_LOAD(PRE, ctx->iv, b); \
- return; \
- } \
- \
- /* --- Do the main chunk of encryption --- * \
- * \
- * This will do the whole lot if it's a whole number of blocks. For \
- * each block, XOR it with the previous ciphertext in @iv@, encrypt, \
- * and keep a copy of the ciphertext for the next block. \
- */ \
- \
- while (sz >= 2 * PRE ## _BLKSZ || sz == PRE ## _BLKSZ) { \
- BLKC_XLOAD(PRE, ctx->iv, s); \
- pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, d, ctx->iv); \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- sz -= PRE ## _BLKSZ; \
- } \
- \
- /* --- Do the tail-end block and bit-left-over --- * \
- * \
- * This isn't very efficient. That shouldn't matter much. \
- */ \
- \
- if (sz) { \
- octet b[PRE ## _BLKSZ]; \
- unsigned i; \
- \
- /* --- Let @sz@ be the size of the partial block --- */ \
- \
- sz -= PRE ## _BLKSZ; \
- \
- /* --- First stage --- * \
- * \
- * XOR the complete block with the current IV, and encrypt it. The \
- * first part of the result is the partial ciphertext block. Don't \
- * write that out yet, because I've not read the partial plaintext \
- * block. \
- */ \
- \
- BLKC_XLOAD(PRE, ctx->iv, s); \
- pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
- \
- /* --- Second stage --- * \
- * \
- * Now XOR in the partial plaintext block, writing out the \
- * ciphertext as I go. Then encrypt, and write the complete \
- * ciphertext block. \
- */ \
- \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- for (i = 0; i < sz; i++) { \
- register octet x = b[i]; \
- b[i] ^= s[i]; \
- d[i] = x; \
- } \
- BLKC_LOAD(PRE, ctx->iv, b); \
- pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, d - PRE ## _BLKSZ, ctx->iv); \
- } \
- \
- /* --- Done --- */ \
- \
- return; \
-} \
+extern void pre##_cbcencrypt(pre##_cbcctx */*ctx*/, \
+ const void */*src*/, void */*dest*/, \
+ size_t /*sz*/); \
\
/* --- @pre_cbcdecrypt@ --- * \
* \
* \
* Returns: --- \
* \
- * Use: Encrypts a block with a block cipher in CBC mode, with \
+ * Use: Decrypts a block with a block cipher in CBC mode, with \
* ciphertext stealing and other clever tricks. \
* Essentially, data can be encrypted in arbitrary sized \
* chunks, although decryption must use the same chunks. \
*/ \
\
-void pre ## _cbcdecrypt(pre ## _cbcctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
-{ \
- const octet *s = src; \
- octet *d = dest; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- Extra magical case for a short block --- * \
- * \
- * Encrypt the IV, then exclusive-or the ciphertext with the octets \
- * of the encrypted IV, shifting ciphertext octets in instead. This \
- * basically switches over to CFB. \
- */ \
- \
- if (sz < PRE ## _BLKSZ) { \
- octet b[PRE ## _BLKSZ], c[PRE ## _BLKSZ]; \
- unsigned i; \
- \
- pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
- BLKC_STORE(PRE, b, ctx->iv); \
- for (i = 0; i < sz; i++) { \
- register octet x = s[i]; \
- d[i] = b[i] ^ x; \
- c[i] = x; \
- } \
- memmove(b, b + sz, PRE ## _BLKSZ - sz); \
- memcpy(b + PRE ## _BLKSZ - sz, c, sz); \
- BLKC_LOAD(PRE, ctx->iv, b); \
- return; \
- } \
- \
- /* --- Do the main chunk of decryption --- * \
- * \
- * This will do the whole lot if it's a whole number of blocks. For \
- * each block, decrypt, XOR it with the previous ciphertext in @iv@, \
- * and keep a copy of the ciphertext for the next block. \
- */ \
+extern void pre##_cbcdecrypt(pre##_cbcctx */*ctx*/, \
+ const void */*src*/, void */*dest*/, \
+ size_t /*sz*/); \
\
- while (sz >= 2 * PRE ## _BLKSZ || sz == PRE ## _BLKSZ) { \
- uint32 b[PRE ## _BLKSZ / 4], niv[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, niv, s); \
- pre ## _dblk(&ctx->ctx, niv, b); \
- BLKC_XSTORE(PRE, d, b, ctx->iv); \
- BLKC_MOVE(PRE, ctx->iv, niv); \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- sz -= PRE ## _BLKSZ; \
- } \
+/* --- Generic cipher interface --- */ \
\
- /* --- Do the tail-end block and bit-left-over --- * \
- * \
- * This isn't very efficient. That shouldn't matter much. \
- */ \
- \
- if (sz) { \
- octet b[PRE ## _BLKSZ]; \
- uint32 bk[PRE ## _BLKSZ / 4], niv[PRE ## _BLKSZ / 4]; \
- unsigned i; \
- \
- /* --- Let @sz@ be the size of the partial block --- */ \
- \
- sz -= PRE ## _BLKSZ; \
- \
- /* --- First stage --- * \
- * \
- * Take the complete ciphertext block, and decrypt it. This block \
- * is carried over for the next encryption operation. \
- */ \
- \
- BLKC_LOAD(PRE, niv, s); \
- pre ## _dblk(&ctx->ctx, niv, bk); \
- \
- /* --- Second stage --- * \
- * \
- * XORing the first few bytes of this with the partial ciphertext \
- * block recovers the partial plaintext block. At the same time, \
- * write the partial ciphertext block's contents in ready for stage \
- * three. \
- */ \
- \
- BLKC_STORE(PRE, b, bk); \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- for (i = 0; i < sz; i++) { \
- register octet x = s[i]; \
- d[i] = b[i] ^ x; \
- b[i] = x; \
- } \
- \
- /* --- Third stage --- * \
- * \
- * Decrypt the block we've got left, and XOR with the initial IV to \
- * recover the complete plaintext block. \
- */ \
- \
- BLKC_LOAD(PRE, bk, b); \
- pre ## _dblk(&ctx->ctx, bk, bk); \
- BLKC_XSTORE(PRE, d - PRE ## _BLKSZ, bk, ctx->iv); \
- BLKC_MOVE(PRE, ctx->iv, niv); \
- } \
- \
- /* --- Done --- */ \
- \
- return; \
-} \
- \
-CBC_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @CBC_TEST@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use: Standard test rig for CBC functions.
- */
-
-#define CBC_TEST(PRE, pre) \
- \
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
- \
-/* --- Key and IV to use --- */ \
- \
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
- \
-/* --- Buffers for encryption and decryption output --- */ \
- \
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
- \
-static void hexdump(const octet *p, size_t sz) \
-{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((sz + 1) % PRE ## _BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
- \
-int main(void) \
-{ \
- size_t sz = 0, rest; \
- pre ## _cbcctx ctx; \
- pre ## _ctx k; \
- int status = 0; \
- int done = 0; \
- \
- size_t keysz = PRE ## _KEYSZ ? \
- PRE ## _KEYSZ : strlen((const char *)key); \
- \
- fputs(#pre "-cbc: ", stdout); \
- \
- pre ## _init(&k, key, keysz); \
- pre ## _cbcsetkey(&ctx, &k); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre ## _cbcsetiv(&ctx, iv); \
- pre ## _cbcencrypt(&ctx, ct, ct, sz); \
- pre ## _cbcencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre ## _cbcsetiv(&ctx, iv); \
- pre ## _cbcdecrypt(&ctx, pt, pt, sz); \
- pre ## _cbcdecrypt(&ctx, pt + sz, pt + sz, rest); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz); \
- printf(", "); hexdump(text + sz, rest); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz); \
- printf(", "); hexdump(ct + sz, rest); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz); \
- printf(", "); hexdump(pt + sz, rest); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
-}
-
-#else
-# define CBC_TEST(PRE, pre)
-#endif
+extern const gccipher pre##_cbc;
/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * $Id: cfb-def.h,v 1.1 1999/12/10 23:16:39 mdw Exp $
+ *
+ * Definitions for ciphertext feedback mode
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: cfb-def.h,v $
+ * Revision 1.1 1999/12/10 23:16:39 mdw
+ * Split mode macros into interface and implementation.
+ *
+ */
+
+#ifndef CATACOMB_CFB_DEF_H
+#define CATACOMB_CFB_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+# include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @CFB_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for CFB mode.
+ */
+
+#define CFB_DEF(PRE, pre) \
+ \
+/* --- @pre_cfbgetiv@ --- * \
+ * \
+ * Arguments: @const pre_cfbctx *ctx@ = pointer to CFB context block \
+ * @void *iv#@ = pointer to output data block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reads the currently set IV. Reading and setting an IV \
+ * is not transparent to the cipher. It will add a `step' \
+ * which must be matched by a similar operation during \
+ * decryption. \
+ */ \
+ \
+void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv) \
+{ \
+ octet *p = iv; \
+ int off = ctx->off; \
+ int rest = PRE##_BLKSZ - off; \
+ memcpy(p, ctx->iv + off, rest); \
+ memcpy(p + rest, ctx->iv, off); \
+} \
+ \
+/* --- @pre_cfbsetiv@ --- * \
+ * \
+ * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \
+ * @cnost void *iv@ = pointer to IV to set \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Sets the IV to use for subsequent encryption. \
+ */ \
+ \
+void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv) \
+{ \
+ uint32 niv[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, niv, iv); \
+ pre##_eblk(&ctx->ctx, niv, niv); \
+ BLKC_STORE(PRE, ctx->iv, niv); \
+ ctx->off = 0; \
+} \
+ \
+/* --- @pre_cfbbdry@ --- * \
+ * \
+ * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Inserts a boundary during encryption. Successful \
+ * decryption must place a similar boundary. \
+ */ \
+ \
+void pre##_cfbbdry(pre##_cfbctx *ctx) \
+{ \
+ octet iv[PRE##_BLKSZ]; \
+ pre##_cfbgetiv(ctx, iv); \
+ pre##_cfbsetiv(ctx, iv); \
+ BURN(iv); \
+} \
+ \
+/* --- @pre_cfbsetkey@ --- * \
+ * \
+ * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \
+ * @const pre_ctx *k@ = pointer to cipher context \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Sets the CFB context to use a different cipher key. \
+ */ \
+ \
+void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k) \
+{ \
+ ctx->ctx = *k; \
+} \
+ \
+/* --- @pre_cfbinit@ --- * \
+ * \
+ * Arguments: @pre_cfbctx *ctx@ = pointer to cipher context \
+ * @const void *key@ = pointer to the key buffer \
+ * @size_t sz@ = size of the key \
+ * @const void *iv@ = pointer to initialization vector \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a CFB context ready for use. You should \
+ * ensure that the IV chosen is unique: reusing an IV will \
+ * compromise the security of at least the first block \
+ * encrypted. This is equivalent to calls to @pre_init@, \
+ * @pre_cfbsetkey@ and @pre_cfbsetiv@. \
+ */ \
+ \
+void pre##_cfbinit(pre##_cfbctx *ctx, \
+ const void *key, size_t sz, \
+ const void *iv) \
+{ \
+ static octet zero[PRE##_BLKSZ] = { 0 }; \
+ pre##_init(&ctx->ctx, key, sz); \
+ pre##_cfbsetiv(ctx, iv ? iv : zero); \
+} \
+ \
+/* --- @pre_cfbencrypt@ --- * \
+ * \
+ * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \
+ * @const void *src@ = pointer to source data \
+ * @void *dest@ = pointer to destination data \
+ * @size_t sz@ = size of block to be encrypted \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Encrypts a block with a block cipher in CFB mode. The \
+ * input block may be arbitrary in size. CFB mode is not \
+ * sensitive to block boundaries. \
+ */ \
+ \
+void pre##_cfbencrypt(pre##_cfbctx *ctx, \
+ const void *src, void *dest, \
+ size_t sz) \
+{ \
+ const octet *s = src; \
+ octet *d = dest; \
+ int off = ctx->off; \
+ \
+ /* --- Empty blocks are trivial --- */ \
+ \
+ if (!sz) \
+ return; \
+ \
+ /* --- If I can deal with the block from my buffer, do that --- */ \
+ \
+ if (sz < PRE##_BLKSZ - off) \
+ goto small; \
+ \
+ /* --- Finish off what's left in my buffer --- */ \
+ \
+ while (off < PRE##_BLKSZ) { \
+ register octet x = *s++; \
+ *d++ = ctx->iv[off++] ^= x; \
+ sz--; \
+ } \
+ \
+ /* --- Main encryption loop --- */ \
+ \
+ { \
+ uint32 iv[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, iv, ctx->iv); \
+ \
+ for (;;) { \
+ pre##_eblk(&ctx->ctx, iv, iv); \
+ if (sz < PRE##_BLKSZ) \
+ break; \
+ BLKC_XLOAD(PRE, iv, s); \
+ BLKC_STORE(PRE, d, iv); \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ sz -= PRE##_BLKSZ; \
+ } \
+ off = 0; \
+ BLKC_STORE(PRE, ctx->iv, iv); \
+ } \
+ \
+ /* --- Tidying up the tail end --- */ \
+ \
+ if (sz) { \
+ small: \
+ do { \
+ register octet x = *s++; \
+ *d++ = ctx->iv[off++] ^= x; \
+ sz--; \
+ } while (sz); \
+ } \
+ \
+ /* --- Done --- */ \
+ \
+ ctx->off = off; \
+ return; \
+} \
+ \
+/* --- @pre_cfbencrypt@ --- * \
+ * \
+ * Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \
+ * @const void *src@ = pointer to source data \
+ * @void *dest@ = pointer to destination data \
+ * @size_t sz@ = size of block to be encrypted \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Decrypts a block with a block cipher in CFB mode. The \
+ * input block may be arbitrary in size. CFB mode is not \
+ * sensitive to block boundaries. \
+ */ \
+ \
+void pre##_cfbdecrypt(pre##_cfbctx *ctx, \
+ const void *src, void *dest, \
+ size_t sz) \
+{ \
+ const octet *s = src; \
+ octet *d = dest; \
+ int off = ctx->off; \
+ \
+ /* --- Empty blocks are trivial --- */ \
+ \
+ if (!sz) \
+ return; \
+ \
+ /* --- If I can deal with the block from my buffer, do that --- */ \
+ \
+ if (sz < PRE##_BLKSZ - off) \
+ goto small; \
+ \
+ /* --- Finish off what's left in my buffer --- */ \
+ \
+ while (off < PRE##_BLKSZ) { \
+ register octet x = *s++; \
+ *d++ = ctx->iv[off] ^ x; \
+ ctx->iv[off++] = x; \
+ sz--; \
+ } \
+ \
+ /* --- Main encryption loop --- */ \
+ \
+ { \
+ uint32 iv[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, iv, ctx->iv); \
+ \
+ for (;;) { \
+ uint32 x[PRE##_BLKSZ / 4]; \
+ pre##_eblk(&ctx->ctx, iv, iv); \
+ if (sz < PRE##_BLKSZ) \
+ break; \
+ BLKC_LOAD(PRE, x, s); \
+ BLKC_XSTORE(PRE, d, iv, x); \
+ BLKC_MOVE(PRE, iv, x); \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ sz -= PRE##_BLKSZ; \
+ } \
+ off = 0; \
+ BLKC_STORE(PRE, ctx->iv, iv); \
+ } \
+ \
+ /* --- Tidying up the tail end --- */ \
+ \
+ if (sz) { \
+ small: \
+ do { \
+ register octet x = *s++; \
+ *d++ = ctx->iv[off] ^ x; \
+ ctx->iv[off++] = x; \
+ sz--; \
+ } while (sz); \
+ } \
+ \
+ /* --- Done --- */ \
+ \
+ ctx->off = off; \
+ return; \
+} \
+ \
+/* --- Generic cipher interface --- */ \
+ \
+static const gcipher_ops gops; \
+ \
+typedef struct gctx { \
+ gcipher c; \
+ pre##_cfbctx k; \
+} gctx; \
+ \
+static gcipher *ginit(const void *k, size_t sz) \
+{ \
+ gctx *g = CREATE(gctx); \
+ g->c.ops = &gops; \
+ pre##_cfbinit(&g->k, k, sz, 0); \
+ return (&g->c); \
+} \
+ \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_cfbencrypt(&g->k, s, t, sz); \
+} \
+ \
+static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_cfbdecrypt(&g->k, s, t, sz); \
+} \
+ \
+static void gdestroy(gcipher *c) \
+{ \
+ gctx *g = (gctx *)c; \
+ DESTROY(g); \
+} \
+ \
+static void gsetiv(gcipher *c, const void *iv) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_cfbsetiv(&g->k, iv); \
+} \
+ \
+static void gbdry(gcipher *c) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_cfbbdry(&g->k); \
+} \
+ \
+static const gcipher_ops gops = { \
+ &pre##_cfb.b, \
+ gencrypt, gdecrypt, gdestroy, gsetiv, gbdry \
+}; \
+ \
+const gccipher pre##_cfb = { \
+ { #pre "-cfb", PRE##_KEYSZ, PRE##_BLKSZ }, \
+ ginit \
+}; \
+ \
+CFB_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @CFB_TEST@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use: Standard test rig for CFB functions.
+ */
+
+#define CFB_TEST(PRE, pre) \
+ \
+/* --- Initial plaintext for the test --- */ \
+ \
+static const octet text[] = TEXT; \
+ \
+/* --- Key and IV to use --- */ \
+ \
+static const octet key[] = KEY; \
+static const octet iv[] = IV; \
+ \
+/* --- Buffers for encryption and decryption output --- */ \
+ \
+static octet ct[sizeof(text)]; \
+static octet pt[sizeof(text)]; \
+ \
+static void hexdump(const octet *p, size_t sz) \
+{ \
+ const octet *q = p + sz; \
+ for (sz = 0; p < q; p++, sz++) { \
+ printf("%02x", *p); \
+ if ((sz + 1) % PRE##_BLKSZ == 0) \
+ putchar(':'); \
+ } \
+} \
+ \
+int main(void) \
+{ \
+ size_t sz = 0, rest; \
+ pre##_cfbctx ctx; \
+ int status = 0; \
+ int done = 0; \
+ pre##_ctx k; \
+ \
+ size_t keysz = PRE##_KEYSZ ? \
+ PRE##_KEYSZ : strlen((const char *)key); \
+ \
+ fputs(#pre "-cfb: ", stdout); \
+ \
+ pre##_init(&k, key, keysz); \
+ pre##_cfbsetkey(&ctx, &k); \
+ \
+ while (sz <= sizeof(text)) { \
+ rest = sizeof(text) - sz; \
+ memcpy(ct, text, sizeof(text)); \
+ pre##_cfbsetiv(&ctx, iv); \
+ pre##_cfbencrypt(&ctx, ct, ct, sz); \
+ pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest); \
+ memcpy(pt, ct, sizeof(text)); \
+ pre##_cfbsetiv(&ctx, iv); \
+ pre##_cfbdecrypt(&ctx, pt, pt, rest); \
+ pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz); \
+ if (memcmp(pt, text, sizeof(text)) == 0) { \
+ done++; \
+ if (sizeof(text) < 40 || done % 8 == 0) \
+ fputc('.', stdout); \
+ if (done % 480 == 0) \
+ fputs("\n\t", stdout); \
+ fflush(stdout); \
+ } else { \
+ printf("\nError (sz = %lu)\n", (unsigned long)sz); \
+ status = 1; \
+ printf("\tplaintext = "); hexdump(text, sz); \
+ printf(", "); hexdump(text + sz, rest); \
+ fputc('\n', stdout); \
+ printf("\tciphertext = "); hexdump(ct, sz); \
+ printf(", "); hexdump(ct + sz, rest); \
+ fputc('\n', stdout); \
+ printf("\trecovered text = "); hexdump(pt, sz); \
+ printf(", "); hexdump(pt + sz, rest); \
+ fputc('\n', stdout); \
+ fputc('\n', stdout); \
+ } \
+ if (sz < 63) \
+ sz++; \
+ else \
+ sz += 9; \
+ } \
+ \
+ fputs(status ? " failed\n" : " ok\n", stdout); \
+ return (status); \
+}
+
+#else
+# define CFB_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
/* -*-c-*-
*
- * $Id: cfb.h,v 1.1 1999/09/03 08:41:11 mdw Exp $
+ * $Id: cfb.h,v 1.2 1999/12/10 23:16:39 mdw Exp $
*
* Ciphertext feedback for block ciphers
*
/*----- Revision history --------------------------------------------------*
*
* $Log: cfb.h,v $
+ * Revision 1.2 1999/12/10 23:16:39 mdw
+ * Split mode macros into interface and implementation.
+ *
* Revision 1.1 1999/09/03 08:41:11 mdw
* Initial import.
*
*/
-#ifndef CFB_H
-#define CFB_H
+#ifndef CATACOMB_CFB_H
+#define CATACOMB_CFB_H
#ifdef __cplusplus
extern "C" {
/*----- Header files ------------------------------------------------------*/
-#include <string.h>
+#include <stddef.h>
#include <mLib/bits.h>
-#ifndef BLKC_H
-# include "blkc.h"
-#endif
-
-#ifndef PARANOIA_H
-# include "paranoia.h"
+#ifndef CATACOMB_GCIPHER_H
+# include "gcipher.h"
#endif
/*----- Data structures ---------------------------------------------------*/
#define CFB_DECL(PRE, pre) \
\
-typedef struct pre ## _cfbctx { \
- pre ## _ctx ctx; /* Underlying cipher context */ \
- int off; /* Offset into @iv@ buffer */ \
- octet iv[PRE ## _BLKSZ]; /* Previous ciphertext or IV */ \
-} pre ## _cfbctx; \
- \
-extern void pre ## _cfbgetiv(const pre ## _cfbctx */*ctx*/, \
- void */*iv*/); \
- \
-extern void pre ## _cfbsetiv(pre ## _cfbctx */*ctx*/, \
- const void */*iv*/); \
- \
-extern void pre ## _cfbbdry(pre ## _cfbctx */*ctx*/); \
- \
-extern void pre ## _cfbsetkey(pre ## _cfbctx */*ctx*/, \
- const pre ## _ctx */*k*/); \
- \
-extern void pre ## _cfbinit(pre ## _cfbctx */*ctx*/, \
- const void */*key*/, size_t /*sz*/, \
- const void */*iv*/); \
+/* --- Ciphertext feedback context --- */ \
\
-extern void pre ## _cfbencrypt(pre ## _cfbctx */*ctx*/, \
- const void */*src*/, void */*dest*/, \
- size_t /*sz*/); \
- \
-extern void pre ## _cfbdecrypt(pre ## _cfbctx */*ctx*/, \
- const void */*src*/, void */*dest*/, \
- size_t /*sz*/); \
-
-
-/* --- @CFB_DEF@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use: Creates an implementation for CFB mode.
- */
-
-#define CFB_DEF(PRE, pre) \
+typedef struct pre##_cfbctx { \
+ pre##_ctx ctx; /* Underlying cipher context */ \
+ int off; /* Offset into @iv@ buffer */ \
+ octet iv[PRE##_BLKSZ]; /* Previous ciphertext or IV */ \
+} pre##_cfbctx; \
\
/* --- @pre_cfbgetiv@ --- * \
* \
* decryption. \
*/ \
\
-void pre ## _cfbgetiv(const pre ## _cfbctx *ctx, void *iv) \
-{ \
- octet *p = iv; \
- int off = ctx->off; \
- int rest = PRE ## _BLKSZ - off; \
- memcpy(p, ctx->iv + off, rest); \
- memcpy(p + rest, ctx->iv, off); \
-} \
+extern void pre##_cfbgetiv(const pre##_cfbctx */*ctx*/, \
+ void */*iv*/); \
\
/* --- @pre_cfbsetiv@ --- * \
* \
* Use: Sets the IV to use for subsequent encryption. \
*/ \
\
-void pre ## _cfbsetiv(pre ## _cfbctx *ctx, const void *iv) \
-{ \
- uint32 niv[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, niv, iv); \
- pre ## _eblk(&ctx->ctx, niv, niv); \
- BLKC_STORE(PRE, ctx->iv, niv); \
- ctx->off = 0; \
-} \
+extern void pre##_cfbsetiv(pre##_cfbctx */*ctx*/, \
+ const void */*iv*/); \
\
/* --- @pre_cfbbdry@ --- * \
* \
* decryption must place a similar boundary. \
*/ \
\
-void pre ## _cfbbdry(pre ## _cfbctx *ctx) \
-{ \
- octet iv[PRE ## _BLKSZ]; \
- pre ## _cfbgetiv(ctx, iv); \
- pre ## _cfbsetiv(ctx, iv); \
- BURN(iv); \
-} \
+extern void pre##_cfbbdry(pre##_cfbctx */*ctx*/); \
\
/* --- @pre_cfbsetkey@ --- * \
* \
* Use: Sets the CFB context to use a different cipher key. \
*/ \
\
-void pre ## _cfbsetkey(pre ## _cfbctx *ctx, const pre ## _ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+extern void pre##_cfbsetkey(pre##_cfbctx */*ctx*/, \
+ const pre##_ctx */*k*/); \
\
/* --- @pre_cfbinit@ --- * \
* \
* @pre_cfbsetkey@ and @pre_cfbsetiv@. \
*/ \
\
-void pre ## _cfbinit(pre ## _cfbctx *ctx, \
- const void *key, size_t sz, \
- const void *iv) \
-{ \
- static octet zero[PRE ## _BLKSZ] = { 0 }; \
- pre ## _init(&ctx->ctx, key, sz); \
- pre ## _cfbsetiv(ctx, iv ? iv : zero); \
-} \
+extern void pre##_cfbinit(pre##_cfbctx */*ctx*/, \
+ const void */*key*/, size_t /*sz*/, \
+ const void */*iv*/); \
\
/* --- @pre_cfbencrypt@ --- * \
* \
* sensitive to block boundaries. \
*/ \
\
-void pre ## _cfbencrypt(pre ## _cfbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
-{ \
- const octet *s = src; \
- octet *d = dest; \
- int off = ctx->off; \
+extern void pre##_cfbencrypt(pre##_cfbctx */*ctx*/, \
+ const void */*src*/, void */*dest*/, \
+ size_t /*sz*/); \
\
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- If I can deal with the block from my buffer, do that --- */ \
- \
- if (sz < PRE ## _BLKSZ - off) \
- goto small; \
- \
- /* --- Finish off what's left in my buffer --- */ \
- \
- while (off < PRE ## _BLKSZ) { \
- register octet x = *s++; \
- *d++ = ctx->iv[off++] ^= x; \
- sz--; \
- } \
- \
- /* --- Main encryption loop --- */ \
- \
- { \
- uint32 iv[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, iv, ctx->iv); \
- \
- for (;;) { \
- pre ## _eblk(&ctx->ctx, iv, iv); \
- if (sz < PRE ## _BLKSZ) \
- break; \
- BLKC_XLOAD(PRE, iv, s); \
- BLKC_STORE(PRE, d, iv); \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- sz -= PRE ## _BLKSZ; \
- } \
- off = 0; \
- BLKC_STORE(PRE, ctx->iv, iv); \
- } \
- \
- /* --- Tidying up the tail end --- */ \
- \
- if (sz) { \
- small: \
- do { \
- register octet x = *s++; \
- *d++ = ctx->iv[off++] ^= x; \
- sz--; \
- } while (sz); \
- } \
- \
- /* --- Done --- */ \
- \
- ctx->off = off; \
- return; \
-} \
- \
-/* --- @pre_cfbdecrypt@ --- * \
+/* --- @pre_cfbencrypt@ --- * \
* \
* Arguments: @pre_cfbctx *ctx@ = pointer to CFB context block \
* @const void *src@ = pointer to source data \
* \
* Returns: --- \
* \
- * Use: Encrypts a block with a block cipher in CFB mode, with \
- * ciphertext stealing and other clever tricks. \
- * Essentially, data can be encrypted in arbitrary sized \
- * chunks, although decryption must use the same chunks. \
+ * Use: Decrypts a block with a block cipher in CFB mode. The \
+ * input block may be arbitrary in size. CFB mode is not \
+ * sensitive to block boundaries. \
*/ \
\
-void pre ## _cfbdecrypt(pre ## _cfbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
-{ \
- const octet *s = src; \
- octet *d = dest; \
- int off = ctx->off; \
- \
- /* --- Empty blocks are trivial --- */ \
+extern void pre##_cfbdecrypt(pre##_cfbctx */*ctx*/, \
+ const void */*src*/, void */*dest*/, \
+ size_t /*sz*/); \
\
- if (!sz) \
- return; \
+/* --- Generic cipher interface --- */ \
\
- /* --- If I can deal with the block from my buffer, do that --- */ \
- \
- if (sz < PRE ## _BLKSZ - off) \
- goto small; \
- \
- /* --- Finish off what's left in my buffer --- */ \
- \
- while (off < PRE ## _BLKSZ) { \
- register octet x = *s++; \
- *d++ = ctx->iv[off] ^ x; \
- ctx->iv[off++] = x; \
- sz--; \
- } \
- \
- /* --- Main encryption loop --- */ \
- \
- { \
- uint32 iv[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, iv, ctx->iv); \
- \
- for (;;) { \
- uint32 x[PRE ## _BLKSZ / 4]; \
- pre ## _eblk(&ctx->ctx, iv, iv); \
- if (sz < PRE ## _BLKSZ) \
- break; \
- BLKC_LOAD(PRE, x, s); \
- BLKC_XSTORE(PRE, d, iv, x); \
- BLKC_MOVE(PRE, iv, x); \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- sz -= PRE ## _BLKSZ; \
- } \
- off = 0; \
- BLKC_STORE(PRE, ctx->iv, iv); \
- } \
- \
- /* --- Tidying up the tail end --- */ \
- \
- if (sz) { \
- small: \
- do { \
- register octet x = *s++; \
- *d++ = ctx->iv[off] ^ x; \
- ctx->iv[off++] = x; \
- sz--; \
- } while (sz); \
- } \
- \
- /* --- Done --- */ \
- \
- ctx->off = off; \
- return; \
-} \
- \
-CFB_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @CFB_TEST@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use: Standard test rig for CFB functions.
- */
-
-#define CFB_TEST(PRE, pre) \
- \
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
- \
-/* --- Key and IV to use --- */ \
- \
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
- \
-/* --- Buffers for encryption and decryption output --- */ \
- \
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
- \
-static void hexdump(const octet *p, size_t sz) \
-{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((sz + 1) % PRE ## _BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
- \
-int main(void) \
-{ \
- size_t sz = 0, rest; \
- pre ## _cfbctx ctx; \
- int status = 0; \
- int done = 0; \
- pre ## _ctx k; \
- \
- size_t keysz = PRE ## _KEYSZ ? \
- PRE ## _KEYSZ : strlen((const char *)key); \
- \
- fputs(#pre "-cfb: ", stdout); \
- \
- pre ## _init(&k, key, keysz); \
- pre ## _cfbsetkey(&ctx, &k); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre ## _cfbsetiv(&ctx, iv); \
- pre ## _cfbencrypt(&ctx, ct, ct, sz); \
- pre ## _cfbencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre ## _cfbsetiv(&ctx, iv); \
- pre ## _cfbdecrypt(&ctx, pt, pt, rest); \
- pre ## _cfbdecrypt(&ctx, pt + rest, pt + rest, sz); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz); \
- printf(", "); hexdump(text + sz, rest); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz); \
- printf(", "); hexdump(ct + sz, rest); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz); \
- printf(", "); hexdump(pt + sz, rest); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
-}
-
-#else
-# define CFB_TEST(PRE, pre)
-#endif
+extern const gccipher pre##_cfb;
/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * $Id: ecb-def.h,v 1.1 1999/12/10 23:16:39 mdw Exp $
+ *
+ * Definitions electronic code book mode
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: ecb-def.h,v $
+ * Revision 1.1 1999/12/10 23:16:39 mdw
+ * Split mode macros into interface and implementation.
+ *
+ */
+
+#ifndef CATACOMB_ECB_DEF_H
+#define CATACOMB_ECB_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <assert.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+# include "gcipher.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @ECB_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates an implementation for ECB stealing mode.
+ */
+
+#define ECB_DEF(PRE, pre) \
+ \
+/* --- @pre_ecbsetkey@ --- * \
+ * \
+ * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
+ * @const pre_ctx *k@ = pointer to cipher context \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Sets the ECB context to use a different cipher key. \
+ */ \
+ \
+void pre##_ecbsetkey(pre##_ecbctx *ctx, const pre##_ctx *k) \
+{ \
+ ctx->ctx = *k; \
+} \
+ \
+/* --- @pre_ecbinit@ --- * \
+ * \
+ * Arguments: @pre_ecbctx *ctx@ = pointer to cipher context \
+ * @const void *key@ = pointer to the key buffer \
+ * @size_t sz@ = size of the key \
+ * @const void *iv@ = pointer to initialization vector \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes an ECB context ready for use. This is \
+ * equivalent to calls to @pre_init@ and @pre_setkey@. \
+ */ \
+ \
+void pre##_ecbinit(pre##_ecbctx *ctx, \
+ const void *key, size_t sz, \
+ const void *iv) \
+{ \
+ pre##_init(&ctx->ctx, key, sz); \
+} \
+ \
+/* --- @pre_ecbencrypt@ --- * \
+ * \
+ * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
+ * @const void *src@ = pointer to source data \
+ * @void *dest@ = pointer to destination data \
+ * @size_t sz@ = size of block to be encrypted \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Encrypts a block with a block cipher in ECB mode, with \
+ * ciphertext stealing and other clever tricks. \
+ * Essentially, data can be encrypted in arbitrary sized \
+ * chunks, although decryption must use the same chunks. \
+ */ \
+ \
+void pre##_ecbencrypt(pre##_ecbctx *ctx, \
+ const void *src, void *dest, \
+ size_t sz) \
+{ \
+ const octet *s = src; \
+ octet *d = dest; \
+ \
+ /* --- Empty blocks are trivial --- */ \
+ \
+ if (!sz) \
+ return; \
+ \
+ /* --- Short blocks aren't allowed in ECB --- * \
+ * \
+ * There's absolutely nothing secure I can do with them. \
+ */ \
+ \
+ assert(((void)"ECB must have at least one whole block to work with", \
+ sz >= PRE##_BLKSZ)); \
+ \
+ /* --- Do the main chunk of encryption --- * \
+ * \
+ * This will do the whole lot if it's a whole number of blocks. Just \
+ * give each block to the cipher in turn. This is trivial. \
+ * Hopefully... \
+ */ \
+ \
+ while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ uint32 x[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, x, s); \
+ pre##_eblk(&ctx->ctx, x, x); \
+ BLKC_STORE(PRE, d, x); \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ sz -= PRE##_BLKSZ; \
+ } \
+ \
+ /* --- Do the tail-end block and bit-left-over --- * \
+ * \
+ * This isn't very efficient. That shouldn't matter much. \
+ */ \
+ \
+ if (sz) { \
+ uint32 x[PRE##_BLKSZ / 4]; \
+ octet b[PRE##_BLKSZ]; \
+ unsigned i; \
+ \
+ /* --- Let @sz@ be the size of the partial block --- */ \
+ \
+ sz -= PRE##_BLKSZ; \
+ \
+ /* --- First stage --- * \
+ * \
+ * Read in the current block, and encrypt it. The first part of \
+ * the result is the partial ciphertext block. Don't write that \
+ * out yet, because I've not read the partial plaintext block. \
+ */ \
+ \
+ BLKC_LOAD(PRE, x, s); \
+ pre##_eblk(&ctx->ctx, x, x); \
+ BLKC_STORE(PRE, b, x); \
+ \
+ /* --- Second stage --- * \
+ * \
+ * Now move in the partial plaintext block, writing out the \
+ * ciphertext as I go. Then encrypt, and write the complete \
+ * ciphertext block. \
+ */ \
+ \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ for (i = 0; i < sz; i++) { \
+ register octet y = b[i]; \
+ b[i] = s[i]; \
+ d[i] = y; \
+ } \
+ BLKC_LOAD(PRE, x, b); \
+ pre##_eblk(&ctx->ctx, x, x); \
+ BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \
+ } \
+ \
+ /* --- Done --- */ \
+ \
+ return; \
+} \
+ \
+/* --- @pre_ecbdecrypt@ --- * \
+ * \
+ * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
+ * @const void *src@ = pointer to source data \
+ * @void *dest@ = pointer to destination data \
+ * @size_t sz@ = size of block to be encrypted \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Decrypts a block with a block cipher in ECB mode, with \
+ * ciphertext stealing and other clever tricks. \
+ * Essentially, data can be encrypted in arbitrary sized \
+ * chunks, although decryption must use the same chunks. \
+ */ \
+ \
+void pre##_ecbdecrypt(pre##_ecbctx *ctx, \
+ const void *src, void *dest, \
+ size_t sz) \
+{ \
+ const octet *s = src; \
+ octet *d = dest; \
+ \
+ /* --- Empty blocks are trivial --- */ \
+ \
+ if (!sz) \
+ return; \
+ \
+ /* --- Short blocks aren't allowed in ECB --- * \
+ * \
+ * There's absolutely nothing secure I can do with them. \
+ */ \
+ \
+ assert(((void)"ECB must have at least one whole block to work with", \
+ sz >= PRE##_BLKSZ)); \
+ \
+ /* --- Do the main chunk of decryption --- * \
+ * \
+ * This will do the whole lot if it's a whole number of blocks. \
+ * Each block is just handed to the block cipher in turn. \
+ */ \
+ \
+ while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
+ uint32 x[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, x, s); \
+ pre##_dblk(&ctx->ctx, x, x); \
+ BLKC_STORE(PRE, d, x); \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ sz -= PRE##_BLKSZ; \
+ } \
+ \
+ /* --- Do the tail-end block and bit-left-over --- * \
+ * \
+ * This isn't very efficient. That shouldn't matter much. \
+ */ \
+ \
+ if (sz) { \
+ uint32 x[PRE##_BLKSZ / 4]; \
+ octet b[PRE##_BLKSZ]; \
+ unsigned i; \
+ \
+ /* --- Let @sz@ be the size of the partial block --- */ \
+ \
+ sz -= PRE##_BLKSZ; \
+ \
+ /* --- First stage --- * \
+ * \
+ * Take the complete ciphertext block, and decrypt it. This block \
+ * is carried over for the next encryption operation. \
+ */ \
+ \
+ BLKC_LOAD(PRE, x, s); \
+ pre##_dblk(&ctx->ctx, x, x); \
+ BLKC_STORE(PRE, b, x); \
+ \
+ /* --- Second stage --- * \
+ * \
+ * The first few bytes are the partial plaintext block. Write that \
+ * and replace with the partial ciphertext block. Then decrypt \
+ * what's left as the complete plaintext. \
+ */ \
+ \
+ s += PRE##_BLKSZ; \
+ d += PRE##_BLKSZ; \
+ for (i = 0; i < sz; i++) { \
+ register octet y = s[i]; \
+ d[i] = b[i]; \
+ b[i] = y; \
+ } \
+ BLKC_LOAD(PRE, x, b); \
+ pre##_dblk(&ctx->ctx, x, x); \
+ BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \
+ } \
+ \
+ /* --- Done --- */ \
+ \
+ return; \
+} \
+ \
+/* --- Generic cipher interface --- */ \
+ \
+static const gcipher_ops gops; \
+ \
+typedef struct gctx { \
+ gcipher c; \
+ pre##_ecbctx k; \
+} gctx; \
+ \
+static gcipher *ginit(const void *k, size_t sz) \
+{ \
+ gctx *g = CREATE(gctx); \
+ g->c.ops = &gops; \
+ pre##_ecbinit(&g->k, k, sz, 0); \
+ return (&g->c); \
+} \
+ \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_ecbencrypt(&g->k, s, t, sz); \
+} \
+ \
+static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_ecbdecrypt(&g->k, s, t, sz); \
+} \
+ \
+static void gdestroy(gcipher *c) \
+{ \
+ gctx *g = (gctx *)c; \
+ DESTROY(g); \
+} \
+ \
+static const gcipher_ops gops = { \
+ &pre##_ecb.b, \
+ gencrypt, gdecrypt, gdestroy, 0, 0 \
+}; \
+ \
+const gccipher pre##_ecb = { \
+ { #pre "-ecb", PRE##_KEYSZ, PRE##_BLKSZ }, \
+ ginit \
+}; \
+ \
+ECB_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @ECB_TEST@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use: Standard test rig for ECB functions.
+ */
+
+#define ECB_TEST(PRE, pre) \
+ \
+/* --- Initial plaintext for the test --- */ \
+ \
+static const octet text[] = TEXT; \
+ \
+/* --- Key and IV to use --- */ \
+ \
+static const octet key[] = KEY; \
+static const octet iv[] = IV; \
+ \
+/* --- Buffers for encryption and decryption output --- */ \
+ \
+static octet ct[sizeof(text)]; \
+static octet pt[sizeof(text)]; \
+ \
+static void hexdump(const octet *p, size_t sz) \
+{ \
+ const octet *q = p + sz; \
+ for (sz = 0; p < q; p++, sz++) { \
+ printf("%02x", *p); \
+ if ((sz + 1) % PRE##_BLKSZ == 0) \
+ putchar(':'); \
+ } \
+} \
+ \
+int main(void) \
+{ \
+ size_t sz = 0, rest; \
+ pre##_ecbctx ctx; \
+ int status = 0; \
+ int done = 0; \
+ \
+ size_t keysz = PRE##_KEYSZ ? \
+ PRE##_KEYSZ : strlen((const char *)key); \
+ \
+ fputs(#pre "-ecb: ", stdout); \
+ \
+ pre##_ecbinit(&ctx, key, keysz, iv); \
+ \
+ while (sz <= sizeof(text)) { \
+ rest = sizeof(text) - sz; \
+ if ((sz != 0 && sz < PRE##_BLKSZ) || \
+ (rest != 0 && rest < PRE##_BLKSZ)) \
+ goto next; \
+ memcpy(ct, text, sizeof(text)); \
+ pre##_ecbencrypt(&ctx, ct, ct, sz); \
+ pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest); \
+ memcpy(pt, ct, sizeof(text)); \
+ pre##_ecbdecrypt(&ctx, pt, pt, sz); \
+ pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest); \
+ if (memcmp(pt, text, sizeof(text)) == 0) { \
+ done++; \
+ if (sizeof(text) < 40 || done % 8 == 0) \
+ fputc('.', stdout); \
+ if (done % 480 == 0) \
+ fputs("\n\t", stdout); \
+ fflush(stdout); \
+ } else { \
+ printf("\nError (sz = %lu)\n", (unsigned long)sz); \
+ status = 1; \
+ printf("\tplaintext = "); hexdump(text, sz); \
+ printf(", "); hexdump(text + sz, rest); \
+ fputc('\n', stdout); \
+ printf("\tciphertext = "); hexdump(ct, sz); \
+ printf(", "); hexdump(ct + sz, rest); \
+ fputc('\n', stdout); \
+ printf("\trecovered text = "); hexdump(pt, sz); \
+ printf(", "); hexdump(pt + sz, rest); \
+ fputc('\n', stdout); \
+ fputc('\n', stdout); \
+ } \
+ next: \
+ if (sz < 63) \
+ sz++; \
+ else \
+ sz += 9; \
+ } \
+ \
+ fputs(status ? " failed\n" : " ok\n", stdout); \
+ return (status); \
+}
+
+#else
+# define ECB_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
/* -*-c-*-
*
- * $Id: ecb.h,v 1.1 1999/09/03 08:41:12 mdw Exp $
+ * $Id: ecb.h,v 1.2 1999/12/10 23:16:40 mdw Exp $
*
- * Ciphertext block chaining for block ciphers
+ * Electronic code book for block ciphers
*
* (c) 1999 Straylight/Edgeware
*/
/*----- Revision history --------------------------------------------------*
*
* $Log: ecb.h,v $
+ * Revision 1.2 1999/12/10 23:16:40 mdw
+ * Split mode macros into interface and implementation.
+ *
* Revision 1.1 1999/09/03 08:41:12 mdw
* Initial import.
*
*/
-#ifndef ECB_H
-#define ECB_H
+#ifndef CATACOMB_ECB_H
+#define CATACOMB_ECB_H
#ifdef __cplusplus
extern "C" {
/*----- Header files ------------------------------------------------------*/
-#include <assert.h>
-#include <string.h>
-
-#include <mLib/bits.h>
+#include <stddef.h>
-#ifndef BLKC_H
-# include "blkc.h"
+#ifndef CATACOMB_GCIPHER_H
+# include "gcipher.h"
#endif
/*----- Macros ------------------------------------------------------------*/
#define ECB_DECL(PRE, pre) \
\
-typedef struct pre ## _ecbctx { \
- pre ## _ctx ctx; /* Underlying cipher context */ \
-} pre ## _ecbctx; \
- \
-extern void pre ## _ecbsetkey(pre ## _ecbctx */*ctx*/, \
- const pre ## _ctx */*k*/); \
+/* --- Electronic codebook context --- */ \
\
-extern void pre ## _ecbinit(pre ## _ecbctx */*ctx*/, \
- const void */*key*/, size_t /*sz*/, \
- const void */*iv*/); \
- \
-extern void pre ## _ecbencrypt(pre ## _ecbctx */*ctx*/, \
- const void */*src*/, void */*dest*/, \
- size_t /*sz*/); \
- \
-extern void pre ## _ecbdecrypt(pre ## _ecbctx */*ctx*/, \
- const void */*src*/, void */*dest*/, \
- size_t /*sz*/); \
-
-/* --- @ECB_DEF@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use: Creates an implementation for ECB stealing mode.
- */
-
-#define ECB_DEF(PRE, pre) \
+typedef struct pre##_ecbctx { \
+ pre##_ctx ctx; /* Underlying cipher context */ \
+} pre##_ecbctx; \
\
/* --- @pre_ecbsetkey@ --- * \
* \
* Use: Sets the ECB context to use a different cipher key. \
*/ \
\
-void pre ## _ecbsetkey(pre ## _ecbctx *ctx, const pre ## _ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+extern void pre##_ecbsetkey(pre##_ecbctx */*ctx*/, \
+ const pre##_ctx */*k*/); \
\
/* --- @pre_ecbinit@ --- * \
* \
* equivalent to calls to @pre_init@ and @pre_setkey@. \
*/ \
\
-void pre ## _ecbinit(pre ## _ecbctx *ctx, \
- const void *key, size_t sz, \
- const void *iv) \
-{ \
- pre ## _init(&ctx->ctx, key, sz); \
-} \
+extern void pre##_ecbinit(pre##_ecbctx */*ctx*/, \
+ const void */*key*/, size_t /*sz*/, \
+ const void */*iv*/); \
\
/* --- @pre_ecbencrypt@ --- * \
* \
* chunks, although decryption must use the same chunks. \
*/ \
\
-void pre ## _ecbencrypt(pre ## _ecbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
-{ \
- const octet *s = src; \
- octet *d = dest; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- Short blocks aren't allowed in ECB --- * \
- * \
- * There's absolutely nothing secure I can do with them. \
- */ \
- \
- assert(((void)"ECB must have at least one whole block to work with", \
- sz >= PRE ## _BLKSZ)); \
- \
- /* --- Do the main chunk of encryption --- * \
- * \
- * This will do the whole lot if it's a whole number of blocks. Just \
- * give each block to the cipher in turn. This is trivial. \
- * Hopefully... \
- */ \
- \
- while (sz >= 2 * PRE ## _BLKSZ || sz == PRE ## _BLKSZ) { \
- uint32 x[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, x, s); \
- pre ## _eblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, d, x); \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- sz -= PRE ## _BLKSZ; \
- } \
- \
- /* --- Do the tail-end block and bit-left-over --- * \
- * \
- * This isn't very efficient. That shouldn't matter much. \
- */ \
- \
- if (sz) { \
- uint32 x[PRE ## _BLKSZ / 4]; \
- octet b[PRE ## _BLKSZ]; \
- unsigned i; \
- \
- /* --- Let @sz@ be the size of the partial block --- */ \
- \
- sz -= PRE ## _BLKSZ; \
- \
- /* --- First stage --- * \
- * \
- * Read in the current block, and encrypt it. The first part of \
- * the result is the partial ciphertext block. Don't write that \
- * out yet, because I've not read the partial plaintext block. \
- */ \
- \
- BLKC_LOAD(PRE, x, s); \
- pre ## _eblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, b, x); \
- \
- /* --- Second stage --- * \
- * \
- * Now move in the partial plaintext block, writing out the \
- * ciphertext as I go. Then encrypt, and write the complete \
- * ciphertext block. \
- */ \
- \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- for (i = 0; i < sz; i++) { \
- register octet y = b[i]; \
- b[i] = s[i]; \
- d[i] = y; \
- } \
- BLKC_LOAD(PRE, x, b); \
- pre ## _eblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, d - PRE ## _BLKSZ, x); \
- } \
- \
- /* --- Done --- */ \
- \
- return; \
-} \
+extern void pre##_ecbencrypt(pre##_ecbctx */*ctx*/, \
+ const void */*src*/, void */*dest*/, \
+ size_t /*sz*/); \
\
/* --- @pre_ecbdecrypt@ --- * \
* \
* \
* Returns: --- \
* \
- * Use: Encrypts a block with a block cipher in ECB mode, with \
+ * Use: Decrypts a block with a block cipher in ECB mode, with \
* ciphertext stealing and other clever tricks. \
* Essentially, data can be encrypted in arbitrary sized \
* chunks, although decryption must use the same chunks. \
*/ \
\
-void pre ## _ecbdecrypt(pre ## _ecbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
-{ \
- const octet *s = src; \
- octet *d = dest; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- Short blocks aren't allowed in ECB --- * \
- * \
- * There's absolutely nothing secure I can do with them. \
- */ \
- \
- assert(((void)"ECB must have at least one whole block to work with", \
- sz >= PRE ## _BLKSZ)); \
- \
- /* --- Do the main chunk of decryption --- * \
- * \
- * This will do the whole lot if it's a whole number of blocks. \
- * Each block is just handed to the block cipher in turn. \
- */ \
- \
- while (sz >= 2 * PRE ## _BLKSZ || sz == PRE ## _BLKSZ) { \
- uint32 x[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, x, s); \
- pre ## _dblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, d, x); \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- sz -= PRE ## _BLKSZ; \
- } \
+extern void pre##_ecbdecrypt(pre##_ecbctx */*ctx*/, \
+ const void */*src*/, void */*dest*/, \
+ size_t /*sz*/); \
\
- /* --- Do the tail-end block and bit-left-over --- * \
- * \
- * This isn't very efficient. That shouldn't matter much. \
- */ \
+/* --- Generic cipher interface --- */ \
\
- if (sz) { \
- uint32 x[PRE ## _BLKSZ / 4]; \
- octet b[PRE ## _BLKSZ]; \
- unsigned i; \
- \
- /* --- Let @sz@ be the size of the partial block --- */ \
- \
- sz -= PRE ## _BLKSZ; \
- \
- /* --- First stage --- * \
- * \
- * Take the complete ciphertext block, and decrypt it. This block \
- * is carried over for the next encryption operation. \
- */ \
- \
- BLKC_LOAD(PRE, x, s); \
- pre ## _dblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, b, x); \
- \
- /* --- Second stage --- * \
- * \
- * The first few bytes are the partial plaintext block. Write that \
- * and replace with the partial ciphertext block. Then decrypt \
- * what's left as the complete plaintext. \
- */ \
- \
- s += PRE ## _BLKSZ; \
- d += PRE ## _BLKSZ; \
- for (i = 0; i < sz; i++) { \
- register octet y = s[i]; \
- d[i] = b[i]; \
- b[i] = y; \
- } \
- BLKC_LOAD(PRE, x, b); \
- pre ## _dblk(&ctx->ctx, x, x); \
- BLKC_STORE(PRE, d - PRE ## _BLKSZ, x); \
- } \
- \
- /* --- Done --- */ \
- \
- return; \
-} \
- \
-ECB_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @ECB_TEST@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use: Standard test rig for ECB functions.
- */
-
-#define ECB_TEST(PRE, pre) \
- \
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
- \
-/* --- Key and IV to use --- */ \
- \
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
- \
-/* --- Buffers for encryption and decryption output --- */ \
- \
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
- \
-static void hexdump(const octet *p, size_t sz) \
-{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((sz + 1) % PRE ## _BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
- \
-int main(void) \
-{ \
- size_t sz = 0, rest; \
- pre ## _ecbctx ctx; \
- int status = 0; \
- int done = 0; \
- \
- size_t keysz = PRE ## _KEYSZ ? \
- PRE ## _KEYSZ : strlen((const char *)key); \
- \
- fputs(#pre "-ecb: ", stdout); \
- \
- pre ## _ecbinit(&ctx, key, keysz, iv); \
- \
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- if ((sz != 0 && sz < PRE ## _BLKSZ) || \
- (rest != 0 && rest < PRE ## _BLKSZ)) \
- goto next; \
- memcpy(ct, text, sizeof(text)); \
- pre ## _ecbencrypt(&ctx, ct, ct, sz); \
- pre ## _ecbencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre ## _ecbdecrypt(&ctx, pt, pt, sz); \
- pre ## _ecbdecrypt(&ctx, pt + sz, pt + sz, rest); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz); \
- printf(", "); hexdump(text + sz, rest); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz); \
- printf(", "); hexdump(ct + sz, rest); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz); \
- printf(", "); hexdump(pt + sz, rest); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- next: \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
- \
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
-}
-
-#else
-# define ECB_TEST(PRE, pre)
-#endif
+extern const gccipher pre##_ecb;
/*----- That's all, folks -------------------------------------------------*/
I=`echo "$i" | tr -d '\n' | tr a-z A-Z | tr -c a-zA-Z0-9 _`
for j in $extlist; do
J=`echo "$j" | tr -d '\n' | tr a-z A-Z | tr -c a-zA-Z0-9 _`
- guard="${I}_${J}_H"
+ guard="CATACOMB_${I}_${J}_H"
cat >$i-$j.h <<EOF
/* -*-c-*-
*
extern "C" {
#endif
-#ifndef ${J}_H
+#ifndef CATACOMB_${J}_H
# include "$j.h"
#endif
-#ifndef ${I}_H
+#ifndef CATACOMB_${I}_H
# include "$i.h"
#endif
cat >$i-$j.c <<EOF
/* -*-c-*-
*
- * $i-$j.h [generated]
+ * $i-$j.c [generated]
*/
#include "$i-$j.h"
+#include "$j-def.h"
${J}_DEF($I, $i)
EOF
done
/* -*-c-*-
*
- * $Id: hash.h,v 1.1 1999/09/03 08:41:12 mdw Exp $
+ * $Id: hash.h,v 1.2 1999/12/10 23:16:40 mdw Exp $
*
* Generic handling for message digest functions
*
/*----- Revision history --------------------------------------------------*
*
* $Log: hash.h,v $
+ * Revision 1.2 1999/12/10 23:16:40 mdw
+ * Split mode macros into interface and implementation.
+ *
* Revision 1.1 1999/09/03 08:41:12 mdw
* Initial import.
*
*/
-#ifndef HASH_H
-#define HASH_H
+#ifndef CATACOMB_HASH_H
+#define CATACOMB_HASH_H
#ifdef __cplusplus
extern "C" {
size_t _bsz = (isz); \
const octet *_bbuf = (octet *)(ibuf); \
\
- /* --- Add on the size done so far --- */ \
- \
- _bctx->count += _bsz; \
+ /* --- Add on the size done so far --- * \
+ * \
+ * Messy, because trapping overflow is difficult when you don't know \
+ * how many bits you've actually got. \
+ */ \
+ \
+ { \
+ uint32 _l = U32(_bsz), _h = (_bsz >> 16) >> 16; \
+ _bctx->nh += _h; \
+ _bctx->nl += _l; \
+ if (_bctx->nl < _l || _bctx->nl & ~MASK32) \
+ _bctx->nh++; \
+ } \
\
/* --- Handle very small contributions --- */ \
\
#define HASH_MD5STRENGTH(PRE, pre, ictx) do { \
pre##_ctx *_mctx = (ictx); \
HASH_PAD(PRE, pre, _mctx, 0x80u, 0, 8); \
- STORE32_L(_mctx->buf + PRE##_BUFSZ - 8, _mctx->count << 3); \
- STORE32_L(_mctx->buf + PRE##_BUFSZ - 4, _mctx->count >> 29); \
+ STORE32_L(_mctx->buf + PRE##_BUFSZ - 8, _mctx->nl << 3); \
+ STORE32_L(_mctx->buf + PRE##_BUFSZ - 4, \
+ (_mctx->nl >> 29) | (_mctx->nh << 3)); \
pre##_compress(_mctx, _mctx->buf); \
} while (0)
--- /dev/null
+/* -*-c-*-
+ *
+ * $Id: hmac-def.h,v 1.1 1999/12/10 23:16:40 mdw Exp $
+ *
+ * Definitions for HMAC and NMAC
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: hmac-def.h,v $
+ * Revision 1.1 1999/12/10 23:16:40 mdw
+ * Split mode macros into interface and implementation.
+ *
+ */
+
+#ifndef CATACOMB_HMAC_DEF_H
+#define CATACOMB_HMAC_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdlib.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_GMAC_H
+# include "gmac.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @HMAC_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying hash function
+ *
+ * Use: Creates implementations for the HMAC and NMAC functions.
+ */
+
+#define HMAC_DEF(PRE, pre) \
+ \
+/* --- @pre_nmacinit@ --- * \
+ * \
+ * Arguments: @pre_macctx *key@ = pointer to a MAC key object \
+ * @const void *ok@ = pointer to outer hash init vector \
+ * @const void *ik@ = pointer to inner hash init vector \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a MAC key for doing NMAC hashing. \
+ */ \
+ \
+void pre##_nmacinit(pre##_mackey *key, const void *ok, const void *ik) \
+{ \
+ memcpy(key->ochain, ok, PRE##_HASHSZ); \
+ memcpy(key->ichain, ik, PRE##_HASHSZ); \
+ key->ocount = key->icount = 0; \
+} \
+ \
+/* --- @pre_hmacinit@ --- * \
+ * \
+ * Arguments: @pre_mackey *key@ = pointer to MAC key object \
+ * @const void *k@ = pointer to key to use \
+ * @size_t sz@ = size of key data \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a MAC key for doing HMAC hashing. Keys \
+ * longer than the hash function's output size aren't very \
+ * useful, but are accepted. Keys longer than the hash's \
+ * block size are also accepted; they are hashed before \
+ * use, as specified in RFC2104. \
+ */ \
+ \
+void pre##_hmacinit(pre##_mackey *key, const void *k, size_t sz) \
+{ \
+ int i; \
+ const octet *kbuf = k; \
+ pre##_ctx ctx; \
+ octet buf[PRE##_HASHSZ]; \
+ \
+ if (sz > PRE##_BUFSZ) { \
+ pre##_init(&ctx); \
+ pre##_hash(&ctx, k, sz); \
+ pre##_done(&ctx, buf); \
+ kbuf = buf; \
+ sz = PRE##_HASHSZ; \
+ } \
+ \
+ pre##_init(&ctx); \
+ memset(ctx.buf, 0x5c, PRE##_BUFSZ); \
+ for (i = 0; i < sz; i++) \
+ ctx.buf[i] ^= kbuf[i]; \
+ pre##_compress(&ctx, ctx.buf); \
+ pre##_state(&ctx, key->ochain); \
+ \
+ pre##_init(&ctx); \
+ memset(ctx.buf, 0x36, PRE##_BUFSZ); \
+ for (i = 0; i < sz; i++) \
+ ctx.buf[i] ^= kbuf[i]; \
+ pre##_compress(&ctx, ctx.buf); \
+ pre##_state(&ctx, key->ichain); \
+ \
+ key->ocount = key->icount = PRE##_BUFSZ; \
+ BURN(ctx); \
+} \
+ \
+/* --- @pre_macinit@ --- * \
+ * \
+ * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \
+ * @const pre_mackey *key@ = pointer to MAC key block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Instantiates a MAC context from a key block. \
+ */ \
+ \
+void pre##_macinit(pre##_macctx *ctx, const pre##_mackey *key) \
+{ \
+ memcpy(ctx->chain, key->ochain, PRE##_HASHSZ); \
+ ctx->count = key->ocount; \
+ pre##_set(&ctx->ctx, key->ichain, key->icount); \
+} \
+ \
+/* --- @pre_machash@ --- * \
+ * \
+ * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \
+ * @const void *buf@ = pointer to buffer \
+ * @size_t sz@ = size of the buffer \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Hashes a buffer. \
+ */ \
+ \
+void pre##_machash(pre##_macctx *ctx, const void *buf, size_t sz) \
+{ \
+ pre##_hash(&ctx->ctx, buf, sz); \
+} \
+ \
+/* --- @pre_macdone@ --- * \
+ * \
+ * Arguments: @pre_macctx *ctx@ = pointer to MAC context block \
+ * @void *mac@ = pointer to buffer to receive MAC \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Returns the result of a MAC computation. \
+ */ \
+ \
+void pre##_macdone(pre##_macctx *ctx, void *mac) \
+{ \
+ pre##_done(&ctx->ctx, mac); \
+ pre##_set(&ctx->ctx, ctx->chain, ctx->count); \
+ pre##_hash(&ctx->ctx, mac, PRE##_HASHSZ); \
+ pre##_done(&ctx->ctx, mac); \
+} \
+ \
+/* --- Generic MAC interface --- */ \
+ \
+static const gmac_ops gkops; \
+static const ghash_ops gops; \
+ \
+typedef struct gkctx { \
+ gmac m; \
+ pre##_mackey k; \
+} gkctx; \
+ \
+typedef struct gctx { \
+ ghash h; \
+ pre##_macctx c; \
+} gctx; \
+ \
+static ghash *gkinit(gmac *m) \
+{ \
+ gkctx *gk = (gkctx *)m; \
+ gctx *g = CREATE(gctx); \
+ g->h.ops = &gops; \
+ pre##_macinit(&g->c, &gk->k); \
+ return (&g->h); \
+} \
+ \
+static gmac *gkey(const void *k, size_t sz) \
+{ \
+ gkctx *gk = CREATE(gkctx); \
+ gk->m.ops = &gkops; \
+ pre##_hmacinit(&gk->k, k, sz); \
+ return (&gk->m); \
+} \
+ \
+static void ghhash(ghash *h, const void *p, size_t sz) \
+{ \
+ gctx *g = (gctx *)h; \
+ pre##_machash(&g->c, p, sz); \
+} \
+ \
+static void ghdone(ghash *h, void *buf) \
+{ \
+ gctx *g = (gctx *)h; \
+ pre##_macdone(&g->c, buf); \
+} \
+ \
+static void ghdestroy(ghash *h) \
+{ \
+ gctx *g = (gctx *)h; \
+ DESTROY(g); \
+} \
+ \
+static void gkdestroy(gmac *m) \
+{ \
+ gkctx *gk = (gkctx *)m; \
+ DESTROY(gk); \
+} \
+ \
+const gcmac pre##_hmac = { { #pre "-hmac", PRE##_HASHSZ }, gkey }; \
+static const gmac_ops gkops = { &pre##_hmac.b, gkinit, gkdestroy }; \
+static const ghash_ops gops = \
+ { &pre##_hmac.b, ghhash, ghdone, ghdestroy }; \
+ \
+HMAC_TEST(PRE, pre)
+
+/* --- @HMAC_TEST@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for hash-specfic definitions
+ *
+ * Use: Standard test rig for MAC functions.
+ */
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include <mLib/dstr.h>
+#include <mLib/quis.h>
+#include <mLib/testrig.h>
+
+#define HMAC_TEST(PRE, pre) \
+ \
+static int macverify(dstr *v) \
+{ \
+ pre##_macctx cctx; \
+ pre##_mackey ckey; \
+ int ok = 1; \
+ int i; \
+ octet *p; \
+ int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
+ size_t csz; \
+ dstr d; \
+ \
+ dstr_create(&d); \
+ dstr_ensure(&d, PRE##_HASHSZ); \
+ d.len = PRE##_HASHSZ; \
+ \
+ pre##_hmacinit(&ckey, v[1].buf, v[1].len); \
+ \
+ for (ip = szs; *ip; ip++) { \
+ i = *ip; \
+ csz = v[0].len; \
+ if (i == -1) \
+ i = csz; \
+ if (i > csz) \
+ continue; \
+ p = (octet *)v[0].buf; \
+ pre##_macinit(&cctx, &ckey); \
+ while (csz) { \
+ if (i > csz) \
+ i = csz; \
+ pre##_machash(&cctx, p, i); \
+ p += i; \
+ csz -= i; \
+ } \
+ pre##_macdone(&cctx, d.buf); \
+ if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) { \
+ printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\tkey = ", \
+ *ip, v[0].buf); \
+ type_hex.dump(&v[1], stdout); \
+ fputs("\n\texpected = ", stdout); \
+ type_hex.dump(&v[2], stdout); \
+ fputs("\n\tcomputed = ", stdout); \
+ type_hex.dump(&d, stdout); \
+ putchar('\n'); \
+ ok = 0; \
+ } \
+ } \
+ \
+ dstr_destroy(&d); \
+ return (ok); \
+} \
+ \
+static test_chunk macdefs[] = { \
+ { #pre "-hmac", macverify, \
+ { &type_string, &type_hex, &type_hex, 0 } }, \
+ { 0, 0, { 0 } } \
+}; \
+ \
+int main(int argc, char *argv[]) \
+{ \
+ ego(argv[0]); \
+ test_run(argc, argv, macdefs, SRCDIR"/tests/" #pre); \
+ return (0); \
+}
+
+#else
+# define HMAC_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
/* -*-c-*-
*
- * $Id: hmac.h,v 1.1 1999/09/03 08:41:12 mdw Exp $
+ * $Id: hmac.h,v 1.2 1999/12/10 23:17:39 mdw Exp $
*
* Generic code for HMAC and NMAC
*
/*----- Revision history --------------------------------------------------*
*
* $Log: hmac.h,v $
+ * Revision 1.2 1999/12/10 23:17:39 mdw
+ * Split mode macros into interface and implementation.
+ *
* Revision 1.1 1999/09/03 08:41:12 mdw
* Initial import.
*
/*----- Notes on the HMAC and NMAC constructions --------------------------*
*
- * Designed by Mihir Bellare, Ran Canetti and Hugo Krawczyk, NMAC is a
- * method for constructing keyed message authentication algorithms from
- * unkeyed hash functions. HMAC is an alternative formulation which doesn't
- * require low-level access to the hash function's implementation. NMAC was
- * designed to allow MD5 has a suitable underlying hash function, even though
- * doubts were already being raised about its collision resistance.
+ * Designed by Mihir Bellare, Ran Canetti and Hugo Krawczyk, NMAC is a method
+ * for constructing keyed message authentication algorithms from unkeyed hash
+ * functions. It has been proven to provide useful security given reasonable
+ * assumptions about the underlying hash function. HMAC is an alternative
+ * formulation which doesn't require low-level access to the hash function's
+ * implementation. NMAC was designed to allow MD5 has a suitable underlying
+ * hash function, even though doubts were already being raised about its
+ * collision resistance.
*/
-#ifndef HMAC_H
-#define HMAC_H
+#ifndef CATACOMB_HMAC_H
+#define CATACOMB_HMAC_H
#ifdef __cplusplus
extern "C" {
/*----- Header files ------------------------------------------------------*/
-#include <stdlib.h>
-#include <string.h>
+#include <stddef.h>
#include <mLib/bits.h>
-#ifndef PARANOIA_H
-# include "paranoia.h"
+#ifndef CATACOMB_GMAC_H
+# include "gmac.h"
#endif
/*----- Macros ------------------------------------------------------------*/
#define HMAC_DECL(PRE, pre) \
\
+/* --- An HMAC or NMAC key --- */ \
+ \
typedef struct pre##_mackey { \
octet ochain[PRE##_HASHSZ]; /* Chaining for outer hash */ \
- unsigned long ocount; /* Byte count for outer hash */ \
+ unsigned ocount; /* Byte count for outer hash */ \
octet ichain[PRE##_HASHSZ]; /* Chaining for inner hash */ \
- unsigned long icount; /* Byte count for inner hash */ \
+ unsigned icount; /* Byte count for inner hash */ \
} pre##_mackey; \
\
+/* --- An HMAC or NMAC hashing context --- */ \
+ \
typedef struct pre##_macctx { \
pre##_ctx ctx; /* Context for main hashing */ \
octet chain[PRE##_HASHSZ]; /* Chaining for outer hash */ \
- unsigned long count; /* Byte count for outer hash */ \
+ unsigned count; /* Byte count for outer hash */ \
} pre##_macctx; \
\
-extern void pre##_nmac(pre##_mackey */*key*/, \
- const void */*ok*/, const void */*ik*/); \
- \
-extern void pre##_hmac(pre##_mackey */*key*/, \
- const void */*k*/, size_t /*sz*/); \
- \
-extern void pre##_macinit(pre##_macctx */*ctx*/, \
- const pre##_mackey */*key*/); \
- \
-extern void pre##_mac(pre##_macctx */*ctx*/, \
- const void */*buf*/, size_t /*sz*/); \
- \
-extern void pre##_macdone(pre##_macctx */*ctx*/, void */*mac*/);
-
-/* --- @HMAC_DEF@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for the underlying hash function
- *
- * Use: Creates implementations for the HMAC and NMAC functions.
- */
-
-#define HMAC_DEF(PRE, pre) \
- \
-/* --- @pre_nmac@ --- * \
+/* --- @pre_nmacinit@ --- * \
* \
* Arguments: @pre_macctx *key@ = pointer to a MAC key object \
* @const void *ok@ = pointer to outer hash init vector \
* Use: Initializes a MAC key for doing NMAC hashing. \
*/ \
\
-void pre##_nmac(pre##_mackey *key, const void *ok, const void *ik) \
-{ \
- memcpy(key->ochain, ok, PRE##_HASHSZ); \
- memcpy(key->ichain, ik, PRE##_HASHSZ); \
- key->ocount = key->icount = 0; \
-} \
+extern void pre##_nmacinit(pre##_mackey */*key*/, \
+ const void */*ok*/, const void */*ik*/); \
\
-/* --- @pre_hmac@ --- * \
+/* --- @pre_hmacinit@ --- * \
* \
* Arguments: @pre_mackey *key@ = pointer to MAC key object \
* @const void *k@ = pointer to key to use \
* use, as specified in RFC2104. \
*/ \
\
-void pre##_hmac(pre##_mackey *key, const void *k, size_t sz) \
-{ \
- int i; \
- const octet *kbuf = k; \
- pre##_ctx ctx; \
- octet buf[PRE##_HASHSZ]; \
- \
- if (sz > PRE##_BUFSZ) { \
- pre##_init(&ctx); \
- pre##_hash(&ctx, k, sz); \
- pre##_done(&ctx, buf); \
- kbuf = buf; \
- sz = PRE##_HASHSZ; \
- } \
- \
- pre##_init(&ctx); \
- memset(ctx.buf, 0x5c, PRE##_BUFSZ); \
- for (i = 0; i < sz; i++) \
- ctx.buf[i] ^= kbuf[i]; \
- pre##_compress(&ctx, ctx.buf); \
- pre##_state(&ctx, key->ochain); \
- \
- pre##_init(&ctx); \
- memset(ctx.buf, 0x36, PRE##_BUFSZ); \
- for (i = 0; i < sz; i++) \
- ctx.buf[i] ^= kbuf[i]; \
- pre##_compress(&ctx, ctx.buf); \
- pre##_state(&ctx, key->ichain); \
- \
- key->ocount = key->icount = PRE##_BUFSZ; \
- BURN(ctx); \
-} \
+extern void pre##_hmacinit(pre##_mackey */*key*/, \
+ const void */*k*/, size_t /*sz*/); \
\
/* --- @pre_macinit@ --- * \
* \
* Use: Instantiates a MAC context from a key block. \
*/ \
\
-void pre##_macinit(pre##_macctx *ctx, const pre##_mackey *key) \
-{ \
- memcpy(ctx->chain, key->ochain, PRE##_HASHSZ); \
- ctx->count = key->ocount; \
- pre##_set(&ctx->ctx, key->ichain, key->icount); \
-} \
+extern void pre##_macinit(pre##_macctx */*ctx*/, \
+ const pre##_mackey */*key*/); \
\
-/* --- @pre_mac@ --- * \
+/* --- @pre_machash@ --- * \
* \
* Arguments: @pre_macctx *ctx@ = pointer to MAC context block \
* @const void *buf@ = pointer to buffer \
* Use: Hashes a buffer. \
*/ \
\
-void pre##_mac(pre##_macctx *ctx, const void *buf, size_t sz) \
-{ \
- pre##_hash(&ctx->ctx, buf, sz); \
-} \
+extern void pre##_machash(pre##_macctx */*ctx*/, \
+ const void */*buf*/, size_t /*sz*/); \
\
/* --- @pre_macdone@ --- * \
* \
* Use: Returns the result of a MAC computation. \
*/ \
\
-void pre##_macdone(pre##_macctx *ctx, void *mac) \
-{ \
- pre##_done(&ctx->ctx, mac); \
- pre##_set(&ctx->ctx, ctx->chain, ctx->count); \
- pre##_hash(&ctx->ctx, mac, PRE##_HASHSZ); \
- pre##_done(&ctx->ctx, mac); \
-} \
- \
-HMAC_TEST(PRE, pre) \
-
-/* --- @HMAC_TEST@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for hash-specfic definitions
- *
- * Use: Standard test rig for MAC functions.
- */
-
-#ifdef TEST_RIG
-
-#include <mLib/dstr.h>
-#include <mLib/quis.h>
-#include <mLib/testrig.h>
-
-#define HMAC_TEST(PRE, pre) \
- \
-static int macverify(dstr *v) \
-{ \
- pre##_macctx cctx; \
- pre##_mackey ckey; \
- int ok = 1; \
- int i; \
- octet *p; \
- int szs[] = { 1, 7, 192, -1, 0 }, *ip; \
- size_t csz; \
- dstr d; \
- \
- dstr_create(&d); \
- dstr_ensure(&d, PRE##_HASHSZ); \
- d.len = PRE##_HASHSZ; \
- \
- pre##_hmac(&ckey, v[1].buf, v[1].len); \
+extern void pre##_macdone(pre##_macctx */*ctx*/, void */*mac*/); \
\
- for (ip = szs; *ip; ip++) { \
- i = *ip; \
- csz = v[0].len; \
- if (i == -1) \
- i = csz; \
- if (i > csz) \
- continue; \
- p = (octet *)v[0].buf; \
- pre##_macinit(&cctx, &ckey); \
- while (csz) { \
- if (i > csz) \
- i = csz; \
- pre##_mac(&cctx, p, i); \
- p += i; \
- csz -= i; \
- } \
- pre##_macdone(&cctx, d.buf); \
- if (memcmp(d.buf, v[2].buf, PRE##_HASHSZ) != 0) { \
- printf("\nfail:\n\tstep = %i\n\tinput = `%s'\n\tkey = ", \
- *ip, v[0].buf); \
- type_hex.dump(&v[1], stdout); \
- fputs("\n\texpected = ", stdout); \
- type_hex.dump(&v[2], stdout); \
- fputs("\n\tcomputed = ", stdout); \
- type_hex.dump(&d, stdout); \
- putchar('\n'); \
- ok = 0; \
- } \
- } \
+/* --- Generic MAC interface --- */ \
\
- dstr_destroy(&d); \
- return (ok); \
-} \
- \
-static test_chunk macdefs[] = { \
- { #pre "-hmac", macverify, \
- { &type_string, &type_hex, &type_hex, 0 } }, \
- { 0, 0, { 0 } } \
-}; \
- \
-int main(int argc, char *argv[]) \
-{ \
- ego(argv[0]); \
- test_run(argc, argv, macdefs, SRCDIR"/tests/" #pre); \
- return (0); \
-}
-
-#else
-# define HMAC_TEST(PRE, pre)
-#endif
+extern const gcmac pre##_hmac;
/*----- That's all, folks -------------------------------------------------*/
--- /dev/null
+/* -*-c-*-
+ *
+ * $Id: ofb-def.h,v 1.1 1999/12/10 23:16:40 mdw Exp $
+ *
+ * Definitions for output feedback mode
+ *
+ * (c) 1999 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.
+ */
+
+/*----- Revision history --------------------------------------------------*
+ *
+ * $Log: ofb-def.h,v $
+ * Revision 1.1 1999/12/10 23:16:40 mdw
+ * Split mode macros into interface and implementation.
+ *
+ */
+
+#ifndef CATACOMB_OFB_DEF_H
+#define CATACOMB_OFB_DEF_H
+
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+/*----- Header files ------------------------------------------------------*/
+
+#include <stdarg.h>
+#include <string.h>
+
+#include <mLib/bits.h>
+#include <mLib/sub.h>
+
+#ifndef CATACOMB_BLKC_H
+# include "blkc.h"
+#endif
+
+#ifndef CATACOMB_GCIPHER_H
+# include "gcipher.h"
+#endif
+
+#ifndef CATACOMB_PARANOIA_H
+# include "paranoia.h"
+#endif
+
+/*----- Macros ------------------------------------------------------------*/
+
+/* --- @OFB_DEF@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
+ *
+ * Use: Creates definitions for output feedback mode.
+ */
+
+#define OFB_DEF(PRE, pre) \
+ \
+/* --- @pre_ofbgetiv@ --- * \
+ * \
+ * Arguments: @const pre_ofbctx *ctx@ = pointer to OFB context block \
+ * @void *iv#@ = pointer to output data block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Reads the currently set IV. Reading and setting an IV \
+ * is not transparent to the cipher. It will add a `step' \
+ * which must be matched by a similar operation during \
+ * decryption. \
+ */ \
+ \
+void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv) \
+{ \
+ octet *p = iv; \
+ int off = ctx->off; \
+ int rest = PRE##_BLKSZ - off; \
+ memcpy(p, ctx->iv + off, rest); \
+ memcpy(p + rest, ctx->iv, off); \
+} \
+ \
+/* --- @pre_ofbsetiv@ --- * \
+ * \
+ * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \
+ * @cnost void *iv@ = pointer to IV to set \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Sets the IV to use for subsequent encryption. \
+ */ \
+ \
+void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv) \
+{ \
+ uint32 niv[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, niv, iv); \
+ pre##_eblk(&ctx->ctx, niv, niv); \
+ BLKC_STORE(PRE, ctx->iv, niv); \
+ ctx->off = 0; \
+} \
+ \
+/* --- @pre_ofbbdry@ --- * \
+ * \
+ * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Inserts a boundary during encryption. Successful \
+ * decryption must place a similar boundary. \
+ */ \
+ \
+void pre##_ofbbdry(pre##_ofbctx *ctx) \
+{ \
+ octet iv[PRE##_BLKSZ]; \
+ pre##_ofbgetiv(ctx, iv); \
+ pre##_ofbsetiv(ctx, iv); \
+ BURN(iv); \
+} \
+ \
+/* --- @pre_ofbsetkey@ --- * \
+ * \
+ * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \
+ * @const pre_ctx *k@ = pointer to cipher context \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Sets the OFB context to use a different cipher key. \
+ */ \
+ \
+void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k) \
+{ \
+ ctx->ctx = *k; \
+} \
+ \
+/* --- @pre_ofbinit@ --- * \
+ * \
+ * Arguments: @pre_ofbctx *ctx@ = pointer to cipher context \
+ * @const void *key@ = pointer to the key buffer \
+ * @size_t sz@ = size of the key \
+ * @const void *iv@ = pointer to initialization vector \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Initializes a OFB context ready for use. You should \
+ * ensure that the IV chosen is unique: reusing an IV will \
+ * compromise the security of the entire plaintext. This \
+ * is equivalent to calls to @pre_init@, @pre_ofbsetkey@ \
+ * and @pre_ofbsetiv@. \
+ */ \
+ \
+void pre##_ofbinit(pre##_ofbctx *ctx, \
+ const void *key, size_t sz, \
+ const void *iv) \
+{ \
+ static octet zero[PRE##_BLKSZ] = { 0 }; \
+ pre##_init(&ctx->ctx, key, sz); \
+ pre##_ofbsetiv(ctx, iv ? iv : zero); \
+} \
+ \
+/* --- @pre_ofbencrypt@ --- * \
+ * \
+ * Arguments: @pre_ofbctx *ctx@ = pointer to OFB context block \
+ * @const void *src@ = pointer to source data \
+ * @void *dest@ = pointer to destination data \
+ * @size_t sz@ = size of block to be encrypted \
+ * \
+ * Returns: --- \
+ * \
+ * Use: Encrypts or decrypts a block with a block cipher in OFB \
+ * mode: encryption and decryption are the same in OFB. \
+ * The destination may be null to just churn the feedback \
+ * round for a bit. The source may be null to use the \
+ * cipher as a random data generator. \
+ */ \
+ \
+void pre##_ofbencrypt(pre##_ofbctx *ctx, \
+ const void *src, void *dest, \
+ size_t sz) \
+{ \
+ const octet *s = src; \
+ octet *d = dest; \
+ int off = ctx->off; \
+ \
+ /* --- Empty blocks are trivial --- */ \
+ \
+ if (!sz) \
+ return; \
+ \
+ /* --- If I can deal with the block from my buffer, do that --- */ \
+ \
+ if (sz < PRE##_BLKSZ - off) \
+ goto small; \
+ \
+ /* --- Finish off what's left in my buffer --- */ \
+ \
+ if (!d) \
+ sz -= off; \
+ else { \
+ while (off < PRE##_BLKSZ) { \
+ register octet x = s ? *s++ : 0; \
+ *d++ = ctx->iv[off++] ^ x; \
+ sz--; \
+ } \
+ } \
+ \
+ /* --- Main encryption loop --- */ \
+ \
+ { \
+ uint32 iv[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, iv, ctx->iv); \
+ \
+ for (;;) { \
+ pre##_eblk(&ctx->ctx, iv, iv); \
+ if (sz < PRE##_BLKSZ) \
+ break; \
+ if (d) { \
+ if (!s) \
+ BLKC_STORE(PRE, d, iv); \
+ else { \
+ uint32 x[PRE##_BLKSZ / 4]; \
+ BLKC_LOAD(PRE, x, s); \
+ BLKC_XSTORE(PRE, d, iv, x); \
+ s += PRE##_BLKSZ; \
+ } \
+ d += PRE##_BLKSZ; \
+ } \
+ sz -= PRE##_BLKSZ; \
+ } \
+ \
+ BLKC_STORE(PRE, ctx->iv, iv); \
+ off = 0; \
+ } \
+ \
+ /* --- Tidying up the tail end --- */ \
+ \
+ if (sz) { \
+ small: \
+ if (!d) \
+ off += sz; \
+ else do { \
+ register octet x = s ? *s++ : 0; \
+ *d++ = ctx->iv[off++] ^ x; \
+ sz--; \
+ } while (sz); \
+ } \
+ \
+ /* --- Done --- */ \
+ \
+ ctx->off = off; \
+ return; \
+} \
+ \
+/* --- Generic cipher interface --- */ \
+ \
+static const gcipher_ops gops; \
+ \
+typedef struct gctx { \
+ gcipher c; \
+ pre##_ofbctx k; \
+} gctx; \
+ \
+static gcipher *ginit(const void *k, size_t sz) \
+{ \
+ gctx *g = CREATE(gctx); \
+ g->c.ops = &gops; \
+ pre##_ofbinit(&g->k, k, sz, 0); \
+ return (&g->c); \
+} \
+ \
+static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_ofbencrypt(&g->k, s, t, sz); \
+} \
+ \
+static void gdestroy(gcipher *c) \
+{ \
+ gctx *g = (gctx *)c; \
+ DESTROY(g); \
+} \
+ \
+static void gsetiv(gcipher *c, const void *iv) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_ofbsetiv(&g->k, iv); \
+} \
+ \
+static void gbdry(gcipher *c) \
+{ \
+ gctx *g = (gctx *)c; \
+ pre##_ofbbdry(&g->k); \
+} \
+ \
+static const gcipher_ops gops = { \
+ &pre##_ofb.b, \
+ gencrypt, gencrypt, gdestroy, gsetiv, gbdry \
+}; \
+ \
+const gccipher pre##_ofb = { \
+ { #pre "-ofb", PRE##_KEYSZ, PRE##_BLKSZ }, \
+ ginit \
+}; \
+ \
+/* --- Generic random number generator interface --- */ \
+ \
+typedef struct grctx { \
+ grand r; \
+ pre##_ofbctx k; \
+} grctx; \
+ \
+static void grdestroy(grand *r) \
+{ \
+ grctx *g = (grctx *)r; \
+ DESTROY(g); \
+} \
+ \
+static int grmisc(grand *r, unsigned op, ...) \
+{ \
+ grctx *g = (grctx *)r; \
+ va_list ap; \
+ int rc = 0; \
+ octet buf[PRE##_BLKSZ]; \
+ va_start(ap, op); \
+ \
+ switch (op) { \
+ case GRAND_CHECK: \
+ switch (va_arg(ap, unsigned)) { \
+ case GRAND_CHECK: \
+ case GRAND_SEEDINT: \
+ case GRAND_SEEDUINT32: \
+ case GRAND_SEEDBLOCK: \
+ rc = 1; \
+ break; \
+ default: \
+ rc = 0; \
+ break; \
+ } \
+ break; \
+ case GRAND_SEEDINT: \
+ memset(buf, 0, sizeof(buf)); \
+ STORE32(buf, va_arg(ap, unsigned)); \
+ pre##_ofbsetiv(&g->k, buf); \
+ break; \
+ case GRAND_SEEDUINT32: \
+ memset(buf, 0, sizeof(buf)); \
+ STORE32(buf, va_arg(ap, uint32)); \
+ pre##_ofbsetiv(&g->k, buf); \
+ break; \
+ case GRAND_SEEDBLOCK: { \
+ const void *p = va_arg(ap, const void *); \
+ size_t sz = va_arg(ap, size_t); \
+ if (sz < sizeof(buf)) { \
+ memset(buf, 0, sizeof(buf)); \
+ memcpy(buf, p, sz); \
+ p = buf; \
+ } \
+ pre##_ofbsetiv(&g->k, p); \
+ } break; \
+ } \
+ \
+ va_end(ap); \
+ return (rc); \
+} \
+ \
+static octet grbyte(grand *r) \
+{ \
+ grctx *g = (grctx *)r; \
+ octet o; \
+ pre##_ofbencrypt(&g->k, 0, &o, 1); \
+ return (o); \
+} \
+ \
+static uint32 grword(grand *r) \
+{ \
+ grctx *g = (grctx *)r; \
+ octet b[4]; \
+ pre##_ofbencrypt(&g->k, 0, b, sizeof(b)); \
+ return (LOAD32(b)); \
+} \
+ \
+static void grfill(grand *r, void *p, size_t sz) \
+{ \
+ grctx *g = (grctx *)r; \
+ pre##_ofbencrypt(&g->k, 0, p, sz); \
+} \
+ \
+static const grand_ops grops = { \
+ #pre "-ofb", \
+ 0, \
+ grmisc, grdestroy, \
+ grword, grbyte, grword, grand_range, grfill \
+}; \
+ \
+/* --- @pre_ofbrand@ --- * \
+ * \
+ * Arguments: @const void *k@ = pointer to key material \
+ * @size_t sz@ = size of key material \
+ * \
+ * Returns: Pointer to generic random number generator interface. \
+ * \
+ * Use: Creates a random number interface wrapper around an \
+ * OFB-mode block cipher. \
+ */ \
+ \
+grand *pre##_ofbrand(const void *k, size_t sz) \
+{ \
+ grctx *g = CREATE(grctx); \
+ g->r.ops = &grops; \
+ pre##_ofbinit(&g->k, k, sz, 0); \
+ return (&g->r); \
+} \
+ \
+OFB_TEST(PRE, pre)
+
+/*----- Test rig ----------------------------------------------------------*/
+
+#ifdef TEST_RIG
+
+#include <stdio.h>
+
+#include "daftstory.h"
+
+/* --- @OFB_TEST@ --- *
+ *
+ * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
+ *
+ * Use: Standard test rig for OFB functions.
+ */
+
+#define OFB_TEST(PRE, pre) \
+ \
+/* --- Initial plaintext for the test --- */ \
+ \
+static const octet text[] = TEXT; \
+ \
+/* --- Key and IV to use --- */ \
+ \
+static const octet key[] = KEY; \
+static const octet iv[] = IV; \
+ \
+/* --- Buffers for encryption and decryption output --- */ \
+ \
+static octet ct[sizeof(text)]; \
+static octet pt[sizeof(text)]; \
+ \
+static void hexdump(const octet *p, size_t sz) \
+{ \
+ const octet *q = p + sz; \
+ for (sz = 0; p < q; p++, sz++) { \
+ printf("%02x", *p); \
+ if ((sz + 1) % PRE##_BLKSZ == 0) \
+ putchar(':'); \
+ } \
+} \
+ \
+int main(void) \
+{ \
+ size_t sz = 0, rest; \
+ pre##_ofbctx ctx; \
+ int status = 0; \
+ int done = 0; \
+ pre##_ctx k; \
+ \
+ size_t keysz = PRE##_KEYSZ ? \
+ PRE##_KEYSZ : strlen((const char *)key); \
+ \
+ fputs(#pre "-ofb: ", stdout); \
+ \
+ pre##_init(&k, key, keysz); \
+ pre##_ofbsetkey(&ctx, &k); \
+ \
+ while (sz <= sizeof(text)) { \
+ rest = sizeof(text) - sz; \
+ memcpy(ct, text, sizeof(text)); \
+ pre##_ofbsetiv(&ctx, iv); \
+ pre##_ofbencrypt(&ctx, ct, ct, sz); \
+ pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest); \
+ memcpy(pt, ct, sizeof(text)); \
+ pre##_ofbsetiv(&ctx, iv); \
+ pre##_ofbencrypt(&ctx, pt, pt, rest); \
+ pre##_ofbencrypt(&ctx, pt + rest, pt + rest, sz); \
+ if (memcmp(pt, text, sizeof(text)) == 0) { \
+ done++; \
+ if (sizeof(text) < 40 || done % 8 == 0) \
+ fputc('.', stdout); \
+ if (done % 480 == 0) \
+ fputs("\n\t", stdout); \
+ fflush(stdout); \
+ } else { \
+ printf("\nError (sz = %lu)\n", (unsigned long)sz); \
+ status = 1; \
+ printf("\tplaintext = "); hexdump(text, sz); \
+ printf(", "); hexdump(text + sz, rest); \
+ fputc('\n', stdout); \
+ printf("\tciphertext = "); hexdump(ct, sz); \
+ printf(", "); hexdump(ct + sz, rest); \
+ fputc('\n', stdout); \
+ printf("\trecovered text = "); hexdump(pt, sz); \
+ printf(", "); hexdump(pt + sz, rest); \
+ fputc('\n', stdout); \
+ fputc('\n', stdout); \
+ } \
+ if (sz < 63) \
+ sz++; \
+ else \
+ sz += 9; \
+ } \
+ \
+ fputs(status ? " failed\n" : " ok\n", stdout); \
+ return (status); \
+}
+
+#else
+# define OFB_TEST(PRE, pre)
+#endif
+
+/*----- That's all, folks -------------------------------------------------*/
+
+#ifdef __cplusplus
+ }
+#endif
+
+#endif
/* -*-c-*-
*
- * $Id: ofb.h,v 1.1 1999/09/03 08:41:12 mdw Exp $
+ * $Id: ofb.h,v 1.2 1999/12/10 23:16:40 mdw Exp $
*
* Output feedback for block ciphers
*
/*----- Revision history --------------------------------------------------*
*
* $Log: ofb.h,v $
+ * Revision 1.2 1999/12/10 23:16:40 mdw
+ * Split mode macros into interface and implementation.
+ *
* Revision 1.1 1999/09/03 08:41:12 mdw
* Initial import.
*
*/
-#ifndef OFB_H
-#define OFB_H
+#ifndef CATACOMB_OFB_H
+#define CATACOMB_OFB_H
#ifdef __cplusplus
extern "C" {
/*----- Header files ------------------------------------------------------*/
-#include <string.h>
+#include <stddef.h>
#include <mLib/bits.h>
-#ifndef BLKC_H
-# include "blkc.h"
+#ifndef CATACOMB_GCIPHER_H
+# include "gcipher.h"
#endif
-#ifndef PARANOIA_H
-# include "paranoia.h"
+#ifndef CATACOMB_GRAND_H
+# include "grand.h"
#endif
/*----- Macros ------------------------------------------------------------*/
#define OFB_DECL(PRE, pre) \
\
-typedef struct pre ## _ofbctx { \
- pre ## _ctx ctx; /* Underlying cipher context */ \
- int off; /* Current offset in buffer */ \
- octet iv[PRE ## _BLKSZ]; /* Output buffer and IV */ \
-} pre ## _ofbctx; \
- \
-extern void pre ## _ofbgetiv(const pre ## _ofbctx */*ctx*/, \
- void */*iv*/); \
- \
-extern void pre ## _ofbsetiv(pre ## _ofbctx */*ctx*/, \
- const void */*iv*/); \
- \
-extern void pre ## _ofbbdry(pre ## _ofbctx */*ctx*/); \
- \
-extern void pre ## _ofbsetkey(pre ## _ofbctx */*ctx*/, \
- const pre ## _ctx */*k*/); \
- \
-extern void pre ## _ofbinit(pre ## _ofbctx */*ctx*/, \
- const void */*key*/, size_t /*sz*/, \
- const void */*iv*/); \
+/* --- Output feedback context --- */ \
\
-extern void pre ## _ofbencrypt(pre ## _ofbctx */*ctx*/, \
- const void */*src*/, void */*dest*/, \
- size_t /*sz*/);
-
-/* --- @OFB_DEF@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
- *
- * Use: Creates definitions for output feedback mode.
- */
-
-#define OFB_DEF(PRE, pre) \
+typedef struct pre##_ofbctx { \
+ pre##_ctx ctx; /* Underlying cipher context */ \
+ int off; /* Current offset in buffer */ \
+ octet iv[PRE##_BLKSZ]; /* Output buffer and IV */ \
+} pre##_ofbctx; \
\
/* --- @pre_ofbgetiv@ --- * \
* \
* decryption. \
*/ \
\
-void pre ## _ofbgetiv(const pre ## _ofbctx *ctx, void *iv) \
-{ \
- octet *p = iv; \
- int off = ctx->off; \
- int rest = PRE ## _BLKSZ - off; \
- memcpy(p, ctx->iv + off, rest); \
- memcpy(p + rest, ctx->iv, off); \
-} \
+extern void pre##_ofbgetiv(const pre##_ofbctx */*ctx*/, \
+ void */*iv*/); \
\
/* --- @pre_ofbsetiv@ --- * \
* \
* Use: Sets the IV to use for subsequent encryption. \
*/ \
\
-void pre ## _ofbsetiv(pre ## _ofbctx *ctx, const void *iv) \
-{ \
- uint32 niv[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, niv, iv); \
- pre ## _eblk(&ctx->ctx, niv, niv); \
- BLKC_STORE(PRE, ctx->iv, niv); \
- ctx->off = 0; \
-} \
+extern void pre##_ofbsetiv(pre##_ofbctx */*ctx*/, \
+ const void */*iv*/); \
\
/* --- @pre_ofbbdry@ --- * \
* \
* decryption must place a similar boundary. \
*/ \
\
-void pre ## _ofbbdry(pre ## _ofbctx *ctx) \
-{ \
- octet iv[PRE ## _BLKSZ]; \
- pre ## _ofbgetiv(ctx, iv); \
- pre ## _ofbsetiv(ctx, iv); \
- BURN(iv); \
-} \
+extern void pre##_ofbbdry(pre##_ofbctx */*ctx*/); \
\
/* --- @pre_ofbsetkey@ --- * \
* \
* Use: Sets the OFB context to use a different cipher key. \
*/ \
\
-void pre ## _ofbsetkey(pre ## _ofbctx *ctx, const pre ## _ctx *k) \
-{ \
- ctx->ctx = *k; \
-} \
+extern void pre##_ofbsetkey(pre##_ofbctx */*ctx*/, \
+ const pre##_ctx */*k*/); \
\
/* --- @pre_ofbinit@ --- * \
* \
* and @pre_ofbsetiv@. \
*/ \
\
-void pre ## _ofbinit(pre ## _ofbctx *ctx, \
- const void *key, size_t sz, \
- const void *iv) \
-{ \
- static octet zero[PRE ## _BLKSZ] = { 0 }; \
- pre ## _init(&ctx->ctx, key, sz); \
- pre ## _ofbsetiv(ctx, iv ? iv : zero); \
-} \
+extern void pre##_ofbinit(pre##_ofbctx */*ctx*/, \
+ const void */*key*/, size_t /*sz*/, \
+ const void */*iv*/); \
\
/* --- @pre_ofbencrypt@ --- * \
* \
* cipher as a random data generator. \
*/ \
\
-void pre ## _ofbencrypt(pre ## _ofbctx *ctx, \
- const void *src, void *dest, \
- size_t sz) \
-{ \
- const octet *s = src; \
- octet *d = dest; \
- int off = ctx->off; \
- \
- /* --- Empty blocks are trivial --- */ \
- \
- if (!sz) \
- return; \
- \
- /* --- If I can deal with the block from my buffer, do that --- */ \
- \
- if (sz < PRE ## _BLKSZ - off) \
- goto small; \
- \
- /* --- Finish off what's left in my buffer --- */ \
- \
- if (!d) \
- sz -= off; \
- else { \
- while (off < PRE ## _BLKSZ) { \
- register octet x = s ? *s++ : 0; \
- *d++ = ctx->iv[off++] ^ x; \
- sz--; \
- } \
- } \
- \
- /* --- Main encryption loop --- */ \
- \
- { \
- uint32 iv[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, iv, ctx->iv); \
- \
- for (;;) { \
- pre ## _eblk(&ctx->ctx, iv, iv); \
- if (sz < PRE ## _BLKSZ) \
- break; \
- if (d) { \
- if (!s) \
- BLKC_STORE(PRE, d, iv); \
- else { \
- uint32 x[PRE ## _BLKSZ / 4]; \
- BLKC_LOAD(PRE, x, s); \
- BLKC_XSTORE(PRE, d, iv, x); \
- s += PRE ## _BLKSZ; \
- } \
- d += PRE ## _BLKSZ; \
- } \
- sz -= PRE ## _BLKSZ; \
- } \
- \
- BLKC_STORE(PRE, ctx->iv, iv); \
- off = 0; \
- } \
- \
- /* --- Tidying up the tail end --- */ \
- \
- if (sz) { \
- small: \
- if (!d) \
- off += sz; \
- else do { \
- register octet x = s ? *s++ : 0; \
- *d++ = ctx->iv[off++] ^ x; \
- sz--; \
- } while (sz); \
- } \
- \
- /* --- Done --- */ \
- \
- ctx->off = off; \
- return; \
-} \
+extern void pre##_ofbencrypt(pre##_ofbctx */*ctx*/, \
+ const void */*src*/, void */*dest*/, \
+ size_t /*sz*/); \
\
-OFB_TEST(PRE, pre)
-
-/*----- Test rig ----------------------------------------------------------*/
-
-#ifdef TEST_RIG
-
-#include <stdio.h>
-
-#include "daftstory.h"
-
-/* --- @OFB_TEST@ --- *
- *
- * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
- *
- * Use: Standard test rig for OFB functions.
- */
-
-#define OFB_TEST(PRE, pre) \
- \
-/* --- Initial plaintext for the test --- */ \
- \
-static const octet text[] = TEXT; \
- \
-/* --- Key and IV to use --- */ \
- \
-static const octet key[] = KEY; \
-static const octet iv[] = IV; \
- \
-/* --- Buffers for encryption and decryption output --- */ \
- \
-static octet ct[sizeof(text)]; \
-static octet pt[sizeof(text)]; \
- \
-static void hexdump(const octet *p, size_t sz) \
-{ \
- const octet *q = p + sz; \
- for (sz = 0; p < q; p++, sz++) { \
- printf("%02x", *p); \
- if ((sz + 1) % PRE ## _BLKSZ == 0) \
- putchar(':'); \
- } \
-} \
- \
-int main(void) \
-{ \
- size_t sz = 0, rest; \
- pre ## _ofbctx ctx; \
- int status = 0; \
- int done = 0; \
- pre ## _ctx k; \
- \
- size_t keysz = PRE ## _KEYSZ ? \
- PRE ## _KEYSZ : strlen((const char *)key); \
- \
- fputs(#pre "-ofb: ", stdout); \
+/* --- @pre_ofbrand@ --- * \
+ * \
+ * Arguments: @const void *k@ = pointer to key material \
+ * @size_t sz@ = size of key material \
+ * \
+ * Returns: Pointer to generic random number generator interface. \
+ * \
+ * Use: Creates a random number interface wrapper around an \
+ * OFB-mode block cipher. \
+ */ \
\
- pre ## _init(&k, key, keysz); \
- pre ## _ofbsetkey(&ctx, &k); \
+extern grand *pre##_ofbrand(const void */*k*/, size_t /*sz*/); \
\
- while (sz <= sizeof(text)) { \
- rest = sizeof(text) - sz; \
- memcpy(ct, text, sizeof(text)); \
- pre ## _ofbsetiv(&ctx, iv); \
- pre ## _ofbencrypt(&ctx, ct, ct, sz); \
- pre ## _ofbencrypt(&ctx, ct + sz, ct + sz, rest); \
- memcpy(pt, ct, sizeof(text)); \
- pre ## _ofbsetiv(&ctx, iv); \
- pre ## _ofbencrypt(&ctx, pt, pt, rest); \
- pre ## _ofbencrypt(&ctx, pt + rest, pt + rest, sz); \
- if (memcmp(pt, text, sizeof(text)) == 0) { \
- done++; \
- if (sizeof(text) < 40 || done % 8 == 0) \
- fputc('.', stdout); \
- if (done % 480 == 0) \
- fputs("\n\t", stdout); \
- fflush(stdout); \
- } else { \
- printf("\nError (sz = %lu)\n", (unsigned long)sz); \
- status = 1; \
- printf("\tplaintext = "); hexdump(text, sz); \
- printf(", "); hexdump(text + sz, rest); \
- fputc('\n', stdout); \
- printf("\tciphertext = "); hexdump(ct, sz); \
- printf(", "); hexdump(ct + sz, rest); \
- fputc('\n', stdout); \
- printf("\trecovered text = "); hexdump(pt, sz); \
- printf(", "); hexdump(pt + sz, rest); \
- fputc('\n', stdout); \
- fputc('\n', stdout); \
- } \
- if (sz < 63) \
- sz++; \
- else \
- sz += 9; \
- } \
+/* --- Generic cipher interface --- */ \
\
- fputs(status ? " failed\n" : " ok\n", stdout); \
- return (status); \
-}
-
-#else
-# define OFB_TEST(PRE, pre)
-#endif
+extern const gccipher pre##_ofb;
/*----- That's all, folks -------------------------------------------------*/