3 * $Id: cbc.h,v 1.1 1999/09/03 08:41:11 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:11 mdw
45 /*----- Header files ------------------------------------------------------*/
49 #include <mLib/bits.h>
55 /*----- Macros ------------------------------------------------------------*/
57 /* --- @CBC_DECL@ --- *
59 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
61 * Use: Creates declarations for CBC stealing mode.
64 #define CBC_DECL(PRE, pre) \
66 typedef struct pre ## _cbcctx { \
67 pre ## _ctx ctx; /* Underlying cipher context */ \
68 uint32 iv[PRE ## _BLKSZ / 4]; /* Previous ciphertext or IV */ \
71 extern void pre ## _cbcgetiv(const pre ## _cbcctx */*ctx*/, \
74 extern void pre ## _cbcsetiv(pre ## _cbcctx */*ctx*/, \
75 const void */*iv*/); \
77 extern void pre ## _cbcsetkey(pre ## _cbcctx */*ctx*/, \
78 const pre ## _ctx */*k*/); \
80 extern void pre ## _cbcinit(pre ## _cbcctx */*ctx*/, \
81 const void */*key*/, size_t /*sz*/, \
82 const void */*iv*/); \
84 extern void pre ## _cbcencrypt(pre ## _cbcctx */*ctx*/, \
85 const void */*src*/, void */*dest*/, \
88 extern void pre ## _cbcdecrypt(pre ## _cbcctx */*ctx*/, \
89 const void */*src*/, void */*dest*/, \
92 /* --- @CBC_DEF@ --- *
94 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
96 * Use: Creates an implementation for CBC stealing mode.
99 #define CBC_DEF(PRE, pre) \
101 /* --- @pre_cbcgetiv@ --- * \
103 * Arguments: @const pre_cbcctx *ctx@ = pointer to CBC context block \
104 * @void *iv#@ = pointer to output data block \
108 * Use: Reads the currently set IV. Reading and setting an IV \
109 * is transparent to the CBC encryption or decryption \
113 void pre ## _cbcgetiv(const pre ## _cbcctx *ctx, void *iv) \
115 BLKC_STORE(PRE, iv, ctx->iv); \
118 /* --- @pre_cbcsetiv@ --- * \
120 * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
121 * @cnost void *iv@ = pointer to IV to set \
125 * Use: Sets the IV to use for subsequent encryption. \
128 void pre ## _cbcsetiv(pre ## _cbcctx *ctx, const void *iv) \
130 BLKC_LOAD(PRE, ctx->iv, iv); \
133 /* --- @pre_cbcsetkey@ --- * \
135 * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
136 * @const pre_ctx *k@ = pointer to cipher context \
140 * Use: Sets the CBC context to use a different cipher key. \
143 void pre ## _cbcsetkey(pre ## _cbcctx *ctx, const pre ## _ctx *k) \
148 /* --- @pre_cbcinit@ --- * \
150 * Arguments: @pre_cbcctx *ctx@ = pointer to cipher context \
151 * @const void *key@ = pointer to the key buffer \
152 * @size_t sz@ = size of the key \
153 * @const void *iv@ = pointer to initialization vector \
157 * Use: Initializes a CBC context ready for use. The @iv@ \
158 * argument may be passed as a null pointer to set a zero \
159 * IV. Apart from that, this call is equivalent to calls \
160 * to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@. \
163 void pre ## _cbcinit(pre ## _cbcctx *ctx, \
164 const void *key, size_t sz, \
167 static octet zero[PRE ## _BLKSZ] = { 0 }; \
168 pre ## _init(&ctx->ctx, key, sz); \
169 BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero); \
172 /* --- @pre_cbcencrypt@ --- * \
174 * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
175 * @const void *src@ = pointer to source data \
176 * @void *dest@ = pointer to destination data \
177 * @size_t sz@ = size of block to be encrypted \
181 * Use: Encrypts a block with a block cipher in CBC mode, with \
182 * ciphertext stealing and other clever tricks. \
183 * Essentially, data can be encrypted in arbitrary sized \
184 * chunks, although decryption must use the same chunks. \
187 void pre ## _cbcencrypt(pre ## _cbcctx *ctx, \
188 const void *src, void *dest, \
191 const octet *s = src; \
194 /* --- Empty blocks are trivial --- */ \
199 /* --- Extra magical case for a short block --- * \
201 * Encrypt the IV, then exclusive-or the plaintext with the octets \
202 * of the encrypted IV, shifting ciphertext octets in instead. This \
203 * basically switches over to CFB. \
206 if (sz < PRE ## _BLKSZ) { \
207 octet b[PRE ## _BLKSZ]; \
210 pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
211 BLKC_STORE(PRE, b, ctx->iv); \
212 for (i = 0; i < sz; i++) \
213 d[i] = b[i] ^ s[i]; \
214 memmove(b, b + sz, PRE ## _BLKSZ - sz); \
215 memcpy(b + PRE ## _BLKSZ - sz, d, sz); \
216 BLKC_LOAD(PRE, ctx->iv, b); \
220 /* --- Do the main chunk of encryption --- * \
222 * This will do the whole lot if it's a whole number of blocks. For \
223 * each block, XOR it with the previous ciphertext in @iv@, encrypt, \
224 * and keep a copy of the ciphertext for the next block. \
227 while (sz >= 2 * PRE ## _BLKSZ || sz == PRE ## _BLKSZ) { \
228 BLKC_XLOAD(PRE, ctx->iv, s); \
229 pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
230 BLKC_STORE(PRE, d, ctx->iv); \
231 s += PRE ## _BLKSZ; \
232 d += PRE ## _BLKSZ; \
233 sz -= PRE ## _BLKSZ; \
236 /* --- Do the tail-end block and bit-left-over --- * \
238 * This isn't very efficient. That shouldn't matter much. \
242 octet b[PRE ## _BLKSZ]; \
245 /* --- Let @sz@ be the size of the partial block --- */ \
247 sz -= PRE ## _BLKSZ; \
249 /* --- First stage --- * \
251 * XOR the complete block with the current IV, and encrypt it. The \
252 * first part of the result is the partial ciphertext block. Don't \
253 * write that out yet, because I've not read the partial plaintext \
257 BLKC_XLOAD(PRE, ctx->iv, s); \
258 pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
259 BLKC_STORE(PRE, b, ctx->iv); \
261 /* --- Second stage --- * \
263 * Now XOR in the partial plaintext block, writing out the \
264 * ciphertext as I go. Then encrypt, and write the complete \
265 * ciphertext block. \
268 s += PRE ## _BLKSZ; \
269 d += PRE ## _BLKSZ; \
270 for (i = 0; i < sz; i++) { \
271 register octet x = b[i]; \
275 BLKC_LOAD(PRE, ctx->iv, b); \
276 pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
277 BLKC_STORE(PRE, d - PRE ## _BLKSZ, ctx->iv); \
285 /* --- @pre_cbcdecrypt@ --- * \
287 * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
288 * @const void *src@ = pointer to source data \
289 * @void *dest@ = pointer to destination data \
290 * @size_t sz@ = size of block to be encrypted \
294 * Use: Encrypts a block with a block cipher in CBC mode, with \
295 * ciphertext stealing and other clever tricks. \
296 * Essentially, data can be encrypted in arbitrary sized \
297 * chunks, although decryption must use the same chunks. \
300 void pre ## _cbcdecrypt(pre ## _cbcctx *ctx, \
301 const void *src, void *dest, \
304 const octet *s = src; \
307 /* --- Empty blocks are trivial --- */ \
312 /* --- Extra magical case for a short block --- * \
314 * Encrypt the IV, then exclusive-or the ciphertext with the octets \
315 * of the encrypted IV, shifting ciphertext octets in instead. This \
316 * basically switches over to CFB. \
319 if (sz < PRE ## _BLKSZ) { \
320 octet b[PRE ## _BLKSZ], c[PRE ## _BLKSZ]; \
323 pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
324 BLKC_STORE(PRE, b, ctx->iv); \
325 for (i = 0; i < sz; i++) { \
326 register octet x = s[i]; \
330 memmove(b, b + sz, PRE ## _BLKSZ - sz); \
331 memcpy(b + PRE ## _BLKSZ - sz, c, sz); \
332 BLKC_LOAD(PRE, ctx->iv, b); \
336 /* --- Do the main chunk of decryption --- * \
338 * This will do the whole lot if it's a whole number of blocks. For \
339 * each block, decrypt, XOR it with the previous ciphertext in @iv@, \
340 * and keep a copy of the ciphertext for the next block. \
343 while (sz >= 2 * PRE ## _BLKSZ || sz == PRE ## _BLKSZ) { \
344 uint32 b[PRE ## _BLKSZ / 4], niv[PRE ## _BLKSZ / 4]; \
345 BLKC_LOAD(PRE, niv, s); \
346 pre ## _dblk(&ctx->ctx, niv, b); \
347 BLKC_XSTORE(PRE, d, b, ctx->iv); \
348 BLKC_MOVE(PRE, ctx->iv, niv); \
349 s += PRE ## _BLKSZ; \
350 d += PRE ## _BLKSZ; \
351 sz -= PRE ## _BLKSZ; \
354 /* --- Do the tail-end block and bit-left-over --- * \
356 * This isn't very efficient. That shouldn't matter much. \
360 octet b[PRE ## _BLKSZ]; \
361 uint32 bk[PRE ## _BLKSZ / 4], niv[PRE ## _BLKSZ / 4]; \
364 /* --- Let @sz@ be the size of the partial block --- */ \
366 sz -= PRE ## _BLKSZ; \
368 /* --- First stage --- * \
370 * Take the complete ciphertext block, and decrypt it. This block \
371 * is carried over for the next encryption operation. \
374 BLKC_LOAD(PRE, niv, s); \
375 pre ## _dblk(&ctx->ctx, niv, bk); \
377 /* --- Second stage --- * \
379 * XORing the first few bytes of this with the partial ciphertext \
380 * block recovers the partial plaintext block. At the same time, \
381 * write the partial ciphertext block's contents in ready for stage \
385 BLKC_STORE(PRE, b, bk); \
386 s += PRE ## _BLKSZ; \
387 d += PRE ## _BLKSZ; \
388 for (i = 0; i < sz; i++) { \
389 register octet x = s[i]; \
394 /* --- Third stage --- * \
396 * Decrypt the block we've got left, and XOR with the initial IV to \
397 * recover the complete plaintext block. \
400 BLKC_LOAD(PRE, bk, b); \
401 pre ## _dblk(&ctx->ctx, bk, bk); \
402 BLKC_XSTORE(PRE, d - PRE ## _BLKSZ, bk, ctx->iv); \
403 BLKC_MOVE(PRE, ctx->iv, niv); \
413 /*----- Test rig ----------------------------------------------------------*/
419 #include "daftstory.h"
421 /* --- @CBC_TEST@ --- *
423 * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
425 * Use: Standard test rig for CBC functions.
428 #define CBC_TEST(PRE, pre) \
430 /* --- Initial plaintext for the test --- */ \
432 static const octet text[] = TEXT; \
434 /* --- Key and IV to use --- */ \
436 static const octet key[] = KEY; \
437 static const octet iv[] = IV; \
439 /* --- Buffers for encryption and decryption output --- */ \
441 static octet ct[sizeof(text)]; \
442 static octet pt[sizeof(text)]; \
444 static void hexdump(const octet *p, size_t sz) \
446 const octet *q = p + sz; \
447 for (sz = 0; p < q; p++, sz++) { \
448 printf("%02x", *p); \
449 if ((sz + 1) % PRE ## _BLKSZ == 0) \
456 size_t sz = 0, rest; \
457 pre ## _cbcctx ctx; \
462 size_t keysz = PRE ## _KEYSZ ? \
463 PRE ## _KEYSZ : strlen((const char *)key); \
465 fputs(#pre "-cbc: ", stdout); \
467 pre ## _init(&k, key, keysz); \
468 pre ## _cbcsetkey(&ctx, &k); \
470 while (sz <= sizeof(text)) { \
471 rest = sizeof(text) - sz; \
472 memcpy(ct, text, sizeof(text)); \
473 pre ## _cbcsetiv(&ctx, iv); \
474 pre ## _cbcencrypt(&ctx, ct, ct, sz); \
475 pre ## _cbcencrypt(&ctx, ct + sz, ct + sz, rest); \
476 memcpy(pt, ct, sizeof(text)); \
477 pre ## _cbcsetiv(&ctx, iv); \
478 pre ## _cbcdecrypt(&ctx, pt, pt, sz); \
479 pre ## _cbcdecrypt(&ctx, pt + sz, pt + sz, rest); \
480 if (memcmp(pt, text, sizeof(text)) == 0) { \
482 if (sizeof(text) < 40 || done % 8 == 0) \
483 fputc('.', stdout); \
484 if (done % 480 == 0) \
485 fputs("\n\t", stdout); \
488 printf("\nError (sz = %lu)\n", (unsigned long)sz); \
490 printf("\tplaintext = "); hexdump(text, sz); \
491 printf(", "); hexdump(text + sz, rest); \
492 fputc('\n', stdout); \
493 printf("\tciphertext = "); hexdump(ct, sz); \
494 printf(", "); hexdump(ct + sz, rest); \
495 fputc('\n', stdout); \
496 printf("\trecovered text = "); hexdump(pt, sz); \
497 printf(", "); hexdump(pt + sz, rest); \
498 fputc('\n', stdout); \
499 fputc('\n', stdout); \
507 fputs(status ? " failed\n" : " ok\n", stdout); \
512 # define CBC_TEST(PRE, pre)
515 /*----- That's all, folks -------------------------------------------------*/