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