chiark / gitweb /
math/gfx-sqr.c: Use bithacking rather than a table for squaring.
[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 #ifndef CATACOMB_RSVR_H
60 #  include "rsvr.h"
61 #endif
62
63 /*----- Macros ------------------------------------------------------------*/
64
65 /* --- @COUNTER_DEF@ --- *
66  *
67  * Arguments:   @PRE@, @pre@ = prefixes for the underlying block cipher
68  *
69  * Use:         Creates definitions for counter mode.
70  */
71
72 #define COUNTER_DEF(PRE, pre) COUNTER_DEFX(PRE, pre, #pre, #pre)
73
74 #define COUNTER_DEFX(PRE, pre, name, fname)                             \
75                                                                         \
76 /* --- @pre_countergetiv@ --- *                                         \
77  *                                                                      \
78  * Arguments:   @const pre_counterctx *ctx@ = pointer to counter        \
79  *                      context                                         \
80  *              @void *iv@ = pointer to output data block               \
81  *                                                                      \
82  * Returns:     ---                                                     \
83  *                                                                      \
84  * Use:         Reads the currently set IV.  Reading and setting an IV  \
85  *              is not transparent to the cipher.  It will add a `step' \
86  *              which must be matched by a similar operation during     \
87  *              decryption.                                             \
88  */                                                                     \
89                                                                         \
90 void pre##_countergetiv(const pre##_counterctx *ctx, void *iv)          \
91   { BLKC_STORE(PRE, iv, ctx->c); }                                      \
92                                                                         \
93 /* --- @pre_countersetiv@ --- *                                         \
94  *                                                                      \
95  * Arguments:   @pre_counterctx *ctx@ = pointer to counter context      \
96  *              @cnost void *iv@ = pointer to IV to set                 \
97  *                                                                      \
98  * Returns:     ---                                                     \
99  *                                                                      \
100  * Use:         Sets the IV to use for subsequent encryption.           \
101  */                                                                     \
102                                                                         \
103 void pre##_countersetiv(pre##_counterctx *ctx, const void *iv)          \
104   { BLKC_LOAD(PRE, ctx->c, iv); ctx->off = PRE##_BLKSZ; }               \
105                                                                         \
106 /* --- @pre_counterbdry@ --- *                                          \
107  *                                                                      \
108  * Arguments:   @pre_counterctx *ctx@ = pointer to counter context      \
109  *                                                                      \
110  * Returns:     ---                                                     \
111  *                                                                      \
112  * Use:         Inserts a boundary during encryption.  Successful       \
113  *              decryption must place a similar boundary.               \
114  */                                                                     \
115                                                                         \
116 void pre##_counterbdry(pre##_counterctx *ctx)                           \
117   { BLKC_STEP(PRE, ctx->c); ctx->off = PRE##_BLKSZ; }                   \
118                                                                         \
119 /* --- @pre_countersetkey@ --- *                                        \
120  *                                                                      \
121  * Arguments:   @pre_counterctx *ctx@ = pointer to counter context      \
122  *              @const pre_ctx *k@ = pointer to cipher context          \
123  *                                                                      \
124  * Returns:     ---                                                     \
125  *                                                                      \
126  * Use:         Sets the counter context to use a different cipher key. \
127  */                                                                     \
128                                                                         \
129 void pre##_countersetkey(pre##_counterctx *ctx, const pre##_ctx *k)     \
130   { ctx->ctx = *k; }                                                    \
131                                                                         \
132 /* --- @pre_counterinit@ --- *                                          \
133  *                                                                      \
134  * Arguments:   @pre_counterctx *ctx@ = pointer to cipher context       \
135  *              @const void *key@ = pointer to the key buffer           \
136  *              @size_t sz@ = size of the key                           \
137  *              @const void *iv@ = pointer to initialization vector     \
138  *                                                                      \
139  * Returns:     ---                                                     \
140  *                                                                      \
141  * Use:         Initializes a counter context ready for use.  You       \
142  *              should ensure that the IV chosen is unique: reusing an  \
143  *              IV will compromise the security of the entire           \
144  *              plaintext.  This is equivalent to calls to @pre_init@,  \
145  *              @pre_countersetkey@ and @pre_countersetiv@.             \
146  */                                                                     \
147                                                                         \
148 void pre##_counterinit(pre##_counterctx *ctx,                           \
149                        const void *key, size_t sz,                      \
150                        const void *iv)                                  \
151 {                                                                       \
152   static const octet zero[PRE##_BLKSZ] = { 0 };                         \
153                                                                         \
154   pre##_init(&ctx->ctx, key, sz);                                       \
155   pre##_countersetiv(ctx, iv ? iv : zero);                              \
156 }                                                                       \
157                                                                         \
158 /* --- @pre_counterencrypt@ --- *                                       \
159  *                                                                      \
160  * Arguments:   @pre_counterctx *ctx@ = pointer to counter context      \
161  *              @const void *src@ = pointer to source data              \
162  *              @void *dest@ = pointer to destination data              \
163  *              @size_t sz@ = size of block to be encrypted             \
164  *                                                                      \
165  * Returns:     ---                                                     \
166  *                                                                      \
167  * Use:         Encrypts or decrypts a block with a block cipher in     \
168  *              counter mode: encryption and decryption are the same in \
169  *              counter.  The destination may be null to just churn the \
170  *              feedback round for a bit.  The source may be null to    \
171  *              use the cipher as a random data generator.              \
172  */                                                                     \
173                                                                         \
174 static const rsvr_policy pre##_counterpolicy =                          \
175   { 0, PRE##_BLKSZ, PRE##_BLKSZ };                                      \
176                                                                         \
177 void pre##_counterencrypt(pre##_counterctx *ctx,                        \
178                           const void *src, void *dest,                  \
179                           size_t sz)                                    \
180 {                                                                       \
181   rsvr_plan plan;                                                       \
182   const octet *s = src, *p;                                             \
183   octet *d = dest;                                                      \
184   uint32 t[PRE##_BLKSZ/4];                                              \
185                                                                         \
186   /* Construct a plan and prepare to follow through. */                 \
187   rsvr_mkplan(&plan, &pre##_counterpolicy, ctx->off, sz);               \
188                                                                         \
189   /* Initial portion, fulfilled from the buffer.  If the chunk is small \
190    * enough, then this will be the only portion.  If the buffer is      \
191    * currently empty, then we must prepare it.                          \
192    */                                                                   \
193   if (plan.head) {                                                      \
194     if (!ctx->off) {                                                    \
195       pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c);         \
196       BLKC_STORE(PRE, ctx->b, t);                                       \
197     }                                                                   \
198     p = ctx->b + ctx->off; ctx->off += plan.head;                       \
199     if (!d) /* nothing to do */;                                        \
200     else if (!s) { memcpy(d, p, plan.head); d += plan.head; }           \
201     else while (plan.head--) *d++ = *s++ ^ *p++;                        \
202   }                                                                     \
203                                                                         \
204   /* If the buffer is all used, then reset it ready for next time. */   \
205   ctx->off -= plan.from_rsvr;                                           \
206                                                                         \
207   /* Handle multiple whole blocks. */                                   \
208   if (!d)                                                               \
209     BLKC_ADD(PRE, ctx->c, plan.from_input/PRE##_BLKSZ);                 \
210   else if (!s) while (plan.from_input) {                                \
211     pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c);           \
212     BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                            \
213     plan.from_input -= PRE##_BLKSZ;                                     \
214   } else while (plan.from_input) {                                      \
215     pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c);           \
216     BLKC_XLOAD(PRE, t, s); s += PRE##_BLKSZ;                            \
217     BLKC_STORE(PRE, d, t); d += PRE##_BLKSZ;                            \
218     plan.from_input -= PRE##_BLKSZ;                                     \
219   }                                                                     \
220                                                                         \
221   /* Final portion.  Note that the buffer must be empty if there is a   \
222    * tail, since otherwise the input data would have been part of the   \
223    * head portion instad. */                                            \
224   if (!plan.tail)                                                       \
225     BLKC_STORE(PRE, ctx->b, t);                                         \
226   else {                                                                \
227     pre##_eblk(&ctx->ctx, ctx->c, t); BLKC_STEP(PRE, ctx->c);           \
228     BLKC_STORE(PRE, ctx->b, t);                                         \
229     p = ctx->b; ctx->off += plan.tail;                                  \
230     if (!d) /* nothing to do */;                                        \
231     else if (!s) { memcpy(d, p, plan.tail); d += plan.tail; }           \
232     else while (plan.tail--) *d++ = *s++ ^ *p++;                        \
233   }                                                                     \
234 }                                                                       \
235                                                                         \
236 /* --- Generic cipher interface --- */                                  \
237                                                                         \
238 static const gcipher_ops gops;                                          \
239                                                                         \
240 typedef struct gctx {                                                   \
241   gcipher c;                                                            \
242   pre##_counterctx k;                                                   \
243 } gctx;                                                                 \
244                                                                         \
245 static gcipher *ginit(const void *k, size_t sz)                         \
246 {                                                                       \
247   gctx *g = S_CREATE(gctx);                                             \
248   g->c.ops = &gops;                                                     \
249   pre##_counterinit(&g->k, k, sz, 0);                                   \
250   return (&g->c);                                                       \
251 }                                                                       \
252                                                                         \
253 static void gencrypt(gcipher *c, const void *s, void *t, size_t sz)     \
254   { gctx *g = (gctx *)c; pre##_counterencrypt(&g->k, s, t, sz); }       \
255                                                                         \
256 static void gdestroy(gcipher *c)                                        \
257   { gctx *g = (gctx *)c; BURN(*g); S_DESTROY(g); }                      \
258                                                                         \
259 static void gsetiv(gcipher *c, const void *iv)                          \
260   { gctx *g = (gctx *)c; pre##_countersetiv(&g->k, iv); }               \
261                                                                         \
262 static void gbdry(gcipher *c)                                           \
263   { gctx *g = (gctx *)c; pre##_counterbdry(&g->k); }                    \
264                                                                         \
265 static const gcipher_ops gops = {                                       \
266   &pre##_counter,                                                       \
267   gencrypt, gencrypt, gdestroy, gsetiv, gbdry                           \
268 };                                                                      \
269                                                                         \
270 const gccipher pre##_counter = {                                        \
271   name "-counter", pre##_keysz, PRE##_BLKSZ,                            \
272   ginit                                                                 \
273 };                                                                      \
274                                                                         \
275 /* --- Generic random number generator interface --- */                 \
276                                                                         \
277 typedef struct grctx {                                                  \
278   grand r;                                                              \
279   pre##_counterctx k;                                                   \
280 } grctx;                                                                \
281                                                                         \
282 static void grdestroy(grand *r)                                         \
283 {                                                                       \
284   grctx *g = (grctx *)r;                                                \
285   BURN(*g);                                                             \
286   S_DESTROY(g);                                                         \
287 }                                                                       \
288                                                                         \
289 static int grmisc(grand *r, unsigned op, ...)                           \
290 {                                                                       \
291   grctx *g = (grctx *)r;                                                \
292   va_list ap;                                                           \
293   int rc = 0;                                                           \
294   octet buf[PRE##_BLKSZ];                                               \
295   va_start(ap, op);                                                     \
296                                                                         \
297   switch (op) {                                                         \
298     case GRAND_CHECK:                                                   \
299       switch (va_arg(ap, unsigned)) {                                   \
300         case GRAND_CHECK:                                               \
301         case GRAND_SEEDINT:                                             \
302         case GRAND_SEEDUINT32:                                          \
303         case GRAND_SEEDBLOCK:                                           \
304         case GRAND_SEEDRAND:                                            \
305           rc = 1;                                                       \
306           break;                                                        \
307         default:                                                        \
308           rc = 0;                                                       \
309           break;                                                        \
310       }                                                                 \
311       break;                                                            \
312     case GRAND_SEEDINT:                                                 \
313       BLKC_SET(PRE, g->k.c, va_arg(ap, unsigned));                      \
314       g->k.off = PRE##_BLKSZ;                                           \
315       break;                                                            \
316     case GRAND_SEEDUINT32:                                              \
317       BLKC_SET(PRE, g->k.c, va_arg(ap, uint32));                        \
318       g->k.off = PRE##_BLKSZ;                                           \
319       break;                                                            \
320     case GRAND_SEEDBLOCK: {                                             \
321       const void *p = va_arg(ap, const void *);                         \
322       size_t sz = va_arg(ap, size_t);                                   \
323       if (sz < sizeof(buf)) {                                           \
324         memset(buf, 0, sizeof(buf));                                    \
325         memcpy(buf, p, sz);                                             \
326         p = buf;                                                        \
327       }                                                                 \
328       pre##_countersetiv(&g->k, p);                                     \
329     } break;                                                            \
330     case GRAND_SEEDRAND: {                                              \
331       grand *rr = va_arg(ap, grand *);                                  \
332       rr->ops->fill(rr, buf, sizeof(buf));                              \
333       pre##_countersetiv(&g->k, buf);                                   \
334     } break;                                                            \
335     default:                                                            \
336       GRAND_BADOP;                                                      \
337       break;                                                            \
338   }                                                                     \
339                                                                         \
340   va_end(ap);                                                           \
341   return (rc);                                                          \
342 }                                                                       \
343                                                                         \
344 static octet grbyte(grand *r)                                           \
345 {                                                                       \
346   grctx *g = (grctx *)r;                                                \
347   octet o;                                                              \
348   pre##_counterencrypt(&g->k, 0, &o, 1);                                \
349   return (o);                                                           \
350 }                                                                       \
351                                                                         \
352 static uint32 grword(grand *r)                                          \
353 {                                                                       \
354   grctx *g = (grctx *)r;                                                \
355   octet b[4];                                                           \
356   pre##_counterencrypt(&g->k, 0, b, sizeof(b));                         \
357   return (LOAD32(b));                                                   \
358 }                                                                       \
359                                                                         \
360 static void grfill(grand *r, void *p, size_t sz)                        \
361   { grctx *g = (grctx *)r; pre##_counterencrypt(&g->k, 0, p, sz); }     \
362                                                                         \
363 static const grand_ops grops = {                                        \
364   name "-counter",                                                      \
365   GRAND_CRYPTO, 0,                                                      \
366   grmisc, grdestroy,                                                    \
367   grword, grbyte, grword, grand_defaultrange, grfill                    \
368 };                                                                      \
369                                                                         \
370 /* --- @pre_counterrand@ --- *                                          \
371  *                                                                      \
372  * Arguments:   @const void *k@ = pointer to key material               \
373  *              @size_t sz@ = size of key material                      \
374  *                                                                      \
375  * Returns:     Pointer to generic random number generator interface.   \
376  *                                                                      \
377  * Use:         Creates a random number interface wrapper around an     \
378  *              counter-mode block cipher.                              \
379  */                                                                     \
380                                                                         \
381 grand *pre##_counterrand(const void *k, size_t sz)                      \
382 {                                                                       \
383   grctx *g = S_CREATE(grctx);                                           \
384   g->r.ops = &grops;                                                    \
385   pre##_counterinit(&g->k, k, sz, 0);                                   \
386   return (&g->r);                                                       \
387 }                                                                       \
388                                                                         \
389 COUNTER_TESTX(PRE, pre, name, fname)
390
391 /*----- Test rig ----------------------------------------------------------*/
392
393 #define COUNTER_TEST(PRE, pre) COUNTER_TESTX(PRE, pre, #pre, #pre)
394
395 #ifdef TEST_RIG
396
397 #include "modes-test.h"
398
399 /* --- @COUNTER_TEST@ --- *
400  *
401  * Arguments:   @PRE@, @pre@ = prefixes for block cipher definitions
402  *
403  * Use:         Standard test rig for counter functions.
404  */
405
406 #define COUNTER_TESTX(PRE, pre, name, fname)                            \
407                                                                         \
408 static pre##_ctx key;                                                   \
409 static pre##_counterctx ctx;                                            \
410                                                                         \
411 static void pre##_counter_test_setup(const octet *k, size_t ksz)        \
412   { pre##_init(&key, k, ksz); pre##_countersetkey(&ctx, &key); }        \
413                                                                         \
414 static void pre##_counter_test_reset(const octet *iv)                   \
415   { pre##_countersetiv(&ctx, iv); }                                     \
416                                                                         \
417 static void pre##_counter_test_enc(const octet *s, octet *d, size_t sz) \
418   { pre##_counterencrypt(&ctx, s, d, sz); }                             \
419                                                                         \
420 int main(int argc, char *argv[])                                        \
421 {                                                                       \
422   return test_encmode(fname "-counter", PRE##_KEYSZ, PRE##_BLKSZ, 1, 0, \
423                       pre##_counter_test_setup, pre##_counter_test_reset, \
424                       pre##_counter_test_enc, pre##_counter_test_enc,   \
425                       argc, argv);                                      \
426 }
427
428 #else
429 #  define COUNTER_TESTX(PRE, pre, name, fname)
430 #endif
431
432 /*----- That's all, folks -------------------------------------------------*/
433
434 #ifdef __cplusplus
435   }
436 #endif
437
438 #endif