3 * $Id: ecb-def.h,v 1.1 1999/12/10 23:16:39 mdw Exp $
5 * Definitions electronic code book mode
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/12/10 23:16:39 mdw
34 * Split mode macros into interface and implementation.
38 #ifndef CATACOMB_ECB_DEF_H
39 #define CATACOMB_ECB_DEF_H
45 /*----- Header files ------------------------------------------------------*/
50 #include <mLib/bits.h>
53 #ifndef CATACOMB_BLKC_H
57 #ifndef CATACOMB_GCIPHER_H
61 /*----- Macros ------------------------------------------------------------*/
63 /* --- @ECB_DEF@ --- *
65 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
67 * Use: Creates an implementation for ECB stealing mode.
70 #define ECB_DEF(PRE, pre) \
72 /* --- @pre_ecbsetkey@ --- * \
74 * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
75 * @const pre_ctx *k@ = pointer to cipher context \
79 * Use: Sets the ECB context to use a different cipher key. \
82 void pre##_ecbsetkey(pre##_ecbctx *ctx, const pre##_ctx *k) \
87 /* --- @pre_ecbinit@ --- * \
89 * Arguments: @pre_ecbctx *ctx@ = pointer to cipher context \
90 * @const void *key@ = pointer to the key buffer \
91 * @size_t sz@ = size of the key \
92 * @const void *iv@ = pointer to initialization vector \
96 * Use: Initializes an ECB context ready for use. This is \
97 * equivalent to calls to @pre_init@ and @pre_setkey@. \
100 void pre##_ecbinit(pre##_ecbctx *ctx, \
101 const void *key, size_t sz, \
104 pre##_init(&ctx->ctx, key, sz); \
107 /* --- @pre_ecbencrypt@ --- * \
109 * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
110 * @const void *src@ = pointer to source data \
111 * @void *dest@ = pointer to destination data \
112 * @size_t sz@ = size of block to be encrypted \
116 * Use: Encrypts a block with a block cipher in ECB mode, with \
117 * ciphertext stealing and other clever tricks. \
118 * Essentially, data can be encrypted in arbitrary sized \
119 * chunks, although decryption must use the same chunks. \
122 void pre##_ecbencrypt(pre##_ecbctx *ctx, \
123 const void *src, void *dest, \
126 const octet *s = src; \
129 /* --- Empty blocks are trivial --- */ \
134 /* --- Short blocks aren't allowed in ECB --- * \
136 * There's absolutely nothing secure I can do with them. \
139 assert(((void)"ECB must have at least one whole block to work with", \
140 sz >= PRE##_BLKSZ)); \
142 /* --- Do the main chunk of encryption --- * \
144 * This will do the whole lot if it's a whole number of blocks. Just \
145 * give each block to the cipher in turn. This is trivial. \
149 while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
150 uint32 x[PRE##_BLKSZ / 4]; \
151 BLKC_LOAD(PRE, x, s); \
152 pre##_eblk(&ctx->ctx, x, x); \
153 BLKC_STORE(PRE, d, x); \
159 /* --- Do the tail-end block and bit-left-over --- * \
161 * This isn't very efficient. That shouldn't matter much. \
165 uint32 x[PRE##_BLKSZ / 4]; \
166 octet b[PRE##_BLKSZ]; \
169 /* --- Let @sz@ be the size of the partial block --- */ \
173 /* --- First stage --- * \
175 * Read in the current block, and encrypt it. The first part of \
176 * the result is the partial ciphertext block. Don't write that \
177 * out yet, because I've not read the partial plaintext block. \
180 BLKC_LOAD(PRE, x, s); \
181 pre##_eblk(&ctx->ctx, x, x); \
182 BLKC_STORE(PRE, b, x); \
184 /* --- Second stage --- * \
186 * Now move in the partial plaintext block, writing out the \
187 * ciphertext as I go. Then encrypt, and write the complete \
188 * ciphertext block. \
193 for (i = 0; i < sz; i++) { \
194 register octet y = b[i]; \
198 BLKC_LOAD(PRE, x, b); \
199 pre##_eblk(&ctx->ctx, x, x); \
200 BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \
208 /* --- @pre_ecbdecrypt@ --- * \
210 * Arguments: @pre_ecbctx *ctx@ = pointer to ECB context block \
211 * @const void *src@ = pointer to source data \
212 * @void *dest@ = pointer to destination data \
213 * @size_t sz@ = size of block to be encrypted \
217 * Use: Decrypts a block with a block cipher in ECB mode, with \
218 * ciphertext stealing and other clever tricks. \
219 * Essentially, data can be encrypted in arbitrary sized \
220 * chunks, although decryption must use the same chunks. \
223 void pre##_ecbdecrypt(pre##_ecbctx *ctx, \
224 const void *src, void *dest, \
227 const octet *s = src; \
230 /* --- Empty blocks are trivial --- */ \
235 /* --- Short blocks aren't allowed in ECB --- * \
237 * There's absolutely nothing secure I can do with them. \
240 assert(((void)"ECB must have at least one whole block to work with", \
241 sz >= PRE##_BLKSZ)); \
243 /* --- Do the main chunk of decryption --- * \
245 * This will do the whole lot if it's a whole number of blocks. \
246 * Each block is just handed to the block cipher in turn. \
249 while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) { \
250 uint32 x[PRE##_BLKSZ / 4]; \
251 BLKC_LOAD(PRE, x, s); \
252 pre##_dblk(&ctx->ctx, x, x); \
253 BLKC_STORE(PRE, d, x); \
259 /* --- Do the tail-end block and bit-left-over --- * \
261 * This isn't very efficient. That shouldn't matter much. \
265 uint32 x[PRE##_BLKSZ / 4]; \
266 octet b[PRE##_BLKSZ]; \
269 /* --- Let @sz@ be the size of the partial block --- */ \
273 /* --- First stage --- * \
275 * Take the complete ciphertext block, and decrypt it. This block \
276 * is carried over for the next encryption operation. \
279 BLKC_LOAD(PRE, x, s); \
280 pre##_dblk(&ctx->ctx, x, x); \
281 BLKC_STORE(PRE, b, x); \
283 /* --- Second stage --- * \
285 * The first few bytes are the partial plaintext block. Write that \
286 * and replace with the partial ciphertext block. Then decrypt \
287 * what's left as the complete plaintext. \
292 for (i = 0; i < sz; i++) { \
293 register octet y = s[i]; \
297 BLKC_LOAD(PRE, x, b); \
298 pre##_dblk(&ctx->ctx, x, x); \
299 BLKC_STORE(PRE, d - PRE##_BLKSZ, x); \
307 /* --- Generic cipher interface --- */ \
309 static const gcipher_ops gops; \
311 typedef struct gctx { \
316 static gcipher *ginit(const void *k, size_t sz) \
318 gctx *g = CREATE(gctx); \
320 pre##_ecbinit(&g->k, k, sz, 0); \
324 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz) \
326 gctx *g = (gctx *)c; \
327 pre##_ecbencrypt(&g->k, s, t, sz); \
330 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz) \
332 gctx *g = (gctx *)c; \
333 pre##_ecbdecrypt(&g->k, s, t, sz); \
336 static void gdestroy(gcipher *c) \
338 gctx *g = (gctx *)c; \
342 static const gcipher_ops gops = { \
344 gencrypt, gdecrypt, gdestroy, 0, 0 \
347 const gccipher pre##_ecb = { \
348 { #pre "-ecb", PRE##_KEYSZ, PRE##_BLKSZ }, \
354 /*----- Test rig ----------------------------------------------------------*/
360 #include "daftstory.h"
362 /* --- @ECB_TEST@ --- *
364 * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
366 * Use: Standard test rig for ECB functions.
369 #define ECB_TEST(PRE, pre) \
371 /* --- Initial plaintext for the test --- */ \
373 static const octet text[] = TEXT; \
375 /* --- Key and IV to use --- */ \
377 static const octet key[] = KEY; \
378 static const octet iv[] = IV; \
380 /* --- Buffers for encryption and decryption output --- */ \
382 static octet ct[sizeof(text)]; \
383 static octet pt[sizeof(text)]; \
385 static void hexdump(const octet *p, size_t sz) \
387 const octet *q = p + sz; \
388 for (sz = 0; p < q; p++, sz++) { \
389 printf("%02x", *p); \
390 if ((sz + 1) % PRE##_BLKSZ == 0) \
397 size_t sz = 0, rest; \
402 size_t keysz = PRE##_KEYSZ ? \
403 PRE##_KEYSZ : strlen((const char *)key); \
405 fputs(#pre "-ecb: ", stdout); \
407 pre##_ecbinit(&ctx, key, keysz, iv); \
409 while (sz <= sizeof(text)) { \
410 rest = sizeof(text) - sz; \
411 if ((sz != 0 && sz < PRE##_BLKSZ) || \
412 (rest != 0 && rest < PRE##_BLKSZ)) \
414 memcpy(ct, text, sizeof(text)); \
415 pre##_ecbencrypt(&ctx, ct, ct, sz); \
416 pre##_ecbencrypt(&ctx, ct + sz, ct + sz, rest); \
417 memcpy(pt, ct, sizeof(text)); \
418 pre##_ecbdecrypt(&ctx, pt, pt, sz); \
419 pre##_ecbdecrypt(&ctx, pt + sz, pt + sz, rest); \
420 if (memcmp(pt, text, sizeof(text)) == 0) { \
422 if (sizeof(text) < 40 || done % 8 == 0) \
423 fputc('.', stdout); \
424 if (done % 480 == 0) \
425 fputs("\n\t", stdout); \
428 printf("\nError (sz = %lu)\n", (unsigned long)sz); \
430 printf("\tplaintext = "); hexdump(text, sz); \
431 printf(", "); hexdump(text + sz, rest); \
432 fputc('\n', stdout); \
433 printf("\tciphertext = "); hexdump(ct, sz); \
434 printf(", "); hexdump(ct + sz, rest); \
435 fputc('\n', stdout); \
436 printf("\trecovered text = "); hexdump(pt, sz); \
437 printf(", "); hexdump(pt + sz, rest); \
438 fputc('\n', stdout); \
439 fputc('\n', stdout); \
448 fputs(status ? " failed\n" : " ok\n", stdout); \
453 # define ECB_TEST(PRE, pre)
456 /*----- That's all, folks -------------------------------------------------*/