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