New multiprecision integer arithmetic suite.
[u/mdw/catacomb] / cbc.h
1 /* -*-c-*-
2 *
3 * $Id: cbc.h,v 1.1 1999/09/03 08:41:11 mdw Exp $
4 *
5 * Ciphertext block chaining for block ciphers
6 *
7 * (c) 1999 Straylight/Edgeware
8 */
9
10 /*----- Licensing notice --------------------------------------------------*
11 *
12 * This file is part of Catacomb.
13 *
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.
18 *
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.
23 *
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,
27 * MA 02111-1307, USA.
28 */
29
30 /*----- Revision history --------------------------------------------------*
31 *
32 * $Log: cbc.h,v $
33 * Revision 1.1 1999/09/03 08:41:11 mdw
34 * Initial import.
35 *
36 */
37
38 #ifndef CBC_H
39 #define CBC_H
40
41 #ifdef __cplusplus
42 extern "C" {
43 #endif
44
45 /*----- Header files ------------------------------------------------------*/
46
47 #include <string.h>
48
49 #include <mLib/bits.h>
50
51 #ifndef BLKC_H
52 # include "blkc.h"
53 #endif
54
55 /*----- Macros ------------------------------------------------------------*/
56
57 /* --- @CBC_DECL@ --- *
58 *
59 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
60 *
61 * Use: Creates declarations for CBC stealing mode.
62 */
63
64 #define CBC_DECL(PRE, pre) \
65 \
66 typedef struct pre ## _cbcctx { \
67 pre ## _ctx ctx; /* Underlying cipher context */ \
68 uint32 iv[PRE ## _BLKSZ / 4]; /* Previous ciphertext or IV */ \
69 } pre ## _cbcctx; \
70 \
71 extern void pre ## _cbcgetiv(const pre ## _cbcctx */*ctx*/, \
72 void */*iv*/); \
73 \
74 extern void pre ## _cbcsetiv(pre ## _cbcctx */*ctx*/, \
75 const void */*iv*/); \
76 \
77 extern void pre ## _cbcsetkey(pre ## _cbcctx */*ctx*/, \
78 const pre ## _ctx */*k*/); \
79 \
80 extern void pre ## _cbcinit(pre ## _cbcctx */*ctx*/, \
81 const void */*key*/, size_t /*sz*/, \
82 const void */*iv*/); \
83 \
84 extern void pre ## _cbcencrypt(pre ## _cbcctx */*ctx*/, \
85 const void */*src*/, void */*dest*/, \
86 size_t /*sz*/); \
87 \
88 extern void pre ## _cbcdecrypt(pre ## _cbcctx */*ctx*/, \
89 const void */*src*/, void */*dest*/, \
90 size_t /*sz*/); \
91
92 /* --- @CBC_DEF@ --- *
93 *
94 * Arguments: @PRE@, @pre@ = prefixes for the underlying block cipher
95 *
96 * Use: Creates an implementation for CBC stealing mode.
97 */
98
99 #define CBC_DEF(PRE, pre) \
100 \
101 /* --- @pre_cbcgetiv@ --- * \
102 * \
103 * Arguments: @const pre_cbcctx *ctx@ = pointer to CBC context block \
104 * @void *iv#@ = pointer to output data block \
105 * \
106 * Returns: --- \
107 * \
108 * Use: Reads the currently set IV. Reading and setting an IV \
109 * is transparent to the CBC encryption or decryption \
110 * process. \
111 */ \
112 \
113 void pre ## _cbcgetiv(const pre ## _cbcctx *ctx, void *iv) \
114 { \
115 BLKC_STORE(PRE, iv, ctx->iv); \
116 } \
117 \
118 /* --- @pre_cbcsetiv@ --- * \
119 * \
120 * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
121 * @cnost void *iv@ = pointer to IV to set \
122 * \
123 * Returns: --- \
124 * \
125 * Use: Sets the IV to use for subsequent encryption. \
126 */ \
127 \
128 void pre ## _cbcsetiv(pre ## _cbcctx *ctx, const void *iv) \
129 { \
130 BLKC_LOAD(PRE, ctx->iv, iv); \
131 } \
132 \
133 /* --- @pre_cbcsetkey@ --- * \
134 * \
135 * Arguments: @pre_cbcctx *ctx@ = pointer to CBC context block \
136 * @const pre_ctx *k@ = pointer to cipher context \
137 * \
138 * Returns: --- \
139 * \
140 * Use: Sets the CBC context to use a different cipher key. \
141 */ \
142 \
143 void pre ## _cbcsetkey(pre ## _cbcctx *ctx, const pre ## _ctx *k) \
144 { \
145 ctx->ctx = *k; \
146 } \
147 \
148 /* --- @pre_cbcinit@ --- * \
149 * \
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 \
154 * \
155 * Returns: --- \
156 * \
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@. \
161 */ \
162 \
163 void pre ## _cbcinit(pre ## _cbcctx *ctx, \
164 const void *key, size_t sz, \
165 const void *iv) \
166 { \
167 static octet zero[PRE ## _BLKSZ] = { 0 }; \
168 pre ## _init(&ctx->ctx, key, sz); \
169 BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero); \
170 } \
171 \
172 /* --- @pre_cbcencrypt@ --- * \
173 * \
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 \
178 * \
179 * Returns: --- \
180 * \
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. \
185 */ \
186 \
187 void pre ## _cbcencrypt(pre ## _cbcctx *ctx, \
188 const void *src, void *dest, \
189 size_t sz) \
190 { \
191 const octet *s = src; \
192 octet *d = dest; \
193 \
194 /* --- Empty blocks are trivial --- */ \
195 \
196 if (!sz) \
197 return; \
198 \
199 /* --- Extra magical case for a short block --- * \
200 * \
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. \
204 */ \
205 \
206 if (sz < PRE ## _BLKSZ) { \
207 octet b[PRE ## _BLKSZ]; \
208 unsigned i; \
209 \
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); \
217 return; \
218 } \
219 \
220 /* --- Do the main chunk of encryption --- * \
221 * \
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. \
225 */ \
226 \
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; \
234 } \
235 \
236 /* --- Do the tail-end block and bit-left-over --- * \
237 * \
238 * This isn't very efficient. That shouldn't matter much. \
239 */ \
240 \
241 if (sz) { \
242 octet b[PRE ## _BLKSZ]; \
243 unsigned i; \
244 \
245 /* --- Let @sz@ be the size of the partial block --- */ \
246 \
247 sz -= PRE ## _BLKSZ; \
248 \
249 /* --- First stage --- * \
250 * \
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 \
254 * block. \
255 */ \
256 \
257 BLKC_XLOAD(PRE, ctx->iv, s); \
258 pre ## _eblk(&ctx->ctx, ctx->iv, ctx->iv); \
259 BLKC_STORE(PRE, b, ctx->iv); \
260 \
261 /* --- Second stage --- * \
262 * \
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. \
266 */ \
267 \
268 s += PRE ## _BLKSZ; \
269 d += PRE ## _BLKSZ; \
270 for (i = 0; i < sz; i++) { \
271 register octet x = b[i]; \
272 b[i] ^= s[i]; \
273 d[i] = x; \
274 } \
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); \
278 } \
279 \
280 /* --- Done --- */ \
281 \
282 return; \
283 } \
284 \
285 /* --- @pre_cbcdecrypt@ --- * \
286 * \
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 \
291 * \
292 * Returns: --- \
293 * \
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. \
298 */ \
299 \
300 void pre ## _cbcdecrypt(pre ## _cbcctx *ctx, \
301 const void *src, void *dest, \
302 size_t sz) \
303 { \
304 const octet *s = src; \
305 octet *d = dest; \
306 \
307 /* --- Empty blocks are trivial --- */ \
308 \
309 if (!sz) \
310 return; \
311 \
312 /* --- Extra magical case for a short block --- * \
313 * \
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. \
317 */ \
318 \
319 if (sz < PRE ## _BLKSZ) { \
320 octet b[PRE ## _BLKSZ], c[PRE ## _BLKSZ]; \
321 unsigned i; \
322 \
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]; \
327 d[i] = b[i] ^ x; \
328 c[i] = x; \
329 } \
330 memmove(b, b + sz, PRE ## _BLKSZ - sz); \
331 memcpy(b + PRE ## _BLKSZ - sz, c, sz); \
332 BLKC_LOAD(PRE, ctx->iv, b); \
333 return; \
334 } \
335 \
336 /* --- Do the main chunk of decryption --- * \
337 * \
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. \
341 */ \
342 \
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; \
352 } \
353 \
354 /* --- Do the tail-end block and bit-left-over --- * \
355 * \
356 * This isn't very efficient. That shouldn't matter much. \
357 */ \
358 \
359 if (sz) { \
360 octet b[PRE ## _BLKSZ]; \
361 uint32 bk[PRE ## _BLKSZ / 4], niv[PRE ## _BLKSZ / 4]; \
362 unsigned i; \
363 \
364 /* --- Let @sz@ be the size of the partial block --- */ \
365 \
366 sz -= PRE ## _BLKSZ; \
367 \
368 /* --- First stage --- * \
369 * \
370 * Take the complete ciphertext block, and decrypt it. This block \
371 * is carried over for the next encryption operation. \
372 */ \
373 \
374 BLKC_LOAD(PRE, niv, s); \
375 pre ## _dblk(&ctx->ctx, niv, bk); \
376 \
377 /* --- Second stage --- * \
378 * \
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 \
382 * three. \
383 */ \
384 \
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]; \
390 d[i] = b[i] ^ x; \
391 b[i] = x; \
392 } \
393 \
394 /* --- Third stage --- * \
395 * \
396 * Decrypt the block we've got left, and XOR with the initial IV to \
397 * recover the complete plaintext block. \
398 */ \
399 \
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); \
404 } \
405 \
406 /* --- Done --- */ \
407 \
408 return; \
409 } \
410 \
411 CBC_TEST(PRE, pre)
412
413 /*----- Test rig ----------------------------------------------------------*/
414
415 #ifdef TEST_RIG
416
417 #include <stdio.h>
418
419 #include "daftstory.h"
420
421 /* --- @CBC_TEST@ --- *
422 *
423 * Arguments: @PRE@, @pre@ = prefixes for block cipher definitions
424 *
425 * Use: Standard test rig for CBC functions.
426 */
427
428 #define CBC_TEST(PRE, pre) \
429 \
430 /* --- Initial plaintext for the test --- */ \
431 \
432 static const octet text[] = TEXT; \
433 \
434 /* --- Key and IV to use --- */ \
435 \
436 static const octet key[] = KEY; \
437 static const octet iv[] = IV; \
438 \
439 /* --- Buffers for encryption and decryption output --- */ \
440 \
441 static octet ct[sizeof(text)]; \
442 static octet pt[sizeof(text)]; \
443 \
444 static void hexdump(const octet *p, size_t sz) \
445 { \
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) \
450 putchar(':'); \
451 } \
452 } \
453 \
454 int main(void) \
455 { \
456 size_t sz = 0, rest; \
457 pre ## _cbcctx ctx; \
458 pre ## _ctx k; \
459 int status = 0; \
460 int done = 0; \
461 \
462 size_t keysz = PRE ## _KEYSZ ? \
463 PRE ## _KEYSZ : strlen((const char *)key); \
464 \
465 fputs(#pre "-cbc: ", stdout); \
466 \
467 pre ## _init(&k, key, keysz); \
468 pre ## _cbcsetkey(&ctx, &k); \
469 \
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) { \
481 done++; \
482 if (sizeof(text) < 40 || done % 8 == 0) \
483 fputc('.', stdout); \
484 if (done % 480 == 0) \
485 fputs("\n\t", stdout); \
486 fflush(stdout); \
487 } else { \
488 printf("\nError (sz = %lu)\n", (unsigned long)sz); \
489 status = 1; \
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); \
500 } \
501 if (sz < 63) \
502 sz++; \
503 else \
504 sz += 9; \
505 } \
506 \
507 fputs(status ? " failed\n" : " ok\n", stdout); \
508 return (status); \
509 }
510
511 #else
512 # define CBC_TEST(PRE, pre)
513 #endif
514
515 /*----- That's all, folks -------------------------------------------------*/
516
517 #ifdef __cplusplus
518 }
519 #endif
520
521 #endif