chiark / gitweb /
Split mode macros into interface and implementation.
[catacomb] / cfb-def.h
1 /* -*-c-*-
2  *
3  * $Id: cfb-def.h,v 1.1 1999/12/10 23:16:39 mdw Exp $
4  *
5  * Definitions for ciphertext feedback 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: cfb-def.h,v $
33  * Revision 1.1  1999/12/10 23:16:39  mdw
34  * Split mode macros into interface and implementation.
35  *
36  */
37
38 #ifndef CATACOMB_CFB_DEF_H
39 #define CATACOMB_CFB_DEF_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 #include <mLib/sub.h>
51
52 #ifndef CATACOMB_BLKC_H
53 #  include "blkc.h"
54 #endif
55
56 #ifndef CATACOMB_GCIPHER_H
57 #  include "gcipher.h"
58 #endif
59
60 #ifndef CATACOMB_PARANOIA_H
61 #  include "paranoia.h"
62 #endif
63
64 /*----- Macros ------------------------------------------------------------*/
65
66 /* --- @CFB_DEF@ --- *
67  *
68  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
69  *
70  * Use:         Creates an implementation for CFB mode.
71  */
72
73 #define CFB_DEF(PRE, pre)                                               \
74                                                                         \
75 /* --- @pre_cfbgetiv@ --- *                                             \
76  *                                                                      \
77  * Arguments:   @const pre_cfbctx *ctx@ = pointer to CFB context block  \
78  *              @void *iv#@ = pointer to output data block              \
79  *                                                                      \
80  * Returns:     ---                                                     \
81  *                                                                      \
82  * Use:         Reads the currently set IV.  Reading and setting an IV  \
83  *              is not transparent to the cipher.  It will add a `step' \
84  *              which must be matched by a similar operation during     \
85  *              decryption.                                             \
86  */                                                                     \
87                                                                         \
88 void pre##_cfbgetiv(const pre##_cfbctx *ctx, void *iv)                  \
89 {                                                                       \
90   octet *p = iv;                                                        \
91   int off = ctx->off;                                                   \
92   int rest = PRE##_BLKSZ - off;                                         \
93   memcpy(p, ctx->iv + off, rest);                                       \
94   memcpy(p + rest, ctx->iv, off);                                       \
95 }                                                                       \
96                                                                         \
97 /* --- @pre_cfbsetiv@ --- *                                             \
98  *                                                                      \
99  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
100  *              @cnost void *iv@ = pointer to IV to set                 \
101  *                                                                      \
102  * Returns:     ---                                                     \
103  *                                                                      \
104  * Use:         Sets the IV to use for subsequent encryption.           \
105  */                                                                     \
106                                                                         \
107 void pre##_cfbsetiv(pre##_cfbctx *ctx, const void *iv)                  \
108 {                                                                       \
109   uint32 niv[PRE##_BLKSZ / 4];                                          \
110   BLKC_LOAD(PRE, niv, iv);                                              \
111   pre##_eblk(&ctx->ctx, niv, niv);                                      \
112   BLKC_STORE(PRE, ctx->iv, niv);                                        \
113   ctx->off = 0;                                                         \
114 }                                                                       \
115                                                                         \
116 /* --- @pre_cfbbdry@ --- *                                              \
117  *                                                                      \
118  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
119  *                                                                      \
120  * Returns:     ---                                                     \
121  *                                                                      \
122  * Use:         Inserts a boundary during encryption.  Successful       \
123  *              decryption must place a similar boundary.               \
124  */                                                                     \
125                                                                         \
126 void pre##_cfbbdry(pre##_cfbctx *ctx)                                   \
127 {                                                                       \
128   octet iv[PRE##_BLKSZ];                                                \
129   pre##_cfbgetiv(ctx, iv);                                              \
130   pre##_cfbsetiv(ctx, iv);                                              \
131   BURN(iv);                                                             \
132 }                                                                       \
133                                                                         \
134 /* --- @pre_cfbsetkey@ --- *                                            \
135  *                                                                      \
136  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
137  *              @const pre_ctx *k@ = pointer to cipher context          \
138  *                                                                      \
139  * Returns:     ---                                                     \
140  *                                                                      \
141  * Use:         Sets the CFB context to use a different cipher key.     \
142  */                                                                     \
143                                                                         \
144 void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k)             \
145 {                                                                       \
146   ctx->ctx = *k;                                                        \
147 }                                                                       \
148                                                                         \
149 /* --- @pre_cfbinit@ --- *                                              \
150  *                                                                      \
151  * Arguments:   @pre_cfbctx *ctx@ = pointer to cipher context           \
152  *              @const void *key@ = pointer to the key buffer           \
153  *              @size_t sz@ = size of the key                           \
154  *              @const void *iv@ = pointer to initialization vector     \
155  *                                                                      \
156  * Returns:     ---                                                     \
157  *                                                                      \
158  * Use:         Initializes a CFB context ready for use.  You should    \
159  *              ensure that the IV chosen is unique: reusing an IV will \
160  *              compromise the security of at least the first block     \
161  *              encrypted.  This is equivalent to calls to @pre_init@,  \
162  *              @pre_cfbsetkey@ and @pre_cfbsetiv@.                     \
163  */                                                                     \
164                                                                         \
165 void pre##_cfbinit(pre##_cfbctx *ctx,                                   \
166                      const void *key, size_t sz,                        \
167                      const void *iv)                                    \
168 {                                                                       \
169   static octet zero[PRE##_BLKSZ] = { 0 };                               \
170   pre##_init(&ctx->ctx, key, sz);                                       \
171   pre##_cfbsetiv(ctx, iv ? iv : zero);                                  \
172 }                                                                       \
173                                                                         \
174 /* --- @pre_cfbencrypt@ --- *                                           \
175  *                                                                      \
176  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
177  *              @const void *src@ = pointer to source data              \
178  *              @void *dest@ = pointer to destination data              \
179  *              @size_t sz@ = size of block to be encrypted             \
180  *                                                                      \
181  * Returns:     ---                                                     \
182  *                                                                      \
183  * Use:         Encrypts a block with a block cipher in CFB mode.  The  \
184  *              input block may be arbitrary in size.  CFB mode is not  \
185  *              sensitive to block boundaries.                          \
186  */                                                                     \
187                                                                         \
188 void pre##_cfbencrypt(pre##_cfbctx *ctx,                                \
189                         const void *src, void *dest,                    \
190                         size_t sz)                                      \
191 {                                                                       \
192   const octet *s = src;                                                 \
193   octet *d = dest;                                                      \
194   int off = ctx->off;                                                   \
195                                                                         \
196   /* --- Empty blocks are trivial --- */                                \
197                                                                         \
198   if (!sz)                                                              \
199     return;                                                             \
200                                                                         \
201   /* --- If I can deal with the block from my buffer, do that --- */    \
202                                                                         \
203   if (sz < PRE##_BLKSZ - off)                                           \
204     goto small;                                                         \
205                                                                         \
206   /* --- Finish off what's left in my buffer --- */                     \
207                                                                         \
208   while (off < PRE##_BLKSZ) {                                           \
209     register octet x = *s++;                                            \
210     *d++ = ctx->iv[off++] ^= x;                                         \
211     sz--;                                                               \
212   }                                                                     \
213                                                                         \
214   /* --- Main encryption loop --- */                                    \
215                                                                         \
216   {                                                                     \
217     uint32 iv[PRE##_BLKSZ / 4];                                         \
218     BLKC_LOAD(PRE, iv, ctx->iv);                                        \
219                                                                         \
220     for (;;) {                                                          \
221       pre##_eblk(&ctx->ctx, iv, iv);                                    \
222       if (sz < PRE##_BLKSZ)                                             \
223         break;                                                          \
224       BLKC_XLOAD(PRE, iv, s);                                           \
225       BLKC_STORE(PRE, d, iv);                                           \
226       s += PRE##_BLKSZ;                                                 \
227       d += PRE##_BLKSZ;                                                 \
228       sz -= PRE##_BLKSZ;                                                \
229     }                                                                   \
230     off = 0;                                                            \
231     BLKC_STORE(PRE, ctx->iv, iv);                                       \
232   }                                                                     \
233                                                                         \
234   /* --- Tidying up the tail end --- */                                 \
235                                                                         \
236   if (sz) {                                                             \
237   small:                                                                \
238     do {                                                                \
239       register octet x = *s++;                                          \
240       *d++ = ctx->iv[off++] ^= x;                                       \
241       sz--;                                                             \
242     } while (sz);                                                       \
243   }                                                                     \
244                                                                         \
245   /* --- Done --- */                                                    \
246                                                                         \
247   ctx->off = off;                                                       \
248   return;                                                               \
249 }                                                                       \
250                                                                         \
251 /* --- @pre_cfbencrypt@ --- *                                           \
252  *                                                                      \
253  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
254  *              @const void *src@ = pointer to source data              \
255  *              @void *dest@ = pointer to destination data              \
256  *              @size_t sz@ = size of block to be encrypted             \
257  *                                                                      \
258  * Returns:     ---                                                     \
259  *                                                                      \
260  * Use:         Decrypts a block with a block cipher in CFB mode.  The  \
261  *              input block may be arbitrary in size.  CFB mode is not  \
262  *              sensitive to block boundaries.                          \
263  */                                                                     \
264                                                                         \
265 void pre##_cfbdecrypt(pre##_cfbctx *ctx,                                \
266                         const void *src, void *dest,                    \
267                         size_t sz)                                      \
268 {                                                                       \
269   const octet *s = src;                                                 \
270   octet *d = dest;                                                      \
271   int off = ctx->off;                                                   \
272                                                                         \
273   /* --- Empty blocks are trivial --- */                                \
274                                                                         \
275   if (!sz)                                                              \
276     return;                                                             \
277                                                                         \
278   /* --- If I can deal with the block from my buffer, do that --- */    \
279                                                                         \
280   if (sz < PRE##_BLKSZ - off)                                           \
281     goto small;                                                         \
282                                                                         \
283   /* --- Finish off what's left in my buffer --- */                     \
284                                                                         \
285   while (off < PRE##_BLKSZ) {                                           \
286     register octet x = *s++;                                            \
287     *d++ = ctx->iv[off] ^ x;                                            \
288     ctx->iv[off++] = x;                                                 \
289     sz--;                                                               \
290   }                                                                     \
291                                                                         \
292   /* --- Main encryption loop --- */                                    \
293                                                                         \
294   {                                                                     \
295     uint32 iv[PRE##_BLKSZ / 4];                                         \
296     BLKC_LOAD(PRE, iv, ctx->iv);                                        \
297                                                                         \
298     for (;;) {                                                          \
299       uint32 x[PRE##_BLKSZ / 4];                                        \
300       pre##_eblk(&ctx->ctx, iv, iv);                                    \
301       if (sz < PRE##_BLKSZ)                                             \
302         break;                                                          \
303       BLKC_LOAD(PRE, x, s);                                             \
304       BLKC_XSTORE(PRE, d, iv, x);                                       \
305       BLKC_MOVE(PRE, iv, x);                                            \
306       s += PRE##_BLKSZ;                                                 \
307       d += PRE##_BLKSZ;                                                 \
308       sz -= PRE##_BLKSZ;                                                \
309     }                                                                   \
310     off = 0;                                                            \
311     BLKC_STORE(PRE, ctx->iv, iv);                                       \
312   }                                                                     \
313                                                                         \
314   /* --- Tidying up the tail end --- */                                 \
315                                                                         \
316   if (sz) {                                                             \
317   small:                                                                \
318     do {                                                                \
319       register octet x = *s++;                                          \
320       *d++ = ctx->iv[off] ^ x;                                          \
321       ctx->iv[off++] = x;                                               \
322       sz--;                                                             \
323     } while (sz);                                                       \
324   }                                                                     \
325                                                                         \
326   /* --- Done --- */                                                    \
327                                                                         \
328   ctx->off = off;                                                       \
329   return;                                                               \
330 }                                                                       \
331                                                                         \
332 /* --- Generic cipher interface --- */                                  \
333                                                                         \
334 static const gcipher_ops gops;                                          \
335                                                                         \
336 typedef struct gctx {                                                   \
337   gcipher c;                                                            \
338   pre##_cfbctx k;                                                       \
339 } gctx;                                                                 \
340                                                                         \
341 static gcipher *ginit(const void *k, size_t sz)                         \
342 {                                                                       \
343   gctx *g = CREATE(gctx);                                               \
344   g->c.ops = &gops;                                                     \
345   pre##_cfbinit(&g->k, k, sz, 0);                                       \
346   return (&g->c);                                                       \
347 }                                                                       \
348                                                                         \
349 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
350 {                                                                       \
351   gctx *g = (gctx *)c;                                                  \
352   pre##_cfbencrypt(&g->k, s, t, sz);                                    \
353 }                                                                       \
354                                                                         \
355 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)     \
356 {                                                                       \
357   gctx *g = (gctx *)c;                                                  \
358   pre##_cfbdecrypt(&g->k, s, t, sz);                                    \
359 }                                                                       \
360                                                                         \
361 static void gdestroy(gcipher *c)                                        \
362 {                                                                       \
363   gctx *g = (gctx *)c;                                                  \
364   DESTROY(g);                                                           \
365 }                                                                       \
366                                                                         \
367 static void gsetiv(gcipher *c, const void *iv)                          \
368 {                                                                       \
369   gctx *g = (gctx *)c;                                                  \
370   pre##_cfbsetiv(&g->k, iv);                                            \
371 }                                                                       \
372                                                                         \
373 static void gbdry(gcipher *c)                                           \
374 {                                                                       \
375   gctx *g = (gctx *)c;                                                  \
376   pre##_cfbbdry(&g->k);                                                 \
377 }                                                                       \
378                                                                         \
379 static const gcipher_ops gops = {                                       \
380   &pre##_cfb.b,                                                         \
381    gencrypt, gdecrypt, gdestroy, gsetiv, gbdry                          \
382 };                                                                      \
383                                                                         \
384 const gccipher pre##_cfb = {                                            \
385   { #pre "-cfb", PRE##_KEYSZ, PRE##_BLKSZ },                            \
386   ginit                                                                 \
387 };                                                                      \
388                                                                         \
389 CFB_TEST(PRE, pre)
390
391 /*----- Test rig ----------------------------------------------------------*/
392
393 #ifdef TEST_RIG
394
395 #include <stdio.h>
396
397 #include "daftstory.h"
398
399 /* --- @CFB_TEST@ --- *
400  *
401  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
402  *
403  * Use:         Standard test rig for CFB functions.
404  */
405
406 #define CFB_TEST(PRE, pre)                                              \
407                                                                         \
408 /* --- Initial plaintext for the test --- */                            \
409                                                                         \
410 static const octet text[] = TEXT;                                       \
411                                                                         \
412 /* --- Key and IV to use --- */                                         \
413                                                                         \
414 static const octet key[] = KEY;                                         \
415 static const octet iv[] = IV;                                           \
416                                                                         \
417 /* --- Buffers for encryption and decryption output --- */              \
418                                                                         \
419 static octet ct[sizeof(text)];                                          \
420 static octet pt[sizeof(text)];                                          \
421                                                                         \
422 static void hexdump(const octet *p, size_t sz)                          \
423 {                                                                       \
424   const octet *q = p + sz;                                              \
425   for (sz = 0; p < q; p++, sz++) {                                      \
426     printf("%02x", *p);                                                 \
427     if ((sz + 1) % PRE##_BLKSZ == 0)                                    \
428       putchar(':');                                                     \
429   }                                                                     \
430 }                                                                       \
431                                                                         \
432 int main(void)                                                          \
433 {                                                                       \
434   size_t sz = 0, rest;                                                  \
435   pre##_cfbctx ctx;                                                     \
436   int status = 0;                                                       \
437   int done = 0;                                                         \
438   pre##_ctx k;                                                          \
439                                                                         \
440   size_t keysz = PRE##_KEYSZ ?                                          \
441     PRE##_KEYSZ : strlen((const char *)key);                            \
442                                                                         \
443   fputs(#pre "-cfb: ", stdout);                                         \
444                                                                         \
445   pre##_init(&k, key, keysz);                                           \
446   pre##_cfbsetkey(&ctx, &k);                                            \
447                                                                         \
448   while (sz <= sizeof(text)) {                                          \
449     rest = sizeof(text) - sz;                                           \
450     memcpy(ct, text, sizeof(text));                                     \
451     pre##_cfbsetiv(&ctx, iv);                                           \
452     pre##_cfbencrypt(&ctx, ct, ct, sz);                                 \
453     pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest);                     \
454     memcpy(pt, ct, sizeof(text));                                       \
455     pre##_cfbsetiv(&ctx, iv);                                           \
456     pre##_cfbdecrypt(&ctx, pt, pt, rest);                               \
457     pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz);                   \
458     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
459       done++;                                                           \
460       if (sizeof(text) < 40 || done % 8 == 0)                           \
461         fputc('.', stdout);                                             \
462       if (done % 480 == 0)                                              \
463         fputs("\n\t", stdout);                                          \
464       fflush(stdout);                                                   \
465     } else {                                                            \
466       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
467       status = 1;                                                       \
468       printf("\tplaintext      = "); hexdump(text, sz);                 \
469         printf(", "); hexdump(text + sz, rest);                         \
470         fputc('\n', stdout);                                            \
471       printf("\tciphertext     = "); hexdump(ct, sz);                   \
472         printf(", "); hexdump(ct + sz, rest);                           \
473         fputc('\n', stdout);                                            \
474       printf("\trecovered text = "); hexdump(pt, sz);                   \
475         printf(", "); hexdump(pt + sz, rest);                           \
476         fputc('\n', stdout);                                            \
477       fputc('\n', stdout);                                              \
478     }                                                                   \
479     if (sz < 63)                                                        \
480       sz++;                                                             \
481     else                                                                \
482       sz += 9;                                                          \
483   }                                                                     \
484                                                                         \
485   fputs(status ? " failed\n" : " ok\n", stdout);                        \
486   return (status);                                                      \
487 }
488
489 #else
490 #  define CFB_TEST(PRE, pre)
491 #endif
492
493 /*----- That's all, folks -------------------------------------------------*/
494
495 #ifdef __cplusplus
496   }
497 #endif
498
499 #endif