chiark / gitweb /
Add some more vectors, and a whinge about how Skipjack test vectors are.
[catacomb] / cbc-def.h
1 /* -*-c-*-
2  *
3  * $Id: cbc-def.h,v 1.2 2000/06/17 10:49:52 mdw Exp $
4  *
5  * Definitions for cipher block chaining mode
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-def.h,v $
33  * Revision 1.2  2000/06/17 10:49:52  mdw
34  * Use secure arena for memory allocation.
35  *
36  * Revision 1.1  1999/12/10 23:16:39  mdw
37  * Split mode macros into interface and implementation.
38  *
39  */
40
41 #ifndef CATACOMB_CBC_DEF_H
42 #define CATACOMB_CBC_DEF_H
43
44 #ifdef __cplusplus
45   extern "C" {
46 #endif
47
48 /*----- Header files ------------------------------------------------------*/
49
50 #include <string.h>
51
52 #include <mLib/bits.h>
53 #include <mLib/sub.h>
54
55 #ifndef CATACOMB_ARENA_H
56 #  include "arena.h"
57 #endif
58
59 #ifndef CATACOMB_BLKC_H
60 #  include "blkc.h"
61 #endif
62
63 #ifndef CATACOMB_GCIPHER_H
64 #  include "gcipher.h"
65 #endif
66
67 #ifndef CATACOMB_PARANOIA_H
68 #  include "paranoia.h"
69 #endif
70
71 /*----- Macros ------------------------------------------------------------*/
72
73 /* --- @CBC_DEF@ --- *
74  *
75  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
76  *
77  * Use:         Creates an implementation for CBC stealing mode.
78  */
79
80 #define CBC_DEF(PRE, pre)                                               \
81                                                                         \
82 /* --- @pre_cbcgetiv@ --- *                                             \
83  *                                                                      \
84  * Arguments:   @const pre_cbcctx *ctx@ = pointer to CBC context block  \
85  *              @void *iv#@ = pointer to output data block              \
86  *                                                                      \
87  * Returns:     ---                                                     \
88  *                                                                      \
89  * Use:         Reads the currently set IV.  Reading and setting an IV  \
90  *              is transparent to the CBC encryption or decryption      \
91  *              process.                                                \
92  */                                                                     \
93                                                                         \
94 void pre##_cbcgetiv(const pre##_cbcctx *ctx, void *iv)                  \
95 {                                                                       \
96   BLKC_STORE(PRE, iv, ctx->iv);                                         \
97 }                                                                       \
98                                                                         \
99 /* --- @pre_cbcsetiv@ --- *                                             \
100  *                                                                      \
101  * Arguments:   @pre_cbcctx *ctx@ = pointer to CBC context block        \
102  *              @cnost void *iv@ = pointer to IV to set                 \
103  *                                                                      \
104  * Returns:     ---                                                     \
105  *                                                                      \
106  * Use:         Sets the IV to use for subsequent encryption.           \
107  */                                                                     \
108                                                                         \
109 void pre##_cbcsetiv(pre##_cbcctx *ctx, const void *iv)                  \
110 {                                                                       \
111   BLKC_LOAD(PRE, ctx->iv, iv);                                          \
112 }                                                                       \
113                                                                         \
114 /* --- @pre_cbcsetkey@ --- *                                            \
115  *                                                                      \
116  * Arguments:   @pre_cbcctx *ctx@ = pointer to CBC context block        \
117  *              @const pre_ctx *k@ = pointer to cipher context          \
118  *                                                                      \
119  * Returns:     ---                                                     \
120  *                                                                      \
121  * Use:         Sets the CBC context to use a different cipher key.     \
122  */                                                                     \
123                                                                         \
124 void pre##_cbcsetkey(pre##_cbcctx *ctx, const pre##_ctx *k)             \
125 {                                                                       \
126   ctx->ctx = *k;                                                        \
127 }                                                                       \
128                                                                         \
129 /* --- @pre_cbcinit@ --- *                                              \
130  *                                                                      \
131  * Arguments:   @pre_cbcctx *ctx@ = pointer to cipher context           \
132  *              @const void *key@ = pointer to the key buffer           \
133  *              @size_t sz@ = size of the key                           \
134  *              @const void *iv@ = pointer to initialization vector     \
135  *                                                                      \
136  * Returns:     ---                                                     \
137  *                                                                      \
138  * Use:         Initializes a CBC context ready for use.  The @iv@      \
139  *              argument may be passed as a null pointer to set a zero  \
140  *              IV.  Apart from that, this call is equivalent to calls  \
141  *              to @pre_init@, @pre_cbcsetkey@ and @pre_cbcsetiv@.      \
142  */                                                                     \
143                                                                         \
144 void pre##_cbcinit(pre##_cbcctx *ctx,                                   \
145                      const void *key, size_t sz,                        \
146                      const void *iv)                                    \
147 {                                                                       \
148   static octet zero[PRE##_BLKSZ] = { 0 };                               \
149   pre##_init(&ctx->ctx, key, sz);                                       \
150   BLKC_LOAD(PRE, ctx->iv, iv ? iv : zero);                              \
151 }                                                                       \
152                                                                         \
153 /* --- @pre_cbcencrypt@ --- *                                           \
154  *                                                                      \
155  * Arguments:   @pre_cbcctx *ctx@ = pointer to CBC context block        \
156  *              @const void *src@ = pointer to source data              \
157  *              @void *dest@ = pointer to destination data              \
158  *              @size_t sz@ = size of block to be encrypted             \
159  *                                                                      \
160  * Returns:     ---                                                     \
161  *                                                                      \
162  * Use:         Encrypts a block with a block cipher in CBC mode, with  \
163  *              ciphertext stealing and other clever tricks.            \
164  *              Essentially, data can be encrypted in arbitrary sized   \
165  *              chunks, although decryption must use the same chunks.   \
166  */                                                                     \
167                                                                         \
168 void pre##_cbcencrypt(pre##_cbcctx *ctx,                                \
169                         const void *src, void *dest,                    \
170                         size_t sz)                                      \
171 {                                                                       \
172   const octet *s = src;                                                 \
173   octet *d = dest;                                                      \
174                                                                         \
175   /* --- Empty blocks are trivial --- */                                \
176                                                                         \
177   if (!sz)                                                              \
178     return;                                                             \
179                                                                         \
180   /* --- Extra magical case for a short block --- *                     \
181    *                                                                    \
182    * Encrypt the IV, then exclusive-or the plaintext with the octets    \
183    * of the encrypted IV, shifting ciphertext octets in instead.  This  \
184    * basically switches over to CFB.                                    \
185    */                                                                   \
186                                                                         \
187   if (sz < PRE##_BLKSZ) {                                               \
188     octet b[PRE##_BLKSZ];                                               \
189     unsigned i;                                                         \
190                                                                         \
191     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
192     BLKC_STORE(PRE, b, ctx->iv);                                        \
193     for (i = 0; i < sz; i++)                                            \
194       d[i] = b[i] ^ s[i];                                               \
195     memmove(b, b + sz, PRE##_BLKSZ - sz);                               \
196     memcpy(b + PRE##_BLKSZ - sz, d, sz);                                \
197     BLKC_LOAD(PRE, ctx->iv, b);                                         \
198     return;                                                             \
199   }                                                                     \
200                                                                         \
201   /* --- Do the main chunk of encryption --- *                          \
202    *                                                                    \
203    * This will do the whole lot if it's a whole number of blocks.  For  \
204    * each block, XOR it with the previous ciphertext in @iv@, encrypt,  \
205    * and keep a copy of the ciphertext for the next block.              \
206    */                                                                   \
207                                                                         \
208   while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                  \
209     BLKC_XLOAD(PRE, ctx->iv, s);                                        \
210     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
211     BLKC_STORE(PRE, d, ctx->iv);                                        \
212     s += PRE##_BLKSZ;                                                   \
213     d += PRE##_BLKSZ;                                                   \
214     sz -= PRE##_BLKSZ;                                                  \
215   }                                                                     \
216                                                                         \
217   /* --- Do the tail-end block and bit-left-over --- *                  \
218    *                                                                    \
219    * This isn't very efficient.  That shouldn't matter much.            \
220    */                                                                   \
221                                                                         \
222   if (sz) {                                                             \
223     octet b[PRE##_BLKSZ];                                               \
224     unsigned i;                                                         \
225                                                                         \
226     /* --- Let @sz@ be the size of the partial block --- */             \
227                                                                         \
228     sz -= PRE##_BLKSZ;                                                  \
229                                                                         \
230     /* --- First stage --- *                                            \
231      *                                                                  \
232      * XOR the complete block with the current IV, and encrypt it.  The \
233      * first part of the result is the partial ciphertext block.  Don't \
234      * write that out yet, because I've not read the partial plaintext  \
235      * block.                                                           \
236      */                                                                 \
237                                                                         \
238     BLKC_XLOAD(PRE, ctx->iv, s);                                        \
239     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
240     BLKC_STORE(PRE, b, ctx->iv);                                        \
241                                                                         \
242     /* --- Second stage --- *                                           \
243      *                                                                  \
244      * Now XOR in the partial plaintext block, writing out the          \
245      * ciphertext as I go.  Then encrypt, and write the complete        \
246      * ciphertext block.                                                \
247      */                                                                 \
248                                                                         \
249     s += PRE##_BLKSZ;                                                   \
250     d += PRE##_BLKSZ;                                                   \
251     for (i = 0; i < sz; i++) {                                          \
252       register octet x = b[i];                                          \
253       b[i] ^= s[i];                                                     \
254       d[i] = x;                                                         \
255     }                                                                   \
256     BLKC_LOAD(PRE, ctx->iv, b);                                         \
257     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
258     BLKC_STORE(PRE, d - PRE##_BLKSZ, ctx->iv);                          \
259   }                                                                     \
260                                                                         \
261   /* --- Done --- */                                                    \
262                                                                         \
263   return;                                                               \
264 }                                                                       \
265                                                                         \
266 /* --- @pre_cbcdecrypt@ --- *                                           \
267  *                                                                      \
268  * Arguments:   @pre_cbcctx *ctx@ = pointer to CBC context block        \
269  *              @const void *src@ = pointer to source data              \
270  *              @void *dest@ = pointer to destination data              \
271  *              @size_t sz@ = size of block to be encrypted             \
272  *                                                                      \
273  * Returns:     ---                                                     \
274  *                                                                      \
275  * Use:         Decrypts a block with a block cipher in CBC mode, with  \
276  *              ciphertext stealing and other clever tricks.            \
277  *              Essentially, data can be encrypted in arbitrary sized   \
278  *              chunks, although decryption must use the same chunks.   \
279  */                                                                     \
280                                                                         \
281 void pre##_cbcdecrypt(pre##_cbcctx *ctx,                                \
282                         const void *src, void *dest,                    \
283                         size_t sz)                                      \
284 {                                                                       \
285   const octet *s = src;                                                 \
286   octet *d = dest;                                                      \
287                                                                         \
288   /* --- Empty blocks are trivial --- */                                \
289                                                                         \
290   if (!sz)                                                              \
291     return;                                                             \
292                                                                         \
293   /* --- Extra magical case for a short block --- *                     \
294    *                                                                    \
295    * Encrypt the IV, then exclusive-or the ciphertext with the octets   \
296    * of the encrypted IV, shifting ciphertext octets in instead.  This  \
297    * basically switches over to CFB.                                    \
298    */                                                                   \
299                                                                         \
300   if (sz < PRE##_BLKSZ) {                                               \
301     octet b[PRE##_BLKSZ], c[PRE##_BLKSZ];                               \
302     unsigned i;                                                         \
303                                                                         \
304     pre##_eblk(&ctx->ctx, ctx->iv, ctx->iv);                            \
305     BLKC_STORE(PRE, b, ctx->iv);                                        \
306     for (i = 0; i < sz; i++) {                                          \
307       register octet x = s[i];                                          \
308       d[i] = b[i] ^ x;                                                  \
309       c[i] = x;                                                         \
310     }                                                                   \
311     memmove(b, b + sz, PRE##_BLKSZ - sz);                               \
312     memcpy(b + PRE##_BLKSZ - sz, c, sz);                                \
313     BLKC_LOAD(PRE, ctx->iv, b);                                         \
314     return;                                                             \
315   }                                                                     \
316                                                                         \
317   /* --- Do the main chunk of decryption --- *                          \
318    *                                                                    \
319    * This will do the whole lot if it's a whole number of blocks.  For  \
320    * each block, decrypt, XOR it with the previous ciphertext in @iv@,  \
321    * and keep a copy of the ciphertext for the next block.              \
322    */                                                                   \
323                                                                         \
324   while (sz >= 2 * PRE##_BLKSZ || sz == PRE##_BLKSZ) {                  \
325     uint32 b[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4];                    \
326     BLKC_LOAD(PRE, niv, s);                                             \
327     pre##_dblk(&ctx->ctx, niv, b);                                      \
328     BLKC_XSTORE(PRE, d, b, ctx->iv);                                    \
329     BLKC_MOVE(PRE, ctx->iv, niv);                                       \
330     s += PRE##_BLKSZ;                                                   \
331     d += PRE##_BLKSZ;                                                   \
332     sz -= PRE##_BLKSZ;                                                  \
333   }                                                                     \
334                                                                         \
335   /* --- Do the tail-end block and bit-left-over --- *                  \
336    *                                                                    \
337    * This isn't very efficient.  That shouldn't matter much.            \
338    */                                                                   \
339                                                                         \
340   if (sz) {                                                             \
341     octet b[PRE##_BLKSZ];                                               \
342     uint32 bk[PRE##_BLKSZ / 4], niv[PRE##_BLKSZ / 4];                   \
343     unsigned i;                                                         \
344                                                                         \
345     /* --- Let @sz@ be the size of the partial block --- */             \
346                                                                         \
347     sz -= PRE##_BLKSZ;                                                  \
348                                                                         \
349     /* --- First stage --- *                                            \
350      *                                                                  \
351      * Take the complete ciphertext block, and decrypt it.  This block  \
352      * is carried over for the next encryption operation.               \
353      */                                                                 \
354                                                                         \
355     BLKC_LOAD(PRE, niv, s);                                             \
356     pre##_dblk(&ctx->ctx, niv, bk);                                     \
357                                                                         \
358     /* --- Second stage --- *                                           \
359      *                                                                  \
360      * XORing the first few bytes of this with the partial ciphertext   \
361      * block recovers the partial plaintext block.  At the same time,   \
362      * write the partial ciphertext block's contents in ready for stage \
363      * three.                                                           \
364      */                                                                 \
365                                                                         \
366     BLKC_STORE(PRE, b, bk);                                             \
367     s += PRE##_BLKSZ;                                                   \
368     d += PRE##_BLKSZ;                                                   \
369     for (i = 0; i < sz; i++) {                                          \
370       register octet x = s[i];                                          \
371       d[i] = b[i] ^ x;                                                  \
372       b[i] = x;                                                         \
373     }                                                                   \
374                                                                         \
375     /* --- Third stage --- *                                            \
376      *                                                                  \
377      * Decrypt the block we've got left, and XOR with the initial IV to \
378      * recover the complete plaintext block.                            \
379      */                                                                 \
380                                                                         \
381     BLKC_LOAD(PRE, bk, b);                                              \
382     pre##_dblk(&ctx->ctx, bk, bk);                                      \
383     BLKC_XSTORE(PRE, d - PRE##_BLKSZ, bk, ctx->iv);                     \
384     BLKC_MOVE(PRE, ctx->iv, niv);                                       \
385   }                                                                     \
386                                                                         \
387   /* --- Done --- */                                                    \
388                                                                         \
389   return;                                                               \
390 }                                                                       \
391                                                                         \
392 /* --- Generic cipher interface --- */                                  \
393                                                                         \
394 static const gcipher_ops gops;                                          \
395                                                                         \
396 typedef struct gctx {                                                   \
397   gcipher c;                                                            \
398   pre##_cbcctx k;                                                       \
399 } gctx;                                                                 \
400                                                                         \
401 static gcipher *ginit(const void *k, size_t sz)                         \
402 {                                                                       \
403   gctx *g = S_CREATE(gctx);                                             \
404   g->c.ops = &gops;                                                     \
405   pre##_cbcinit(&g->k, k, sz, 0);                                       \
406   return (&g->c);                                                       \
407 }                                                                       \
408                                                                         \
409 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
410 {                                                                       \
411   gctx *g = (gctx *)c;                                                  \
412   pre##_cbcencrypt(&g->k, s, t, sz);                                    \
413 }                                                                       \
414                                                                         \
415 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)     \
416 {                                                                       \
417   gctx *g = (gctx *)c;                                                  \
418   pre##_cbcdecrypt(&g->k, s, t, sz);                                    \
419 }                                                                       \
420                                                                         \
421 static void gdestroy(gcipher *c)                                        \
422 {                                                                       \
423   gctx *g = (gctx *)c;                                                  \
424   BURN(*g);                                                             \
425   S_DESTROY(g);                                                         \
426 }                                                                       \
427                                                                         \
428 static void gsetiv(gcipher *c, const void *iv)                          \
429 {                                                                       \
430   gctx *g = (gctx *)c;                                                  \
431   pre##_cbcsetiv(&g->k, iv);                                            \
432 }                                                                       \
433                                                                         \
434 static const gcipher_ops gops = {                                       \
435   &pre##_cbc,                                                           \
436   gencrypt, gdecrypt, gdestroy, gsetiv, 0                               \
437 };                                                                      \
438                                                                         \
439 const gccipher pre##_cbc = {                                            \
440   #pre "-cbc", pre##_keysz, PRE##_BLKSZ,                                \
441   ginit                                                                 \
442 };                                                                      \
443                                                                         \
444 CBC_TEST(PRE, pre)
445
446 /*----- Test rig ----------------------------------------------------------*/
447
448 #ifdef TEST_RIG
449
450 #include <stdio.h>
451
452 #include "daftstory.h"
453
454 /* --- @CBC_TEST@ --- *
455  *
456  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
457  *
458  * Use:         Standard test rig for CBC functions.
459  */
460
461 #define CBC_TEST(PRE, pre)                                              \
462                                                                         \
463 /* --- Initial plaintext for the test --- */                            \
464                                                                         \
465 static const octet text[] = TEXT;                                       \
466                                                                         \
467 /* --- Key and IV to use --- */                                         \
468                                                                         \
469 static const octet key[] = KEY;                                         \
470 static const octet iv[] = IV;                                           \
471                                                                         \
472 /* --- Buffers for encryption and decryption output --- */              \
473                                                                         \
474 static octet ct[sizeof(text)];                                          \
475 static octet pt[sizeof(text)];                                          \
476                                                                         \
477 static void hexdump(const octet *p, size_t sz)                          \
478 {                                                                       \
479   const octet *q = p + sz;                                              \
480   for (sz = 0; p < q; p++, sz++) {                                      \
481     printf("%02x", *p);                                                 \
482     if ((sz + 1) % PRE##_BLKSZ == 0)                                    \
483       putchar(':');                                                     \
484   }                                                                     \
485 }                                                                       \
486                                                                         \
487 int main(void)                                                          \
488 {                                                                       \
489   size_t sz = 0, rest;                                                  \
490   pre##_cbcctx ctx;                                                     \
491   pre##_ctx k;                                                          \
492   int status = 0;                                                       \
493   int done = 0;                                                         \
494                                                                         \
495   size_t keysz = PRE##_KEYSZ ?                                          \
496     PRE##_KEYSZ : strlen((const char *)key);                            \
497                                                                         \
498   fputs(#pre "-cbc: ", stdout);                                         \
499                                                                         \
500   pre##_init(&k, key, keysz);                                           \
501   pre##_cbcsetkey(&ctx, &k);                                            \
502                                                                         \
503   while (sz <= sizeof(text)) {                                          \
504     rest = sizeof(text) - sz;                                           \
505     memcpy(ct, text, sizeof(text));                                     \
506     pre##_cbcsetiv(&ctx, iv);                                           \
507     pre##_cbcencrypt(&ctx, ct, ct, sz);                                 \
508     pre##_cbcencrypt(&ctx, ct + sz, ct + sz, rest);                     \
509     memcpy(pt, ct, sizeof(text));                                       \
510     pre##_cbcsetiv(&ctx, iv);                                           \
511     pre##_cbcdecrypt(&ctx, pt, pt, sz);                                 \
512     pre##_cbcdecrypt(&ctx, pt + sz, pt + sz, rest);                     \
513     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
514       done++;                                                           \
515       if (sizeof(text) < 40 || done % 8 == 0)                           \
516         fputc('.', stdout);                                             \
517       if (done % 480 == 0)                                              \
518         fputs("\n\t", stdout);                                          \
519       fflush(stdout);                                                   \
520     } else {                                                            \
521       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
522       status = 1;                                                       \
523       printf("\tplaintext      = "); hexdump(text, sz);                 \
524         printf(", "); hexdump(text + sz, rest);                         \
525         fputc('\n', stdout);                                            \
526       printf("\tciphertext     = "); hexdump(ct, sz);                   \
527         printf(", "); hexdump(ct + sz, rest);                           \
528         fputc('\n', stdout);                                            \
529       printf("\trecovered text = "); hexdump(pt, sz);                   \
530         printf(", "); hexdump(pt + sz, rest);                           \
531         fputc('\n', stdout);                                            \
532       fputc('\n', stdout);                                              \
533     }                                                                   \
534     if (sz < 63)                                                        \
535       sz++;                                                             \
536     else                                                                \
537       sz += 9;                                                          \
538   }                                                                     \
539                                                                         \
540   fputs(status ? " failed\n" : " ok\n", stdout);                        \
541   return (status);                                                      \
542 }
543
544 #else
545 #  define CBC_TEST(PRE, pre)
546 #endif
547
548 /*----- That's all, folks -------------------------------------------------*/
549
550 #ifdef __cplusplus
551   }
552 #endif
553
554 #endif