chiark / gitweb /
debian/control: Don't require `valgrind' on `armel'.
[catacomb] / symm / cfb-def.h
1 /* -*-c-*-
2  *
3  * Definitions for ciphertext feedback mode
4  *
5  * (c) 1999 Straylight/Edgeware
6  */
7
8 /*----- Licensing notice --------------------------------------------------*
9  *
10  * This file is part of Catacomb.
11  *
12  * Catacomb is free software; you can redistribute it and/or modify
13  * it under the terms of the GNU Library General Public License as
14  * published by the Free Software Foundation; either version 2 of the
15  * License, or (at your option) any later version.
16  *
17  * Catacomb is distributed in the hope that it will be useful,
18  * but WITHOUT ANY WARRANTY; without even the implied warranty of
19  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
20  * GNU Library General Public License for more details.
21  *
22  * You should have received a copy of the GNU Library General Public
23  * License along with Catacomb; if not, write to the Free
24  * Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
25  * MA 02111-1307, USA.
26  */
27
28 #ifndef CATACOMB_CFB_DEF_H
29 #define CATACOMB_CFB_DEF_H
30
31 #ifdef __cplusplus
32   extern "C" {
33 #endif
34
35 /*----- Header files ------------------------------------------------------*/
36
37 #include <string.h>
38
39 #include <mLib/bits.h>
40 #include <mLib/sub.h>
41
42 #ifndef CATACOMB_ARENA_H
43 #  include "arena.h"
44 #endif
45
46 #ifndef CATACOMB_BLKC_H
47 #  include "blkc.h"
48 #endif
49
50 #ifndef CATACOMB_GCIPHER_H
51 #  include "gcipher.h"
52 #endif
53
54 #ifndef CATACOMB_PARANOIA_H
55 #  include "paranoia.h"
56 #endif
57
58 #ifndef CATACOMB_PARANOIA_H
59 #  include "paranoia.h"
60 #endif
61
62 /*----- Macros ------------------------------------------------------------*/
63
64 /* --- @CFB_DEF@ --- *
65  *
66  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
67  *
68  * Use:         Creates an implementation for CFB mode.
69  */
70
71 #define CFB_DEF(PRE, pre) CFB_DEFX(PRE, pre, #pre, #pre)
72
73 #define CFB_DEFX(PRE, pre, name, fname)                                 \
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     ctx->iv[off] ^= x;                                                  \
211     if (d) *d++ = ctx->iv[off];                                         \
212     off++;                                                              \
213     sz--;                                                               \
214   }                                                                     \
215                                                                         \
216   /* --- Main encryption loop --- */                                    \
217                                                                         \
218   {                                                                     \
219     uint32 iv[PRE##_BLKSZ / 4];                                         \
220     BLKC_LOAD(PRE, iv, ctx->iv);                                        \
221                                                                         \
222     for (;;) {                                                          \
223       pre##_eblk(&ctx->ctx, iv, iv);                                    \
224       if (sz < PRE##_BLKSZ)                                             \
225         break;                                                          \
226       if (s) {                                                          \
227         BLKC_XLOAD(PRE, iv, s);                                         \
228         s += PRE##_BLKSZ;                                               \
229       }                                                                 \
230       if (d) {                                                          \
231         BLKC_STORE(PRE, d, iv);                                         \
232         d += PRE##_BLKSZ;                                               \
233       }                                                                 \
234       sz -= PRE##_BLKSZ;                                                \
235     }                                                                   \
236     off = 0;                                                            \
237     BLKC_STORE(PRE, ctx->iv, iv);                                       \
238   }                                                                     \
239                                                                         \
240   /* --- Tidying up the tail end --- */                                 \
241                                                                         \
242   if (sz) {                                                             \
243   small:                                                                \
244     do {                                                                \
245       register octet x = *s++;                                          \
246       ctx->iv[off] ^= x;                                                \
247       if (d) *d++ = ctx->iv[off];                                       \
248       off++;                                                            \
249       sz--;                                                             \
250     } while (sz);                                                       \
251   }                                                                     \
252                                                                         \
253   /* --- Done --- */                                                    \
254                                                                         \
255   ctx->off = off;                                                       \
256   return;                                                               \
257 }                                                                       \
258                                                                         \
259 /* --- @pre_cfbdecrypt@ --- *                                           \
260  *                                                                      \
261  * Arguments:   @pre_cfbctx *ctx@ = pointer to CFB context block        \
262  *              @const void *src@ = pointer to source data              \
263  *              @void *dest@ = pointer to destination data              \
264  *              @size_t sz@ = size of block to be encrypted             \
265  *                                                                      \
266  * Returns:     ---                                                     \
267  *                                                                      \
268  * Use:         Decrypts a block with a block cipher in CFB mode.  The  \
269  *              input block may be arbitrary in size.  CFB mode is not  \
270  *              sensitive to block boundaries.                          \
271  */                                                                     \
272                                                                         \
273 void pre##_cfbdecrypt(pre##_cfbctx *ctx,                                \
274                         const void *src, void *dest,                    \
275                         size_t sz)                                      \
276 {                                                                       \
277   const octet *s = src;                                                 \
278   octet *d = dest;                                                      \
279   unsigned off = ctx->off;                                              \
280                                                                         \
281   /* --- Empty blocks are trivial --- */                                \
282                                                                         \
283   if (!sz)                                                              \
284     return;                                                             \
285                                                                         \
286   /* --- If I can deal with the block from my buffer, do that --- */    \
287                                                                         \
288   if (sz < PRE##_BLKSZ - off)                                           \
289     goto small;                                                         \
290                                                                         \
291   /* --- Finish off what's left in my buffer --- */                     \
292                                                                         \
293   while (off < PRE##_BLKSZ) {                                           \
294     register octet x = *s++;                                            \
295     *d++ = ctx->iv[off] ^ x;                                            \
296     ctx->iv[off++] = x;                                                 \
297     sz--;                                                               \
298   }                                                                     \
299                                                                         \
300   /* --- Main encryption loop --- */                                    \
301                                                                         \
302   {                                                                     \
303     uint32 iv[PRE##_BLKSZ / 4];                                         \
304     BLKC_LOAD(PRE, iv, ctx->iv);                                        \
305                                                                         \
306     for (;;) {                                                          \
307       uint32 x[PRE##_BLKSZ / 4];                                        \
308       pre##_eblk(&ctx->ctx, iv, iv);                                    \
309       if (sz < PRE##_BLKSZ)                                             \
310         break;                                                          \
311       BLKC_LOAD(PRE, x, s);                                             \
312       BLKC_XSTORE(PRE, d, iv, x);                                       \
313       BLKC_MOVE(PRE, iv, x);                                            \
314       s += PRE##_BLKSZ;                                                 \
315       d += PRE##_BLKSZ;                                                 \
316       sz -= PRE##_BLKSZ;                                                \
317     }                                                                   \
318     off = 0;                                                            \
319     BLKC_STORE(PRE, ctx->iv, iv);                                       \
320   }                                                                     \
321                                                                         \
322   /* --- Tidying up the tail end --- */                                 \
323                                                                         \
324   if (sz) {                                                             \
325   small:                                                                \
326     do {                                                                \
327       register octet x = *s++;                                          \
328       *d++ = ctx->iv[off] ^ x;                                          \
329       ctx->iv[off++] = x;                                               \
330       sz--;                                                             \
331     } while (sz);                                                       \
332   }                                                                     \
333                                                                         \
334   /* --- Done --- */                                                    \
335                                                                         \
336   ctx->off = off;                                                       \
337   return;                                                               \
338 }                                                                       \
339                                                                         \
340 /* --- Generic cipher interface --- */                                  \
341                                                                         \
342 static const gcipher_ops gops;                                          \
343                                                                         \
344 typedef struct gctx {                                                   \
345   gcipher c;                                                            \
346   pre##_cfbctx k;                                                       \
347 } gctx;                                                                 \
348                                                                         \
349 static gcipher *ginit(const void *k, size_t sz)                         \
350 {                                                                       \
351   gctx *g = S_CREATE(gctx);                                             \
352   g->c.ops = &gops;                                                     \
353   pre##_cfbinit(&g->k, k, sz, 0);                                       \
354   return (&g->c);                                                       \
355 }                                                                       \
356                                                                         \
357 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
358 {                                                                       \
359   gctx *g = (gctx *)c;                                                  \
360   pre##_cfbencrypt(&g->k, s, t, sz);                                    \
361 }                                                                       \
362                                                                         \
363 static void gdecrypt(gcipher *c, const void *s, void *t, size_t sz)     \
364 {                                                                       \
365   gctx *g = (gctx *)c;                                                  \
366   pre##_cfbdecrypt(&g->k, s, t, sz);                                    \
367 }                                                                       \
368                                                                         \
369 static void gdestroy(gcipher *c)                                        \
370 {                                                                       \
371   gctx *g = (gctx *)c;                                                  \
372   BURN(*g);                                                             \
373   S_DESTROY(g);                                                         \
374 }                                                                       \
375                                                                         \
376 static void gsetiv(gcipher *c, const void *iv)                          \
377 {                                                                       \
378   gctx *g = (gctx *)c;                                                  \
379   pre##_cfbsetiv(&g->k, iv);                                            \
380 }                                                                       \
381                                                                         \
382 static void gbdry(gcipher *c)                                           \
383 {                                                                       \
384   gctx *g = (gctx *)c;                                                  \
385   pre##_cfbbdry(&g->k);                                                 \
386 }                                                                       \
387                                                                         \
388 static const gcipher_ops gops = {                                       \
389   &pre##_cfb,                                                           \
390   gencrypt, gdecrypt, gdestroy, gsetiv, gbdry                           \
391 };                                                                      \
392                                                                         \
393 const gccipher pre##_cfb = {                                            \
394   name "-cfb", pre##_keysz, PRE##_BLKSZ,                                \
395   ginit                                                                 \
396 };                                                                      \
397                                                                         \
398 CFB_TESTX(PRE, pre, name, fname)
399
400 /*----- Test rig ----------------------------------------------------------*/
401
402 #define CFB_TEST(PRE, pre) CFB_TESTX(PRE, pre, #pre, #pre)
403
404 #ifdef TEST_RIG
405
406 #include <stdio.h>
407
408 #include "daftstory.h"
409
410 /* --- @CFB_TEST@ --- *
411  *
412  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
413  *
414  * Use:         Standard test rig for CFB functions.
415  */
416
417 #define CFB_TESTX(PRE, pre, name, fname)                                \
418                                                                         \
419 /* --- Initial plaintext for the test --- */                            \
420                                                                         \
421 static const octet text[] = TEXT;                                       \
422                                                                         \
423 /* --- Key and IV to use --- */                                         \
424                                                                         \
425 static const octet key[] = KEY;                                         \
426 static const octet iv[] = IV;                                           \
427                                                                         \
428 /* --- Buffers for encryption and decryption output --- */              \
429                                                                         \
430 static octet ct[sizeof(text)];                                          \
431 static octet pt[sizeof(text)];                                          \
432                                                                         \
433 static void hexdump(const octet *p, size_t sz, size_t off)              \
434 {                                                                       \
435   const octet *q = p + sz;                                              \
436   for (sz = 0; p < q; p++, sz++) {                                      \
437     printf("%02x", *p);                                                 \
438     if ((off + sz + 1) % PRE##_BLKSZ == 0)                              \
439       putchar(':');                                                     \
440   }                                                                     \
441 }                                                                       \
442                                                                         \
443 int main(void)                                                          \
444 {                                                                       \
445   size_t sz = 0, rest;                                                  \
446   pre##_cfbctx ctx;                                                     \
447   int status = 0;                                                       \
448   int done = 0;                                                         \
449   pre##_ctx k;                                                          \
450                                                                         \
451   size_t keysz = PRE##_KEYSZ ?                                          \
452     PRE##_KEYSZ : strlen((const char *)key);                            \
453                                                                         \
454   fputs(name "-cfb: ", stdout);                                         \
455                                                                         \
456   pre##_init(&k, key, keysz);                                           \
457   pre##_cfbsetkey(&ctx, &k);                                            \
458                                                                         \
459   while (sz <= sizeof(text)) {                                          \
460     rest = sizeof(text) - sz;                                           \
461     memcpy(ct, text, sizeof(text));                                     \
462     pre##_cfbsetiv(&ctx, iv);                                           \
463     pre##_cfbencrypt(&ctx, ct, ct, sz);                                 \
464     pre##_cfbencrypt(&ctx, ct + sz, ct + sz, rest);                     \
465     memcpy(pt, ct, sizeof(text));                                       \
466     pre##_cfbsetiv(&ctx, iv);                                           \
467     pre##_cfbdecrypt(&ctx, pt, pt, rest);                               \
468     pre##_cfbdecrypt(&ctx, pt + rest, pt + rest, sz);                   \
469     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
470       done++;                                                           \
471       if (sizeof(text) < 40 || done % 8 == 0)                           \
472         fputc('.', stdout);                                             \
473       if (done % 480 == 0)                                              \
474         fputs("\n\t", stdout);                                          \
475       fflush(stdout);                                                   \
476     } else {                                                            \
477       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
478       status = 1;                                                       \
479       printf("\tplaintext      = "); hexdump(text, sz, 0);              \
480         printf(", "); hexdump(text + sz, rest, sz);                     \
481         fputc('\n', stdout);                                            \
482       printf("\tciphertext     = "); hexdump(ct, sz, 0);                \
483         printf(", "); hexdump(ct + sz, rest, sz);                       \
484         fputc('\n', stdout);                                            \
485       printf("\trecovered text = "); hexdump(pt, sz, 0);                \
486         printf(", "); hexdump(pt + sz, rest, sz);                       \
487         fputc('\n', stdout);                                            \
488       fputc('\n', stdout);                                              \
489     }                                                                   \
490     if (sz < 63)                                                        \
491       sz++;                                                             \
492     else                                                                \
493       sz += 9;                                                          \
494   }                                                                     \
495                                                                         \
496   fputs(status ? " failed\n" : " ok\n", stdout);                        \
497   return (status);                                                      \
498 }
499
500 #else
501 #  define CFB_TESTX(PRE, pre, name, fname)
502 #endif
503
504 /*----- That's all, folks -------------------------------------------------*/
505
506 #ifdef __cplusplus
507   }
508 #endif
509
510 #endif