3 * $Id: ecb.h,v 1.1 1999/09/03 08:41:12 mdw Exp $
5 * Ciphertext block chaining for block ciphers
7 * (c) 1999 Straylight/Edgeware
10 /*----- Licensing notice --------------------------------------------------*
12 * This file is part of Catacomb.
14 * Catacomb is free software; you can redistribute it and/or modify
15 * it under the terms of the GNU Library General Public License as
16 * published by the Free Software Foundation; either version 2 of the
17 * License, or (at your option) any later version.
19 * Catacomb is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU Library General Public License for more details.
24 * You should have received a copy of the GNU Library General Public
25 * License along with Catacomb; if not, write to the Free
26 * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
30 /*----- Revision history --------------------------------------------------*
33 * Revision 1.1 1999/09/03 08:41:12 mdw
45 /*----- Header files ------------------------------------------------------*/
50 #include <mLib/bits.h>
56 /*----- Macros ------------------------------------------------------------*/
58 /* --- @ECB_DECL@ --- *
60 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
62 * Use: Creates declarations for ECB stealing mode.
65 #define ECB_DECL(PRE, pre) \
67 typedef struct pre ## _ecbctx { \
68 pre ## _ctx ctx; /* Underlying cipher context */ \
71 extern void pre ## _ecbsetkey(pre ## _ecbctx */*ctx*/, \
72 const pre ## _ctx */*k*/); \
74 extern void pre ## _ecbinit(pre ## _ecbctx */*ctx*/, \
75 const void */*key*/, size_t /*sz*/, \
76 const void */*iv*/); \
78 extern void pre ## _ecbencrypt(pre ## _ecbctx */*ctx*/, \
79 const void */*src*/, void */*dest*/, \
82 extern void pre ## _ecbdecrypt(pre ## _ecbctx */*ctx*/, \
83 const void */*src*/, void */*dest*/, \
86 /* --- @ECB_DEF@ --- *
88 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
90 * Use: Creates an implementation for ECB stealing mode.
93 #define ECB_DEF(PRE, pre) \
95 /* --- @pre_ecbsetkey@ --- * \
97 * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
98 * @const pre_ctx *k@ = pointer to cipher context \
102 * Use: Sets the ECB context to use a different cipher key. \
105 void pre ## _ecbsetkey(pre ## _ecbctx *ctx, const pre ## _ctx *k) \
110 /* --- @pre_ecbinit@ --- * \
112 * Arguments: @pre_ecbctx *ctx@ = pointer to cipher context \
113 * @const void *key@ = pointer to the key buffer \
114 * @size_t sz@ = size of the key \
115 * @const void *iv@ = pointer to initialization vector \
119 * Use: Initializes an ECB context ready for use. This is \
120 * equivalent to calls to @pre_init@ and @pre_setkey@. \
123 void pre ## _ecbinit(pre ## _ecbctx *ctx, \
124 const void *key, size_t sz, \
127 pre ## _init(&ctx->ctx, key, sz); \
130 /* --- @pre_ecbencrypt@ --- * \
132 * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
133 * @const void *src@ = pointer to source data \
134 * @void *dest@ = pointer to destination data \
135 * @size_t sz@ = size of block to be encrypted \
139 * Use: Encrypts a block with a block cipher in ECB mode, with \
140 * ciphertext stealing and other clever tricks. \
141 * Essentially, data can be encrypted in arbitrary sized \
142 * chunks, although decryption must use the same chunks. \
145 void pre ## _ecbencrypt(pre ## _ecbctx *ctx, \
146 const void *src, void *dest, \
149 const octet *s = src; \
152 /* --- Empty blocks are trivial --- */ \
157 /* --- Short blocks aren't allowed in ECB --- * \
159 * There's absolutely nothing secure I can do with them. \
162 assert(((void)"ECB must have at least one whole block to work with", \
163 sz >= PRE ## _BLKSZ)); \
165 /* --- Do the main chunk of encryption --- * \
167 * This will do the whole lot if it's a whole number of blocks. Just \
168 * give each block to the cipher in turn. This is trivial. \
172 while (sz >= 2 * PRE ## _BLKSZ || sz == PRE ## _BLKSZ) { \
173 uint32 x[PRE ## _BLKSZ / 4]; \
174 BLKC_LOAD(PRE, x, s); \
175 pre ## _eblk(&ctx->ctx, x, x); \
176 BLKC_STORE(PRE, d, x); \
177 s += PRE ## _BLKSZ; \
178 d += PRE ## _BLKSZ; \
179 sz -= PRE ## _BLKSZ; \
182 /* --- Do the tail-end block and bit-left-over --- * \
184 * This isn't very efficient. That shouldn't matter much. \
188 uint32 x[PRE ## _BLKSZ / 4]; \
189 octet b[PRE ## _BLKSZ]; \
192 /* --- Let @sz@ be the size of the partial block --- */ \
194 sz -= PRE ## _BLKSZ; \
196 /* --- First stage --- * \
198 * Read in the current block, and encrypt it. The first part of \
199 * the result is the partial ciphertext block. Don't write that \
200 * out yet, because I've not read the partial plaintext block. \
203 BLKC_LOAD(PRE, x, s); \
204 pre ## _eblk(&ctx->ctx, x, x); \
205 BLKC_STORE(PRE, b, x); \
207 /* --- Second stage --- * \
209 * Now move in the partial plaintext block, writing out the \
210 * ciphertext as I go. Then encrypt, and write the complete \
211 * ciphertext block. \
214 s += PRE ## _BLKSZ; \
215 d += PRE ## _BLKSZ; \
216 for (i = 0; i < sz; i++) { \
217 register octet y = b[i]; \
221 BLKC_LOAD(PRE, x, b); \
222 pre ## _eblk(&ctx->ctx, x, x); \
223 BLKC_STORE(PRE, d - PRE ## _BLKSZ, x); \
231 /* --- @pre_ecbdecrypt@ --- * \
233 * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
234 * @const void *src@ = pointer to source data \
235 * @void *dest@ = pointer to destination data \
236 * @size_t sz@ = size of block to be encrypted \
240 * Use: Encrypts a block with a block cipher in ECB mode, with \
241 * ciphertext stealing and other clever tricks. \
242 * Essentially, data can be encrypted in arbitrary sized \
243 * chunks, although decryption must use the same chunks. \
246 void pre ## _ecbdecrypt(pre ## _ecbctx *ctx, \
247 const void *src, void *dest, \
250 const octet *s = src; \
253 /* --- Empty blocks are trivial --- */ \
258 /* --- Short blocks aren't allowed in ECB --- * \
260 * There's absolutely nothing secure I can do with them. \
263 assert(((void)"ECB must have at least one whole block to work with", \
264 sz >= PRE ## _BLKSZ)); \
266 /* --- Do the main chunk of decryption --- * \
268 * This will do the whole lot if it's a whole number of blocks. \
269 * Each block is just handed to the block cipher in turn. \
272 while (sz >= 2 * PRE ## _BLKSZ || sz == PRE ## _BLKSZ) { \
273 uint32 x[PRE ## _BLKSZ / 4]; \
274 BLKC_LOAD(PRE, x, s); \
275 pre ## _dblk(&ctx->ctx, x, x); \
276 BLKC_STORE(PRE, d, x); \
277 s += PRE ## _BLKSZ; \
278 d += PRE ## _BLKSZ; \
279 sz -= PRE ## _BLKSZ; \
282 /* --- Do the tail-end block and bit-left-over --- * \
284 * This isn't very efficient. That shouldn't matter much. \
288 uint32 x[PRE ## _BLKSZ / 4]; \
289 octet b[PRE ## _BLKSZ]; \
292 /* --- Let @sz@ be the size of the partial block --- */ \
294 sz -= PRE ## _BLKSZ; \
296 /* --- First stage --- * \
298 * Take the complete ciphertext block, and decrypt it. This block \
299 * is carried over for the next encryption operation. \
302 BLKC_LOAD(PRE, x, s); \
303 pre ## _dblk(&ctx->ctx, x, x); \
304 BLKC_STORE(PRE, b, x); \
306 /* --- Second stage --- * \
308 * The first few bytes are the partial plaintext block. Write that \
309 * and replace with the partial ciphertext block. Then decrypt \
310 * what's left as the complete plaintext. \
313 s += PRE ## _BLKSZ; \
314 d += PRE ## _BLKSZ; \
315 for (i = 0; i < sz; i++) { \
316 register octet y = s[i]; \
320 BLKC_LOAD(PRE, x, b); \
321 pre ## _dblk(&ctx->ctx, x, x); \
322 BLKC_STORE(PRE, d - PRE ## _BLKSZ, x); \
332 /*----- Test rig ----------------------------------------------------------*/
338 #include "daftstory.h"
340 /* --- @ECB_TEST@ --- *
342 * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
344 * Use: Standard test rig for ECB functions.
347 #define ECB_TEST(PRE, pre) \
349 /* --- Initial plaintext for the test --- */ \
351 static const octet text[] = TEXT; \
353 /* --- Key and IV to use --- */ \
355 static const octet key[] = KEY; \
356 static const octet iv[] = IV; \
358 /* --- Buffers for encryption and decryption output --- */ \
360 static octet ct[sizeof(text)]; \
361 static octet pt[sizeof(text)]; \
363 static void hexdump(const octet *p, size_t sz) \
365 const octet *q = p + sz; \
366 for (sz = 0; p < q; p++, sz++) { \
367 printf("%02x", *p); \
368 if ((sz + 1) % PRE ## _BLKSZ == 0) \
375 size_t sz = 0, rest; \
376 pre ## _ecbctx ctx; \
380 size_t keysz = PRE ## _KEYSZ ? \
381 PRE ## _KEYSZ : strlen((const char *)key); \
383 fputs(#pre "-ecb: ", stdout); \
385 pre ## _ecbinit(&ctx, key, keysz, iv); \
387 while (sz <= sizeof(text)) { \
388 rest = sizeof(text) - sz; \
389 if ((sz != 0 && sz < PRE ## _BLKSZ) || \
390 (rest != 0 && rest < PRE ## _BLKSZ)) \
392 memcpy(ct, text, sizeof(text)); \
393 pre ## _ecbencrypt(&ctx, ct, ct, sz); \
394 pre ## _ecbencrypt(&ctx, ct + sz, ct + sz, rest); \
395 memcpy(pt, ct, sizeof(text)); \
396 pre ## _ecbdecrypt(&ctx, pt, pt, sz); \
397 pre ## _ecbdecrypt(&ctx, pt + sz, pt + sz, rest); \
398 if (memcmp(pt, text, sizeof(text)) == 0) { \
400 if (sizeof(text) < 40 || done % 8 == 0) \
401 fputc('.', stdout); \
402 if (done % 480 == 0) \
403 fputs("\n\t", stdout); \
406 printf("\nError (sz = %lu)\n", (unsigned long)sz); \
408 printf("\tplaintext = "); hexdump(text, sz); \
409 printf(", "); hexdump(text + sz, rest); \
410 fputc('\n', stdout); \
411 printf("\tciphertext = "); hexdump(ct, sz); \
412 printf(", "); hexdump(ct + sz, rest); \
413 fputc('\n', stdout); \
414 printf("\trecovered text = "); hexdump(pt, sz); \
415 printf(", "); hexdump(pt + sz, rest); \
416 fputc('\n', stdout); \
417 fputc('\n', stdout); \
426 fputs(status ? " failed\n" : " ok\n", stdout); \
431 # define ECB_TEST(PRE, pre)
434 /*----- That's all, folks -------------------------------------------------*/