X-Git-Url: https://git.distorted.org.uk/u/mdw/catacomb/blobdiff_plain/d03ab969116fe715d569304c1c474749b2f64529..c65df27983057ec76ed0e72bb370f9a5ae7dad28:/cbc.h diff --git a/cbc.h b/cbc.h index 66979de..1b51009 100644 --- a/cbc.h +++ b/cbc.h @@ -1,6 +1,6 @@ /* -*-c-*- * - * $Id: cbc.h,v 1.1 1999/09/03 08:41:11 mdw Exp $ + * $Id: cbc.h,v 1.4 2004/04/08 01:36:15 mdw Exp $ * * Ciphertext block chaining for block ciphers * @@ -27,16 +27,8 @@ * MA 02111-1307, USA. */ -/*----- Revision history --------------------------------------------------* - * - * $Log: cbc.h,v $ - * 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" { @@ -44,12 +36,12 @@ /*----- Header files ------------------------------------------------------*/ -#include +#include #include -#ifndef BLKC_H -# include "blkc.h" +#ifndef CATACOMB_GCIPHER_H +# include "gcipher.h" #endif /*----- Macros ------------------------------------------------------------*/ @@ -63,45 +55,17 @@ #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*/); \ +/* --- Cipher block chaining context --- */ \ \ -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*/); \ - \ -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@ --- * \ * \ * Arguments: @const pre_cbcctx *ctx@ = pointer to CBC context block \ - * @void *iv#@ = pointer to output data block \ + * @void *iv@ = pointer to output data block \ * \ * Returns: --- \ * \ @@ -110,10 +74,8 @@ extern void pre ## _cbcdecrypt(pre ## _cbcctx */*ctx*/, \ * 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@ --- * \ * \ @@ -125,10 +87,8 @@ void pre ## _cbcgetiv(const pre ## _cbcctx *ctx, void *iv) \ * 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@ --- * \ * \ @@ -140,10 +100,8 @@ void pre ## _cbcsetiv(pre ## _cbcctx *ctx, const void *iv) \ * 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@ --- * \ * \ @@ -160,14 +118,9 @@ void pre ## _cbcsetkey(pre ## _cbcctx *ctx, const pre ## _ctx *k) \ * 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@ --- * \ * \ @@ -184,103 +137,9 @@ void pre ## _cbcinit(pre ## _cbcctx *ctx, \ * 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@ --- * \ * \ @@ -291,226 +150,19 @@ void pre ## _cbcencrypt(pre ## _cbcctx *ctx, \ * \ * 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; \ - } \ +extern void pre##_cbcdecrypt(pre##_cbcctx */*ctx*/, \ + const void */*src*/, void */*dest*/, \ + size_t /*sz*/); \ \ - /* --- 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. \ - */ \ +/* --- Generic cipher interface --- */ \ \ - 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; \ -} \ - \ -CBC_TEST(PRE, pre) - -/*----- Test rig ----------------------------------------------------------*/ - -#ifdef TEST_RIG - -#include - -#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 -------------------------------------------------*/