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