chiark / gitweb /
82503959b4e70ae2cf460b7a0a70f646c4a6a3cc
[catacomb] / ofb-def.h
1 /* -*-c-*-
2  *
3  * $Id: ofb-def.h,v 1.7 2004/04/08 01:36:15 mdw Exp $
4  *
5  * Definitions for output 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_OFB_DEF_H
31 #define CATACOMB_OFB_DEF_H
32
33 #ifdef __cplusplus
34   extern "C" {
35 #endif
36
37 /*----- Header files ------------------------------------------------------*/
38
39 #include <stdarg.h>
40 #include <string.h>
41
42 #include <mLib/bits.h>
43 #include <mLib/sub.h>
44
45 #ifndef CATACOMB_ARENA_H
46 #  include "arena.h"
47 #endif
48
49 #ifndef CATACOMB_BLKC_H
50 #  include "blkc.h"
51 #endif
52
53 #ifndef CATACOMB_GCIPHER_H
54 #  include "gcipher.h"
55 #endif
56
57 #ifndef CATACOMB_PARANOIA_H
58 #  include "paranoia.h"
59 #endif
60
61 /*----- Macros ------------------------------------------------------------*/
62
63 /* --- @OFB_DEF@ --- *
64  *
65  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
66  *
67  * Use:         Creates definitions for output feedback mode.
68  */
69
70 #define OFB_DEF(PRE, pre)                                               \
71                                                                         \
72 /* --- @pre_ofbgetiv@ --- *                                             \
73  *                                                                      \
74  * Arguments:   @const pre_ofbctx *ctx@ = pointer to OFB context block  \
75  *              @void *iv@ = pointer to output data block               \
76  *                                                                      \
77  * Returns:     ---                                                     \
78  *                                                                      \
79  * Use:         Reads the currently set IV.  Reading and setting an IV  \
80  *              is not transparent to the cipher.  It will add a `step' \
81  *              which must be matched by a similar operation during     \
82  *              decryption.                                             \
83  */                                                                     \
84                                                                         \
85 void pre##_ofbgetiv(const pre##_ofbctx *ctx, void *iv)                  \
86 {                                                                       \
87   octet *p = iv;                                                        \
88   unsigned off = ctx->off;                                              \
89   unsigned rest = PRE##_BLKSZ - off;                                    \
90   memcpy(p, ctx->iv + off, rest);                                       \
91   memcpy(p + rest, ctx->iv, off);                                       \
92 }                                                                       \
93                                                                         \
94 /* --- @pre_ofbsetiv@ --- *                                             \
95  *                                                                      \
96  * Arguments:   @pre_ofbctx *ctx@ = pointer to OFB context block        \
97  *              @cnost void *iv@ = pointer to IV to set                 \
98  *                                                                      \
99  * Returns:     ---                                                     \
100  *                                                                      \
101  * Use:         Sets the IV to use for subsequent encryption.           \
102  */                                                                     \
103                                                                         \
104 void pre##_ofbsetiv(pre##_ofbctx *ctx, const void *iv)                  \
105 {                                                                       \
106   memcpy(ctx->iv, iv, PRE##_BLKSZ);                                     \
107   ctx->off = PRE##_BLKSZ;                                               \
108 }                                                                       \
109                                                                         \
110 /* --- @pre_ofbbdry@ --- *                                              \
111  *                                                                      \
112  * Arguments:   @pre_ofbctx *ctx@ = pointer to OFB context block        \
113  *                                                                      \
114  * Returns:     ---                                                     \
115  *                                                                      \
116  * Use:         Inserts a boundary during encryption.  Successful       \
117  *              decryption must place a similar boundary.               \
118  */                                                                     \
119                                                                         \
120 void pre##_ofbbdry(pre##_ofbctx *ctx)                                   \
121 {                                                                       \
122   uint32 niv[PRE##_BLKSZ / 4];                                          \
123   BLKC_LOAD(PRE, niv, ctx->iv);                                         \
124   pre##_eblk(&ctx->ctx, niv, niv);                                      \
125   BLKC_STORE(PRE, ctx->iv, niv);                                        \
126   ctx->off = PRE##_BLKSZ;                                               \
127   BURN(niv);                                                            \
128 }                                                                       \
129                                                                         \
130 /* --- @pre_ofbsetkey@ --- *                                            \
131  *                                                                      \
132  * Arguments:   @pre_ofbctx *ctx@ = pointer to OFB context block        \
133  *              @const pre_ctx *k@ = pointer to cipher context          \
134  *                                                                      \
135  * Returns:     ---                                                     \
136  *                                                                      \
137  * Use:         Sets the OFB context to use a different cipher key.     \
138  */                                                                     \
139                                                                         \
140 void pre##_ofbsetkey(pre##_ofbctx *ctx, const pre##_ctx *k)             \
141 {                                                                       \
142   ctx->ctx = *k;                                                        \
143 }                                                                       \
144                                                                         \
145 /* --- @pre_ofbinit@ --- *                                              \
146  *                                                                      \
147  * Arguments:   @pre_ofbctx *ctx@ = pointer to cipher context           \
148  *              @const void *key@ = pointer to the key buffer           \
149  *              @size_t sz@ = size of the key                           \
150  *              @const void *iv@ = pointer to initialization vector     \
151  *                                                                      \
152  * Returns:     ---                                                     \
153  *                                                                      \
154  * Use:         Initializes a OFB context ready for use.  You should    \
155  *              ensure that the IV chosen is unique: reusing an IV will \
156  *              compromise the security of the entire plaintext.  This  \
157  *              is equivalent to calls to @pre_init@, @pre_ofbsetkey@   \
158  *              and @pre_ofbsetiv@.                                     \
159  */                                                                     \
160                                                                         \
161 void pre##_ofbinit(pre##_ofbctx *ctx,                                   \
162                      const void *key, size_t sz,                        \
163                      const void *iv)                                    \
164 {                                                                       \
165   static const octet zero[PRE##_BLKSZ] = { 0 };                         \
166   pre##_init(&ctx->ctx, key, sz);                                       \
167   pre##_ofbsetiv(ctx, iv ? iv : zero);                                  \
168 }                                                                       \
169                                                                         \
170 /* --- @pre_ofbencrypt@ --- *                                           \
171  *                                                                      \
172  * Arguments:   @pre_ofbctx *ctx@ = pointer to OFB context block        \
173  *              @const void *src@ = pointer to source data              \
174  *              @void *dest@ = pointer to destination data              \
175  *              @size_t sz@ = size of block to be encrypted             \
176  *                                                                      \
177  * Returns:     ---                                                     \
178  *                                                                      \
179  * Use:         Encrypts or decrypts a block with a block cipher in OFB \
180  *              mode: encryption and decryption are the same in OFB.    \
181  *              The destination may be null to just churn the feedback  \
182  *              round for a bit.  The source may be null to use the     \
183  *              cipher as a random data generator.                      \
184  */                                                                     \
185                                                                         \
186 void pre##_ofbencrypt(pre##_ofbctx *ctx,                                \
187                         const void *src, void *dest,                    \
188                         size_t sz)                                      \
189 {                                                                       \
190   const octet *s = src;                                                 \
191   octet *d = dest;                                                      \
192   unsigned off = ctx->off;                                              \
193                                                                         \
194   /* --- Empty blocks are trivial --- */                                \
195                                                                         \
196   if (!sz)                                                              \
197     return;                                                             \
198                                                                         \
199   /* --- If I can deal with the block from my buffer, do that --- */    \
200                                                                         \
201   if (sz < PRE##_BLKSZ - off)                                           \
202     goto small;                                                         \
203                                                                         \
204   /* --- Finish off what's left in my buffer --- */                     \
205                                                                         \
206   if (!d)                                                               \
207     sz -= PRE##_BLKSZ - off;                                            \
208   else {                                                                \
209     while (off < PRE##_BLKSZ) {                                         \
210       register octet x = s ? *s++ : 0;                                  \
211       *d++ = ctx->iv[off++] ^ x;                                        \
212       sz--;                                                             \
213     }                                                                   \
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 (d) {                                                          \
227         if (!s)                                                         \
228           BLKC_STORE(PRE, d, iv);                                       \
229         else {                                                          \
230           uint32 x[PRE##_BLKSZ / 4];                                    \
231           BLKC_LOAD(PRE, x, s);                                         \
232           BLKC_XSTORE(PRE, d, iv, x);                                   \
233           s += PRE##_BLKSZ;                                             \
234         }                                                               \
235         d += PRE##_BLKSZ;                                               \
236       }                                                                 \
237       sz -= PRE##_BLKSZ;                                                \
238     }                                                                   \
239                                                                         \
240     BLKC_STORE(PRE, ctx->iv, iv);                                       \
241     off = 0;                                                            \
242   }                                                                     \
243                                                                         \
244   /* --- Tidying up the tail end --- */                                 \
245                                                                         \
246   if (sz) {                                                             \
247   small:                                                                \
248     if (!d)                                                             \
249       off += sz;                                                        \
250     else do {                                                           \
251       register octet x = s ? *s++ : 0;                                  \
252       *d++ = ctx->iv[off++] ^ x;                                        \
253       sz--;                                                             \
254     } while (sz);                                                       \
255   }                                                                     \
256                                                                         \
257   /* --- Done --- */                                                    \
258                                                                         \
259   ctx->off = off;                                                       \
260   return;                                                               \
261 }                                                                       \
262                                                                         \
263 /* --- Generic cipher interface --- */                                  \
264                                                                         \
265 static const gcipher_ops gops;                                          \
266                                                                         \
267 typedef struct gctx {                                                   \
268   gcipher c;                                                            \
269   pre##_ofbctx k;                                                       \
270 } gctx;                                                                 \
271                                                                         \
272 static gcipher *ginit(const void *k, size_t sz)                         \
273 {                                                                       \
274   gctx *g = S_CREATE(gctx);                                             \
275   g->c.ops = &gops;                                                     \
276   pre##_ofbinit(&g->k, k, sz, 0);                                       \
277   return (&g->c);                                                       \
278 }                                                                       \
279                                                                         \
280 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
281 {                                                                       \
282   gctx *g = (gctx *)c;                                                  \
283   pre##_ofbencrypt(&g->k, s, t, sz);                                    \
284 }                                                                       \
285                                                                         \
286 static void gdestroy(gcipher *c)                                        \
287 {                                                                       \
288   gctx *g = (gctx *)c;                                                  \
289   BURN(*g);                                                             \
290   S_DESTROY(g);                                                         \
291 }                                                                       \
292                                                                         \
293 static void gsetiv(gcipher *c, const void *iv)                          \
294 {                                                                       \
295   gctx *g = (gctx *)c;                                                  \
296   pre##_ofbsetiv(&g->k, iv);                                            \
297 }                                                                       \
298                                                                         \
299 static void gbdry(gcipher *c)                                           \
300 {                                                                       \
301   gctx *g = (gctx *)c;                                                  \
302   pre##_ofbbdry(&g->k);                                                 \
303 }                                                                       \
304                                                                         \
305 static const gcipher_ops gops = {                                       \
306   &pre##_ofb,                                                           \
307   gencrypt, gencrypt, gdestroy, gsetiv, gbdry                           \
308 };                                                                      \
309                                                                         \
310 const gccipher pre##_ofb = {                                            \
311   #pre "-ofb", pre##_keysz, PRE##_BLKSZ,                                \
312   ginit                                                                 \
313 };                                                                      \
314                                                                         \
315 /* --- Generic random number generator interface --- */                 \
316                                                                         \
317 typedef struct grctx {                                                  \
318   grand r;                                                              \
319   pre##_ofbctx k;                                                       \
320 } grctx;                                                                \
321                                                                         \
322 static void grdestroy(grand *r)                                         \
323 {                                                                       \
324   grctx *g = (grctx *)r;                                                \
325   BURN(*g);                                                             \
326   S_DESTROY(g);                                                         \
327 }                                                                       \
328                                                                         \
329 static int grmisc(grand *r, unsigned op, ...)                           \
330 {                                                                       \
331   grctx *g = (grctx *)r;                                                \
332   va_list ap;                                                           \
333   int rc = 0;                                                           \
334   uint32 i;                                                             \
335   octet buf[PRE##_BLKSZ];                                               \
336   va_start(ap, op);                                                     \
337                                                                         \
338   switch (op) {                                                         \
339     case GRAND_CHECK:                                                   \
340       switch (va_arg(ap, unsigned)) {                                   \
341         case GRAND_CHECK:                                               \
342         case GRAND_SEEDINT:                                             \
343         case GRAND_SEEDUINT32:                                          \
344         case GRAND_SEEDBLOCK:                                           \
345         case GRAND_SEEDRAND:                                            \
346           rc = 1;                                                       \
347           break;                                                        \
348         default:                                                        \
349           rc = 0;                                                       \
350           break;                                                        \
351       }                                                                 \
352       break;                                                            \
353     case GRAND_SEEDINT:                                                 \
354       memset(buf, 0, sizeof(buf));                                      \
355       i = va_arg(ap, unsigned);                                         \
356       STORE32(buf, i);                                                  \
357       pre##_ofbsetiv(&g->k, buf);                                       \
358       break;                                                            \
359     case GRAND_SEEDUINT32:                                              \
360       memset(buf, 0, sizeof(buf));                                      \
361       i = va_arg(ap, uint32);                                           \
362       STORE32(buf, i);                                                  \
363       pre##_ofbsetiv(&g->k, buf);                                       \
364       break;                                                            \
365     case GRAND_SEEDBLOCK: {                                             \
366       const void *p = va_arg(ap, const void *);                         \
367       size_t sz = va_arg(ap, size_t);                                   \
368       if (sz < sizeof(buf)) {                                           \
369         memset(buf, 0, sizeof(buf));                                    \
370         memcpy(buf, p, sz);                                             \
371         p = buf;                                                        \
372       }                                                                 \
373       pre##_ofbsetiv(&g->k, p);                                         \
374     } break;                                                            \
375     case GRAND_SEEDRAND: {                                              \
376       grand *rr = va_arg(ap, grand *);                                  \
377       rr->ops->fill(rr, buf, sizeof(buf));                              \
378       pre##_ofbsetiv(&g->k, buf);                                       \
379     } break;                                                            \
380     default:                                                            \
381       GRAND_BADOP;                                                      \
382       break;                                                            \
383   }                                                                     \
384                                                                         \
385   va_end(ap);                                                           \
386   return (rc);                                                          \
387 }                                                                       \
388                                                                         \
389 static octet grbyte(grand *r)                                           \
390 {                                                                       \
391   grctx *g = (grctx *)r;                                                \
392   octet o;                                                              \
393   pre##_ofbencrypt(&g->k, 0, &o, 1);                                    \
394   return (o);                                                           \
395 }                                                                       \
396                                                                         \
397 static uint32 grword(grand *r)                                          \
398 {                                                                       \
399   grctx *g = (grctx *)r;                                                \
400   octet b[4];                                                           \
401   pre##_ofbencrypt(&g->k, 0, b, sizeof(b));                             \
402   return (LOAD32(b));                                                   \
403 }                                                                       \
404                                                                         \
405 static void grfill(grand *r, void *p, size_t sz)                        \
406 {                                                                       \
407   grctx *g = (grctx *)r;                                                \
408   pre##_ofbencrypt(&g->k, 0, p, sz);                                    \
409 }                                                                       \
410                                                                         \
411 static const grand_ops grops = {                                        \
412   #pre "-ofb",                                                          \
413   GRAND_CRYPTO, 0,                                                      \
414   grmisc, grdestroy,                                                    \
415   grword, grbyte, grword, grand_range, grfill                           \
416 };                                                                      \
417                                                                         \
418 /* --- @pre_ofbrand@ --- *                                              \
419  *                                                                      \
420  * Arguments:   @const void *k@ = pointer to key material               \
421  *              @size_t sz@ = size of key material                      \
422  *                                                                      \
423  * Returns:     Pointer to generic random number generator interface.   \
424  *                                                                      \
425  * Use:         Creates a random number interface wrapper around an     \
426  *              OFB-mode block cipher.                                  \
427  */                                                                     \
428                                                                         \
429 grand *pre##_ofbrand(const void *k, size_t sz)                          \
430 {                                                                       \
431   grctx *g = S_CREATE(grctx);                                           \
432   g->r.ops = &grops;                                                    \
433   pre##_ofbinit(&g->k, k, sz, 0);                                       \
434   return (&g->r);                                                       \
435 }                                                                       \
436                                                                         \
437 OFB_TEST(PRE, pre)
438
439 /*----- Test rig ----------------------------------------------------------*/
440
441 #ifdef TEST_RIG
442
443 #include <stdio.h>
444
445 #include "daftstory.h"
446
447 /* --- @OFB_TEST@ --- *
448  *
449  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
450  *
451  * Use:         Standard test rig for OFB functions.
452  */
453
454 #define OFB_TEST(PRE, pre)                                              \
455                                                                         \
456 /* --- Initial plaintext for the test --- */                            \
457                                                                         \
458 static const octet text[] = TEXT;                                       \
459                                                                         \
460 /* --- Key and IV to use --- */                                         \
461                                                                         \
462 static const octet key[] = KEY;                                         \
463 static const octet iv[] = IV;                                           \
464                                                                         \
465 /* --- Buffers for encryption and decryption output --- */              \
466                                                                         \
467 static octet ct[sizeof(text)];                                          \
468 static octet pt[sizeof(text)];                                          \
469                                                                         \
470 static void hexdump(const octet *p, size_t sz)                          \
471 {                                                                       \
472   const octet *q = p + sz;                                              \
473   for (sz = 0; p < q; p++, sz++) {                                      \
474     printf("%02x", *p);                                                 \
475     if ((sz + 1) % PRE##_BLKSZ == 0)                                    \
476       putchar(':');                                                     \
477   }                                                                     \
478 }                                                                       \
479                                                                         \
480 int main(void)                                                          \
481 {                                                                       \
482   size_t sz = 0, rest;                                                  \
483   pre##_ofbctx ctx;                                                     \
484   int status = 0;                                                       \
485   int done = 0;                                                         \
486   pre##_ctx k;                                                          \
487                                                                         \
488   size_t keysz = PRE##_KEYSZ ?                                          \
489     PRE##_KEYSZ : strlen((const char *)key);                            \
490                                                                         \
491   fputs(#pre "-ofb: ", stdout);                                         \
492                                                                         \
493   pre##_init(&k, key, keysz);                                           \
494   pre##_ofbsetkey(&ctx, &k);                                            \
495                                                                         \
496   while (sz <= sizeof(text)) {                                          \
497     rest = sizeof(text) - sz;                                           \
498     memcpy(ct, text, sizeof(text));                                     \
499     pre##_ofbsetiv(&ctx, iv);                                           \
500     pre##_ofbencrypt(&ctx, ct, ct, sz);                                 \
501     pre##_ofbencrypt(&ctx, ct + sz, ct + sz, rest);                     \
502     memcpy(pt, ct, sizeof(text));                                       \
503     pre##_ofbsetiv(&ctx, iv);                                           \
504     pre##_ofbencrypt(&ctx, pt, pt, rest);                               \
505     pre##_ofbencrypt(&ctx, pt + rest, pt + rest, sz);                   \
506     if (memcmp(pt, text, sizeof(text)) == 0) {                          \
507       done++;                                                           \
508       if (sizeof(text) < 40 || done % 8 == 0)                           \
509         fputc('.', stdout);                                             \
510       if (done % 480 == 0)                                              \
511         fputs("\n\t", stdout);                                          \
512       fflush(stdout);                                                   \
513     } else {                                                            \
514       printf("\nError (sz = %lu)\n", (unsigned long)sz);                \
515       status = 1;                                                       \
516       printf("\tplaintext      = "); hexdump(text, sz);                 \
517         printf(", "); hexdump(text + sz, rest);                         \
518         fputc('\n', stdout);                                            \
519       printf("\tciphertext     = "); hexdump(ct, sz);                   \
520         printf(", "); hexdump(ct + sz, rest);                           \
521         fputc('\n', stdout);                                            \
522       printf("\trecovered text = "); hexdump(pt, sz);                   \
523         printf(", "); hexdump(pt + sz, rest);                           \
524         fputc('\n', stdout);                                            \
525       fputc('\n', stdout);                                              \
526     }                                                                   \
527     if (sz < 63)                                                        \
528       sz++;                                                             \
529     else                                                                \
530       sz += 9;                                                          \
531   }                                                                     \
532                                                                         \
533   fputs(status ? " failed\n" : " ok\n", stdout);                        \
534   return (status);                                                      \
535 }
536
537 #else
538 #  define OFB_TEST(PRE, pre)
539 #endif
540
541 /*----- That's all, folks -------------------------------------------------*/
542
543 #ifdef __cplusplus
544   }
545 #endif
546
547 #endif