chiark / gitweb /
Expunge revision histories in files.
[catacomb] / cfb-def.h
1 /* -*-c-*-
2  *
3  * $Id: cfb-def.h,v 1.5 2004/04/08 01:36:15 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 #ifndef CATACOMB_CFB_DEF_H
31 #define CATACOMB_CFB_DEF_H
32
33 #ifdef __cplusplus
34   extern "C" {
35 #endif
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include <string.h>
40
41 #include <mLib/bits.h>
42 #include <mLib/sub.h>
43
44 #ifndef CATACOMB_ARENA_H
45 #  include "arena.h"
46 #endif
47
48 #ifndef CATACOMB_BLKC_H
49 #  include "blkc.h"
50 #endif
51
52 #ifndef CATACOMB_GCIPHER_H
53 #  include "gcipher.h"
54 #endif
55
56 #ifndef CATACOMB_PARANOIA_H
57 #  include "paranoia.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   unsigned off = ctx->off;                                              \
92   unsigned 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   memcpy(ctx->iv, iv, PRE##_BLKSZ);                                     \
110   ctx->off = PRE##_BLKSZ;                                               \
111 }                                                                       \
112                                                                         \
113 /* --- @pre_cfbbdry@ --- *                                              \
114  *                                                                      \
115  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
116  *                                                                      \
117  * Returns:     ---                                                     \
118  *                                                                      \
119  * Use:         Inserts a boundary during encryption.  Successful       \
120  *              decryption must place a similar boundary.               \
121  */                                                                     \
122                                                                         \
123 void pre##_cfbbdry(pre##_cfbctx *ctx)                                   \
124 {                                                                       \
125   uint32 niv[PRE##_BLKSZ / 4];                                          \
126   BLKC_LOAD(PRE, niv, ctx->iv);                                         \
127   pre##_eblk(&ctx->ctx, niv, niv);                                      \
128   BLKC_STORE(PRE, ctx->iv, niv);                                        \
129   ctx->off = PRE##_BLKSZ;                                               \
130   BURN(niv);                                                            \
131 }                                                                       \
132                                                                         \
133 /* --- @pre_cfbsetkey@ --- *                                            \
134  *                                                                      \
135  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
136  *              @const pre_ctx *k@ = pointer to cipher context          \
137  *                                                                      \
138  * Returns:     ---                                                     \
139  *                                                                      \
140  * Use:         Sets the CFB context to use a different cipher key.     \
141  */                                                                     \
142                                                                         \
143 void pre##_cfbsetkey(pre##_cfbctx *ctx, const pre##_ctx *k)             \
144 {                                                                       \
145   ctx->ctx = *k;                                                        \
146   ctx->off = PRE##_BLKSZ;                                               \
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 const 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   unsigned 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_cfbdecrypt@ --- *                                           \
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   unsigned 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 = S_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   BURN(*g);                                                             \
365   S_DESTROY(g);                                                         \
366 }                                                                       \
367                                                                         \
368 static void gsetiv(gcipher *c, const void *iv)                          \
369 {                                                                       \
370   gctx *g = (gctx *)c;                                                  \
371   pre##_cfbsetiv(&g->k, iv);                                            \
372 }                                                                       \
373                                                                         \
374 static void gbdry(gcipher *c)                                           \
375 {                                                                       \
376   gctx *g = (gctx *)c;                                                  \
377   pre##_cfbbdry(&g->k);                                                 \
378 }                                                                       \
379                                                                         \
380 static const gcipher_ops gops = {                                       \
381   &pre##_cfb,                                                           \
382   gencrypt, gdecrypt, gdestroy, gsetiv, gbdry                           \
383 };                                                                      \
384                                                                         \
385 const gccipher pre##_cfb = {                                            \
386   #pre "-cfb", pre##_keysz, PRE##_BLKSZ,                                \
387   ginit                                                                 \
388 };                                                                      \
389                                                                         \
390 CFB_TEST(PRE, pre)
391
392 /*----- Test rig ----------------------------------------------------------*/
393
394 #ifdef TEST_RIG
395
396 #include <stdio.h>
397
398 #include "daftstory.h"
399
400 /* --- @CFB_TEST@ --- *
401  *
402  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
403  *
404  * Use:         Standard test rig for CFB functions.
405  */
406
407 #define CFB_TEST(PRE, pre)                                              \
408                                                                         \
409 /* --- Initial plaintext for the test --- */                            \
410                                                                         \
411 static const octet text[] = TEXT;                                       \
412                                                                         \
413 /* --- Key and IV to use --- */                                         \
414                                                                         \
415 static const octet key[] = KEY;                                         \
416 static const octet iv[] = IV;                                           \
417                                                                         \
418 /* --- Buffers for encryption and decryption output --- */              \
419                                                                         \
420 static octet ct[sizeof(text)];                                          \
421 static octet pt[sizeof(text)];                                          \
422                                                                         \
423 static void hexdump(const octet *p, size_t sz)                          \
424 {                                                                       \
425   const octet *q = p + sz;                                              \
426   for (sz = 0; p < q; p++, sz++) {                                      \
427     printf("%02x", *p);                                                 \
428     if ((sz + 1) % PRE##_BLKSZ == 0)                                    \
429       putchar(':');                                                     \
430   }                                                                     \
431 }                                                                       \
432                                                                         \
433 int main(void)                                                          \
434 {                                                                       \
435   size_t sz = 0, rest;                                                  \
436   pre##_cfbctx ctx;                                                     \
437   int status = 0;                                                       \
438   int done = 0;                                                         \
439   pre##_ctx k;                                                          \
440                                                                         \
441   size_t keysz = PRE##_KEYSZ ?                                          \
442     PRE##_KEYSZ : strlen((const char *)key);                            \
443                                                                         \
444   fputs(#pre "-cfb: ", stdout);                                         \
445                                                                         \
446   pre##_init(&k, key, keysz);                                           \
447   pre##_cfbsetkey(&ctx, &k);                                            \
448                                                                         \
449   while (sz <= sizeof(text)) {                                          \
450     rest = sizeof(text) - sz;                                           \
451     memcpy(ct, text, sizeof(text));                                     \
452     pre##_cfbsetiv(&ctx, iv);                                           \
453     pre##_cfbencrypt(&ctx, ct, ct, sz);                                 \
454     pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest);                     \
455     memcpy(pt, ct, sizeof(text));                                       \
456     pre##_cfbsetiv(&ctx, iv);                                           \
457     pre##_cfbdecrypt(&ctx, pt, pt, rest);                               \
458     pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz);                   \
459     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
460       done++;                                                           \
461       if (sizeof(text) < 40 || done % 8 == 0)                           \
462         fputc('.', stdout);                                             \
463       if (done % 480 == 0)                                              \
464         fputs("\n\t", stdout);                                          \
465       fflush(stdout);                                                   \
466     } else {                                                            \
467       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
468       status = 1;                                                       \
469       printf("\tplaintext      = "); hexdump(text, sz);                 \
470         printf(", "); hexdump(text + sz, rest);                         \
471         fputc('\n', stdout);                                            \
472       printf("\tciphertext     = "); hexdump(ct, sz);                   \
473         printf(", "); hexdump(ct + sz, rest);                           \
474         fputc('\n', stdout);                                            \
475       printf("\trecovered text = "); hexdump(pt, sz);                   \
476         printf(", "); hexdump(pt + sz, rest);                           \
477         fputc('\n', stdout);                                            \
478       fputc('\n', stdout);                                              \
479     }                                                                   \
480     if (sz < 63)                                                        \
481       sz++;                                                             \
482     else                                                                \
483       sz += 9;                                                          \
484   }                                                                     \
485                                                                         \
486   fputs(status ? " failed\n" : " ok\n", stdout);                        \
487   return (status);                                                      \
488 }
489
490 #else
491 #  define CFB_TEST(PRE, pre)
492 #endif
493
494 /*----- That's all, folks -------------------------------------------------*/
495
496 #ifdef __cplusplus
497   }
498 #endif
499
500 #endif