X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/d03ab969116fe715d569304c1c474749b2f64529..95ccefe3ce59a0773f915aca6948d5b6f1f7c882:/cfb.h diff --git a/cfb.h b/cfb.h index 0719934..e2082a1 100644 --- a/cfb.h +++ b/cfb.h @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: cfb.h,v 1.1 1999/09/03 08:41:11 mdw Exp $ + * $Id: cfb.h,v 1.5 2004/04/08 01:36:15 mdw Exp $ * * Ciphertext feedback for block ciphers * * (c) 1999 Straylight/Edgeware */ -/*----- Licensing notice --------------------------------------------------* +/*----- Licensing notice --------------------------------------------------* * * This file is part of Catacomb. * @@ -15,28 +15,20 @@ * 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.h,v $ - * 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" { @@ -44,16 +36,12 @@ /*----- Header files ------------------------------------------------------*/ -#include +#include #include -#ifndef BLKC_H -# include "blkc.h" -#endif - -#ifndef PARANOIA_H -# include "paranoia.h" +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" #endif /*----- Data structures ---------------------------------------------------*/ @@ -67,49 +55,18 @@ #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*/); \ +/* --- Ciphertext feedback context --- */ \ \ -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*/); \ - \ -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 */ \ + unsigned off; /* Offset into @iv@ buffer */ \ + octet iv[PRE##_BLKSZ]; /* Previous ciphertext or IV */ \ +} pre##_cfbctx; \ \ /* --- @pre_cfbgetiv@ --- * \ * \ * Arguments: @const pre_cfbctx *ctx@ = pointer to CFB context block \ - * @void *iv#@ = pointer to output data block \ + * @void *iv@ = pointer to output data block \ * \ * Returns: --- \ * \ @@ -119,14 +76,8 @@ extern void pre ## _cfbdecrypt(pre ## _cfbctx */*ctx*/, \ * 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@ --- * \ * \ @@ -138,14 +89,8 @@ void pre ## _cfbgetiv(const pre ## _cfbctx *ctx, void *iv) \ * 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@ --- * \ * \ @@ -157,13 +102,7 @@ void pre ## _cfbsetiv(pre ## _cfbctx *ctx, const void *iv) \ * 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@ --- * \ * \ @@ -175,10 +114,8 @@ void pre ## _cfbbdry(pre ## _cfbctx *ctx) \ * 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@ --- * \ * \ @@ -196,14 +133,9 @@ void pre ## _cfbsetkey(pre ## _cfbctx *ctx, const pre ## _ctx *k) \ * @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@ --- * \ * \ @@ -219,70 +151,11 @@ void pre ## _cfbinit(pre ## _cfbctx *ctx, \ * 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 --- */ \ +extern void pre##_cfbencrypt(pre##_cfbctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ \ - { \ - 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 \ @@ -291,182 +164,18 @@ void pre ## _cfbencrypt(pre ## _cfbctx *ctx, \ * \ * 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; \ +extern void pre##_cfbdecrypt(pre##_cfbctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ \ - /* --- Empty blocks are trivial --- */ \ +/* --- Generic cipher interface --- */ \ \ - 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; \ -} \ - \ -CFB_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#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 -------------------------------------------------*/