X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/d03ab969116fe715d569304c1c474749b2f64529..097fb6f2f97575ce17738b4afb3216e9492de2b4:/ecb.h diff --git a/ecb.h b/ecb.h index 1027591..ed39310 100644 --- a/ecb.h +++ b/ecb.h @@ -1,13 +1,13 @@ /* -*-c-*- * - * $Id: ecb.h,v 1.1 1999/09/03 08:41:12 mdw Exp $ + * $Id: ecb.h,v 1.3 2004/04/08 01:36:15 mdw Exp $ * - * Ciphertext block chaining for block ciphers + * Electronic code book 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: ecb.h,v $ - * 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" { @@ -44,13 +36,10 @@ /*----- Header files ------------------------------------------------------*/ -#include -#include - -#include +#include -#ifndef BLKC_H -# include "blkc.h" +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" #endif /*----- Macros ------------------------------------------------------------*/ @@ -64,33 +53,11 @@ #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*/); \ - \ -extern void pre ## _ecbinit(pre ## _ecbctx */*ctx*/, \ - const void */*key*/, size_t /*sz*/, \ - const void */*iv*/); \ +/* --- Electronic codebook context --- */ \ \ -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@ --- * \ * \ @@ -102,10 +69,8 @@ extern void pre ## _ecbdecrypt(pre ## _ecbctx */*ctx*/, \ * 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@ --- * \ * \ @@ -120,12 +85,9 @@ void pre ## _ecbsetkey(pre ## _ecbctx *ctx, const pre ## _ctx *k) \ * 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@ --- * \ * \ @@ -142,91 +104,9 @@ void pre ## _ecbinit(pre ## _ecbctx *ctx, \ * 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@ --- * \ * \ @@ -237,199 +117,19 @@ void pre ## _ecbencrypt(pre ## _ecbctx *ctx, \ * \ * 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. \ - */ \ +extern void pre##_ecbdecrypt(pre##_ecbctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ \ - assert(((void)"ECB must have at least one whole block to work with", \ - sz >= PRE ## _BLKSZ)); \ +/* --- Generic cipher interface --- */ \ \ - /* --- 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; \ -} \ - \ -ECB_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#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 -------------------------------------------------*/