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